XDEL [ ... ] * * Removes the specified entries from the stream. Returns the number * of items actually deleted, that may be different from the number * of IDs passed in case certain IDs do not exist. */
| 3203 | * of items actually deleted, that may be different from the number |
| 3204 | * of IDs passed in case certain IDs do not exist. */ |
| 3205 | void xdelCommand(client *c) { |
| 3206 | robj *o; |
| 3207 | streamID static_ids[STREAMID_STATIC_VECTOR_LEN]; |
| 3208 | streamID *ids = static_ids; |
| 3209 | |
| 3210 | if ((o = lookupKeyWriteOrReply(c,c->argv[1],shared.czero)) == NULL |
| 3211 | || checkType(c,o,OBJ_STREAM)) return; |
| 3212 | stream *s = (stream*)ptrFromObj(o); |
| 3213 | |
| 3214 | { // BEGIN GOTO PROTECTED VARS |
| 3215 | /* We need to sanity check the IDs passed to start. Even if not |
| 3216 | * a big issue, it is not great that the command is only partially |
| 3217 | * executed because at some point an invalid ID is parsed. */ |
| 3218 | int id_count = c->argc-2; |
| 3219 | if (id_count > STREAMID_STATIC_VECTOR_LEN) |
| 3220 | ids = (streamID*)zmalloc(sizeof(streamID)*id_count); |
| 3221 | for (int j = 2; j < c->argc; j++) { |
| 3222 | if (streamParseStrictIDOrReply(c,c->argv[j],&ids[j-2],0) != C_OK) goto cleanup; |
| 3223 | } |
| 3224 | |
| 3225 | /* Actually apply the command. */ |
| 3226 | int deleted = 0; |
| 3227 | for (int j = 2; j < c->argc; j++) { |
| 3228 | deleted += streamDeleteItem(s,&ids[j-2]); |
| 3229 | } |
| 3230 | |
| 3231 | /* Propagate the write if needed. */ |
| 3232 | if (deleted) { |
| 3233 | signalModifiedKey(c,c->db,c->argv[1]); |
| 3234 | notifyKeyspaceEvent(NOTIFY_STREAM,"xdel",c->argv[1],c->db->id); |
| 3235 | g_pserver->dirty += deleted; |
| 3236 | } |
| 3237 | addReplyLongLong(c,deleted); |
| 3238 | }// END PROTECTED GOTO VARS |
| 3239 | cleanup: |
| 3240 | if (ids != static_ids) zfree(ids); |
| 3241 | } |
| 3242 | |
| 3243 | /* General form: XTRIM <key> [... options ...] |
| 3244 | * |
nothing calls this directly
no test coverage detected