Commit 9bca8e5e authored by Vincent Pelletier's avatar Vincent Pelletier

IdTool: Add poisoning support.

Allows for safe migration to another id generator, by preventing silent
success of any piece of code still using the former generator, allowing
its detection and resolution before duplicate ids are emitted.
As a consequence, also allows on-demand and partial migration of id
generators.
parent dde89f18
......@@ -81,7 +81,8 @@ class IdGenerator(Base):
security.declareProtected(Permissions.AccessContentsInformation,
'generateNewIdList')
def generateNewIdList(self, id_group=None, id_count=1, default=None):
def generateNewIdList(self, id_group=None, id_count=1, default=None,
poison=False):
"""
Generate a list of next ids in the sequence of ids of a particular group
Store the last id on a database in the portal_ids table
......@@ -94,7 +95,8 @@ class IdGenerator(Base):
raise TypeError, 'id_group is not a string'
return self._getLatestSpecialiseValue().generateNewIdList(id_group=id_group,
id_count=id_count,
default=default)
default=default,
poison=poison)
security.declareProtected(Permissions.ModifyPortalContent,
'initializeGenerator')
......
......@@ -58,7 +58,7 @@ class SQLNonContinuousIncreasingIdGenerator(IdGenerator):
last_max_id_dict = None
def _generateNewId(self, id_group, id_count=1, default=None):
def _generateNewId(self, id_group, id_count=1, default=None, poison=False):
"""
Return the next_id with the last_id with the sql method
Store the last id on a database in the portal_ids table
......@@ -92,6 +92,8 @@ class SQLNonContinuousIncreasingIdGenerator(IdGenerator):
try:
# Tries of generate the new_id
new_id = result_query[0]['LAST_INSERT_ID()']
if poison:
portal.IdTool_zSetLastId(id_group, None)
# Commit the changement of new_id
portal.IdTool_zCommit()
except ProgrammingError, error:
......@@ -114,6 +116,8 @@ class SQLNonContinuousIncreasingIdGenerator(IdGenerator):
# Check the store interval to store the data
if last_max_id_value <= new_id - (self.getStoreInterval() or 1):
last_max_id.set(new_id)
if poison:
last_max_id.set(None)
return new_id
def _updateSqlTable(self):
......@@ -141,20 +145,20 @@ class SQLNonContinuousIncreasingIdGenerator(IdGenerator):
security.declareProtected(Permissions.AccessContentsInformation,
'generateNewId')
def generateNewId(self, id_group=None, default=None):
def generateNewId(self, id_group=None, default=None, poison=False):
"""
Generate the next id in the sequence of ids of a particular group
"""
return self._generateNewId(id_group=id_group, default=default)
return self._generateNewId(id_group=id_group, default=default, poison=poison)
security.declareProtected(Permissions.AccessContentsInformation,
'generateNewIdList')
def generateNewIdList(self, id_group=None, id_count=1, default=None):
def generateNewIdList(self, id_group=None, id_count=1, default=None, poison=False):
"""
Generate a list of next ids in the sequence of ids of a particular group
"""
new_id = 1 + self._generateNewId(id_group=id_group, id_count=id_count,
default=default)
default=default, poison=poison)
return range(new_id - id_count, new_id)
security.declareProtected(Permissions.ModifyPortalContent,
......
......@@ -48,7 +48,7 @@ class ZODBContinuousIncreasingIdGenerator(IdGenerator):
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
def _generateNewId(self, id_group, id_count=1, default=None):
def _generateNewId(self, id_group, id_count=1, default=None, poison=False):
"""
Return the new_id from the last_id of the zodb
Use int to store the last_id, use also a persistant mapping for to be
......@@ -66,25 +66,25 @@ class ZODBContinuousIncreasingIdGenerator(IdGenerator):
# Retrieve the last id and increment
new_id = last_id_dict.get(id_group, default - 1) + id_count
# Store the new_id in the dictionary
last_id_dict[id_group] = new_id
last_id_dict[id_group] = None if poison else new_id
return new_id
security.declareProtected(Permissions.AccessContentsInformation,
'generateNewId')
def generateNewId(self, id_group=None, default=None):
def generateNewId(self, id_group=None, default=None, poison=False):
"""
Generate the next id in the sequence of ids of a particular group
"""
return self._generateNewId(id_group=id_group, default=default)
return self._generateNewId(id_group=id_group, default=default, poison=poison)
security.declareProtected(Permissions.AccessContentsInformation,
'generateNewIdList')
def generateNewIdList(self, id_group=None, id_count=1, default=None):
def generateNewIdList(self, id_group=None, id_count=1, default=None, poison=False):
"""
Generate a list of next ids in the sequence of ids of a particular group
"""
new_id = 1 + self._generateNewId(id_group=id_group, id_count=id_count,
default=default)
default=default, poison=poison)
return range(new_id - id_count, new_id)
security.declareProtected(Permissions.ModifyPortalContent,
......
......@@ -108,7 +108,7 @@ class IdTool(BaseTool):
security.declareProtected(Permissions.AccessContentsInformation,
'generateNewId')
def generateNewId(self, id_group=None, default=None, method=_marker,
id_generator=None):
id_generator=None, poison=False):
"""
Generate the next id in the sequence of ids of a particular group
"""
......@@ -127,8 +127,11 @@ class IdTool(BaseTool):
#use _getLatestGeneratorValue here for that the technical level
#must not call the method
last_generator = self._getLatestGeneratorValue(id_generator)
new_id = last_generator.generateNewId(id_group=id_group, \
default=default)
new_id = last_generator.generateNewId(
id_group=id_group,
default=default,
poison=poison,
)
except KeyError:
# XXX backward compatiblity
if self.getTypeInfo():
......@@ -165,7 +168,7 @@ class IdTool(BaseTool):
security.declareProtected(Permissions.AccessContentsInformation,
'generateNewIdList')
def generateNewIdList(self, id_group=None, id_count=1, default=None,
store=_marker, id_generator=None):
store=_marker, id_generator=None, poison=False):
"""
Generate a list of next ids in the sequence of ids of a particular group
"""
......@@ -186,7 +189,7 @@ class IdTool(BaseTool):
#must not call the method
last_generator = self._getLatestGeneratorValue(id_generator)
new_id_list = last_generator.generateNewIdList(id_group=id_group,
id_count=id_count, default=default)
id_count=id_count, default=default, poison=poison)
except (KeyError, ValueError):
# XXX backward compatiblity
if self.getTypeInfo():
......
BEGIN
<dtml-var sql_delimiter>
INSERT INTO portal_ids (`id_group`, `last_id`)
VALUES (<dtml-sqlvar id_group type="string">, <dtml-sqlvar last_id type="int">)
ON DUPLICATE KEY UPDATE `last_id` = <dtml-sqlvar last_id type="int">
VALUES (<dtml-sqlvar id_group type="string">, <dtml-sqlvar last_id type="int" optional>)
ON DUPLICATE KEY UPDATE `last_id` = <dtml-sqlvar last_id type="int" optional>
<dtml-var sql_delimiter>
COMMIT
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment