changeset 2103:8c6c0d40f9c8

more metakit fixes
author Richard Jones <richard@users.sourceforge.net>
date Wed, 24 Mar 2004 05:33:13 +0000
parents 666402433998
children f376437cd35c
files roundup/backends/back_metakit.py test/test_metakit.py
diffstat 2 files changed, 62 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/roundup/backends/back_metakit.py	Wed Mar 24 04:57:25 2004 +0000
+++ b/roundup/backends/back_metakit.py	Wed Mar 24 05:33:13 2004 +0000
@@ -1,4 +1,4 @@
-# $Id: back_metakit.py,v 1.67 2004-03-22 07:45:39 richard Exp $
+# $Id: back_metakit.py,v 1.68 2004-03-24 05:33:13 richard Exp $
 '''Metakit backend for Roundup, originally by Gordon McMillan.
 
 Known Current Bugs:
@@ -48,6 +48,7 @@
 from indexer_dbm import Indexer
 import locking
 from roundup.date import Range
+from blobfiles import files_in_dir
 
 # view modes for opening
 # XXX FIXME BPK -> these don't do anything, they are ignored
@@ -324,6 +325,12 @@
         ''' No-op in metakit
         '''
         pass
+
+    def numfiles(self):
+        '''Get number of files in storage, even across subdirectories.
+        '''
+        files_dir = os.path.join(self.config.DATABASE, 'files')
+        return files_in_dir(files_dir)
         
 _STRINGTYPE = type('')
 _LISTTYPE = type([])
@@ -377,6 +384,7 @@
         if view:
             self.maxid = view[-1].id + 1
         self.uncommitted = {}
+        self.comactions = []
         self.rbactions = []
 
         # people reach inside!!
@@ -1533,11 +1541,15 @@
         ''' called post commit of the DB.
             interested subclasses may override '''
         self.uncommitted = {}
+        for action in self.comactions:
+            action()
+        self.comactions = []
         self.rbactions = []
         self.idcache = {}
     def _rollback(self):  
         ''' called pre rollback of the DB.
             interested subclasses may override '''
+        self.comactions = []
         for action in self.rbactions:
             action()
         self.rbactions = []
@@ -1551,6 +1563,10 @@
         iv = self.getindexview(READWRITE)
         if iv:
             iv[:] = []
+    def commitaction(self, action):
+        ''' call this to register a callback called on commit
+            callback is removed on end of transaction '''
+        self.comactions.append(action)
     def rollbackaction(self, action):
         ''' call this to register a callback called on rollback
             callback is removed on end of transaction '''
@@ -1732,6 +1748,8 @@
         if propname == 'content':
             poss_msg = 'Possibly an access right configuration problem.'
             fnm = self.gen_filename(nodeid)
+            if not os.path.exists(fnm):
+                fnm = fnm + '.tmp'
             try:
                 f = open(fnm, 'rb')
             except IOError, (strerror):
@@ -1758,16 +1776,56 @@
 
         # figure a filename
         nm = self.gen_filename(newid)
-        open(nm, 'wb').write(content)
+        f = open(nm + '.tmp', 'wb')
+        f.write(content)
+        f.close()
 
         mimetype = propvalues.get('type', self.default_mime_type)
         self.db.indexer.add_text((self.classname, newid, 'content'), content,
             mimetype)
+
+        # register commit and rollback actions
+        def commit(fnm=nm):
+            os.rename(fnm + '.tmp', fnm)
+        self.commitaction(commit)
         def undo(fnm=nm):
-            os.remove(fnm)
+            os.remove(fnm + '.tmp')
         self.rollbackaction(undo)
         return newid
 
+    def set(self, itemid, **propvalues):
+        if not propvalues:
+            return
+        self.fireAuditors('set', None, propvalues)
+
+        content = propvalues.get('content', None)
+        if content is not None:
+            del propvalues['content']
+
+        propvalues, oldnode = Class.set_inner(self, itemid, **propvalues)
+
+        # figure a filename
+        if content is not None:
+            nm = self.gen_filename(itemid)
+            f = open(nm + '.tmp', 'wb')
+            f.write(content)
+            f.close()
+            mimetype = propvalues.get('type', self.default_mime_type)
+            self.db.indexer.add_text((self.classname, itemid, 'content'),
+                content, mimetype)
+
+            # register commit and rollback actions
+            def commit(fnm=nm):
+                if os.path.exists(fnm):
+                    os.remove(fnm)
+                os.rename(fnm + '.tmp', fnm)
+            self.commitaction(commit)
+            def undo(fnm=nm):
+                os.remove(fnm + '.tmp')
+            self.rollbackaction(undo)
+
+        self.fireReactors('set', oldnode, propvalues)
+
     def index(self, nodeid):
         Class.index(self, nodeid)
         mimetype = self.get(nodeid, 'type')
--- a/test/test_metakit.py	Wed Mar 24 04:57:25 2004 +0000
+++ b/test/test_metakit.py	Wed Mar 24 05:33:13 2004 +0000
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: test_metakit.py,v 1.4 2004-03-18 01:58:46 richard Exp $ 
+# $Id: test_metakit.py,v 1.5 2004-03-24 05:33:13 richard Exp $ 
 import unittest, os, shutil, time, weakref
 
 from db_test_base import DBTest, ROTest, SchemaTest, ClassicInitTest, config, password
@@ -31,37 +31,6 @@
         shutil.rmtree(config.DATABASE)
 
 class metakitDBTest(metakitOpener, DBTest):
-    def testTransactions(self):
-        # remember the number of items we started
-        num_issues = len(self.db.issue.list())
-        self.db.issue.create(title="don't commit me!", status='1')
-        self.assertNotEqual(num_issues, len(self.db.issue.list()))
-        self.db.rollback()
-        self.assertEqual(num_issues, len(self.db.issue.list()))
-        self.db.issue.create(title="please commit me!", status='1')
-        self.assertNotEqual(num_issues, len(self.db.issue.list()))
-        self.db.commit()
-        self.assertNotEqual(num_issues, len(self.db.issue.list()))
-        self.db.rollback()
-        self.assertNotEqual(num_issues, len(self.db.issue.list()))
-        self.db.file.create(name="test", type="text/plain", content="hi")
-        self.db.rollback()
-        num_files = len(self.db.file.list())
-        for i in range(10):
-            self.db.file.create(name="test", type="text/plain", 
-                    content="hi %d"%(i))
-            self.db.commit()
-        # TODO: would be good to be able to ensure the file is not on disk after
-        # a rollback...
-        num_files2 = len(self.db.file.list())
-        self.assertNotEqual(num_files, num_files2)
-        self.db.file.create(name="test", type="text/plain", content="hi")
-        num_rfiles = len(os.listdir(self.db.config.DATABASE + '/files/file/0'))
-        self.db.rollback()
-        num_rfiles2 = len(os.listdir(self.db.config.DATABASE + '/files/file/0'))
-        self.assertEqual(num_files2, len(self.db.file.list()))
-        self.assertEqual(num_rfiles2, num_rfiles-1)
-
     def testBooleanUnset(self):
         # XXX: metakit can't unset Booleans :(
         nid = self.db.user.create(username='foo', assignable=1)

Roundup Issue Tracker: http://roundup-tracker.org/