int resloveMessage(char **msg, vuiClient *c) { char *buf; char *body; int left; buf = *msg; body = strstr(buf, "\r\n\r\n"); if (NULL == body)return -2;//continue read //头部没有结束 body = body + 4; c->querymsg = sdscpylen(c->querymsg, buf, body - buf); if (0 != resolveHeader(c->querymsg, &c->prot)){ *msg = body; return -1; } left = sdslen(c->querybuf) - (body - c->querybuf); if (c->prot.lenght <= left) { c->querymsg = sdscatlen(c->querymsg, body, c->prot.lenght); *msg = body + c->prot.lenght; return 0; } c->prot.waiting = c->prot.lenght - left; c->querymsg = sdscat(c->querymsg, body); return -3; }
/* Define a lua function with the specified function name and body. * The function name musts be a 2 characters long string, since all the * functions we defined in the Lua context are in the form: * * f_<hex sha1 sum> * * On success REDIS_OK is returned, and nothing is left on the Lua stack. * On error REDIS_ERR is returned and an appropriate error is set in the * client context. */ int luaCreateFunction(redisClient *c, lua_State *lua, char *funcname, robj *body) { sds funcdef = sdsempty(); funcdef = sdscat(funcdef,"function "); funcdef = sdscatlen(funcdef,funcname,42); funcdef = sdscatlen(funcdef,"() ",3); funcdef = sdscatlen(funcdef,body->ptr,sdslen(body->ptr)); funcdef = sdscatlen(funcdef," end",4); if (luaL_loadbuffer(lua,funcdef,sdslen(funcdef),"@user_script")) { addReplyErrorFormat(c,"Error compiling script (new function): %s\n", lua_tostring(lua,-1)); lua_pop(lua,1); sdsfree(funcdef); return REDIS_ERR; } sdsfree(funcdef); if (lua_pcall(lua,0,0,0)) { addReplyErrorFormat(c,"Error running script (new function): %s\n", lua_tostring(lua,-1)); lua_pop(lua,1); return REDIS_ERR; } /* We also save a SHA1 -> Original script map in a dictionary * so that we can replicate / write in the AOF all the * EVALSHA commands as EVAL using the original script. */ { int retval = dictAdd(server.lua_scripts, sdsnewlen(funcname+2,40),body); redisAssertWithInfo(c,NULL,retval == DICT_OK); incrRefCount(body); } return REDIS_OK; }
sds sdscatvprintf(sds s, const char *fmt, va_list ap) { va_list cpy; char *buf, *t; size_t buflen = 16; while(1) { buf = zmalloc(buflen); #ifdef SDS_ABORT_ON_OOM if (buf == NULL) sdsOomAbort(); #else if (buf == NULL) return NULL; #endif buf[buflen-2] = '\0'; va_copy(cpy,ap); vsnprintf(buf, buflen, fmt, cpy); if (buf[buflen-2] != '\0') { zfree(buf); buflen *= 2; continue; } break; } t = sdscat(s, buf); zfree(buf); return t; }
/** * Takes partial tags and replaces them with a parsed partial template. * * @param sds tag The tag * * @retval sds buff Partial template buffer. */ static sds tag_partial(sds tag) { puts("tag_partial"); printf("tag found: '%s'\n",tag); sds re = sdsempty(); sds f = sdsempty(); sds buff = sdsempty(); re = sdscatprintf(re, "%s>([^}]+)%s", ldelim, rdelim); struct slre_cap caps[1]; if (slre_match(re, tag, strlen(tag), caps, 1) > 0) { f = sdscatprintf(f,"%.*s", caps[0].len, caps[0].ptr); sdstrim(f," "); sds fname = sdscatprintf(sdsempty(),"%s%s", tpldir, f); fname = sdscat(fname,tplext); //puts(fname); FILE * fp; if ((fp = fopen(fname, "r")) != NULL) { fclose(fp); buff = render_template(f); } puts("free fname"); sdsfree(fname); } puts("free f"); sdsfree(f); // //sdsfree(buff); puts("free re"); sdsfree(re); return buff; }
const char * TTF_BreakString(int w, const char *in) { TTFtextRow rows[2]; int nrows = 0, i; int oldAlign = state.align; int halign = state.align & (FONS_ALIGN_LEFT | FONS_ALIGN_CENTER | FONS_ALIGN_RIGHT); int valign = state.align & (FONS_ALIGN_TOP | FONS_ALIGN_MIDDLE | FONS_ALIGN_BOTTOM | FONS_ALIGN_BASELINE); float lineh; fonsVertMetrics(ctx, nullptr, nullptr, &lineh); fonsSetAlign(ctx, FONS_ALIGN_LEFT | valign); if (splitStr != nullptr) { sdsfree(splitStr); } splitStr = sdsempty(); while ((nrows = TTF_BreakLines(in, nullptr, w, rows, 2)) > 0) { for (i = 0; i < nrows; i++) { TTFtextRow* row = &rows[i]; splitStr = sdscatlen(splitStr, row->start, row->end - row->start); splitStr = sdscat(splitStr, "\n"); } in = rows[nrows - 1].next; } fonsSetAlign(ctx, oldAlign); return splitStr; }
/** * concat some format characters after s, * the format likes the parameter of printf */ sds sdscatprintf(sds s, const char *fmt, ...) { /* ap : va_list */ va_list ap; char *buf, *t; /* start buf size */ size_t buflen = 32; /* look for a suffient buf size */ while(1) { buf = zmalloc(buflen); #ifdef SDS_ABORT_ON_OOM if (buf == NULL) sdsOomAbort(); #else if (buf == NULL) return NULL; #endif buf[buflen-2] = '\0'; /* print the format string to buf */ va_start(ap, fmt); vsnprintf(buf, buflen, fmt, ap); va_end(ap); /* if buf isn't bigger enough to hold the format string * keeping on looking*/ if (buf[buflen-2] != '\0') { zfree(buf); buflen *= 2; continue; } break; } /* concat the format string after s */ t = sdscat(s, buf); /* free the memory we allocated before */ zfree(buf); return t; }
static void completionCallback(const char *buf, linenoiseCompletions *lc) { size_t startpos = 0; int mask; int i; size_t matchlen; sds tmp; if (strncasecmp(buf,"help ",5) == 0) { startpos = 5; while (isspace(buf[startpos])) startpos++; mask = CLI_HELP_COMMAND | CLI_HELP_GROUP; } else { mask = CLI_HELP_COMMAND; } for (i = 0; i < helpEntriesLen; i++) { if (!(helpEntries[i].type & mask)) continue; matchlen = strlen(buf+startpos); if (strncasecmp(buf+startpos,helpEntries[i].full,matchlen) == 0) { tmp = sdsnewlen(buf,startpos); tmp = sdscat(tmp,helpEntries[i].full); linenoiseAddCompletion(lc,tmp); sdsfree(tmp); } } }
static sds cliFormatReplyRaw(redisReply *r) { sds out = sdsempty(), tmp; size_t i; switch (r->type) { case REDIS_REPLY_NIL: /* Nothing... */ break; case REDIS_REPLY_ERROR: case REDIS_REPLY_STATUS: case REDIS_REPLY_STRING: out = sdscatlen(out,r->str,r->len); break; case REDIS_REPLY_INTEGER: out = sdscatprintf(out,"%lld",r->integer); break; case REDIS_REPLY_ARRAY: for (i = 0; i < r->elements; i++) { if (i > 0) out = sdscat(out,config.mb_delim); tmp = cliFormatReplyRaw(r->element[i]); out = sdscatlen(out,tmp,sdslen(tmp)); sdsfree(tmp); } break; default: fprintf(stderr,"Unknown reply type: %d\n", r->type); exit(1); } return out; }
S triefort_put(TF * fort, const void * const buffer, const size_t bufferlen, void * const hash) { NULLCHK(fort); NULLCHK(buffer); NULLCHK(hash); const size_t hashlen = fort->cfg.hash_len; triefort_hasher_fn * hfn = fort->hcfg->hasher; if (0 != hfn(hash, hashlen, buffer, bufferlen)) { return triefort_err_hasher_error; } sds sdata_path = NULL; PANIC_IF(triefort_ok != mk_trie_dirs(fort, hash, hashlen, &sdata_path)); sdata_path = sdscat(sdata_path, "/triefort.data"); S s = triefort_ok; if (file_exists(sdata_path)) { s = triefort_err_hash_already_exists; } else { if (!file_exists(sdata_path)) { s = write_file(sdata_path, buffer, bufferlen); } } sdsfree(sdata_path); return s; }
void destor_shutdown() { sds stat_file = sdsdup(destor.working_directory); stat_file = sdscat(stat_file, "/destor.stat"); FILE *fp; if ((fp = fopen(stat_file, "w")) == 0) { destor_log(DESTOR_WARNING, "Fatal error, can not open destor.stat!"); exit(1); } fwrite(&destor.chunk_num, 8, 1, fp); fwrite(&destor.stored_chunk_num, 8, 1, fp); fwrite(&destor.data_size, 8, 1, fp); fwrite(&destor.stored_data_size, 8, 1, fp); fwrite(&destor.zero_chunk_num, 8, 1, fp); fwrite(&destor.zero_chunk_size, 8, 1, fp); fwrite(&destor.rewritten_chunk_num, 8, 1, fp); fwrite(&destor.rewritten_chunk_size, 8, 1, fp); fwrite(&destor.index_memory_footprint, 4, 1, fp); fwrite(&destor.live_container_num, 4, 1, fp); fwrite(&destor.backup_retention_time, 4, 1, fp); fwrite(&destor.simulation_level, 4, 1, fp); fclose(fp); sdsfree(stat_file); }
void call_bridge_event(struct redisClient *c,int triggle_place,int event_type) { if(event_type==-1) { sds cmds=(sds)sdsdup(c->argv[0]->ptr); sdstolower(cmds); if(triggle_place==TRIGGLE_BEFORE) //no event given { cmds=sdscat(cmds,"ing"); } if(triggle_place==TRIGGLE_AFTER) { cmds=sdscat(cmds,"ed"); } event_type=process_trigglecmd(cmds); // redisLog(REDIS_NOTICE,"cmds:%s id:%d",cmds,event_type); sdsfree(cmds); } if(event_type==-1) return; struct dictIterator *iter=dictGetIterator(server.bridge_db.triggle_scipts[c->db->id]); dictEntry *trigs; do{ trigs=dictNext(iter); if(trigs!=NULL) { struct bridge_db_triggle_t * tmptrg=dictGetVal(trigs); if(tmptrg->event==event_type&&strncmp(c->argv[1]->ptr,dictGetKey(trigs),sdslen(dictGetKey(trigs)))==0){ //找到指定的类型事件 //if(tmptrg->event==event_type){ //找到指定的类型事件 // redisLog(REDIS_NOTICE,"triggle_event:%d,%s",event_type,(char *)dictGetKey(trigs)); triggle_event(c,dictGetKey(trigs)); } } }while(trigs!=NULL); dictReleaseIterator(iter); }
void update_manifest(GHashTable *monitor){ GHashTable *manifest = g_hash_table_new_full(g_int64_hash, g_int64_equal, NULL, free); sds fname = sdsdup(destor.working_directory); fname = sdscat(fname, "/manifest"); FILE *fp = NULL; if((fp = fopen(fname, "r"))){ /* file exists. Reconstruct the manifest from the file. */ struct record tmp; while(fscanf(fp, "%lld,%d", &tmp.id, &tmp.time) == 2){ struct record* rec = (struct record*) malloc(sizeof(struct record)); rec->id = tmp.id; rec->time = tmp.time; g_hash_table_insert(manifest, &rec->id, rec); } DEBUG("CMA: read %d records.", g_hash_table_size(manifest)); fclose(fp); } /* Update the backup times in the manifest. */ GHashTableIter iter; gpointer key, value; g_hash_table_iter_init(&iter, monitor); while(g_hash_table_iter_next(&iter, &key, &value)){ /* the key is a pointer to a container ID. */ struct record *r = g_hash_table_lookup(manifest, key); if(!r){ r = (struct record*) malloc(sizeof(struct record)); r->id = *(containerid*)key; g_hash_table_insert(manifest, &r->id, r); } r->time = jcr.id; } /* Flush the manifest */ if((fp = fopen(fname, "w"))){ /* Update the manifest into the file. */ g_hash_table_iter_init(&iter, manifest); while(g_hash_table_iter_next(&iter, &key, &value)){ struct record* r = value; fprintf(fp, "%lld,%d\n", r->id, r->time); } DEBUG("CMA: update %d records.", g_hash_table_size(manifest)); fclose(fp); }else{ WARNING("Cannot create the manifest!"); exit(1); } destor.live_container_num = g_hash_table_size(manifest); g_hash_table_destroy(manifest); sdsfree(fname); }
int parg_asset_download(const char* filename, sds targetpath) { sds baseurl = parg_asset_baseurl(); sds fullurl = sdscat(sdsdup(baseurl), filename); printf("Downloading %s...\n", fullurl); return par_easycurl_to_file(fullurl, targetpath); return 0; }
SDS create_sds(const SDS content) { SDSHDR *sh = NULL; SDS s = NULL; s = _expand_room_for_sds(sh->buf, strlen(content)); sdscat(&s, content); return s; }
S triefort_put_with_key(TF * fort, const void * const key, const size_t keylen, const void * const buffer, const size_t bufferlen, void * const hash) { NULLCHK(fort); NULLCHK(key); NULLCHK(buffer); NULLCHK(hash); if (keylen > fort->cfg.max_key_len) { return triefort_err_key_too_long; } triefort_hasher_fn * hfn = fort->hcfg->hasher; const size_t hashlen = fort->cfg.hash_len; if (0 != hfn(hash, hashlen, key, keylen)) { return triefort_err_hasher_error; } S s; sds dir_path = NULL; PANIC_IF(triefort_ok != mk_trie_dirs(fort, hash, hashlen, &dir_path)); sds skey_path = sdsdup(dir_path); sds sdata_path = sdsdup(dir_path); sdata_path = sdscat(sdata_path, "/triefort.data"); skey_path = sdscat(skey_path, "/triefort.key"); if (file_exists(sdata_path)) { s = triefort_err_hash_already_exists; } else { s = write_file(skey_path, key, keylen); if (triefort_ok == s) { s = write_file(sdata_path, buffer, bufferlen); } } sdsfree(skey_path); sdsfree(sdata_path); sdsfree(dir_path); return s; }
/* * Be called when users delete backups in FIFO order. * Delete all backups earlier than jobid. * All container IDs with a time smaller than or equal to jobid can be removed. * Return these IDs. */ GHashTable* trunc_manifest(int jobid){ /* The containers we reclaim */ GHashTable *invalid_containers = g_hash_table_new_full(g_int64_hash, g_int64_equal, free, NULL); GHashTable *manifest = g_hash_table_new_full(g_int64_hash, g_int64_equal, NULL, free); sds fname = sdsdup(destor.working_directory); fname = sdscat(fname, "/manifest"); FILE *fp = NULL; if((fp = fopen(fname, "r"))){ /* file exists. Reconstruct the manifest from the file. */ struct record tmp; while(fscanf(fp, "%lld,%d", &tmp.id, &tmp.time) == 2){ struct record* rec = (struct record*) malloc(sizeof(struct record)); if(tmp.time <= jobid){ /* This record can be removed. */ containerid *cid = (containerid*) malloc(sizeof(containerid)); *cid = tmp.id; g_hash_table_insert(invalid_containers, cid, NULL); NOTICE("CMA: container %lld can be reclaimed.", cid); }else{ /* This record remains valid. */ rec->id = tmp.id; rec->time = tmp.time; g_hash_table_insert(manifest, &rec->id, rec); } } NOTICE("CMA: %d of records are valid.", g_hash_table_size(manifest)); NOTICE("CMA: %d of records are going to be reclaimed.", g_hash_table_size(invalid_containers)); fclose(fp); }else{ NOTICE("manifest doesn't exist!"); exit(1); } if((fp = fopen(fname, "w"))){ GHashTableIter iter; gpointer key, value; g_hash_table_iter_init(&iter, manifest); while(g_hash_table_iter_next(&iter, &key, &value)){ struct record* rec = value; fprintf(fp, "%lld,%d\n", rec->id, rec->time); } fclose(fp); }else{ WARNING("CMA: cannot create manifest!"); exit(1); } destor.live_container_num = g_hash_table_size(manifest); g_hash_table_destroy(manifest); return invalid_containers; }
void init_recipe_store() { recipepath = sdsdup(destor.working_directory); recipepath = sdscat(recipepath, "/recipes/"); sds count_fname = sdsdup(recipepath); count_fname = sdscat(count_fname, "backupversion.count"); FILE *fp; if ((fp = fopen(count_fname, "r"))) { /* Read if exists. */ fread(&backup_version_count, 4, 1, fp); fclose(fp); } sdsfree(count_fname); NOTICE("Init recipe store successfully"); }
/* Join an array of C strings using the specified separator (also a C string). * Returns the result as an sds string. */ sds sdsjoin(char **argv, int argc, char *sep, size_t seplen) { sds join = sdsempty(); int j; for (j = 0; j < argc; j++) { join = sdscat(join, argv[j]); if (j != argc-1) join = sdscatlen(join,sep,seplen); } return join; }
void init_har() { /* Monitor the utilizations of containers */ container_utilization_monitor = g_hash_table_new_full( g_int64_hash, g_int64_equal, NULL, free); /* IDs of inherited sparse containers */ inherited_sparse_containers = g_hash_table_new_full(g_int64_hash, g_int64_equal, NULL, free); /* The first backup doesn't have inherited sparse containers. */ if (jcr.id > 0) { sds fname = sdsdup(destor.working_directory); fname = sdscat(fname, "recipes/bv"); char s[20]; sprintf(s, "%d", jcr.id - 1); fname = sdscat(fname, s); fname = sdscat(fname, ".sparse"); FILE* sparse_file = fopen(fname, "r"); if (sparse_file) { char buf[128]; while (fgets(buf, 128, sparse_file) != NULL) { struct containerRecord *record = (struct containerRecord*) malloc( sizeof(struct containerRecord)); sscanf(buf, "%lld %d", &record->cid, &record->size); g_hash_table_insert(inherited_sparse_containers, &record->cid, record); } fclose(sparse_file); } sdsfree(fname); } NOTICE("Read %d inherited sparse containers", g_hash_table_size(inherited_sparse_containers)); }
parg_buffer* parg_buffer_from_path(const char* filename) { #if EMSCRIPTEN sds baseurl = parg_asset_baseurl(); sds fullurl = sdscat(sdsdup(baseurl), filename); parg_buffer* retval = 0; printf("TODO: download %s here\n", fullurl); sdsfree(fullurl); #else sds execdir = parg_asset_whereami(); sds fullpath = sdscat(sdsdup(execdir), filename); if (!parg_asset_fileexists(fullpath)) { parg_asset_download(filename, fullpath); } parg_buffer* retval = parg_buffer_from_file(fullpath); sdsfree(fullpath); #endif return retval; }
static S mk_info_from_path(const TF * const fort, sds path, const void * const hash, INFO ** info) { sds data_path = sdsdup(path); sds key_path = sdsdup(path); data_path = sdscat(data_path, "/triefort.data"); key_path = sdscat(key_path, "/triefort.key"); S status = triefort_ok; if (file_exists(data_path)) { struct stat s; PANIC_IF(0 != stat(data_path, &s)); *info = calloc(1, sizeof(**info)); INFO * inf = *info; inf->hash = calloc(1, fort->cfg.hash_len); memcpy(inf->hash, hash, fort->cfg.hash_len); inf->hashlen = fort->cfg.hash_len; inf->length = s.st_size; if (file_exists(key_path)) { FILE * kh = fopen(key_path, "rb"); PANIC_IF(NULL == kh); PANIC_IF(0 != fstat(fileno(kh), &s)); inf->keylen = s.st_size; inf->key = calloc(1, s.st_size); PANIC_IF(1 != fread(inf->key, s.st_size, 1, kh)); fclose(kh); } else { inf->keylen = 0; inf->key = NULL; } } else { status = triefort_err_hash_does_not_exist; } sdsfree(data_path); sdsfree(key_path); return status; }
/** * Replaces the string `search` with `replace` in string `sds` * * @param sds str The string to be manipulated * @param sds search The search string * @param char *replace The replacement string * * @retval sds str The manipulated string. */ static sds sdsreplace(sds str, sds search, char *replace) { puts("sdsreplace"); sds buff = sdsempty(); char *p; if (!(p = strstr(str, search))) return str; buff = sdscatlen(buff, str, p-str); if (replace != NULL) { buff = sdscat(buff, replace); } buff = sdscat(buff, p+sdslen(search)); //sdsfree(search); str = sdscpylen(str,buff,sdslen(buff)); puts("free buff"); //sdsfree(buff); return str; }
static sds mk_hash_str(const void * const hash, const size_t hashlen) { const uint8_t * const hashb = hash; char node[3] = { 0 }; sds hs = sdsempty(); for (size_t i = 0; i < hashlen; i++) { snprintf(node, sizeof(node), "%02x", hashb[i]); hs = sdscat(hs, node); } return hs; }
static int cliSendCommand(int argc, char **argv) { struct redisCommand *rc = lookupCommand(argv[0]); int fd, j, retval = 0; sds cmd = sdsempty(); if (!rc) { fprintf(stderr,"Unknown command '%s'\n",argv[0]); return 1; } if ((rc->arity > 0 && argc != rc->arity) || (rc->arity < 0 && argc < -rc->arity)) { fprintf(stderr,"Wrong number of arguments for '%s'\n",rc->name); return 1; } if ((fd = cliConnect()) == -1) return 1; /* Build the command to send */ for (j = 0; j < argc; j++) { if (j != 0) cmd = sdscat(cmd," "); if (j == argc-1 && rc->flags & REDIS_CMD_BULK) { cmd = sdscatprintf(cmd,"%d",sdslen(argv[j])); } else { cmd = sdscatlen(cmd,argv[j],sdslen(argv[j])); } } cmd = sdscat(cmd,"\r\n"); if (rc->flags & REDIS_CMD_BULK) { cmd = sdscatlen(cmd,argv[argc-1],sdslen(argv[argc-1])); cmd = sdscat(cmd,"\r\n"); } anetWrite(fd,cmd,sdslen(cmd)); retval = cliReadReply(fd); if (retval) { close(fd); return retval; } close(fd); return 0; }
static sds trie_dir_path(const TF * const fort, const void * const hash, const char * filename) { const size_t width = fort->cfg.width; const size_t depth = fort->cfg.depth; const size_t hashlen = fort->cfg.hash_len; const uint8_t * const hashb = hash; char dir_node[(width * 2) + 2]; sds path = sdsdup(fort->path); for (size_t i = 0; i < depth; i++) { path = sdscat(path, "/"); for (size_t j = 0; j < width; j++) { char * strpos = &dir_node[j * 2]; size_t hashix = (i * width) + j; snprintf(strpos, 3, "%02x", hashb[hashix]); } path = sdscat(path, dir_node); } path = sdscat(path, "/"); sds shash = mk_hash_str(hash, hashlen); path = sdscat(path, shash); sdsfree(shash); if (NULL != filename) { path = sdscat(path, "/"); path = sdscat(path, filename); } return path; }
void close_kvstore_htable() { sds indexpath = sdsdup(destor.working_directory); indexpath = sdscat(indexpath, "index/htable"); FILE *fp; if ((fp = fopen(indexpath, "w")) == NULL) { perror("Can not open index/htable for write because:"); exit(1); } NOTICE("flushing hash table!"); int key_num = g_hash_table_size(htable); fwrite(&key_num, sizeof(int), 1, fp); GHashTableIter iter; gpointer key, value; g_hash_table_iter_init(&iter, htable); while (g_hash_table_iter_next(&iter, &key, &value)) { /* Write a feature. */ kvpair kv = value; if(fwrite(get_key(kv), destor.index_key_size, 1, fp) != 1){ perror("Fail to write a key!"); exit(1); } /* Write the number of segments/containers */ if(fwrite(&destor.index_value_length, sizeof(int), 1, fp) != 1){ perror("Fail to write a length!"); exit(1); } int i; for (i = 0; i < destor.index_value_length; i++) if(fwrite(&get_value(kv)[i], sizeof(int64_t), 1, fp) != 1){ perror("Fail to write a value!"); exit(1); } } /* It is a rough estimation */ destor.index_memory_footprint = g_hash_table_size(htable) * (destor.index_key_size + sizeof(int64_t) * destor.index_value_length + 4); fclose(fp); NOTICE("flushing hash table successfully!"); sdsfree(indexpath); g_hash_table_destroy(htable); }
void init_jcr(char *path) { jcr.path = sdsnew(path); struct stat s; if (stat(path, &s) != 0) { fprintf(stderr, "backup path does not exist!"); exit(1); } if (S_ISDIR(s.st_mode) && jcr.path[sdslen(jcr.path) - 1] != '/') jcr.path = sdscat(jcr.path, "/"); jcr.bv = NULL; jcr.id = TEMPORARY_ID; jcr.status = JCR_STATUS_INIT; jcr.file_num = 0; jcr.data_size = 0; jcr.unique_data_size = 0; jcr.chunk_num = 0; jcr.unique_chunk_num = 0; jcr.zero_chunk_num = 0; jcr.zero_chunk_size = 0; jcr.rewritten_chunk_num = 0; jcr.rewritten_chunk_size = 0; jcr.sparse_container_num = 0; jcr.inherited_sparse_num = 0; jcr.total_container_num = 0; jcr.total_time = 0; /* * the time consuming of seven backup phase */ jcr.read_time = 0; jcr.chunk_time = 0; jcr.hash_time = 0; jcr.dedup_time = 0; jcr.rewrite_time = 0; jcr.filter_time = 0; jcr.write_time = 0; /* * the time consuming of three restore phase */ jcr.read_recipe_time = 0; jcr.read_chunk_time = 0; jcr.write_chunk_time = 0; jcr.read_container_num = 0; }
static sds cliVersion() { sds version; version = sdscatprintf(sdsempty(), "%s", REDIS_VERSION); /* Add git commit and working tree status when available */ if (strtoll(redisGitSHA1(),NULL,16)) { version = sdscatprintf(version, " (git:%s", redisGitSHA1()); if (strtoll(redisGitDirty(),NULL,10)) version = sdscatprintf(version, "-dirty"); version = sdscat(version, ")"); } return version; }
/* Define a lua function with the specified function name and body. * * 根据给定函数名和代码体(body),创建 Lua 函数。 * * The function name musts be a 2 characters long string, since all the * functions we defined in the Lua context are in the form: * * 所有函数名称的长度都必须大于 2 ,因为我们使用以下格式来创建函数名: * * f_<hex sha1 sum> * * On success REDIS_OK is returned, and nothing is left on the Lua stack. * 创建成功返回 REDIS_OK ,并清除 Lua 栈中的所有资料。 * * On error REDIS_ERR is returned and an appropriate error is set in the * client context. */ int luaCreateFunction(redisClient *c, lua_State *lua, char *funcname, robj *body) { sds funcdef = sdsempty(); // 函数定义 funcdef = sdscat(funcdef,"function "); funcdef = sdscatlen(funcdef,funcname,42); funcdef = sdscatlen(funcdef,"() ",3); funcdef = sdscatlen(funcdef,body->ptr,sdslen(body->ptr)); funcdef = sdscatlen(funcdef," end",4); // 将函数定义载入到 Lua 中(并编译),但不执行该定义 if (luaL_loadbuffer(lua,funcdef,sdslen(funcdef),"@user_script")) { // 如果编译出错,那么返回错误 addReplyErrorFormat(c,"Error compiling script (new function): %s\n", lua_tostring(lua,-1)); lua_pop(lua,1); sdsfree(funcdef); return REDIS_ERR; } sdsfree(funcdef); // 定义函数 if (lua_pcall(lua,0,0,0)) { addReplyErrorFormat(c,"Error running script (new function): %s\n", lua_tostring(lua,-1)); lua_pop(lua,1); return REDIS_ERR; } /* We also save a SHA1 -> Original script map in a dictionary * so that we can replicate / write in the AOF all the * EVALSHA commands as EVAL using the original script. * * 创建一个从 SHA1 映射到原始脚本的字典, * 从而使得脚本可以用于复制,以及写入到 AOF 文件 */ { int retval = dictAdd(server.lua_scripts, // SHA1 值,不包括前缀 f_ sdsnewlen(funcname+2,40), // 代码体 body); redisAssertWithInfo(c,NULL,retval == DICT_OK); incrRefCount(body); } return REDIS_OK; }
/* Like sdscatprintf() but gets va_list instead of being variadic. */ sds sdscatvprintf(sds s, const char *fmt, va_list ap) { va_list cpy; char staticbuf[1024], *buf = staticbuf, *t; size_t buflen = strlen(fmt)*2; /* We try to start using a static buffer for speed. * If not possible we revert to heap allocation. */ if (buflen > sizeof(staticbuf)) { buf = zmalloc(buflen); if (buf == NULL) return NULL; } else { buflen = sizeof(staticbuf); } /* Try with buffers two times bigger every time we fail to * fit the string in the current buffer size. */ while(1) { buf[buflen-2] = '\0'; va_copy(cpy,ap); #ifdef _WIN32 // see comment below vsnprintf(buf, buflen-1, fmt, cpy); #else vsnprintf(buf, buflen, fmt, cpy); #endif va_end(cpy); if (buf[buflen-2] != '\0') { if (buf != staticbuf) zfree(buf); buflen *= 2; #ifdef _WIN32 // from the vsnprintf documentation in MSDN: // "To ensure that there is room for the terminating null, // be sure that count is strictly less than the buffer length // and initialize the buffer to null prior to calling the function." buf = zcalloc(buflen); #else buf = zmalloc(buflen); #endif if (buf == NULL) return NULL; continue; } break; } /* Finally concat the obtained string to the SDS string and return it. */ t = sdscat(s, buf); if (buf != staticbuf) zfree(buf); return t; }