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