Show More
@@ -81,8 +81,9 b' def perfmanifest(ui, repo):' | |||||
81 |
|
81 | |||
82 | def perfindex(ui, repo): |
|
82 | def perfindex(ui, repo): | |
83 | import mercurial.changelog |
|
83 | import mercurial.changelog | |
|
84 | n = repo["tip"].node() | |||
84 | def d(): |
|
85 | def d(): | |
85 | t = repo.changelog.tip() |
|
86 | repo[n] | |
86 | repo.invalidate() |
|
87 | repo.invalidate() | |
87 | timer(d) |
|
88 | timer(d) | |
88 |
|
89 |
@@ -244,41 +244,6 b' quit:' | |||||
244 | const char nullid[20]; |
|
244 | const char nullid[20]; | |
245 | const int nullrev = -1; |
|
245 | const int nullrev = -1; | |
246 |
|
246 | |||
247 | /* create an index tuple, insert into the nodemap */ |
|
|||
248 | static PyObject * _build_idx_entry(PyObject *nodemap, int n, uint64_t offset_flags, |
|
|||
249 | int comp_len, int uncomp_len, int base_rev, |
|
|||
250 | int link_rev, int parent_1, int parent_2, |
|
|||
251 | const char *c_node_id) |
|
|||
252 | { |
|
|||
253 | int err; |
|
|||
254 | PyObject *entry, *node_id, *n_obj; |
|
|||
255 |
|
||||
256 | node_id = PyBytes_FromStringAndSize(c_node_id, 20); |
|
|||
257 | n_obj = PyInt_FromLong(n); |
|
|||
258 |
|
||||
259 | if (!node_id || !n_obj) |
|
|||
260 | err = -1; |
|
|||
261 | else |
|
|||
262 | err = PyDict_SetItem(nodemap, node_id, n_obj); |
|
|||
263 |
|
||||
264 | Py_XDECREF(n_obj); |
|
|||
265 | if (err) |
|
|||
266 | goto error_dealloc; |
|
|||
267 |
|
||||
268 | entry = Py_BuildValue("LiiiiiiN", offset_flags, comp_len, |
|
|||
269 | uncomp_len, base_rev, link_rev, |
|
|||
270 | parent_1, parent_2, node_id); |
|
|||
271 | if (!entry) |
|
|||
272 | goto error_dealloc; |
|
|||
273 | PyObject_GC_UnTrack(entry); /* don't waste time with this */ |
|
|||
274 |
|
||||
275 | return entry; |
|
|||
276 |
|
||||
277 | error_dealloc: |
|
|||
278 | Py_XDECREF(node_id); |
|
|||
279 | return NULL; |
|
|||
280 | } |
|
|||
281 |
|
||||
282 | /* RevlogNG format (all in big endian, data may be inlined): |
|
247 | /* RevlogNG format (all in big endian, data may be inlined): | |
283 | * 6 bytes: offset |
|
248 | * 6 bytes: offset | |
284 | * 2 bytes: flags |
|
249 | * 2 bytes: flags | |
@@ -290,8 +255,8 b' error_dealloc:' | |||||
290 | * 4 bytes: parent 2 revision |
|
255 | * 4 bytes: parent 2 revision | |
291 | * 32 bytes: nodeid (only 20 bytes used) |
|
256 | * 32 bytes: nodeid (only 20 bytes used) | |
292 | */ |
|
257 | */ | |
293 |
static int _parse_index_ng |
|
258 | static int _parse_index_ng(const char *data, int size, int inlined, | |
294 |
|
|
259 | PyObject *index) | |
295 | { |
|
260 | { | |
296 | PyObject *entry; |
|
261 | PyObject *entry; | |
297 | int n = 0, err; |
|
262 | int n = 0, err; | |
@@ -321,13 +286,15 b' static int _parse_index_ng (const char *' | |||||
321 | parent_2 = ntohl(*((uint32_t *)(decode + 28))); |
|
286 | parent_2 = ntohl(*((uint32_t *)(decode + 28))); | |
322 | c_node_id = decode + 32; |
|
287 | c_node_id = decode + 32; | |
323 |
|
288 | |||
324 | entry = _build_idx_entry(nodemap, n, offset_flags, |
|
289 | entry = Py_BuildValue("Liiiiiis#", offset_flags, comp_len, | |
325 |
|
|
290 | uncomp_len, base_rev, link_rev, | |
326 | link_rev, parent_1, parent_2, |
|
291 | parent_1, parent_2, c_node_id, 20); | |
327 | c_node_id); |
|
292 | ||
328 | if (!entry) |
|
293 | if (!entry) | |
329 | return 0; |
|
294 | return 0; | |
330 |
|
295 | |||
|
296 | PyObject_GC_UnTrack(entry); /* don't waste time with this */ | |||
|
297 | ||||
331 | if (inlined) { |
|
298 | if (inlined) { | |
332 | err = PyList_Append(index, entry); |
|
299 | err = PyList_Append(index, entry); | |
333 | Py_DECREF(entry); |
|
300 | Py_DECREF(entry); | |
@@ -348,12 +315,14 b' static int _parse_index_ng (const char *' | |||||
348 | return 0; |
|
315 | return 0; | |
349 | } |
|
316 | } | |
350 |
|
317 | |||
351 |
/* create the nullid |
|
318 | /* create the magic nullid entry in the index at [-1] */ | |
352 | * magic nullid entry in the index at [-1] */ |
|
319 | entry = Py_BuildValue("Liiiiiis#", (uint64_t)0, 0, 0, -1, -1, -1, -1, nullid, 20); | |
353 | entry = _build_idx_entry(nodemap, |
|
320 | ||
354 | nullrev, 0, 0, 0, -1, -1, -1, -1, nullid); |
|
|||
355 | if (!entry) |
|
321 | if (!entry) | |
356 | return 0; |
|
322 | return 0; | |
|
323 | ||||
|
324 | PyObject_GC_UnTrack(entry); /* don't waste time with this */ | |||
|
325 | ||||
357 | if (inlined) { |
|
326 | if (inlined) { | |
358 | err = PyList_Append(index, entry); |
|
327 | err = PyList_Append(index, entry); | |
359 | Py_DECREF(entry); |
|
328 | Py_DECREF(entry); | |
@@ -366,17 +335,16 b' static int _parse_index_ng (const char *' | |||||
366 | } |
|
335 | } | |
367 |
|
336 | |||
368 | /* This function parses a index file and returns a Python tuple of the |
|
337 | /* This function parses a index file and returns a Python tuple of the | |
369 |
* following format: (index, |
|
338 | * following format: (index, cache) | |
370 | * |
|
339 | * | |
371 | * index: a list of tuples containing the RevlogNG records |
|
340 | * index: a list of tuples containing the RevlogNG records | |
372 | * nodemap: a dict mapping node ids to indices in the index list |
|
|||
373 | * cache: if data is inlined, a tuple (index_file_content, 0) else None |
|
341 | * cache: if data is inlined, a tuple (index_file_content, 0) else None | |
374 | */ |
|
342 | */ | |
375 | static PyObject *parse_index(PyObject *self, PyObject *args) |
|
343 | static PyObject *parse_index2(PyObject *self, PyObject *args) | |
376 | { |
|
344 | { | |
377 | const char *data; |
|
345 | const char *data; | |
378 | int size, inlined; |
|
346 | int size, inlined; | |
379 |
PyObject *rval = NULL, *index = NULL, * |
|
347 | PyObject *rval = NULL, *index = NULL, *cache = NULL; | |
380 | PyObject *data_obj = NULL, *inlined_obj; |
|
348 | PyObject *data_obj = NULL, *inlined_obj; | |
381 |
|
349 | |||
382 | if (!PyArg_ParseTuple(args, "s#O", &data, &size, &inlined_obj)) |
|
350 | if (!PyArg_ParseTuple(args, "s#O", &data, &size, &inlined_obj)) | |
@@ -390,10 +358,6 b' static PyObject *parse_index(PyObject *s' | |||||
390 | if (!index) |
|
358 | if (!index) | |
391 | goto quit; |
|
359 | goto quit; | |
392 |
|
360 | |||
393 | nodemap = PyDict_New(); |
|
|||
394 | if (!nodemap) |
|
|||
395 | goto quit; |
|
|||
396 |
|
||||
397 | /* set up the cache return value */ |
|
361 | /* set up the cache return value */ | |
398 | if (inlined) { |
|
362 | if (inlined) { | |
399 | /* Note that the reference to data_obj is only borrowed */ |
|
363 | /* Note that the reference to data_obj is only borrowed */ | |
@@ -406,18 +370,17 b' static PyObject *parse_index(PyObject *s' | |||||
406 | Py_INCREF(Py_None); |
|
370 | Py_INCREF(Py_None); | |
407 | } |
|
371 | } | |
408 |
|
372 | |||
409 |
/* actually populate the index |
|
373 | /* actually populate the index with data */ | |
410 |
if (!_parse_index_ng |
|
374 | if (!_parse_index_ng(data, size, inlined, index)) | |
411 | goto quit; |
|
375 | goto quit; | |
412 |
|
376 | |||
413 |
rval = Py_BuildValue("NN |
|
377 | rval = Py_BuildValue("NN", index, cache); | |
414 | if (!rval) |
|
378 | if (!rval) | |
415 | goto quit; |
|
379 | goto quit; | |
416 | return rval; |
|
380 | return rval; | |
417 |
|
381 | |||
418 | quit: |
|
382 | quit: | |
419 | Py_XDECREF(index); |
|
383 | Py_XDECREF(index); | |
420 | Py_XDECREF(nodemap); |
|
|||
421 | Py_XDECREF(cache); |
|
384 | Py_XDECREF(cache); | |
422 | Py_XDECREF(rval); |
|
385 | Py_XDECREF(rval); | |
423 | return NULL; |
|
386 | return NULL; | |
@@ -429,7 +392,7 b' static char parsers_doc[] = "Efficient c' | |||||
429 | static PyMethodDef methods[] = { |
|
392 | static PyMethodDef methods[] = { | |
430 | {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"}, |
|
393 | {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"}, | |
431 | {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"}, |
|
394 | {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"}, | |
432 | {"parse_index", parse_index, METH_VARARGS, "parse a revlog index\n"}, |
|
395 | {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"}, | |
433 | {NULL, NULL} |
|
396 | {NULL, NULL} | |
434 | }; |
|
397 | }; | |
435 |
|
398 |
@@ -172,8 +172,8 b' class revlogio(object):' | |||||
172 |
|
172 | |||
173 | def parseindex(self, fp, data, inline): |
|
173 | def parseindex(self, fp, data, inline): | |
174 | # call the C implementation to parse the index data |
|
174 | # call the C implementation to parse the index data | |
175 |
index |
|
175 | index, cache = parsers.parse_index2(data, inline) | |
176 |
return index, |
|
176 | return index, None, cache | |
177 |
|
177 | |||
178 | def packentry(self, entry, node, version, rev): |
|
178 | def packentry(self, entry, node, version, rev): | |
179 | p = _pack(indexformatng, *entry) |
|
179 | p = _pack(indexformatng, *entry) | |
@@ -218,7 +218,6 b' class revlog(object):' | |||||
218 | self.opener = opener |
|
218 | self.opener = opener | |
219 | self._cache = None |
|
219 | self._cache = None | |
220 | self._chunkcache = (0, '') |
|
220 | self._chunkcache = (0, '') | |
221 | self.nodemap = {nullid: nullrev} |
|
|||
222 | self.index = [] |
|
221 | self.index = [] | |
223 | self._shallowroot = shallowroot |
|
222 | self._shallowroot = shallowroot | |
224 | self._parentdelta = 0 |
|
223 | self._parentdelta = 0 | |
@@ -267,7 +266,9 b' class revlog(object):' | |||||
267 | d = self._io.parseindex(f, i, self._inline) |
|
266 | d = self._io.parseindex(f, i, self._inline) | |
268 | except (ValueError, IndexError): |
|
267 | except (ValueError, IndexError): | |
269 | raise RevlogError(_("index %s is corrupted") % (self.indexfile)) |
|
268 | raise RevlogError(_("index %s is corrupted") % (self.indexfile)) | |
270 |
self.index, |
|
269 | self.index, n, self._chunkcache = d | |
|
270 | if n: | |||
|
271 | self.nodemap = n | |||
271 | if not self._chunkcache: |
|
272 | if not self._chunkcache: | |
272 | self._chunkclear() |
|
273 | self._chunkclear() | |
273 |
|
274 | |||
@@ -275,6 +276,14 b' class revlog(object):' | |||||
275 | if self.index == [] or self.index[-1][7] != nullid: |
|
276 | if self.index == [] or self.index[-1][7] != nullid: | |
276 | self.index.append((0, 0, 0, -1, -1, -1, -1, nullid)) |
|
277 | self.index.append((0, 0, 0, -1, -1, -1, -1, nullid)) | |
277 |
|
278 | |||
|
279 | @util.propertycache | |||
|
280 | def nodemap(self): | |||
|
281 | n = {nullid: nullrev} | |||
|
282 | i = self.index | |||
|
283 | for r in xrange(len(i) - 1): | |||
|
284 | n[i[r][7]] = r | |||
|
285 | return n | |||
|
286 | ||||
278 | def tip(self): |
|
287 | def tip(self): | |
279 | return self.node(len(self.index) - 2) |
|
288 | return self.node(len(self.index) - 2) | |
280 | def __len__(self): |
|
289 | def __len__(self): |
@@ -50,7 +50,7 b' def py_parseindex(data, inline) :' | |||||
50 | # add the magic null revision at -1 |
|
50 | # add the magic null revision at -1 | |
51 | index.append((0, 0, 0, -1, -1, -1, -1, nullid)) |
|
51 | index.append((0, 0, 0, -1, -1, -1, -1, nullid)) | |
52 |
|
52 | |||
53 |
return index, |
|
53 | return index, cache | |
54 |
|
54 | |||
55 |
|
55 | |||
56 | data_inlined = '\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x01\x8c' \ |
|
56 | data_inlined = '\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x01\x8c' \ | |
@@ -97,10 +97,10 b" data_non_inlined = '\\x00\\x00\\x00\\x01\\x00" | |||||
97 | def runtest() : |
|
97 | def runtest() : | |
98 |
|
98 | |||
99 | py_res_1 = py_parseindex(data_inlined, True) |
|
99 | py_res_1 = py_parseindex(data_inlined, True) | |
100 | c_res_1 = parsers.parse_index(data_inlined, True) |
|
100 | c_res_1 = parsers.parse_index2(data_inlined, True) | |
101 |
|
101 | |||
102 | py_res_2 = py_parseindex(data_non_inlined, False) |
|
102 | py_res_2 = py_parseindex(data_non_inlined, False) | |
103 | c_res_2 = parsers.parse_index(data_non_inlined, False) |
|
103 | c_res_2 = parsers.parse_index2(data_non_inlined, False) | |
104 |
|
104 | |||
105 | if py_res_1 != c_res_1: |
|
105 | if py_res_1 != c_res_1: | |
106 | print "Parse index result (with inlined data) differs!" |
|
106 | print "Parse index result (with inlined data) differs!" |
General Comments 0
You need to be logged in to leave comments.
Login now