~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/_groupcompress_pyx.pyx

  • Committer: Jelmer Vernooij
  • Date: 2011-05-11 14:26:41 UTC
  • mto: This revision was merged to the branch mainline in revision 5852.
  • Revision ID: jelmer@samba.org-20110511142641-wbx6svyykkgtq24u
Use osutils.sha_string() when possible.

Show diffs side-by-side

added added

removed removed

Lines of Context:
56
56
        DELTA_SIZE_TOO_BIG
57
57
    delta_result create_delta_index(source_info *src,
58
58
                                    delta_index *old,
59
 
                                    delta_index **fresh,
60
 
                                    int max_entries) nogil
 
59
                                    delta_index **fresh) nogil
61
60
    delta_result create_delta_index_from_delta(source_info *delta,
62
61
                                               delta_index *old,
63
62
                                               delta_index **fresh) nogil
71
70
                                     unsigned char *top) nogil
72
71
    unsigned long sizeof_delta_index(delta_index *index)
73
72
    Py_ssize_t DELTA_SIZE_MIN
74
 
    int get_hash_offset(delta_index *index, int pos, unsigned int *hash_offset)
75
 
    int get_entry_summary(delta_index *index, int pos,
76
 
                          unsigned int *global_offset, unsigned int *hash_val)
77
 
    unsigned int rabin_hash (unsigned char *data)
78
73
 
79
74
 
80
75
cdef void *safe_malloc(size_t count) except NULL:
118
113
    return AssertionError("Unrecognised delta result code: %d" % result)
119
114
 
120
115
 
121
 
def _rabin_hash(content):
122
 
    if not PyString_CheckExact(content):
123
 
        raise ValueError('content must be a string')
124
 
    if len(content) < 16:
125
 
        raise ValueError('content must be at least 16 bytes long')
126
 
    # Try to cast it to an int, if it can fit
127
 
    return int(rabin_hash(<unsigned char*>(PyString_AS_STRING(content))))
128
 
 
129
 
 
130
116
cdef class DeltaIndex:
131
117
 
132
118
    # We need Pyrex 0.9.8+ to understand a 'list' definition, and this object
137
123
    cdef delta_index *_index
138
124
    cdef public unsigned long _source_offset
139
125
    cdef readonly unsigned int _max_num_sources
140
 
    cdef public int _max_bytes_to_index
141
126
 
142
 
    def __init__(self, source=None, max_bytes_to_index=None):
 
127
    def __init__(self, source=None):
143
128
        self._sources = []
144
129
        self._index = NULL
145
130
        self._max_num_sources = 65000
146
131
        self._source_infos = <source_info *>safe_malloc(sizeof(source_info)
147
132
                                                        * self._max_num_sources)
148
133
        self._source_offset = 0
149
 
        self._max_bytes_to_index = 0
150
 
        if max_bytes_to_index is not None:
151
 
            self._max_bytes_to_index = max_bytes_to_index
152
134
 
153
135
        if source is not None:
154
136
            self.add_source(source, 0)
182
164
    def _has_index(self):
183
165
        return (self._index != NULL)
184
166
 
185
 
    def _dump_index(self):
186
 
        """Dump the pointers in the index.
187
 
 
188
 
        This is an arbitrary layout, used for testing. It is not meant to be
189
 
        used in production code.
190
 
 
191
 
        :return: (hash_list, entry_list)
192
 
            hash_list   A list of offsets, so hash[i] points to the 'hash
193
 
                        bucket' starting at the given offset and going until
194
 
                        hash[i+1]
195
 
            entry_list  A list of (text_offset, hash_val). text_offset is the
196
 
                        offset in the "source" texts, and hash_val is the RABIN
197
 
                        hash for that offset.
198
 
                        Note that the entry should be in the hash bucket
199
 
                        defined by
200
 
                        hash[(hash_val & mask)] && hash[(hash_val & mask) + 1]
201
 
        """
202
 
        cdef int pos
203
 
        cdef unsigned int text_offset
204
 
        cdef unsigned int hash_val
205
 
        cdef unsigned int hash_offset
206
 
        if self._index == NULL:
207
 
            return None
208
 
        hash_list = []
209
 
        pos = 0
210
 
        while get_hash_offset(self._index, pos, &hash_offset):
211
 
            hash_list.append(int(hash_offset))
212
 
            pos += 1
213
 
        entry_list = []
214
 
        pos = 0
215
 
        while get_entry_summary(self._index, pos, &text_offset, &hash_val):
216
 
            # Map back using 'int' so that we don't get Long everywhere, when
217
 
            # almost everything is <2**31.
218
 
            val = tuple(map(int, [text_offset, hash_val]))
219
 
            entry_list.append(val)
220
 
            pos += 1
221
 
        return hash_list, entry_list
222
 
 
223
167
    def add_delta_source(self, delta, unadded_bytes):
224
168
        """Add a new delta to the source texts.
225
169
 
263
207
        :param source: The text in question, this must be a byte string
264
208
        :param unadded_bytes: Assume there are this many bytes that didn't get
265
209
            added between this source and the end of the previous source.
266
 
        :param max_pointers: Add no more than this many entries to the index.
267
 
            By default, we sample every 16 bytes, if that would require more
268
 
            than max_entries, we will reduce the sampling rate.
269
 
            A value of 0 means unlimited, None means use the default limit.
270
210
        """
271
211
        cdef char *c_source
272
212
        cdef Py_ssize_t c_source_size
275
215
        cdef unsigned int source_location
276
216
        cdef source_info *src
277
217
        cdef unsigned int num_indexes
278
 
        cdef int max_num_entries
279
218
 
280
219
        if not PyString_CheckExact(source):
281
220
            raise TypeError('source is not a str')
298
237
        # We delay creating the index on the first insert
299
238
        if source_location != 0:
300
239
            with nogil:
301
 
                res = create_delta_index(src, self._index, &index,
302
 
                                         self._max_bytes_to_index)
 
240
                res = create_delta_index(src, self._index, &index)
303
241
            if res != DELTA_OK:
304
242
                raise _translate_delta_failure(res)
305
243
            if index != self._index:
316
254
        # We know that self._index is already NULL, so create_delta_index
317
255
        # will always create a new index unless there's a malloc failure
318
256
        with nogil:
319
 
            res = create_delta_index(&self._source_infos[0], NULL, &index,
320
 
                                     self._max_bytes_to_index)
 
257
            res = create_delta_index(&self._source_infos[0], NULL, &index)
321
258
        if res != DELTA_OK:
322
259
            raise _translate_delta_failure(res)
323
260
        self._index = index