Example #1
0
/*
 find the hashlink for the supplied key and remove it, also freeing the memory
 for that hashlink. it is not an error to be unable to find the hashlink, if it
 cannot be found do nothing (or print a message) but do not use an assert which
 will end your program.
 */
void removeKey (struct hashMap * ht, KeyType k)
{
	/*write this*/
	assert (ht != NULL);
    struct hashLink *cur = ht->table[_findKey(ht, k)];
    while (cur != 0){
        if (strcmp(cur->key, k) == 0 ){
            struct hashLink *temp = cur->next;
            free (cur->key);
            free (cur);
            ht->table[_findKey( ht, k ) ] = temp;
            ht->count--;
            return;
        }
        while (cur->next != NULL ){
            if (strcmp(cur->next->key, k) == 0){
                struct hashLink *temp = cur->next->next;
                free(cur->next->key);
                free(cur->next);
                cur->next = temp;
                ht->count--;
                return;
            }
            cur = cur->next;
        }
    }
}
Example #2
0
//return */0:不存在;1:获取;-1:空间不足
int UnistorStoreMemCache::fetch(char const* szKey,
                 CWX_UINT16 unKeyLen,
                 char* szData,
                 CWX_UINT32& uiDataLen,
                 CWX_UINT32& uiExpire,
                 CWX_UINT32  uiCurExpireTime,
                 bool bTouch)
{
    char key_buf[UnistorStoreMemCacheItem::calKeySize(unKeyLen , 0)];
    UnistorStoreMemCacheItem* key = (UnistorStoreMemCacheItem*)key_buf;
    memcpy(key->m_szBuf, szKey, unKeyLen);
    key->m_unKeyLen = unKeyLen;
    UnistorStoreMemCacheIter iter;
    iter.m_uiHash = UnistorStoreMemCacheItem::m_fnHash(key->getKey(), key->getKeyLen())%m_bucket_num;
    {
        CwxReadLockGuard<CwxRwLock> lock(&m_rwLock);
        if (!_findKey(key, iter)) return 0;
        if (uiDataLen < iter.m_pFind->getDataLen()) return -1;
        if (iter.m_pFind->m_uiExpire && (iter.m_pFind->m_uiExpire <= uiCurExpireTime)){///<超时
            return 0;
        }
        memcpy(szData, iter.m_pFind->getData(), iter.m_pFind->getDataLen());
        uiDataLen = iter.m_pFind->getDataLen();
        uiExpire = iter.m_pFind->m_uiExpire;
        if(bTouch) {
            CWX_UINT32 uiIndex = iter.m_pFind->index();
            CwxMutexGuard<CwxMutexLock> lock(m_chainMutexArr[uiIndex%UNISTOR_STORE_MEM_CACHE_CHAIN_LOCK_NUM]);
            _touch(iter.m_pFind, uiIndex);
        }
        return 1;
    }
}    
Example #3
0
/*
 insert the following values into a hashLink, you must create this hashLink but
 only after you confirm that this key does not already exist in the table. For example, you
 cannot have two hashLinks for the word "taco".

 if a hashLink already exists in the table for the key provided you should
 replace that hashLink--this requires freeing up the old memory pointed by hashLink->value
 and then pointing hashLink->value to value v.

 also, you must monitor the load factor and resize when the load factor is greater than
 or equal LOAD_FACTOR_THRESHOLD (defined in hashMap.h).
 */
void insertMap (struct hashMap * ht, KeyType k, ValueType v){
	/*write this*/
    assert (ht != 0);
    if (containsKey(ht, k))
    ht->table[_findKey(ht, k)]->value = v;
    else {
        struct hashLink *newLink = malloc(sizeof(struct hashLink));
        newLink->value = v;
        newLink->key = k;
        newLink->next = ht->table[_findKey(ht, k)];
        ht->table[_findKey(ht, k)] = newLink;
        ht->count++;
    }
    if (tableLoad(ht) > LOAD_FACTOR_THRESHOLD)
    _setTableSize(ht, ht->tableSize * 2);
}
Example #4
0
int UnistorReadCacheEx2::fetch(char const* szKey,
                 CWX_UINT16 unKeyLen,
                 char* szData,
                 CWX_UINT32& uiDataLen,
                 bool bTouch)
{
    char key_buf[UnistorReadCacheItemEx2::calKeySize(unKeyLen , 0)];
    UnistorReadCacheItemEx2* key = (UnistorReadCacheItemEx2*)key_buf;
    memcpy(key->m_szBuf, szKey, unKeyLen);
    key->m_unKeyLen = unKeyLen;
    UnistorReadCacheExIter iter;
    iter.m_uiHash = UnistorReadCacheItemEx2::m_fnHash(key->getKey(), key->getKeyLen())%m_bucket_num;
    {
        CwxReadLockGuard<CwxRwLock> lock(this->m_rwLock);
        if (!_findKey(key, iter)) return 0;
        if (uiDataLen < iter.m_pFind->getDataLen()) return -1;
        memcpy(szData, iter.m_pFind->getData(), iter.m_pFind->getDataLen());
        uiDataLen = iter.m_pFind->getDataLen();
        if(bTouch) {
            CWX_UINT32 uiIndex = iter.m_pFind->index();
            CwxMutexGuard<CwxMutexLock> lock(m_chainMutexArr[uiIndex%UNISTOR_READ_CACHE_CHAIN_LOCK_NUM]);
            _touch(iter.m_pFind, uiIndex);
        }
        return 1;
    }
}    
Example #5
0
///检测超时的元素,key的expire时间超过uiCurTime的全部失效
void UnistorStoreMemCache::checkExpire(CWX_UINT32 uiCurTime, CWX_UINT32 uiBatchNum){
    CWX_UINT32 uiSlot=m_uiCurCheckSlotIndex;
    CWX_UINT32 uiPos=m_uiCurCheckSlotPos;
    CWX_UINT32 uiTotalSlot = m_cacheBufArrIndex + 1;
    CWX_UINT32 uiCheckNum = 0;
    UnistorStoreMemCacheItem* key=NULL;
    m_uiExpireNum = 0;
    for (; uiSlot<uiTotalSlot; uiSlot++){
        while(UNISTOR_STORE_MEM_CACHE_SLOT_SIZE >= uiPos + sizeof(UnistorStoreMemCacheItem)){
            key = (UnistorStoreMemCacheItem*)(m_cacheBufArr[uiSlot] + uiPos);
            if (UnistorStoreMemCacheItem::UNISTOR_MEM_ITEM_STATE_UNMALLOC == key->m_ucState){
                break;///<剩余的空间没有分配
            }else if (UnistorStoreMemCacheItem::UNISTOR_MEM_ITEM_STATE_USED == key->m_ucState){
                if (key->m_uiExpire && (key->m_uiExpire < uiCurTime)){///<疑似超时
                    m_arrExpiredItem[m_uiExpireNum++] = key;
                }
            }
            uiCheckNum++;
            uiPos += key->size();
            ///如果已经检查了指定的数量,则break。
            if (uiCheckNum >= m_uiMaxPerCheckExpireNum) break;
        }
        ///如果已经检查了指定的数量,则break。
        if (uiCheckNum >= m_uiMaxPerCheckExpireNum) break;
        uiPos = 0;///<从头开始
    }
    ///如果已经满了,则break
    if (uiCheckNum < m_uiMaxPerCheckExpireNum){
        ///本轮检测全部完成
        CWX_ASSERT(uiSlot == uiTotalSlot);
        m_uiCurCheckSlotIndex = 0;
        m_uiCurCheckSlotPos = 0;
    }else{
        m_uiCurCheckSlotIndex = uiSlot;
        m_uiCurCheckSlotPos = uiPos;
    }
    CWX_UINT32 uiIndex = 0;
    UnistorStoreMemCacheIter iter;
    while(uiIndex < m_uiExpireNum){
        if (uiIndex + uiBatchNum > m_uiExpireNum){
            uiBatchNum = m_uiExpireNum - uiIndex;
        }
        {
            ///获取写锁
            CwxWriteLockGuard<CwxRwLock> lock(&m_rwLock);
            for (CWX_UINT32 i=0; i<uiBatchNum; i++){
                iter.m_uiHash = UnistorStoreMemCacheItem::m_fnHash(m_arrExpiredItem[uiIndex]->getKey(), m_arrExpiredItem[uiIndex]->getKeyLen())%m_bucket_num;
                if (_findKey(m_arrExpiredItem[uiIndex], iter) && m_arrExpiredItem[uiIndex]->m_uiExpire && (m_arrExpiredItem[uiIndex]->m_uiExpire < uiCurTime)){
                    _remove(iter);
                }
                uiIndex++;
            } 

        }
    }
    m_uiExpireNum = 0;

}
Example #6
0
/*
 a simple yes/no if the key is in the hashtable.
 0 is no, all other values are yes.
 */
int containsKey (struct hashMap * ht, KeyType k)
{
	/*write this*/
	assert (ht != NULL);
    struct hashLink *ptr = ht->table[_findKey(ht, k)];
    while (ptr != 0){
        if (strcmp(ptr->key,k) == 0)
            return 1;
            ptr = ptr->next;
    }
    return 0;
}
Example #7
0
/*
 this returns the value (which is void*) stored in a hashLink specified by the key k.

 if the user supplies the key "taco" you should find taco in the hashTable, then
 return the value member of the hashLink that represents taco.

 if the supplied key is not in the hashtable return NULL.
 */
ValueType* atMap (struct hashMap * ht, KeyType k)
{
	/*write this*/
	assert (ht != 0);
    struct hashLink *ptr = ht->table[_findKey(ht, k)];
    while (ptr != 0){
        if (strcmp(ptr->key,k) == 0)
            return(&(ptr->value));
            ptr = ptr->next;
    }
    return 0;
}
Example #8
0
void UnistorStoreMemCache::remove( char const* szKey, CWX_UINT16 unKeyLen, CWX_UINT32 uiExpire){
    char key_buf[UnistorStoreMemCacheItem::calKeySize(unKeyLen , 0)];
    UnistorStoreMemCacheItem* key = (UnistorStoreMemCacheItem*)key_buf;
    memcpy(key->m_szBuf, szKey, unKeyLen);
    key->m_unKeyLen = unKeyLen;
    UnistorStoreMemCacheIter iter;
    iter.m_uiHash = UnistorStoreMemCacheItem::m_fnHash(key->getKey(), key->getKeyLen())%m_bucket_num;
    {
        CwxWriteLockGuard<CwxRwLock> lock(&m_rwLock);
        if (_findKey(key, iter) && (!uiExpire || (iter.m_pFind->m_uiExpire == uiExpire))){
            _remove(iter);
        }
    }
}
Example #9
0
void UnistorReadCacheEx2::remove( char const* szKey, CWX_UINT16 unKeyLen){
    char key_buf[UnistorReadCacheItemEx2::calKeySize(unKeyLen , 0)];
    UnistorReadCacheItemEx2* key = (UnistorReadCacheItemEx2*)key_buf;
    memcpy(key->m_szBuf, szKey, unKeyLen);
    key->m_unKeyLen = unKeyLen;
    UnistorReadCacheExIter iter;
    iter.m_uiHash = UnistorReadCacheItemEx2::m_fnHash(key->getKey(), key->getKeyLen())%m_bucket_num;
    {
        CwxWriteLockGuard<CwxRwLock> lock(this->m_rwLock);
        if (_findKey(key, iter)){
            _remove(iter);
        }
    }
}
Example #10
0
bool UnistorStoreMemCache::exist(char const* szKey, ///<key
                  CWX_UINT16 unKeyLen ///<key的长度
                  )
{
    char key_buf[UnistorStoreMemCacheItem::calKeySize(unKeyLen, 0)];
    UnistorStoreMemCacheItem* key = (UnistorStoreMemCacheItem*)key_buf;
    memcpy(key->m_szBuf, szKey, unKeyLen);
    key->m_unKeyLen = unKeyLen;
    UnistorStoreMemCacheIter iter;
    iter.m_uiHash = UnistorStoreMemCacheItem::m_fnHash(key->getKey(), key->getKeyLen())%m_bucket_num;
    {
        CwxReadLockGuard<CwxRwLock> lock(&m_rwLock);
        return _findKey(key, iter);
    }
}
Example #11
0
void UnistorStoreMemCache::touch(char const* szKey, ///<key
                  CWX_UINT16 unKeyLen ///<key的长度
                  )
{
    char key_buf[UnistorStoreMemCacheItem::calKeySize(unKeyLen , 0)];
    UnistorStoreMemCacheItem* key = (UnistorStoreMemCacheItem*)key_buf;
    memcpy(key->m_szBuf, szKey, unKeyLen);
    key->m_unKeyLen = unKeyLen;
    UnistorStoreMemCacheIter iter;
    iter.m_uiHash = UnistorStoreMemCacheItem::m_fnHash(key->getKey(), key->getKeyLen())%m_bucket_num;
    {
        CwxReadLockGuard<CwxRwLock> lock(&m_rwLock);
        if (_findKey(key, iter)){
            CWX_UINT32 uiIndex = iter.m_pFind->index();
            CwxMutexGuard<CwxMutexLock> lock(m_chainMutexArr[uiIndex%UNISTOR_STORE_MEM_CACHE_CHAIN_LOCK_NUM]);
            _touch(iter.m_pFind, uiIndex);
        }
    }
}
Example #12
0
void UnistorStoreMemCache::insert(char const* szKey,
            CWX_UINT16 unKeyLen,
            char const* szData,
            CWX_UINT32 uiDataLen,
            CWX_UINT32* uiExpire)
{
    ///key的长度不能为0
    if (!unKeyLen) return;
    CWX_UINT32 uiOldExpire = 0;
    CWX_UINT32 uiIndex = 0;
    char key_buf[UnistorStoreMemCacheItem::calKeySize(unKeyLen , 0)];
    UnistorStoreMemCacheItem* key = (UnistorStoreMemCacheItem*)key_buf;
    memcpy(key->m_szBuf, szKey, unKeyLen);
    key->m_unKeyLen = unKeyLen;
    UnistorStoreMemCacheIter iter;

    CWX_UINT32 uiKeySize = UnistorStoreMemCacheItem::calKeySize(unKeyLen , uiDataLen);
    ///若key的空间大小大于slot,则不cache
    if (uiKeySize > UNISTOR_STORE_MEM_CACHE_MAX_ITEM_SIZE) return;

    iter.m_uiHash = UnistorStoreMemCacheItem::m_fnHash(key->getKey(), key->getKeyLen())%m_bucket_num;
    {
        CwxWriteLockGuard<CwxRwLock> lock(&m_rwLock);
        ///如果key存在
        if(_findKey(key, iter)){
            if (uiKeySize == iter.m_pFind->size()){///属于同一个slot
                ///修改空间
                m_usedDataSize -= iter.m_pFind->getDataLen();
                m_usedDataSize += uiDataLen;
                iter.m_pFind->m_uiDataLen = uiDataLen;
                if (uiExpire) iter.m_pFind->m_uiExpire = *uiExpire;
                if (uiDataLen){
                    memcpy((char*)iter.m_pFind->getData(), szData, uiDataLen);  
                }
                uiIndex = iter.m_pFind->index();
                _touch(iter.m_pFind, uiIndex);
                return;
            }
            uiOldExpire = iter.m_pFind->m_uiExpire;
            ///属于不同的slot,首先溢出,此时拥有hash锁、链表锁、及统计锁
            _remove(iter);
        }
        ///计算索引
        uiIndex = UnistorStoreMemCacheItem::calKeyIndex(unKeyLen , uiDataLen);
        ///优先使用空闲的key
        if (m_chainArr[uiIndex].m_freeHead){
            key = m_chainArr[uiIndex].m_freeHead;
            m_chainArr[uiIndex].m_freeHead = m_chainArr[uiIndex].m_freeHead->m_next;
            ///修改空间
            m_chainArr[uiIndex].m_uiFreeNum--;
            m_freeSize -= uiKeySize;
            m_freeCapacity -= (uiKeySize - sizeof(UnistorStoreMemCacheItem));
            m_freeItemCount --;
        }else if ((m_cacheBufArrIndex + 1 < m_cacheBufArrSize) ||  ///从新内存分配key
            (m_cacheBufArrPos + uiKeySize < UNISTOR_STORE_MEM_CACHE_SLOT_SIZE))
        {
            if (m_cacheBufArrPos + uiKeySize > UNISTOR_STORE_MEM_CACHE_SLOT_SIZE){///<使用新slot
                m_cacheBufArrIndex ++;
                m_cacheBufArrPos = 0;
            }
            ///分配新空间
            key = (UnistorStoreMemCacheItem*)(m_cacheBufArr[m_cacheBufArrIndex] + m_cacheBufArrPos);
            m_cacheBufArrPos += uiKeySize;
        }else if (m_chainArr[uiIndex].m_usedTail){///释放已有空间
            key = m_chainArr[uiIndex].m_usedTail;
            iter.m_uiHash = UnistorStoreMemCacheItem::m_fnHash(key->getKey(), key->getKeyLen())%m_bucket_num;
            _findKey(key, iter);
            if (iter.m_pFind != key){
                CWX_ASSERT(0);
            }
            ///从hash中删除key
            _removeKey(iter);
            m_chainArr[uiIndex].m_usedTail = m_chainArr[uiIndex].m_usedTail->m_prev;
            if (!m_chainArr[uiIndex].m_usedTail){
                m_chainArr[uiIndex].m_usedHead = NULL;
            }else{
                m_chainArr[uiIndex].m_usedTail->m_next = NULL;
            }
            m_chainArr[uiIndex].m_uiUsedNum--;
            m_usedSize -= uiKeySize;
            m_usedCapacity -= uiKeySize - sizeof(UnistorStoreMemCacheItem);
            m_usedDataSize -= key->m_uiDataLen + key->m_unKeyLen;
            m_cachedKeyCount--;
            m_cachedItemCount--;
        }else{ ///没有空间可用,不cache
            return ;
        }
        ///copy数据
        key->m_uiKeyIndex = uiIndex; ///<设置key的index
        key->m_unKeyLen = unKeyLen;
        key->m_uiDataLen = uiDataLen;
        key->m_ucState = UnistorStoreMemCacheItem::UNISTOR_MEM_ITEM_STATE_USED;
        key->m_uiExpire = uiExpire?*uiExpire:uiOldExpire;
        if (unKeyLen)  memcpy((char*)key->getKey(), szKey, unKeyLen);
        if (uiDataLen) memcpy((char*)key->getData(), szData, uiDataLen);
        _addKey(uiIndex, uiKeySize, key);
    }
}