##// END OF EJS Templates
revlog: only build the nodemap on demand
Matt Mackall -
r13254:5ef5eb1f default
parent child Browse files
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 (const char *data, int size, int inlined,
258 static int _parse_index_ng(const char *data, int size, int inlined,
294 PyObject *index, PyObject *nodemap)
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 comp_len, uncomp_len, base_rev,
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/nullrev entry in the nodemap and the
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, nodemap, cache)
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, *nodemap = NULL, *cache = 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 and the nodemap with data */
373 /* actually populate the index with data */
410 if (!_parse_index_ng (data, size, inlined, index, nodemap))
374 if (!_parse_index_ng(data, size, inlined, index))
411 goto quit;
375 goto quit;
412
376
413 rval = Py_BuildValue("NNN", index, nodemap, cache);
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, nodemap, cache = parsers.parse_index(data, inline)
175 index, cache = parsers.parse_index2(data, inline)
176 return index, nodemap, cache
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, self.nodemap, self._chunkcache = d
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, nodemap, cache
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