Unblock a client that's waiting in a blocking operation such as BLPOP. * You should never call this function directly, but unblockClient() instead. */
| 699 | /* Unblock a client that's waiting in a blocking operation such as BLPOP. |
| 700 | * You should never call this function directly, but unblockClient() instead. */ |
| 701 | void unblockClientWaitingData(client *c) { |
| 702 | dictEntry *de; |
| 703 | dictIterator *di; |
| 704 | list *l; |
| 705 | |
| 706 | serverAssertWithInfo(c,NULL,dictSize(c->bpop.keys) != 0); |
| 707 | di = dictGetIterator(c->bpop.keys); |
| 708 | /* The client may wait for multiple keys, so unblock it for every key. */ |
| 709 | while((de = dictNext(di)) != NULL) { |
| 710 | robj *key = (robj*)dictGetKey(de); |
| 711 | bkinfo *bki = (bkinfo*)dictGetVal(de); |
| 712 | |
| 713 | /* Remove this client from the list of clients waiting for this key. */ |
| 714 | l = (list*)dictFetchValue(c->db->blocking_keys,key); |
| 715 | serverAssertWithInfo(c,key,l != NULL); |
| 716 | listDelNode(l,bki->listnode); |
| 717 | /* If the list is empty we need to remove it to avoid wasting memory */ |
| 718 | if (listLength(l) == 0) |
| 719 | dictDelete(c->db->blocking_keys,key); |
| 720 | } |
| 721 | dictReleaseIterator(di); |
| 722 | |
| 723 | /* Cleanup the client structure */ |
| 724 | dictEmpty(c->bpop.keys,NULL); |
| 725 | if (c->bpop.target) { |
| 726 | decrRefCount(c->bpop.target); |
| 727 | c->bpop.target = NULL; |
| 728 | } |
| 729 | if (c->bpop.xread_group) { |
| 730 | decrRefCount(c->bpop.xread_group); |
| 731 | decrRefCount(c->bpop.xread_consumer); |
| 732 | c->bpop.xread_group = NULL; |
| 733 | c->bpop.xread_consumer = NULL; |
| 734 | } |
| 735 | c->bpop.timeout = 0; |
| 736 | } |
| 737 | |
| 738 | static int getBlockedTypeByType(int type) { |
| 739 | switch (type) { |
no test coverage detected