void execCommand(redisClient *c) { int j; robj **orig_argv; int orig_argc; if (!(c->flags & REDIS_MULTI)) { addReplySds(c,sdsnew("-ERR EXEC without MULTI\r\n")); return; } /* Check if we need to abort the EXEC if some WATCHed key was touched. * A failed EXEC will return a multi bulk nil object. */ if (c->flags & REDIS_DIRTY_CAS) { freeClientMultiState(c); initClientMultiState(c); c->flags &= ~(REDIS_MULTI|REDIS_DIRTY_CAS); unwatchAllKeys(c); addReply(c,shared.nullmultibulk); return; } /* Replicate a MULTI request now that we are sure the block is executed. * This way we'll deliver the MULTI/..../EXEC block as a whole and * both the AOF and the replication link will have the same consistency * and atomicity guarantees. */ execCommandReplicateMulti(c); /* Exec all the queued commands */ unwatchAllKeys(c); /* Unwatch ASAP otherwise we'll waste CPU cycles */ orig_argv = c->argv; orig_argc = c->argc; addReplySds(c,sdscatprintf(sdsempty(),"*%d\r\n",c->mstate.count)); for (j = 0; j < c->mstate.count; j++) { c->argc = c->mstate.commands[j].argc; c->argv = c->mstate.commands[j].argv; call(c,c->mstate.commands[j].cmd); } c->argv = orig_argv; c->argc = orig_argc; freeClientMultiState(c); initClientMultiState(c); c->flags &= ~(REDIS_MULTI|REDIS_DIRTY_CAS); /* Make sure the EXEC command is always replicated / AOF, since we * always send the MULTI command (we can't know beforehand if the * next operations will contain at least a modification to the DB). */ server.dirty++; }
/* * cetcd_cluster_request tries to request the whole cluster. It round-robin to next server if the request failed * */ cetcd_response *cetcd_cluster_request(cetcd_client *cli, cetcd_request *req) { int i; size_t count; cetcd_string url; cetcd_error *err; cetcd_response *resp; err = NULL; resp = NULL; count = cetcd_array_size(cli->addresses); for(i = 0; i < count; ++i) { url = sdscatprintf(sdsempty(), "http://%s/%s", (cetcd_string)cetcd_array_get(cli->addresses, cli->picked), req->uri); req->url = url; req->cli = cli; resp = cetcd_send_request(cli->curl, req); sdsfree(url); if(resp && resp->err && resp->err->ecode == error_send_request_failed) { if (i == count-1) { break; } /*try next*/ cli->picked = (cli->picked + 1) % count; cetcd_response_release(resp); resp = NULL; } else { /*got response, return*/ return resp; } } /*the whole cluster failed*/ if (resp) { if(resp->err) { err = resp->err; /*remember last error*/ } resp->err = calloc(1, sizeof(cetcd_error)); resp->err->ecode = error_cluster_failed; resp->err->message = sdsnew("etcd_do_request: all cluster servers failed."); if (err) { resp->err->message = sdscatprintf(resp->err->message, " last error: %s", err->message); cetcd_error_release(err); } resp->err->cause = sdsdup(req->uri); } return resp; }
void make_trace(char* path) { init_jcr(path); sds trace_file = sdsnew(path); char *p = trace_file + sdslen(trace_file) - 1; while (*p == '/') --p; *(p + 1) = 0; sdsupdatelen(trace_file); trace_file = sdscat(trace_file, ".trace"); NOTICE("output to %s", trace_file); start_read_phase(); start_chunk_phase(); start_hash_phase(); unsigned char code[41]; FILE *fp = fopen(trace_file, "w"); while (1) { struct chunk *c = sync_queue_pop(hash_queue); if (c == NULL) { break; } if (CHECK_CHUNK(c, CHUNK_FILE_START)) { destor_log(DESTOR_NOTICE, c->data); fprintf(fp, "file start %zd\n", strlen(c->data)); fprintf(fp, "%s\n", c->data); } else if (CHECK_CHUNK(c, CHUNK_FILE_END)) { fprintf(fp, "file end\n"); } else { hash2code(c->fp, code); code[40] = 0; fprintf(fp, "%s %d\n", code, c->size); } free_chunk(c); } fprintf(fp, "stream end"); fclose(fp); }
/* Mass-unblock clients because something changed in the instance that makes * blocking no longer safe. For example clients blocked in list operations * in an instance which turns from master to slave is unsafe, so this function * is called when a master turns into a slave. * * The semantics is to send an -UNBLOCKED error to the client, disconnecting * it at the same time. */ void disconnectAllBlockedClients(void) { listNode *ln; listIter li; listRewind(server.clients,&li); while((ln = listNext(&li))) { client *c = listNodeValue(ln); if (c->flags & CLIENT_BLOCKED) { addReplySds(c,sdsnew( "-UNBLOCKED force unblock from blocking operation, " "instance state changed (master -> slave?)\r\n")); unblockClient(c); c->flags |= CLIENT_CLOSE_AFTER_REPLY; } } }
/* This function does exactly the revese of the function above: it gets * as input an integer with the xored flags and returns a string representing * the selected classes. The string returned is an sds string that needs to * be released with sdsfree(). */ sds keyspaceEventsFlagsToString(int flags) { sds res; if ((flags & REDIS_NOTIFY_ALL) == REDIS_NOTIFY_ALL) return sdsnew("A"); res = sdsempty(); if (flags & REDIS_NOTIFY_GENERIC) res = sdscatlen(res,"g",1); if (flags & REDIS_NOTIFY_STRING) res = sdscatlen(res,"$",1); if (flags & REDIS_NOTIFY_LIST) res = sdscatlen(res,"l",1); if (flags & REDIS_NOTIFY_SET) res = sdscatlen(res,"s",1); if (flags & REDIS_NOTIFY_HASH) res = sdscatlen(res,"h",1); if (flags & REDIS_NOTIFY_ZSET) res = sdscatlen(res,"z",1); if (flags & REDIS_NOTIFY_EXPIRED) res = sdscatlen(res,"x",1); if (flags & REDIS_NOTIFY_EVICTED) res = sdscatlen(res,"e",1); if (flags & REDIS_NOTIFY_KEYSPACE) res = sdscatlen(res,"K",1); if (flags & REDIS_NOTIFY_KEYEVENT) res = sdscatlen(res,"E",1); return res; }
static bool checkPurge() { listNode *ln; listIter li; uint32 num_ok = 0; sds ds = sdsnew("DIRTY\r\n"); listRewind(server.slaves, &li); while((ln = listNext(&li))) { cli *slave = ln->value; redisReply *reply; int fd = remoteMessage(slave->bindaddr, slave->bindport, ds, 1, &reply); if (fd == -1) close(fd); if (reply) { assert(reply->type == REDIS_REPLY_INTEGER); if (reply->integer == server.alc.stat_num_dirty_commands) num_ok++; } } sdsfree(ds); return (server.slaves->len == num_ok); }
S triefort_destroy(const char * const path) { S s = triefort_ok; sds spath = sdsnew(path); spath = sdscat(spath, "/" CONFIG_FILE_NAME); if (!file_exists(spath)) { s = triefort_err_not_a_triefort; } else { if (0 != recursive_remove(path)) { s = triefort_err_path_could_not_be_destroyed; } } sdsfree(spath); return s; }
cetcd_response *cetcd_send_request(CURL *curl, cetcd_request *req) { CURLcode res; cetcd_response_parser parser; cetcd_response *resp; resp = calloc(1, sizeof(cetcd_response)); parser.resp = resp; parser.st = 0; /*0 should be the start state of the state machine*/ parser.buf = sdsempty(); curl_easy_setopt(curl, CURLOPT_URL, req->url); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, http_method[req->method]); if (req->method == ETCD_HTTP_PUT || req->method == ETCD_HTTP_POST) { curl_easy_setopt(curl, CURLOPT_POSTFIELDS, req->data); } else { /* We must clear post fields here: * We reuse the curl handle for all HTTP methods. * CURLOPT_POSTFIELDS would be set when issue a PUT request. * The field pointed to the freed req->data. It would be * reused by next request. * */ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, ""); } curl_easy_setopt(curl, CURLOPT_HEADER, 1L); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &parser); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cetcd_parse_response); curl_easy_setopt(curl, CURLOPT_VERBOSE, req->cli->settings.verbose); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, req->cli->settings.connect_timeout); res = curl_easy_perform(curl); sdsfree(parser.buf); if (res != CURLE_OK) { if (resp->err == NULL) { resp->err = calloc(1, sizeof(cetcd_error)); resp->err->ecode = error_send_request_failed; resp->err->message = sdsnew(curl_easy_strerror(res)); resp->err->cause = sdsdup(req->url); } return resp; } return resp; }
vuiClient * createClient(int fd) { if (server.client != NULL) { close(fd); return NULL; } LogInfo("creat client fd:%d", fd); vuiClient *c = zmalloc(sizeof(vuiClient)); memset(c, 0, sizeof(vuiClient)); c->querybuf = sdsempty(); c->querymsg = sdsempty(); c->prot.method = NULL; c->prot.version = NULL; c->prot.body = NULL; c->prot.lenght = 0; c->prot.waiting = 0; c->res.version = "VPC/1.0"; c->res.code = 200; c->res.reason = sdsnew("OK"); c->res.body = sdsempty(); c->res.buf = sdsempty(); c->jsons = listCreate(); c->fd = fd; anetNonBlock(NULL,fd); anetEnableTcpNoDelay(NULL,fd); if (aeCreateFileEvent(server.el, fd, AE_READABLE, readQueryFromClient, c) == AE_ERR) { close(fd); zfree(c); return NULL; } server.client = c; return c; }
/* * parse master info comman and get oplog.last */ static void test_repl_parse_master_info() { sds buf = sdsnew("#repl\r\n" \ "oplog.first:3\r\n" \ "oplog.last:5\r\n" ); sds value = repl_parse_master_info(buf, "oplog.last"); TEST_ASSERT("parse master info", strcmp(value, "5") == 0); sdsfree(value); value = repl_parse_master_info(buf, "oplog.last2"); TEST_ASSERT("parse master info", value == NULL); sdsfree(value); sdsfree(buf); }
/* This should be called from any function PUSHing into lists. * 'c' is the "pushing client", 'key' is the key it is pushing data against, * 'ele' is the element pushed. * * If the function returns 0 there was no client waiting for a list push * against this key. * * If the function returns 1 there was a client waiting for a list push * against this key, the element was passed to this client thus it's not * needed to actually add it to the list and the caller should return asap. */ int handleClientsWaitingListPush(redisClient *c, robj *key, robj *ele) { struct dictEntry *de; redisClient *receiver; list *l; listNode *ln; de = dictFind(c->db->blocking_keys,key); if (de == NULL) return 0; l = dictGetEntryVal(de); ln = listFirst(l); redisAssert(ln != NULL); receiver = ln->value; addReplySds(receiver,sdsnew("*2\r\n")); addReplyBulk(receiver,key); addReplyBulk(receiver,ele); unblockClientWaitingData(receiver); return 1; }
/* Populates the Redis Command Table starting from the hard coded list * we have in the rct_command.h file. */ void populateCommandTable(dict *commands) { int ret; int j; int numcommands; if(commands == NULL) { return; } numcommands = sizeof(rctCommandTable)/sizeof(RCTCommand); for (j = 0; j < numcommands; j++) { RCTCommand *c = rctCommandTable+j; ret = dictAdd(commands, sdsnew(c->name), c); } }
sds _masterGetStatus() { /*TODO: calculate cache increase speed, * then adopt a suitable stale-cache freeing strategy * Three involved params: * (1) master sleep, * (2) ae loop wait, * and (3) number of stale entries in one ae loop */ sds status = sdsempty();//sdsfromlonglong(master_total_mem); status = sdscatprintf(status,"TOL RAM: %-6.2lfMB\tUSED RAM: %-6.2lf\n", BYTES_TO_MEGABYTES(MASTER_MAX_AVAIL_MEM), BYTES_TO_MEGABYTES(master_total_mem)); #if (CCACHE_LOG_LEVEL == CCACHE_DEBUG) status = sdscatprintf(status,"Detail:\n"); status = sdscatprintf(status,"%-3s %-32s: %-6s\n"," ","KEY","MEM"); dictIterator *di = dictGetIterator(master_cache); dictEntry *de; int idx = 1; while((de = dictNext(di)) != NULL) { objSds *value = (objSds*)dictGetEntryVal(de); if(value) { if(value->ptr) { status = sdscatprintf(status,"%-3d %-32s: %-6ld\n", idx++, (char*)dictGetEntryKey(de), sdslen(value->ptr)); } else { status = sdscatprintf(status,"%-3d %-32s: %-6s\n", idx++, (char*)dictGetEntryKey(de), "WAITING"); } } } dictReleaseIterator(di); #endif sds status_reply = sdsnew("HTTP/1.1 200 OK\r\n"); status_reply = sdscatprintf(status_reply,"Content-Length: %ld\r\n\r\n%s",sdslen(status),status); sdsfree(status); return status_reply; }
void slaveofCommand(redisClient *c) { if (!strcasecmp(c->argv[1]->ptr,"no") && !strcasecmp(c->argv[2]->ptr,"one")) { if (server.masterhost) { sdsfree(server.masterhost); server.masterhost = NULL; if (server.master) freeClient(server.master); if (server.repl_state == REDIS_REPL_TRANSFER) replicationAbortSyncTransfer(); else if (server.repl_state == REDIS_REPL_CONNECTING || server.repl_state == REDIS_REPL_RECEIVE_PONG) undoConnectWithMaster(); server.repl_state = REDIS_REPL_NONE; redisLog(REDIS_NOTICE,"MASTER MODE enabled (user request)"); } } else { long port; if ((getLongFromObjectOrReply(c, c->argv[2], &port, NULL) != REDIS_OK)) return; /* Check if we are already attached to the specified slave */ if (server.masterhost && !strcasecmp(server.masterhost,c->argv[1]->ptr) && server.masterport == port) { redisLog(REDIS_NOTICE,"SLAVE OF would result into synchronization with the master we are already connected with. No operation performed."); addReplySds(c,sdsnew("+OK Already connected to specified master\r\n")); return; } /* There was no previous master or the user specified a different one, * we can continue. */ sdsfree(server.masterhost); server.masterhost = sdsdup(c->argv[1]->ptr); server.masterport = port; if (server.master) freeClient(server.master); disconnectSlaves(); /* Force our slaves to resync with us as well. */ if (server.repl_state == REDIS_REPL_TRANSFER) replicationAbortSyncTransfer(); server.repl_state = REDIS_REPL_CONNECT; redisLog(REDIS_NOTICE,"SLAVE OF %s:%d enabled (user request)", server.masterhost, server.masterport); } addReply(c,shared.ok); }
/* Use this function if the caller has already read the data. It will * feed bytes to the reply parser. * * After this function is called, you may use redisContextReadReply to * see if there is a reply available. */ int redisBufferReadDone(redisContext *c, char *buf, int nread) { if (nread == -1) { if (errno == EAGAIN && !(c->flags & REDIS_BLOCK)) { /* Try again later */ } else { __redisSetError(c,REDIS_ERR_IO,NULL); return REDIS_ERR; } } else if (nread == 0) { __redisSetError(c,REDIS_ERR_EOF, sdsnew("Server closed the connection")); return REDIS_ERR; } else { if (redisReaderFeed(c->reader,buf,nread) != REDIS_OK) { __redisSetError(c,c->reader->err,c->reader->errstr); return REDIS_ERR; } } return REDIS_OK; }
static int parse_options(int argc, char **argv) { int i; if (argc == 1) usage(); for (i = 1; i < argc; i++) { int lastarg = i==argc-1; if (!strcmp(argv[i],"-h") && !lastarg) { sdsfree(config.redd_ip); config.redd_ip = sdsnew(argv[++i]); } else if (!strcmp(argv[i],"-h") && lastarg) { usage(); } else if (!strcmp(argv[i],"--help")) { usage(); } else if (!strcmp(argv[i],"-p") && !lastarg) { config.redd_port = atoi(argv[++i]); } else if (!strcmp(argv[i],"-v") || !strcmp(argv[i], "--version")) { printf("red %s\n", RED_VERSION); exit(0); } else if (!strcmp(argv[i],"-y") || !strcmp(argv[i], "--yaml")) { config.yaml_out = 1; } else if (!strcmp(argv[i],"-n") || !strcmp(argv[i], "--nooutput")) { config.no_output = 1; } else { if (argv[i][0] == '-') { fprintf(stderr, "Unrecognized option or bad number of args for: '%s'\n", argv[i]); exit(1); } else { /* Likely the command name, stop here. */ break; } } } return i; }
void typeCommand(redisClient *c) { robj *o; char *type; o = lookupKeyRead(c->db,c->argv[1]); if (o == NULL) { type = "+none"; } else { switch(o->type) { case REDIS_STRING: type = "+string"; break; case REDIS_LIST: type = "+list"; break; case REDIS_SET: type = "+set"; break; case REDIS_ZSET: type = "+zset"; break; case REDIS_HASH: type = "+hash"; break; default: type = "+unknown"; break; } } addReplySds(c,sdsnew(type)); addReply(c,shared.crlf); }
/* Use this function to handle a read event on the descriptor. It will try * and read some bytes from the socket and feed them to the reply parser. * * After this function is called, you may use redisContextReadReply to * see if there is a reply available. */ int redisBufferRead(redisContext *c) { char buf[2048]; int nread = read(c->fd,buf,sizeof(buf)); if (nread == -1) { if (errno == EAGAIN && !(c->flags & REDIS_BLOCK)) { /* Try again later */ } else { __redisSetError(c,REDIS_ERR_IO,NULL); return REDIS_ERR; } } else if (nread == 0) { __redisSetError(c,REDIS_ERR_EOF, sdsnew("Server closed the connection")); return REDIS_ERR; } else { __redisCreateReplyReader(c); redisReplyReaderFeed(c->reader,buf,nread); } return REDIS_OK; }
static response *resolve_stream(const char *url) { request *request = http_get(url); response *response = http_send(request); if (http_read_body(response) < 0 && response->status != 302) { fprintf(stderr, "request failed %s", url); return NULL; } sds stream_url = sdsnew(http_header(response, "Location")); free_response(response); request = http_get(stream_url); response = http_send(request); sdsfree(stream_url); return response; }
void replicationFeedMonitors(redisClient *c, list *monitors, int dictid, robj **argv, int argc) { listNode *ln; listIter li; int j, port; sds cmdrepr = sdsnew("+"); robj *cmdobj; char ip[32]; struct timeval tv; gettimeofday(&tv,NULL); cmdrepr = sdscatprintf(cmdrepr,"%ld.%06ld ",(long)tv.tv_sec,(long)tv.tv_usec); if (c->flags & REDIS_LUA_CLIENT) { cmdrepr = sdscatprintf(cmdrepr,"[%d lua] ",dictid); } else if (c->flags & REDIS_UNIX_SOCKET) { cmdrepr = sdscatprintf(cmdrepr,"[%d unix:%s] ",dictid,server.unixsocket); } else { anetPeerToString(c->fd,ip,&port); cmdrepr = sdscatprintf(cmdrepr,"[%d %s:%d] ",dictid,ip,port); } for (j = 0; j < argc; j++) { if (argv[j]->encoding == REDIS_ENCODING_INT) { cmdrepr = sdscatprintf(cmdrepr, "\"%ld\"", (long)argv[j]->ptr); } else { cmdrepr = sdscatrepr(cmdrepr,(char*)argv[j]->ptr, sdslen(argv[j]->ptr)); } if (j != argc-1) cmdrepr = sdscatlen(cmdrepr," ",1); } cmdrepr = sdscatlen(cmdrepr,"\r\n",2); cmdobj = createObject(REDIS_STRING,cmdrepr); listRewind(monitors,&li); while((ln = listNext(&li))) { redisClient *monitor = ln->value; addReply(monitor,cmdobj); } decrRefCount(cmdobj); }
S triefort_open(TF ** const fort, const HCFG * const hashcfg, const char * const path) { NULLCHK(fort); NULLCHK(hashcfg); NULLCHK(path); S s; sds fortpath = sdsnew(path); sds cfgpath = sdsdup(fortpath); cfgpath = sdscat(cfgpath, "/" CONFIG_FILE_NAME); if (!file_exists(cfgpath)) { s = triefort_err_not_a_triefort; } else { *fort = calloc(1, sizeof(**fort)); TF * f = *fort; f->path = fortpath; // *fort takes ownership of `fortpath` f->hcfg = hashcfg; if (triefort_ok == (s = load_cfg(&f->cfg, cfgpath))) { if (!validate_cfg(&(*fort)->cfg)) { s = triefort_err_invalid_config; } if (0 != strncmp(hashcfg->fn_name, (*fort)->cfg.hash_name, MAX_LEN_HASH_NAME)) { s = triefort_err_hash_name_mismatch; } if (triefort_ok != s) { triefort_close(*fort); *fort = NULL; } } } sdsfree(cfgpath); return s; }
void cetcd_client_init(cetcd_client *cli, cetcd_array *addresses) { size_t i; cetcd_array *addrs; curl_global_init(CURL_GLOBAL_ALL); srand(time(0)); cli->keys_space = "v2/keys"; cli->stat_space = "v2/stat"; cli->member_space = "v2/members"; cli->curl = curl_easy_init(); addrs = cetcd_array_create(cetcd_array_size(addresses)); for (i=0; i<cetcd_array_size(addresses); ++i) { cetcd_array_append(addrs, sdsnew(cetcd_array_get(addresses, i))); } cli->addresses = cetcd_array_shuffle(addrs); cli->picked = rand() % (cetcd_array_size(cli->addresses)); cli->settings.verbose = 0; cli->settings.connect_timeout = 1; cli->settings.read_timeout = 1; /*not used now*/ cli->settings.write_timeout = 1; /*not used now*/ cetcd_array_init(&cli->watchers, 10); /* Set CURLOPT_NOSIGNAL to 1 to work around the libcurl bug: * http://stackoverflow.com/questions/9191668/error-longjmp-causes-uninitialized-stack-frame * http://curl.haxx.se/mail/lib-2008-09/0197.html * */ curl_easy_setopt(cli->curl, CURLOPT_NOSIGNAL, 1L); #if LIBCURL_VERSION_NUM >= 0x071900 curl_easy_setopt(cli->curl, CURLOPT_TCP_KEEPALIVE, 1L); curl_easy_setopt(cli->curl, CURLOPT_TCP_KEEPINTVL, 1L); /*the same as go-etcd*/ #endif curl_easy_setopt(cli->curl, CURLOPT_USERAGENT, "cetcd"); curl_easy_setopt(cli->curl, CURLOPT_POSTREDIR, 3L); /*post after redirecting*/ }
void slaveofCommand(redisClient *c) { if (!strcasecmp(c->argv[1]->ptr,"no") && !strcasecmp(c->argv[2]->ptr,"one")) { if (server.masterhost) {//已经是个slave了,需要关闭之 sdsfree(server.masterhost); server.masterhost = NULL; if (server.master) freeClient(server.master); cancelReplicationHandshake(); server.repl_state = REDIS_REPL_NONE; redisLog(REDIS_NOTICE,"MASTER MODE enabled (user request)"); } } else { long port; if ((getLongFromObjectOrReply(c, c->argv[2], &port, NULL) != REDIS_OK)) return; /* Check if we are already attached to the specified slave */ if (server.masterhost && !strcasecmp(server.masterhost,c->argv[1]->ptr) && server.masterport == port) { redisLog(REDIS_NOTICE,"SLAVE OF would result into synchronization with the master we are already connected with. No operation performed."); addReplySds(c,sdsnew("+OK Already connected to specified master\r\n")); return; } /* There was no previous master or the user specified a different one, * we can continue. */ sdsfree(server.masterhost); server.masterhost = sdsdup(c->argv[1]->ptr); server.masterport = port; if (server.master) freeClient(server.master);//直接关闭之前的master连接,readSyncBulkPayload接收完RDB文件会设置这个的。 disconnectSlaves(); /* Force our slaves to resync with us as well. */ cancelReplicationHandshake(); //下面设置这个的状态为需要连接master, 这样在serverCron定时任务会每秒调用replicationCron,进而会调用connectWithMaster进行重连的。 server.repl_state = REDIS_REPL_CONNECT; redisLog(REDIS_NOTICE,"SLAVE OF %s:%d enabled (user request)", server.masterhost, server.masterport); } addReply(c,shared.ok); }
cetcd_watcher *cetcd_watcher_create(cetcd_string key, uint64_t index, int recursive, int once, watcher_callback callback, void *userdata) { cetcd_watcher *watcher; watcher = calloc(1, sizeof(cetcd_watcher)); watcher->key = sdsnew(key); watcher->index = index; watcher->recursive = recursive; watcher->once = once; watcher->callback = callback; watcher->userdata = userdata; watcher->curl = curl_easy_init(); watcher->parser = calloc(1, sizeof(cetcd_response_parser)); watcher->parser->st = 0; watcher->parser->buf = sdsempty(); watcher->parser->resp = calloc(1, sizeof(cetcd_response)); watcher->array_index = -1; return watcher; }
int main(int argc, char **argv) { int firstarg, j; char **argvcopy; struct redisCommand *rc; config.hostip = "127.0.0.1"; config.hostport = 6379; config.repeat = 1; firstarg = parseOptions(argc,argv); argc -= firstarg; argv += firstarg; /* Turn the plain C strings into Sds strings */ argvcopy = zmalloc(sizeof(char*)*argc+1); for(j = 0; j < argc; j++) argvcopy[j] = sdsnew(argv[j]); if (argc < 1) { fprintf(stderr, "usage: redis-cli [-h host] [-p port] [-r repeat_times] cmd arg1 arg2 arg3 ... argN\n"); fprintf(stderr, "usage: echo \"argN\" | redis-cli [-h host] [-p port] -r [repeat_times] cmd arg1 arg2 ... arg(N-1)\n"); fprintf(stderr, "\nIf a pipe from standard input is detected this data is used as last argument.\n\n"); fprintf(stderr, "example: cat /etc/passwd | redis-cli set my_passwd\n"); fprintf(stderr, "example: redis-cli get my_passwd\n"); fprintf(stderr, "example: redis-cli -r 100 lpush mylist x\n"); exit(1); } /* Read the last argument from stdandard input if needed */ if ((rc = lookupCommand(argv[0])) != NULL) { if (rc->arity > 0 && argc == rc->arity-1) { sds lastarg = readArgFromStdin(); argvcopy[argc] = lastarg; argc++; } } return cliSendCommand(argc, argvcopy); }
static int slotsmgrt_get_socket(redisClient *c, sds host, sds port, int timeout) { sds name = sdsempty(); name = sdscatlen(name, host, sdslen(host)); name = sdscatlen(name, ":", 1); name = sdscatlen(name, port, sdslen(port)); slotsmgrt_sockfd *pfd = dictFetchValue(server.slotsmgrt_cached_sockfds, name); if (pfd != NULL) { sdsfree(name); pfd->lasttime = server.unixtime; return pfd->fd; } int fd = anetTcpNonBlockConnect(server.neterr, host, atoi(port)); if (fd == -1) { redisLog(REDIS_WARNING, "slotsmgrt: connect to target %s:%s, error = '%s'", host, port, server.neterr); sdsfree(name); addReplyErrorFormat(c,"Can't connect to target node: %s", server.neterr); return -1; } anetEnableTcpNoDelay(server.neterr, fd); if ((aeWait(fd, AE_WRITABLE, timeout) & AE_WRITABLE) == 0) { redisLog(REDIS_WARNING, "slotsmgrt: connect to target %s:%s, aewait error = '%s'", host, port, server.neterr); sdsfree(name); close(fd); addReplySds(c, sdsnew("-IOERR error or timeout connecting to the client\r\n")); return -1; } redisLog(REDIS_WARNING, "slotsmgrt: connect to target %s:%s", host, port); pfd = zmalloc(sizeof(*pfd)); pfd->fd = fd; pfd->lasttime = server.unixtime; dictAdd(server.slotsmgrt_cached_sockfds, name, pfd); return fd; }
static int process_command(sub_client *c) { srv_log(LOG_DEBUG, "c->argv[0]: %s", c->argv[0]); sds name = sdsnew(c->argv[0]); sdstolower(name); sub_command *cmd = ght_get(server.sub_commands, sdslen(name), name); if (!cmd) { add_reply_error_fmt(c, "unknown command '%s'", name); } else if ((cmd->arity > 0 && cmd->arity != c->argc) || (c->argc < -cmd->arity)) { add_reply_error_fmt(c, "wrong number of arguments for '%s' command", name); } else { srv_log(LOG_DEBUG, "cmd name: %s arity: %d", cmd->name, cmd->arity); cmd->proc(c); } sdsfree(name); return SUBCLI_OK; }
void parg_asset_preload(parg_token id) { if (!_pngsuffix) { _pngsuffix = sdsnew(".png"); } sds filename = parg_token_to_sds(id); parg_buffer* buf = parg_buffer_from_path(filename); parg_assert(buf, "Unable to load asset"); if (sdslen(filename) > 4) { sds suffix = sdsdup(filename); sdsrange(suffix, -4, -1); if (!sdscmp(suffix, _pngsuffix)) { unsigned char* decoded; unsigned dims[3] = {0, 0, 4}; unsigned char* filedata = parg_buffer_lock(buf, PARG_READ); unsigned err = lodepng_decode_memory(&decoded, &dims[0], &dims[1], filedata, parg_buffer_length(buf), LCT_RGBA, 8); parg_assert(err == 0, "PNG decoding error"); parg_buffer_free(buf); int nbytes = dims[0] * dims[1] * dims[2]; buf = parg_buffer_alloc(nbytes + 12, PARG_CPU); int* ptr = parg_buffer_lock(buf, PARG_WRITE); *ptr++ = dims[0]; *ptr++ = dims[1]; *ptr++ = dims[2]; memcpy(ptr, decoded, nbytes); free(decoded); parg_buffer_unlock(buf); } sdsfree(suffix); } if (!_asset_registry) { _asset_registry = kh_init(assmap); } int ret; int iter = kh_put(assmap, _asset_registry, id, &ret); kh_value(_asset_registry, iter) = buf; }
void server_accept_client(struct evconnlistener *listener, evutil_socket_t sock, struct sockaddr *addr, int len, void *ptr) { int port = ntohs(((struct sockaddr_in*)addr)->sin_port); sds ip = sdsnew(inet_ntoa(((struct sockaddr_in*)addr)->sin_addr)); server.client_connected++; log_info("Accepted client socket from %s:%d, current[%d], max[%d], total[%"PRIu64"]", ip, port, server.client_current + 1, server.client_max, server.client_connected); if(server.client_current >= server.client_max) { ssize_t wl; log_warn("Reached max connection: %d, client will be closed.", server.client_current + 1); sds msg = sdscatprintf(sdsempty(), "%s 1%sMax connection error.", ZR_CMD_REP_ERR, ZR_MSG_NL); wl = write(sock, msg, sdslen(msg)); sdsfree(msg); close(sock); return; } //struct client *c = client_alloc(sock, (struct sockaddr_in*)addr); client_alloc(sock, (struct sockaddr_in*)addr); }
int main(int argc, const char **argv) { int i; char *data, *cmd; int len; client c; signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); config.numclients = 50; config.requests = 10000; config.liveclients = 0; config.el = aeCreateEventLoop(1024*10); aeCreateTimeEvent(config.el,1,showThroughput,NULL,NULL); config.keepalive = 1; config.datasize = 3; config.pipeline = 1; config.randomkeys = 0; config.randomkeys_keyspacelen = 0; config.quiet = 0; config.csv = 0; config.loop = 0; config.idlemode = 0; config.latency = NULL; config.clients = listCreate(); config.hostip = "127.0.0.1"; config.hostport = 6379; config.hostsocket = NULL; config.tests = NULL; config.dbnum = 0; i = parseOptions(argc,argv); argc -= i; argv += i; // printf ("SET PAGE POOL SIZE\n"); // set_page_pool_size(config.requests); config.latency = zmalloc(sizeof(long long)*config.requests); if (config.keepalive == 0) { printf("WARNING: keepalive disabled, you probably need 'echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse' for Linux and 'sudo sysctl -w net.inet.tcp.msl=1000' for Mac OS X in order to use a lot of clients/requests\n"); } if (config.idlemode) { printf("Creating %d idle connections and waiting forever (Ctrl+C when done)\n", config.numclients); c = createClient("",0,NULL); /* will never receive a reply */ createMissingClients(c); aeMain(config.el); /* and will wait for every */ } /* Run benchmark with command in the remainder of the arguments. */ if (argc) { sds title = sdsnew(argv[0]); for (i = 1; i < argc; i++) { title = sdscatlen(title, " ", 1); title = sdscatlen(title, (char*)argv[i], strlen(argv[i])); } do { len = redisFormatCommandArgv(&cmd,argc,argv,NULL); benchmark(title,cmd,len); free(cmd); } while(config.loop); return 0; } /* Run default benchmark suite. */ do { data = zmalloc(config.datasize+1); memset(data,'x',config.datasize); data[config.datasize] = '\0'; if (test_is_selected("ping_inline") || test_is_selected("ping")) benchmark("PING_INLINE","PING\r\n",6); if (test_is_selected("ping_mbulk") || test_is_selected("ping")) { len = redisFormatCommand(&cmd,"PING"); benchmark("PING_BULK",cmd,len); free(cmd); } if (test_is_selected("set")) { len = redisFormatCommand(&cmd,"SET key:__rand_int__ %s",data); benchmark("SET",cmd,len); free(cmd); } if (test_is_selected("get")) { len = redisFormatCommand(&cmd,"GET key:__rand_int__"); benchmark("GET",cmd,len); free(cmd); } if (test_is_selected("incr")) { len = redisFormatCommand(&cmd,"INCR counter:__rand_int__"); benchmark("INCR",cmd,len); free(cmd); } if (test_is_selected("lpush")) { len = redisFormatCommand(&cmd,"LPUSH mylist %s",data); benchmark("LPUSH",cmd,len); free(cmd); } if (test_is_selected("lpop")) { len = redisFormatCommand(&cmd,"LPOP mylist"); benchmark("LPOP",cmd,len); free(cmd); } if (test_is_selected("sadd")) { len = redisFormatCommand(&cmd, "SADD myset element:__rand_int__"); benchmark("SADD",cmd,len); free(cmd); } if (test_is_selected("spop")) { len = redisFormatCommand(&cmd,"SPOP myset"); benchmark("SPOP",cmd,len); free(cmd); } if (test_is_selected("lrange") || test_is_selected("lrange_100") || test_is_selected("lrange_300") || test_is_selected("lrange_500") || test_is_selected("lrange_600")) { len = redisFormatCommand(&cmd,"LPUSH mylist %s",data); benchmark("LPUSH (needed to benchmark LRANGE)",cmd,len); free(cmd); } if (test_is_selected("lrange") || test_is_selected("lrange_100")) { len = redisFormatCommand(&cmd,"LRANGE mylist 0 99"); benchmark("LRANGE_100 (first 100 elements)",cmd,len); free(cmd); } if (test_is_selected("lrange") || test_is_selected("lrange_300")) { len = redisFormatCommand(&cmd,"LRANGE mylist 0 299"); benchmark("LRANGE_300 (first 300 elements)",cmd,len); free(cmd); } if (test_is_selected("lrange") || test_is_selected("lrange_500")) { len = redisFormatCommand(&cmd,"LRANGE mylist 0 449"); benchmark("LRANGE_500 (first 450 elements)",cmd,len); free(cmd); } if (test_is_selected("lrange") || test_is_selected("lrange_600")) { len = redisFormatCommand(&cmd,"LRANGE mylist 0 599"); benchmark("LRANGE_600 (first 600 elements)",cmd,len); free(cmd); } if (test_is_selected("mset")) { const char *argv[21]; argv[0] = "MSET"; for (i = 1; i < 21; i += 2) { argv[i] = "key:__rand_int__"; argv[i+1] = data; } len = redisFormatCommandArgv(&cmd,21,argv,NULL); benchmark("MSET (10 keys)",cmd,len); free(cmd); } if (!config.csv) printf("\n"); } while(config.loop); return 0; }