Exemple #1
0
/**
 * Generate unique id
 *
 * @param seed      additional seed string. this can be NULL
 *
 * @return a pointer of malloced string
 *
 * @note
 *  The length of returned string is 32+1 bytes long including terminating NULL
 *  character. It's a good idea to call srand() once before calling this because
 *  it uses rand().
 */
char *qstrunique(const char *seed)
{
    long int usec;
#ifdef _WIN32
    FILETIME ft;
    GetSystemTimeAsFileTime(&ft);
    usec = ft.dwLowDateTime % 1000000;
#else
    struct timeval tv;
    gettimeofday(&tv, NULL);
    usec = tv.tv_usec;
#endif

    char uniquestr[128];
    snprintf(uniquestr, sizeof(uniquestr), "%u%d%lu%ld%s",
             getpid(),
             rand(),
             (unsigned long int)time(NULL),
             usec,
             (seed != NULL) ? seed : "");

    unsigned char md5hash[16];
    qhashmd5(uniquestr, strlen(uniquestr), md5hash);
    char *md5ascii = qhex_encode(md5hash, 16);

    return md5ascii;
}
Exemple #2
0
static int _get_idx(qhasharr_t *tbl, const char *key, size_t key_size, unsigned int hash)
{
    if (NULL == tbl || NULL == key)
        return -1;
    qhasharr_slot_t *_tbl_slots = NULL;
    qhasharr_init(tbl, &_tbl_slots);

    if (_tbl_slots[hash].count > 0)
    {
        unsigned int idx;
        int count = 0;
        for (count = 0, idx = hash; count < _tbl_slots[hash].count; )
        {
            if (_tbl_slots[idx].hash == hash
                    && (_tbl_slots[idx].count > 0 || _tbl_slots[idx].count == -1))
            {
                // same hash
                count++;

                // first check key length
                if (key_size == _tbl_slots[idx].data.pair.keylen)
                {
                    if (key_size <= _Q_HASHARR_KEYSIZE)
                    {
                        // original key is stored
                        if (!memcmp(key, _tbl_slots[idx].data.pair.key, key_size))
                        {
                            return idx;
                        }
                    }
                    else
                    {
                        // key is truncated, compare MD5 also.
                        unsigned char keymd5[16];
                        qhashmd5(key, key_size, keymd5);
                        if (!memcmp(key, _tbl_slots[idx].data.pair.key,
                                    _Q_HASHARR_KEYSIZE) &&
                                !memcmp(keymd5, _tbl_slots[idx].data.pair.keymd5,
                                        16))
                        {
                            return idx;
                        }
                    }
                }
            }

            // increase idx
            idx++;
            if (idx >= (unsigned int)tbl->maxslots) idx = 0;

            // check loop
            if (idx == hash) break;

            continue;
        }
    }

    return -1;
}
Exemple #3
0
static int get_idx(qhasharr_t *tbl, const void *name, size_t namesize,
                   uint32_t hash) {
    qhasharr_data_t *tbldata = tbl->data;
    qhasharr_slot_t *tblslots = get_slots(tbl);

    if (tblslots[hash].count > 0) {
        int count, idx;
        for (count = 0, idx = hash; count < tblslots[hash].count;) {
            if (tblslots[idx].hash == hash
                    && (tblslots[idx].count > 0 || tblslots[idx].count == COLLISION_MARK)) {
                // same hash
                count++;

                // is same key?
                // first check key length
                if (namesize == tblslots[idx].data.pair.namesize) {
                    if (namesize <= Q_HASHARR_NAMESIZE) {
                        // original key is stored
                        if (!memcmp(name, tblslots[idx].data.pair.name,
                                    namesize)) {
                            return idx;
                        }
                    } else {
                        // key is truncated, compare MD5 also.
                        unsigned char namemd5[16];
                        qhashmd5(name, namesize, namemd5);
                        if (!memcmp(name, tblslots[idx].data.pair.name,
                        Q_HASHARR_NAMESIZE)
                                && !memcmp(namemd5,
                                           tblslots[idx].data.pair.namemd5,
                                           16)) {
                            return idx;
                        }
                    }
                }
            }

            // increase idx
            idx++;
            if (idx >= tbldata->maxslots)
                idx = 0;

            // check loop
            if (idx == hash)
                break;

            continue;
        }
    }

    return -1;
}
Exemple #4
0
static int _get_idx(qhasharr_t *tbl, const char *key, unsigned int hash) {
    qhasharr_data_t *data = tbl->data;

    if (data->slots[hash].count > 0) {
        int count, idx;
        for (count = 0, idx = hash; count < data->slots[hash].count;) {
            if (data->slots[idx].hash == hash
                    && (data->slots[idx].count > 0
                            || data->slots[idx].count == -1)) {
                // same hash
                count++;

                // is same key?
                size_t keylen = strlen(key);
                // first check key length
                if (keylen == data->slots[idx].data.pair.keylen) {
                    if (keylen <= _Q_HASHARR_KEYSIZE) {
                        // original key is stored
                        if (!memcmp(key, data->slots[idx].data.pair.key,
                                    keylen)) {
                            return idx;
                        }
                    } else {
                        // key is truncated, compare MD5 also.
                        unsigned char keymd5[16];
                        qhashmd5(key, keylen, keymd5);
                        if (!memcmp(key, data->slots[idx].data.pair.key,
                        _Q_HASHARR_KEYSIZE)
                                && !memcmp(keymd5,
                                           data->slots[idx].data.pair.keymd5,
                                           16)) {
                            return idx;
                        }
                    }
                }
            }

            // increase idx
            idx++;
            if (idx >= data->maxslots)
                idx = 0;

            // check loop
            if (idx == hash)
                break;

            continue;
        }
    }

    return -1;
}
Exemple #5
0
static bool _put_data(qhasharr_t *tbl, int idx, unsigned int hash,
                      const char *key, size_t key_size, const void *value, size_t val_size,
                      int count)
{
    size_t tmp_size = 0;
    qhasharr_slot_t *_tbl_slots = NULL;
    qhasharr_init(tbl, &_tbl_slots);

    // check if used
    if (_tbl_slots[idx].count != 0)
    {
        errno = EFAULT;
        return false;
    }

    unsigned char keymd5[16];
    qhashmd5(key, key_size, keymd5);

    // store key
    _tbl_slots[idx].count = count;
    _tbl_slots[idx].hash = hash;
    tmp_size = (key_size <= _Q_HASHARR_KEYSIZE) ? key_size : _Q_HASHARR_KEYSIZE;
    memcpy(_tbl_slots[idx].data.pair.key, key, tmp_size);
    memcpy((char *)_tbl_slots[idx].data.pair.keymd5, (char *)keymd5, 16);
    _tbl_slots[idx].data.pair.keylen = key_size;
    _tbl_slots[idx].link = -1;

    // store value
    int newidx;
    size_t savesize;
    for (newidx = idx, savesize = 0; savesize < val_size;)
    {
        if (savesize > 0)   // find next empty slot
        {
            int tmpidx = _find_empty(tbl, newidx + 1);
            if (tmpidx < 0)
            {
                _remove_data(tbl, idx);
                errno = ENOBUFS;
                return false;
            }

            // clear & set
            memset((void *)(&_tbl_slots[tmpidx]), '\0',
                   sizeof(qhasharr_slot_t));

            _tbl_slots[tmpidx].count = -2;      // extended data block
            _tbl_slots[tmpidx].hash = newidx;   // prev link
            _tbl_slots[tmpidx].link = -1;       // end block mark
            _tbl_slots[tmpidx].size = 0;

            _tbl_slots[newidx].link = tmpidx;   // link chain

            newidx = tmpidx;
        }

        // copy data
        size_t copysize = val_size - savesize;

        if (_tbl_slots[newidx].count == -2)
        {
            // extended value
            //if (copysize > sizeof(struct _Q_HASHARR_SLOT_EXT)) {
            //    copysize = sizeof(struct _Q_HASHARR_SLOT_EXT);
            //}
            if (copysize > sizeof(union _slot_data))
            {
                copysize = sizeof(union _slot_data);
            }

            memcpy(_tbl_slots[newidx].data.ext.value,
                   (char*)value + savesize, copysize);
        }
        else
        {
            // first slot
            if (copysize > _Q_HASHARR_VALUESIZE)
            {
                copysize = _Q_HASHARR_VALUESIZE;
            }
            memcpy(_tbl_slots[newidx].data.pair.value,
                   (char*)value + savesize, copysize);

            // increase stored key counter
            tbl->num++;
        }
        _tbl_slots[newidx].size = copysize;
        savesize += copysize;

        // increase used slot counter
        tbl->usedslots++;
    }

    return true;
}
Exemple #6
0
static bool _put_data(qhasharr_t *tbl, int idx, unsigned int hash,
                      const char *key, const void *value, size_t size,
                      int count)
{
    // check if used
    if (tbl->slots[idx].count != 0) {
        DEBUG("hasharr: BUG found.");
        errno = EFAULT;
        return false;
    }

    size_t keylen = strlen(key);
    unsigned char keymd5[16];
    qhashmd5(key, keylen, keymd5);

    // store key
    tbl->slots[idx].count = count;
    tbl->slots[idx].hash = hash;
    strncpy(tbl->slots[idx].data.pair.key, key, _Q_HASHARR_KEYSIZE);
    memcpy((char *)tbl->slots[idx].data.pair.keymd5, (char *)keymd5, 16);
    tbl->slots[idx].data.pair.keylen = keylen;
    tbl->slots[idx].link = -1;

    // store value
    int newidx;
    size_t savesize;
    for (newidx = idx, savesize = 0; savesize < size;) {
        if (savesize > 0) { // find next empty slot
            int tmpidx = _find_empty(tbl, newidx + 1);
            if (tmpidx < 0) {
                DEBUG("hasharr: Can't expand slot for key %s.", key);
                _remove_data(tbl, idx);
                errno = ENOBUFS;
                return false;
            }

            // clear & set
            memset((void *)(&tbl->slots[tmpidx]), '\0',
                   sizeof(qhasharr_slot_t));

            tbl->slots[tmpidx].count = -2;      // extended data block
            tbl->slots[tmpidx].hash = newidx;   // prev link
            tbl->slots[tmpidx].link = -1;       // end block mark
            tbl->slots[tmpidx].size = 0;

            tbl->slots[newidx].link = tmpidx;   // link chain

            DEBUG("hasharr: slot %d is linked to slot %d for key %s.",
                  tmpidx, newidx, key);
            newidx = tmpidx;
        }

        // copy data
        size_t copysize = size - savesize;

        if (tbl->slots[newidx].count == -2) {
            // extended value
            if (copysize > sizeof(struct _Q_HASHARR_SLOT_EXT)) {
                copysize = sizeof(struct _Q_HASHARR_SLOT_EXT);
            }
            memcpy(tbl->slots[newidx].data.ext.value,
                   value + savesize, copysize);
        } else {
            // first slot
            if (copysize > _Q_HASHARR_VALUESIZE) {
                copysize = _Q_HASHARR_VALUESIZE;
            }
            memcpy(tbl->slots[newidx].data.pair.value,
                   value + savesize, copysize);

            // increase stored key counter
            tbl->num++;
        }
        tbl->slots[newidx].size = copysize;
        savesize += copysize;

        // increase used slot counter
        tbl->usedslots++;
    }

    return true;
}
Exemple #7
0
static bool put_data(qhasharr_t *tbl, int idx, uint32_t hash, const void *name,
                     size_t namesize, const void *data, size_t datasize,
                     int count) {
    qhasharr_data_t *tbldata = tbl->data;
    qhasharr_slot_t *tblslots = get_slots(tbl);

    assert(tblslots[idx].count == 0);

    unsigned char namemd5[16];
    qhashmd5(name, namesize, namemd5);

    // store name
    tblslots[idx].count = count;
    tblslots[idx].hash = hash;
    memcpy(tblslots[idx].data.pair.name, name,
           (namesize < Q_HASHARR_NAMESIZE) ? namesize : Q_HASHARR_NAMESIZE);
    memcpy((char *) tblslots[idx].data.pair.namemd5, (char *) namemd5, 16);
    tblslots[idx].data.pair.namesize = namesize;
    tblslots[idx].link = -1;

    // store data
    int newidx;
    size_t savesize;
    for (newidx = idx, savesize = 0; savesize < datasize;) {
        if (savesize > 0) {  // find next empty slot
            int tmpidx = find_avail(tbl, newidx + 1);
            if (tmpidx < 0) {
                remove_data(tbl, idx);
                errno = ENOBUFS;
                return false;
            }

            // clear & set
            memset((void *) (&tblslots[tmpidx]), '\0', sizeof(qhasharr_slot_t));

            tblslots[tmpidx].count = EXTBLOCK_MARK; // extended data block
            tblslots[tmpidx].hash = newidx;   // previous link
            tblslots[tmpidx].link = -1;       // end block mark
            tblslots[tmpidx].datasize = 0;
            tblslots[newidx].link = tmpidx;   // link chain

            newidx = tmpidx;
        }

        // copy data
        size_t copysize = datasize - savesize;
        if (tblslots[newidx].count == EXTBLOCK_MARK) {
            // extended value
            if (copysize > sizeof(struct Q_HASHARR_SLOT_EXT)) {
                copysize = sizeof(struct Q_HASHARR_SLOT_EXT);
            }
            memcpy(tblslots[newidx].data.ext.data, data + savesize, copysize);
        } else {
            // first slot
            if (copysize > Q_HASHARR_DATASIZE) {
                copysize = Q_HASHARR_DATASIZE;
            }
            memcpy(tblslots[newidx].data.pair.data, data + savesize, copysize);

            // increase stored key counter
            tbldata->num++;
        }
        tblslots[newidx].datasize = copysize;
        savesize += copysize;

        // increase used slot counter
        tbldata->usedslots++;
    }

#ifdef QHASHARR_TIMESTAMP
    time(&tblslots[idx].timestamp);
#endif

    return true;
}