Remove the current entry from the stream: can be called after the * GetID() API or after any GetField() call, however we need to iterate * a valid entry while calling this function. Moreover the function * requires the entry ID we are currently iterating, that was previously * returned by GetID(). * * Note that after calling this function, next calls to GetField() can't * be performed: the
| 1256 | * automatically re-seek to the next entry, so the caller should continue |
| 1257 | * with GetID(). */ |
| 1258 | void streamIteratorRemoveEntry(streamIterator *si, streamID *current) { |
| 1259 | unsigned char *lp = si->lp; |
| 1260 | int64_t aux; |
| 1261 | |
| 1262 | /* We do not really delete the entry here. Instead we mark it as |
| 1263 | * deleted flagging it, and also incrementing the count of the |
| 1264 | * deleted entries in the listpack header. |
| 1265 | * |
| 1266 | * We start flagging: */ |
| 1267 | int64_t flags = lpGetInteger(si->lp_flags); |
| 1268 | flags |= STREAM_ITEM_FLAG_DELETED; |
| 1269 | lp = lpReplaceInteger(lp,&si->lp_flags,flags); |
| 1270 | |
| 1271 | /* Change the valid/deleted entries count in the master entry. */ |
| 1272 | unsigned char *p = lpFirst(lp); |
| 1273 | aux = lpGetInteger(p); |
| 1274 | |
| 1275 | if (aux == 1) { |
| 1276 | /* If this is the last element in the listpack, we can remove the whole |
| 1277 | * node. */ |
| 1278 | lpFree(lp); |
| 1279 | raxRemove(si->pstream->rax,si->ri.key,si->ri.key_len,NULL); |
| 1280 | } else { |
| 1281 | /* In the base case we alter the counters of valid/deleted entries. */ |
| 1282 | lp = lpReplaceInteger(lp,&p,aux-1); |
| 1283 | p = lpNext(lp,p); /* Seek deleted field. */ |
| 1284 | aux = lpGetInteger(p); |
| 1285 | lp = lpReplaceInteger(lp,&p,aux+1); |
| 1286 | |
| 1287 | /* Update the listpack with the new pointer. */ |
| 1288 | if (si->lp != lp) |
| 1289 | raxInsert(si->pstream->rax,si->ri.key,si->ri.key_len,lp,NULL); |
| 1290 | } |
| 1291 | |
| 1292 | /* Update the number of entries counter. */ |
| 1293 | si->pstream->length--; |
| 1294 | |
| 1295 | /* Re-seek the iterator to fix the now messed up state. */ |
| 1296 | streamID start, end; |
| 1297 | if (si->rev) { |
| 1298 | streamDecodeID(si->start_key,&start); |
| 1299 | end = *current; |
| 1300 | } else { |
| 1301 | start = *current; |
| 1302 | streamDecodeID(si->end_key,&end); |
| 1303 | } |
| 1304 | streamIteratorStop(si); |
| 1305 | streamIteratorStart(si,si->pstream,&start,&end,si->rev); |
| 1306 | |
| 1307 | /* TODO: perform a garbage collection here if the ration between |
| 1308 | * deleted and valid goes over a certain limit. */ |
| 1309 | } |
| 1310 | |
| 1311 | /* Stop the stream iterator. The only cleanup we need is to free the rax |
| 1312 | * iterator, since the stream iterator itself is supposed to be stack |
no test coverage detected