diff options
Diffstat (limited to 'Mailman/Pending.py')
| -rw-r--r-- | Mailman/Pending.py | 44 |
1 files changed, 37 insertions, 7 deletions
diff --git a/Mailman/Pending.py b/Mailman/Pending.py index 96c74511f..44b7c94e7 100644 --- a/Mailman/Pending.py +++ b/Mailman/Pending.py @@ -35,10 +35,16 @@ from Mailman import LockFile DBFILE = os.path.join(mm_cfg.DATA_DIR, 'pending.db') LOCKFILE = os.path.join(mm_cfg.LOCK_DIR, 'pending.lock') +# Types of pending records +SUBSCRIPTION = 'S' +UNSUBSCRIPTION = 'U' + def new(*content): """Create a new entry in the pending database, returning cookie for it.""" + # It's a programming error if this assertion fails! + assert content[:1] in ((SUBSCRIPTION,), (UNSUBSCRIPTION,)) # Acquire the pending database lock, letting TimeOutError percolate up. lock = LockFile.LockFile(LOCKFILE) lock.lock(timeout=30) @@ -55,7 +61,9 @@ def new(*content): break # Store the content, plus the time in the future when this entry will # be evicted from the database, due to staleness. - db[cookie] = content + (now + mm_cfg.PENDING_REQUEST_LIFE,) + db[cookie] = content + evictions = db.setdefault('evictions', {}) + evictions[cookie] = now + mm_cfg.PENDING_REQUEST_LIFE _save(db) return cookie finally: @@ -78,8 +86,7 @@ def confirm(cookie): # Remove the entry from the database del db[cookie] _save(db) - # Strip off the timestamp and return the data - return content[:-1] + return content finally: lock.unlock() @@ -93,17 +100,22 @@ def _load(): except IOError, e: if e.errno <> errno.ENOENT: raise # No database yet, so initialize a fresh one - return {} + return {'evictions': {}} def _save(db): # Lock must be acquired. + evictions = db['evictions'] now = time.time() for cookie, data in db.items(): - timestamp = data[-1] + if cookie in ('evictions', 'version'): + continue + timestamp = evictions[cookie] if now > timestamp: # The entry is stale, so remove it. del db[cookie] + del evictions[cookie] + db['version'] = mm_cfg.PENDING_FILE_SCHEMA_VERSION omask = os.umask(007) try: fp = open(DBFILE, 'w') @@ -115,7 +127,7 @@ def _save(db): def _update(olddb): - # Update an old pending database to the new database + # Update an old pending_subscriptions.db database to the new format lock = LockFile.LockFile(LOCKFILE) lock.lock(timeout=30) try: @@ -123,7 +135,25 @@ def _update(olddb): if olddb.has_key('lastculltime'): del olddb['lastculltime'] db = _load() - db.update(olddb) + evictions = db.setdefault('evictions', {}) + for cookie, data in olddb.items(): + # The cookies used to be kept as a 6 digit integer. We now keep + # the cookies as a string (sha in our case, but it doesn't matter + # for cookie matching). + cookie = str(cookie) + # The old format kept the content as a tuple and tacked the + # timestamp on as the last element of the tuple. We keep the + # timestamps separate, but require the prepending of a record type + # indicator. We know that the only things that were kept in the + # old format were subscription requests. Also, the old request + # format didn't have the subscription language. Best we can do + # here is use the server default. + db[cookie] = (SUBSCRIPTION,) + data[:-1] + \ + (mm_cfg.DEFAULT_SERVER_LANGUAGE,) + # The old database format kept the timestamp as the time the + # request was made. The new format keeps it as the time the + # request should be evicted. + evictions[cookie] = data[-1] + mm_cfg.PENDING_REQUEST_LIFE _save(db) finally: lock.unlock() |
