Ejemplo n.º 1
0
//修改item的时间
base_item* LRU_list::do_item_touch(const char* key, const size_t nkey, const uint32_t exptime, const uint32_t hv) {
    base_item *it = do_item_get(key, nkey, hv);
    if (it != NULL) {
        it->exptime = exptime;
    }
    return it;
}
Ejemplo n.º 2
0
Archivo: thread.c Proyecto: alxn/memc3
enum store_item_type do_store_item(item *it, const uint32_t hv) {
    enum store_item_type stored;
    char *key = ITEM_key(it);
    item *old_it = do_item_get(key, it->nkey, hv);
    if (old_it != NULL) {
        assert(old_it != it);

        before_write(old_it);
        do_item_unlink_nolock(old_it, hv);
        //do_item_remove(old_it);         /* release our reference */
        item_free(old_it);
        assert((old_it->it_flags & ITEM_LINKED) == 0);
        assert((old_it->it_flags & ITEM_SLABBED) != 0);
        after_write(old_it);
    } 
    before_write(it);
    int ret = do_item_link_nolock(it, hv);
    after_write(it);

    if (ret == 0) {
        stored = NOT_STORED;
        printf("not stored\n");
    } else {
        stored = STORED;
    }

    return  stored;
}
Ejemplo n.º 3
0
/*
 * Returns an item if it hasn't been marked as expired,
 * lazy-expiring as needed.
 */
item *item_get(const char *key, const size_t nkey) {
    item *it;
    pthread_mutex_lock(&cache_lock);
    it = do_item_get(key, nkey);
    pthread_mutex_unlock(&cache_lock);
    return it;
}
Ejemplo n.º 4
0
item *do_item_touch(const char *key, size_t nkey, uint32_t exptime,
                    const uint32_t hv) {
    item *it = do_item_get(key, nkey, hv);
    if (it != NULL) {
        it->exptime = exptime;
    }
    return it;
}
Ejemplo n.º 5
0
/*
 * Returns an item if it hasn't been marked as expired,
 * lazy-expiring as needed.
 */
hash_item *item_get(struct default_engine *engine,
                    const void *key, const size_t nkey) {
    hash_item *it;
    pthread_mutex_lock(&engine->cache_lock);
    it = do_item_get(engine, key, nkey);
    pthread_mutex_unlock(&engine->cache_lock);
    return it;
}
Ejemplo n.º 6
0
item *do_item_touch(const char *key, size_t nkey, uint32_t exptime,
                    const uint32_t hv) {
		syslog(LOG_INFO, "[%s:%s:%d]", __FILE__, __func__, __LINE__);
    item *it = do_item_get(key, nkey, hv);
    if (it != NULL) {
        it->exptime = exptime;
    }
    return it;
}
Ejemplo n.º 7
0
/*
 * Returns an item if it hasn't been marked as expired,
 * lazy-expiring as needed.
 */
item *item_get(const char *key, const size_t nkey, conn *c, const bool do_update) {
    item *it;
    uint32_t hv;
    hv = hash(key, nkey);
    item_lock(hv);
    it = do_item_get(key, nkey, hv, c, do_update);
    item_unlock(hv);
    return it;
}
Ejemplo n.º 8
0
/*
 * Returns an item if it hasn't been marked as expired,
 * lazy-expiring as needed.
 */
item *item_get(const char *key, const size_t nkey) {
    item *it;
    uint32_t hv;
    hv = hash(key, nkey);
    item_lock(hv);
    it = do_item_get(key, nkey, hv);
    item_unlock(hv);
    return it;
}
Ejemplo n.º 9
0
base_item* LRU_list::item_get(const char* key, const size_t nkey) {
    base_item *it;
    uint32_t hv;
    hv = HashTable::hash(key, nkey);
    hashtable.hash_lock(hv);
    it = do_item_get(key, nkey, hv);
    hashtable.hash_unlock(hv);
    return it;
}
Ejemplo n.º 10
0
static hash_item *do_touch_item(struct default_engine *engine,
                                const hash_key *hkey,
                                uint32_t exptime)
{
   hash_item *item = do_item_get(engine, hkey);
   if (item != NULL) {
       item->exptime = exptime;
   }
   return item;
}
Ejemplo n.º 11
0
/*
 * Returns an item if it hasn't been marked as expired,
 * lazy-expiring as needed.
 */
hash_item *item_get(struct default_engine *engine,
                    const void *cookie,
                    const void *key,
                    const size_t nkey) {
    hash_item *it;
    hash_key hkey;
    if (!hash_key_create(&hkey, key, nkey, engine, cookie)) {
        return NULL;
    }
    cb_mutex_enter(&engine->items.lock);
    it = do_item_get(engine, &hkey);
    cb_mutex_exit(&engine->items.lock);
    hash_key_destroy(&hkey);
    return it;
}
Ejemplo n.º 12
0
static ENGINE_ERROR_CODE do_arithmetic(struct default_engine *engine,
                                       const void* cookie,
                                       const hash_key* key,
                                       const bool increment,
                                       const bool create,
                                       const uint64_t delta,
                                       const uint64_t initial,
                                       const rel_time_t exptime,
                                       item **result_item,
                                       uint8_t datatype,
                                       uint64_t *result)
{
   hash_item *item = do_item_get(engine, key);
   ENGINE_ERROR_CODE ret;

   if (item == NULL) {
      if (!create) {
         return ENGINE_KEY_ENOENT;
      } else {
         char buffer[128];
         int len = snprintf(buffer, sizeof(buffer), "%"PRIu64,
                            (uint64_t)initial);
         if (len < 0 || len >= sizeof(buffer)) {
             return ENGINE_ENOMEM;
         }

         item = do_item_alloc(engine, key, 0, exptime, len, cookie,
                              datatype);
         if (item == NULL) {
            return ENGINE_ENOMEM;
         }
         memcpy((void*)item_get_data(item), buffer, len);
         if ((ret = do_store_item(engine, item, OPERATION_ADD, cookie,
                                  (hash_item**)result_item)) == ENGINE_SUCCESS) {
             *result = initial;
         } else {
             do_item_release(engine, item);
         }
      }
   } else {
      ret = do_add_delta(engine, item, increment, delta, result_item, result,
                         cookie);
   }

   return ret;
}
Ejemplo n.º 13
0
static ENGINE_ERROR_CODE do_item_delete(struct demo_engine *engine,
                                        const void* key, const size_t nkey,
                                        uint64_t cas)
{
    ENGINE_ERROR_CODE ret;
    hash_item *it = do_item_get(engine, key, nkey, true);
    if (it == NULL) {
        ret = ENGINE_KEY_ENOENT;
    } else {
        if (cas == 0 || cas == dm_item_get_cas(it)) {
            do_item_unlink(engine, it, ITEM_UNLINK_NORMAL);
            ret = ENGINE_SUCCESS;
        } else {
            ret = ENGINE_KEY_EEXISTS;
        }
        do_item_release(engine, it);
    }
    return ret;
}
Ejemplo n.º 14
0
enum store_item_type do_store_item ( item *it, int comm, const uint32_t hv )
{
    char *key = ITEM_key (it);
    item *old_it = do_item_get (key, it->nkey, hv);
    enum store_item_type stored = NOT_STORED;

    item *new_it = NULL;
    int flags;

    if ( old_it != NULL && comm == NREAD_ADD )
    {
        do_item_update (old_it);
    }
    else if ( ! old_it && ( comm == NREAD_REPLACE || comm == NREAD_APPEND || comm == NREAD_PREPEND ) )
    {

    }
    else
    {
        if ( comm == NREAD_APPEND || comm == NREAD_PREPEND )
        {
            if ( stored == NOT_STORED )
            {
                flags = ( int ) strtol (ITEM_suffix (old_it), ( char ** ) NULL, 10);
                new_it = do_item_alloc (key, it->nkey, flags, old_it->exptime, ITEM_data (it), it->nbytes + old_it->nbytes - 2, hv);
                if ( ! new_it )
                {
                    if ( old_it )
                        do_item_remove (old_it);
                    return NOT_STORED;
                }
                if ( comm == NREAD_APPEND )
                {
                    memcpy (ITEM_data (new_it), ITEM_data (old_it), old_it->nbytes);
                    memcpy (ITEM_data (new_it) + old_it->nbytes - 2, ITEM_data (it), it->nbytes);
                }
                else
                {
                    memcpy (ITEM_data (new_it), ITEM_data (it), it->nbytes);
                    memcpy (ITEM_data (new_it) + it->nbytes - 2, ITEM_data (old_it), old_it->nbytes);
                }
                it = new_it;
            }
        }
        if ( stored == NOT_STORED )
        {
            if ( old_it != NULL )
            {
                item_replace (old_it, it, hv);
            }
            else
            {
                do_item_link (it, hv);
            }
            stored = STORED;
        }
    }
    if ( old_it != NULL )
    {
        do_item_remove (old_it);
    }
    if ( new_it != NULL )
    {
        do_item_remove (new_it);
    }
    return stored;
}
Ejemplo n.º 15
0
int LRU_list::do_store_item(base_item* it, Conn* c, uint32_t hv) {
    char* key = it->data;
    
    //获取旧的数据项
    base_item* old_it = do_item_get(key, it->nkey, hv);
    int store_stat = LRU_list::NOT_STORED;

    base_item* new_it = 0;
    int flags = 0;

    //已经有该项item存在
    if (old_it != 0 && c->cmd == NREAD_ADD) {
        /* 
         * 更新当前item目的
         * 1.更新时间,重建LRU链
         * 2.后面执行do_item_remove,每次remove会把refcount引用计数减一
         *   如果引用计数=1则被删除,重建之后refcount为2
         * */
        do_item_update(old_it);
    //旧的item不存在
    }else if (!old_it && (c->cmd == NREAD_REPLACE || c->cmd == NREAD_APPEND 
                || c->cmd == NREAD_PREPEND)) {
        //什么也不做,因为只有replace替换已有值
    }else if (c->cmd == NREAD_CAS) {

        //不存在此项
        if (old_it == 0) {
            store_stat = LRU_list::NOT_FOUND;
        }
        if (it->cas == old_it->cas) {
            item_replace(old_it, it, hv);
            store_stat = LRU_list::STORED;
        }
        else {
            if (mem_setting.verbose > 1) {
                std::cerr << "CAS: failure: expected " << old_it->get_cas() << " but got " 
                    << it->cas;
            }
            store_stat = LRU_list::EXISTS;
        }
    }
    else {
        //与上面第二个判断不同,这里是旧的item存在的replace append prepend set命令
        if (c->cmd == NREAD_APPEND || c->cmd == NREAD_PREPEND) {
            //if (it->cas != 0) {
            if (it->cas != old_it->cas) {
                store_stat = LRU_list::EXISTS;
            }
            //}

            if (store_stat == LRU_list::NOT_STORED) {
                new_it = do_item_alloc(key, it->nkey, flags, old_it->exptime, 
                        it->nbytes + old_it->nbytes - 2, hv);
                //分配失败
                if (new_it == 0) {
                    if (old_it != 0) 
                        do_item_remove(old_it);
                    return LRU_list::NOT_STORED;
                }

                new_it->nkey = old_it->nkey;
                new_it->item_flag = flags;
                new_it->exptime = old_it->exptime;
                new_it->nbytes = it->nbytes + old_it->nbytes - 2;
                memcpy(new_it->data, old_it->data, old_it->nkey);
                new_it->data[old_it->nkey] = '0';

                //copy数据
                if (c->cmd == NREAD_APPEND) {
                    memcpy(new_it->real_data_addr(), old_it->real_data_addr(), 
                            old_it->nbytes);
                    memcpy(new_it->real_data_addr() + old_it->nbytes - 2/*\r\n*/, 
                            it->real_data_addr(), it->nbytes);
                }
                else {
                    //NREAD_PREPEND
                    memcpy(new_it->real_data_addr(), it->real_data_addr(), it->nbytes);
                    memcpy(new_it->real_data_addr() + it->nbytes - 2, 
                            old_it->real_data_addr(), old_it->nbytes);
                }
                it = new_it;
            }
        }

        if (store_stat == LRU_list::NOT_STORED) {
            it->cas++;
            if (old_it != 0)
                item_replace(old_it, it, hv);
            else 
                //set a new key-value
                do_item_link(it, hv);

            store_stat = LRU_list::STORED;
        }
    }

    if (old_it != 0)
        do_item_remove(old_it);
    if (new_it != 0)
        do_item_remove(new_it);

    if (store_stat == LRU_list::STORED) {
        c->cas = it->get_cas();
    }

    return store_stat;
}
Ejemplo n.º 16
0
/*
 * Stores an item in the cache according to the semantics of one of the set
 * commands. In threaded mode, this is protected by the cache lock.
 *
 * Returns the state of storage.
 */
static ENGINE_ERROR_CODE do_item_store(struct demo_engine *engine,
                                       hash_item *it, uint64_t *cas,
                                       ENGINE_STORE_OPERATION operation,
                                       const void *cookie)
{
    const char *key = dm_item_get_key(it);
    hash_item *old_it;
    hash_item *new_it = NULL;
    ENGINE_ERROR_CODE stored;

    old_it = do_item_get(engine, key, it->nkey, true);

    if (old_it != NULL) {
        if (operation == OPERATION_ADD) {
            do_item_release(engine, old_it);
            return ENGINE_NOT_STORED;
        }
    } else {
        if (operation == OPERATION_REPLACE ||
            operation == OPERATION_APPEND || operation == OPERATION_PREPEND) {
            return ENGINE_NOT_STORED;
        }
        if (operation == OPERATION_CAS) {
            return ENGINE_KEY_ENOENT;
        }
    }

    stored = ENGINE_NOT_STORED;

    if (operation == OPERATION_CAS) {
        assert(old_it != NULL);
        if (dm_item_get_cas(it) == dm_item_get_cas(old_it)) {
            // cas validates
            // it and old_it may belong to different classes.
            // I'm updating the stats for the one that's getting pushed out
            do_item_replace(engine, old_it, it);
            stored = ENGINE_SUCCESS;
        } else {
            if (engine->config.verbose > 1) {
                logger->log(EXTENSION_LOG_WARNING, NULL,
                        "CAS:  failure: expected %"PRIu64", got %"PRIu64"\n",
                        dm_item_get_cas(old_it), dm_item_get_cas(it));
            }
            stored = ENGINE_KEY_EEXISTS;
        }
    } else {
        /*
         * Append - combine new and old record into single one. Here it's
         * atomic and thread-safe.
         */
        if (operation == OPERATION_APPEND || operation == OPERATION_PREPEND) {
            assert(old_it != NULL);
            /*
             * Validate CAS
             */
            if (dm_item_get_cas(it) != 0) {
                // CAS much be equal
                if (dm_item_get_cas(it) != dm_item_get_cas(old_it)) {
                    stored = ENGINE_KEY_EEXISTS;
                }
            }
            if (stored == ENGINE_NOT_STORED) {
                /* we have it and old_it here - alloc memory to hold both */
                new_it = do_item_alloc(engine, key, it->nkey,
                                       old_it->flags,
                                       old_it->exptime,
                                       it->nbytes + old_it->nbytes - 2 /* CRLF */,
                                       cookie);
                if (new_it == NULL) {
                    /* SERVER_ERROR out of memory */
                    if (old_it != NULL)
                        do_item_release(engine, old_it);
                    return ENGINE_NOT_STORED;
                }

                /* copy data from it and old_it to new_it */
                if (operation == OPERATION_APPEND) {
                    memcpy(dm_item_get_data(new_it), dm_item_get_data(old_it), old_it->nbytes);
                    memcpy(dm_item_get_data(new_it) + old_it->nbytes - 2 /* CRLF */,
                           dm_item_get_data(it), it->nbytes);
                } else {
                    /* OPERATION_PREPEND */
                    memcpy(dm_item_get_data(new_it), dm_item_get_data(it), it->nbytes);
                    memcpy(dm_item_get_data(new_it) + it->nbytes - 2 /* CRLF */,
                           dm_item_get_data(old_it), old_it->nbytes);
                }

                it = new_it;
            }
        }
        if (stored == ENGINE_NOT_STORED) {
            if (old_it != NULL) {
                do_item_replace(engine, old_it, it);
                stored = ENGINE_SUCCESS;
            } else {
                stored = do_item_link(engine, it);
            }
            if (stored == ENGINE_SUCCESS) {
                *cas = dm_item_get_cas(it);
            }
        }
    }

    if (old_it != NULL) {
        do_item_release(engine, old_it);         /* release our reference */
    }
    if (new_it != NULL) {
        do_item_release(engine, new_it);
    }
    if (stored == ENGINE_SUCCESS) {
        *cas = dm_item_get_cas(it);
    }
    return stored;
}
Ejemplo n.º 17
0
/*
 * Stores an item in the cache according to the semantics of one of the set
 * commands. In threaded mode, this is protected by the cache lock.
 *
 * Returns the state of storage.
 */
static ENGINE_ERROR_CODE do_store_item(struct default_engine *engine,
                                       hash_item *it, uint64_t *cas,
                                       ENGINE_STORE_OPERATION operation,
                                       const void *cookie) {
    const char *key = item_get_key(it);
    hash_item *old_it = do_item_get(engine, key, it->nkey);
    ENGINE_ERROR_CODE stored = ENGINE_NOT_STORED;

    hash_item *new_it = NULL;

    if (old_it != NULL && operation == OPERATION_ADD) {
        /* add only adds a nonexistent item, but promote to head of LRU */
        do_item_update(engine, old_it);
    } else if (!old_it && (operation == OPERATION_REPLACE
        || operation == OPERATION_APPEND || operation == OPERATION_PREPEND))
    {
        /* replace only replaces an existing value; don't store */
    } else if (operation == OPERATION_CAS) {
        /* validate cas operation */
        if(old_it == NULL) {
            // LRU expired
            stored = ENGINE_KEY_ENOENT;
        }
        else if (item_get_cas(it) == item_get_cas(old_it)) {
            // cas validates
            // it and old_it may belong to different classes.
            // I'm updating the stats for the one that's getting pushed out
            do_item_replace(engine, old_it, it);
            stored = ENGINE_SUCCESS;
        } else {
            if (engine->config.verbose > 1) {
                EXTENSION_LOGGER_DESCRIPTOR *logger;
                logger = (void*)engine->server.extension->get_extension(EXTENSION_LOGGER);
                logger->log(EXTENSION_LOG_INFO, NULL,
                        "CAS:  failure: expected %"PRIu64", got %"PRIu64"\n",
                        item_get_cas(old_it),
                        item_get_cas(it));
            }
            stored = ENGINE_KEY_EEXISTS;
        }
    } else {
        /*
         * Append - combine new and old record into single one. Here it's
         * atomic and thread-safe.
         */
        if (operation == OPERATION_APPEND || operation == OPERATION_PREPEND) {
            /*
             * Validate CAS
             */
            if (item_get_cas(it) != 0) {
                // CAS much be equal
                if (item_get_cas(it) != item_get_cas(old_it)) {
                    stored = ENGINE_KEY_EEXISTS;
                }
            }

            if (stored == ENGINE_NOT_STORED) {
                /* we have it and old_it here - alloc memory to hold both */
                new_it = do_item_alloc(engine, key, it->nkey,
                                       old_it->flags,
                                       old_it->exptime,
                                       it->nbytes + old_it->nbytes,
                                       cookie);

                if (new_it == NULL) {
                    /* SERVER_ERROR out of memory */
                    if (old_it != NULL) {
                        do_item_release(engine, old_it);
                    }

                    return ENGINE_NOT_STORED;
                }

                /* copy data from it and old_it to new_it */

                if (operation == OPERATION_APPEND) {
                    memcpy(item_get_data(new_it), item_get_data(old_it), old_it->nbytes);
                    memcpy(item_get_data(new_it) + old_it->nbytes, item_get_data(it), it->nbytes);
                } else {
                    /* OPERATION_PREPEND */
                    memcpy(item_get_data(new_it), item_get_data(it), it->nbytes);
                    memcpy(item_get_data(new_it) + it->nbytes, item_get_data(old_it), old_it->nbytes);
                }

                it = new_it;
            }
        }

        if (stored == ENGINE_NOT_STORED) {
            if (old_it != NULL) {
                do_item_replace(engine, old_it, it);
            } else {
                do_item_link(engine, it);
            }

            *cas = item_get_cas(it);
            stored = ENGINE_SUCCESS;
        }
    }

    if (old_it != NULL) {
        do_item_release(engine, old_it);         /* release our reference */
    }

    if (new_it != NULL) {
        do_item_release(engine, new_it);
    }

    if (stored == ENGINE_SUCCESS) {
        *cas = item_get_cas(it);
    }

    return stored;
}