Blocking RPOP/LPOP */
| 933 | |
| 934 | /* Blocking RPOP/LPOP */ |
| 935 | void blockingPopGenericCommand(client *c, int where) { |
| 936 | robj *o; |
| 937 | mstime_t timeout; |
| 938 | int j; |
| 939 | |
| 940 | if (getTimeoutFromObjectOrReply(c,c->argv[c->argc-1],&timeout,UNIT_SECONDS) |
| 941 | != C_OK) return; |
| 942 | |
| 943 | for (j = 1; j < c->argc-1; j++) { |
| 944 | o = lookupKeyWrite(c->db,c->argv[j]); |
| 945 | if (o != NULL) { |
| 946 | if (checkType(c,o,OBJ_LIST)) { |
| 947 | return; |
| 948 | } else { |
| 949 | if (listTypeLength(o) != 0) { |
| 950 | /* Non empty list, this is like a normal [LR]POP. */ |
| 951 | robj *value = listTypePop(o,where); |
| 952 | serverAssert(value != NULL); |
| 953 | |
| 954 | addReplyArrayLen(c,2); |
| 955 | addReplyBulk(c,c->argv[j]); |
| 956 | addReplyBulk(c,value); |
| 957 | decrRefCount(value); |
| 958 | listElementsRemoved(c,c->argv[j],where,o,1); |
| 959 | |
| 960 | /* Replicate it as an [LR]POP instead of B[LR]POP. */ |
| 961 | rewriteClientCommandVector(c,2, |
| 962 | (where == LIST_HEAD) ? shared.lpop : shared.rpop, |
| 963 | c->argv[j]); |
| 964 | return; |
| 965 | } |
| 966 | } |
| 967 | } |
| 968 | } |
| 969 | |
| 970 | /* If we are not allowed to block the client, the only thing |
| 971 | * we can do is treating it as a timeout (even with timeout 0). */ |
| 972 | if (c->flags & CLIENT_DENY_BLOCKING) { |
| 973 | addReplyNullArray(c); |
| 974 | return; |
| 975 | } |
| 976 | |
| 977 | /* If the keys do not exist we must block */ |
| 978 | listPos pos = {where}; |
| 979 | blockForKeys(c,BLOCKED_LIST,c->argv + 1,c->argc - 2,timeout,NULL,&pos,NULL); |
| 980 | } |
| 981 | |
| 982 | /* BLPOP <key> [<key> ...] <timeout> */ |
| 983 | void blpopCommand(client *c) { |
no test coverage detected