Skip to content

Commit 9ba93c0

Browse files
committed
Apparently, the most serious memory bugs are fixed for now, lets get back to the actual thing
1 parent 445b716 commit 9ba93c0

File tree

2 files changed

+57
-17
lines changed

2 files changed

+57
-17
lines changed

_fun.c

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <stdint.h>
33
#include <assert.h>
44
#include <stdio.h>
5+
#include <math.h>
56

67
static PyObject *PackIndexFile_sha_to_index(PyObject *self, PyObject *args)
78
{
@@ -87,7 +88,6 @@ static PyObject *PackIndexFile_sha_to_index(PyObject *self, PyObject *args)
8788
typedef unsigned long long ull;
8889
typedef unsigned int uint;
8990

90-
9191
// DELTA CHUNK
9292
////////////////
9393
// Internal Delta Chunk Objects
@@ -142,13 +142,17 @@ int DCV_grow(DeltaChunkVector* vec, uint num_dc)
142142
}
143143

144144
if (vec->mem == NULL){
145-
vec->mem = PyMem_Malloc(grow_by_chunks * sizeof(vec->mem));
145+
vec->mem = PyMem_Malloc(grow_by_chunks * sizeof(DeltaChunk));
146146
} else {
147-
vec->mem = PyMem_Realloc(vec->mem, (vec->reserved_size + grow_by_chunks) * sizeof(vec->mem));
147+
vec->mem = PyMem_Realloc(vec->mem, (vec->reserved_size + grow_by_chunks) * sizeof(DeltaChunk));
148148
}
149149
assert(vec->mem != NULL);
150150
vec->reserved_size = vec->reserved_size + grow_by_chunks;
151151

152+
#ifdef DEBUG
153+
fprintf(stderr, "Allocated %i bytes at %p, to hold up to %i chunks\n", (int)((vec->reserved_size + grow_by_chunks) * sizeof(DeltaChunk)), vec->mem, (int)(vec->reserved_size + grow_by_chunks));
154+
#endif
155+
152156
return vec->mem != NULL;
153157
}
154158

@@ -192,7 +196,11 @@ DeltaChunk* DCV_end(DeltaChunkVector* vec)
192196
void DCV_dealloc(DeltaChunkVector* vec)
193197
{
194198
if (vec->mem){
195-
const DeltaChunk* end = DCV_end(vec);
199+
#ifdef DEBUG
200+
fprintf(stderr, "Freeing %p\n", (void*)vec->mem);
201+
#endif
202+
203+
const DeltaChunk* end = &vec->mem[vec->size];
196204
DeltaChunk* i;
197205
for(i = vec->mem; i < end; i++){
198206
DC_destroy(i);
@@ -342,6 +350,7 @@ DeltaChunkList* DCL_new_instance(void)
342350

343351
DCL_init(dcl, 0, 0);
344352
assert(dcl->vec.size == 0);
353+
assert(dcl->vec.mem == NULL);
345354
return dcl;
346355
}
347356

@@ -377,16 +386,13 @@ static PyObject* connect_deltas(PyObject *self, PyObject *dstreams)
377386
stream_iter = dstreams;
378387
}
379388

380-
DeltaChunkList* bdcl = 0;
381-
DeltaChunkList* tdcl = 0;
382-
DeltaChunkList* dcl = 0;
389+
DeltaChunkVector bdcv;
390+
DeltaChunkVector tdcv;
391+
DeltaChunkVector dcv;
392+
DCV_init(&bdcv, 0);
393+
DCV_init(&dcv, 0);
394+
DCV_init(&tdcv, 0);
383395

384-
dcl = tdcl = DCL_new_instance();
385-
assert(dcl != NULL);
386-
if (!dcl){
387-
PyErr_SetString(PyExc_RuntimeError, "Couldn't allocate list");
388-
return NULL;
389-
}
390396

391397
unsigned int dsi;
392398
PyObject* ds;
@@ -408,6 +414,10 @@ static PyObject* connect_deltas(PyObject *self, PyObject *dstreams)
408414
Py_ssize_t ofs = 0;
409415
const ull base_size = msb_size(data, dlen, 0, &ofs);
410416
const ull target_size = msb_size(data, dlen, ofs, &ofs);
417+
418+
// estimate number of ops - assume one third adds, half two byte (size+offset) copies
419+
const uint approx_num_cmds = (dlen / 3) + (((dlen / 3) * 2) / (2+2+1));
420+
DCV_grow(&dcv, approx_num_cmds);
411421

412422
// parse command stream
413423
const char* dend = data + dlen;
@@ -431,7 +441,7 @@ static PyObject* connect_deltas(PyObject *self, PyObject *dstreams)
431441
const unsigned long rbound = cp_off + cp_size;
432442
if (rbound < cp_size ||
433443
rbound > base_size){
434-
goto loop_end;
444+
break;
435445
}
436446

437447
// TODO: Add node
@@ -446,8 +456,19 @@ static PyObject* connect_deltas(PyObject *self, PyObject *dstreams)
446456
goto loop_end;
447457
}
448458
}// END handle command opcodes
449-
450459
assert(tbw == target_size);
460+
461+
// swap the vector
462+
// Skip the first vector, as it is also used as top chunk vector
463+
if (bdcv.mem != tdcv.mem){
464+
DCV_dealloc(&bdcv);
465+
}
466+
bdcv = dcv;
467+
if (dsi == 0){
468+
tdcv = dcv;
469+
}
470+
DCV_init(&dcv, 0);
471+
451472

452473
loop_end:
453474
// perform cleanup
@@ -467,11 +488,31 @@ static PyObject* connect_deltas(PyObject *self, PyObject *dstreams)
467488
Py_DECREF(stream_iter);
468489
}
469490

491+
DCV_dealloc(&bdcv);
492+
if (dsi > 1){
493+
// otherwise dcv equals tcl
494+
DCV_dealloc(&dcv);
495+
}
496+
497+
// Return the actual python object - its just a container
498+
DeltaChunkList* dcl = DCL_new_instance();
499+
if (!dcl){
500+
PyErr_SetString(PyExc_RuntimeError, "Couldn't allocate list");
501+
// Otherwise tdcv would be deallocated by the chunk list
502+
DCV_dealloc(&tdcv);
503+
error = 1;
504+
} else {
505+
// Plain copy, don't deallocate
506+
dcl->vec = tdcv;
507+
}
508+
470509
if (error){
510+
// Will dealloc tdcv
511+
Py_XDECREF(dcl);
471512
return NULL;
472513
}
473514

474-
return (PyObject*)tdcl;
515+
return (PyObject*)dcl;
475516
}
476517

477518
static PyMethodDef py_fun[] = {

stream.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,6 @@ def _set_cache_(self, attr):
338338
# the last delta, and reverse-merge its ancestor delta, until we receive
339339
# the final delta data stream.
340340
dcl = connect_deltas(self._dstreams)
341-
assert dcl is not None
342341

343342
# call len directly, as the (optional) c version doesn't implement the sequence
344343
# protocol

0 commit comments

Comments
 (0)