/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/_chk_map_pyx.pyx

  • Committer: Robert Collins
  • Date: 2010-05-06 23:41:35 UTC
  • mto: This revision was merged to the branch mainline in revision 5223.
  • Revision ID: robertc@robertcollins.net-20100506234135-yivbzczw1sejxnxc
Lock methods on ``Tree``, ``Branch`` and ``Repository`` are now
expected to return an object which can be used to unlock them. This reduces
duplicate code when using cleanups. The previous 'tokens's returned by
``Branch.lock_write`` and ``Repository.lock_write`` are now attributes
on the result of the lock_write. ``repository.RepositoryWriteLockResult``
and ``branch.BranchWriteLockResult`` document this. (Robert Collins)

``log._get_info_for_log_files`` now takes an add_cleanup callable.
(Robert Collins)

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
from __future__ import absolute_import
18
17
 
 
18
#python2.4 support
19
19
cdef extern from "python-compat.h":
20
20
    pass
21
21
 
22
 
from libc.stdio cimport (
23
 
    sprintf,
24
 
    )
25
 
from libc.stdlib cimport (
26
 
    strtol,
27
 
    )
28
 
from libc.string cimport (
29
 
    memcmp,
30
 
    memcpy,
31
 
    memchr,
32
 
    )
33
 
 
34
 
from cpython.bytes cimport (
35
 
    PyBytes_CheckExact,
36
 
    PyBytes_FromStringAndSize,
37
 
    PyBytes_AS_STRING,
38
 
    PyBytes_GET_SIZE,
39
 
    )
40
 
from cpython.dict cimport (
41
 
    PyDict_SetItem,
42
 
    )
43
 
from cpython.int cimport (
44
 
    PyInt_AsUnsignedLongMask,
45
 
    )
46
 
from cpython.object cimport (
47
 
    PyObject,
48
 
    )
49
 
from cpython.ref cimport (
50
 
    Py_INCREF,
51
 
    )
52
 
from cpython.tuple cimport (
53
 
    PyTuple_CheckExact,
54
 
    PyTuple_GET_SIZE,
55
 
    )
56
 
 
57
 
from ._str_helpers cimport (
58
 
    _my_memrchr,
59
 
    safe_interned_string_from_size,
60
 
    )
 
22
cdef extern from *:
 
23
    ctypedef unsigned int size_t
 
24
    int memcmp(void *, void*, size_t)
 
25
    void memcpy(void *, void*, size_t)
 
26
    void *memchr(void *s, int c, size_t len)
 
27
    long strtol(char *, char **, int)
 
28
    void sprintf(char *, char *, ...)
 
29
 
 
30
cdef extern from "Python.h":
 
31
    ctypedef int Py_ssize_t # Required for older pyrex versions
 
32
    ctypedef struct PyObject:
 
33
        pass
 
34
    int PyTuple_CheckExact(object p)
 
35
    Py_ssize_t PyTuple_GET_SIZE(object t)
 
36
    int PyString_CheckExact(object)
 
37
    char *PyString_AS_STRING(object s)
 
38
    Py_ssize_t PyString_GET_SIZE(object)
 
39
 
 
40
    int PyDict_SetItem(object d, object k, object v) except -1
 
41
 
 
42
    object PyTuple_New(Py_ssize_t count)
 
43
    void PyTuple_SET_ITEM(object t, Py_ssize_t offset, object)
 
44
 
 
45
    void Py_INCREF(object)
 
46
 
 
47
    PyObject * PyTuple_GET_ITEM_ptr "PyTuple_GET_ITEM" (object t,
 
48
                                                        Py_ssize_t offset)
 
49
    int PyString_CheckExact_ptr "PyString_CheckExact" (PyObject *p)
 
50
    Py_ssize_t PyString_GET_SIZE_ptr "PyString_GET_SIZE" (PyObject *s)
 
51
    char *PyString_AS_STRING_ptr "PyString_AS_STRING" (PyObject *s)
 
52
    object PyString_FromStringAndSize(char*, Py_ssize_t)
61
53
 
62
54
# cimport all of the definitions we will need to access
63
 
from .._static_tuple_c cimport (
64
 
    import_static_tuple_c,
65
 
    StaticTuple,
66
 
    StaticTuple_New,
67
 
    StaticTuple_Intern,
68
 
    StaticTuple_SET_ITEM,
69
 
    StaticTuple_CheckExact,
70
 
    StaticTuple_GET_SIZE,
71
 
    )
 
55
from _static_tuple_c cimport StaticTuple,\
 
56
    import_static_tuple_c, StaticTuple_New, \
 
57
    StaticTuple_Intern, StaticTuple_SET_ITEM, StaticTuple_CheckExact
 
58
 
 
59
cdef extern from "_static_tuple_c.h":
 
60
    # Defined explicitly rather than cimport-ing. Trying to use cimport, the
 
61
    # type for PyObject is a different class that happens to have the same
 
62
    # name...
 
63
    PyObject * StaticTuple_GET_ITEM_ptr "StaticTuple_GET_ITEM" (StaticTuple,
 
64
                                                                Py_ssize_t)
 
65
 
 
66
cdef extern from "zlib.h":
 
67
    ctypedef unsigned long uLong
 
68
    ctypedef unsigned int uInt
 
69
    ctypedef unsigned char Bytef
 
70
 
 
71
    uLong crc32(uLong crc, Bytef *buf, uInt len)
 
72
 
72
73
 
73
74
# Set up the StaticTuple C_API functionality
74
75
import_static_tuple_c()
75
76
 
76
 
cdef object crc32
77
 
from zlib import crc32
78
 
 
79
77
cdef object _LeafNode
80
78
_LeafNode = None
81
79
cdef object _InternalNode
83
81
cdef object _unknown
84
82
_unknown = None
85
83
 
 
84
# We shouldn't just copy this from _dirstate_helpers_pyx
 
85
cdef void* _my_memrchr(void *s, int c, size_t n): # cannot_raise
 
86
    # memrchr seems to be a GNU extension, so we have to implement it ourselves
 
87
    cdef char *pos
 
88
    cdef char *start
 
89
 
 
90
    start = <char*>s
 
91
    pos = start + n - 1
 
92
    while pos >= start:
 
93
        if pos[0] == c:
 
94
            return <void*>pos
 
95
        pos = pos - 1
 
96
    return NULL
 
97
 
86
98
 
87
99
def _search_key_16(key):
88
100
    """See chk_map._search_key_16."""
89
101
    cdef Py_ssize_t num_bits
90
102
    cdef Py_ssize_t i, j
91
103
    cdef Py_ssize_t num_out_bytes
92
 
    cdef unsigned long crc_val
 
104
    cdef Bytef *c_bit
 
105
    cdef uLong c_len
 
106
    cdef uInt crc_val
93
107
    cdef Py_ssize_t out_off
94
108
    cdef char *c_out
 
109
    cdef PyObject *bit
95
110
 
 
111
    if not StaticTuple_CheckExact(key):
 
112
        raise TypeError('key %r is not a StaticTuple' % (key,))
96
113
    num_bits = len(key)
97
114
    # 4 bytes per crc32, and another 1 byte between bits
98
115
    num_out_bytes = (9 * num_bits) - 1
99
 
    out = PyBytes_FromStringAndSize(NULL, num_out_bytes)
100
 
    c_out = PyBytes_AS_STRING(out)
 
116
    out = PyString_FromStringAndSize(NULL, num_out_bytes)
 
117
    c_out = PyString_AS_STRING(out)
101
118
    for i from 0 <= i < num_bits:
102
119
        if i > 0:
103
120
            c_out[0] = c'\x00'
104
121
            c_out = c_out + 1
105
 
        crc_val = PyInt_AsUnsignedLongMask(crc32(key[i])) & 0xFFFFFFFFUL
 
122
        # We use the _ptr variant, because GET_ITEM returns a borrowed
 
123
        # reference, and Pyrex assumes that returned 'object' are a new
 
124
        # reference
 
125
        bit = StaticTuple_GET_ITEM_ptr(key, i)
 
126
        if not PyString_CheckExact_ptr(bit):
 
127
            raise TypeError('Bit %d of %r is not a string' % (i, key))
 
128
        c_bit = <Bytef *>PyString_AS_STRING_ptr(bit)
 
129
        c_len = PyString_GET_SIZE_ptr(bit)
 
130
        crc_val = crc32(0, c_bit, c_len)
106
131
        # Hex(val) order
107
 
        sprintf(c_out, '%08lX', crc_val)
 
132
        sprintf(c_out, '%08X', crc_val)
108
133
        c_out = c_out + 8
109
134
    return out
110
135
 
114
139
    cdef Py_ssize_t num_bits
115
140
    cdef Py_ssize_t i, j
116
141
    cdef Py_ssize_t num_out_bytes
117
 
    cdef unsigned long crc_val
 
142
    cdef Bytef *c_bit
 
143
    cdef uLong c_len
 
144
    cdef uInt crc_val
118
145
    cdef Py_ssize_t out_off
119
146
    cdef char *c_out
 
147
    cdef PyObject *bit
120
148
 
 
149
    if not StaticTuple_CheckExact(key):
 
150
        raise TypeError('key %r is not a StaticTuple' % (key,))
121
151
    num_bits = len(key)
122
152
    # 4 bytes per crc32, and another 1 byte between bits
123
153
    num_out_bytes = (5 * num_bits) - 1
124
 
    out = PyBytes_FromStringAndSize(NULL, num_out_bytes)
125
 
    c_out = PyBytes_AS_STRING(out)
 
154
    out = PyString_FromStringAndSize(NULL, num_out_bytes)
 
155
    c_out = PyString_AS_STRING(out)
126
156
    for i from 0 <= i < num_bits:
127
157
        if i > 0:
128
158
            c_out[0] = c'\x00'
129
159
            c_out = c_out + 1
130
 
        crc_val = PyInt_AsUnsignedLongMask(crc32(key[i]))
 
160
        bit = StaticTuple_GET_ITEM_ptr(key, i)
 
161
        if not PyString_CheckExact_ptr(bit):
 
162
            raise TypeError('Bit %d of %r is not a string: %r'
 
163
                            % (i, key, <object>bit))
 
164
        c_bit = <Bytef *>PyString_AS_STRING_ptr(bit)
 
165
        c_len = PyString_GET_SIZE_ptr(bit)
 
166
        crc_val = crc32(0, c_bit, c_len)
131
167
        # MSB order
132
168
        c_out[0] = (crc_val >> 24) & 0xFF
133
169
        c_out[1] = (crc_val >> 16) & 0xFF
149
185
    :return: The integer stored in those bytes
150
186
    """
151
187
    cdef int value
152
 
    cdef char *next_line
153
 
    cdef char *next_int
 
188
    cdef char *next_line, *next
154
189
 
155
190
    next_line = <char *>memchr(cur[0], c'\n', end - cur[0])
156
191
    if next_line == NULL:
157
192
        raise ValueError("Missing %s line\n" % message)
158
193
 
159
 
    value = strtol(cur[0], &next_int, 10)
160
 
    if next_int != next_line:
 
194
    value = strtol(cur[0], &next, 10)
 
195
    if next != next_line:
161
196
        raise ValueError("%s line not a proper int\n" % message)
162
197
    cur[0] = next_line + 1
163
198
    return value
164
199
 
165
200
 
166
 
cdef _import_globals():
167
 
    """Set the global attributes. Done lazy to avoid recursive import loops."""
168
 
    global _LeafNode, _InternalNode, _unknown
169
 
 
170
 
    from . import chk_map
171
 
    _LeafNode = chk_map.LeafNode
172
 
    _InternalNode = chk_map.InternalNode
173
 
    _unknown = chk_map._unknown
174
 
 
175
 
 
176
 
def _deserialise_leaf_node(data, key, search_key_func=None):
 
201
def _deserialise_leaf_node(bytes, key, search_key_func=None):
177
202
    """Deserialise bytes, with key key, into a LeafNode.
178
203
 
179
204
    :param bytes: The bytes of the node.
180
205
    :param key: The key that the serialised node has.
181
206
    """
182
 
    cdef char *c_bytes
183
 
    cdef char *cur
184
 
    cdef char *next
185
 
    cdef char *end
 
207
    cdef char *c_bytes, *cur, *next, *end
186
208
    cdef char *next_line
187
209
    cdef Py_ssize_t c_bytes_len, prefix_length, items_length
188
210
    cdef int maximum_size, width, length, i, prefix_tail_len
189
211
    cdef int num_value_lines, num_prefix_bits
190
 
    cdef char *prefix
191
 
    cdef char *value_start
192
 
    cdef char *prefix_tail
193
 
    cdef char *next_null
194
 
    cdef char *last_null
195
 
    cdef char *line_start
196
 
    cdef char *c_entry
197
 
    cdef char *entry_start
 
212
    cdef char *prefix, *value_start, *prefix_tail
 
213
    cdef char *next_null, *last_null, *line_start
 
214
    cdef char *c_entry, *entry_start
198
215
    cdef StaticTuple entry_bits
199
216
 
200
217
    if _LeafNode is None:
201
 
        _import_globals()
 
218
        from bzrlib import chk_map
 
219
        _LeafNode = chk_map.LeafNode
 
220
        _InternalNode = chk_map.InternalNode
 
221
        _unknown = chk_map._unknown
202
222
 
203
223
    result = _LeafNode(search_key_func=search_key_func)
204
224
    # Splitlines can split on '\r' so don't use it, split('\n') adds an
205
225
    # extra '' if the bytes ends in a final newline.
206
 
    if not PyBytes_CheckExact(data):
207
 
        raise TypeError('expected bytes not %s' % (type(data),))
208
 
 
209
 
    c_bytes = PyBytes_AS_STRING(data)
210
 
    c_bytes_len = PyBytes_GET_SIZE(data)
211
 
 
212
 
    if c_bytes_len < 9 or memcmp(c_bytes, b"chkleaf:\n", 9) != 0:
213
 
        raise ValueError("not a serialised leaf node: %r" % data)
 
226
    if not PyString_CheckExact(bytes):
 
227
        raise TypeError('bytes must be a plain string not %s' % (type(bytes),))
 
228
 
 
229
    c_bytes = PyString_AS_STRING(bytes)
 
230
    c_bytes_len = PyString_GET_SIZE(bytes)
 
231
 
 
232
    if c_bytes_len < 9 or memcmp(c_bytes, "chkleaf:\n", 9) != 0:
 
233
        raise ValueError("not a serialised leaf node: %r" % bytes)
214
234
    if c_bytes[c_bytes_len - 1] != c'\n':
215
235
        raise ValueError("bytes does not end in a newline")
216
236
 
234
254
    while next_null != NULL:
235
255
        num_prefix_bits = num_prefix_bits + 1
236
256
        prefix_bits.append(
237
 
            PyBytes_FromStringAndSize(prefix_tail, next_null - prefix_tail))
 
257
            PyString_FromStringAndSize(prefix_tail, next_null - prefix_tail))
238
258
        prefix_tail = next_null + 1
239
259
        next_null = <char *>memchr(prefix_tail, c'\0', next_line - prefix_tail)
240
260
    prefix_tail_len = next_line - prefix_tail
271
291
            # SET_ITEM 'steals' a reference
272
292
            Py_INCREF(entry)
273
293
            StaticTuple_SET_ITEM(entry_bits, i, entry)
274
 
        value = PyBytes_FromStringAndSize(value_start, next_line - value_start)
 
294
        value = PyString_FromStringAndSize(value_start, next_line - value_start)
275
295
        # The next entry bit needs the 'tail' from the prefix, and first part
276
296
        # of the line
277
297
        entry_start = line_start
279
299
                                   last_null - entry_start + 1)
280
300
        if next_null == NULL:
281
301
            raise ValueError('bad no null, bad')
282
 
        entry = PyBytes_FromStringAndSize(
283
 
            NULL, prefix_tail_len + next_null - line_start)
284
 
        c_entry = PyBytes_AS_STRING(entry)
 
302
        entry = PyString_FromStringAndSize(NULL,
 
303
                    prefix_tail_len + next_null - line_start)
 
304
        c_entry = PyString_AS_STRING(entry)
285
305
        if prefix_tail_len > 0:
286
306
            memcpy(c_entry, prefix_tail, prefix_tail_len)
287
307
        if next_null - line_start > 0:
298
318
                                       last_null - entry_start + 1)
299
319
            if next_null == NULL:
300
320
                raise ValueError('bad no null')
301
 
            entry = PyBytes_FromStringAndSize(
302
 
                entry_start, next_null - entry_start)
 
321
            entry = PyString_FromStringAndSize(entry_start,
 
322
                                               next_null - entry_start)
303
323
            Py_INCREF(entry)
304
324
            StaticTuple_SET_ITEM(entry_bits, i, entry)
305
 
        if StaticTuple_GET_SIZE(entry_bits) != width:
 
325
        if len(entry_bits) != width:
306
326
            raise AssertionError(
307
327
                'Incorrect number of elements (%d vs %d)'
308
328
                % (len(entry_bits)+1, width + 1))
322
342
        result._common_serialised_prefix = None
323
343
    else:
324
344
        result._search_prefix = _unknown
325
 
        result._common_serialised_prefix = PyBytes_FromStringAndSize(
326
 
            prefix, prefix_length)
 
345
        result._common_serialised_prefix = PyString_FromStringAndSize(prefix,
 
346
                                                prefix_length)
327
347
    if c_bytes_len != result._current_size():
328
348
        raise AssertionError('_current_size computed incorrectly %d != %d',
329
349
            c_bytes_len, result._current_size())
330
350
    return result
331
351
 
332
352
 
333
 
def _deserialise_internal_node(data, key, search_key_func=None):
334
 
    cdef char *c_bytes
335
 
    cdef char *cur
336
 
    cdef char *end
 
353
def _deserialise_internal_node(bytes, key, search_key_func=None):
 
354
    cdef char *c_bytes, *cur, *next, *end
337
355
    cdef char *next_line
338
356
    cdef Py_ssize_t c_bytes_len, prefix_length
339
357
    cdef int maximum_size, width, length, i, prefix_tail_len
340
 
    cdef char *prefix
341
 
    cdef char *line_prefix
342
 
    cdef char *next_null
343
 
    cdef char *c_item_prefix
 
358
    cdef char *prefix, *line_prefix, *next_null, *c_item_prefix
344
359
 
345
360
    if _InternalNode is None:
346
 
        _import_globals()
 
361
        from bzrlib import chk_map
 
362
        _LeafNode = chk_map.LeafNode
 
363
        _InternalNode = chk_map.InternalNode
 
364
        _unknown = chk_map._unknown
347
365
    result = _InternalNode(search_key_func=search_key_func)
348
366
 
349
367
    if not StaticTuple_CheckExact(key):
350
368
        raise TypeError('key %r is not a StaticTuple' % (key,))
351
 
    if not PyBytes_CheckExact(data):
352
 
        raise TypeError('expected bytes not %s' % (type(data),))
353
 
 
354
 
    c_bytes = PyBytes_AS_STRING(data)
355
 
    c_bytes_len = PyBytes_GET_SIZE(data)
356
 
 
357
 
    if c_bytes_len < 9 or memcmp(c_bytes, b"chknode:\n", 9) != 0:
358
 
        raise ValueError("not a serialised internal node: %r" % data)
 
369
    if not PyString_CheckExact(bytes):
 
370
        raise TypeError('bytes must be a plain string not %s' % (type(bytes),))
 
371
 
 
372
    c_bytes = PyString_AS_STRING(bytes)
 
373
    c_bytes_len = PyString_GET_SIZE(bytes)
 
374
 
 
375
    if c_bytes_len < 9 or memcmp(c_bytes, "chknode:\n", 9) != 0:
 
376
        raise ValueError("not a serialised internal node: %r" % bytes)
359
377
    if c_bytes[c_bytes_len - 1] != c'\n':
360
378
        raise ValueError("bytes does not end in a newline")
361
379
 
381
399
        next_null = <char *>_my_memrchr(cur, c'\0', next_line - cur)
382
400
        if next_null == NULL:
383
401
            raise ValueError('bad no null')
384
 
        item_prefix = PyBytes_FromStringAndSize(
385
 
            NULL, prefix_length + next_null - cur)
386
 
        c_item_prefix = PyBytes_AS_STRING(item_prefix)
 
402
        item_prefix = PyString_FromStringAndSize(NULL,
 
403
            prefix_length + next_null - cur)
 
404
        c_item_prefix = PyString_AS_STRING(item_prefix)
387
405
        if prefix_length:
388
406
            memcpy(c_item_prefix, prefix, prefix_length)
389
407
        memcpy(c_item_prefix + prefix_length, cur, next_null - cur)
390
 
        flat_key = PyBytes_FromStringAndSize(
391
 
            next_null + 1, next_line - next_null - 1)
 
408
        flat_key = PyString_FromStringAndSize(next_null + 1,
 
409
                                              next_line - next_null - 1)
392
410
        flat_key = StaticTuple(flat_key).intern()
393
411
        PyDict_SetItem(items, item_prefix, flat_key)
394
412
        cur = next_line + 1
400
418
    result._key_width = width
401
419
    # XXX: InternalNodes don't really care about their size, and this will
402
420
    #      change if we add prefix compression
403
 
    result._raw_size = None
 
421
    result._raw_size = None # len(bytes)
404
422
    result._node_width = len(item_prefix)
405
 
    result._search_prefix = PyBytes_FromStringAndSize(prefix, prefix_length)
 
423
    result._search_prefix = PyString_FromStringAndSize(prefix, prefix_length)
406
424
    return result
407
 
 
408
 
 
409
 
def _bytes_to_text_key(data):
410
 
    """Take a CHKInventory value string and return a (file_id, rev_id) tuple"""
411
 
    cdef StaticTuple key
412
 
    cdef char *byte_str
413
 
    cdef char *cur_end
414
 
    cdef char *file_id_str
415
 
    cdef char *byte_end
416
 
    cdef char *revision_str
417
 
    cdef Py_ssize_t byte_size, pos, file_id_len
418
 
 
419
 
    if not PyBytes_CheckExact(data):
420
 
        raise TypeError('expected bytes not %s' % (type(data),))
421
 
    byte_str = PyBytes_AS_STRING(data)
422
 
    byte_size = PyBytes_GET_SIZE(data)
423
 
    byte_end = byte_str + byte_size
424
 
    cur_end = <char*>memchr(byte_str, c':', byte_size)
425
 
    if cur_end == NULL:
426
 
        raise ValueError('No kind section found.')
427
 
    if cur_end[1] != c' ':
428
 
        raise ValueError(
429
 
            'Kind section should end with ": ", got %r' % str(cur_end[:2],))
430
 
    file_id_str = cur_end + 2
431
 
    # file_id is now the data up until the next newline
432
 
    cur_end = <char*>memchr(file_id_str, c'\n', byte_end - file_id_str)
433
 
    if cur_end == NULL:
434
 
        raise ValueError('no newline after file-id')
435
 
    file_id = safe_interned_string_from_size(file_id_str,
436
 
                                             cur_end - file_id_str)
437
 
    # this is the end of the parent_str
438
 
    cur_end = <char*>memchr(cur_end + 1, c'\n', byte_end - cur_end - 1)
439
 
    if cur_end == NULL:
440
 
        raise ValueError('no newline after parent_str')
441
 
    # end of the name str
442
 
    cur_end = <char*>memchr(cur_end + 1, c'\n', byte_end - cur_end - 1)
443
 
    if cur_end == NULL:
444
 
        raise ValueError('no newline after name str')
445
 
    # the next section is the revision info
446
 
    revision_str = cur_end + 1
447
 
    cur_end = <char*>memchr(cur_end + 1, c'\n', byte_end - cur_end - 1)
448
 
    if cur_end == NULL:
449
 
        # This is probably a dir: entry, which has revision as the last item
450
 
        cur_end = byte_end
451
 
    revision = safe_interned_string_from_size(revision_str,
452
 
        cur_end - revision_str)
453
 
    key = StaticTuple_New(2)
454
 
    Py_INCREF(file_id)
455
 
    StaticTuple_SET_ITEM(key, 0, file_id)
456
 
    Py_INCREF(revision)
457
 
    StaticTuple_SET_ITEM(key, 1, revision)
458
 
    return StaticTuple_Intern(key)