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