97 int ntinitialized; /* 0 or 1 */ |
97 int ntinitialized; /* 0 or 1 */ |
98 int ntrev; /* last rev scanned */ |
98 int ntrev; /* last rev scanned */ |
99 int ntlookups; /* # lookups */ |
99 int ntlookups; /* # lookups */ |
100 int ntmisses; /* # lookups that miss the cache */ |
100 int ntmisses; /* # lookups that miss the cache */ |
101 int inlined; |
101 int inlined; |
102 long hdrsize; /* size of index headers. Differs in v1 v.s. v2 format */ |
102 long entry_size; /* size of index headers. Differs in v1 v.s. v2 format |
|
103 */ |
103 }; |
104 }; |
104 |
105 |
105 static Py_ssize_t index_length(const indexObject *self) |
106 static Py_ssize_t index_length(const indexObject *self) |
106 { |
107 { |
107 return self->length + self->new_length; |
108 return self->length + self->new_length; |
121 static const char *const v1_tuple_format = PY23("kiiiiiis#", "kiiiiiiy#"); |
122 static const char *const v1_tuple_format = PY23("kiiiiiis#", "kiiiiiiy#"); |
122 static const char *const v2_tuple_format = PY23("kiiiiiis#ki", "kiiiiiiy#ki"); |
123 static const char *const v2_tuple_format = PY23("kiiiiiis#ki", "kiiiiiiy#ki"); |
123 #endif |
124 #endif |
124 |
125 |
125 /* A RevlogNG v1 index entry is 64 bytes long. */ |
126 /* A RevlogNG v1 index entry is 64 bytes long. */ |
126 static const long v1_hdrsize = 64; |
127 static const long v1_entry_size = 64; |
127 |
128 |
128 /* A Revlogv2 index entry is 96 bytes long. */ |
129 /* A Revlogv2 index entry is 96 bytes long. */ |
129 static const long v2_hdrsize = 96; |
130 static const long v2_entry_size = 96; |
130 |
131 |
131 static void raise_revlog_error(void) |
132 static void raise_revlog_error(void) |
132 { |
133 { |
133 PyObject *mod = NULL, *dict = NULL, *errclass = NULL; |
134 PyObject *mod = NULL, *dict = NULL, *errclass = NULL; |
134 |
135 |
162 * Return a pointer to the beginning of a RevlogNG record. |
163 * Return a pointer to the beginning of a RevlogNG record. |
163 */ |
164 */ |
164 static const char *index_deref(indexObject *self, Py_ssize_t pos) |
165 static const char *index_deref(indexObject *self, Py_ssize_t pos) |
165 { |
166 { |
166 if (pos >= self->length) |
167 if (pos >= self->length) |
167 return self->added + (pos - self->length) * self->hdrsize; |
168 return self->added + (pos - self->length) * self->entry_size; |
168 |
169 |
169 if (self->inlined && pos > 0) { |
170 if (self->inlined && pos > 0) { |
170 if (self->offsets == NULL) { |
171 if (self->offsets == NULL) { |
171 Py_ssize_t ret; |
172 Py_ssize_t ret; |
172 self->offsets = |
173 self->offsets = |
326 link_rev = getbe32(data + 20); |
327 link_rev = getbe32(data + 20); |
327 parent_1 = getbe32(data + 24); |
328 parent_1 = getbe32(data + 24); |
328 parent_2 = getbe32(data + 28); |
329 parent_2 = getbe32(data + 28); |
329 c_node_id = data + 32; |
330 c_node_id = data + 32; |
330 |
331 |
331 if (self->hdrsize == v1_hdrsize) { |
332 if (self->entry_size == v1_entry_size) { |
332 return Py_BuildValue(v1_tuple_format, offset_flags, comp_len, |
333 return Py_BuildValue(v1_tuple_format, offset_flags, comp_len, |
333 uncomp_len, base_rev, link_rev, parent_1, |
334 uncomp_len, base_rev, link_rev, parent_1, |
334 parent_2, c_node_id, self->nodelen); |
335 parent_2, c_node_id, self->nodelen); |
335 } else { |
336 } else { |
336 sidedata_offset = getbe64(data + 64); |
337 sidedata_offset = getbe64(data + 64); |
376 data = index_deref(self, rev); |
377 data = index_deref(self, rev); |
377 if (data == NULL) |
378 if (data == NULL) |
378 return NULL; |
379 return NULL; |
379 if (rev == 0) { |
380 if (rev == 0) { |
380 /* the header is eating the start of the first entry */ |
381 /* the header is eating the start of the first entry */ |
381 return PyBytes_FromStringAndSize(data + 4, self->hdrsize - 4); |
382 return PyBytes_FromStringAndSize(data + 4, |
382 } |
383 self->entry_size - 4); |
383 return PyBytes_FromStringAndSize(data, self->hdrsize); |
384 } |
|
385 return PyBytes_FromStringAndSize(data, self->entry_size); |
384 } |
386 } |
385 |
387 |
386 /* |
388 /* |
387 * Return the hash of node corresponding to the given rev. |
389 * Return the hash of node corresponding to the given rev. |
388 */ |
390 */ |
435 int rev, comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2; |
437 int rev, comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2; |
436 Py_ssize_t c_node_id_len, sidedata_comp_len; |
438 Py_ssize_t c_node_id_len, sidedata_comp_len; |
437 const char *c_node_id; |
439 const char *c_node_id; |
438 char *data; |
440 char *data; |
439 |
441 |
440 if (self->hdrsize == v1_hdrsize) { |
442 if (self->entry_size == v1_entry_size) { |
441 if (!PyArg_ParseTuple(obj, v1_tuple_format, &offset_flags, |
443 if (!PyArg_ParseTuple(obj, v1_tuple_format, &offset_flags, |
442 &comp_len, &uncomp_len, &base_rev, |
444 &comp_len, &uncomp_len, &base_rev, |
443 &link_rev, &parent_1, &parent_2, |
445 &link_rev, &parent_1, &parent_2, |
444 &c_node_id, &c_node_id_len)) { |
446 &c_node_id, &c_node_id_len)) { |
445 PyErr_SetString(PyExc_TypeError, "8-tuple required"); |
447 PyErr_SetString(PyExc_TypeError, "8-tuple required"); |
462 } |
464 } |
463 |
465 |
464 if (self->new_length == self->added_length) { |
466 if (self->new_length == self->added_length) { |
465 size_t new_added_length = |
467 size_t new_added_length = |
466 self->added_length ? self->added_length * 2 : 4096; |
468 self->added_length ? self->added_length * 2 : 4096; |
467 void *new_added = PyMem_Realloc(self->added, new_added_length * |
469 void *new_added = PyMem_Realloc( |
468 self->hdrsize); |
470 self->added, new_added_length * self->entry_size); |
469 if (!new_added) |
471 if (!new_added) |
470 return PyErr_NoMemory(); |
472 return PyErr_NoMemory(); |
471 self->added = new_added; |
473 self->added = new_added; |
472 self->added_length = new_added_length; |
474 self->added_length = new_added_length; |
473 } |
475 } |
474 rev = self->length + self->new_length; |
476 rev = self->length + self->new_length; |
475 data = self->added + self->hdrsize * self->new_length++; |
477 data = self->added + self->entry_size * self->new_length++; |
476 putbe32(offset_flags >> 32, data); |
478 putbe32(offset_flags >> 32, data); |
477 putbe32(offset_flags & 0xffffffffU, data + 4); |
479 putbe32(offset_flags & 0xffffffffU, data + 4); |
478 putbe32(comp_len, data + 8); |
480 putbe32(comp_len, data + 8); |
479 putbe32(uncomp_len, data + 12); |
481 putbe32(uncomp_len, data + 12); |
480 putbe32(base_rev, data + 16); |
482 putbe32(base_rev, data + 16); |
482 putbe32(parent_1, data + 24); |
484 putbe32(parent_1, data + 24); |
483 putbe32(parent_2, data + 28); |
485 putbe32(parent_2, data + 28); |
484 memcpy(data + 32, c_node_id, c_node_id_len); |
486 memcpy(data + 32, c_node_id, c_node_id_len); |
485 /* Padding since SHA-1 is only 20 bytes for now */ |
487 /* Padding since SHA-1 is only 20 bytes for now */ |
486 memset(data + 32 + c_node_id_len, 0, 32 - c_node_id_len); |
488 memset(data + 32 + c_node_id_len, 0, 32 - c_node_id_len); |
487 if (self->hdrsize != v1_hdrsize) { |
489 if (self->entry_size != v1_entry_size) { |
488 putbe64(sidedata_offset, data + 64); |
490 putbe64(sidedata_offset, data + 64); |
489 putbe32(sidedata_comp_len, data + 72); |
491 putbe32(sidedata_comp_len, data + 72); |
490 /* Padding for 96 bytes alignment */ |
492 /* Padding for 96 bytes alignment */ |
491 memset(data + 76, 0, self->hdrsize - 76); |
493 memset(data + 76, 0, self->entry_size - 76); |
492 } |
494 } |
493 |
495 |
494 if (self->ntinitialized) |
496 if (self->ntinitialized) |
495 nt_insert(&self->nt, c_node_id, rev); |
497 nt_insert(&self->nt, c_node_id, rev); |
496 |
498 |
511 const char *const sidedata_format = PY23("nKiK", "nKiK"); |
513 const char *const sidedata_format = PY23("nKiK", "nKiK"); |
512 #else |
514 #else |
513 const char *const sidedata_format = PY23("nkik", "nkik"); |
515 const char *const sidedata_format = PY23("nkik", "nkik"); |
514 #endif |
516 #endif |
515 |
517 |
516 if (self->hdrsize == v1_hdrsize || self->inlined) { |
518 if (self->entry_size == v1_entry_size || self->inlined) { |
517 /* |
519 /* |
518 There is a bug in the transaction handling when going from an |
520 There is a bug in the transaction handling when going from an |
519 inline revlog to a separate index and data file. Turn it off until |
521 inline revlog to a separate index and data file. Turn it off until |
520 it's fixed, since v2 revlogs sometimes get rewritten on exchange. |
522 it's fixed, since v2 revlogs sometimes get rewritten on exchange. |
521 See issue6485. |
523 See issue6485. |
539 return NULL; |
541 return NULL; |
540 } |
542 } |
541 |
543 |
542 /* Find the newly added node, offset from the "already on-disk" length |
544 /* Find the newly added node, offset from the "already on-disk" length |
543 */ |
545 */ |
544 data = self->added + self->hdrsize * (rev - self->length); |
546 data = self->added + self->entry_size * (rev - self->length); |
545 putbe64(offset_flags, data); |
547 putbe64(offset_flags, data); |
546 putbe64(sidedata_offset, data + 64); |
548 putbe64(sidedata_offset, data + 64); |
547 putbe32(sidedata_comp_len, data + 72); |
549 putbe32(sidedata_comp_len, data + 72); |
548 |
550 |
549 Py_RETURN_NONE; |
551 Py_RETURN_NONE; |
2690 static Py_ssize_t inline_scan(indexObject *self, const char **offsets) |
2692 static Py_ssize_t inline_scan(indexObject *self, const char **offsets) |
2691 { |
2693 { |
2692 const char *data = (const char *)self->buf.buf; |
2694 const char *data = (const char *)self->buf.buf; |
2693 Py_ssize_t pos = 0; |
2695 Py_ssize_t pos = 0; |
2694 Py_ssize_t end = self->buf.len; |
2696 Py_ssize_t end = self->buf.len; |
2695 long incr = self->hdrsize; |
2697 long incr = self->entry_size; |
2696 Py_ssize_t len = 0; |
2698 Py_ssize_t len = 0; |
2697 |
2699 |
2698 while (pos + self->hdrsize <= end && pos >= 0) { |
2700 while (pos + self->entry_size <= end && pos >= 0) { |
2699 uint32_t comp_len, sidedata_comp_len = 0; |
2701 uint32_t comp_len, sidedata_comp_len = 0; |
2700 /* 3rd element of header is length of compressed inline data */ |
2702 /* 3rd element of header is length of compressed inline data */ |
2701 comp_len = getbe32(data + pos + 8); |
2703 comp_len = getbe32(data + pos + 8); |
2702 if (self->hdrsize == v2_hdrsize) { |
2704 if (self->entry_size == v2_entry_size) { |
2703 sidedata_comp_len = getbe32(data + pos + 72); |
2705 sidedata_comp_len = getbe32(data + pos + 72); |
2704 } |
2706 } |
2705 incr = self->hdrsize + comp_len + sidedata_comp_len; |
2707 incr = self->entry_size + comp_len + sidedata_comp_len; |
2706 if (offsets) |
2708 if (offsets) |
2707 offsets[len] = data + pos; |
2709 offsets[len] = data + pos; |
2708 len++; |
2710 len++; |
2709 pos += incr; |
2711 pos += incr; |
2710 } |
2712 } |
2753 PyErr_SetString(PyExc_RuntimeError, "unsupported node size"); |
2755 PyErr_SetString(PyExc_RuntimeError, "unsupported node size"); |
2754 return -1; |
2756 return -1; |
2755 } |
2757 } |
2756 |
2758 |
2757 if (revlogv2 && PyObject_IsTrue(revlogv2)) { |
2759 if (revlogv2 && PyObject_IsTrue(revlogv2)) { |
2758 self->hdrsize = v2_hdrsize; |
2760 self->entry_size = v2_entry_size; |
2759 } else { |
2761 } else { |
2760 self->hdrsize = v1_hdrsize; |
2762 self->entry_size = v1_entry_size; |
2761 } |
2763 } |
2762 |
2764 |
2763 if (self->hdrsize == v1_hdrsize) { |
2765 if (self->entry_size == v1_entry_size) { |
2764 self->nullentry = |
2766 self->nullentry = |
2765 Py_BuildValue(PY23("iiiiiiis#", "iiiiiiiy#"), 0, 0, 0, -1, |
2767 Py_BuildValue(PY23("iiiiiiis#", "iiiiiiiy#"), 0, 0, 0, -1, |
2766 -1, -1, -1, nullid, self->nodelen); |
2768 -1, -1, -1, nullid, self->nodelen); |
2767 } else { |
2769 } else { |
2768 self->nullentry = |
2770 self->nullentry = |
2911 {"nodemap", (getter)index_nodemap, NULL, "nodemap", NULL}, |
2913 {"nodemap", (getter)index_nodemap, NULL, "nodemap", NULL}, |
2912 {NULL} /* Sentinel */ |
2914 {NULL} /* Sentinel */ |
2913 }; |
2915 }; |
2914 |
2916 |
2915 static PyMemberDef index_members[] = { |
2917 static PyMemberDef index_members[] = { |
2916 {"entry_size", T_LONG, offsetof(indexObject, hdrsize), 0, |
2918 {"entry_size", T_LONG, offsetof(indexObject, entry_size), 0, |
2917 "size of an index entry"}, |
2919 "size of an index entry"}, |
2918 {NULL} /* Sentinel */ |
2920 {NULL} /* Sentinel */ |
2919 }; |
2921 }; |
2920 |
2922 |
2921 PyTypeObject HgRevlogIndex_Type = { |
2923 PyTypeObject HgRevlogIndex_Type = { |