2016-11-17 20:07:59 +00:00
/***
* Here are the wrappers for the lightning database
2016-12-14 17:07:43 +00:00
* NOTE : In this implementation , the database will contain the base32 encoded value
* of the multihash key if the file exists on disk .
2016-11-17 20:07:59 +00:00
*/
# include <stdlib.h>
2016-11-30 16:46:41 +00:00
# include <sys/stat.h>
# include <errno.h>
# include <string.h>
2016-11-17 20:07:59 +00:00
# include "lmdb.h"
# include "ipfs/repo/fsrepo/lmdb_datastore.h"
2016-12-05 22:23:58 +00:00
/***
* retrieve a record from the database and put in a pre - sized buffer
* @ param key the key to look for
* @ param key_size the length of the key
* @ param data the data that is retrieved
* @ param max_data_size the length of the data buffer
* @ param data_size the length of the data that was found in the database
* @ param datastore where to look for the data
* @ returns true ( 1 ) on success
*/
int repo_fsrepo_lmdb_get ( const char * key , size_t key_size , unsigned char * data , size_t max_data_size , size_t * data_size , const struct Datastore * datastore ) {
int retVal ;
MDB_txn * mdb_txn ;
MDB_dbi mdb_dbi ;
struct MDB_val db_key ;
struct MDB_val db_value ;
MDB_env * mdb_env = ( MDB_env * ) datastore - > handle ;
if ( mdb_env = = NULL )
return 0 ;
// open transaction
retVal = mdb_txn_begin ( mdb_env , NULL , 0 , & mdb_txn ) ;
if ( retVal ! = 0 )
return 0 ;
retVal = mdb_dbi_open ( mdb_txn , NULL , MDB_DUPSORT , & mdb_dbi ) ;
if ( retVal ! = 0 ) {
mdb_txn_commit ( mdb_txn ) ;
return 0 ;
}
// prepare data
db_key . mv_size = key_size ;
db_key . mv_data = ( char * ) key ;
2016-12-15 17:38:08 +00:00
//printf("Looking for data that has a key size of %lu that starts with %02x and ends with %02x\n", db_key.mv_size, ((char*)db_key.mv_data)[0], ((char*)db_key.mv_data)[db_key.mv_size - 1]);
2016-12-05 22:23:58 +00:00
retVal = mdb_get ( mdb_txn , mdb_dbi , & db_key , & db_value ) ;
if ( retVal ! = 0 ) {
2016-12-15 17:38:08 +00:00
//mdb_dbi_close(mdb_env, mdb_dbi);
2016-12-05 22:23:58 +00:00
mdb_txn_commit ( mdb_txn ) ;
return 0 ;
}
// now copy the data
if ( db_value . mv_size > max_data_size ) {
2016-12-15 17:38:08 +00:00
//mdb_dbi_close(mdb_env, mdb_dbi);
2016-12-05 22:23:58 +00:00
mdb_txn_commit ( mdb_txn ) ;
return 0 ;
}
// set return values
memcpy ( data , db_value . mv_data , db_value . mv_size ) ;
( * data_size ) = db_value . mv_size ;
// clean up
2016-12-15 17:38:08 +00:00
//mdb_dbi_close(mdb_env, mdb_dbi);
2016-12-05 22:23:58 +00:00
mdb_txn_commit ( mdb_txn ) ;
return 1 ;
}
2016-11-30 16:46:41 +00:00
/**
2016-12-05 22:23:58 +00:00
* Write data to the datastore with the specified key
2016-11-30 16:46:41 +00:00
* @ param key the key
2016-12-05 22:23:58 +00:00
* @ param key_size the length of the key
* @ param data the data to be written
* @ param data_size the length of the data to be written
* @ param datastore the datastore to write to
2016-11-30 16:46:41 +00:00
* @ returns true ( 1 ) on success
*/
2016-12-05 22:23:58 +00:00
int repo_fsrepo_lmdb_put ( unsigned const char * key , size_t key_size , unsigned char * data , size_t data_size , const struct Datastore * datastore ) {
2016-11-30 16:46:41 +00:00
int retVal ;
MDB_txn * mdb_txn ;
MDB_dbi mdb_dbi ;
struct MDB_val db_key ;
struct MDB_val db_value ;
MDB_env * mdb_env = ( MDB_env * ) datastore - > handle ;
if ( mdb_env = = NULL )
return 0 ;
// open transaction
retVal = mdb_txn_begin ( mdb_env , NULL , 0 , & mdb_txn ) ;
if ( retVal ! = 0 )
return 0 ;
2016-12-05 19:34:10 +00:00
retVal = mdb_dbi_open ( mdb_txn , NULL , MDB_DUPSORT , & mdb_dbi ) ;
2016-11-30 16:46:41 +00:00
if ( retVal ! = 0 )
return 0 ;
2016-12-05 19:34:10 +00:00
// prepare data
2016-12-01 18:08:30 +00:00
db_key . mv_size = key_size ;
2016-11-30 16:46:41 +00:00
db_key . mv_data = ( char * ) key ;
2016-12-05 19:34:10 +00:00
// write
2016-12-05 11:54:21 +00:00
db_value . mv_size = data_size ;
db_value . mv_data = data ;
2016-12-05 19:34:10 +00:00
retVal = mdb_put ( mdb_txn , mdb_dbi , & db_key , & db_value , MDB_NODUPDATA | MDB_NOOVERWRITE ) ;
if ( retVal = = 0 ) // the normal case
retVal = 1 ;
else {
if ( retVal = = MDB_KEYEXIST ) // We tried to add a key that already exists. Skip.
retVal = 1 ;
else
retVal = 0 ;
}
2016-11-30 16:46:41 +00:00
// cleanup
2016-12-15 17:38:08 +00:00
//mdb_dbi_close(mdb_env, mdb_dbi);
2016-11-30 16:46:41 +00:00
mdb_txn_commit ( mdb_txn ) ;
2016-12-05 19:34:10 +00:00
return retVal ;
2016-11-30 16:46:41 +00:00
}
2016-11-17 20:07:59 +00:00
/**
* Open an lmdb database with the given parameters .
* Note : for now , the parameters are not used
* @ param argc number of parameters in the following array
* @ param argv an array of parameters
*/
int repo_fsrepro_lmdb_open ( int argc , char * * argv , struct Datastore * datastore ) {
// create environment
struct MDB_env * mdb_env ;
int retVal = mdb_env_create ( & mdb_env ) ;
if ( retVal < 0 ) {
mdb_env_close ( mdb_env ) ;
return 0 ;
}
// open the environment
2016-11-30 16:46:41 +00:00
retVal = mdb_env_open ( mdb_env , datastore - > path , 0 , S_IRWXU ) ;
2016-11-17 20:07:59 +00:00
if ( retVal < 0 ) {
mdb_env_close ( mdb_env ) ;
return 0 ;
}
datastore - > handle = ( void * ) mdb_env ;
return 1 ;
}
/***
* Close an LMDB database
* NOTE : for now , argc and argv are not used
* @ param argc number of parameters in the argv array
* @ param argv parameters to be passed in
* @ param datastore the datastore struct that contains information about the opened database
*/
2016-12-01 18:08:30 +00:00
int repo_fsrepo_lmdb_close ( struct Datastore * datastore ) {
2016-11-17 20:07:59 +00:00
struct MDB_env * mdb_env = ( struct MDB_env * ) datastore - > handle ;
mdb_env_close ( mdb_env ) ;
return 1 ;
}
/***
* Places the LMDB methods into the datastore ' s function pointers
* @ param datastore the datastore to fill
* @ returns true ( 1 ) on success ;
*/
int repo_fsrepo_lmdb_cast ( struct Datastore * datastore ) {
datastore - > datastore_open = & repo_fsrepro_lmdb_open ;
datastore - > datastore_close = & repo_fsrepo_lmdb_close ;
2016-11-30 16:46:41 +00:00
datastore - > datastore_put = & repo_fsrepo_lmdb_put ;
2016-12-05 22:23:58 +00:00
datastore - > datastore_get = & repo_fsrepo_lmdb_get ;
2016-11-17 20:07:59 +00:00
return 1 ;
}
2016-11-30 16:46:41 +00:00
/***
* Creates the directory
* @ param datastore contains the path that needs to be created
* @ returns true ( 1 ) on success
*/
int repo_fsrepo_lmdb_create_directory ( struct Datastore * datastore ) {
2017-01-12 21:45:44 +00:00
# ifdef __MINGW32__
return mkdir ( datastore - > path ) = = 0 ;
# else
2016-11-30 16:46:41 +00:00
return mkdir ( datastore - > path , S_IRWXU ) = = 0 ;
2017-01-12 21:45:44 +00:00
# endif
2016-11-30 16:46:41 +00:00
}