Esempio n. 1
0
static ham_status_t
_remote_cursor_move(ham_cursor_t *cursor, ham_key_t *key, 
                ham_record_t *record, ham_u32_t flags)
{
    ham_status_t st;
    ham_db_t *db=cursor_get_db(cursor);
    ham_env_t *env=db_get_env(db);
    proto_wrapper_t *request, *reply;
    
    request=proto_init_cursor_move_request(cursor_get_remote_handle(cursor), 
                        key, record, flags);

    st=_perform_request(env, env_get_curl(env), request, &reply);
    proto_delete(request);
    if (st) {
        if (reply)
            proto_delete(reply);
        return (st);
    }

    ham_assert(reply!=0, (""));
    ham_assert(proto_has_cursor_move_reply(reply)!=0, (""));

    st=proto_cursor_move_reply_get_status(reply);
    if (st) 
        goto bail;

    /* modify key/record, but make sure that USER_ALLOC is respected! */
    if (proto_cursor_move_reply_has_key(reply)) {
        ham_assert(key, (""));
        key->_flags=proto_cursor_move_reply_get_key_intflags(reply);
        key->size=proto_cursor_move_reply_get_key_size(reply);
        if (!(key->flags&HAM_KEY_USER_ALLOC)) {
            st=db_resize_key_allocdata(db, key->size);
            if (st)
                goto bail;
            key->data=db_get_key_allocdata(db);
        }
        memcpy(key->data, proto_cursor_move_reply_get_key_data(reply),
                key->size);
    }

    /* same for the record */
    if (proto_cursor_move_reply_has_record(reply)) {
        ham_assert(record, (""));
        record->size=proto_cursor_move_reply_get_record_size(reply);
        if (!(record->flags&HAM_RECORD_USER_ALLOC)) {
            st=db_resize_record_allocdata(db, record->size);
            if (st)
                goto bail;
            record->data=db_get_record_allocdata(db);
        }
        memcpy(record->data, proto_cursor_move_reply_get_record_data(reply),
                record->size);
    }

bail:
    proto_delete(reply);
    return (st);
}
Esempio n. 2
0
static ham_status_t
_remote_fun_find(ham_db_t *db, ham_txn_t *txn, ham_key_t *key,
            ham_record_t *record, ham_u32_t flags)
{
    ham_status_t st;
    ham_env_t *env=db_get_env(db);
    proto_wrapper_t *request, *reply;

    request=proto_init_db_find_request(db_get_remote_handle(db), 
                        txn ? txn_get_remote_handle(txn) : 0, 
                        key, record, flags);

    st=_perform_request(env, env_get_curl(env), request, &reply);
    proto_delete(request);
    if (st) {
        if (reply)
            proto_delete(reply);
        return (st);
    }

    ham_assert(reply!=0, (""));
    ham_assert(proto_has_db_find_reply(reply)!=0, (""));

    st=proto_db_find_reply_get_status(reply);
    if (st==0) {
        /* approx. matching: need to copy the _flags and the key data! */
        if (proto_db_find_reply_has_key(reply)) {
            ham_assert(key, (""));
            key->_flags=proto_db_find_reply_get_key_intflags(reply);
            key->size=proto_db_find_reply_get_key_size(reply);
            if (!(key->flags&HAM_KEY_USER_ALLOC)) {
                st=db_resize_key_allocdata(db, key->size);
                if (st)
                    goto bail;
                key->data=db_get_key_allocdata(db);
            }
            memcpy(key->data, proto_db_find_reply_get_key_data(reply),
                    key->size);
        }
        if (proto_db_find_reply_has_record(reply)) {
            record->size=proto_db_find_reply_get_record_size(reply);
            if (!(record->flags&HAM_RECORD_USER_ALLOC)) {
                st=db_resize_record_allocdata(db, record->size);
                if (st)
                    goto bail;
                record->data=db_get_record_allocdata(db);
            }
            memcpy(record->data, proto_db_find_reply_get_record_data(reply),
                    record->size);
        }
    }

bail:
    proto_delete(reply);

    return (st);
}
Esempio n. 3
0
static ham_status_t
_remote_cursor_find(ham_cursor_t *cursor, ham_key_t *key, 
                ham_record_t *record, ham_u32_t flags)
{
    ham_status_t st;
    ham_db_t *db=cursor_get_db(cursor);
    ham_env_t *env=db_get_env(db);
    proto_wrapper_t *request, *reply;

    request=proto_init_cursor_find_request(cursor_get_remote_handle(cursor), 
                        key, record, flags);
    
    st=_perform_request(env, env_get_curl(env), request, &reply);
    proto_delete(request);
    if (st) {
        if (reply)
            proto_delete(reply);
        return (st);
    }

    ham_assert(reply!=0, (""));
    ham_assert(proto_has_cursor_find_reply(reply)!=0, (""));

    st=proto_cursor_find_reply_get_status(reply);
    if (st) 
        goto bail;

    /* approx. matching: need to copy the _flags! */
    if (proto_cursor_find_reply_has_key(reply)) {
        key->_flags=proto_cursor_find_reply_get_key_intflags(reply);
    }
    if (proto_cursor_find_reply_has_record(reply)) {
        ham_assert(record, (""));
        record->size=proto_cursor_find_reply_get_record_size(reply);
        if (!(record->flags&HAM_RECORD_USER_ALLOC)) {
            st=db_resize_record_allocdata(db, record->size);
            if (st)
                goto bail;
            record->data=db_get_record_allocdata(db);
        }
        memcpy(record->data, proto_cursor_find_reply_get_record_data(reply),
                record->size);
    }

bail:
    proto_delete(reply);
    return (st);
}
Esempio n. 4
0
ham_status_t
blob_read(ham_db_t *db, ham_offset_t blobid, 
        ham_record_t *record, ham_u32_t flags)
{
    ham_status_t st;
    ham_page_t *page;
    blob_t hdr;
    ham_size_t blobsize=0;

    /*
     * in-memory-database: the blobid is actually a pointer to the memory
     * buffer, in which the blob is stored
     */
    if (env_get_rt_flags(db_get_env(db))&HAM_IN_MEMORY_DB) {
        blob_t *hdr=(blob_t *)U64_TO_PTR(blobid);
        ham_u8_t *data=(ham_u8_t *)(U64_TO_PTR(blobid))+sizeof(blob_t);

        /* when the database is closing, the header is already deleted */
        if (!hdr) {
            record->size = 0;
            return (0);
        }

        blobsize = (ham_size_t)blob_get_size(hdr);

        if (flags&HAM_PARTIAL) {
            if (record->partial_offset>blobsize) {
                ham_trace(("partial offset is greater than the total "
                            "record size"));
                return (HAM_INV_PARAMETER);
            }
            if (record->partial_offset+record->partial_size>blobsize)
                blobsize=blobsize-record->partial_offset;
            else
                blobsize=record->partial_size;
        }

        if (!blobsize) {
            /* empty blob? */
            record->data = 0;
            record->size = 0;
        }
        else {
            ham_u8_t *d=data;
            if (flags&HAM_PARTIAL)
                d+=record->partial_offset;

            if ((flags&HAM_DIRECT_ACCESS) 
                    && !(record->flags&HAM_RECORD_USER_ALLOC)) {
                record->size=blobsize;
                record->data=d;
            }
            else {
                /* resize buffer, if necessary */
                if (!(record->flags & HAM_RECORD_USER_ALLOC)) {
                    st=db_resize_record_allocdata(db, blobsize);
                    if (st)
                        return (st);
                    record->data = db_get_record_allocdata(db);
                }
                /* and copy the data */
                memcpy(record->data, d, blobsize);
                record->size = blobsize;
            }
        }

        return (0);
    }

    ham_assert(blobid%DB_CHUNKSIZE==0, ("blobid is %llu", blobid));

    /*
     * first step: read the blob header 
     */
    st=__read_chunk(db_get_env(db), 0, &page, blobid, 
                    (ham_u8_t *)&hdr, sizeof(hdr));
    if (st)
        return (st);

    ham_assert(blob_get_alloc_size(&hdr)%DB_CHUNKSIZE==0, (0));

    /*
     * sanity check
     */
    if (blob_get_self(&hdr)!=blobid)
        return (HAM_BLOB_NOT_FOUND);

    blobsize = (ham_size_t)blob_get_size(&hdr);

    if (flags&HAM_PARTIAL) {
        if (record->partial_offset>blobsize) {
            ham_trace(("partial offset+size is greater than the total "
                        "record size"));
            return (HAM_INV_PARAMETER);
        }
        if (record->partial_offset+record->partial_size>blobsize)
            blobsize=blobsize-record->partial_offset;
        else
            blobsize=record->partial_size;
    }

    /* 
     * empty blob? 
     */
    if (!blobsize) {
        record->data = 0;
        record->size = 0;
        return (0);
    }

    /*
     * second step: resize the blob buffer
     */
    if (!(record->flags & HAM_RECORD_USER_ALLOC)) {
        st=db_resize_record_allocdata(db, blobsize);
        if (st)
            return (st);
        record->data = db_get_record_allocdata(db);
    }

    /*
     * third step: read the blob data
     */
    st=__read_chunk(db_get_env(db), page, 0, 
                    blobid+sizeof(blob_t)+(flags&HAM_PARTIAL 
                            ? record->partial_offset 
                            : 0),
                    record->data, blobsize);
    if (st)
        return (st);

    record->size = blobsize;

    return (0);
}
Esempio n. 5
0
ham_status_t
blob_duplicate_erase(ham_db_t *db, ham_offset_t table_id,
        ham_size_t position, ham_u32_t flags, ham_offset_t *new_table_id)
{
    ham_status_t st;
    ham_record_t rec;
    ham_size_t i;
    dupe_table_t *table;
    ham_offset_t rid;
	ham_env_t *env = db_get_env(db);

    /* store the public record pointer, otherwise it's destroyed */
    ham_size_t rs=db_get_record_allocsize(db);
    void      *rp=db_get_record_allocdata(db);
    db_set_record_allocdata(db, 0);
    db_set_record_allocsize(db, 0);

    memset(&rec, 0, sizeof(rec));

    if (new_table_id)
        *new_table_id=table_id;

    st=blob_read(db, table_id, &rec, 0);
    if (st)
        return (st);

    /* restore the public record pointer */
    db_set_record_allocsize(db, rs);
    db_set_record_allocdata(db, rp);

    table=(dupe_table_t *)rec.data;

    /*
     * if BLOB_FREE_ALL_DUPES is set *OR* if the last duplicate is deleted:
     * free the whole duplicate table
     */
    if (flags&BLOB_FREE_ALL_DUPES
            || (position==0 && dupe_table_get_count(table)==1)) {
        for (i=0; i<dupe_table_get_count(table); i++) {
            dupe_entry_t *e=dupe_table_get_entry(table, i);
            if (!(dupe_entry_get_flags(e)&(KEY_BLOB_SIZE_SMALL
                                        |KEY_BLOB_SIZE_TINY
                                        |KEY_BLOB_SIZE_EMPTY))) {
                st=blob_free(env, db, dupe_entry_get_rid(e), 0);
                if (st) {
                    allocator_free(env_get_allocator(env), table);
                    return (st);
                }
            }
        }
        st=blob_free(env, db, table_id, 0); /* [i_a] isn't this superfluous (& 
                                        * dangerous), thanks to the 
                                        * free_all_dupes loop above??? */
        allocator_free(env_get_allocator(env), table);
        if (st)
            return (st);

        if (new_table_id)
            *new_table_id=0;

        return (0);
    }
    else {
        ham_record_t rec={0};
        dupe_entry_t *e=dupe_table_get_entry(table, position);
        if (!(dupe_entry_get_flags(e)&(KEY_BLOB_SIZE_SMALL
                                    |KEY_BLOB_SIZE_TINY
                                    |KEY_BLOB_SIZE_EMPTY))) {
            st=blob_free(env, db, dupe_entry_get_rid(e), 0);
            if (st) {
                allocator_free(env_get_allocator(env), table);
                return (st);
            }
        }
        memmove(e, e+1,
            ((dupe_table_get_count(table)-position)-1)*sizeof(dupe_entry_t));
        dupe_table_set_count(table, dupe_table_get_count(table)-1);

        rec.data=(ham_u8_t *)table;
        rec.size=sizeof(dupe_table_t)
                    +(dupe_table_get_capacity(table)-1)*sizeof(dupe_entry_t);
        st=blob_overwrite(env, db, table_id, &rec, 0, &rid);
        if (st) {
            allocator_free(env_get_allocator(env), table);
            return (st);
        }
        if (new_table_id)
            *new_table_id=rid;
    }

    /*
     * return 0 as a rid if the table is empty
     */
    if (dupe_table_get_count(table)==0)
        if (new_table_id)
            *new_table_id=0;

    allocator_free(env_get_allocator(env), table);
    return (0);
}