index edges in an asynchronous manner edges are being indexed in batchs while the graph's read lock is held to avoid interfering with the DB ongoing operation after each batch of edges is indexed the graph read lock is released alowing for write queries to be processed it is safe to run a write query which effects the index by either: adding/removing/updating an entity while the index is being po
| 110 | // adding/removing/updating an entity while the index is being populated |
| 111 | // in the "worst" case we will index that entity twice which is perfectly OK |
| 112 | static void _Index_PopulateEdgeIndex |
| 113 | ( |
| 114 | Index idx, |
| 115 | Graph *g |
| 116 | ) { |
| 117 | ASSERT(g != NULL); |
| 118 | ASSERT(idx != NULL); |
| 119 | |
| 120 | GrB_Info info; |
| 121 | EntityID src_id = 0; // current processed row idx |
| 122 | EntityID dest_id = 0; // current processed column idx |
| 123 | EntityID edge_id = 0; // current processed edge id |
| 124 | EntityID prev_src_id = 0; // last processed row idx |
| 125 | EntityID prev_dest_id = 0; // last processed column idx |
| 126 | int indexed = 0; // number of entities indexed in current batch |
| 127 | int batch_size = 1000; // max number of entities to index in one go |
| 128 | RG_MatrixTupleIter it = {0}; |
| 129 | |
| 130 | while(true) { |
| 131 | // lock graph for reading |
| 132 | Graph_AcquireReadLock(g); |
| 133 | |
| 134 | // index state changed, abort indexing |
| 135 | // this can happen if for example the following sequance is issued: |
| 136 | // 1. CREATE INDEX FOR (:Person)-[e:WORKS]-(:Company) ON (e.since) |
| 137 | // 2. CREATE INDEX FOR (:Person)-[e:WORKS]-(:Company) ON (e.title) |
| 138 | if(Index_PendingChanges(idx) > 1) { |
| 139 | break; |
| 140 | } |
| 141 | |
| 142 | // reset number of indexed edges in batch |
| 143 | indexed = 0; |
| 144 | prev_src_id = src_id; |
| 145 | prev_dest_id = dest_id; |
| 146 | |
| 147 | // fetch relation matrix |
| 148 | const RG_Matrix m = Graph_GetRelationMatrix(g, Index_GetLabelID(idx), |
| 149 | false); |
| 150 | ASSERT(m != NULL); |
| 151 | |
| 152 | //---------------------------------------------------------------------- |
| 153 | // resume scanning from previous row/col indices |
| 154 | //---------------------------------------------------------------------- |
| 155 | |
| 156 | info = RG_MatrixTupleIter_attach(&it, m); |
| 157 | ASSERT(info == GrB_SUCCESS); |
| 158 | info = RG_MatrixTupleIter_iterate_range(&it, src_id, UINT64_MAX); |
| 159 | ASSERT(info == GrB_SUCCESS); |
| 160 | |
| 161 | // skip previously indexed edges |
| 162 | while((info = RG_MatrixTupleIter_next_UINT64(&it, &src_id, &dest_id, |
| 163 | &edge_id)) == GrB_SUCCESS && |
| 164 | src_id == prev_src_id && |
| 165 | dest_id < prev_dest_id); |
| 166 | |
| 167 | // process only if iterator is on an active entry |
| 168 | if(info != GrB_SUCCESS) { |
| 169 | break; |
no test coverage detected