comparison mercurial/parsers.c @ 25190:22438cfd11b5

phases: add set per phase in C phase computation To speed up the computation of draft(), secret(), divergent(), obsolete() and unstable() we need to have a fast way of getting the list of revisions that are in draft(), secret() or the union of both: not public(). This patch extends the work on phase computation in C and make the phase computation code also return a list of set for each non public phase. Using these sets we can quickly obtain all the revisions of a given phase. We do not return a set for the public phase as we expect it to be roughly the size of the repo. Also, it can be computed easily by substracting the entries in the non public phases from all the revs in the repo.
author Laurent Charignon <lcharignon@fb.com>
date Wed, 01 Apr 2015 11:17:17 -0700
parents b3142ea2a0d4
children 8c8af4d8aca3
comparison
equal deleted inserted replaced
25189:1c8c33eaea0a 25190:22438cfd11b5
1069 phases[i] = phases[parent_1]; 1069 phases[i] = phases[parent_1];
1070 if (parent_2 >= 0 && phases[parent_2] > phases[i]) 1070 if (parent_2 >= 0 && phases[parent_2] > phases[i])
1071 phases[i] = phases[parent_2]; 1071 phases[i] = phases[parent_2];
1072 } 1072 }
1073 1073
1074 static PyObject *compute_phases(indexObject *self, PyObject *args) 1074 static PyObject *compute_phases_map_sets(indexObject *self, PyObject *args)
1075 { 1075 {
1076 PyObject *roots = Py_None; 1076 PyObject *roots = Py_None;
1077 PyObject *ret = NULL;
1077 PyObject *phaseslist = NULL; 1078 PyObject *phaseslist = NULL;
1078 PyObject *phaseroots = NULL; 1079 PyObject *phaseroots = NULL;
1079 PyObject *rev = NULL; 1080 PyObject *rev = NULL;
1080 PyObject *p1 = NULL; 1081 PyObject *p1 = NULL;
1081 PyObject *p2 = NULL; 1082 PyObject *p2 = NULL;
1083 PyObject *phaseset = NULL;
1084 PyObject *phasessetlist = NULL;
1082 Py_ssize_t addlen = self->added ? PyList_GET_SIZE(self->added) : 0; 1085 Py_ssize_t addlen = self->added ? PyList_GET_SIZE(self->added) : 0;
1083 Py_ssize_t len = index_length(self) - 1; 1086 Py_ssize_t len = index_length(self) - 1;
1084 Py_ssize_t numphase = 0; 1087 Py_ssize_t numphase = 0;
1085 Py_ssize_t minrevallphases = 0; 1088 Py_ssize_t minrevallphases = 0;
1086 Py_ssize_t minrevphase = 0; 1089 Py_ssize_t minrevphase = 0;
1087 Py_ssize_t i = 0; 1090 Py_ssize_t i = 0;
1088 int parent_1, parent_2; 1091 int parent_1, parent_2;
1089 char *phases = NULL; 1092 char *phases = NULL;
1090 const char *data; 1093 const char *data;
1094 long phase;
1091 1095
1092 if (!PyArg_ParseTuple(args, "O", &roots)) 1096 if (!PyArg_ParseTuple(args, "O", &roots))
1093 goto release_none; 1097 goto release_none;
1094 if (roots == NULL || !PyList_Check(roots)) 1098 if (roots == NULL || !PyList_Check(roots))
1095 goto release_none; 1099 goto release_none;
1098 if (phases == NULL) 1102 if (phases == NULL)
1099 goto release_none; 1103 goto release_none;
1100 /* Put the phase information of all the roots in phases */ 1104 /* Put the phase information of all the roots in phases */
1101 numphase = PyList_GET_SIZE(roots)+1; 1105 numphase = PyList_GET_SIZE(roots)+1;
1102 minrevallphases = len + 1; 1106 minrevallphases = len + 1;
1107 phasessetlist = PyList_New(numphase);
1108 if (phasessetlist == NULL)
1109 goto release_none;
1110
1111 PyList_SET_ITEM(phasessetlist, 0, Py_None);
1112 Py_INCREF(Py_None);
1113
1103 for (i = 0; i < numphase-1; i++) { 1114 for (i = 0; i < numphase-1; i++) {
1104 phaseroots = PyList_GET_ITEM(roots, i); 1115 phaseroots = PyList_GET_ITEM(roots, i);
1116 phaseset = PySet_New(NULL);
1117 if (phaseset == NULL)
1118 goto release_phasesetlist;
1119 PyList_SET_ITEM(phasessetlist, i+1, phaseset);
1105 if (!PyList_Check(phaseroots)) 1120 if (!PyList_Check(phaseroots))
1106 goto release_phases; 1121 goto release_phasesetlist;
1107 minrevphase = add_roots_get_min(self, phaseroots, i+1, phases); 1122 minrevphase = add_roots_get_min(self, phaseroots, i+1, phases);
1108 if (minrevphase == -2) /* Error from add_roots_get_min */ 1123 if (minrevphase == -2) /* Error from add_roots_get_min */
1109 goto release_phases; 1124 goto release_phasesetlist;
1110 minrevallphases = MIN(minrevallphases, minrevphase); 1125 minrevallphases = MIN(minrevallphases, minrevphase);
1111 } 1126 }
1112 /* Propagate the phase information from the roots to the revs */ 1127 /* Propagate the phase information from the roots to the revs */
1113 if (minrevallphases != -1) { 1128 if (minrevallphases != -1) {
1114 for (i = minrevallphases; i < self->raw_length; i++) { 1129 for (i = minrevallphases; i < self->raw_length; i++) {
1119 rev = PyList_GET_ITEM(self->added, i); 1134 rev = PyList_GET_ITEM(self->added, i);
1120 p1 = PyTuple_GET_ITEM(rev, 5); 1135 p1 = PyTuple_GET_ITEM(rev, 5);
1121 p2 = PyTuple_GET_ITEM(rev, 6); 1136 p2 = PyTuple_GET_ITEM(rev, 6);
1122 if (!PyInt_Check(p1) || !PyInt_Check(p2)) { 1137 if (!PyInt_Check(p1) || !PyInt_Check(p2)) {
1123 PyErr_SetString(PyExc_TypeError, "revlog parents are invalid"); 1138 PyErr_SetString(PyExc_TypeError, "revlog parents are invalid");
1124 goto release_phases; 1139 goto release_phasesetlist;
1125 } 1140 }
1126 parent_1 = (int)PyInt_AS_LONG(p1); 1141 parent_1 = (int)PyInt_AS_LONG(p1);
1127 parent_2 = (int)PyInt_AS_LONG(p2); 1142 parent_2 = (int)PyInt_AS_LONG(p2);
1128 set_phase_from_parents(phases, parent_1, parent_2, i+self->raw_length); 1143 set_phase_from_parents(phases, parent_1, parent_2, i+self->raw_length);
1129 } 1144 }
1130 } 1145 }
1131 /* Transform phase list to a python list */ 1146 /* Transform phase list to a python list */
1132 phaseslist = PyList_New(len); 1147 phaseslist = PyList_New(len);
1133 if (phaseslist == NULL) 1148 if (phaseslist == NULL)
1134 goto release_phases; 1149 goto release_phasesetlist;
1135 for (i = 0; i < len; i++) 1150 for (i = 0; i < len; i++) {
1136 PyList_SET_ITEM(phaseslist, i, PyInt_FromLong(phases[i])); 1151 phase = phases[i];
1137 1152 /* We only store the sets of phase for non public phase, the public phase
1153 * is computed as a difference */
1154 if (phase != 0) {
1155 phaseset = PyList_GET_ITEM(phasessetlist, phase);
1156 PySet_Add(phaseset, PyInt_FromLong(i));
1157 }
1158 PyList_SET_ITEM(phaseslist, i, PyInt_FromLong(phase));
1159 }
1160 ret = PyList_New(2);
1161 if (ret == NULL)
1162 goto release_phaseslist;
1163
1164 PyList_SET_ITEM(ret, 0, phaseslist);
1165 PyList_SET_ITEM(ret, 1, phasessetlist);
1166 /* We don't release phaseslist and phasessetlist as we return them to
1167 * python */
1168 goto release_phases;
1169
1170 release_phaseslist:
1171 Py_XDECREF(phaseslist);
1172 release_phasesetlist:
1173 Py_XDECREF(phasessetlist);
1138 release_phases: 1174 release_phases:
1139 free(phases); 1175 free(phases);
1140 release_none: 1176 release_none:
1141 return phaseslist; 1177 return ret;
1142 } 1178 }
1143 1179
1144 static PyObject *index_headrevs(indexObject *self, PyObject *args) 1180 static PyObject *index_headrevs(indexObject *self, PyObject *args)
1145 { 1181 {
1146 Py_ssize_t i, len, addlen; 1182 Py_ssize_t i, len, addlen;
2276 "return the heads of the common ancestors of the given revs"}, 2312 "return the heads of the common ancestors of the given revs"},
2277 {"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS, 2313 {"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS,
2278 "clear the index caches"}, 2314 "clear the index caches"},
2279 {"get", (PyCFunction)index_m_get, METH_VARARGS, 2315 {"get", (PyCFunction)index_m_get, METH_VARARGS,
2280 "get an index entry"}, 2316 "get an index entry"},
2281 {"computephases", (PyCFunction)compute_phases, METH_VARARGS, 2317 {"computephasesmapsets", (PyCFunction)compute_phases_map_sets,
2282 "compute phases"}, 2318 METH_VARARGS, "compute phases"},
2283 {"headrevs", (PyCFunction)index_headrevs, METH_VARARGS, 2319 {"headrevs", (PyCFunction)index_headrevs, METH_VARARGS,
2284 "get head revisions"}, /* Can do filtering since 3.2 */ 2320 "get head revisions"}, /* Can do filtering since 3.2 */
2285 {"headrevsfiltered", (PyCFunction)index_headrevs, METH_VARARGS, 2321 {"headrevsfiltered", (PyCFunction)index_headrevs, METH_VARARGS,
2286 "get filtered head revisions"}, /* Can always do filtering */ 2322 "get filtered head revisions"}, /* Can always do filtering */
2287 {"insert", (PyCFunction)index_insert, METH_VARARGS, 2323 {"insert", (PyCFunction)index_insert, METH_VARARGS,