| % 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. |
| |
| -module(erlfdb_nif). |
| |
| -compile(no_native). |
| -on_load(init/0). |
| |
| -export([ |
| ohai/0, |
| |
| get_max_api_version/0, |
| |
| future_cancel/1, |
| future_silence/1, |
| future_is_ready/1, |
| future_get_error/1, |
| future_get/1, |
| |
| create_database/1, |
| database_set_option/2, |
| database_set_option/3, |
| database_create_transaction/1, |
| |
| transaction_set_option/2, |
| transaction_set_option/3, |
| transaction_set_read_version/2, |
| transaction_get_read_version/1, |
| transaction_get/3, |
| transaction_get_key/3, |
| transaction_get_addresses_for_key/2, |
| transaction_get_range/9, |
| transaction_set/3, |
| transaction_clear/2, |
| transaction_clear_range/3, |
| transaction_atomic_op/4, |
| transaction_commit/1, |
| transaction_get_committed_version/1, |
| transaction_get_versionstamp/1, |
| transaction_watch/2, |
| transaction_on_error/2, |
| transaction_reset/1, |
| transaction_cancel/1, |
| transaction_add_conflict_range/4, |
| transaction_get_next_tx_id/1, |
| transaction_is_read_only/1, |
| transaction_has_watches/1, |
| transaction_get_writes_allowed/1, |
| transaction_get_approximate_size/1, |
| |
| get_error/1, |
| error_predicate/2 |
| ]). |
| |
| |
| -define(DEFAULT_API_VERSION, 620). |
| |
| |
| -type error() :: {erlfdb_error, Code::integer()}. |
| -type future() :: {erlfdb_future, reference(), reference()}. |
| -type database() :: {erlfdb_database, reference()}. |
| -type transaction() :: {erlfdb_transaction, reference()}. |
| |
| -type option_value() :: integer() | binary(). |
| |
| -type key_selector() :: |
| {Key::binary(), lt | lteq | gt | gteq} | |
| {Key::binary(), OrEqual::boolean(), Offset::integer()}. |
| |
| -type future_result() :: |
| database() | |
| integer() | |
| binary() | |
| {[{binary(), binary()}], integer(), boolean()} | |
| not_found | |
| {error, invalid_future_type}. |
| |
| -type network_option() :: |
| local_address | |
| cluster_file | |
| trace_enable | |
| trace_format | |
| trace_roll_size | |
| trace_max_logs_size | |
| trace_log_group | |
| knob | |
| tls_plugin | |
| tls_cert_bytes | |
| tls_cert_path | |
| tls_key_bytes | |
| tls_key_path | |
| tls_verify_peers | |
| client_buggify_enable | |
| client_buggify_disable | |
| client_buggify_section_activated_probability | |
| client_buggify_section_fired_probability | |
| tls_ca_bytes | |
| tls_ca_path | |
| tls_password | |
| disable_multi_version_client_api | |
| callbacks_on_external_threads | |
| external_client_library | |
| external_client_directory | |
| disable_local_client | |
| disable_client_statistics_logging | |
| enable_slow_task_profiling. |
| |
| -type database_option() :: |
| location_cache_size | |
| max_watches | |
| machine_id | |
| datacenter_id. |
| |
| -type transaction_option() :: |
| causal_write_risky | |
| causal_read_risky | |
| causal_read_disable | |
| next_write_no_write_conflict_range | |
| read_your_writes_disable | |
| read_ahead_disable | |
| durability_datacenter | |
| durability_risky | |
| durability_dev_null_is_web_scale | |
| priority_system_immediate | |
| priority_batch | |
| initialize_new_database | |
| access_system_keys | |
| read_system_keys | |
| debug_retry_logging | |
| transaction_logging_enable | |
| timeout | |
| retry_limit | |
| max_retry_delay | |
| snapshot_ryw_enable | |
| snapshot_ryw_disable | |
| lock_aware | |
| used_during_commit_protection_disable | |
| read_lock_aware | |
| size_limit | |
| allow_writes | |
| disallow_writes. |
| |
| |
| -type streaming_mode() :: |
| stream_want_all | |
| stream_iterator | |
| stream_exact | |
| stream_small | |
| stream_medium | |
| stream_large | |
| stream_serial. |
| |
| -type atomic_mode() :: |
| add | |
| bit_and | |
| bit_or | |
| bit_xor | |
| append_if_fits | |
| max | |
| min | |
| byte_min | |
| byte_max | |
| set_versionstamped_key | |
| set_versionstamped_value. |
| |
| -type atomic_operand() :: integer() | binary(). |
| |
| -type conflict_type() :: read | write. |
| |
| -type error_predicate() :: |
| retryable | |
| maybe_committed | |
| retryable_not_committed. |
| |
| |
| ohai() -> |
| foo. |
| |
| |
| -spec get_max_api_version() -> {ok, integer()}. |
| get_max_api_version() -> |
| erlfdb_get_max_api_version(). |
| |
| |
| -spec future_cancel(future()) -> ok. |
| future_cancel({erlfdb_future, _Ref, Ft}) -> |
| erlfdb_future_cancel(Ft). |
| |
| |
| -spec future_silence(future()) -> ok. |
| future_silence({erlfdb_future, _Ref, Ft}) -> |
| erlfdb_future_silence(Ft). |
| |
| |
| -spec future_is_ready(future()) -> boolean(). |
| future_is_ready({erlfdb_future, _Ref, Ft}) -> |
| erlfdb_future_is_ready(Ft). |
| |
| |
| -spec future_get_error(future()) -> error(). |
| future_get_error({erlfdb_future, _Ref, Ft}) -> |
| erlfdb_future_get_error(Ft). |
| |
| |
| -spec future_get(future()) -> future_result(). |
| future_get({erlfdb_future, _Ref, Ft}) -> |
| erlfdb_future_get(Ft). |
| |
| |
| -spec create_database(ClusterFilePath::binary()) -> database(). |
| create_database(<<>>) -> |
| create_database(<<0>>); |
| |
| create_database(ClusterFilePath) -> |
| Size = size(ClusterFilePath) - 1, |
| % Make sure we pass a NULL-terminated string |
| % to FoundationDB |
| NifPath = case ClusterFilePath of |
| <<_:Size/binary, 0>> -> |
| ClusterFilePath; |
| _ -> |
| <<ClusterFilePath/binary, 0>> |
| end, |
| erlfdb_create_database(NifPath). |
| |
| |
| -spec database_set_option(database(), Option::database_option()) -> ok. |
| database_set_option(Database, Option) -> |
| database_set_option(Database, Option, <<>>). |
| |
| |
| -spec database_set_option( |
| database(), |
| Option::database_option(), |
| Value::option_value() |
| ) -> ok. |
| database_set_option({erlfdb_database, Db}, Opt, Val) -> |
| BinVal = option_val_to_binary(Val), |
| erlfdb_database_set_option(Db, Opt, BinVal). |
| |
| |
| -spec database_create_transaction(database()) -> |
| {ok, transaction()}. |
| database_create_transaction({erlfdb_database, Db}) -> |
| erlfdb_database_create_transaction(Db). |
| |
| |
| -spec transaction_set_option(transaction(), Option::transaction_option()) -> ok. |
| transaction_set_option(Transaction, Option) -> |
| transaction_set_option(Transaction, Option, <<>>). |
| |
| |
| -spec transaction_set_option( |
| transaction(), |
| Option::transaction_option(), |
| Value::option_value() |
| ) -> ok. |
| transaction_set_option({erlfdb_transaction, Tx}, Opt, Val) -> |
| BinVal = option_val_to_binary(Val), |
| erlfdb_transaction_set_option(Tx, Opt, BinVal). |
| |
| |
| -spec transaction_set_read_version(transaction(), Version::integer()) -> ok. |
| transaction_set_read_version({erlfdb_transaction, Tx}, Version) -> |
| erlfdb_transaction_set_read_version(Tx, Version). |
| |
| |
| -spec transaction_get_read_version(transaction()) -> future(). |
| transaction_get_read_version({erlfdb_transaction, Tx}) -> |
| erlfdb_transaction_get_read_version(Tx). |
| |
| |
| -spec transaction_get(transaction(), Key::binary(), Snapshot::boolean()) -> |
| future(). |
| transaction_get({erlfdb_transaction, Tx}, Key, Snapshot) -> |
| erlfdb_transaction_get(Tx, Key, Snapshot). |
| |
| |
| -spec transaction_get_key( |
| transaction(), |
| KeySelector::key_selector(), |
| Snapshot::boolean() |
| ) -> future(). |
| transaction_get_key({erlfdb_transaction, Tx}, KeySelector, Snapshot) -> |
| erlfdb_transaction_get_key(Tx, KeySelector, Snapshot). |
| |
| |
| -spec transaction_get_addresses_for_key(transaction(), Key::binary()) -> |
| future(). |
| transaction_get_addresses_for_key({erlfdb_transaction, Tx}, Key) -> |
| erlfdb_transaction_get_addresses_for_key(Tx, Key). |
| |
| |
| -spec transaction_get_range( |
| transaction(), |
| StartKeySelector::key_selector(), |
| EndKeySelector::key_selector(), |
| Limit::non_neg_integer(), |
| TargetBytes::non_neg_integer(), |
| StreamingMode::streaming_mode(), |
| Iteration::non_neg_integer(), |
| Snapshot::boolean(), |
| Reverse::boolean() |
| ) -> future(). |
| transaction_get_range( |
| {erlfdb_transaction, Tx}, |
| StartKeySelector, |
| EndKeySelector, |
| Limit, |
| TargetBytes, |
| StreamingMode, |
| Iteration, |
| Snapshot, |
| Reverse |
| ) -> |
| erlfdb_transaction_get_range( |
| Tx, |
| StartKeySelector, |
| EndKeySelector, |
| Limit, |
| TargetBytes, |
| StreamingMode, |
| Iteration, |
| Snapshot, |
| Reverse |
| ). |
| |
| |
| -spec transaction_set(transaction(), Key::binary(), Val::binary()) -> ok. |
| transaction_set({erlfdb_transaction, Tx}, Key, Val) -> |
| erlfdb_transaction_set(Tx, Key, Val). |
| |
| |
| -spec transaction_clear(transaction(), Key::binary()) -> ok. |
| transaction_clear({erlfdb_transaction, Tx}, Key) -> |
| erlfdb_transaction_clear(Tx, Key). |
| |
| |
| -spec transaction_clear_range( |
| transaction(), |
| StartKey::binary(), |
| EndKey::binary() |
| ) -> ok. |
| transaction_clear_range({erlfdb_transaction, Tx}, StartKey, EndKey) -> |
| erlfdb_transaction_clear_range(Tx, StartKey, EndKey). |
| |
| |
| -spec transaction_atomic_op( |
| transaction(), |
| Key::binary(), |
| Operand::atomic_operand(), |
| Mode::atomic_mode() |
| ) -> ok. |
| transaction_atomic_op({erlfdb_transaction, Tx}, Key, Operand, OpName) -> |
| BinOperand = case Operand of |
| Bin when is_binary(Bin) -> |
| Bin; |
| Int when is_integer(Int) -> |
| <<Int:64/little>> |
| end, |
| erlfdb_transaction_atomic_op(Tx, Key, BinOperand, OpName). |
| |
| |
| -spec transaction_commit(transaction()) -> future(). |
| transaction_commit({erlfdb_transaction, Tx}) -> |
| erlfdb_transaction_commit(Tx). |
| |
| |
| -spec transaction_get_committed_version(transaction()) -> integer(). |
| transaction_get_committed_version({erlfdb_transaction, Tx}) -> |
| erlfdb_transaction_get_committed_version(Tx). |
| |
| |
| -spec transaction_get_versionstamp(transaction()) -> future(). |
| transaction_get_versionstamp({erlfdb_transaction, Tx}) -> |
| erlfdb_transaction_get_versionstamp(Tx). |
| |
| |
| -spec transaction_watch(transaction(), Key::binary()) -> future(). |
| transaction_watch({erlfdb_transaction, Tx}, Key) -> |
| erlfdb_transaction_watch(Tx, Key). |
| |
| |
| -spec transaction_on_error(transaction(), Error::integer()) -> future(). |
| transaction_on_error({erlfdb_transaction, Tx}, Error) -> |
| erlfdb_transaction_on_error(Tx, Error). |
| |
| |
| -spec transaction_reset(transaction()) -> ok. |
| transaction_reset({erlfdb_transaction, Tx}) -> |
| erlfdb_transaction_reset(Tx). |
| |
| |
| -spec transaction_cancel(transaction()) -> ok. |
| transaction_cancel({erlfdb_transaction, Tx}) -> |
| erlfdb_transaction_cancel(Tx). |
| |
| |
| -spec transaction_add_conflict_range( |
| transaction(), |
| StartKey::binary(), |
| EndKey::binary(), |
| ConflictType::conflict_type() |
| ) -> ok. |
| transaction_add_conflict_range( |
| {erlfdb_transaction, Tx}, |
| StartKey, |
| EndKey, |
| ConflictType |
| ) -> |
| erlfdb_transaction_add_conflict_range(Tx, StartKey, EndKey, ConflictType). |
| |
| |
| -spec transaction_get_approximate_size(transaction()) -> non_neg_integer(). |
| transaction_get_approximate_size({erlfdb_transaction, Tx}) -> |
| erlfdb_transaction_get_approximate_size(Tx). |
| |
| |
| -spec transaction_get_next_tx_id(transaction()) -> non_neg_integer(). |
| transaction_get_next_tx_id({erlfdb_transaction, Tx}) -> |
| erlfdb_transaction_get_next_tx_id(Tx). |
| |
| |
| -spec transaction_is_read_only(transaction()) -> true | false. |
| transaction_is_read_only({erlfdb_transaction, Tx}) -> |
| erlfdb_transaction_is_read_only(Tx). |
| |
| |
| -spec transaction_has_watches(transaction()) -> true | false. |
| transaction_has_watches({erlfdb_transaction, Tx}) -> |
| erlfdb_transaction_has_watches(Tx). |
| |
| |
| -spec transaction_get_writes_allowed(transaction()) -> true | false. |
| transaction_get_writes_allowed({erlfdb_transaction, Tx}) -> |
| erlfdb_transaction_get_writes_allowed(Tx). |
| |
| |
| -spec get_error(integer()) -> binary(). |
| get_error(Error) -> |
| erlfdb_get_error(Error). |
| |
| |
| -spec error_predicate(Predicate::error_predicate(), Error::integer()) -> |
| boolean(). |
| error_predicate(Predicate, Error) -> |
| erlfdb_error_predicate(Predicate, Error). |
| |
| |
| -spec option_val_to_binary(binary() | integer()) -> binary(). |
| option_val_to_binary(Val) when is_binary(Val) -> |
| Val; |
| |
| option_val_to_binary(Val) when is_integer(Val) -> |
| <<Val:8/little-unsigned-integer-unit:8>>. |
| |
| |
| init() -> |
| PrivDir = case code:priv_dir(?MODULE) of |
| {error, _} -> |
| EbinDir = filename:dirname(code:which(?MODULE)), |
| AppPath = filename:dirname(EbinDir), |
| filename:join(AppPath, "priv"); |
| Path -> |
| Path |
| end, |
| Status = erlang:load_nif(filename:join(PrivDir, "erlfdb_nif"), 0), |
| if Status /= ok -> Status; true -> |
| true = erlfdb_can_initialize(), |
| |
| Vsn = case application:get_env(erlfdb, api_version) of |
| {ok, V} -> V; |
| undefined -> ?DEFAULT_API_VERSION |
| end, |
| ok = select_api_version(Vsn), |
| |
| Opts = case application:get_env(erlfdb, network_options) of |
| {ok, O} when is_list(O) -> O; |
| undefined -> [] |
| end, |
| |
| lists:foreach(fun(Option) -> |
| case Option of |
| Name when is_atom(Name) -> |
| ok = network_set_option(Name, <<>>); |
| {Name, Value} when is_atom(Name) -> |
| ok = network_set_option(Name, Value) |
| end |
| end, Opts), |
| |
| ok = erlfdb_setup_network() |
| end. |
| |
| |
| -define(NOT_LOADED, erlang:nif_error({erlfdb_nif_not_loaded, ?FILE, ?LINE})). |
| |
| |
| -spec select_api_version(Version::pos_integer()) -> ok. |
| select_api_version(Version) when is_integer(Version), Version > 0 -> |
| erlfdb_select_api_version(Version). |
| |
| |
| -spec network_set_option(Option::network_option(), Value::option_value()) -> |
| ok | error(). |
| network_set_option(Name, Value) -> |
| BinValue = case Value of |
| B when is_binary(B) -> B; |
| I when is_integer(I) -> <<I:8/little-unsigned-integer-unit:8>> |
| end, |
| erlfdb_network_set_option(Name, BinValue). |
| |
| |
| % Sentinel Check |
| erlfdb_can_initialize() -> ?NOT_LOADED. |
| |
| |
| % Versioning |
| erlfdb_get_max_api_version() -> ?NOT_LOADED. |
| erlfdb_select_api_version(_Version) -> ?NOT_LOADED. |
| |
| % Networking Setup |
| erlfdb_network_set_option(_NetworkOption, _Value) -> ?NOT_LOADED. |
| erlfdb_setup_network() -> ?NOT_LOADED. |
| |
| % Futures |
| erlfdb_future_cancel(_Future) -> ?NOT_LOADED. |
| erlfdb_future_silence(_Future) -> ?NOT_LOADED. |
| erlfdb_future_is_ready(_Future) -> ?NOT_LOADED. |
| erlfdb_future_get_error(_Future) -> ?NOT_LOADED. |
| erlfdb_future_get(_Future) -> ?NOT_LOADED. |
| |
| % Databases |
| erlfdb_create_database(_ClusterFilePath) -> ?NOT_LOADED. |
| erlfdb_database_set_option(_Database, _DatabaseOption, _Value) -> ?NOT_LOADED. |
| erlfdb_database_create_transaction(_Database) -> ?NOT_LOADED. |
| |
| |
| % Transactions |
| erlfdb_transaction_set_option( |
| _Transaction, |
| _TransactionOption, |
| _Value |
| ) -> ?NOT_LOADED. |
| erlfdb_transaction_set_read_version(_Transaction, _Version) -> ?NOT_LOADED. |
| erlfdb_transaction_get_read_version(_Transaction) -> ?NOT_LOADED. |
| erlfdb_transaction_get(_Transaction, _Key, _Snapshot) -> ?NOT_LOADED. |
| erlfdb_transaction_get_key( |
| _Transaction, |
| _KeySelector, |
| _Snapshot |
| ) -> ?NOT_LOADED. |
| erlfdb_transaction_get_addresses_for_key(_Transaction, _Key) -> ?NOT_LOADED. |
| erlfdb_transaction_get_range( |
| _Transaction, |
| _StartKeySelector, |
| _EndKeySelector, |
| _Limit, |
| _TargetBytes, |
| _StreamingMode, |
| _Iteration, |
| _Snapshot, |
| _Reverse |
| ) -> ?NOT_LOADED. |
| erlfdb_transaction_set(_Transaction, _Key, _Value) -> ?NOT_LOADED. |
| erlfdb_transaction_clear(_Transaction, _Key) -> ?NOT_LOADED. |
| erlfdb_transaction_clear_range(_Transaction, _StartKey, _EndKey) -> ?NOT_LOADED. |
| erlfdb_transaction_atomic_op( |
| _Transaction, |
| _Mutation, |
| _Key, |
| _Value |
| ) -> ?NOT_LOADED. |
| erlfdb_transaction_commit(_Transaction) -> ?NOT_LOADED. |
| erlfdb_transaction_get_committed_version(_Transaction) -> ?NOT_LOADED. |
| erlfdb_transaction_get_versionstamp(_Transaction) -> ?NOT_LOADED. |
| erlfdb_transaction_watch(_Transaction, _Key) -> ?NOT_LOADED. |
| erlfdb_transaction_on_error(_Transaction, _Error) -> ?NOT_LOADED. |
| erlfdb_transaction_reset(_Transaction) -> ?NOT_LOADED. |
| erlfdb_transaction_cancel(_Transaction) -> ?NOT_LOADED. |
| erlfdb_transaction_add_conflict_range( |
| _Transaction, |
| _StartKey, |
| _EndKey, |
| _Type |
| ) -> ?NOT_LOADED. |
| erlfdb_transaction_get_next_tx_id(_Transaction) -> ?NOT_LOADED. |
| erlfdb_transaction_is_read_only(_Transaction) -> ?NOT_LOADED. |
| erlfdb_transaction_has_watches(_Transaction) -> ?NOT_LOADED. |
| erlfdb_transaction_get_writes_allowed(_Transaction) -> ?NOT_LOADED. |
| erlfdb_transaction_get_approximate_size(_Transaction) -> ?NOT_LOADED. |
| |
| |
| % Misc |
| erlfdb_get_error(_Error) -> ?NOT_LOADED. |
| erlfdb_error_predicate(_Predicate, _Error) -> ?NOT_LOADED. |