[Commits] (vajda) - change history now tracks attribute value
changes
commits at osafoundation.org
commits at osafoundation.org
Mon Aug 30 14:27:18 PDT 2004
Commit by: vajda
Modified files:
chandler/repository/item/Item.py 1.154 1.155
chandler/repository/item/Values.py 1.15 1.16
chandler/repository/persistence/DBContainer.py 1.16 1.17
chandler/repository/persistence/RepositoryError.py 1.1 1.2
chandler/repository/persistence/XMLRepository.py 1.78 1.79
chandler/repository/persistence/XMLRepositoryView.py 1.50 1.51
Log message:
- change history now tracks attribute value changes
- added more details to VersionConflictError
- fixed bug 1777
ViewCVS links:
http://cvs.osafoundation.org/index.cgi/chandler/repository/item/Item.py.diff?r1=text&tr1=1.154&r2=text&tr2=1.155
http://cvs.osafoundation.org/index.cgi/chandler/repository/item/Values.py.diff?r1=text&tr1=1.15&r2=text&tr2=1.16
http://cvs.osafoundation.org/index.cgi/chandler/repository/persistence/DBContainer.py.diff?r1=text&tr1=1.16&r2=text&tr2=1.17
http://cvs.osafoundation.org/index.cgi/chandler/repository/persistence/RepositoryError.py.diff?r1=text&tr1=1.1&r2=text&tr2=1.2
http://cvs.osafoundation.org/index.cgi/chandler/repository/persistence/XMLRepository.py.diff?r1=text&tr1=1.78&r2=text&tr2=1.79
http://cvs.osafoundation.org/index.cgi/chandler/repository/persistence/XMLRepositoryView.py.diff?r1=text&tr1=1.50&r2=text&tr2=1.51
Index: chandler/repository/persistence/DBContainer.py
diff -u chandler/repository/persistence/DBContainer.py:1.16 chandler/repository/persistence/DBContainer.py:1.17
--- chandler/repository/persistence/DBContainer.py:1.16 Wed Jul 28 13:40:38 2004
+++ chandler/repository/persistence/DBContainer.py Mon Aug 30 14:27:16 2004
@@ -1,6 +1,6 @@
-__revision__ = "$Revision: 1.16 $"
-__date__ = "$Date: 2004/07/28 20:40:38 $"
+__revision__ = "$Revision: 1.17 $"
+__date__ = "$Date: 2004/08/30 21:27:16 $"
__copyright__ = "Copyright (c) 2002 Open Source Applications Foundation"
__license__ = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
@@ -9,6 +9,7 @@
from struct import pack, unpack
from repository.item.Access import ACL, ACE
+from repository.item.Item import Item
from repository.util.UUID import UUID
from repository.persistence.Repository import Repository
@@ -389,18 +390,40 @@
class HistContainer(DBContainer):
- def writeVersion(self, uuid, version, docId, status, parentId=None):
+ def writeVersion(self, uuid, version, docId, status, parentId,
+ dirtyValues, dirtyRefs):
+
+ if status & Item.DELETED:
+ value = pack('>ll16s', status, docId, parentId._uuid)
- if parentId is not None:
- value = pack('>li16s', docId, status, parentId._uuid)
else:
- value = pack('>li', docId, status)
+ buffer = cStringIO.StringIO()
+
+ buffer.write(pack('>ll', status, docId))
+ for name in dirtyValues:
+ if isinstance(name, unicode):
+ name = name.encode('utf-8')
+ buffer.write(pack('>l', UUIDext.hash(name)))
+ for name in dirtyRefs:
+ if isinstance(name, unicode):
+ name = name.encode('utf-8')
+ buffer.write(pack('>l', UUIDext.hash(name)))
+
+ value = buffer.getvalue()
+ buffer.close()
self.put(pack('>l16s', version, uuid._uuid), value)
# has to run within the commit transaction
def apply(self, fn, oldVersion, newVersion):
+ class hashTuple(tuple):
+ def __contains__(self, name):
+ if isinstance(name, unicode):
+ name = name.encode('utf-8')
+ hash = UUIDext.hash(name)
+ return super(hashTuple, self).__contains__(hash)
+
try:
cursor = self.cursor()
@@ -415,14 +438,22 @@
if version > newVersion:
break
- if len(value[1]) == 24:
- docId, status, parentId = unpack('>li16s', value[1])
+ value = value[1]
+ status, = unpack('>l', value[0:4])
+ value = value[4:]
+
+ if status & Item.DELETED:
+ docId, parentId = unpack('>l16s', value)
parentId = UUID(parentId)
+ dirties = ()
else:
- docId, status = unpack('>li', value[1])
+ docId, = unpack('>l', value[0:4])
parentId = None
+ value = value[4:]
+ dirties = unpack('>%dl' %(len(value) >> 2), value)
+ dirties = hashTuple(dirties)
- fn(UUID(uuid), version, docId, status, parentId)
+ fn(UUID(uuid), version, docId, status, parentId, dirties)
value = cursor.next()
Index: chandler/repository/persistence/RepositoryError.py
diff -u chandler/repository/persistence/RepositoryError.py:1.1 chandler/repository/persistence/RepositoryError.py:1.2
--- chandler/repository/persistence/RepositoryError.py:1.1 Mon Jun 7 23:59:08 2004
+++ chandler/repository/persistence/RepositoryError.py Mon Aug 30 14:27:16 2004
@@ -1,6 +1,6 @@
-__revision__ = "$Revision: 1.1 $"
-__date__ = "$Date: 2004/06/08 06:59:08 $"
+__revision__ = "$Revision: 1.2 $"
+__date__ = "$Date: 2004/08/30 21:27:16 $"
__copyright__ = "Copyright (c) 2002 Open Source Applications Foundation"
__license__ = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
@@ -11,10 +11,11 @@
class VersionConflictError(RepositoryError):
- "Another thread changed %s and saved those changes before this thread got a chance to do so. These changes conflict with this thread's changes, the item cannot be saved."
+ "Another view changed %s and saved those changes before this view - %s - got a chance to do so. These changes conflict with this thread's changes, the item cannot be saved (0x%0.4x/0x%0.4x)."
def __str__(self):
- return self.__doc__ %(self.args[0].itsPath)
+ return self.__doc__ %(self.args[0].itsPath, self.args[0].itsView,
+ self.args[1], self.args[2])
def getItem(self):
return self.args[0]
Index: chandler/repository/item/Item.py
diff -u chandler/repository/item/Item.py:1.154 chandler/repository/item/Item.py:1.155
--- chandler/repository/item/Item.py:1.154 Sun Aug 29 19:50:28 2004
+++ chandler/repository/item/Item.py Mon Aug 30 14:27:15 2004
@@ -1,6 +1,6 @@
-__revision__ = "$Revision: 1.154 $"
-__date__ = "$Date: 2004/08/30 02:50:28 $"
+__revision__ = "$Revision: 1.155 $"
+__date__ = "$Date: 2004/08/30 21:27:15 $"
__copyright__ = "Copyright (c) 2002 Open Source Applications Foundation"
__license__ = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
@@ -1331,8 +1331,9 @@
if attrDict is not None:
assert attribute is not None
assert attrDict is not None
+ attrDict._setDirty(attribute)
self._invokeMonitors(attribute, attrDict)
-
+
self._lastAccess = Item._countAccess()
if self._status & Item.DIRTY == 0:
repository = self.getRepositoryView()
Index: chandler/repository/persistence/XMLRepository.py
diff -u chandler/repository/persistence/XMLRepository.py:1.78 chandler/repository/persistence/XMLRepository.py:1.79
--- chandler/repository/persistence/XMLRepository.py:1.78 Wed Jul 21 14:32:29 2004
+++ chandler/repository/persistence/XMLRepository.py Mon Aug 30 14:27:16 2004
@@ -1,6 +1,6 @@
-__revision__ = "$Revision: 1.78 $"
-__date__ = "$Date: 2004/07/21 21:32:29 $"
+__revision__ = "$Revision: 1.79 $"
+__date__ = "$Date: 2004/08/30 21:27:16 $"
__copyright__ = "Copyright (c) 2002 Open Source Applications Foundation"
__license__ = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
@@ -197,19 +197,11 @@
def loadItem(self, version, uuid):
- store = self.store
- txnStarted = False
- try:
- txnStarted = store.startTransaction()
- docId = store._versions.getDocId(uuid, version)
+ docId = self.store._versions.getDocId(uuid, version)
- # None -> not found, 0 -> deleted
- if docId:
- return self.getDocument(docId)
-
- finally:
- if txnStarted:
- store.abortTransaction()
+ # None -> not found, 0 -> deleted
+ if docId:
+ return self.getDocument(docId)
return None
@@ -558,7 +550,8 @@
self.repository._env.lock_put(lock)
return None
- def saveItem(self, xml, uuid, version, currPN, origPN, status):
+ def saveItem(self, xml, uuid, version, currPN, origPN, status,
+ dirtyValues, dirtyRefs):
doc = XmlDocument()
doc.setContent(xml)
@@ -575,12 +568,14 @@
if status & Item.DELETED:
parent, name = origPN
self._versions.setDocVersion(uuid, version, 0)
- self._history.writeVersion(uuid, version, 0, status, parent)
+ self._history.writeVersion(uuid, version, 0, status,
+ parent, [], [])
self.writeName(version, parent, name, None)
else:
self._versions.setDocVersion(uuid, version, docId)
- self._history.writeVersion(uuid, version, docId, status)
+ self._history.writeVersion(uuid, version, docId, status,
+ None, dirtyValues, dirtyRefs)
if origPN is not None:
parent, name = origPN
Index: chandler/repository/item/Values.py
diff -u chandler/repository/item/Values.py:1.15 chandler/repository/item/Values.py:1.16
--- chandler/repository/item/Values.py:1.15 Sun Aug 29 19:50:28 2004
+++ chandler/repository/item/Values.py Mon Aug 30 14:27:15 2004
@@ -1,6 +1,6 @@
-__revision__ = "$Revision: 1.15 $"
-__date__ = "$Date: 2004/08/30 02:50:28 $"
+__revision__ = "$Revision: 1.16 $"
+__date__ = "$Date: 2004/08/30 21:27:15 $"
__copyright__ = "Copyright (c) 2002 Open Source Applications Foundation"
__license__ = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
@@ -15,6 +15,15 @@
super(Values, self).__init__()
self._setItem(item)
+ def clear(self):
+
+ try:
+ del self._flags
+ except AttributeError:
+ pass
+
+ super(Values, self).clear()
+
def _getItem(self):
return self._item
@@ -68,9 +77,9 @@
def _setFlag(self, key, flag):
- if '_flags' in self.__dict__:
+ try:
self._flags[key] = self._flags.get(key, 0) | flag
- else:
+ except AttributeError:
self._flags = { key: flag }
def _clearFlag(self, key, flag):
@@ -81,17 +90,17 @@
def _setFlags(self, key, flags):
- if '_flags' in self.__dict__:
+ try:
self._flags[key] = flags
- else:
+ except AttributeError:
self._flags = { key: flags }
def _getFlags(self, key, default=0):
- if '_flags' in self.__dict__:
+ try:
return self._flags.get(key, default)
-
- return default
+ except AttributeError:
+ return default
def _isReadOnly(self, key):
@@ -113,13 +122,40 @@
self._setFlag(key, Values.MONITORED)
+ def _setDirty(self, key):
+
+ self._setFlag(key, Values.DIRTY)
+
def _clearTransient(self, key):
- self._flags[key] &= ~Values.TRANSIENT
+ try:
+ self._flags[key] &= ~Values.TRANSIENT
+ except AttributeError:
+ pass
def _clearMonitored(self, key):
- self._flags[key] &= ~Values.MONITORED
+ try:
+ self._flags[key] &= ~Values.MONITORED
+ except AttributeError:
+ pass
+
+ def _getDirties(self):
+
+ try:
+ return [ key for key, flags in self._flags.iteritems()
+ if flags & Values.DIRTY ]
+ except AttributeError:
+ return []
+
+ def _clearDirties(self):
+
+ try:
+ for key, flags in self._flags.iteritems():
+ if flags & Values.DIRTY:
+ self._flags[key] &= ~Values.DIRTY
+ except AttributeError:
+ pass
def _xmlValues(self, generator, withSchema, version, mode):
@@ -142,7 +178,8 @@
if persist:
flags = self._getFlags(key)
- persist = flags & self.TRANSIENT == 0
+ persist = flags & Values.TRANSIENT == 0
+ flags &= Values.SAVEMASK
if persist:
if attribute is not None:
@@ -169,9 +206,11 @@
READONLY = 0x0001 # value is read-only
- TRANSIENT = 0x0002 # value is transient
- MONITORED = 0x0004 # value is monitored
-
+ MONITORED = 0x0002 # value is monitored
+ DIRTY = 0x0100 # value is dirty
+ TRANSIENT = 0x0200 # value is transient
+ SAVEMASK = 0x00ff # save these flags
+
class References(Values):
@@ -206,7 +245,7 @@
for key, value in self.iteritems():
if item.getAttributeAspect(key, 'persist', default=True):
- flags = self._getFlags(key)
+ flags = self._getFlags(key) & Values.SAVEMASK
attrs = {}
if flags:
attrs['flags'] = str(flags)
Index: chandler/repository/persistence/XMLRepositoryView.py
diff -u chandler/repository/persistence/XMLRepositoryView.py:1.50 chandler/repository/persistence/XMLRepositoryView.py:1.51
--- chandler/repository/persistence/XMLRepositoryView.py:1.50 Wed Aug 25 18:00:53 2004
+++ chandler/repository/persistence/XMLRepositoryView.py Mon Aug 30 14:27:16 2004
@@ -1,6 +1,6 @@
-__revision__ = "$Revision: 1.50 $"
-__date__ = "$Date: 2004/08/26 01:00:53 $"
+__revision__ = "$Revision: 1.51 $"
+__date__ = "$Date: 2004/08/30 21:27:16 $"
__copyright__ = "Copyright (c) 2002 Open Source Applications Foundation"
__license__ = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
@@ -197,15 +197,17 @@
if newVersion > self.version:
histNotifications = RepositoryNotifications()
- def unload(uuid, version, docId, status, parent):
+ def unload(uuid, version, docId, status, parent, dirties):
if status & Item.DELETED:
histNotifications.history(uuid, 'deleted',
parent=parent)
elif status & Item.NEW:
- histNotifications.history(uuid, 'added')
+ histNotifications.history(uuid, 'added',
+ dirties=dirties)
else:
- histNotifications.history(uuid, 'changed')
+ histNotifications.history(uuid, 'changed',
+ dirties=dirties)
item = self._registry.get(uuid)
if (item is not None and
@@ -247,6 +249,8 @@
item._version = newVersion
item._status &= ~(Item.NEW | Item.DIRTY |
Item.MERGED | Item.SAVED)
+ item._values._clearDirties()
+ item._references._clearDirties()
del self._log[:]
if newVersion > self.version:
@@ -324,7 +328,9 @@
store.saveItem(xml, uuid, newVersion,
(item.itsParent.itsUUID, item._name), origPN,
- item._status)
+ item._status,
+ item._values._getDirties(),
+ item._references._getDirties())
if item._status & item.ADIRTY:
for name, acl in item._acls.iteritems():
@@ -341,13 +347,13 @@
def _mergeItems(self, items, oldVersion, newVersion, history):
- def check(uuid, version, docId, status, parentId):
+ def check(uuid, version, docId, status, parentId, dirties):
item = items.get(uuid)
if item is not None:
newDirty = item.getDirty()
oldDirty = status & item.DIRTY
if newDirty & oldDirty:
- raise VersionConflictError, item
+ raise VersionConflictError, (item, newDirty, oldDirty)
else:
if (newDirty == item.VDIRTY or oldDirty == item.VDIRTY or
newDirty == item.RDIRTY or oldDirty == item.RDIRTY or
More information about the Commits
mailing list