Esempio n. 1
0
void
UnqliteCursor::seek(
	const char* key,
	int key_len,
	SeekMatchType match_type
)
{
	int iPos = 0;
	switch (match_type)
	{
	case SEEK_MATCH_EXACT:
		iPos = UNQLITE_CURSOR_MATCH_EXACT;
		break;
	case SEEK_MATCH_LE:
		iPos = UNQLITE_CURSOR_MATCH_LE;
		break;
	case SEEK_MATCH_GE:
		iPos = UNQLITE_CURSOR_MATCH_GE;
		break;
	default:
		throw UnqliteException(UNQLITE_INVALID);
	}

	int rc = unqlite_kv_cursor_seek(this->_cursor, key, key_len, iPos);
	if (rc != UNQLITE_OK)
		throw UnqliteException(rc, this->_db);
}
Esempio n. 2
0
/*
 * Fetch a record by its unique ID.
 */
UNQLITE_PRIVATE int unqliteCollectionFetchRecordById(
	unqlite_col *pCol, /* Target collection */
	jx9_int64 nId,     /* Unique record ID */
	jx9_value *pValue  /* OUT: record value */
	)
{
	SyBlob *pWorker = &pCol->sWorker;
	unqlite_col_record *pRec;
	int rc;
	jx9_value_null(pValue);
	/* Perform a cache lookup first */
	pRec = CollectionCacheFetchRecord(pCol,nId);
	if( pRec ){
		/* Copy record value */
		jx9MemObjStore(&pRec->sValue,pValue);
		return UNQLITE_OK;
	}
	/* Reset the working buffer */
	SyBlobReset(pWorker);
	/* Generate the unique ID */
	SyBlobFormat(pWorker,"%z_%qd",&pCol->sName,nId);
	/* Reset the cursor */
	unqlite_kv_cursor_reset(pCol->pCursor);
	/* Seek the cursor to the desired location */
	rc = unqlite_kv_cursor_seek(pCol->pCursor,
		SyBlobData(pWorker),SyBlobLength(pWorker),
		UNQLITE_CURSOR_MATCH_EXACT
		);
	if( rc != UNQLITE_OK ){
		return rc;
	}
	/* Consume the binary JSON */
	SyBlobReset(pWorker);
	unqlite_kv_cursor_data_callback(pCol->pCursor,unqliteDataConsumer,pWorker);
	if( SyBlobLength(pWorker) < 1 ){
		unqliteGenErrorFormat(pCol->pVm->pDb,
			"Empty record '%qd'",nId
			);
		jx9_value_null(pValue);
	}else{
		/* Decode the binary JSON */
		rc = FastJsonDecode(SyBlobData(pWorker),SyBlobLength(pWorker),pValue,0,0);
		if( rc == UNQLITE_OK ){
			/* Install the record in the cache */
			CollectionCacheInstallRecord(pCol,nId,pValue);
		}
	}
	return rc;
}
Esempio n. 3
0
/*
 * Drop a collection from the KV storage engine and the underlying
 * unqlite VM.
 */
UNQLITE_PRIVATE int unqliteDropCollection(unqlite_col *pCol)
{
	unqlite_vm *pVm = pCol->pVm;
	jx9_int64 nId;
	int rc;
	/* Reset the cursor */
	unqlite_kv_cursor_reset(pCol->pCursor);
	/* Seek the cursor to the desired location */
	rc = unqlite_kv_cursor_seek(pCol->pCursor,
		SyStringData(&pCol->sName),SyStringLength(&pCol->sName),
		UNQLITE_CURSOR_MATCH_EXACT
		);
	if( rc == UNQLITE_OK ){
		/* Remove the record from the storage engine */
		rc = unqlite_kv_cursor_delete_entry(pCol->pCursor);
	}
	if( rc != UNQLITE_OK ){
		unqliteGenErrorFormat(pCol->pVm->pDb,
				"Cannot remove collection '%z' due to a read-only Key/Value storage engine",
				&pCol->sName
			);
		return rc;
	}
	/* Drop collection records */
	for( nId = 0 ; nId < pCol->nLastid ; ++nId ){
		unqliteCollectionDropRecord(pCol,nId,0,0);
	}
	/* Cleanup */
	CollectionCacheRelease(pCol);
	SyBlobRelease(&pCol->sHeader);
	SyBlobRelease(&pCol->sWorker);
	SyMemBackendFree(&pVm->sAlloc,(void *)SyStringData(&pCol->sName));
	unqliteReleaseCursor(pVm->pDb,pCol->pCursor);
	/* Unlink */
	if( pCol->pPrevCol ){
		pCol->pPrevCol->pNextCol = pCol->pNextCol;
	}else{
		sxu32 iBucket = pCol->nHash & (pVm->iColSize - 1);
		pVm->apCol[iBucket] = pCol->pNextCol;
	}
	if( pCol->pNextCol ){
		pCol->pNextCol->pPrevCol = pCol->pPrevCol;
	}
	MACRO_LD_REMOVE(pVm->pCol,pCol);
	pVm->iCol--;
	SyMemBackendPoolFree(&pVm->sAlloc,pCol);
	return UNQLITE_OK;
}
Esempio n. 4
0
/*
 * Drop a record from a given collection.
 */
UNQLITE_PRIVATE int unqliteCollectionDropRecord(
	unqlite_col *pCol,  /* Target collection */
	jx9_int64 nId,      /* Unique ID of the record to be droped */
	int wr_header,      /* True to alter collection header */
	int log_err         /* True to log error */
	)
{
	SyBlob *pWorker = &pCol->sWorker;
	int rc;		
	/* Reset the working buffer */
	SyBlobReset(pWorker);
	/* Prepare the unique ID for this record */
	SyBlobFormat(pWorker,"%z_%qd",&pCol->sName,nId);
	/* Reset the cursor */
	unqlite_kv_cursor_reset(pCol->pCursor);
	/* Seek the cursor to the desired location */
	rc = unqlite_kv_cursor_seek(pCol->pCursor,
		SyBlobData(pWorker),SyBlobLength(pWorker),
		UNQLITE_CURSOR_MATCH_EXACT
		);
	if( rc != UNQLITE_OK ){
		return rc;
	}
	/* Remove the record from the storage engine */
	rc = unqlite_kv_cursor_delete_entry(pCol->pCursor);
	/* Finally, Remove the record from the cache */
	unqliteCollectionCacheRemoveRecord(pCol,nId);
	if( rc == UNQLITE_OK ){
		pCol->nTotRec--;
		if( wr_header ){
			/* Relect in the collection header */
			rc = CollectionSetHeader(0,pCol,-1,pCol->nTotRec,0);
		}
	}else if( rc == UNQLITE_NOTIMPLEMENTED ){
		if( log_err ){
			unqliteGenErrorFormat(pCol->pVm->pDb,
				"Cannot delete record from collection '%z' due to a read-only Key/Value storage engine",
				&pCol->sName
				);
		}
	}
	return rc;
}
Esempio n. 5
0
void Storage::scan(const char *keyData, uint keySize,
                   const std::function<bool(void *keyPtr, int keySize, void *valuePtr, int valueSize)> &resultHandler,
                   const std::function<void(const Storage::Error &error)> &errorHandler)
{
    if (!d->db) {
        Error error(d->name.toStdString(), -1, "Not open");
        errorHandler(error);
        return;
    }

    unqlite_kv_cursor *cursor;

    int rc = unqlite_kv_cursor_init(d->db, &cursor);
    if (rc != UNQLITE_OK) {
        d->reportDbError("unqlite_kv_cursor_init", rc, errorHandler);
        return;
    }

    void *keyBuffer = nullptr;
    int keyBufferLength = 0;
    void *dataBuffer = nullptr;
    //FIXME: 64bit ints, but feeding int lenghts to the callbacks. can result in truncation
    unqlite_int64 dataBufferLength = 0;
    if (!keyData || keySize == 0) {
        for (unqlite_kv_cursor_first_entry(cursor); unqlite_kv_cursor_valid_entry(cursor); unqlite_kv_cursor_next_entry(cursor)) {
            fetchCursorData(cursor, &keyBuffer, &keyBufferLength, &dataBuffer, &dataBufferLength, resultHandler);
        }
    } else {
        rc = unqlite_kv_cursor_seek(cursor, keyData, keySize, UNQLITE_CURSOR_MATCH_EXACT);
        if (rc == UNQLITE_OK) {
            fetchCursorData(cursor, &keyBuffer, &keyBufferLength, &dataBuffer, &dataBufferLength, resultHandler);
        } else {
            std::cout << "couldn't find value " << std::string(keyData, keySize) << std::endl;
        }

    }

    free(keyBuffer);
    free(dataBuffer);
    unqlite_kv_cursor_release(d->db, cursor);
}