summaryrefslogtreecommitdiff
path: root/Mailman/Pending.py
diff options
context:
space:
mode:
Diffstat (limited to 'Mailman/Pending.py')
-rw-r--r--Mailman/Pending.py44
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()