comparison mercurial/cext/revlog.c @ 47249:130c9f7ed914

revlog: add a "data compression mode" entry in the index tuple That will make it possible to keep track of compression information in the revlog index, opening the way to more efficient revision restoration (in native code, but the python usage is already defeating performance work). We start with adding a new entry to the index tuple, using a value matching the current behavior. We will introduce storage and other value in later changesets. Differential Revision: https://phab.mercurial-scm.org/D10646
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Mon, 03 May 2021 18:19:16 +0200
parents 6b1eae313b2f
children 4dca422d3907
comparison
equal deleted inserted replaced
47248:013c645dd28c 47249:130c9f7ed914
116 static Py_ssize_t inline_scan(indexObject *self, const char **offsets); 116 static Py_ssize_t inline_scan(indexObject *self, const char **offsets);
117 117
118 static int index_find_node(indexObject *self, const char *node); 118 static int index_find_node(indexObject *self, const char *node);
119 119
120 #if LONG_MAX == 0x7fffffffL 120 #if LONG_MAX == 0x7fffffffL
121 static const char *const tuple_format = PY23("Kiiiiiis#Ki", "Kiiiiiiy#Ki"); 121 static const char *const tuple_format = PY23("Kiiiiiis#KiB", "Kiiiiiiy#KiB");
122 #else 122 #else
123 static const char *const tuple_format = PY23("kiiiiiis#ki", "kiiiiiiy#ki"); 123 static const char *const tuple_format = PY23("kiiiiiis#kiB", "kiiiiiiy#kiB");
124 #endif 124 #endif
125 125
126 /* A RevlogNG v1 index entry is 64 bytes long. */ 126 /* A RevlogNG v1 index entry is 64 bytes long. */
127 static const long v1_entry_size = 64; 127 static const long v1_entry_size = 64;
128 128
129 /* A Revlogv2 index entry is 96 bytes long. */ 129 /* A Revlogv2 index entry is 96 bytes long. */
130 static const long v2_entry_size = 96; 130 static const long v2_entry_size = 96;
131 131
132 static const long format_v1 = 1; /* Internal only, could be any number */ 132 static const long format_v1 = 1; /* Internal only, could be any number */
133 static const long format_v2 = 2; /* Internal only, could be any number */ 133 static const long format_v2 = 2; /* Internal only, could be any number */
134
135 static const char comp_mode_inline = 2;
134 136
135 static void raise_revlog_error(void) 137 static void raise_revlog_error(void)
136 { 138 {
137 PyObject *mod = NULL, *dict = NULL, *errclass = NULL; 139 PyObject *mod = NULL, *dict = NULL, *errclass = NULL;
138 140
292 static PyObject *index_get(indexObject *self, Py_ssize_t pos) 294 static PyObject *index_get(indexObject *self, Py_ssize_t pos)
293 { 295 {
294 uint64_t offset_flags, sidedata_offset; 296 uint64_t offset_flags, sidedata_offset;
295 int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2, 297 int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2,
296 sidedata_comp_len; 298 sidedata_comp_len;
299 char data_comp_mode;
297 const char *c_node_id; 300 const char *c_node_id;
298 const char *data; 301 const char *data;
299 Py_ssize_t length = index_length(self); 302 Py_ssize_t length = index_length(self);
300 303
301 if (pos == nullrev) { 304 if (pos == nullrev) {
338 } else { 341 } else {
339 sidedata_offset = getbe64(data + 64); 342 sidedata_offset = getbe64(data + 64);
340 sidedata_comp_len = getbe32(data + 72); 343 sidedata_comp_len = getbe32(data + 72);
341 } 344 }
342 345
346 data_comp_mode = comp_mode_inline;
343 return Py_BuildValue(tuple_format, offset_flags, comp_len, uncomp_len, 347 return Py_BuildValue(tuple_format, offset_flags, comp_len, uncomp_len,
344 base_rev, link_rev, parent_1, parent_2, c_node_id, 348 base_rev, link_rev, parent_1, parent_2, c_node_id,
345 self->nodelen, sidedata_offset, sidedata_comp_len); 349 self->nodelen, sidedata_offset, sidedata_comp_len,
350 data_comp_mode);
346 } 351 }
347 /* 352 /*
348 * Pack header information in binary 353 * Pack header information in binary
349 */ 354 */
350 static PyObject *index_pack_header(indexObject *self, PyObject *args) 355 static PyObject *index_pack_header(indexObject *self, PyObject *args)
441 446
442 static PyObject *index_append(indexObject *self, PyObject *obj) 447 static PyObject *index_append(indexObject *self, PyObject *obj)
443 { 448 {
444 uint64_t offset_flags, sidedata_offset; 449 uint64_t offset_flags, sidedata_offset;
445 int rev, comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2; 450 int rev, comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2;
451 char data_comp_mode;
446 Py_ssize_t c_node_id_len, sidedata_comp_len; 452 Py_ssize_t c_node_id_len, sidedata_comp_len;
447 const char *c_node_id; 453 const char *c_node_id;
448 char *data; 454 char *data;
449 455
450 if (!PyArg_ParseTuple(obj, tuple_format, &offset_flags, &comp_len, 456 if (!PyArg_ParseTuple(obj, tuple_format, &offset_flags, &comp_len,
451 &uncomp_len, &base_rev, &link_rev, &parent_1, 457 &uncomp_len, &base_rev, &link_rev, &parent_1,
452 &parent_2, &c_node_id, &c_node_id_len, 458 &parent_2, &c_node_id, &c_node_id_len,
453 &sidedata_offset, &sidedata_comp_len)) { 459 &sidedata_offset, &sidedata_comp_len,
454 PyErr_SetString(PyExc_TypeError, "10-tuple required"); 460 &data_comp_mode)) {
461 PyErr_SetString(PyExc_TypeError, "11-tuple required");
455 return NULL; 462 return NULL;
456 } 463 }
457 464
458 if (c_node_id_len != self->nodelen) { 465 if (c_node_id_len != self->nodelen) {
459 PyErr_SetString(PyExc_TypeError, "invalid node"); 466 PyErr_SetString(PyExc_TypeError, "invalid node");
467 return NULL;
468 }
469 if (data_comp_mode != comp_mode_inline) {
470 PyErr_Format(PyExc_ValueError,
471 "invalid data compression mode: %i",
472 data_comp_mode);
460 return NULL; 473 return NULL;
461 } 474 }
462 475
463 if (self->new_length == self->added_length) { 476 if (self->new_length == self->added_length) {
464 size_t new_added_length = 477 size_t new_added_length =
2759 } else { 2772 } else {
2760 self->format_version = format_v1; 2773 self->format_version = format_v1;
2761 self->entry_size = v1_entry_size; 2774 self->entry_size = v1_entry_size;
2762 } 2775 }
2763 2776
2764 self->nullentry = 2777 self->nullentry = Py_BuildValue(PY23("iiiiiiis#iiB", "iiiiiiiy#iiB"), 0,
2765 Py_BuildValue(PY23("iiiiiiis#ii", "iiiiiiiy#ii"), 0, 0, 0, -1, -1, 2778 0, 0, -1, -1, -1, -1, nullid,
2766 -1, -1, nullid, self->nodelen, 0, 0); 2779 self->nodelen, 0, 0, comp_mode_inline);
2767 2780
2768 if (!self->nullentry) 2781 if (!self->nullentry)
2769 return -1; 2782 return -1;
2770 PyObject_GC_UnTrack(self->nullentry); 2783 PyObject_GC_UnTrack(self->nullentry);
2771 2784