Rev 62: Implement a DeltaIndex wrapper. in http://bzr.arbash-meinel.com/plugins/groupcompress_rabin

John Arbash Meinel john at arbash-meinel.com
Sat Feb 28 04:24:49 GMT 2009


At http://bzr.arbash-meinel.com/plugins/groupcompress_rabin

------------------------------------------------------------
revno: 62
revision-id: john at arbash-meinel.com-20090228042448-nfhhzpjuqic78bfr
parent: john at arbash-meinel.com-20090228040012-lbkwky6vtdmhjepx
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: groupcompress_rabin
timestamp: Fri 2009-02-27 22:24:48 -0600
message:
  Implement a DeltaIndex wrapper.
  
  This splits out the create_delta_index from the create_delta code.
  Which should also help for profiling purposes.
-------------- next part --------------
=== modified file '_groupcompress_c.pyx'
--- a/_groupcompress_c.pyx	2009-02-27 20:18:47 +0000
+++ b/_groupcompress_c.pyx	2009-02-28 04:24:48 +0000
@@ -75,6 +75,77 @@
 #         free(val[0])
 #         val[0] = NULL
 
+cdef class DeltaIndex:
+
+    cdef object _source
+    cdef delta_index *_index
+
+    def __repr__(self):
+        if self._index == NULL:
+            return '%s(NULL)' % (self.__class__.__name__,)
+        return '%s(%d)' % (self.__class__.__name__,
+            len(self._source))
+
+    def __init__(self, source):
+        self._source = None
+        self._index = NULL
+
+        self._create_delta_index(source)
+
+    def _create_delta_index(self, source):
+        cdef char *c_source
+        cdef Py_ssize_t c_source_size
+
+        if not PyString_CheckExact(source):
+            raise TypeError('source is not a str')
+
+        self._source = source
+        c_source = PyString_AS_STRING(source)
+        c_source_size = PyString_GET_SIZE(source)
+
+        # TODO: Are usage is ultimately going to be different than the one that
+        #       was originally designed. Specifically, we are going to want to
+        #       be able to update the index by hashing future data. It should
+        #       fit just fine into the structure. But for now, we just wrap
+        #       create_delta_index (For example, we could always reserve enough
+        #       space to hash a 4MB string, etc.)
+        self._index = create_delta_index(c_source, c_source_size)
+        # TODO: Handle if _index == NULL
+
+    cdef _ensure_no_index(self):
+        if self._index != NULL:
+            free_delta_index(self._index)
+            self._index = NULL
+
+    def __dealloc__(self):
+        self._ensure_no_index()
+
+    def make_delta(self, target_bytes, max_delta_size=0):
+        """Create a delta from the current source to the target bytes."""
+        cdef char *target
+        cdef Py_ssize_t target_size
+        cdef void * delta
+        cdef unsigned long delta_size
+
+        assert self._index != NULL
+
+        if not PyString_CheckExact(target_bytes):
+            raise TypeError('target is not a str')
+
+        target = PyString_AS_STRING(target_bytes)
+        target_size = PyString_GET_SIZE(target_bytes)
+
+        # TODO: inline some of create_delta so we at least don't have to double
+        #       malloc, and can instead use PyString_FromStringAndSize, to
+        #       allocate the bytes into the final string
+        delta = create_delta(self._index, target, target_size,
+                             &delta_size, max_delta_size)
+        result = None
+        if delta:
+            result = PyString_FromStringAndSize(<char *>delta, delta_size)
+            free(delta)
+        return result
+
 
 def make_delta(source_bytes, target_bytes):
     """Create a delta from source_bytes => target_bytes."""

=== modified file 'tests/test__groupcompress_c.py'
--- a/tests/test__groupcompress_c.py	2009-02-27 18:43:07 +0000
+++ b/tests/test__groupcompress_c.py	2009-02-28 04:24:48 +0000
@@ -69,8 +69,14 @@
         self.requireFeature(CompiledGroupCompress)
         from bzrlib.plugins.groupcompress_rabin import _groupcompress_c
         self._gc_module = _groupcompress_c
-        self.make_delta = _groupcompress_c.make_delta
-        self.apply_delta = _groupcompress_c.apply_delta
+
+
+class TestMakeAndApplyDelta(Test_GroupCompress):
+
+    def setUp(self):
+        super(TestMakeAndApplyDelta, self).setUp()
+        self.make_delta = self._gc_module.make_delta
+        self.apply_delta = self._gc_module.apply_delta
 
     def test_make_delta_is_typesafe(self):
         self.make_delta('a string', 'another string')
@@ -120,3 +126,15 @@
         target = self.apply_delta(_text2,
                     'NM\x90/\x1ebe matched\nagainst other text\n')
         self.assertEqual(_text1, target)
+
+
+class TestDeltaIndex(Test_GroupCompress):
+
+    def test_repr(self):
+        di = self._gc_module.DeltaIndex('test text\n')
+        self.assertEqual('DeltaIndex(10)', repr(di))
+
+    def test_make_delta(self):
+        di = self._gc_module.DeltaIndex(_text1)
+        delta = di.make_delta(_text2)
+        self.assertEqual('MN\x90/\x1fdiffer from\nagainst other text\n', delta)



More information about the bazaar-commits mailing list