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