Example #1
0
/**
 * qhasharr->remove_by_idx(): Remove an object from this table by index number.
 *
 * @param tbl       qhasharr_t container pointer.
 * @param idx       slot index number
 *
 * @return true if successful, otherwise(not found) returns false
 * @retval errno will be set in error condition.
 *  - ENOENT    : Index is not pointing a valid object.
 *  - EINVAL    : Invald argument.
 *  - EFAULT    : Unexpected error. Data structure is not constant.
 *
 * @code
 *  int idx = 0;
 *  qhasharr_obj_t obj;
 *  while(tbl->getnext(tbl, &obj, &idx) == true) {
 *    if (condition_to_remove) {
 *      idx--;  // adjust index by -1
 *      remove_by_idx(idx);
 *    }
 *    free(obj.name);
 *    free(obj.data);
 *  }
 * @endcode
 *
 * @note
 * This function is to remove an object in getnext() traversal loop without
 * knowing the object name but index value. When key names are longer than
 * defined size, the keys are stored with truncation with their fingerprint,
 * so this method provides a way to remove those keys.
 * getnext() returns actual index + 1(pointing next slot of current finding),
 * so you need to adjust it by -1 for the valid index number. And once you
 * remove object by this method, rewind idx by -1 before calling getnext()
 * because collision objects can be moved back to removed index again, so
 * by adjusting index by -1, getnext() can continue search from the removed
 * slot index again. Please refer an example code.
 */
bool qhasharr_remove_by_idx(qhasharr_t *tbl, int idx) {
    if (idx < 0) {
        errno = EINVAL;
        return false;
    }

    qhasharr_data_t *tbldata = tbl->data;
    qhasharr_slot_t *tblslots = get_slots(tbl);

    if (tblslots[idx].count == 1) {
        // just remove
        remove_data(tbl, idx);
    } else if (tblslots[idx].count > 1) {  // leading slot and has collision
        // find the collision key
        int idx2;
        for (idx2 = idx + 1;; idx2++) {
            if (idx2 >= tbldata->maxslots)
                idx2 = 0;
            if (idx2 == idx) {
                errno = EFAULT;
                return false;
            }
            if (tblslots[idx2].count == COLLISION_MARK
                    && tblslots[idx2].hash == tblslots[idx].hash) {
                break;
            }
        }

        // move to leading slot
        int backupcount = tblslots[idx].count;
        remove_data(tbl, idx);  // remove leading data
        copy_slot(tbl, idx, idx2);  // copy slot
        remove_slot(tbl, idx2);  // remove moved slot

        tblslots[idx].count = backupcount - 1;  // adjust collision counter
        if (tblslots[idx].link != -1) {
            tblslots[tblslots[idx].link].hash = idx;
        }

    } else if (tblslots[idx].count == COLLISION_MARK) {  // collision key
        // decrease counter from leading slot
        if (tblslots[tblslots[idx].hash].count <= 1) {
            errno = EFAULT;
            return false;
        }
        tblslots[tblslots[idx].hash].count--;

        // remove data
        remove_data(tbl, idx);
    } else {
        errno = ENOENT;
        return false;
    }

    return true;
}
Example #2
0
static bool remove_data(qhasharr_t *tbl, int idx) {
    qhasharr_data_t *tbldata = tbl->data;
    qhasharr_slot_t *tblslots = get_slots(tbl);
    assert(tblslots[idx].count != 0);

    while (true) {
        int link = tblslots[idx].link;
        remove_slot(tbl, idx);
        tbldata->usedslots--;

        if (link == -1)
            break;

        idx = link;
    }

    // decrease stored key counter
    tbldata->num--;

    return true;
}
Example #3
0
		// from signal_interface
		virtual void slot_destroyed(slot_interface& aSlot) const
		{
			remove_slot(aSlot);
		}
Example #4
0
		void disconnect(const Key& aKey, slot_interface& aSlot) const
		{
			remove_slot(aKey, aSlot);
		}
Example #5
0
		void disconnect(slot_interface& aSlot) const
		{
			remove_slot(aSlot);
		}
Example #6
0
/**
 * qhasharr->put_by_obj(): ut an object into this table by key object.
 *
 * @param tbl       qhasharr_t container pointer.
 * @param name      key data
 * @param namesize  size of key
 * @param data      data
 * @param datasize  size of data
 *
 * @return true if successful, otherwise returns false
 * @retval errno will be set in error condition.
 *  - ENOBUFS   : Table doesn't have enough space to store the object.
 *  - EINVAL    : Invalid argument.
 *  - EFAULT    : Unexpected error. Data structure is not constant.
 */
bool qhasharr_put_by_obj(qhasharr_t *tbl, const void *name, size_t namesize,
                         const void *data, size_t datasize) {
    if (tbl == NULL || name == NULL || namesize == 0 || data == NULL
            || datasize == 0) {
        errno = EINVAL;
        return false;
    }

    qhasharr_data_t *tbldata = tbl->data;
    qhasharr_slot_t *tblslots = get_slots(tbl);

    // check full
    if (tbldata->usedslots >= tbldata->maxslots) {
        errno = ENOBUFS;
        return false;
    }

    // get hash integer
    uint32_t hash = qhashmurmur3_32(name, namesize) % tbldata->maxslots;

    // check, is slot empty
    if (tblslots[hash].count == 0) {  // empty slot
        // put data
        if (put_data(tbl, hash, hash, name, namesize, data, datasize,
                     1) == false) {
            return false;
        }
    } else if (tblslots[hash].count > 0) {  // same key or hash collision
        // check same key;
        int idx = get_idx(tbl, name, namesize, hash);
        if (idx >= 0) {  // same key
            // remove and recall
            qhasharr_remove_by_idx(tbl, idx);
            return qhasharr_put_by_obj(tbl, name, namesize, data, datasize);
        } else {  // no same key but hash collision
            // find empty slot
            int idx = find_avail(tbl, hash);
            if (idx < 0) {
                errno = ENOBUFS;
                return false;
            }

            // put data. -1 is used for collision resolution (idx != hash);
            if (put_data(tbl, idx, hash, name, namesize, data, datasize,
                         COLLISION_MARK) == false) {
                return false;
            }

            // increase counter from leading slot
            tblslots[hash].count++;
        }
    } else {
        // collision key or extended block

        // find empty slot
        int idx = find_avail(tbl, hash + 1);
        if (idx < 0) {
            errno = ENOBUFS;
            return false;
        }

        // move the slot
        copy_slot(tbl, idx, hash);
        remove_slot(tbl, hash);

        // adjust the link chain
        if (tblslots[idx].link != -1) {
            tblslots[tblslots[idx].link].hash = idx;
        }
        if (tblslots[idx].count == EXTBLOCK_MARK) {
            tblslots[tblslots[idx].hash].link = idx;
        }

        // store data
        if (put_data(tbl, hash, hash, name, namesize, data, datasize,
                     1) == false) {
            return false;
        }
    }

    return true;
}