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 |
|
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 |
|
383 | istat(nt.capacity, "node trie capacity"); | |
379 |
istat(nt |
|
384 | istat(nt.depth, "node trie depth"); | |
380 |
istat(nt |
|
385 | istat(nt.length, "node trie count"); | |
381 |
istat(nt |
|
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 |
|
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 |
|
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 |
|
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 |
|
1242 | {"insert", (PyCFunction)ntobj_insert, METH_VARARGS, | |
1233 | "insert an index entry"}, |
|
1243 | "insert an index entry"}, | |
1234 |
{"shortest", (PyCFunction)nt_shortest |
|
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, |
|
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, |
|
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 |
|
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 |
|
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_in |
|
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 = |
|
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 |
|
2126 | if (self->ntinitialized) { | |
2122 | nt_dealloc(self->nt); |
|
2127 | nt_dealloc(&self->nt); | |
2123 | } |
|
2128 | } | |
2124 |
self->nt = |
|
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