Commit 830b128d authored by Vincent Pelletier's avatar Vincent Pelletier

Implement 2 new Id generators. Both are conflict-less.

generateNewLongId generates human-unfriendly ids based on zope transaction Ids.
generateNewLengthId generates human-friendly always increasing ids, with potential gaps between ids.


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@9415 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 21630acc
...@@ -38,6 +38,7 @@ from Products.ERP5 import _dtmldir ...@@ -38,6 +38,7 @@ from Products.ERP5 import _dtmldir
import threading import threading
from zLOG import LOG from zLOG import LOG
from BTrees.Length import Length
class IdTool(UniqueObject, Folder): class IdTool(UniqueObject, Folder):
""" """
...@@ -140,4 +141,61 @@ class IdTool(UniqueObject, Folder): ...@@ -140,4 +141,61 @@ class IdTool(UniqueObject, Folder):
return new_id return new_id
security.declareProtected(Permissions.AccessContentsInformation,
'generateNewLongId')
def generateNewLongId(self, **kw):
"""
Returns the ZODB transation id to be used as an identifier.
It's a 64bits number, so it can look ugly and/or huge to users.
"""
tid = get_transaction()._id;
return (tid < 0) and (2**63 - tid) or tid; # It's a 64 bits number, but sometimes it returns as a negative int... so make it positive again and add 2**63.
security.declareProtected(Permissions.AccessContentsInformation,
'copyDictLengthIds')
def getDictLengthIdsItems(self):
"""
Return a copy of dict_length_ids.
This is a workaround to access the persistent mapping content from ZSQL
method to be able to insert initial tuples in the database at creation.
"""
if getattr(self, 'dict_length_ids', None) is None:
self.dict_length_ids = PersistentMapping()
return self.dict_length_ids.items()
security.declareProtected(Permissions.AccessContentsInformation,
'generateNewLengthId')
def generateNewLengthId(self, id_group=None, default=None):
"""
Generates an Id.
The id is generated by mysql and then stored in a Length object in a
persistant mapping to be persistent.
We use MySQL to generate an ID, because it is atomic and we don't want
to generate any conflict at zope level. The possible downfall is that
some IDs might be skipped because of failed transactions (MySQL is not
and must not be rolled back).
2 ZSQL methods are required for this method to work :
-
"Length" because the id is stored in a BTrees.Length. It doesn't have
to be a length.
"""
if getattr(self, 'dict_length_ids', None) is None:
self.dict_length_ids = PersistentMapping()
new_id = None
if id_group not in (None, 'None'):
if not isinstance(id_group, str):
id_group = repr(id_group)
default = isinstance(default, int) and default or 1
query = getattr(self, 'Base_zGenerateId')
commit = getattr(self, 'Base_zCommit')
if None not in (query, commit):
result = query(id_group=id_group, default=default)
commit()
new_id = result[0]['LAST_INSERT_ID()']
if self.dict_length_ids.get(id_group) is None:
self.dict_length_ids[id_group]=Length(new_id)
self.dict_length_ids[id_group].set(new_id)
return new_id
InitializeClass(IdTool) InitializeClass(IdTool)
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