| 746 | } |
| 747 | |
| 748 | void replicationFeedMonitors(client *c, list *monitors, int dictid, robj **argv, int argc) { |
| 749 | if (!(listLength(g_pserver->monitors) && !g_pserver->loading)) return; |
| 750 | listNode *ln; |
| 751 | listIter li; |
| 752 | int j; |
| 753 | sds cmdrepr = sdsnew("+"); |
| 754 | robj *cmdobj; |
| 755 | struct timeval tv; |
| 756 | serverAssert(GlobalLocksAcquired()); |
| 757 | |
| 758 | gettimeofday(&tv,NULL); |
| 759 | cmdrepr = sdscatprintf(cmdrepr,"%ld.%06ld ",(long)tv.tv_sec,(long)tv.tv_usec); |
| 760 | if (c->flags & CLIENT_LUA) { |
| 761 | cmdrepr = sdscatprintf(cmdrepr,"[%d lua] ",dictid); |
| 762 | } else if (c->flags & CLIENT_UNIX_SOCKET) { |
| 763 | cmdrepr = sdscatprintf(cmdrepr,"[%d unix:%s] ",dictid,g_pserver->unixsocket); |
| 764 | } else { |
| 765 | cmdrepr = sdscatprintf(cmdrepr,"[%d %s] ",dictid,getClientPeerId(c)); |
| 766 | } |
| 767 | |
| 768 | for (j = 0; j < argc; j++) { |
| 769 | if (argv[j]->encoding == OBJ_ENCODING_INT) { |
| 770 | cmdrepr = sdscatprintf(cmdrepr, "\"%ld\"", (long)ptrFromObj(argv[j])); |
| 771 | } else { |
| 772 | cmdrepr = sdscatrepr(cmdrepr,(char*)ptrFromObj(argv[j]), |
| 773 | sdslen((sds)ptrFromObj(argv[j]))); |
| 774 | } |
| 775 | if (j != argc-1) |
| 776 | cmdrepr = sdscatlen(cmdrepr," ",1); |
| 777 | } |
| 778 | cmdrepr = sdscatlen(cmdrepr,"\r\n",2); |
| 779 | cmdobj = createObject(OBJ_STRING,cmdrepr); |
| 780 | |
| 781 | listRewind(monitors,&li); |
| 782 | while((ln = listNext(&li))) { |
| 783 | client *monitor = (client*)ln->value; |
| 784 | std::unique_lock<decltype(monitor->lock)> lock(monitor->lock, std::defer_lock); |
| 785 | // When writing to clients on other threads the global lock is sufficient provided we only use AddReply*Async() |
| 786 | if (FCorrectThread(c)) |
| 787 | lock.lock(); |
| 788 | addReply(monitor,cmdobj); |
| 789 | } |
| 790 | decrRefCount(cmdobj); |
| 791 | } |
| 792 | |
| 793 | int prepareClientToWrite(client *c); |
| 794 |
no test coverage detected