codernity avatar codernity committed a81f37b

Implements changes for #1

Comments (0)

Files changed (4)

CodernityDB/database.py

                                IndexNotFoundException,
                                IndexConflict)
 
-from CodernityDB.misc import NONE, random_hex_4
+from CodernityDB.misc import NONE
 
 from CodernityDB.env import cdb_environment
 
+from random import randrange
+
 
 def header_for_indexes(index_name, index_class, db_custom="", ind_custom="", classes_code=""):
     return """# %s
         self.indexes_names = {}
         self.opened = False
 
+    def create_new_rev(self, old_rev=None):
+        if old_rev:
+            try:
+                rev_num = int(old_rev[:4], 16)
+            except:
+                raise RevConflict()
+            rev_num += 1
+            if rev_num > 65025:
+            # starting the counter from 0 again
+                rev_num = 0
+            rnd = randrange(65536)
+            return "%04x%04x" % (rev_num, rnd)
+        else:
+            # new rev
+            rnd = randrange(256 ** 2)
+            return '0001%04x' % rnd
+
     def __not_opened(self):
         if not self.opened:
             raise DatabaseIsNotOpened("Database is not opened")
 
     def _read_index_single(self, p, ind, ind_kwargs={}):
         """
-        It will read single index from index file (ie. generated in :py:meth:`._add_single_index`). Then it will perform ``exec`` on that code
+        It will read single index from index file (ie. generated in :py:meth:`._add_single_index`).
+        Then it will perform ``exec`` on that code
 
         :param p: path
         :param ind: index name (will be joined with *p*)
                 ind_obj.create_index()
         if name == 'id':
             self.__set_main_storage()
+            self.__compat_things()
         return name
 
     def edit_index(self, index, reindex=False, ind_kwargs=None):
             if ind.endswith('.py'):
                 self.add_index('path:' + ind, create=False)
 
+    def __compat_things(self):
+        # patch for rev size change
+        if not self.id_ind:
+            return
+        if self.id_ind.entry_line_format[4:6] == '4s':
+            # rev compatibility...
+            import warnings
+            warnings.warn("Your database is using old rev mechanizm \
+for ID index. You should update that index \
+(CodernityDB.migrate.migrate).")
+            from misc import random_hex_4
+            self.create_new_rev = random_hex_4
+
     def create(self, path=None, **kwargs):
         """
         Create database
             raise DatabaseConflict("Already opened")
         self.__open_new(**kwargs)
         self.__set_main_storage()
+        self.__compat_things()
         self.opened = True
         return self.path
 
             index.open_index()
         self.indexes.sort(key=lambda ind: ind._order)
         self.__set_main_storage()
+        self.__compat_things()
         self.opened = True
         return True
 
         db_data = self.get('id', _id)
         if db_data['_rev'] != _rev:
             raise RevConflict()
-        new_rev = random_hex_4()
+        new_rev = self.create_new_rev(_rev)
         storage = self.storage
         start, size = storage.update(value)
         self.id_ind.update(_id, new_rev, start, size)
             self.__not_opened()
             raise PreconditionsException(
                 "Can't add record with forbidden fields")
-        _rev = random_hex_4()
+        _rev = self.create_new_rev()
         if not '_id' in data:
             try:
                 _id = self.id_ind.create_key()

CodernityDB/hash_index.py

         self._find_key = cache(self._find_key)
         self._locate_doc_id = cache(self._locate_doc_id)
         self.bucket_struct = struct.Struct(self.bucket_line_format)
-        self.entry_struct = struct.Struct(entry_line_format)
+        self.entry_struct = struct.Struct(self.entry_line_format)
         self.data_start = (
             self.hash_lim + 1) * self.bucket_line_size + self._start_ind + 2
 
         super(IU_HashIndex, self)._fix_params()
         self.bucket_line_size = struct.calcsize(self.bucket_line_format)
         self.entry_line_size = struct.calcsize(self.entry_line_format)
+        self.bucket_struct = struct.Struct(self.bucket_line_format)
+        self.entry_struct = struct.Struct(self.entry_line_format)
         self.data_start = (
             self.hash_lim + 1) * self.bucket_line_size + self._start_ind + 2
 
     That design is because main index logic should be always in database not in custom user indexes.
     """
 
-    def __init__(self, db_path, name, entry_line_format="<32s4sIIcI", *args, **kwargs):
+    def __init__(self, db_path, name, entry_line_format="<32s8sIIcI", *args, **kwargs):
         if 'key' in kwargs:
             raise IndexPreconditionsException(
                 "UniqueHashIndex doesn't accept key parameter'")

CodernityDB/misc.py

     return uuid.UUID(int=getrandbits(128), version=4).hex
 
 
-def random_hex_4():
+def random_hex_4(*args, **kwargs):
     return '%04x' % randrange(256 ** 2)
         doc = dict(a=1)
         db.insert(doc)
         doc2 = doc.copy()
-        doc2['_rev'] = '0000'
+        doc2['_rev'] = '00000000'
         with pytest.raises(RevConflict):
             db.update(doc2)
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.