memcached_1.4.14之process_get_command解析

来源:互联网 发布:ica 似然最大算法 编辑:程序博客网 时间:2024/05/17 05:26
/* ntokens is overwritten here... shrug.. */static inline void process_get_command(conn *c, token_t *tokens, size_t ntokens, bool return_cas) {    char *key;    size_t nkey;    int i = 0;    item *it;    //需要get的key值 = key_token->value    token_t *key_token = &tokens[KEY_TOKEN];    char *suffix;    assert(c != NULL);    //key_token->value != NULL    //遇到command结束标识符'\0'时跳出循环    do {        //针对多个key的情况,一个key处理结束时跳出循环        while(key_token->length != 0) {            key = key_token->value;            nkey = key_token->length;            //key最大长度250            if(nkey > KEY_MAX_LENGTH) {                out_string(c, "CLIENT_ERROR bad command line format");                return;            }            it = item_get(key, nkey);            //stat详细信息开启            if (settings.detail_enabled) {                stats_prefix_record_get(key, nkey, NULL != it);            }            if (it) {                //isize:ilist大小,超出ilist大小时重新分配                if (i >= c->isize) {                    item **new_list = realloc(c->ilist, sizeof(item *) * c->isize * 2);                    if (new_list) {                        c->isize *= 2;                        c->ilist = new_list;                    } else {//分配失败,移除it,放入回收槽slot中。                        item_remove(it);                        break;                    }                }                /*                 * Construct the response. Each hit adds three elements to the                 * outgoing data list:                 *   "VALUE "                 *   key                 *   " " + flags + " " + data length + "\r\n" + data (with \r\n)                 */                //使用gets命令                if (return_cas)                {                  MEMCACHED_COMMAND_GET(c->sfd, ITEM_key(it), it->nkey,                                        it->nbytes, ITEM_get_cas(it));                  /* Goofy mid-flight realloc. */                  if (i >= c->suffixsize) {                    char **new_suffix_list = realloc(c->suffixlist,                                           sizeof(char *) * c->suffixsize * 2);                    if (new_suffix_list) {                        c->suffixsize *= 2;                        c->suffixlist  = new_suffix_list;                    } else {                        item_remove(it);                        break;                    }                  }                  suffix = cache_alloc(c->thread->suffix_cache);                  if (suffix == NULL) {                    out_string(c, "SERVER_ERROR out of memory making CAS suffix");                    item_remove(it);                    return;                  }                  *(c->suffixlist + i) = suffix;                  //suffix:代表cas的版本号,包括\r\n                  int suffix_len = snprintf(suffix, SUFFIX_SIZE,                                            " %llu\r\n",                                            (unsigned long long)ITEM_get_cas(it));                  //ITEM_suffix(it),指向flag,nsuffix包括flag+data length + \r\n                  if (add_iov(c, "VALUE ", 6) != 0 ||                      add_iov(c, ITEM_key(it), it->nkey) != 0 ||                      add_iov(c, ITEM_suffix(it), it->nsuffix - 2) != 0 ||    //减去\r\n,则不换行,版本号紧跟着flags+length                      add_iov(c, suffix, suffix_len) != 0 ||                      add_iov(c, ITEM_data(it), it->nbytes) != 0)                      {                          item_remove(it);                          break;                      }                }                else                {                  MEMCACHED_COMMAND_GET(c->sfd, ITEM_key(it), it->nkey,                                        it->nbytes, ITEM_get_cas(it));                  if (add_iov(c, "VALUE ", 6) != 0 ||                      add_iov(c, ITEM_key(it), it->nkey) != 0 ||                      add_iov(c, ITEM_suffix(it), it->nsuffix + it->nbytes) != 0)                      {                          item_remove(it);                          break;                      }                }                if (settings.verbose > 1)                    fprintf(stderr, ">%d sending key %s\n", c->sfd, ITEM_key(it));                /* item_get() has incremented it->refcount for us */                pthread_mutex_lock(&c->thread->stats.mutex);                c->thread->stats.slab_stats[it->slabs_clsid].get_hits++;                c->thread->stats.get_cmds++;                pthread_mutex_unlock(&c->thread->stats.mutex);                item_update(it);//访问时间超过60秒更新下时间,放到LRU header                //将it放入ilist,等待返回给client                *(c->ilist + i) = it;                i++;            } else {                pthread_mutex_lock(&c->thread->stats.mutex);                c->thread->stats.get_misses++;                c->thread->stats.get_cmds++;                pthread_mutex_unlock(&c->thread->stats.mutex);                MEMCACHED_COMMAND_GET(c->sfd, key, nkey, -1, 0);            }            key_token++;        }        /*         * If the command string hasn't been fully processed, get the next set         * of tokens.         */        //get多个key时,解析剩余的key        if(key_token->value != NULL) {            ntokens = tokenize_command(key_token->value, tokens, MAX_TOKENS);            key_token = tokens;        }    } while(key_token->value != NULL);    c->icurr = c->ilist;    c->ileft = i;    if (return_cas) {        c->suffixcurr = c->suffixlist;        c->suffixleft = i;    }    if (settings.verbose > 1)        fprintf(stderr, ">%d END\n", c->sfd);    /*        If the loop was terminated because of out-of-memory, it is not        reliable to add END\r\n to the buffer, because it might not end        in \r\n. So we send SERVER_ERROR instead.    */    if (key_token->value != NULL || add_iov(c, "END\r\n", 5) != 0        || (IS_UDP(c->transport) && build_udp_headers(c) != 0)) {        out_string(c, "SERVER_ERROR out of memory writing get response");    }    else {        conn_set_state(c, conn_mwrite);        c->msgcurr = 0;    }    return;}


转载前请标明出处,谢谢!

原创粉丝点击