~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/_groupcompress_pyx.pyx

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2009-11-19 16:41:31 UTC
  • mfrom: (4788.2.2 2.1.0b3-gc-nogil)
  • Revision ID: pqm@pqm.ubuntu.com-20091119164131-pg4ky6zrxe6kpzhq
(jam) Release the gil during some of the core groupcompress code
        paths.

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
 
32
32
cdef extern from *:
33
33
    ctypedef unsigned long size_t
34
 
    void * malloc(size_t)
35
 
    void * realloc(void *, size_t)
36
 
    void free(void *)
37
 
    void memcpy(void *, void *, size_t)
 
34
    void * malloc(size_t) nogil
 
35
    void * realloc(void *, size_t) nogil
 
36
    void free(void *) nogil
 
37
    void memcpy(void *, void *, size_t) nogil
38
38
 
39
39
 
40
40
cdef extern from "delta.h":
44
44
        unsigned long agg_offset
45
45
    struct delta_index:
46
46
        pass
47
 
    delta_index * create_delta_index(source_info *src, delta_index *old)
 
47
    delta_index * create_delta_index(source_info *src, delta_index *old) nogil
48
48
    delta_index * create_delta_index_from_delta(source_info *delta,
49
 
                                                delta_index *old)
50
 
    void free_delta_index(delta_index *index)
 
49
                                                delta_index *old) nogil
 
50
    void free_delta_index(delta_index *index) nogil
51
51
    void *create_delta(delta_index *indexes,
52
52
             void *buf, unsigned long bufsize,
53
 
             unsigned long *delta_size, unsigned long max_delta_size)
 
53
             unsigned long *delta_size, unsigned long max_delta_size) nogil
54
54
    unsigned long get_delta_hdr_size(unsigned char **datap,
55
 
                                     unsigned char *top)
 
55
                                     unsigned char *top) nogil
56
56
    Py_ssize_t DELTA_SIZE_MIN
57
 
    void *patch_delta(void *src_buf, unsigned long src_size,
58
 
                      void *delta_buf, unsigned long delta_size,
59
 
                      unsigned long *dst_size)
60
57
 
61
58
 
62
59
cdef void *safe_malloc(size_t count) except NULL:
148
145
        src.buf = c_delta
149
146
        src.size = c_delta_size
150
147
        src.agg_offset = self._source_offset + unadded_bytes
151
 
        index = create_delta_index_from_delta(src, self._index)
 
148
        with nogil:
 
149
            index = create_delta_index_from_delta(src, self._index)
152
150
        self._source_offset = src.agg_offset + src.size
153
151
        if index != NULL:
154
152
            free_delta_index(self._index)
188
186
        self._source_offset = src.agg_offset + src.size
189
187
        # We delay creating the index on the first insert
190
188
        if source_location != 0:
191
 
            index = create_delta_index(src, self._index)
 
189
            with nogil:
 
190
                index = create_delta_index(src, self._index)
192
191
            if index != NULL:
193
192
                free_delta_index(self._index)
194
193
                self._index = index
201
200
 
202
201
        # We know that self._index is already NULL, so whatever
203
202
        # create_delta_index returns is fine
204
 
        self._index = create_delta_index(&self._source_infos[0], NULL)
 
203
        with nogil:
 
204
            self._index = create_delta_index(&self._source_infos[0], NULL)
205
205
        assert self._index != NULL
206
206
 
207
207
    cdef _expand_sources(self):
218
218
        cdef Py_ssize_t target_size
219
219
        cdef void * delta
220
220
        cdef unsigned long delta_size
 
221
        cdef unsigned long c_max_delta_size
221
222
 
222
223
        if self._index == NULL:
223
224
            if len(self._sources) == 0:
234
235
        # TODO: inline some of create_delta so we at least don't have to double
235
236
        #       malloc, and can instead use PyString_FromStringAndSize, to
236
237
        #       allocate the bytes into the final string
237
 
        delta = create_delta(self._index,
238
 
                             target, target_size,
239
 
                             &delta_size, max_delta_size)
 
238
        c_max_delta_size = max_delta_size
 
239
        with nogil:
 
240
            delta = create_delta(self._index,
 
241
                                 target, target_size,
 
242
                                 &delta_size, c_max_delta_size)
240
243
        result = None
241
244
        if delta:
242
245
            result = PyString_FromStringAndSize(<char *>delta, delta_size)
276
279
 
277
280
 
278
281
cdef unsigned char *_decode_copy_instruction(unsigned char *bytes,
279
 
    unsigned char cmd, unsigned int *offset, unsigned int *length):
 
282
    unsigned char cmd, unsigned int *offset, unsigned int *length) nogil:
280
283
    """Decode a copy instruction from the next few bytes.
281
284
 
282
285
    A copy instruction is a variable number of bytes, so we will parse the
326
329
    cdef unsigned char *dst_buf, *out, cmd
327
330
    cdef Py_ssize_t size
328
331
    cdef unsigned int cp_off, cp_size
 
332
    cdef int failed
329
333
 
330
334
    data = <unsigned char *>delta
331
335
    top = data + delta_size
335
339
    result = PyString_FromStringAndSize(NULL, size)
336
340
    dst_buf = <unsigned char*>PyString_AS_STRING(result)
337
341
 
338
 
    out = dst_buf
339
 
    while (data < top):
340
 
        cmd = data[0]
341
 
        data = data + 1
342
 
        if (cmd & 0x80):
343
 
            # Copy instruction
344
 
            data = _decode_copy_instruction(data, cmd, &cp_off, &cp_size)
345
 
            if (cp_off + cp_size < cp_size or
346
 
                cp_off + cp_size > source_size or
347
 
                cp_size > size):
348
 
                raise RuntimeError('Something wrong with:'
349
 
                    ' cp_off = %s, cp_size = %s'
350
 
                    ' source_size = %s, size = %s'
351
 
                    % (cp_off, cp_size, source_size, size))
352
 
            memcpy(out, source + cp_off, cp_size)
353
 
            out = out + cp_size
354
 
            size = size - cp_size
355
 
        else:
356
 
            # Insert instruction
357
 
            if cmd == 0:
358
 
                # cmd == 0 is reserved for future encoding
359
 
                # extensions. In the mean time we must fail when
360
 
                # encountering them (might be data corruption).
361
 
                raise RuntimeError('Got delta opcode: 0, not supported')
362
 
            if (cmd > size):
363
 
                raise RuntimeError('Insert instruction longer than remaining'
364
 
                    ' bytes: %d > %d' % (cmd, size))
365
 
            memcpy(out, data, cmd)
366
 
            out = out + cmd
367
 
            data = data + cmd
368
 
            size = size - cmd
 
342
    failed = 0
 
343
    with nogil:
 
344
        out = dst_buf
 
345
        while (data < top):
 
346
            cmd = data[0]
 
347
            data = data + 1
 
348
            if (cmd & 0x80):
 
349
                # Copy instruction
 
350
                data = _decode_copy_instruction(data, cmd, &cp_off, &cp_size)
 
351
                if (cp_off + cp_size < cp_size or
 
352
                    cp_off + cp_size > source_size or
 
353
                    cp_size > size):
 
354
                    failed = 1
 
355
                    break
 
356
                memcpy(out, source + cp_off, cp_size)
 
357
                out = out + cp_size
 
358
                size = size - cp_size
 
359
            else:
 
360
                # Insert instruction
 
361
                if cmd == 0:
 
362
                    # cmd == 0 is reserved for future encoding
 
363
                    # extensions. In the mean time we must fail when
 
364
                    # encountering them (might be data corruption).
 
365
                    failed = 2
 
366
                    break
 
367
                if cmd > size:
 
368
                    failed = 3
 
369
                    break
 
370
                memcpy(out, data, cmd)
 
371
                out = out + cmd
 
372
                data = data + cmd
 
373
                size = size - cmd
 
374
    if failed:
 
375
        if failed == 1:
 
376
            raise ValueError('Something wrong with:'
 
377
                ' cp_off = %s, cp_size = %s'
 
378
                ' source_size = %s, size = %s'
 
379
                % (cp_off, cp_size, source_size, size))
 
380
        elif failed == 2:
 
381
            raise ValueError('Got delta opcode: 0, not supported')
 
382
        elif failed == 3:
 
383
            raise ValueError('Insert instruction longer than remaining'
 
384
                ' bytes: %d > %d' % (cmd, size))
369
385
 
370
386
    # sanity check
371
387
    if (data != top or size != 0):