##// END OF EJS Templates
index: embed nodetree in index object to avoid reference cycle...
Martin von Zweigbergk -
r39327:9f097214 default
parent child Browse files
Show More
@@ -42,7 +42,6 b' typedef struct {'
42 * Zero is empty
42 * Zero is empty
43 */
43 */
44 typedef struct {
44 typedef struct {
45 PyObject_HEAD
46 indexObject *index;
45 indexObject *index;
47 nodetreenode *nodes;
46 nodetreenode *nodes;
48 unsigned length; /* # nodes in use */
47 unsigned length; /* # nodes in use */
@@ -51,6 +50,11 b' typedef struct {'
51 int splits; /* # splits performed */
50 int splits; /* # splits performed */
52 } nodetree;
51 } nodetree;
53
52
53 typedef struct {
54 PyObject_HEAD
55 nodetree nt;
56 } nodetreeObject;
57
54 /*
58 /*
55 * This class has two behaviors.
59 * This class has two behaviors.
56 *
60 *
@@ -75,7 +79,8 b' struct indexObjectStruct {'
75 PyObject *added; /* populated on demand */
79 PyObject *added; /* populated on demand */
76 PyObject *headrevs; /* cache, invalidated on changes */
80 PyObject *headrevs; /* cache, invalidated on changes */
77 PyObject *filteredrevs;/* filtered revs set */
81 PyObject *filteredrevs;/* filtered revs set */
78 nodetree *nt; /* base-16 trie */
82 nodetree nt; /* base-16 trie */
83 int ntinitialized; /* 0 or 1 */
79 int ntrev; /* last rev scanned */
84 int ntrev; /* last rev scanned */
80 int ntlookups; /* # lookups */
85 int ntlookups; /* # lookups */
81 int ntmisses; /* # lookups that miss the cache */
86 int ntmisses; /* # lookups that miss the cache */
@@ -333,8 +338,8 b' static PyObject *index_append(indexObjec'
333 if (PyList_Append(self->added, obj) == -1)
338 if (PyList_Append(self->added, obj) == -1)
334 return NULL;
339 return NULL;
335
340
336 if (self->nt)
341 if (self->ntinitialized)
337 nt_insert(self->nt, node, (int)len);
342 nt_insert(&self->nt, node, (int)len);
338
343
339 Py_CLEAR(self->headrevs);
344 Py_CLEAR(self->headrevs);
340 Py_RETURN_NONE;
345 Py_RETURN_NONE;
@@ -374,11 +379,11 b' static PyObject *index_stats(indexObject'
374 istat(ntlookups, "node trie lookups");
379 istat(ntlookups, "node trie lookups");
375 istat(ntmisses, "node trie misses");
380 istat(ntmisses, "node trie misses");
376 istat(ntrev, "node trie last rev scanned");
381 istat(ntrev, "node trie last rev scanned");
377 if (self->nt) {
382 if (self->ntinitialized) {
378 istat(nt->capacity, "node trie capacity");
383 istat(nt.capacity, "node trie capacity");
379 istat(nt->depth, "node trie depth");
384 istat(nt.depth, "node trie depth");
380 istat(nt->length, "node trie count");
385 istat(nt.length, "node trie count");
381 istat(nt->splits, "node trie splits");
386 istat(nt.splits, "node trie splits");
382 }
387 }
383
388
384 #undef istat
389 #undef istat
@@ -1087,20 +1092,20 b' static int nt_insert(nodetree *self, con'
1087 return -1;
1092 return -1;
1088 }
1093 }
1089
1094
1090 static PyObject *nt_insert_py(nodetree *self, PyObject *args)
1095 static PyObject *ntobj_insert(nodetreeObject *self, PyObject *args)
1091 {
1096 {
1092 Py_ssize_t rev;
1097 Py_ssize_t rev;
1093 const char *node;
1098 const char *node;
1094 Py_ssize_t length;
1099 Py_ssize_t length;
1095 if (!PyArg_ParseTuple(args, "n", &rev))
1100 if (!PyArg_ParseTuple(args, "n", &rev))
1096 return NULL;
1101 return NULL;
1097 length = index_length(self->index);
1102 length = index_length(self->nt.index);
1098 if (rev < 0 || rev >= length) {
1103 if (rev < 0 || rev >= length) {
1099 PyErr_SetString(PyExc_ValueError, "revlog index out of range");
1104 PyErr_SetString(PyExc_ValueError, "revlog index out of range");
1100 return NULL;
1105 return NULL;
1101 }
1106 }
1102 node = index_node_existing(self->index, rev);
1107 node = index_node_existing(self->nt.index, rev);
1103 if (nt_insert(self, node, (int)rev) == -1)
1108 if (nt_insert(&self->nt, node, (int)rev) == -1)
1104 return NULL;
1109 return NULL;
1105 Py_RETURN_NONE;
1110 Py_RETURN_NONE;
1106 }
1111 }
@@ -1117,7 +1122,6 b' static int nt_init(nodetree *self, index'
1117 self->nodes = NULL;
1122 self->nodes = NULL;
1118
1123
1119 self->index = index;
1124 self->index = index;
1120 Py_INCREF(index);
1121 /* The input capacity is in terms of revisions, while the field is in
1125 /* The input capacity is in terms of revisions, while the field is in
1122 * terms of nodetree nodes. */
1126 * terms of nodetree nodes. */
1123 self->capacity = (capacity < 4 ? 4 : capacity / 2);
1127 self->capacity = (capacity < 4 ? 4 : capacity / 2);
@@ -1138,13 +1142,14 b' static int nt_init(nodetree *self, index'
1138
1142
1139 static PyTypeObject indexType;
1143 static PyTypeObject indexType;
1140
1144
1141 static int nt_init_py(nodetree *self, PyObject *args)
1145 static int ntobj_init(nodetreeObject *self, PyObject *args)
1142 {
1146 {
1143 PyObject *index;
1147 PyObject *index;
1144 unsigned capacity;
1148 unsigned capacity;
1145 if (!PyArg_ParseTuple(args, "O!I", &indexType, &index, &capacity))
1149 if (!PyArg_ParseTuple(args, "O!I", &indexType, &index, &capacity))
1146 return -1;
1150 return -1;
1147 return nt_init(self, (indexObject*)index, capacity);
1151 Py_INCREF(index);
1152 return nt_init(&self->nt, (indexObject*)index, capacity);
1148 }
1153 }
1149
1154
1150 static int nt_partialmatch(nodetree *self, const char *node,
1155 static int nt_partialmatch(nodetree *self, const char *node,
@@ -1199,7 +1204,7 b' static int nt_shortest(nodetree *self, c'
1199 return -3;
1204 return -3;
1200 }
1205 }
1201
1206
1202 static PyObject *nt_shortest_py(nodetree *self, PyObject *args)
1207 static PyObject *ntobj_shortest(nodetreeObject *self, PyObject *args)
1203 {
1208 {
1204 PyObject *val;
1209 PyObject *val;
1205 char *node;
1210 char *node;
@@ -1210,7 +1215,7 b' static PyObject *nt_shortest_py(nodetree'
1210 if (node_check(val, &node) == -1)
1215 if (node_check(val, &node) == -1)
1211 return NULL;
1216 return NULL;
1212
1217
1213 length = nt_shortest(self, node);
1218 length = nt_shortest(&self->nt, node);
1214 if (length == -3)
1219 if (length == -3)
1215 return NULL;
1220 return NULL;
1216 if (length == -2) {
1221 if (length == -2) {
@@ -1222,16 +1227,21 b' static PyObject *nt_shortest_py(nodetree'
1222
1227
1223 static void nt_dealloc(nodetree *self)
1228 static void nt_dealloc(nodetree *self)
1224 {
1229 {
1225 Py_XDECREF(self->index);
1226 free(self->nodes);
1230 free(self->nodes);
1227 self->nodes = NULL;
1231 self->nodes = NULL;
1232 }
1233
1234 static void ntobj_dealloc(nodetreeObject *self)
1235 {
1236 Py_XDECREF(self->nt.index);
1237 nt_dealloc(&self->nt);
1228 PyObject_Del(self);
1238 PyObject_Del(self);
1229 }
1239 }
1230
1240
1231 static PyMethodDef nt_methods[] = {
1241 static PyMethodDef ntobj_methods[] = {
1232 {"insert", (PyCFunction)nt_insert_py, METH_VARARGS,
1242 {"insert", (PyCFunction)ntobj_insert, METH_VARARGS,
1233 "insert an index entry"},
1243 "insert an index entry"},
1234 {"shortest", (PyCFunction)nt_shortest_py, METH_VARARGS,
1244 {"shortest", (PyCFunction)ntobj_shortest, METH_VARARGS,
1235 "find length of shortest hex nodeid of a binary ID"},
1245 "find length of shortest hex nodeid of a binary ID"},
1236 {NULL} /* Sentinel */
1246 {NULL} /* Sentinel */
1237 };
1247 };
@@ -1241,7 +1251,7 b' static PyTypeObject nodetreeType = {'
1241 "parsers.nodetree", /* tp_name */
1251 "parsers.nodetree", /* tp_name */
1242 sizeof(nodetree) , /* tp_basicsize */
1252 sizeof(nodetree) , /* tp_basicsize */
1243 0, /* tp_itemsize */
1253 0, /* tp_itemsize */
1244 (destructor)nt_dealloc, /* tp_dealloc */
1254 (destructor)ntobj_dealloc, /* tp_dealloc */
1245 0, /* tp_print */
1255 0, /* tp_print */
1246 0, /* tp_getattr */
1256 0, /* tp_getattr */
1247 0, /* tp_setattr */
1257 0, /* tp_setattr */
@@ -1264,7 +1274,7 b' static PyTypeObject nodetreeType = {'
1264 0, /* tp_weaklistoffset */
1274 0, /* tp_weaklistoffset */
1265 0, /* tp_iter */
1275 0, /* tp_iter */
1266 0, /* tp_iternext */
1276 0, /* tp_iternext */
1267 nt_methods, /* tp_methods */
1277 ntobj_methods, /* tp_methods */
1268 0, /* tp_members */
1278 0, /* tp_members */
1269 0, /* tp_getset */
1279 0, /* tp_getset */
1270 0, /* tp_base */
1280 0, /* tp_base */
@@ -1272,27 +1282,22 b' static PyTypeObject nodetreeType = {'
1272 0, /* tp_descr_get */
1282 0, /* tp_descr_get */
1273 0, /* tp_descr_set */
1283 0, /* tp_descr_set */
1274 0, /* tp_dictoffset */
1284 0, /* tp_dictoffset */
1275 (initproc)nt_init_py, /* tp_init */
1285 (initproc)ntobj_init, /* tp_init */
1276 0, /* tp_alloc */
1286 0, /* tp_alloc */
1277 };
1287 };
1278
1288
1279 static int index_init_nt(indexObject *self)
1289 static int index_init_nt(indexObject *self)
1280 {
1290 {
1281 if (self->nt == NULL) {
1291 if (!self->ntinitialized) {
1282 self->nt = PyObject_New(nodetree, &nodetreeType);
1292 if (nt_init(&self->nt, self, (int)self->raw_length) == -1) {
1283 if (self->nt == NULL) {
1293 nt_dealloc(&self->nt);
1284 return -1;
1294 return -1;
1285 }
1295 }
1286 if (nt_init(self->nt, self, (int)self->raw_length) == -1) {
1296 if (nt_insert(&self->nt, nullid, -1) == -1) {
1287 nt_dealloc(self->nt);
1297 nt_dealloc(&self->nt);
1288 self->nt = NULL;
1289 return -1;
1298 return -1;
1290 }
1299 }
1291 if (nt_insert(self->nt, nullid, -1) == -1) {
1300 self->ntinitialized = 1;
1292 nt_dealloc(self->nt);
1293 self->nt = NULL;
1294 return -1;
1295 }
1296 self->ntrev = (int)index_length(self);
1301 self->ntrev = (int)index_length(self);
1297 self->ntlookups = 1;
1302 self->ntlookups = 1;
1298 self->ntmisses = 0;
1303 self->ntmisses = 0;
@@ -1316,7 +1321,7 b' static int index_find_node(indexObject *'
1316 return -3;
1321 return -3;
1317
1322
1318 self->ntlookups++;
1323 self->ntlookups++;
1319 rev = nt_find(self->nt, node, nodelen, 0);
1324 rev = nt_find(&self->nt, node, nodelen, 0);
1320 if (rev >= -1)
1325 if (rev >= -1)
1321 return rev;
1326 return rev;
1322
1327
@@ -1335,7 +1340,7 b' static int index_find_node(indexObject *'
1335 if (n == NULL)
1340 if (n == NULL)
1336 return -3;
1341 return -3;
1337 if (memcmp(node, n, nodelen > 20 ? 20 : nodelen) == 0) {
1342 if (memcmp(node, n, nodelen > 20 ? 20 : nodelen) == 0) {
1338 if (nt_insert(self->nt, n, rev) == -1)
1343 if (nt_insert(&self->nt, n, rev) == -1)
1339 return -3;
1344 return -3;
1340 break;
1345 break;
1341 }
1346 }
@@ -1345,7 +1350,7 b' static int index_find_node(indexObject *'
1345 const char *n = index_node_existing(self, rev);
1350 const char *n = index_node_existing(self, rev);
1346 if (n == NULL)
1351 if (n == NULL)
1347 return -3;
1352 return -3;
1348 if (nt_insert(self->nt, n, rev) == -1) {
1353 if (nt_insert(&self->nt, n, rev) == -1) {
1349 self->ntrev = rev + 1;
1354 self->ntrev = rev + 1;
1350 return -3;
1355 return -3;
1351 }
1356 }
@@ -1389,7 +1394,7 b' static int index_populate_nt(indexObject'
1389 const char *n = index_node_existing(self, rev);
1394 const char *n = index_node_existing(self, rev);
1390 if (n == NULL)
1395 if (n == NULL)
1391 return -1;
1396 return -1;
1392 if (nt_insert(self->nt, n, rev) == -1)
1397 if (nt_insert(&self->nt, n, rev) == -1)
1393 return -1;
1398 return -1;
1394 }
1399 }
1395 self->ntrev = -1;
1400 self->ntrev = -1;
@@ -1429,7 +1434,7 b' static PyObject *index_partialmatch(inde'
1429 return NULL;
1434 return NULL;
1430 if (index_populate_nt(self) == -1)
1435 if (index_populate_nt(self) == -1)
1431 return NULL;
1436 return NULL;
1432 rev = nt_partialmatch(self->nt, node, nodelen);
1437 rev = nt_partialmatch(&self->nt, node, nodelen);
1433
1438
1434 switch (rev) {
1439 switch (rev) {
1435 case -4:
1440 case -4:
@@ -1464,7 +1469,7 b' static PyObject *index_shortest(indexObj'
1464 return NULL;
1469 return NULL;
1465 if (index_populate_nt(self) == -1)
1470 if (index_populate_nt(self) == -1)
1466 return NULL;
1471 return NULL;
1467 length = nt_shortest(self->nt, node);
1472 length = nt_shortest(&self->nt, node);
1468 if (length == -3)
1473 if (length == -3)
1469 return NULL;
1474 return NULL;
1470 if (length == -2) {
1475 if (length == -2) {
@@ -1886,7 +1891,7 b' static void index_invalidate_added(index'
1886 PyObject *tuple = PyList_GET_ITEM(self->added, i);
1891 PyObject *tuple = PyList_GET_ITEM(self->added, i);
1887 PyObject *node = PyTuple_GET_ITEM(tuple, 7);
1892 PyObject *node = PyTuple_GET_ITEM(tuple, 7);
1888
1893
1889 nt_delete_node(self->nt, PyBytes_AS_STRING(node));
1894 nt_delete_node(&self->nt, PyBytes_AS_STRING(node));
1890 }
1895 }
1891
1896
1892 if (start == 0)
1897 if (start == 0)
@@ -1937,7 +1942,7 b' static int index_slice_del(indexObject *'
1937 }
1942 }
1938
1943
1939 if (start < self->length) {
1944 if (start < self->length) {
1940 if (self->nt) {
1945 if (self->ntinitialized) {
1941 Py_ssize_t i;
1946 Py_ssize_t i;
1942
1947
1943 for (i = start + 1; i < self->length; i++) {
1948 for (i = start + 1; i < self->length; i++) {
@@ -1945,7 +1950,7 b' static int index_slice_del(indexObject *'
1945 if (node == NULL)
1950 if (node == NULL)
1946 return -1;
1951 return -1;
1947
1952
1948 nt_delete_node(self->nt, node);
1953 nt_delete_node(&self->nt, node);
1949 }
1954 }
1950 if (self->added)
1955 if (self->added)
1951 index_invalidate_added(self, 0);
1956 index_invalidate_added(self, 0);
@@ -1964,7 +1969,7 b' static int index_slice_del(indexObject *'
1964 goto done;
1969 goto done;
1965 }
1970 }
1966
1971
1967 if (self->nt) {
1972 if (self->ntinitialized) {
1968 index_invalidate_added(self, start - self->length);
1973 index_invalidate_added(self, start - self->length);
1969 if (self->ntrev > start)
1974 if (self->ntrev > start)
1970 self->ntrev = (int)start;
1975 self->ntrev = (int)start;
@@ -1997,7 +2002,7 b' static int index_assign_subscript(indexO'
1997 return -1;
2002 return -1;
1998
2003
1999 if (value == NULL)
2004 if (value == NULL)
2000 return self->nt ? nt_delete_node(self->nt, node) : 0;
2005 return self->ntinitialized ? nt_delete_node(&self->nt, node) : 0;
2001 rev = PyInt_AsLong(value);
2006 rev = PyInt_AsLong(value);
2002 if (rev > INT_MAX || rev < 0) {
2007 if (rev > INT_MAX || rev < 0) {
2003 if (!PyErr_Occurred())
2008 if (!PyErr_Occurred())
@@ -2007,7 +2012,7 b' static int index_assign_subscript(indexO'
2007
2012
2008 if (index_init_nt(self) == -1)
2013 if (index_init_nt(self) == -1)
2009 return -1;
2014 return -1;
2010 return nt_insert(self->nt, node, (int)rev);
2015 return nt_insert(&self->nt, node, (int)rev);
2011 }
2016 }
2012
2017
2013 /*
2018 /*
@@ -2056,7 +2061,7 b' static int index_init(indexObject *self,'
2056 self->headrevs = NULL;
2061 self->headrevs = NULL;
2057 self->filteredrevs = Py_None;
2062 self->filteredrevs = Py_None;
2058 Py_INCREF(Py_None);
2063 Py_INCREF(Py_None);
2059 self->nt = NULL;
2064 self->ntinitialized = 0;
2060 self->offsets = NULL;
2065 self->offsets = NULL;
2061
2066
2062 if (!PyArg_ParseTuple(args, "OO", &data_obj, &inlined_obj))
2067 if (!PyArg_ParseTuple(args, "OO", &data_obj, &inlined_obj))
@@ -2118,10 +2123,10 b' static void _index_clearcaches(indexObje'
2118 PyMem_Free((void *)self->offsets);
2123 PyMem_Free((void *)self->offsets);
2119 self->offsets = NULL;
2124 self->offsets = NULL;
2120 }
2125 }
2121 if (self->nt != NULL) {
2126 if (self->ntinitialized) {
2122 nt_dealloc(self->nt);
2127 nt_dealloc(&self->nt);
2123 }
2128 }
2124 self->nt = NULL;
2129 self->ntinitialized = 0;
2125 Py_CLEAR(self->headrevs);
2130 Py_CLEAR(self->headrevs);
2126 }
2131 }
2127
2132
@@ -2143,7 +2148,6 b' static void index_dealloc(indexObject *s'
2143 }
2148 }
2144 Py_XDECREF(self->data);
2149 Py_XDECREF(self->data);
2145 Py_XDECREF(self->added);
2150 Py_XDECREF(self->added);
2146 Py_XDECREF(self->nt);
2147 PyObject_Del(self);
2151 PyObject_Del(self);
2148 }
2152 }
2149
2153
General Comments 0
You need to be logged in to leave comments. Login now