Merge pull request #942 from ajbeamon/remove-cluster-from-bindings

Remove cluster from bindings
This commit is contained in:
Alec Grieser 2019-01-24 14:39:09 -08:00 committed by GitHub
commit 04b94e74c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 684 additions and 913 deletions

4
.gitignore vendored
View File

@ -16,7 +16,9 @@ packaging/msi/FDBInstaller.msi
*.pom
bindings/java/pom*.xml
bindings/java/src*/main/overview.html
bindings/java/src*/main/com/apple/foundationdb/*Options.java
bindings/java/src*/main/com/apple/foundationdb/NetworkOptions.java
bindings/java/src*/main/com/apple/foundationdb/DatabaseOptions.java
bindings/java/src*/main/com/apple/foundationdb/TransactionOptions.java
bindings/java/src*/main/com/apple/foundationdb/StreamingMode.java
bindings/java/src*/main/com/apple/foundationdb/MutationType.java
bindings/java/src*/main/com/apple/foundationdb/ConflictRangeType.java

View File

@ -19,6 +19,7 @@
*/
#define FDB_API_VERSION 610
#define FDB_INCLUDE_LEGACY_TYPES
#include "fdbclient/MultiVersionTransaction.h"
#include "foundationdb/fdb_c.h"
@ -31,17 +32,18 @@ int g_api_version = 0;
*
* type mapping:
* FDBFuture -> ThreadSingleAssignmentVarBase
* FDBCluster -> char
* FDBDatabase -> IDatabase
* FDBTransaction -> ITransaction
*/
#define TSAVB(f) ((ThreadSingleAssignmentVarBase*)(f))
#define TSAV(T, f) ((ThreadSingleAssignmentVar<T>*)(f))
#define CLUSTER(c) ((char*)c)
#define DB(d) ((IDatabase*)d)
#define TXN(t) ((ITransaction*)t)
// Legacy (pre API version 610)
#define CLUSTER(c) ((char*)c)
/*
* While we could just use the MultiVersionApi instance directly, this #define allows us to swap in any other IClientApi instance (e.g. from ThreadSafeApi)
*/
@ -132,16 +134,6 @@ fdb_error_t fdb_add_network_thread_completion_hook(void (*hook)(void*), void *ho
CATCH_AND_RETURN( API->addNetworkThreadCompletionHook(hook, hook_parameter); );
}
extern "C" DLLEXPORT
FDBFuture* fdb_cluster_configure_database( FDBCluster* c, int config_type,
int config_mode, uint8_t const* db_name,
int db_name_length )
{
// Obsolete, but needed for linker compatibility with api version 12 and below
return (FDBFuture*)ThreadFuture<Void>(client_invalid_operation()).extractPtr();
}
extern "C" DLLEXPORT
void fdb_future_cancel( FDBFuture* f ) {
CATCH_AND_DIE(
@ -235,14 +227,14 @@ fdb_error_t fdb_future_get_key( FDBFuture* f, uint8_t const** out_key,
}
extern "C" DLLEXPORT
fdb_error_t fdb_future_get_cluster( FDBFuture* f, FDBCluster** out_cluster ) {
fdb_error_t fdb_future_get_cluster_v609( FDBFuture* f, FDBCluster** out_cluster ) {
CATCH_AND_RETURN(
*out_cluster = (FDBCluster*)
( (TSAV( char*, f )->get() ) ); );
}
extern "C" DLLEXPORT
fdb_error_t fdb_future_get_database( FDBFuture* f, FDBDatabase** out_database ) {
fdb_error_t fdb_future_get_database_v609( FDBFuture* f, FDBDatabase** out_database ) {
CATCH_AND_RETURN(
*out_database = (FDBDatabase*)
( (TSAV( Reference<IDatabase>, f )->get() ).extractPtr() ); );
@ -294,7 +286,7 @@ fdb_error_t fdb_future_get_string_array(
}
extern "C" DLLEXPORT
FDBFuture* fdb_create_cluster( const char* cluster_file_path ) {
FDBFuture* fdb_create_cluster_v609( const char* cluster_file_path ) {
char *path;
if(cluster_file_path) {
path = new char[strlen(cluster_file_path) + 1];
@ -308,7 +300,7 @@ FDBFuture* fdb_create_cluster( const char* cluster_file_path ) {
}
extern "C" DLLEXPORT
fdb_error_t fdb_cluster_set_option( FDBCluster* c,
fdb_error_t fdb_cluster_set_option_v609( FDBCluster* c,
FDBClusterOption option,
uint8_t const* value,
int value_length )
@ -318,19 +310,32 @@ fdb_error_t fdb_cluster_set_option( FDBCluster* c,
}
extern "C" DLLEXPORT
void fdb_cluster_destroy( FDBCluster* c ) {
void fdb_cluster_destroy_v609( FDBCluster* c ) {
CATCH_AND_DIE( delete[] CLUSTER(c); );
}
extern "C" DLLEXPORT
FDBFuture* fdb_cluster_create_database( FDBCluster* c, uint8_t const* db_name,
FDBFuture* fdb_cluster_create_database_v609( FDBCluster* c, uint8_t const* db_name,
int db_name_length )
{
if(strncmp((const char*)db_name, "DB", db_name_length) != 0) {
return (FDBFuture*)ThreadFuture<Reference<IDatabase>>(invalid_database_name()).extractPtr();
}
return (FDBFuture*) API->createDatabase(CLUSTER(c)).extractPtr();
FDBDatabase *db;
fdb_error_t err = fdb_create_database(CLUSTER(c), &db);
if(err) {
return (FDBFuture*)ThreadFuture<Reference<IDatabase>>(Error(err)).extractPtr();
}
return (FDBFuture*)ThreadFuture<Reference<IDatabase>>(Reference<IDatabase>(DB(db))).extractPtr();
}
extern "C" DLLEXPORT
fdb_error_t fdb_create_database( const char* cluster_file_path, FDBDatabase** out_database ) {
CATCH_AND_RETURN(
*out_database = (FDBDatabase*)API->createDatabase( cluster_file_path ? cluster_file_path : "" ).extractPtr();
);
}
extern "C" DLLEXPORT
@ -663,6 +668,12 @@ fdb_error_t fdb_select_api_version_impl( int runtime_version, int header_version
// Versioned API changes -- descending order by version (new changes at top)
// FDB_API_CHANGED( function, ver ) means there is a new implementation as of ver, and a function function_(ver-1) is the old implementation
// FDB_API_REMOVED( function, ver ) means the function was removed as of ver, and function_(ver-1) is the old implementation
FDB_API_REMOVED( fdb_create_cluster, 610 );
FDB_API_REMOVED( fdb_cluster_create_database, 610 );
FDB_API_REMOVED( fdb_cluster_set_option, 610 );
FDB_API_REMOVED( fdb_cluster_destroy, 610 );
FDB_API_REMOVED( fdb_future_get_cluster, 610 );
FDB_API_REMOVED( fdb_future_get_database, 610 );
FDB_API_CHANGED( fdb_future_get_error, 23 );
FDB_API_REMOVED( fdb_future_is_error, 23 );
FDB_API_CHANGED( fdb_future_get_keyvalue_array, 14 );

View File

@ -62,7 +62,6 @@ extern "C" {
/* Pointers to these opaque types represent objects in the FDB API */
typedef struct FDB_future FDBFuture;
typedef struct FDB_cluster FDBCluster;
typedef struct FDB_database FDBDatabase;
typedef struct FDB_transaction FDBTransaction;
@ -128,12 +127,6 @@ extern "C" {
fdb_future_get_key( FDBFuture* f, uint8_t const** out_key,
int* out_key_length );
DLLEXPORT WARN_UNUSED_RESULT fdb_error_t
fdb_future_get_cluster( FDBFuture* f, FDBCluster** out_cluster );
DLLEXPORT WARN_UNUSED_RESULT fdb_error_t
fdb_future_get_database( FDBFuture* f, FDBDatabase** out_database );
DLLEXPORT WARN_UNUSED_RESULT fdb_error_t
fdb_future_get_value( FDBFuture* f, fdb_bool_t *out_present,
uint8_t const** out_value,
@ -148,17 +141,8 @@ extern "C" {
DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_future_get_string_array(FDBFuture* f,
const char*** out_strings, int* out_count);
DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_create_cluster( const char* cluster_file_path );
DLLEXPORT void fdb_cluster_destroy( FDBCluster* c );
DLLEXPORT WARN_UNUSED_RESULT fdb_error_t
fdb_cluster_set_option( FDBCluster* c, FDBClusterOption option,
uint8_t const* value, int value_length );
DLLEXPORT WARN_UNUSED_RESULT FDBFuture*
fdb_cluster_create_database( FDBCluster* c, uint8_t const* db_name,
int db_name_length );
fdb_create_database( const char* cluster_file_path, FDBDatabase** out_database );
DLLEXPORT void fdb_database_destroy( FDBDatabase* d );
@ -269,6 +253,35 @@ extern "C" {
/* LEGACY API VERSIONS */
#if FDB_API_VERSION < 610 || defined FDB_INCLUDE_LEGACY_TYPES
typedef struct FDB_cluster FDBCluster;
typedef enum {
// This option is only a placeholder for C compatibility and should not be used
FDB_CLUSTER_OPTION_DUMMY_DO_NOT_USE=-1
} FDBClusterOption;
#endif
#if FDB_API_VERSION < 610
DLLEXPORT WARN_UNUSED_RESULT fdb_error_t
fdb_future_get_cluster( FDBFuture* f, FDBCluster** out_cluster );
DLLEXPORT WARN_UNUSED_RESULT fdb_error_t
fdb_future_get_database( FDBFuture* f, FDBDatabase** out_database );
DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_create_cluster( const char* cluster_file_path );
DLLEXPORT void fdb_cluster_destroy( FDBCluster* c );
DLLEXPORT WARN_UNUSED_RESULT fdb_error_t
fdb_cluster_set_option( FDBCluster* c, FDBClusterOption option,
uint8_t const* value, int value_length );
DLLEXPORT WARN_UNUSED_RESULT FDBFuture*
fdb_cluster_create_database( FDBCluster* c, uint8_t const* db_name,
int db_name_length );
#endif
#if FDB_API_VERSION < 23
DLLEXPORT WARN_UNUSED_RESULT fdb_error_t
fdb_future_get_error( FDBFuture* f,

View File

@ -236,22 +236,8 @@ FDBDatabase* openDatabase(struct ResultSet *rs, pthread_t *netThread) {
checkError(fdb_setup_network(), "setup network", rs);
pthread_create(netThread, NULL, &runNetwork, NULL);
FDBFuture *f = fdb_create_cluster(NULL);
checkError(fdb_future_block_until_ready(f), "block for cluster", rs);
FDBCluster *cluster;
checkError(fdb_future_get_cluster(f, &cluster), "get cluster", rs);
fdb_future_destroy(f);
f = fdb_cluster_create_database(cluster, (uint8_t*)"DB", 2);
checkError(fdb_future_block_until_ready(f), "block for database", rs);
FDBDatabase *db;
checkError(fdb_future_get_database(f, &db), "get database", rs);
fdb_future_destroy(f);
fdb_cluster_destroy(cluster);
checkError(fdb_create_database(NULL, &db), "create database", rs);
return db;
}

View File

@ -34,8 +34,7 @@ THREAD_FUNC networkThread(void* fdb) {
ACTOR Future<Void> _test() {
API *fdb = FDB::API::selectAPIVersion(610);
auto c = fdb->createCluster( std::string() );
auto db = c->createDatabase();
auto db = fdb->createDatabase();
state Reference<Transaction> tr( new Transaction(db) );
// tr->setVersion(1);
@ -189,13 +188,13 @@ namespace FDB {
}
Reference<Cluster> API::createCluster( std::string const& connFilename ) {
CFuture f( fdb_create_cluster( connFilename.c_str() ) );
f.blockUntilReady();
return Reference<Cluster>(new Cluster(connFilename));
}
FDBCluster* c;
throw_on_error( fdb_future_get_cluster( f.f, &c ) );
return Reference<Cluster>( new Cluster(c) );
Reference<DatabaseContext> API::createDatabase(std::string const& connFilename) {
FDBDatabase *db;
throw_on_error(fdb_create_database(connFilename.c_str(), &db));
return Reference<DatabaseContext>(new DatabaseContext(db));
}
int API::getAPIVersion() const {
@ -203,14 +202,7 @@ namespace FDB {
}
Reference<DatabaseContext> Cluster::createDatabase() {
const char *dbName = "DB";
CFuture f( fdb_cluster_create_database( c, (uint8_t*)dbName, (int)strlen(dbName) ) );
f.blockUntilReady();
FDBDatabase* db;
throw_on_error( fdb_future_get_database( f.f, &db ) );
return Reference<DatabaseContext>( new DatabaseContext(db) );
return API::getInstance()->createDatabase(connFilename.c_str());
}
void DatabaseContext::setDatabaseOption(FDBDatabaseOption option, Optional<StringRef> value) {

View File

@ -44,20 +44,21 @@ namespace FDB {
private:
FDBDatabase* db;
explicit DatabaseContext( FDBDatabase* db ) : db(db) {}
friend class API;
};
// Deprecated: Use createDatabase instead.
class Cluster : public ReferenceCounted<Cluster>, NonCopyable {
public:
~Cluster() {
fdb_cluster_destroy( c );
}
~Cluster() {}
Reference<DatabaseContext> createDatabase();
private:
explicit Cluster( FDBCluster* c ) : c(c) {}
FDBCluster* c;
explicit Cluster( std::string connFilename ) : connFilename(connFilename) {}
std::string connFilename;
friend class API;
};
@ -73,8 +74,11 @@ namespace FDB {
void runNetwork();
void stopNetwork();
// Deprecated: Use createDatabase instead.
Reference<Cluster> createCluster( std::string const& connFilename );
Reference<DatabaseContext> createDatabase( std::string const& connFilename="" );
bool evaluatePredicate(FDBErrorPredicate pred, Error const& e);
int getAPIVersion() const;

View File

@ -28,7 +28,7 @@
#include <string.h>
#endif
// Otherwise we have to type setupNetwork(), Cluster::createCluster(), etc.
// Otherwise we have to type setupNetwork(), FDB::open(), etc.
using namespace FDB;
std::map<std::string, FDBMutationType> optionInfo;
@ -1714,8 +1714,7 @@ ACTOR void startTest(std::string clusterFilename, StringRef prefix, int apiVersi
startThread(networkThread, fdb);
// Connect to the default cluster/database, and create a transaction
auto cluster = fdb->createCluster(clusterFilename);
Reference<DatabaseContext> db = cluster->createDatabase();
auto db = fdb->createDatabase(clusterFilename);
Reference<FlowTesterData> data = Reference<FlowTesterData>(new FlowTesterData(fdb));
wait(runTest(data, db, prefix));
@ -1744,8 +1743,7 @@ ACTOR void _test_versionstamp() {
fdb->setupNetwork();
startThread(networkThread, fdb);
auto c = fdb->createCluster(std::string());
auto db = c->createDatabase();
auto db = fdb->createDatabase();
state Reference<Transaction> tr(new Transaction(db));
state Future<FDBStandalone<StringRef>> ftrVersion = tr->getVersionstamp();

View File

@ -893,7 +893,7 @@ func main() {
log.Fatal("API version not equal to value selected")
}
db, e = fdb.Open(clusterFile, []byte("DB"))
db, e = fdb.OpenDatabase(clusterFile)
if e != nil {
log.Fatal(e)
}

View File

@ -28,47 +28,18 @@ package fdb
*/
import "C"
import (
"runtime"
)
// Deprecated: Use OpenDatabase or OpenDefault to obtain a database handle directly
// Cluster is a handle to a FoundationDB cluster. Cluster is a lightweight
// object that may be efficiently copied, and is safe for concurrent use by
// multiple goroutines.
//
// It is generally preferable to use Open or OpenDefault to obtain a database
// handle directly.
type Cluster struct {
*cluster
clusterFileName string
}
type cluster struct {
ptr *C.FDBCluster
}
func (c *cluster) destroy() {
C.fdb_cluster_destroy(c.ptr)
}
// OpenDatabase returns a database handle from the FoundationDB cluster. It is
// generally preferable to use Open or OpenDefault to obtain a database handle
// directly.
// Deprecated: Use OpenDatabase or OpenDefault to obtain a database handle directly
// OpenDatabase returns a database handle from the FoundationDB cluster.
//
// In the current release, the database name must be []byte("DB").
// The database name must be []byte("DB").
func (c Cluster) OpenDatabase(dbName []byte) (Database, error) {
f := C.fdb_cluster_create_database(c.ptr, byteSliceToPtr(dbName), C.int(len(dbName)))
fdb_future_block_until_ready(f)
var outd *C.FDBDatabase
if err := C.fdb_future_get_database(f, &outd); err != 0 {
return Database{}, Error{int(err)}
}
C.fdb_future_destroy(f)
d := &database{outd}
runtime.SetFinalizer(d, (*database).destroy)
return Database{d}, nil
return Open(c.clusterFileName, dbName)
}

View File

@ -30,6 +30,7 @@ package fdb
import "C"
import (
"bytes"
"fmt"
"log"
"runtime"
@ -192,17 +193,10 @@ var apiVersion int
var networkStarted bool
var networkMutex sync.Mutex
type DatabaseId struct {
clusterFile string
dbName string
}
var openClusters map[string]Cluster
var openDatabases map[DatabaseId]Database
var openDatabases map[string]Database
func init() {
openClusters = make(map[string]Cluster)
openDatabases = make(map[DatabaseId]Database)
openDatabases = make(map[string]Database)
}
func startNetwork() error {
@ -222,10 +216,9 @@ func startNetwork() error {
return nil
}
// StartNetwork initializes the FoundationDB client networking engine. It is not
// necessary to call StartNetwork when using the fdb.Open or fdb.OpenDefault
// functions to obtain a database handle. StartNetwork must not be called more
// than once.
// Deprecated: the network is started automatically when a database is opened.
// StartNetwork initializes the FoundationDB client networking engine. StartNetwork
// must not be called more than once.
func StartNetwork() error {
networkMutex.Lock()
defer networkMutex.Unlock()
@ -237,17 +230,15 @@ func StartNetwork() error {
return startNetwork()
}
// DefaultClusterFile should be passed to fdb.Open or fdb.CreateCluster to allow
// the FoundationDB C library to select the platform-appropriate default cluster
// file on the current machine.
// DefaultClusterFile should be passed to fdb.Open to allow the FoundationDB C
// library to select the platform-appropriate default cluster file on the current machine.
const DefaultClusterFile string = ""
// OpenDefault returns a database handle to the default database from the
// FoundationDB cluster identified by the DefaultClusterFile on the current
// machine. The FoundationDB client networking engine will be initialized first,
// if necessary.
// OpenDefault returns a database handle to the FoundationDB cluster identified
// by the DefaultClusterFile on the current machine. The FoundationDB client
// networking engine will be initialized first, if necessary.
func OpenDefault() (Database, error) {
return Open(DefaultClusterFile, []byte("DB"))
return OpenDatabase(DefaultClusterFile)
}
// MustOpenDefault is like OpenDefault but panics if the default database cannot
@ -260,13 +251,9 @@ func MustOpenDefault() Database {
return db
}
// Open returns a database handle to the named database from the FoundationDB
// cluster identified by the provided cluster file and database name. The
// FoundationDB client networking engine will be initialized first, if
// necessary.
//
// In the current release, the database name must be []byte("DB").
func Open(clusterFile string, dbName []byte) (Database, error) {
// Open returns a database handle to the FoundationDB cluster identified
// by the provided cluster file and database name.
func OpenDatabase(clusterFile string) (Database, error) {
networkMutex.Lock()
defer networkMutex.Unlock()
@ -283,27 +270,36 @@ func Open(clusterFile string, dbName []byte) (Database, error) {
}
}
cluster, ok := openClusters[clusterFile]
db, ok := openDatabases[clusterFile]
if !ok {
cluster, e = createCluster(clusterFile)
db, e = createDatabase(clusterFile)
if e != nil {
return Database{}, e
}
openClusters[clusterFile] = cluster
}
db, ok := openDatabases[DatabaseId{clusterFile, string(dbName)}]
if !ok {
db, e = cluster.OpenDatabase(dbName)
if e != nil {
return Database{}, e
}
openDatabases[DatabaseId{clusterFile, string(dbName)}] = db
openDatabases[clusterFile] = db
}
return db, nil
}
func MustOpenDatabase(clusterFile string) Database {
db, err := OpenDatabase(clusterFile)
if err != nil {
panic(err)
}
return db
}
// Deprecated: Use OpenDatabase instead
// The database name must be []byte("DB").
func Open(clusterFile string, dbName []byte) (Database, error) {
if bytes.Compare(dbName, []byte("DB")) != 0 {
return Database{}, Error{2013} // invalid_database_name
}
return OpenDatabase(clusterFile)
}
// Deprecated: Use MustOpenDatabase instead
// MustOpen is like Open but panics if the database cannot be opened.
func MustOpen(clusterFile string, dbName []byte) Database {
db, err := Open(clusterFile, dbName)
@ -313,7 +309,7 @@ func MustOpen(clusterFile string, dbName []byte) Database {
return db
}
func createCluster(clusterFile string) (Cluster, error) {
func createDatabase(clusterFile string) (Database, error) {
var cf *C.char
if len(clusterFile) != 0 {
@ -321,23 +317,18 @@ func createCluster(clusterFile string) (Cluster, error) {
defer C.free(unsafe.Pointer(cf))
}
f := C.fdb_create_cluster(cf)
fdb_future_block_until_ready(f)
var outc *C.FDBCluster
if err := C.fdb_future_get_cluster(f, &outc); err != 0 {
return Cluster{}, Error{int(err)}
var outdb *C.FDBDatabase
if err := C.fdb_create_database(cf, &outdb); err != 0 {
return Database{}, Error{int(err)}
}
C.fdb_future_destroy(f)
db := &database{outdb}
runtime.SetFinalizer(db, (*database).destroy)
c := &cluster{outc}
runtime.SetFinalizer(c, (*cluster).destroy)
return Cluster{c}, nil
return Database{db}, nil
}
// Deprecated: Use OpenDatabase instead.
// CreateCluster returns a cluster handle to the FoundationDB cluster identified
// by the provided cluster file.
func CreateCluster(clusterFile string) (Cluster, error) {
@ -352,7 +343,7 @@ func CreateCluster(clusterFile string) (Cluster, error) {
return Cluster{}, errNetworkNotSetup
}
return createCluster(clusterFile)
return Cluster{clusterFile}, nil
}
func byteSliceToPtr(b []byte) *C.uint8_t {

View File

@ -25,7 +25,7 @@
#include <foundationdb/fdb_c.h>
#define JNI_NULL 0
#define JNI_NULL nullptr
#if defined(__GNUG__)
#define thread_local __thread
@ -38,15 +38,15 @@
#error Missing thread local storage
#endif
static JavaVM* g_jvm = 0;
static thread_local JNIEnv* g_thread_jenv = 0; // Defined for the network thread once it is running, and for any thread that has called registerCallback
static thread_local jmethodID g_IFutureCallback_call_methodID = 0;
static JavaVM* g_jvm = nullptr;
static thread_local JNIEnv* g_thread_jenv = nullptr; // Defined for the network thread once it is running, and for any thread that has called registerCallback
static thread_local jmethodID g_IFutureCallback_call_methodID = JNI_NULL;
static thread_local bool is_external = false;
void detachIfExternalThread(void *ignore) {
if(is_external && g_thread_jenv != 0) {
g_thread_jenv = 0;
g_IFutureCallback_call_methodID = 0;
if(is_external && g_thread_jenv != nullptr) {
g_thread_jenv = nullptr;
g_IFutureCallback_call_methodID = JNI_NULL;
g_jvm->DetachCurrentThread();
}
}
@ -58,7 +58,7 @@ void throwOutOfMem(JNIEnv *jenv) {
if(jenv->ExceptionOccurred())
return;
if( jenv->ThrowNew( illegalArgClass, NULL ) != 0 ) {
if( jenv->ThrowNew( illegalArgClass, nullptr ) != 0 ) {
if( !jenv->ExceptionOccurred() ) {
jenv->FatalError("Could not throw OutOfMemoryError");
} else {
@ -68,7 +68,7 @@ void throwOutOfMem(JNIEnv *jenv) {
}
}
static jthrowable getThrowable(JNIEnv *jenv, fdb_error_t e, const char* msg = NULL) {
static jthrowable getThrowable(JNIEnv *jenv, fdb_error_t e, const char* msg = nullptr) {
jclass excepClass = jenv->FindClass("com/apple/foundationdb/FDBException");
if(jenv->ExceptionOccurred())
return JNI_NULL;
@ -128,11 +128,11 @@ static bool findCallbackMethods(JNIEnv *jenv) {
}
static void callCallback( FDBFuture* f, void* data ) {
if (g_thread_jenv == 0) {
if (g_thread_jenv == nullptr) {
// We are on an external thread and must attach to the JVM.
// The shutdown hook will later detach this thread.
is_external = true;
if( g_jvm != 0 && g_jvm->AttachCurrentThreadAsDaemon((void **) &g_thread_jenv, JNI_NULL) == JNI_OK ) {
if( g_jvm != nullptr && g_jvm->AttachCurrentThreadAsDaemon((void **) &g_thread_jenv, nullptr) == JNI_OK ) {
if( !findCallbackMethods( g_thread_jenv ) ) {
g_thread_jenv->FatalError("FDB: Could not find callback method.\n");
}
@ -169,9 +169,9 @@ JNIEXPORT void JNICALL Java_com_apple_foundationdb_NativeFuture_Future_1register
}
FDBFuture *f = (FDBFuture *)future;
// This is documented as not throwing, but simply returning NULL on OMM.
// This is documented as not throwing, but simply returning null on OOM.
// As belt and suspenders, we will check for pending exceptions and then,
// if there are none and the result is NULL, we'll throw our own OMM.
// if there are none and the result is null, we'll throw our own OOM.
callback = jenv->NewGlobalRef( callback );
if( !callback ) {
if( !jenv->ExceptionOccurred() )
@ -280,7 +280,7 @@ JNIEXPORT jobject JNICALL Java_com_apple_foundationdb_FutureStrings_FutureString
jclass str_clazz = jenv->FindClass("java/lang/String");
if( jenv->ExceptionOccurred() )
return JNI_NULL;
jobjectArray arr = jenv->NewObjectArray(count, str_clazz, NULL);
jobjectArray arr = jenv->NewObjectArray(count, str_clazz, JNI_NULL);
if( !arr ) {
if( !jenv->ExceptionOccurred() )
throwOutOfMem(jenv);
@ -327,7 +327,7 @@ JNIEXPORT jobject JNICALL Java_com_apple_foundationdb_FutureResults_FutureResult
return JNI_NULL;
}
jbyteArray lastKey = NULL;
jbyteArray lastKey = JNI_NULL;
if(count) {
lastKey = jenv->NewByteArray(kvs[count - 1].key_length);
if( !lastKey ) {
@ -378,7 +378,7 @@ JNIEXPORT jobject JNICALL Java_com_apple_foundationdb_FutureResults_FutureResult
throwOutOfMem(jenv);
return JNI_NULL;
}
uint8_t *keyvalues_barr = (uint8_t *)jenv->GetByteArrayElements(keyValueArray, NULL);
uint8_t *keyvalues_barr = (uint8_t *)jenv->GetByteArrayElements(keyValueArray, JNI_NULL);
if (!keyvalues_barr) {
throwRuntimeEx( jenv, "Error getting handle to native resources" );
return JNI_NULL;
@ -393,7 +393,7 @@ JNIEXPORT jobject JNICALL Java_com_apple_foundationdb_FutureResults_FutureResult
return JNI_NULL;
}
jint *length_barr = jenv->GetIntArrayElements(lengthArray, NULL);
jint *length_barr = jenv->GetIntArrayElements(lengthArray, JNI_NULL);
if( !length_barr ) {
if( !jenv->ExceptionOccurred() )
throwOutOfMem(jenv);
@ -480,38 +480,6 @@ JNIEXPORT jbyteArray JNICALL Java_com_apple_foundationdb_FutureKey_FutureKey_1ge
return result;
}
JNIEXPORT jlong JNICALL Java_com_apple_foundationdb_FutureCluster_FutureCluster_1get(JNIEnv *jenv, jobject, jlong future) {
if( !future ) {
throwParamNotNull(jenv);
return 0;
}
FDBFuture *f = (FDBFuture *)future;
FDBCluster *cluster;
fdb_error_t err = fdb_future_get_cluster(f, &cluster);
if( err ) {
safeThrow( jenv, getThrowable( jenv, err ) );
return 0;
}
return (jlong)cluster;
}
JNIEXPORT jlong JNICALL Java_com_apple_foundationdb_FutureDatabase_FutureDatabase_1get(JNIEnv *jenv, jobject, jlong future) {
if( !future ) {
throwParamNotNull(jenv);
return 0;
}
FDBFuture *f = (FDBFuture *)future;
FDBDatabase *database;
fdb_error_t err = fdb_future_get_database(f, &database);
if( err ) {
safeThrow( jenv, getThrowable( jenv, err ) );
return 0;
}
return (jlong)database;
}
JNIEXPORT jlong JNICALL Java_com_apple_foundationdb_FDBDatabase_Database_1createTransaction(JNIEnv *jenv, jobject, jlong dbPtr) {
if( !dbPtr ) {
throwParamNotNull(jenv);
@ -541,11 +509,11 @@ JNIEXPORT void JNICALL Java_com_apple_foundationdb_FDBDatabase_Database_1setOpti
return;
}
FDBDatabase *c = (FDBDatabase *)dPtr;
uint8_t *barr = NULL;
uint8_t *barr = nullptr;
int size = 0;
if(value != 0) {
barr = (uint8_t *)jenv->GetByteArrayElements( value, NULL );
if(value != JNI_NULL) {
barr = (uint8_t *)jenv->GetByteArrayElements( value, JNI_NULL );
if (!barr) {
throwRuntimeEx( jenv, "Error getting handle to native resources" );
return;
@ -553,7 +521,7 @@ JNIEXPORT void JNICALL Java_com_apple_foundationdb_FDBDatabase_Database_1setOpti
size = jenv->GetArrayLength( value );
}
fdb_error_t err = fdb_database_set_option( c, (FDBDatabaseOption)code, barr, size );
if(value != 0)
if(value != JNI_NULL)
jenv->ReleaseByteArrayElements( value, (jbyte *)barr, JNI_ABORT );
if( err ) {
safeThrow( jenv, getThrowable( jenv, err ) );
@ -564,69 +532,28 @@ JNIEXPORT jboolean JNICALL Java_com_apple_foundationdb_FDB_Error_1predicate(JNIE
return (jboolean)fdb_error_predicate(predicate, code);
}
JNIEXPORT jlong JNICALL Java_com_apple_foundationdb_FDB_Cluster_1create(JNIEnv *jenv, jobject, jstring clusterFileName) {
const char* fileName = 0;
if(clusterFileName != 0) {
fileName = jenv->GetStringUTFChars(clusterFileName, 0);
if( jenv->ExceptionOccurred() )
JNIEXPORT jlong JNICALL Java_com_apple_foundationdb_FDB_Database_1create(JNIEnv *jenv, jobject, jstring clusterFileName) {
const char* fileName = nullptr;
if(clusterFileName != JNI_NULL) {
fileName = jenv->GetStringUTFChars(clusterFileName, JNI_NULL);
if(jenv->ExceptionOccurred()) {
return 0;
}
FDBFuture *cluster = fdb_create_cluster( fileName );
if(clusterFileName != 0)
jenv->ReleaseStringUTFChars( clusterFileName, fileName );
return (jlong)cluster;
}
JNIEXPORT void JNICALL Java_com_apple_foundationdb_Cluster_Cluster_1setOption(JNIEnv *jenv, jobject, jlong cPtr, jint code, jbyteArray value) {
if( !cPtr ) {
throwParamNotNull(jenv);
return;
}
FDBCluster *c = (FDBCluster *)cPtr;
uint8_t *barr = NULL;
int size = 0;
if(value != 0) {
barr = (uint8_t *)jenv->GetByteArrayElements( value, NULL );
if (!barr) {
throwRuntimeEx( jenv, "Error getting handle to native resources" );
return;
}
size = jenv->GetArrayLength( value );
}
fdb_error_t err = fdb_cluster_set_option( c, (FDBClusterOption)code, barr, size );
if(value != 0)
jenv->ReleaseByteArrayElements( value, (jbyte *)barr, JNI_ABORT );
if( err ) {
safeThrow( jenv, getThrowable( jenv, err ) );
}
}
JNIEXPORT void JNICALL Java_com_apple_foundationdb_Cluster_Cluster_1dispose(JNIEnv *jenv, jobject, jlong cPtr) {
if( !cPtr ) {
throwParamNotNull(jenv);
return;
}
fdb_cluster_destroy( (FDBCluster *)cPtr );
}
FDBDatabase *db;
fdb_error_t err = fdb_create_database(fileName, &db);
JNIEXPORT jlong JNICALL Java_com_apple_foundationdb_Cluster_Cluster_1createDatabase(JNIEnv *jenv, jobject, jlong cPtr, jbyteArray dbNameBytes) {
if( !cPtr || !dbNameBytes ) {
throwParamNotNull(jenv);
return 0;
if(clusterFileName != JNI_NULL) {
jenv->ReleaseStringUTFChars(clusterFileName, fileName);
}
FDBCluster *cluster = (FDBCluster *)cPtr;
uint8_t *barr = (uint8_t *)jenv->GetByteArrayElements( dbNameBytes, NULL );
if (!barr) {
throwRuntimeEx( jenv, "Error getting handle to native resources" );
if(err) {
safeThrow(jenv, getThrowable(jenv, err));
return 0;
}
int size = jenv->GetArrayLength( dbNameBytes );
FDBFuture * f = fdb_cluster_create_database( cluster, barr, size );
jenv->ReleaseByteArrayElements( dbNameBytes, (jbyte *)barr, JNI_ABORT );
return (jlong)f;
return (jlong)db;
}
JNIEXPORT void JNICALL Java_com_apple_foundationdb_FDBTransaction_Transaction_1setVersion(JNIEnv *jenv, jobject, jlong tPtr, jlong version) {
@ -655,7 +582,7 @@ JNIEXPORT jlong JNICALL Java_com_apple_foundationdb_FDBTransaction_Transaction_1
}
FDBTransaction *tr = (FDBTransaction *)tPtr;
uint8_t *barr = (uint8_t *)jenv->GetByteArrayElements( keyBytes, NULL );
uint8_t *barr = (uint8_t *)jenv->GetByteArrayElements( keyBytes, JNI_NULL );
if(!barr) {
if( !jenv->ExceptionOccurred() )
throwRuntimeEx( jenv, "Error getting handle to native resources" );
@ -675,7 +602,7 @@ JNIEXPORT jlong JNICALL Java_com_apple_foundationdb_FDBTransaction_Transaction_1
}
FDBTransaction *tr = (FDBTransaction *)tPtr;
uint8_t *barr = (uint8_t *)jenv->GetByteArrayElements( keyBytes, NULL );
uint8_t *barr = (uint8_t *)jenv->GetByteArrayElements( keyBytes, JNI_NULL );
if(!barr) {
if( !jenv->ExceptionOccurred() )
throwRuntimeEx( jenv, "Error getting handle to native resources" );
@ -697,14 +624,14 @@ JNIEXPORT jlong JNICALL Java_com_apple_foundationdb_FDBTransaction_Transaction_1
}
FDBTransaction *tr = (FDBTransaction *)tPtr;
uint8_t *barrBegin = (uint8_t *)jenv->GetByteArrayElements( keyBeginBytes, NULL );
uint8_t *barrBegin = (uint8_t *)jenv->GetByteArrayElements( keyBeginBytes, JNI_NULL );
if (!barrBegin) {
if( !jenv->ExceptionOccurred() )
throwRuntimeEx( jenv, "Error getting handle to native resources" );
return 0;
}
uint8_t *barrEnd = (uint8_t *)jenv->GetByteArrayElements( keyEndBytes, NULL );
uint8_t *barrEnd = (uint8_t *)jenv->GetByteArrayElements( keyEndBytes, JNI_NULL );
if (!barrEnd) {
jenv->ReleaseByteArrayElements( keyBeginBytes, (jbyte *)barrBegin, JNI_ABORT );
if( !jenv->ExceptionOccurred() )
@ -728,14 +655,14 @@ JNIEXPORT void JNICALL Java_com_apple_foundationdb_FDBTransaction_Transaction_1s
}
FDBTransaction *tr = (FDBTransaction *)tPtr;
uint8_t *barrKey = (uint8_t *)jenv->GetByteArrayElements( keyBytes, NULL );
uint8_t *barrKey = (uint8_t *)jenv->GetByteArrayElements( keyBytes, JNI_NULL );
if (!barrKey) {
if( !jenv->ExceptionOccurred() )
throwRuntimeEx( jenv, "Error getting handle to native resources" );
return;
}
uint8_t *barrValue = (uint8_t *)jenv->GetByteArrayElements( valueBytes, NULL );
uint8_t *barrValue = (uint8_t *)jenv->GetByteArrayElements( valueBytes, JNI_NULL );
if (!barrValue) {
jenv->ReleaseByteArrayElements( keyBytes, (jbyte *)barrKey, JNI_ABORT );
if( !jenv->ExceptionOccurred() )
@ -757,7 +684,7 @@ JNIEXPORT void JNICALL Java_com_apple_foundationdb_FDBTransaction_Transaction_1c
}
FDBTransaction *tr = (FDBTransaction *)tPtr;
uint8_t *barr = (uint8_t *)jenv->GetByteArrayElements( keyBytes, NULL );
uint8_t *barr = (uint8_t *)jenv->GetByteArrayElements( keyBytes, JNI_NULL );
if (!barr) {
if( !jenv->ExceptionOccurred() )
throwRuntimeEx( jenv, "Error getting handle to native resources" );
@ -775,14 +702,14 @@ JNIEXPORT void JNICALL Java_com_apple_foundationdb_FDBTransaction_Transaction_1c
}
FDBTransaction *tr = (FDBTransaction *)tPtr;
uint8_t *barrKeyBegin = (uint8_t *)jenv->GetByteArrayElements( keyBeginBytes, NULL );
uint8_t *barrKeyBegin = (uint8_t *)jenv->GetByteArrayElements( keyBeginBytes, JNI_NULL );
if (!barrKeyBegin) {
if( !jenv->ExceptionOccurred() )
throwRuntimeEx( jenv, "Error getting handle to native resources" );
return;
}
uint8_t *barrKeyEnd = (uint8_t *)jenv->GetByteArrayElements( keyEndBytes, NULL );
uint8_t *barrKeyEnd = (uint8_t *)jenv->GetByteArrayElements( keyEndBytes, JNI_NULL );
if (!barrKeyEnd) {
jenv->ReleaseByteArrayElements( keyBeginBytes, (jbyte *)barrKeyBegin, JNI_ABORT );
if( !jenv->ExceptionOccurred() )
@ -805,14 +732,14 @@ JNIEXPORT void JNICALL Java_com_apple_foundationdb_FDBTransaction_Transaction_1m
}
FDBTransaction *tr = (FDBTransaction *)tPtr;
uint8_t *barrKey = (uint8_t *)jenv->GetByteArrayElements( key, NULL );
uint8_t *barrKey = (uint8_t *)jenv->GetByteArrayElements( key, JNI_NULL );
if (!barrKey) {
if( !jenv->ExceptionOccurred() )
throwRuntimeEx( jenv, "Error getting handle to native resources" );
return;
}
uint8_t *barrValue = (uint8_t *)jenv->GetByteArrayElements( value, NULL );
uint8_t *barrValue = (uint8_t *)jenv->GetByteArrayElements( value, JNI_NULL );
if (!barrValue) {
jenv->ReleaseByteArrayElements( key, (jbyte *)barrKey, JNI_ABORT );
if( !jenv->ExceptionOccurred() )
@ -845,11 +772,11 @@ JNIEXPORT void JNICALL Java_com_apple_foundationdb_FDBTransaction_Transaction_1s
return;
}
FDBTransaction *tr = (FDBTransaction *)tPtr;
uint8_t *barr = NULL;
uint8_t *barr = nullptr;
int size = 0;
if(value != 0) {
barr = (uint8_t *)jenv->GetByteArrayElements( value, NULL );
if(value != JNI_NULL) {
barr = (uint8_t *)jenv->GetByteArrayElements( value, JNI_NULL );
if (!barr) {
if( !jenv->ExceptionOccurred() )
throwRuntimeEx( jenv, "Error getting handle to native resources" );
@ -858,7 +785,7 @@ JNIEXPORT void JNICALL Java_com_apple_foundationdb_FDBTransaction_Transaction_1s
size = jenv->GetArrayLength( value );
}
fdb_error_t err = fdb_transaction_set_option( tr, (FDBTransactionOption)code, barr, size );
if(value != 0)
if(value != JNI_NULL)
jenv->ReleaseByteArrayElements( value, (jbyte *)barr, JNI_ABORT );
if( err ) {
safeThrow( jenv, getThrowable( jenv, err ) );
@ -897,7 +824,7 @@ JNIEXPORT jlong JNICALL Java_com_apple_foundationdb_FDBTransaction_Transaction_1
}
FDBTransaction *tr = (FDBTransaction *)tPtr;
uint8_t *barr = (uint8_t *)jenv->GetByteArrayElements( key, NULL );
uint8_t *barr = (uint8_t *)jenv->GetByteArrayElements( key, JNI_NULL );
if (!barr) {
if( !jenv->ExceptionOccurred() )
throwRuntimeEx( jenv, "Error getting handle to native resources" );
@ -944,7 +871,7 @@ JNIEXPORT jlong JNICALL Java_com_apple_foundationdb_FDBTransaction_Transaction_1
}
FDBTransaction *tr = (FDBTransaction *)tPtr;
uint8_t *barr = (uint8_t *)jenv->GetByteArrayElements( key, NULL );
uint8_t *barr = (uint8_t *)jenv->GetByteArrayElements( key, JNI_NULL );
if (!barr) {
if( !jenv->ExceptionOccurred() )
throwRuntimeEx( jenv, "Error getting handle to native resources" );
@ -973,7 +900,7 @@ JNIEXPORT void JNICALL Java_com_apple_foundationdb_FDBTransaction_Transaction_1a
}
FDBTransaction *tr = (FDBTransaction *)tPtr;
uint8_t *begin_barr = (uint8_t *)jenv->GetByteArrayElements( keyBegin, NULL );
uint8_t *begin_barr = (uint8_t *)jenv->GetByteArrayElements( keyBegin, JNI_NULL );
if (!begin_barr) {
if( !jenv->ExceptionOccurred() )
throwRuntimeEx( jenv, "Error getting handle to native resources" );
@ -981,7 +908,7 @@ JNIEXPORT void JNICALL Java_com_apple_foundationdb_FDBTransaction_Transaction_1a
}
int begin_size = jenv->GetArrayLength( keyBegin );
uint8_t *end_barr = (uint8_t *)jenv->GetByteArrayElements( keyEnd, NULL );
uint8_t *end_barr = (uint8_t *)jenv->GetByteArrayElements( keyEnd, JNI_NULL );
if (!end_barr) {
jenv->ReleaseByteArrayElements( keyBegin, (jbyte *)begin_barr, JNI_ABORT );
if( !jenv->ExceptionOccurred() )
@ -1026,10 +953,10 @@ JNIEXPORT void JNICALL Java_com_apple_foundationdb_FDB_Select_1API_1version(JNIE
}
JNIEXPORT void JNICALL Java_com_apple_foundationdb_FDB_Network_1setOption(JNIEnv *jenv, jobject, jint code, jbyteArray value) {
uint8_t *barr = NULL;
uint8_t *barr = nullptr;
int size = 0;
if(value != 0) {
barr = (uint8_t *)jenv->GetByteArrayElements( value, NULL );
if(value != JNI_NULL) {
barr = (uint8_t *)jenv->GetByteArrayElements( value, JNI_NULL );
if (!barr) {
if( !jenv->ExceptionOccurred() )
throwRuntimeEx( jenv, "Error getting handle to native resources" );
@ -1038,7 +965,7 @@ JNIEXPORT void JNICALL Java_com_apple_foundationdb_FDB_Network_1setOption(JNIEnv
size = jenv->GetArrayLength( value );
}
fdb_error_t err = fdb_network_set_option((FDBNetworkOption)code, barr, size);
if(value != 0)
if(value != JNI_NULL)
jenv->ReleaseByteArrayElements( value, (jbyte *)barr, JNI_ABORT );
if( err ) {
safeThrow( jenv, getThrowable( jenv, err ) );
@ -1060,7 +987,7 @@ JNIEXPORT void JNICALL Java_com_apple_foundationdb_FDB_Network_1run(JNIEnv *jenv
return;
}
fdb_error_t hookErr = fdb_add_network_thread_completion_hook( &detachIfExternalThread, NULL );
fdb_error_t hookErr = fdb_add_network_thread_completion_hook( &detachIfExternalThread, nullptr );
if( hookErr ) {
safeThrow( jenv, getThrowable( jenv, hookErr ) );
}

View File

@ -20,33 +20,29 @@
package com.apple.foundationdb;
import java.nio.charset.Charset;
import java.util.concurrent.Executor;
/**
* The {@code Cluster} represents a connection to a physical set of cooperating machines
* running FoundationDB. A {@code Cluster} is opened with a reference to a cluster file.<br>
* running FoundationDB. A {@code Cluster} is opened with a reference to a cluster file.
*
* This class is deprecated. Use {@link FDB#open} to open a {@link Database} directly<br>
* <br>
* <b>Note:</b> {@code Cluster} objects must be {@link #close closed} when no longer in use
* in order to free any associated resources.
*/
@Deprecated
public class Cluster extends NativeObjectWrapper {
private ClusterOptions options;
private final Executor executor;
private final String clusterFile;
private static final Charset UTF8 = Charset.forName("UTF-8");
protected Cluster(String clusterFile, Executor executor) {
super(0);
protected Cluster(long cPtr, Executor executor) {
super(cPtr);
this.executor = executor;
this.options = new ClusterOptions((code, parameter) -> {
pointerReadLock.lock();
try {
Cluster_setOption(getPtr(), code, parameter);
} finally {
pointerReadLock.unlock();
}
});
this.options = new ClusterOptions((code, parameter) -> {});
this.clusterFile = clusterFile;
}
/**
@ -59,19 +55,8 @@ public class Cluster extends NativeObjectWrapper {
return options;
}
@Override
protected void finalize() throws Throwable {
try {
checkUnclosed("Cluster");
close();
}
finally {
super.finalize();
}
}
/**
* Creates a connection to a specific database on an <i>FDB</i> cluster.
* Creates a connection to the database on an <i>FDB</i> cluster.
*
* @return a {@code Future} that will be set to a {@code Database} upon
* successful connection.
@ -81,7 +66,7 @@ public class Cluster extends NativeObjectWrapper {
}
/**
* Creates a connection to a specific database on an <i>FDB</i> cluster.
* Creates a connection to the database on an <i>FDB</i> cluster.
*
* @param e the {@link Executor} to use when executing asynchronous callbacks for the database
*
@ -89,22 +74,9 @@ public class Cluster extends NativeObjectWrapper {
* successful connection.
*/
public Database openDatabase(Executor e) throws FDBException {
FutureDatabase futureDatabase;
pointerReadLock.lock();
try {
futureDatabase = new FutureDatabase(Cluster_createDatabase(getPtr(), "DB".getBytes(UTF8)), e);
} finally {
pointerReadLock.unlock();
}
return futureDatabase.join();
return FDB.instance().open(clusterFile, e);
}
@Override
protected void closeInternal(long cPtr) {
Cluster_dispose(cPtr);
}
private native void Cluster_dispose(long cPtr);
private native long Cluster_createDatabase(long cPtr, byte[] dbName);
private native void Cluster_setOption(long cPtr, int code, byte[] value) throws FDBException;
protected void closeInternal(long cPtr) {}
}

View File

@ -1,9 +1,9 @@
/*
* FutureCluster.java
* ClusterOptions.java
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
* Copyright 2013-2019 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,21 +20,14 @@
package com.apple.foundationdb;
import java.util.concurrent.Executor;
class FutureCluster extends NativeFuture<Cluster> {
private final Executor executor;
protected FutureCluster(long cPtr, Executor executor) {
super(cPtr);
this.executor = executor;
registerMarshalCallback(executor);
/**
* A set of options that can be set on a {@link Cluster}.
*
* @deprecated There are no cluster options.
*/
@Deprecated
public class ClusterOptions extends OptionsSet {
public ClusterOptions( OptionConsumer consumer ) {
super(consumer);
}
@Override
protected Cluster getIfDone_internal(long cPtr) throws FDBException {
return new Cluster(FutureCluster_get(cPtr), executor);
}
private native long FutureCluster_get(long cPtr) throws FDBException;
}

View File

@ -26,7 +26,6 @@ import java.util.function.Function;
/**
* A mutable, lexicographically ordered mapping from binary keys to binary values.
* A {@code Database} is stored on a FoundationDB {@link Cluster}.
* {@link Transaction}s are used to manipulate data within a single
* {@code Database} -- multiple, concurrent
* {@code Transaction}s on a {@code Database} enforce <b>ACID</b> properties.<br>

View File

@ -54,8 +54,8 @@ import java.util.concurrent.atomic.AtomicInteger;
* to call {@link #open}.
* <br>
* <h3>Client networking</h3>
* The network is started either implicitly with a call to a variant of {@link #open()} or
* {@link #createCluster()}, or started explicitly with a call to {@link #startNetwork()}.
* The network is started either implicitly with a call to a variant of {@link #open()}
* or started explicitly with a call to {@link #startNetwork()}.
* <br>
*
*/
@ -114,8 +114,8 @@ public class FDB {
* Returns a set of options that can be set on a the FoundationDB API. Generally,
* these options to the top level of the API affect the networking engine and
* therefore must be set before the network engine is started. The network is started
* by calls to {@link #startNetwork()} and implicitly by calls to {@link #open()} and
* {@link #createCluster()} (and their respective variants).
* by calls to {@link #startNetwork()} or implicitly by a call to {@link #open()} and
* and its variants.
*
* @return a set of options affecting this instance of the FoundationDB API
*/
@ -218,11 +218,14 @@ public class FDB {
* If the FoundationDB network has not been started, it will be started in the course of this call
* as if {@link FDB#startNetwork()} had been called.
*
* @deprecated Use {@link #open()} instead.
*
* @return a {@code CompletableFuture} that will be set to a FoundationDB {@code Cluster}.
*
* @throws FDBException on errors encountered starting the FoundationDB networking engine
* @throws IllegalStateException if the network had been previously stopped
*/
@Deprecated
public Cluster createCluster() throws IllegalStateException, FDBException {
return createCluster(null);
}
@ -232,6 +235,8 @@ public class FDB {
* has not been started, it will be started in the course of this call as if
* {@link #startNetwork()} had been called.
*
* @deprecated Use {@link #open(String)} instead.
*
* @param clusterFilePath the
* <a href="/foundationdb/administration.html#foundationdb-cluster-file" target="_blank">cluster file</a>
* defining the FoundationDB cluster. This can be {@code null} if the
@ -243,6 +248,7 @@ public class FDB {
* @throws FDBException on errors encountered starting the FoundationDB networking engine
* @throws IllegalStateException if the network had been previously stopped
*/
@Deprecated
public Cluster createCluster(String clusterFilePath) throws IllegalStateException, FDBException {
return createCluster(clusterFilePath, DEFAULT_EXECUTOR);
}
@ -253,6 +259,8 @@ public class FDB {
* {@link Executor} will be used as the default for the execution of all callbacks that
* are produced from using the resulting {@link Cluster}.
*
* @deprecated Use {@link #open(String, Executor)} instead.
*
* @param clusterFilePath the
* <a href="/foundationdb/administration.html#foundationdb-cluster-file" target="_blank">cluster file</a>
* defining the FoundationDB cluster. This can be {@code null} if the
@ -265,16 +273,10 @@ public class FDB {
* @throws FDBException on errors encountered starting the FoundationDB networking engine
* @throws IllegalStateException if the network had been previously stopped
*/
@Deprecated
public Cluster createCluster(String clusterFilePath, Executor e)
throws FDBException, IllegalStateException {
FutureCluster f;
synchronized (this) {
if (!isConnected()) {
startNetwork();
}
f = new FutureCluster(Cluster_create(clusterFilePath), e);
}
return f.join();
return new Cluster(clusterFilePath, e);
}
/**
@ -318,26 +320,21 @@ public class FDB {
* @return a {@code CompletableFuture} that will be set to a FoundationDB {@link Database}
*/
public Database open(String clusterFilePath, Executor e) throws FDBException {
FutureCluster f;
synchronized (this) {
if (!isConnected()) {
synchronized(this) {
if(!isConnected()) {
startNetwork();
}
f = new FutureCluster(Cluster_create(clusterFilePath), e);
}
Cluster c = f.join();
Database db = c.openDatabase(e);
c.close();
return db;
return new FDBDatabase(Database_create(clusterFilePath), e);
}
/**
* Initializes networking. Can only be called once. This version of
* {@code startNetwork()} will create a new thread and execute the networking
* event loop on that thread. This method is called upon {@link Database} or
* {@link Cluster} creation by default if the network has not yet
* been started. If one wishes to control what thread the network runs on,
* event loop on that thread. This method is called upon {@link Database}
* creation by default if the network has not yet been started. If one
* wishes to control what thread the network runs on,
* one should use the version of {@link #startNetwork(Executor) startNetwork()}
* that takes an {@link Executor}.<br>
* <br>
@ -472,5 +469,5 @@ public class FDB {
private native boolean Error_predicate(int predicate, int code);
private native long Cluster_create(String clusterFileName);
private native long Database_create(String clusterFilePath) throws FDBException;
}

View File

@ -1,40 +0,0 @@
/*
* FutureDatabase.java
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.apple.foundationdb;
import java.util.concurrent.Executor;
class FutureDatabase extends NativeFuture<Database> {
private final Executor executor;
FutureDatabase(long cPtr, Executor executor) {
super(cPtr);
this.executor = executor;
registerMarshalCallback(executor);
}
@Override
protected Database getIfDone_internal(long cPtr) throws FDBException {
return new FDBDatabase(FutureDatabase_get(cPtr), executor);
}
private native long FutureDatabase_get(long cPtr) throws FDBException;
}

View File

@ -33,7 +33,6 @@ import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import com.apple.foundationdb.Cluster;
import com.apple.foundationdb.Database;
import com.apple.foundationdb.FDB;
import com.apple.foundationdb.FDBException;
@ -723,9 +722,7 @@ public class AsyncStackTester {
throw new IllegalStateException("API version not correctly set to " + apiVersion);
}
//ExecutorService executor = Executors.newFixedThreadPool(2);
Cluster cl = fdb.createCluster(args.length > 2 ? args[2] : null);
Database db = cl.openDatabase();
Database db = fdb.open(args.length > 2 ? args[2] : null);
Context c = new AsynchronousContext(db, prefix);
//System.out.println("Starting test...");

View File

@ -81,17 +81,16 @@ def api_version(ver):
elif err != 0:
raise RuntimeError('FoundationDB API error')
fdb.impl.init_c_api()
list = (
'FDBError',
'predicates',
'Future',
'Cluster',
'Database',
'Transaction',
'KeyValue',
'KeySelector',
'init',
'create_cluster',
'open',
'transactional',
'options',
@ -100,6 +99,12 @@ def api_version(ver):
_add_symbols(fdb.impl, list)
if ver < 610:
globals()["init"] = getattr(fdb.impl, "init")
globals()["open"] = getattr(fdb.impl, "open_v609")
globals()["create_cluster"] = getattr(fdb.impl, "create_cluster")
globals()["Cluster"] = getattr(fdb.impl, "Cluster")
if ver > 22:
import fdb.locality

View File

@ -51,11 +51,6 @@ class _ErrorPredicates(object):
self._parent = parent
class _ClusterOptions(object):
def __init__(self, cluster):
self._parent = weakref.proxy(cluster)
class _DatabaseOptions(object):
def __init__(self, db):
self._parent = weakref.proxy(db)
@ -158,7 +153,7 @@ def fill_operations():
add_operation("bit_" + fname, v)
for scope in ['ClusterOption', 'DatabaseOption', 'TransactionOption', 'NetworkOption']:
for scope in ['DatabaseOption', 'TransactionOption', 'NetworkOption']:
fill_options(scope)
fill_options('ErrorPredicate', True)
@ -600,11 +595,6 @@ class Future(_FDBBase):
def block_until_ready(self):
self.capi.fdb_future_block_until_ready(self.fpointer)
# Depending on the event_model, block_until_ready may be remapped to do something asynchronous or
# just fail. really_block_until_ready() is always fdb_future_block_until_ready() and is used e.g.
# for database and cluster futures that should always be available very quickly
really_block_until_ready = block_until_ready
def on_ready(self, callback):
def cb_and_delref(ignore):
_unpin_callback(cbfunc[0])
@ -878,7 +868,7 @@ class FormerFuture(_FDBBase):
pass
class Database(FormerFuture):
class Database(_FDBBase):
def __init__(self, dpointer):
self.dpointer = dpointer
self.options = _DatabaseOptions(self)
@ -1097,33 +1087,25 @@ class Database(FormerFuture):
fill_operations()
class Cluster(FormerFuture):
def __init__(self, cpointer):
self.cpointer = cpointer
self.options = _ClusterOptions(self)
def __del__(self):
# print('Destroying cluster 0x%x' % self.cpointer)
self.capi.fdb_cluster_destroy(self.cpointer)
class Cluster(_FDBBase):
def __init__(self, cluster_file):
self.cluster_file = cluster_file
self.options = None
def open_database(self, name):
name = paramToBytes(name)
f = Future(self.capi.fdb_cluster_create_database(self.cpointer, name, len(name)))
f.really_block_until_ready()
dpointer = ctypes.c_void_p()
self.capi.fdb_future_get_database(f.fpointer, ctypes.byref(dpointer))
return Database(dpointer)
if name != b'DB':
raise FDBError(2013) # invalid_database_name
def _set_option(self, option, param, length):
self.capi.fdb_cluster_set_option(self.cpointer, option, param, length)
return create_database(self.cluster_file)
def create_database(cluster_file=None):
pointer = ctypes.c_void_p()
_FDBBase.capi.fdb_create_database(optionalParamToBytes(cluster_file)[0], ctypes.byref(pointer))
return Database(pointer)
def create_cluster(cluster_file=None):
f = Future(_FDBBase.capi.fdb_create_cluster(optionalParamToBytes(cluster_file)[0]))
cpointer = ctypes.c_void_p()
f.really_block_until_ready()
_FDBBase.capi.fdb_future_get_cluster(f.fpointer, ctypes.byref(cpointer))
return Cluster(cpointer)
return Cluster(cluster_file)
class KeySelector(object):
@ -1303,176 +1285,160 @@ def optionalParamToBytes(v):
_FDBBase.capi = _capi
_capi.fdb_select_api_version_impl.argtypes = [ctypes.c_int, ctypes.c_int]
_capi.fdb_select_api_version_impl.restype = ctypes.c_int
def init_c_api():
_capi.fdb_select_api_version_impl.argtypes = [ctypes.c_int, ctypes.c_int]
_capi.fdb_select_api_version_impl.restype = ctypes.c_int
_capi.fdb_get_error.argtypes = [ctypes.c_int]
_capi.fdb_get_error.restype = ctypes.c_char_p
_capi.fdb_get_error.argtypes = [ctypes.c_int]
_capi.fdb_get_error.restype = ctypes.c_char_p
_capi.fdb_error_predicate.argtypes = [ctypes.c_int, ctypes.c_int]
_capi.fdb_error_predicate.restype = ctypes.c_int
_capi.fdb_error_predicate.argtypes = [ctypes.c_int, ctypes.c_int]
_capi.fdb_error_predicate.restype = ctypes.c_int
_capi.fdb_setup_network.argtypes = []
_capi.fdb_setup_network.restype = ctypes.c_int
_capi.fdb_setup_network.errcheck = check_error_code
_capi.fdb_setup_network.argtypes = []
_capi.fdb_setup_network.restype = ctypes.c_int
_capi.fdb_setup_network.errcheck = check_error_code
_capi.fdb_network_set_option.argtypes = [ctypes.c_int, ctypes.c_void_p, ctypes.c_int]
_capi.fdb_network_set_option.restype = ctypes.c_int
_capi.fdb_network_set_option.errcheck = check_error_code
_capi.fdb_network_set_option.argtypes = [ctypes.c_int, ctypes.c_void_p, ctypes.c_int]
_capi.fdb_network_set_option.restype = ctypes.c_int
_capi.fdb_network_set_option.errcheck = check_error_code
_capi.fdb_run_network.argtypes = []
_capi.fdb_run_network.restype = ctypes.c_int
_capi.fdb_run_network.errcheck = check_error_code
_capi.fdb_run_network.argtypes = []
_capi.fdb_run_network.restype = ctypes.c_int
_capi.fdb_run_network.errcheck = check_error_code
_capi.fdb_stop_network.argtypes = []
_capi.fdb_stop_network.restype = ctypes.c_int
_capi.fdb_stop_network.errcheck = check_error_code
_capi.fdb_stop_network.argtypes = []
_capi.fdb_stop_network.restype = ctypes.c_int
_capi.fdb_stop_network.errcheck = check_error_code
_capi.fdb_future_destroy.argtypes = [ctypes.c_void_p]
_capi.fdb_future_destroy.restype = None
_capi.fdb_future_destroy.argtypes = [ctypes.c_void_p]
_capi.fdb_future_destroy.restype = None
_capi.fdb_future_release_memory.argtypes = [ctypes.c_void_p]
_capi.fdb_future_release_memory.restype = None
_capi.fdb_future_release_memory.argtypes = [ctypes.c_void_p]
_capi.fdb_future_release_memory.restype = None
_capi.fdb_future_cancel.argtypes = [ctypes.c_void_p]
_capi.fdb_future_cancel.restype = None
_capi.fdb_future_cancel.argtypes = [ctypes.c_void_p]
_capi.fdb_future_cancel.restype = None
_capi.fdb_future_block_until_ready.argtypes = [ctypes.c_void_p]
_capi.fdb_future_block_until_ready.restype = ctypes.c_int
_capi.fdb_future_block_until_ready.errcheck = check_error_code
_capi.fdb_future_block_until_ready.argtypes = [ctypes.c_void_p]
_capi.fdb_future_block_until_ready.restype = ctypes.c_int
_capi.fdb_future_block_until_ready.errcheck = check_error_code
_capi.fdb_future_is_ready.argtypes = [ctypes.c_void_p]
_capi.fdb_future_is_ready.restype = ctypes.c_int
_capi.fdb_future_is_ready.argtypes = [ctypes.c_void_p]
_capi.fdb_future_is_ready.restype = ctypes.c_int
_CBFUNC = ctypes.CFUNCTYPE(None, ctypes.c_void_p)
_CBFUNC = ctypes.CFUNCTYPE(None, ctypes.c_void_p)
_capi.fdb_future_set_callback.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
_capi.fdb_future_set_callback.restype = int
_capi.fdb_future_set_callback.errcheck = check_error_code
_capi.fdb_future_set_callback.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
_capi.fdb_future_set_callback.restype = int
_capi.fdb_future_set_callback.errcheck = check_error_code
_capi.fdb_future_get_error.argtypes = [ctypes.c_void_p]
_capi.fdb_future_get_error.restype = int
_capi.fdb_future_get_error.errcheck = check_error_code
_capi.fdb_future_get_error.argtypes = [ctypes.c_void_p]
_capi.fdb_future_get_error.restype = int
_capi.fdb_future_get_error.errcheck = check_error_code
_capi.fdb_future_get_version.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_int64)]
_capi.fdb_future_get_version.restype = ctypes.c_int
_capi.fdb_future_get_version.errcheck = check_error_code
_capi.fdb_future_get_version.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_int64)]
_capi.fdb_future_get_version.restype = ctypes.c_int
_capi.fdb_future_get_version.errcheck = check_error_code
_capi.fdb_future_get_key.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.POINTER(ctypes.c_byte)),
ctypes.POINTER(ctypes.c_int)]
_capi.fdb_future_get_key.restype = ctypes.c_int
_capi.fdb_future_get_key.errcheck = check_error_code
_capi.fdb_future_get_key.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.POINTER(ctypes.c_byte)),
ctypes.POINTER(ctypes.c_int)]
_capi.fdb_future_get_key.restype = ctypes.c_int
_capi.fdb_future_get_key.errcheck = check_error_code
_capi.fdb_future_get_cluster.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_void_p)]
_capi.fdb_future_get_cluster.restype = ctypes.c_int
_capi.fdb_future_get_cluster.errcheck = check_error_code
_capi.fdb_future_get_value.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_int),
ctypes.POINTER(ctypes.POINTER(ctypes.c_byte)), ctypes.POINTER(ctypes.c_int)]
_capi.fdb_future_get_value.restype = ctypes.c_int
_capi.fdb_future_get_value.errcheck = check_error_code
_capi.fdb_future_get_database.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_void_p)]
_capi.fdb_future_get_database.restype = ctypes.c_int
_capi.fdb_future_get_database.errcheck = check_error_code
_capi.fdb_future_get_keyvalue_array.argtypes = [ctypes.c_void_p, ctypes.POINTER(
ctypes.POINTER(KeyValueStruct)), ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int)]
_capi.fdb_future_get_keyvalue_array.restype = int
_capi.fdb_future_get_keyvalue_array.errcheck = check_error_code
_capi.fdb_future_get_value.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_int),
ctypes.POINTER(ctypes.POINTER(ctypes.c_byte)), ctypes.POINTER(ctypes.c_int)]
_capi.fdb_future_get_value.restype = ctypes.c_int
_capi.fdb_future_get_value.errcheck = check_error_code
_capi.fdb_future_get_string_array.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.POINTER(ctypes.c_char_p)), ctypes.POINTER(ctypes.c_int)]
_capi.fdb_future_get_string_array.restype = int
_capi.fdb_future_get_string_array.errcheck = check_error_code
_capi.fdb_future_get_keyvalue_array.argtypes = [ctypes.c_void_p, ctypes.POINTER(
ctypes.POINTER(KeyValueStruct)), ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int)]
_capi.fdb_future_get_keyvalue_array.restype = int
_capi.fdb_future_get_keyvalue_array.errcheck = check_error_code
_capi.fdb_create_database.argtypes = [ctypes.c_char_p, ctypes.POINTER(ctypes.c_void_p)]
_capi.fdb_create_database.restype = ctypes.c_int
_capi.fdb_create_database.errcheck = check_error_code
_capi.fdb_future_get_string_array.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.POINTER(ctypes.c_char_p)), ctypes.POINTER(ctypes.c_int)]
_capi.fdb_future_get_string_array.restype = int
_capi.fdb_future_get_string_array.errcheck = check_error_code
_capi.fdb_database_destroy.argtypes = [ctypes.c_void_p]
_capi.fdb_database_destroy.restype = None
_capi.fdb_create_cluster.argtypes = [ctypes.c_char_p]
_capi.fdb_create_cluster.restype = ctypes.c_void_p
_capi.fdb_database_create_transaction.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_void_p)]
_capi.fdb_database_create_transaction.restype = ctypes.c_int
_capi.fdb_database_create_transaction.errcheck = check_error_code
_capi.fdb_cluster_destroy.argtypes = [ctypes.c_void_p]
_capi.fdb_cluster_destroy.restype = None
_capi.fdb_database_set_option.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_int]
_capi.fdb_database_set_option.restype = ctypes.c_int
_capi.fdb_database_set_option.errcheck = check_error_code
_capi.fdb_cluster_create_database.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int]
_capi.fdb_cluster_create_database.restype = ctypes.c_void_p
_capi.fdb_transaction_destroy.argtypes = [ctypes.c_void_p]
_capi.fdb_transaction_destroy.restype = None
_capi.fdb_cluster_set_option.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_int]
_capi.fdb_cluster_set_option.restype = ctypes.c_int
_capi.fdb_cluster_set_option.errcheck = check_error_code
_capi.fdb_transaction_cancel.argtypes = [ctypes.c_void_p]
_capi.fdb_transaction_cancel.restype = None
_capi.fdb_database_destroy.argtypes = [ctypes.c_void_p]
_capi.fdb_database_destroy.restype = None
_capi.fdb_transaction_set_read_version.argtypes = [ctypes.c_void_p, ctypes.c_int64]
_capi.fdb_transaction_set_read_version.restype = None
_capi.fdb_database_create_transaction.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_void_p)]
_capi.fdb_database_create_transaction.restype = ctypes.c_int
_capi.fdb_database_create_transaction.errcheck = check_error_code
_capi.fdb_transaction_get_read_version.argtypes = [ctypes.c_void_p]
_capi.fdb_transaction_get_read_version.restype = ctypes.c_void_p
_capi.fdb_database_set_option.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_int]
_capi.fdb_database_set_option.restype = ctypes.c_int
_capi.fdb_database_set_option.errcheck = check_error_code
_capi.fdb_transaction_get.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int, ctypes.c_int]
_capi.fdb_transaction_get.restype = ctypes.c_void_p
_capi.fdb_transaction_destroy.argtypes = [ctypes.c_void_p]
_capi.fdb_transaction_destroy.restype = None
_capi.fdb_transaction_get_key.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int]
_capi.fdb_transaction_get_key.restype = ctypes.c_void_p
_capi.fdb_transaction_cancel.argtypes = [ctypes.c_void_p]
_capi.fdb_transaction_cancel.restype = None
_capi.fdb_transaction_get_range.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_void_p,
ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int,
ctypes.c_int, ctypes.c_int]
_capi.fdb_transaction_get_range.restype = ctypes.c_void_p
_capi.fdb_transaction_set_read_version.argtypes = [ctypes.c_void_p, ctypes.c_int64]
_capi.fdb_transaction_set_read_version.restype = None
_capi.fdb_transaction_add_conflict_range.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_int]
_capi.fdb_transaction_add_conflict_range.restype = ctypes.c_int
_capi.fdb_transaction_add_conflict_range.errcheck = check_error_code
_capi.fdb_transaction_get_read_version.argtypes = [ctypes.c_void_p]
_capi.fdb_transaction_get_read_version.restype = ctypes.c_void_p
_capi.fdb_transaction_get_addresses_for_key.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int]
_capi.fdb_transaction_get_addresses_for_key.restype = ctypes.c_void_p
_capi.fdb_transaction_get.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int, ctypes.c_int]
_capi.fdb_transaction_get.restype = ctypes.c_void_p
_capi.fdb_transaction_set_option.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_int]
_capi.fdb_transaction_set_option.restype = ctypes.c_int
_capi.fdb_transaction_set_option.errcheck = check_error_code
_capi.fdb_transaction_get_key.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int]
_capi.fdb_transaction_get_key.restype = ctypes.c_void_p
_capi.fdb_transaction_atomic_op.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_int]
_capi.fdb_transaction_atomic_op.restype = None
_capi.fdb_transaction_get_range.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_void_p,
ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int,
ctypes.c_int, ctypes.c_int]
_capi.fdb_transaction_get_range.restype = ctypes.c_void_p
_capi.fdb_transaction_set.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_int]
_capi.fdb_transaction_set.restype = None
_capi.fdb_transaction_add_conflict_range.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_int]
_capi.fdb_transaction_add_conflict_range.restype = ctypes.c_int
_capi.fdb_transaction_add_conflict_range.errcheck = check_error_code
_capi.fdb_transaction_clear.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int]
_capi.fdb_transaction_clear.restype = None
_capi.fdb_transaction_get_addresses_for_key.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int]
_capi.fdb_transaction_get_addresses_for_key.restype = ctypes.c_void_p
_capi.fdb_transaction_clear_range.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_int]
_capi.fdb_transaction_clear_range.restype = None
_capi.fdb_transaction_set_option.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_int]
_capi.fdb_transaction_set_option.restype = ctypes.c_int
_capi.fdb_transaction_set_option.errcheck = check_error_code
_capi.fdb_transaction_watch.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int]
_capi.fdb_transaction_watch.restype = ctypes.c_void_p
_capi.fdb_transaction_atomic_op.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_int]
_capi.fdb_transaction_atomic_op.restype = None
_capi.fdb_transaction_commit.argtypes = [ctypes.c_void_p]
_capi.fdb_transaction_commit.restype = ctypes.c_void_p
_capi.fdb_transaction_set.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_int]
_capi.fdb_transaction_set.restype = None
_capi.fdb_transaction_get_committed_version.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_int64)]
_capi.fdb_transaction_get_committed_version.restype = ctypes.c_int
_capi.fdb_transaction_get_committed_version.errcheck = check_error_code
_capi.fdb_transaction_clear.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int]
_capi.fdb_transaction_clear.restype = None
_capi.fdb_transaction_get_versionstamp.argtypes = [ctypes.c_void_p]
_capi.fdb_transaction_get_versionstamp.restype = ctypes.c_void_p
_capi.fdb_transaction_clear_range.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_int]
_capi.fdb_transaction_clear_range.restype = None
_capi.fdb_transaction_on_error.argtypes = [ctypes.c_void_p, ctypes.c_int]
_capi.fdb_transaction_on_error.restype = ctypes.c_void_p
_capi.fdb_transaction_watch.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int]
_capi.fdb_transaction_watch.restype = ctypes.c_void_p
_capi.fdb_transaction_commit.argtypes = [ctypes.c_void_p]
_capi.fdb_transaction_commit.restype = ctypes.c_void_p
_capi.fdb_transaction_get_committed_version.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_int64)]
_capi.fdb_transaction_get_committed_version.restype = ctypes.c_int
_capi.fdb_transaction_get_committed_version.errcheck = check_error_code
_capi.fdb_transaction_get_versionstamp.argtypes = [ctypes.c_void_p]
_capi.fdb_transaction_get_versionstamp.restype = ctypes.c_void_p
_capi.fdb_transaction_on_error.argtypes = [ctypes.c_void_p, ctypes.c_int]
_capi.fdb_transaction_on_error.restype = ctypes.c_void_p
_capi.fdb_transaction_reset.argtypes = [ctypes.c_void_p]
_capi.fdb_transaction_reset.restype = None
_capi.fdb_transaction_reset.argtypes = [ctypes.c_void_p]
_capi.fdb_transaction_reset.restype = None
if hasattr(ctypes.pythonapi, 'Py_IncRef'):
def _pin_callback(cb):
@ -1660,13 +1626,12 @@ def init_v13(local_address, event_model=None):
return init(event_model)
open_clusters = {}
open_databases = {}
cacheLock = threading.Lock()
def open(cluster_file=None, database_name=b'DB', event_model=None):
def open(cluster_file=None, event_model=None):
"""Opens the given database (or the default database of the cluster indicated
by the fdb.cluster file in a platform-specific location, if no cluster_file
or database_name is provided). Initializes the FDB interface as required."""
@ -1676,17 +1641,21 @@ def open(cluster_file=None, database_name=b'DB', event_model=None):
init(event_model=event_model)
with cacheLock:
if cluster_file not in open_clusters:
open_clusters[cluster_file] = create_cluster(cluster_file)
if cluster_file not in open_databases:
open_databases[cluster_file] = create_database(cluster_file)
if (cluster_file, database_name) not in open_databases:
open_databases[(cluster_file, database_name)] = open_clusters[cluster_file].open_database(database_name)
return open_databases[(cluster_file)]
return open_databases[(cluster_file, database_name)]
def open_v609(cluster_file=None, database_name=b'DB', event_model=None):
if database_name != b'DB':
raise FDBError(2013) # invalid_database_name
return open(cluster_file, event_model)
def open_v13(cluster_id_path, database_name, local_address=None, event_model=None):
return open(cluster_id_path, database_name, event_model)
return open_v609(cluster_id_path, database_name, event_model)
import atexit

View File

@ -70,8 +70,15 @@ module FDB
raise "FoundationDB API version error"
end
FDBC.init_c_api()
require_relative 'fdbtuple'
require_relative 'fdbdirectory'
if version < 610
require_relative 'fdbimpl_v609'
end
if version > 22
require_relative 'fdblocality'
end

View File

@ -64,64 +64,61 @@ module FDB
typedef :int, :fdb_error
typedef :int, :fdb_bool
attach_function :fdb_get_error, [ :fdb_error ], :string
attach_function :fdb_network_set_option, [ :int, :pointer, :int ], :fdb_error
attach_function :fdb_setup_network, [ ], :fdb_error
attach_function :fdb_run_network, [ ], :fdb_error, :blocking => true
attach_function :fdb_stop_network, [ ], :fdb_error
attach_function :fdb_future_cancel, [ :pointer ], :void
attach_function :fdb_future_release_memory, [ :pointer ], :void
attach_function :fdb_future_destroy, [ :pointer ], :void
attach_function :fdb_future_block_until_ready, [ :pointer ], :fdb_error, :blocking => true
attach_function :fdb_future_is_ready, [ :pointer ], :fdb_bool
callback :fdb_future_callback, [ :pointer, :pointer ], :void
attach_function :fdb_future_set_callback, [ :pointer, :fdb_future_callback, :pointer ], :fdb_error
attach_function :fdb_future_get_error, [ :pointer ], :fdb_error
attach_function :fdb_future_get_version, [ :pointer, :pointer ], :fdb_error
attach_function :fdb_future_get_key, [ :pointer, :pointer, :pointer ], :fdb_error
attach_function :fdb_future_get_cluster, [ :pointer, :pointer ], :fdb_error
attach_function :fdb_future_get_database, [ :pointer, :pointer ], :fdb_error
attach_function :fdb_future_get_value, [ :pointer, :pointer, :pointer, :pointer ], :fdb_error
attach_function :fdb_future_get_keyvalue_array, [ :pointer, :pointer, :pointer, :pointer ], :fdb_error
attach_function :fdb_future_get_string_array, [ :pointer, :pointer, :pointer ], :fdb_error
attach_function :fdb_create_cluster, [ :string ], :pointer
attach_function :fdb_cluster_destroy, [ :pointer ], :void
attach_function :fdb_cluster_set_option, [ :pointer, :int, :pointer, :int ], :fdb_error
attach_function :fdb_cluster_create_database, [ :pointer, :pointer, :int ], :pointer
attach_function :fdb_database_destroy, [ :pointer ], :void
attach_function :fdb_database_set_option, [ :pointer, :int, :pointer, :int ], :fdb_error
attach_function :fdb_database_create_transaction, [ :pointer, :pointer ], :fdb_error
attach_function :fdb_transaction_destroy, [ :pointer ], :void
attach_function :fdb_transaction_cancel, [ :pointer ], :void
attach_function :fdb_transaction_atomic_op, [ :pointer, :pointer, :int, :pointer, :int, :int ], :void
attach_function :fdb_transaction_add_conflict_range, [ :pointer, :pointer, :int, :pointer, :int, :int ], :int
attach_function :fdb_transaction_get_addresses_for_key, [ :pointer, :pointer, :int ], :pointer
attach_function :fdb_transaction_set_option, [ :pointer, :int, :pointer, :int ], :fdb_error
attach_function :fdb_transaction_set_read_version, [ :pointer, :int64 ], :void
attach_function :fdb_transaction_get_read_version, [ :pointer ], :pointer
attach_function :fdb_transaction_get, [ :pointer, :pointer, :int, :int ], :pointer
attach_function :fdb_transaction_get_key, [ :pointer, :pointer, :int, :int, :int, :int ], :pointer
attach_function :fdb_transaction_get_range, [ :pointer, :pointer, :int, :int, :int, :pointer, :int, :int, :int, :int, :int, :int, :int, :int, :int ], :pointer
attach_function :fdb_transaction_set, [ :pointer, :pointer, :int, :pointer, :int ], :void
attach_function :fdb_transaction_clear, [ :pointer, :pointer, :int ], :void
attach_function :fdb_transaction_clear_range, [ :pointer, :pointer, :int, :pointer, :int ], :void
attach_function :fdb_transaction_watch, [ :pointer, :pointer, :int ], :pointer
attach_function :fdb_transaction_commit, [ :pointer ], :pointer
attach_function :fdb_transaction_get_committed_version, [ :pointer, :pointer ], :fdb_error
attach_function :fdb_transaction_get_versionstamp, [ :pointer ], :pointer
attach_function :fdb_transaction_on_error, [ :pointer, :fdb_error ], :pointer
attach_function :fdb_transaction_reset, [ :pointer ], :void
attach_function :fdb_select_api_version_impl, [ :int, :int ], :fdb_error
attach_function :fdb_get_max_api_version, [ ], :int
def self.init_c_api
attach_function :fdb_get_error, [ :fdb_error ], :string
attach_function :fdb_network_set_option, [ :int, :pointer, :int ], :fdb_error
attach_function :fdb_setup_network, [ ], :fdb_error
attach_function :fdb_run_network, [ ], :fdb_error, :blocking => true
attach_function :fdb_stop_network, [ ], :fdb_error
attach_function :fdb_future_cancel, [ :pointer ], :void
attach_function :fdb_future_release_memory, [ :pointer ], :void
attach_function :fdb_future_destroy, [ :pointer ], :void
attach_function :fdb_future_block_until_ready, [ :pointer ], :fdb_error, :blocking => true
attach_function :fdb_future_is_ready, [ :pointer ], :fdb_bool
callback :fdb_future_callback, [ :pointer, :pointer ], :void
attach_function :fdb_future_set_callback, [ :pointer, :fdb_future_callback, :pointer ], :fdb_error
attach_function :fdb_future_get_error, [ :pointer ], :fdb_error
attach_function :fdb_future_get_version, [ :pointer, :pointer ], :fdb_error
attach_function :fdb_future_get_key, [ :pointer, :pointer, :pointer ], :fdb_error
attach_function :fdb_future_get_value, [ :pointer, :pointer, :pointer, :pointer ], :fdb_error
attach_function :fdb_future_get_keyvalue_array, [ :pointer, :pointer, :pointer, :pointer ], :fdb_error
attach_function :fdb_future_get_string_array, [ :pointer, :pointer, :pointer ], :fdb_error
attach_function :fdb_create_database, [ :string, :pointer ], :fdb_error
attach_function :fdb_database_destroy, [ :pointer ], :void
attach_function :fdb_database_set_option, [ :pointer, :int, :pointer, :int ], :fdb_error
attach_function :fdb_database_create_transaction, [ :pointer, :pointer ], :fdb_error
attach_function :fdb_transaction_destroy, [ :pointer ], :void
attach_function :fdb_transaction_cancel, [ :pointer ], :void
attach_function :fdb_transaction_atomic_op, [ :pointer, :pointer, :int, :pointer, :int, :int ], :void
attach_function :fdb_transaction_add_conflict_range, [ :pointer, :pointer, :int, :pointer, :int, :int ], :int
attach_function :fdb_transaction_get_addresses_for_key, [ :pointer, :pointer, :int ], :pointer
attach_function :fdb_transaction_set_option, [ :pointer, :int, :pointer, :int ], :fdb_error
attach_function :fdb_transaction_set_read_version, [ :pointer, :int64 ], :void
attach_function :fdb_transaction_get_read_version, [ :pointer ], :pointer
attach_function :fdb_transaction_get, [ :pointer, :pointer, :int, :int ], :pointer
attach_function :fdb_transaction_get_key, [ :pointer, :pointer, :int, :int, :int, :int ], :pointer
attach_function :fdb_transaction_get_range, [ :pointer, :pointer, :int, :int, :int, :pointer, :int, :int, :int, :int, :int, :int, :int, :int, :int ], :pointer
attach_function :fdb_transaction_set, [ :pointer, :pointer, :int, :pointer, :int ], :void
attach_function :fdb_transaction_clear, [ :pointer, :pointer, :int ], :void
attach_function :fdb_transaction_clear_range, [ :pointer, :pointer, :int, :pointer, :int ], :void
attach_function :fdb_transaction_watch, [ :pointer, :pointer, :int ], :pointer
attach_function :fdb_transaction_commit, [ :pointer ], :pointer
attach_function :fdb_transaction_get_committed_version, [ :pointer, :pointer ], :fdb_error
attach_function :fdb_transaction_get_versionstamp, [ :pointer ], :pointer
attach_function :fdb_transaction_on_error, [ :pointer, :fdb_error ], :pointer
attach_function :fdb_transaction_reset, [ :pointer ], :void
end
class KeyValueStruct < FFI::Struct
pack 4
layout :key, :pointer,
@ -156,7 +153,7 @@ module FDB
@@ffi_callbacks
end
[ "Network", "Cluster", "Database", "Transaction" ].each do |scope|
[ "Network", "Database", "Transaction" ].each do |scope|
klass = FDB.const_set("#{scope}Options", Class.new)
klass.class_eval do
define_method(:initialize) do |setfunc|
@ -242,6 +239,10 @@ module FDB
nil
end
class << self
private :init
end
def self.stop()
FDBC.check_error FDBC.fdb_stop_network
end
@ -254,11 +255,10 @@ module FDB
end
end
@@open_clusters = {}
@@open_databases = {}
@@cache_lock = Mutex.new
def self.open( cluster_file = nil, database_name = "DB" )
def self.open( cluster_file = nil )
@@network_thread_monitor.synchronize do
if ! @@network_thread
init
@ -266,15 +266,13 @@ module FDB
end
@@cache_lock.synchronize do
if ! @@open_clusters.has_key? cluster_file
@@open_clusters[cluster_file] = create_cluster( cluster_file )
if ! @@open_databases.has_key? [cluster_file]
dpointer = FFI::MemoryPointer.new :pointer
FDBC.check_error FDBC.fdb_create_database(cluster_file, dpointer)
@@open_databases[cluster_file] = Database.new dpointer.get_pointer(0)
end
if ! @@open_databases.has_key? [cluster_file, database_name]
@@open_databases[[cluster_file, database_name]] = @@open_clusters[cluster_file].open_database(database_name)
end
@@open_databases[[cluster_file, database_name]]
@@open_databases[cluster_file]
end
end
@ -503,41 +501,6 @@ module FDB
end
end
def self.create_cluster(cluster=nil)
f = FDBC.fdb_create_cluster(cluster)
cpointer = FFI::MemoryPointer.new :pointer
FDBC.check_error FDBC.fdb_future_block_until_ready(f)
FDBC.check_error FDBC.fdb_future_get_cluster(f, cpointer)
Cluster.new cpointer.get_pointer(0)
end
class Cluster < FormerFuture
attr_reader :options
def self.finalize(ptr)
proc do
# puts "Destroying cluster #{ptr}"
FDBC.fdb_cluster_destroy(ptr)
end
end
def initialize(cpointer)
@cpointer = cpointer
@options = ClusterOptions.new lambda { |code, param|
FDBC.check_error FDBC.fdb_cluster_set_option(cpointer, code, param, param.nil? ? 0 : param.bytesize)
}
ObjectSpace.define_finalizer(self, self.class.finalize(@cpointer))
end
def open_database(name="DB")
f = FDBC.fdb_cluster_create_database(@cpointer, name, name.bytesize)
dpointer = FFI::MemoryPointer.new :pointer
FDBC.check_error FDBC.fdb_future_block_until_ready(f)
FDBC.check_error FDBC.fdb_future_get_database(f, dpointer)
Database.new dpointer.get_pointer(0)
end
end
class Database < FormerFuture
attr_reader :options

View File

@ -0,0 +1,62 @@
#encoding: BINARY
#
# fdbimpl.rb
#
# This source file is part of the FoundationDB open source project
#
# Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# FoundationDB Ruby API
# Documentation for this API can be found at
# https://apple.github.io/foundationdb/api-ruby.html
module FDB
class << self
alias_method :open_impl, :open
def open( cluster_file = nil, database_name = "DB" )
if database_name != "DB"
raise Error.new(2013) # invalid_database_name
end
open_impl(cluster_file)
end
def create_cluster(cluster_file_path=nil)
Cluster.new cluster_file_path
end
public :init
end
class ClusterOptions
end
class Cluster < FormerFuture
attr_reader :options
def initialize(cluster_file_path)
@cluster_file_path = cluster_file_path
@options = ClusterOptions.new
end
def open_database(name="DB")
FDB.open(@cluster_file_path, name)
end
end
end

View File

@ -85,7 +85,7 @@ Specifying the cluster file
All FoundationDB components can be configured to use a specified cluster file:
* The ``fdbcli`` tool allows a cluster file to be passed on the command line using the ``-C`` option.
* The :doc:`client APIs <api-reference>` allow a cluster file to be passed when connecting to a cluster, usually via ``open()`` or ``create_cluster()``.
* The :doc:`client APIs <api-reference>` allow a cluster file to be passed when connecting to a cluster, usually via ``open()``.
* A FoundationDB server or ``backup-agent`` allow a cluster file to be specified in :ref:`foundationdb.conf <foundationdb-conf>`.
In addition, FoundationDB allows you to use the environment variable ``FDB_CLUSTER_FILE`` to specify a cluster file. This approach is helpful if you operate or access more than one cluster.

View File

@ -13,7 +13,6 @@
.. |reset-func-name| replace:: :func:`reset <fdb_transaction_reset()>`
.. |reset-func| replace:: :func:`fdb_transaction_reset()`
.. |cancel-func| replace:: :func:`fdb_transaction_cancel()`
.. |init-func| replace:: FIXME
.. |open-func| replace:: FIXME
.. |set-cluster-file-func| replace:: FIXME
.. |set-local-address-func| replace:: FIXME
@ -292,22 +291,6 @@ See :ref:`developer-guide-programming-with-futures` for further (language-indepe
|future-memory-mine|
.. function:: fdb_error_t fdb_future_get_cluster(FDBFuture* future, FDBCluster** out_cluster)
Extracts a value of type :type:`FDBCluster*` from an :type:`FDBFuture` into a caller-provided variable. |future-warning|
|future-get-return1| |future-get-return2|.
|future-memory-yours1| :type:`FDBCluster` |future-memory-yours2| :func:`fdb_cluster_destroy()` |future-memory-yours3|
.. function:: fdb_error_t fdb_future_get_database(FDBFuture* future, FDBDatabase** out_database)
Extracts a value of type :type:`FDBDatabase*` from an :type:`FDBFuture` into a caller-provided variable. |future-warning|
|future-get-return1| |future-get-return2|.
|future-memory-yours1| :type:`FDBDatabase` |future-memory-yours2| ``fdb_database_destroy(*out_database)`` |future-memory-yours3|
.. function:: fdb_error_t fdb_future_get_value(FDBFuture* future, fdb_bool_t* out_present, uint8_t const** out_value, int* out_value_length)
Extracts a database value from an :type:`FDBFuture` into caller-provided variables. |future-warning|
@ -379,42 +362,6 @@ See :ref:`developer-guide-programming-with-futures` for further (language-indepe
:data:`value_length`
The length of the value pointed to by :data:`value`.
Cluster
=======
.. type:: FDBCluster
An opaque type that represents a Cluster in the FoundationDB C API.
.. function:: FDBFuture* fdb_create_cluster(const char* cluster_file_path)
|future-return0| an :type:`FDBCluster` object. |future-return1| call :func:`fdb_future_get_cluster()` to extract the :type:`FDBCluster` object, |future-return2|
:data:`cluster_file_path`
A NULL-terminated string giving a local path of a :ref:`cluster file <foundationdb-cluster-file>` (often called 'fdb.cluster') which contains connection information for the FoundationDB cluster. If cluster_file_path is NULL or an empty string, then a :ref:`default cluster file <default-cluster-file>` will be used.
.. function:: void fdb_cluster_destroy(FDBCluster* cluster)
Destroys an :type:`FDBCluster` object. It must be called exactly once for each successful call to :func:`fdb_future_get_cluster()`. This function only destroys a handle to the cluster -- your cluster will be fine!
.. function:: fdb_error_t fdb_cluster_set_option(FDBCluster* cluster, FDBClusterOption option, uint8_t const* value, int value_length)
Called to set an option on an :type:`FDBCluster`. |option-parameter| :func:`fdb_cluster_set_option()` returns.
.. type:: FDBClusterOption
|option-doc|
.. function:: FDBFuture* fdb_cluster_create_database(FDBCluster *cluster, uint8_t const* db_name, int db_name_length)
|future-return0| an :type:`FDBDatabase` object. |future-return1| call :func:`fdb_future_get_database()` to extract the :type:`FDBDatabase` object, |future-return2|
:data:`db_name`
A pointer to the name of the database to be opened. |no-null| In the current FoundationDB API, the database name *must* be "DB".
:data:`db_name_length`
|length-of| :data:`db_name`.
Database
========
@ -424,9 +371,19 @@ An |database-blurb1| Modifications to a database are performed via transactions.
An opaque type that represents a database in the FoundationDB C API.
.. function:: fdb_error_t fdb_create_database(const char* cluster_file_path, FDBDatabase** out_database)
Creates a new database connected the specified cluster. The caller assumes ownership of the :type:`FDBDatabase` object and must destroy it with :func:`fdb_database_destroy()`.
:data:`cluster_file_path`
A NULL-terminated string giving a local path of a :ref:`cluster file <foundationdb-cluster-file>` (often called 'fdb.cluster') which contains connection information for the FoundationDB cluster. If cluster_file_path is NULL or an empty string, then a :ref:`default cluster file <default-cluster-file>` will be used.
:data:`*out_database`
Set to point to the newly created :type:`FDBDatabase`.
.. function:: void fdb_database_destroy(FDBDatabase* database)
Destroys an :type:`FDBDatabase` object. It must be called exactly once for each successful call to :func:`fdb_future_get_database()`. This function only destroys a handle to the database -- your database will be fine!
Destroys an :type:`FDBDatabase` object. It must be called exactly once for each successful call to :func:`fdb_create_database()`. This function only destroys a handle to the database -- your database will be fine!
.. function:: fdb_error_t fdb_database_set_option(FDBDatabase* database, FDBDatabaseOption option, uint8_t const* value, int value_length)

View File

@ -234,7 +234,7 @@
.. |network-options-warning| replace::
It is an error to set these options after the first call to |open-func| or |init-func| anywhere in your application.
It is an error to set these options after the first call to |open-func| anywhere in your application.
.. |tls-options-burb| replace::
@ -398,7 +398,7 @@
Cancels |future-type-string| and its associated asynchronous operation. If called before the future is ready, attempts to access its value will |error-raise-type| an :ref:`operation_cancelled <developer-guide-error-codes>` |error-type|. Cancelling a future which is already ready has no effect. Note that even if a future is not ready, its associated asynchronous operation may have succesfully completed and be unable to be cancelled.
.. |fdb-open-blurb| replace::
Initializes the FoundationDB API, connects to the cluster specified by the :ref:`cluster file <foundationdb-cluster-file>`, and opens the database with the specified name. This function is often called without any parameters, using only the defaults. If no cluster file is passed, FoundationDB automatically :ref:`determines a cluster file <specifying-a-cluster-file>` with which to connect to a cluster.
Initializes the FoundationDB API and connects to the cluster specified by the :ref:`cluster file <foundationdb-cluster-file>`. This function is often called without any parameters, using only the defaults. If no cluster file is passed, FoundationDB automatically :ref:`determines a cluster file <specifying-a-cluster-file>` with which to connect to a cluster.
.. |fdb-transactional-unknown-result-note| replace::
In some failure scenarios, it is possible that your transaction will be executed twice. See :ref:`developer-guide-unknown-results` for more information.

View File

@ -14,7 +14,6 @@
.. |reset-func-name| replace:: :func:`reset <Transaction.reset>`
.. |reset-func| replace:: :func:`Transaction.reset`
.. |cancel-func| replace:: :func:`Transaction.cancel`
.. |init-func| replace:: :func:`fdb.init`
.. |open-func| replace:: :func:`fdb.open`
.. |on-error-func| replace:: :meth:`Transaction.on_error`
.. |null-type| replace:: ``None``
@ -86,33 +85,18 @@ For API changes between version 13 and |api-version| (for the purpose of porting
Opening a database
==================
After importing the ``fdb`` module and selecting an API version, you probably want to open a :class:`Database`. The simplest way of doing this is using :func:`open`::
After importing the ``fdb`` module and selecting an API version, you probably want to open a :class:`Database` using :func:`open`::
import fdb
fdb.api_version(610)
db = fdb.open()
.. function:: open( cluster_file=None, db_name="DB", event_model=None )
.. function:: open( cluster_file=None, event_model=None )
|fdb-open-blurb|
.. param event_model:: Can be used to select alternate :ref:`api-python-event-models`
.. note:: In this release, db_name must be "DB".
.. note:: ``fdb.open()`` combines the effect of :func:`init`, :func:`create_cluster`, and :meth:`Cluster.open_database`.
.. function:: init()
Initializes the FoundationDB API, creating a thread for the FoundationDB client and initializing the client's networking engine. :func:`init()` can only be called once. If called subsequently or after :func:`open`, it will raise an ``client_invalid_operation`` error.
.. function:: create_cluster( cluster_file=None )
Connects to the cluster specified by :ref:`cluster_file <foundationdb-cluster-file>`, or by a :ref:`default cluster file <default-cluster-file>` if
``cluster_file`` is None. :func:`init` must be called first.
Returns a |future-type| :class:`Cluster` object.
.. data:: options
|network-options-blurb|
@ -175,19 +159,6 @@ After importing the ``fdb`` module and selecting an API version, you probably wa
|option-tls-key-bytes|
Cluster objects
===============
.. class:: Cluster
.. method:: Cluster.open_database(name="DB")
Opens a database with the given name.
Returns a |future-type| :class:`Database` object.
.. note:: In this release, name **must** be "DB".
.. _api-python-keys:
Keys and values
@ -966,7 +937,7 @@ The following streaming modes are available:
Event models
============
By default, the FoundationDB Python API assumes that the calling program uses threads (as provided by the ``threading`` module) for concurrency. This means that blocking operations will block the current Python thread. This behavior can be changed by specifying the optional ``event_model`` parameter to the :func:`open` or :func:`init` functions.
By default, the FoundationDB Python API assumes that the calling program uses threads (as provided by the ``threading`` module) for concurrency. This means that blocking operations will block the current Python thread. This behavior can be changed by specifying the optional ``event_model`` parameter to the :func:`open` function.
The following event models are available:

View File

@ -12,7 +12,6 @@
.. |reset-func-name| replace:: :meth:`reset <Transaction.reset>`
.. |reset-func| replace:: :meth:`Transaction.reset`
.. |cancel-func| replace:: :meth:`Transaction.cancel`
.. |init-func| replace:: :func:`FDB.init`
.. |open-func| replace:: :func:`FDB.open`
.. |on-error-func| replace:: :meth:`Transaction.on_error`
.. |null-type| replace:: ``nil``
@ -75,28 +74,16 @@ For API changes between version 14 and |api-version| (for the purpose of porting
Opening a database
==================
After requiring the ``FDB`` gem and selecting an API version, you probably want to open a :class:`Database`. The simplest way of doing this is using :func:`open`::
After requiring the ``FDB`` gem and selecting an API version, you probably want to open a :class:`Database` using :func:`open`::
require 'fdb'
FDB.api_version 610
db = FDB.open
.. function:: open( cluster_file=nil, db_name="DB" ) -> Database
.. function:: open( cluster_file=nil ) -> Database
|fdb-open-blurb|
.. note:: In this release, db_name must be "DB".
.. note:: ``fdb.open`` combines the effect of :func:`init`, :func:`create_cluster`, and :meth:`Cluster.open_database`.
.. function:: init() -> nil
Initializes the FoundationDB API, creating a thread for the FoundationDB client and initializing the client's networking engine. :func:`init` can only be called once. If called subsequently or after :func:`open`, it will raise a ``client_invalid_operation`` error.
.. function:: create_cluster(cluster_file=nil) -> Cluster
Connects to the cluster specified by :ref:`cluster_file <foundationdb-cluster-file>`, or by a :ref:`default cluster file <default-cluster-file>` if ``cluster_file`` is ``nil``.
.. global:: FDB.options
|network-options-blurb|
@ -160,17 +147,6 @@ After requiring the ``FDB`` gem and selecting an API version, you probably want
.. method :: FDB.options.set_disable_multi_version_client_api() -> nil
Cluster objects
===============
.. class:: Cluster
.. method:: Cluster.open_database(name="DB") -> Database
Opens a database with the given name.
.. note:: In this release, name **must** be "DB".
.. _api-ruby-keys:
Keys and values

View File

@ -12,7 +12,6 @@
.. |get-key-func| replace:: get_key()
.. |get-range-func| replace:: get_range()
.. |commit-func| replace:: FIXME
.. |init-func| replace:: FIXME
.. |open-func| replace:: FIXME
.. |set-cluster-file-func| replace:: FIXME
.. |set-local-address-func| replace:: FIXME

View File

@ -12,7 +12,6 @@
.. |get-key-func| replace:: get_key()
.. |get-range-func| replace:: get_range()
.. |commit-func| replace:: ``commit()``
.. |init-func| replace:: FIXME
.. |open-func| replace:: FIXME
.. |set-cluster-file-func| replace:: FIXME
.. |set-local-address-func| replace:: FIXME

View File

@ -20,6 +20,16 @@ Status
Bindings
--------
* The API to create a database has been simplified across the bindings. All changes are backward compatible with previous API versions, with one exception in Java noted below.
* C: `FDBCluster` objects and related methods (`fdb_create_cluster`, `fdb_cluster_create_database`, `fdb_cluster_set_option`, `fdb_cluster_destroy`, `fdb_future_get_cluster`) have been removed.
* C: Added `fdb_create_database` that creates a new `FDBDatabase` object synchronously and removed `fdb_future_get_database`.
* Python: Removed `fdb.init`, `fdb.create_cluster`, and `fdb.Cluster`. `fdb.open` no longer accepts a `database_name` parameter.
* Java: Deprecated `FDB.createCluster` and `Cluster`. The preferred way to get a `Database` is by using `FDB.open`, which should work in both new and old API versions.
* Java: Removed `Cluster(long cPtr, Executor executor)` constructor. This is API breaking for any code that has subclassed the `Cluster` class and is not protected by API versioning.
* Ruby: Removed `FDB.init`, `FDB.create_cluster`, and `FDB.Cluster`. `FDB.open` no longer accepts a `database_name` parameter.
* Golang: Deprecated `fdb.StartNetwork`, `fdb.Open`, `fdb.MustOpen`, and `fdb.CreateCluster` and added `fdb.OpenDatabase` and `fdb.MustOpenDatabase`. The preferred way to start the network and get a `Database` is by using `FDB.OpenDatabase` or `FDB.OpenDefault`.
* Flow: Deprecated `API::createCluster` and `Cluster` and added `API::createDatabase`. The preferred way to get a `Database` is by using `API::createDatabase`.
Other Changes
-------------

View File

@ -75,8 +75,12 @@ public:
Error deferredError;
bool lockAware;
bool isError() {
return deferredError.code() != invalid_error_code;
}
void checkDeferredError() {
if( deferredError.code() != invalid_error_code ) {
if(isError()) {
throw deferredError;
}
}
@ -91,6 +95,8 @@ public:
Future<Void> clientInfoMonitor, Standalone<StringRef> dbId, int taskID, LocalityData const& clientLocality,
bool enableLocalityLoadBalance, bool lockAware, int apiVersion = Database::API_VERSION_LATEST );
explicit DatabaseContext( const Error &err );
// Key DB-specific information
AsyncTrigger masterProxiesChangeTrigger;
Future<Void> monitorMasterProxiesInfoChange;

View File

@ -94,7 +94,7 @@ public:
virtual void runNetwork() = 0;
virtual void stopNetwork() = 0;
virtual ThreadFuture<Reference<IDatabase>> createDatabase(const char *clusterFilePath) = 0;
virtual Reference<IDatabase> createDatabase(const char *clusterFilePath) = 0;
virtual void addNetworkThreadCompletionHook(void (*hook)(void*), void *hookParameter) = 0;
};

View File

@ -212,6 +212,21 @@ void DLTransaction::reset() {
}
// DLDatabase
DLDatabase::DLDatabase(Reference<FdbCApi> api, ThreadFuture<FdbCApi::FDBDatabase*> dbFuture) : api(api), db(nullptr) {
ready = mapThreadFuture<FdbCApi::FDBDatabase*, Void>(dbFuture, [this](ErrorOr<FdbCApi::FDBDatabase*> db){
if(db.isError()) {
return ErrorOr<Void>(db.getError());
}
this->db = db.get();
return ErrorOr<Void>(Void());
});
}
ThreadFuture<Void> DLDatabase::onReady() {
return ready;
}
Reference<ITransaction> DLDatabase::createTransaction() {
FdbCApi::FDBTransaction *tr;
api->databaseCreateTransaction(db, &tr);
@ -251,11 +266,7 @@ void DLApi::init() {
loadClientFunction(&api->setupNetwork, lib, fdbCPath, "fdb_setup_network");
loadClientFunction(&api->runNetwork, lib, fdbCPath, "fdb_run_network");
loadClientFunction(&api->stopNetwork, lib, fdbCPath, "fdb_stop_network");
loadClientFunction(&api->createCluster, lib, fdbCPath, "fdb_create_cluster");
loadClientFunction(&api->clusterCreateDatabase, lib, fdbCPath, "fdb_cluster_create_database");
loadClientFunction(&api->clusterSetOption, lib, fdbCPath, "fdb_cluster_set_option");
loadClientFunction(&api->clusterDestroy, lib, fdbCPath, "fdb_cluster_destroy");
loadClientFunction(&api->createDatabase, lib, fdbCPath, "fdb_create_database", headerVersion >= 610);
loadClientFunction(&api->databaseCreateTransaction, lib, fdbCPath, "fdb_database_create_transaction");
loadClientFunction(&api->databaseSetOption, lib, fdbCPath, "fdb_database_set_option");
@ -282,7 +293,6 @@ void DLApi::init() {
loadClientFunction(&api->transactionCancel, lib, fdbCPath, "fdb_transaction_cancel");
loadClientFunction(&api->transactionAddConflictRange, lib, fdbCPath, "fdb_transaction_add_conflict_range");
loadClientFunction(&api->futureGetCluster, lib, fdbCPath, "fdb_future_get_cluster");
loadClientFunction(&api->futureGetDatabase, lib, fdbCPath, "fdb_future_get_database");
loadClientFunction(&api->futureGetVersion, lib, fdbCPath, "fdb_future_get_version");
loadClientFunction(&api->futureGetError, lib, fdbCPath, "fdb_future_get_error");
@ -293,6 +303,11 @@ void DLApi::init() {
loadClientFunction(&api->futureSetCallback, lib, fdbCPath, "fdb_future_set_callback");
loadClientFunction(&api->futureCancel, lib, fdbCPath, "fdb_future_cancel");
loadClientFunction(&api->futureDestroy, lib, fdbCPath, "fdb_future_destroy");
loadClientFunction(&api->createCluster, lib, fdbCPath, "fdb_create_cluster", headerVersion < 610);
loadClientFunction(&api->clusterCreateDatabase, lib, fdbCPath, "fdb_cluster_create_database", headerVersion < 610);
loadClientFunction(&api->clusterDestroy, lib, fdbCPath, "fdb_cluster_destroy", headerVersion < 610);
loadClientFunction(&api->futureGetCluster, lib, fdbCPath, "fdb_future_get_cluster", headerVersion < 610);
}
void DLApi::selectApiVersion(int apiVersion) {
@ -346,7 +361,7 @@ void DLApi::stopNetwork() {
}
}
ThreadFuture<Reference<IDatabase>> DLApi::createDatabase(const char *clusterFilePath) {
Reference<IDatabase> DLApi::createDatabase609(const char *clusterFilePath) {
FdbCApi::FDBFuture *f = api->createCluster(clusterFilePath);
auto clusterFuture = toThreadFuture<FdbCApi::FDBCluster*>(api, f, [](FdbCApi::FDBFuture *f, FdbCApi *api) {
@ -356,22 +371,35 @@ ThreadFuture<Reference<IDatabase>> DLApi::createDatabase(const char *clusterFile
});
Reference<FdbCApi> innerApi = api;
return flatMapThreadFuture<FdbCApi::FDBCluster*, Reference<IDatabase>>(clusterFuture, [innerApi](ErrorOr<FdbCApi::FDBCluster*> cluster) {
auto dbFuture = flatMapThreadFuture<FdbCApi::FDBCluster*, FdbCApi::FDBDatabase*>(clusterFuture, [innerApi](ErrorOr<FdbCApi::FDBCluster*> cluster) {
if(cluster.isError()) {
return ErrorOr<ThreadFuture<Reference<IDatabase>>>(cluster.getError());
return ErrorOr<ThreadFuture<FdbCApi::FDBDatabase*>>(cluster.getError());
}
auto dbFuture = toThreadFuture<Reference<IDatabase>>(innerApi, innerApi->clusterCreateDatabase(cluster.get(), (uint8_t*)"DB", 2), [](FdbCApi::FDBFuture *f, FdbCApi *api) {
auto innerDbFuture = toThreadFuture<FdbCApi::FDBDatabase*>(innerApi, innerApi->clusterCreateDatabase(cluster.get(), (uint8_t*)"DB", 2), [](FdbCApi::FDBFuture *f, FdbCApi *api) {
FdbCApi::FDBDatabase *db;
api->futureGetDatabase(f, &db);
return Reference<IDatabase>(new DLDatabase(Reference<FdbCApi>::addRef(api), db));
return db;
});
return ErrorOr<ThreadFuture<Reference<IDatabase>>>(mapThreadFuture<Reference<IDatabase>, Reference<IDatabase>>(dbFuture, [cluster, innerApi](ErrorOr<Reference<IDatabase>> db) {
return ErrorOr<ThreadFuture<FdbCApi::FDBDatabase*>>(mapThreadFuture<FdbCApi::FDBDatabase*, FdbCApi::FDBDatabase*>(innerDbFuture, [cluster, innerApi](ErrorOr<FdbCApi::FDBDatabase*> db) {
innerApi->clusterDestroy(cluster.get());
return db;
}));
});
return Reference<DLDatabase>(new DLDatabase(api, dbFuture));
}
Reference<IDatabase> DLApi::createDatabase(const char *clusterFilePath) {
if(headerVersion >= 610) {
FdbCApi::FDBDatabase *db;
api->createDatabase(clusterFilePath, &db);
return Reference<IDatabase>(new DLDatabase(api, db));
}
else {
return DLApi::createDatabase609(clusterFilePath);
}
}
void DLApi::addNetworkThreadCompletionHook(void (*hook)(void*), void *hookParameter) {
@ -634,28 +662,32 @@ void MultiVersionDatabase::Connector::connect() {
connectionFuture.cancel();
}
ThreadFuture<Reference<IDatabase>> dbFuture = client->api->createDatabase(clusterFilePath.c_str());
connectionFuture = flatMapThreadFuture<Reference<IDatabase>, Void>(dbFuture, [this](ErrorOr<Reference<IDatabase>> db) {
if(db.isError()) {
return ErrorOr<ThreadFuture<Void>>(db.getError());
}
else {
candidateDatabase = db.get();
tr = db.get()->createTransaction();
auto versionFuture = mapThreadFuture<Version, Void>(tr->getReadVersion(), [this](ErrorOr<Version> v) {
// If the version attempt returns an error, we regard that as a connection (except operation_cancelled)
if(v.isError() && v.getError().code() == error_code_operation_cancelled) {
return ErrorOr<Void>(v.getError());
}
else {
return ErrorOr<Void>(Void());
}
});
candidateDatabase = client->api->createDatabase(clusterFilePath.c_str());
if(client->external) {
connectionFuture = candidateDatabase.castTo<DLDatabase>()->onReady();
}
else {
connectionFuture = ThreadFuture<Void>(Void());
}
return ErrorOr<ThreadFuture<Void>>(versionFuture);
connectionFuture = flatMapThreadFuture<Void, Void>(connectionFuture, [this](ErrorOr<Void> ready) {
if(ready.isError()) {
return ErrorOr<ThreadFuture<Void>>(ready.getError());
}
tr = candidateDatabase->createTransaction();
return ErrorOr<ThreadFuture<Void>>(mapThreadFuture<Version, Void>(tr->getReadVersion(), [this](ErrorOr<Version> v) {
// If the version attempt returns an error, we regard that as a connection (except operation_cancelled)
if(v.isError() && v.getError().code() == error_code_operation_cancelled) {
return ErrorOr<Void>(v.getError());
}
else {
return ErrorOr<Void>(Void());
}
}));
});
int userParam;
connectionFuture.callOrSetAsCallback(this, userParam, 0);
}
@ -1113,11 +1145,11 @@ void MultiVersionApi::addNetworkThreadCompletionHook(void (*hook)(void*), void *
}
}
ThreadFuture<Reference<IDatabase>> MultiVersionApi::createDatabase(const char *clusterFilePath) {
Reference<IDatabase> MultiVersionApi::createDatabase(const char *clusterFilePath) {
lock.enter();
if(!networkSetup) {
lock.leave();
return network_not_setup();
throw network_not_setup();
}
lock.leave();
@ -1126,21 +1158,15 @@ ThreadFuture<Reference<IDatabase>> MultiVersionApi::createDatabase(const char *c
return Reference<IDatabase>(new MultiVersionDatabase(this, clusterFile, Reference<IDatabase>()));
}
auto databaseFuture = localClient->api->createDatabase(clusterFilePath);
auto db = localClient->api->createDatabase(clusterFilePath);
if(bypassMultiClientApi) {
return databaseFuture;
return db;
}
else {
for(auto it : externalClients) {
TraceEvent("CreatingDatabaseOnExternalClient").detail("LibraryPath", it.second->libPath).detail("Failed", it.second->failed);
}
return mapThreadFuture<Reference<IDatabase>, Reference<IDatabase>>(databaseFuture, [this, clusterFile](ErrorOr<Reference<IDatabase>> database) {
if(database.isError()) {
return database;
}
return ErrorOr<Reference<IDatabase>>(Reference<IDatabase>(new MultiVersionDatabase(this, clusterFile, database.get())));
});
return Reference<IDatabase>(new MultiVersionDatabase(this, clusterFile, db));
}
}

View File

@ -55,12 +55,7 @@ struct FdbCApi : public ThreadSafeReferenceCounted<FdbCApi> {
fdb_error_t (*setupNetwork)();
fdb_error_t (*runNetwork)();
fdb_error_t (*stopNetwork)();
FDBFuture* (*createCluster)(const char *clusterFilePath);
//Cluster
FDBFuture* (*clusterCreateDatabase)(FDBCluster *cluster, uint8_t *dbName, int dbNameLength);
fdb_error_t (*clusterSetOption)(FDBCluster *cluster, FDBClusterOptions::Option option, uint8_t const *value, int valueLength);
void (*clusterDestroy)(FDBCluster *cluster);
fdb_error_t* (*createDatabase)(const char *clusterFilePath, FDBDatabase **db);
//Database
fdb_error_t (*databaseCreateTransaction)(FDBDatabase *database, FDBTransaction **tr);
@ -98,7 +93,6 @@ struct FdbCApi : public ThreadSafeReferenceCounted<FdbCApi> {
uint8_t const *endKeyName, int endKeyNameLength, FDBConflictRangeTypes::Option);
//Future
fdb_error_t (*futureGetCluster)(FDBFuture *f, FDBCluster **outCluster);
fdb_error_t (*futureGetDatabase)(FDBFuture *f, FDBDatabase **outDb);
fdb_error_t (*futureGetVersion)(FDBFuture *f, int64_t *outVersion);
fdb_error_t (*futureGetError)(FDBFuture *f);
@ -109,6 +103,12 @@ struct FdbCApi : public ThreadSafeReferenceCounted<FdbCApi> {
fdb_error_t (*futureSetCallback)(FDBFuture *f, FDBCallback callback, void *callback_parameter);
void (*futureCancel)(FDBFuture *f);
void (*futureDestroy)(FDBFuture *f);
//Legacy Support
FDBFuture* (*createCluster)(const char *clusterFilePath);
FDBFuture* (*clusterCreateDatabase)(FDBCluster *cluster, uint8_t *dbName, int dbNameLength);
void (*clusterDestroy)(FDBCluster *cluster);
fdb_error_t (*futureGetCluster)(FDBFuture *f, FDBCluster **outCluster);
};
class DLTransaction : public ITransaction, ThreadSafeReferenceCounted<DLTransaction> {
@ -159,9 +159,12 @@ private:
class DLDatabase : public IDatabase, ThreadSafeReferenceCounted<DLDatabase> {
public:
DLDatabase(Reference<FdbCApi> api, FdbCApi::FDBDatabase *db) : api(api), db(db) {}
DLDatabase(Reference<FdbCApi> api, FdbCApi::FDBDatabase *db) : api(api), db(db), ready(Void()) {}
DLDatabase(Reference<FdbCApi> api, ThreadFuture<FdbCApi::FDBDatabase*> dbFuture);
~DLDatabase() { api->databaseDestroy(db); }
ThreadFuture<Void> onReady();
Reference<ITransaction> createTransaction();
void setOption(FDBDatabaseOptions::Option option, Optional<StringRef> value = Optional<StringRef>());
@ -170,7 +173,8 @@ public:
private:
const Reference<FdbCApi> api;
FdbCApi::FDBDatabase* const db;
FdbCApi::FDBDatabase* db; // Always set if API version >= 610, otherwise guaranteed to be set when onReady future is set
ThreadFuture<Void> ready;
};
class DLApi : public IClientApi {
@ -185,7 +189,8 @@ public:
void runNetwork();
void stopNetwork();
ThreadFuture<Reference<IDatabase>> createDatabase(const char *clusterFilePath);
Reference<IDatabase> createDatabase(const char *clusterFilePath);
Reference<IDatabase> createDatabase609(const char *clusterFilePath); // legacy database creation
void addNetworkThreadCompletionHook(void (*hook)(void*), void *hookParameter);
@ -327,7 +332,6 @@ private:
Reference<IDatabase> db;
const Reference<ThreadSafeAsyncVar<Reference<IDatabase>>> dbVar;
ThreadFuture<Reference<IDatabase>> dbFuture;
ThreadFuture<Void> changed;
bool cancelled;
@ -355,7 +359,7 @@ public:
void stopNetwork();
void addNetworkThreadCompletionHook(void (*hook)(void*), void *hookParameter);
ThreadFuture<Reference<IDatabase>> createDatabase(const char *clusterFilePath);
Reference<IDatabase> createDatabase(const char *clusterFilePath);
static MultiVersionApi* api;
Reference<ClientInfo> getLocalClient();

View File

@ -486,6 +486,8 @@ DatabaseContext::DatabaseContext(
clientStatusUpdater.actor = clientStatusUpdateActor(this);
}
DatabaseContext::DatabaseContext( const Error &err ) : deferredError(err), latencies(1000), readLatencies(1000), commitLatencies(1000), GRVLatencies(1000), mutationsPerCommit(1000), bytesPerCommit(1000) {}
ACTOR static Future<Void> monitorClientInfo( Reference<AsyncVar<Optional<ClusterInterface>>> clusterInterface, Reference<ClusterConnectionFile> ccf, Reference<AsyncVar<ClientDBInfo>> outInfo ) {
try {
state Optional<std::string> incorrectConnectionString;
@ -1855,8 +1857,9 @@ Transaction::Transaction( Database const& cx )
: cx(cx), info(cx->taskID), backoff(CLIENT_KNOBS->DEFAULT_BACKOFF), committedVersion(invalidVersion), versionstampPromise(Promise<Standalone<StringRef>>()), numErrors(0), trLogInfo(createTrLogInfoProbabilistically(cx))
{
setPriority(GetReadVersionRequest::PRIORITY_DEFAULT);
if(cx->lockAware)
if(cx->lockAware) {
options.lockAware = true;
}
}
Transaction::~Transaction() {
@ -3049,11 +3052,14 @@ Future< Standalone<VectorRef<KeyRef>> > Transaction::splitStorageMetrics( KeyRan
void Transaction::checkDeferredError() { cx->checkDeferredError(); }
Reference<TransactionLogInfo> Transaction::createTrLogInfoProbabilistically(const Database &cx) {
double clientSamplingProbability = std::isinf(cx->clientInfo->get().clientTxnInfoSampleRate) ? CLIENT_KNOBS->CSI_SAMPLING_PROBABILITY : cx->clientInfo->get().clientTxnInfoSampleRate;
if (((networkOptions.logClientInfo.present() && networkOptions.logClientInfo.get()) || BUGGIFY) && g_random->random01() < clientSamplingProbability && (!g_network->isSimulated() || !g_simulator.speedUpSimulation))
return Reference<TransactionLogInfo>(new TransactionLogInfo());
else
return Reference<TransactionLogInfo>();
if(!cx->isError()) {
double clientSamplingProbability = std::isinf(cx->clientInfo->get().clientTxnInfoSampleRate) ? CLIENT_KNOBS->CSI_SAMPLING_PROBABILITY : cx->clientInfo->get().clientTxnInfoSampleRate;
if (((networkOptions.logClientInfo.present() && networkOptions.logClientInfo.get()) || BUGGIFY) && g_random->random01() < clientSamplingProbability && (!g_network->isSimulated() || !g_simulator.speedUpSimulation)) {
return Reference<TransactionLogInfo>(new TransactionLogInfo());
}
}
return Reference<TransactionLogInfo>();
}
void enableClientInfoLogging() {

View File

@ -1097,7 +1097,7 @@ public:
}
};
ReadYourWritesTransaction::ReadYourWritesTransaction( Database const& cx ) : cache(&arena), writes(&arena), tr(cx), retries(0), creationTime(now()), commitStarted(false), options(tr) {}
ReadYourWritesTransaction::ReadYourWritesTransaction( Database const& cx ) : cache(&arena), writes(&arena), tr(cx), retries(0), creationTime(now()), commitStarted(false), options(tr), deferredError(cx->deferredError) {}
ACTOR Future<Void> timebomb(double totalSeconds, Promise<Void> resetPromise) {
if(totalSeconds == 0.0) {

View File

@ -30,20 +30,8 @@
// Users of ThreadSafeTransaction might share Reference<ThreadSafe...> between different threads as long as they don't call addRef (e.g. C API follows this).
// Therefore, it is unsafe to call (explicitly or implicitly) this->addRef in any of these functions.
Reference<IDatabase> constructThreadSafeDatabase( Database db ) {
return Reference<IDatabase>( new ThreadSafeDatabase(db.extractPtr()) );
}
Future<Reference<IDatabase>> createThreadSafeDatabase( std::string connFilename, int apiVersion ) {
Database db = Database::createDatabase( connFilename, apiVersion );
return constructThreadSafeDatabase( db );
}
ThreadFuture<Reference<IDatabase>> ThreadSafeDatabase::create( std::string connFilename, int apiVersion ) {
if (!g_network) return ThreadFuture<Reference<IDatabase>>(network_not_setup());
return onMainThread( [connFilename, apiVersion](){ return createThreadSafeDatabase( connFilename, apiVersion ); } );
}
ThreadFuture<Void> ThreadSafeDatabase::onConnected() {
DatabaseContext* db = this->db;
return onMainThread( [db]() -> Future<Void> {
return onMainThread( [this]() -> Future<Void> {
db->checkDeferredError();
return db->onConnected();
} );
@ -52,31 +40,45 @@ ThreadFuture<Void> ThreadSafeDatabase::onConnected() {
ThreadFuture<Reference<IDatabase>> ThreadSafeDatabase::createFromExistingDatabase(Database db) {
return onMainThread( [db](){
db->checkDeferredError();
return Future<Reference<IDatabase>>(constructThreadSafeDatabase(db));
DatabaseContext *cx = db.getPtr();
cx->addref();
return Future<Reference<IDatabase>>(Reference<IDatabase>(new ThreadSafeDatabase(cx)));
});
}
Reference<ITransaction> ThreadSafeDatabase::createTransaction() {
return Reference<ITransaction>(new ThreadSafeTransaction(this));
}
Database ThreadSafeDatabase::unsafeGetDatabase() const {
db->addref();
return Database(db);
return Reference<ITransaction>(new ThreadSafeTransaction(Reference<ThreadSafeDatabase>::addRef(this)));
}
void ThreadSafeDatabase::setOption( FDBDatabaseOptions::Option option, Optional<StringRef> value) {
DatabaseContext *db = this->db;
Standalone<Optional<StringRef>> passValue = value;
onMainThreadVoid( [db, option, passValue](){ db->setOption(option, passValue.contents()); }, &db->deferredError );
onMainThreadVoid( [this, option, passValue](){ db->setOption(option, passValue.contents()); }, &db->deferredError );
}
ThreadSafeDatabase::ThreadSafeDatabase(std::string connFilename, int apiVersion) {
db = NULL; // All accesses to db happen on the main thread, so this pointer will be set by the time anybody uses it
Reference<ClusterConnectionFile> connFile = Reference<ClusterConnectionFile>(new ClusterConnectionFile(ClusterConnectionFile::lookupClusterFileName(connFilename).first));
onMainThreadVoid([this, connFile, apiVersion](){
try {
Database db = Database::createDatabase(connFile, apiVersion);
this->db = db.extractPtr();
}
catch(Error &e) {
this->db = new DatabaseContext(e);
}
catch(...) {
this->db = new DatabaseContext(unknown_error());
}
}, NULL);
}
ThreadSafeDatabase::~ThreadSafeDatabase() {
DatabaseContext* db = this->db;
DatabaseContext *db = this->db;
onMainThreadVoid( [db](){ db->delref(); }, NULL );
}
ThreadSafeTransaction::ThreadSafeTransaction( ThreadSafeDatabase *cx ) {
ThreadSafeTransaction::ThreadSafeTransaction( Reference<ThreadSafeDatabase> db ) {
// Allocate memory for the transaction from this thread (so the pointer is known for subsequent method calls)
// but run its constructor on the main thread
@ -84,10 +86,12 @@ ThreadSafeTransaction::ThreadSafeTransaction( ThreadSafeDatabase *cx ) {
// because the reference count of the DatabaseContext is solely managed from the main thread. If cx is destructed
// immediately after this call, it will defer the DatabaseContext::delref (and onMainThread preserves the order of
// these operations).
DatabaseContext* db = cx->db;
ReadYourWritesTransaction *tr = this->tr = ReadYourWritesTransaction::allocateOnForeignThread();
// No deferred error -- if the construction of the RYW transaction fails, we have no where to put it
onMainThreadVoid( [tr,db](){ db->addref(); new (tr) ReadYourWritesTransaction( Database(db) ); }, NULL );
onMainThreadVoid( [tr, db](){
db->db->addref();
new (tr) ReadYourWritesTransaction( Database(db->db) );
}, NULL );
}
ThreadSafeTransaction::~ThreadSafeTransaction() {
@ -357,8 +361,8 @@ void ThreadSafeApi::stopNetwork() {
::stopNetwork();
}
ThreadFuture<Reference<IDatabase>> ThreadSafeApi::createDatabase(const char *clusterFilePath) {
return ThreadSafeDatabase::create(clusterFilePath, apiVersion);
Reference<IDatabase> ThreadSafeApi::createDatabase(const char *clusterFilePath) {
return Reference<IDatabase>(new ThreadSafeDatabase(clusterFilePath, apiVersion));
}
void ThreadSafeApi::addNetworkThreadCompletionHook(void (*hook)(void*), void *hookParameter) {

View File

@ -30,7 +30,6 @@
class ThreadSafeDatabase : public IDatabase, public ThreadSafeReferenceCounted<ThreadSafeDatabase> {
public:
~ThreadSafeDatabase();
static ThreadFuture<Reference<IDatabase>> create( std::string connFilename, int apiVersion=-1 );
static ThreadFuture<Reference<IDatabase>> createFromExistingDatabase(Database cx);
Reference<ITransaction> createTransaction();
@ -46,14 +45,14 @@ private:
friend class ThreadSafeTransaction;
DatabaseContext* db;
public: // Internal use only
ThreadSafeDatabase( std::string connFilename, int apiVersion );
ThreadSafeDatabase( DatabaseContext* db ) : db(db) {}
DatabaseContext* unsafeGetPtr() const { return db; }
Database unsafeGetDatabase() const; // This is thread unsafe (ONLY call from the network thread), but respects reference counting
};
class ThreadSafeTransaction : public ITransaction, ThreadSafeReferenceCounted<ThreadSafeTransaction>, NonCopyable {
public:
explicit ThreadSafeTransaction( ThreadSafeDatabase *cx );
explicit ThreadSafeTransaction( Reference<ThreadSafeDatabase> db );
~ThreadSafeTransaction();
void cancel();
@ -119,7 +118,7 @@ public:
void runNetwork();
void stopNetwork();
ThreadFuture<Reference<IDatabase>> createDatabase(const char *clusterFilePath);
Reference<IDatabase> createDatabase(const char *clusterFilePath);
void addNetworkThreadCompletionHook(void (*hook)(void*), void *hookParameter);

View File

@ -85,8 +85,6 @@ namespace vexillographer
{
{ Scope.NetworkOption, new ScopeOptions(true,
"A set of options that can be set globally for the {@link FDB FoundationDB API}.") },
{ Scope.ClusterOption, new ScopeOptions(true,
"A set of options that can be set on a {@link Cluster}.") },
{ Scope.DatabaseOption, new ScopeOptions(true,
"A set of options that can be set on a {@link Database}.") },
{ Scope.TransactionOption, new ScopeOptions(true,

View File

@ -30,7 +30,6 @@ namespace vexillographer
public enum Scope
{
NetworkOption,
ClusterOption,
DatabaseOption,
TransactionOption,
StreamingMode,
@ -172,8 +171,6 @@ namespace vexillographer
{
case Scope.NetworkOption:
return "NET_OPTION";
case Scope.ClusterOption:
return "CLUSTER_OPTION";
case Scope.DatabaseOption:
return "DB_OPTION";
case Scope.TransactionOption: