Created
May 8, 2014 14:17
-
-
Save smurfix/827026360f7ee3245b86 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class BinData(ObjectRef): | |
""" | |
Stores (a reference to) one data file | |
This object implements a content-based file system: the hash of the | |
file contents is an index. | |
""" | |
storage_seq = Column(Integer, autoincrement=True, unique=True) | |
mime_id = Column(Integer, ForeignKey(MIMEtype.id), nullable=False, index=True) | |
mime = relationship(MIMEtype, primaryjoin=mime_id==MIMEtype.id) | |
name = Column(Unicode(100), nullable=False) | |
hash = Column(Unicode(33), nullable=True, unique=True) ## NULL if deleted, 404's without hitting the file system | |
timestamp = Column(DateTime,default=datetime.utcnow) | |
size = Column(Integer) | |
[…] | |
def _get_chars(self): | |
"""This creates a unique path+filename for storage.""" | |
if self.storage_seq is None: | |
db.flush() | |
db.refresh(self,('storage_seq',)) | |
if self.storage_seq is None: ## sqlite, probably | |
from sqlalchemy import func | |
self.storage_seq = (db.query(func.max(BinData.storage_seq)).scalar() or 0) +1 | |
db.flush() | |
assert self.storage_seq, repr(self) | |
id = self.storage_seq-1 | |
chars = "abcdefghjk" ## 100 files per end directory (long names) | |
midchars = "abcdefghjkmnopqr" ## 256 subdirectories (short names) | |
fc = [] | |
flast = chars[id % len(chars)] | |
id = id // len(chars) | |
flast += chars[id % len(chars)] | |
id = id // len(chars) | |
while id: | |
id -= 1 | |
c = midchars[id % len(midchars)] | |
id = id // len(midchars) | |
c = midchars[id % len(midchars)] + c | |
id = id // len(midchars) | |
fc.insert(0,c) | |
fc.append("_") | |
fc.append(self.name+"_"+self.hash[0:10]+flast) | |
if self.mime.ext: | |
fc[-1] += "."+self.mime.ext | |
return fc | |
try: | |
from hashlib import sha1 | |
except ImportError: | |
from sha import sha as sha1 | |
def hash_data(content): | |
""" | |
Create an URL-compatible ASCII hash | |
""" | |
from base64 import b64encode | |
return b64encode(sha1(content).digest(),altchars=str("-_")).rstrip("=") | |
## The mysql driver ignores autoincrement on non-primary-key columns. | |
## Workaround: | |
from sqlalchemy import event | |
from sqlalchemy.schema import DDL | |
event.listen(BinData.__table__, 'after_create', | |
DDL("ALTER TABLE bindata CHANGE storage_seq storage_seq INT AUTO_INCREMENT NOT NULL", on="mysql")) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment