Merge branch 'release-5.2' of github.com:apple/foundationdb into feature-redwood

This commit is contained in:
Stephen Atherton 2018-04-06 16:29:37 -07:00
commit 2752a28611
827 changed files with 26264 additions and 4628 deletions

View File

@ -144,7 +144,7 @@ OBJDIR := .objs
include $(MK_INCLUDE)
clean: $(CLEAN_TARGETS)
clean: $(CLEAN_TARGETS) docpreview_clean
@echo "Cleaning toplevel"
@rm -rf $(OBJDIR)
@rm -rf $(DEPSDIR)
@ -174,12 +174,21 @@ lib/libstdc++.a: $(shell $(CC) -print-file-name=libstdc++_pic.a)
@ar rcs $@ .libstdc++/*.o
@rm -r .libstdc++
docpreview: javadoc godoc
TARGETS= $(MAKE) -C documentation docpreview
ifeq ($(PLATFORM),osx)
MD5SUM=md5
else
MD5SUM=md5sum
endif
docpreview_clean:
CLEAN_TARGETS= $(MAKE) -C documentation docpreview_clean
packages/foundationdb-docs-$(VERSION).tar.gz: FORCE javadoc godoc
TARGETS= $(MAKE) -C documentation docpackage
@mkdir -p packages
@rm -f packages/foundationdb-docs-$(VERSION).tar.gz
@cp documentation/sphinx/.dist/foundationdb-docs-$(VERSION).tar.gz packages/foundationdb-docs-$(VERSION).tar.gz
docpackage: packages/foundationdb-docs-$(VERSION).tar.gz
FORCE:
.SECONDEXPANSION:

View File

@ -4,13 +4,13 @@
# 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.

View File

@ -4,13 +4,13 @@
# 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.
@ -21,36 +21,37 @@
import sys
import os
sys.path[:0]=[os.path.join(os.path.dirname(__file__), '..', '..', 'bindings', 'python')]
sys.path[:0] = [os.path.join(os.path.dirname(__file__), '..', '..', 'bindings', 'python')]
import util
FDB_API_VERSION = 510
FDB_API_VERSION = 520
LOGGING = {
'version' : 1,
'disable_existing_loggers' : False,
'formatters' : {
'simple' : {
'format' : '%(message)s'
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'simple': {
'format': '%(message)s'
}
},
'handlers' : {
'console' : {
'level' : 'NOTSET',
'class' : 'logging.StreamHandler',
'stream' : sys.stdout,
'formatter' : 'simple'
'handlers': {
'console': {
'level': 'NOTSET',
'class': 'logging.StreamHandler',
'stream': sys.stdout,
'formatter': 'simple'
}
},
'loggers' : {
'foundationdb.bindingtester' : {
'level' : 'INFO',
'handlers' : ['console']
'loggers': {
'foundationdb.bindingtester': {
'level': 'INFO',
'handlers': ['console']
}
}
}
class Result:
def __init__(self, subspace, key, values):
self.subspace_tuple = util.subspace_to_tuple(subspace)
@ -63,7 +64,7 @@ class Result:
left_key = self.key_tuple[specification.key_start_index:]
right_key = self.key_tuple[specification.key_start_index:]
if len(left_key) != len(right_key) or left_key != right_key:
return False
@ -81,7 +82,7 @@ class Result:
def sequence_num(self, specification):
if specification.ordering_index is not None:
return self.key_tuple[specification.ordering_index]
return None
def __str__(self):
@ -91,4 +92,3 @@ class Result:
value_str = repr(self.values)
return '%s = %s' % (repr(self.subspace_tuple + self.key_tuple), value_str)

View File

@ -5,13 +5,13 @@
# 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.
@ -34,8 +34,9 @@ from threading import Timer, Event
import logging.config
from collections import OrderedDict
from functools import reduce
sys.path[:0]=[os.path.join(os.path.dirname(__file__), '..')]
sys.path[:0] = [os.path.join(os.path.dirname(__file__), '..')]
import bindingtester
@ -52,6 +53,7 @@ import fdb.tuple
fdb.api_version(FDB_API_VERSION)
class ResultSet(object):
def __init__(self, specification):
self.specification = specification
@ -80,20 +82,20 @@ class ResultSet(object):
has_filtered_error = False
while True:
results = { i : r[indices[i]] for i, r in enumerate(self.tester_results.values()) if len(r) > indices[i] }
results = {i: r[indices[i]] for i, r in enumerate(self.tester_results.values()) if len(r) > indices[i]}
if len(results) == 0:
break
sequence_nums = [ r.sequence_num(self.specification) for r in results.values() ]
sequence_nums = [r.sequence_num(self.specification) for r in results.values()]
if any([s is not None for s in sequence_nums]):
results = { i : r for i, r in results.items() if r.sequence_num(self.specification) == min(sequence_nums) }
results = {i: r for i, r in results.items() if r.sequence_num(self.specification) == min(sequence_nums)}
else:
results = { i : r for i, r in results.items() if r.matches(min(results.values()), self.specification) }
results = {i: r for i, r in results.items() if r.matches(min(results.values()), self.specification)}
for i in results.keys():
indices[i] += 1
all_results = { i : results[i] if i in results else None for i in range(len(self.tester_results)) }
all_results = {i: results[i] if i in results else None for i in range(len(self.tester_results))}
result_str = '\n'.join([' %-*s - %s' % (name_length, self.tester_results.keys()[i], r) for i, r in all_results.items()])
result_list = results.values()
@ -113,12 +115,15 @@ class ResultSet(object):
return (num_errors, has_filtered_error)
def choose_api_version(selected_api_version, tester_min_version, tester_max_version, test_min_version, test_max_version):
if selected_api_version is not None:
if selected_api_version < tester_min_version or selected_api_version > tester_max_version:
raise Exception('Not all testers support the API version %d (min=%d, max=%d)' % (selected_api_version, tester_min_version, tester_max_version))
raise Exception('Not all testers support the API version %d (min=%d, max=%d)' %
(selected_api_version, tester_min_version, tester_max_version))
elif selected_api_version < test_min_version or selected_api_version > test_max_version:
raise Exception('API version %d is not supported by the specified test (min=%d, max=%d)' % (selected_api_version, test_min_version, test_max_version))
raise Exception('API version %d is not supported by the specified test (min=%d, max=%d)' %
(selected_api_version, test_min_version, test_max_version))
api_version = selected_api_version
else:
@ -126,19 +131,23 @@ def choose_api_version(selected_api_version, tester_min_version, tester_max_vers
max_version = min(tester_max_version, test_max_version)
if min_version > max_version:
raise Exception('Not all testers support the API versions required by the specified test (tester: min=%d, max=%d; test: min=%d, max=%d)' % (tester_min_version, tester_max_version, test_min_version, test_max_version))
raise Exception(
'Not all testers support the API versions required by the specified test'
'(tester: min=%d, max=%d; test: min=%d, max=%d)' % (tester_min_version, tester_max_version, test_min_version, test_max_version))
if random.random() < 0.7:
api_version = max_version
elif random.random() < 0.7:
api_version = min_version
elif random.random() < 0.9:
api_version = random.choice([v for v in [13, 14, 16, 21, 22, 23, 100, 200, 300, 400, 410, 420, 430, 440, 450, 460, 500, 510] if v >= min_version and v <= max_version])
api_version = random.choice([v for v in [13, 14, 16, 21, 22, 23, 100, 200, 300, 400, 410, 420, 430,
440, 450, 460, 500, 510, 520] if v >= min_version and v <= max_version])
else:
api_version = random.randint(min_version, max_version)
return api_version
class TestRunner(object):
def __init__(self, args):
self.args = copy.copy(args)
@ -157,7 +166,8 @@ class TestRunner(object):
min_api_version = max([tester.min_api_version for tester in self.testers])
max_api_version = min([tester.max_api_version for tester in self.testers])
self.args.api_version = choose_api_version(self.args.api_version, min_api_version, max_api_version, self.test.min_api_version, self.test.max_api_version)
self.args.api_version = choose_api_version(self.args.api_version, min_api_version, max_api_version,
self.test.min_api_version, self.test.max_api_version)
util.get_logger().info('\nCreating test at API version %d' % self.args.api_version)
@ -165,7 +175,8 @@ class TestRunner(object):
if self.args.max_int_bits is None:
self.args.max_int_bits = max_int_bits
elif self.args.max_int_bits > max_int_bits:
raise Exception('The specified testers support at most %d-bit ints, but --max-int-bits was set to %d' % (max_int_bits, self.args.max_int_bits))
raise Exception('The specified testers support at most %d-bit ints, but --max-int-bits was set to %d' %
(max_int_bits, self.args.max_int_bits))
self.args.no_threads = self.args.no_threads or any([not tester.threads_enabled for tester in self.testers])
if self.args.no_threads and self.args.concurrency > 1:
@ -189,15 +200,15 @@ class TestRunner(object):
for i, instruction in enumerate(instructions):
if self.args.print_all or (instruction.operation != 'SWAP' and instruction.operation != 'PUSH'):
util.get_logger().error(' %d. %r' % (i+offset, instruction))
util.get_logger().error(' %d. %r' % (i + offset, instruction))
util.get_logger().error('');
util.get_logger().error('')
def run_test(self):
test_instructions = self._generate_test()
expected_results = self.test.get_expected_results()
tester_results = { s.subspace : ResultSet(s) for s in self.test.get_result_specifications() }
tester_results = {s.subspace: ResultSet(s) for s in self.test.get_result_specifications()}
for subspace, results in expected_results.items():
tester_results[subspace].add('expected', results)
@ -208,7 +219,8 @@ class TestRunner(object):
self.test.pre_run(self.db, self.args)
return_code = self._run_tester(tester)
if return_code != 0:
util.get_logger().error('Test of type %s failed to complete successfully with random seed %d and %d operations\n' % (self.args.test_name, self.args.seed, self.args.num_ops))
util.get_logger().error('Test of type %s failed to complete successfully with random seed %d and %d operations\n' %
(self.args.test_name, self.args.seed, self.args.num_ops))
return 2
tester_errors[tester] = self.test.validate(self.db, self.args)
@ -226,18 +238,19 @@ class TestRunner(object):
self._insert_instructions(test_instructions)
def _generate_test(self):
util.get_logger().info('Generating %s test at seed %d with %d op(s) and %d concurrent tester(s)...' % (self.args.test_name, self.args.seed, self.args.num_ops, self.args.concurrency))
util.get_logger().info('Generating %s test at seed %d with %d op(s) and %d concurrent tester(s)...' %
(self.args.test_name, self.args.seed, self.args.num_ops, self.args.concurrency))
random.seed(self.test_seed)
if self.args.concurrency == 1:
self.test.setup(self.args)
test_instructions = { fdb.Subspace((self.args.instruction_prefix,)) : self.test.generate(self.args, 0) }
test_instructions = {fdb.Subspace((self.args.instruction_prefix,)): self.test.generate(self.args, 0)}
else:
test_instructions = {}
main_thread = InstructionSet()
for i in range(self.args.concurrency):
#thread_spec = fdb.Subspace(('thread_spec', i))
# thread_spec = fdb.Subspace(('thread_spec', i))
thread_spec = 'thread_spec%d' % i
main_thread.push_args(thread_spec)
main_thread.append('START_THREAD')
@ -260,7 +273,7 @@ class TestRunner(object):
params += [self.args.cluster_file]
util.get_logger().info('\nRunning tester \'%s\'...' % ' '.join(params))
sys.stdout.flush();
sys.stdout.flush()
proc = subprocess.Popen(params)
timed_out = Event()
@ -321,9 +334,10 @@ class TestRunner(object):
if len(errors) > 0:
util.get_logger().error('The %s tester reported errors:\n' % tester.name)
for i, error in enumerate(errors):
util.get_logger().error(' %d. %s' % (i+1, error))
util.get_logger().error(' %d. %s' % (i + 1, error))
log_message = '\nTest with seed %d and concurrency %d had %d incorrect result(s) and %d error(s) at API version %d' % (self.args.seed, self.args.concurrency, num_incorrect, num_errors, self.args.api_version)
log_message = '\nTest with seed %d and concurrency %d had %d incorrect result(s) and %d error(s) at API version %d' %\
(self.args.seed, self.args.concurrency, num_incorrect, num_errors, self.args.api_version)
if num_errors == 0 and (num_incorrect == 0 or has_filtered_error):
util.get_logger().info(log_message)
if has_filtered_error:
@ -333,6 +347,7 @@ class TestRunner(object):
util.get_logger().error(log_message)
return 1
def bisect(test_runner, args):
util.get_logger().info('')
@ -354,7 +369,8 @@ def bisect(test_runner, args):
util.get_logger().error('Error finding minimal failing test for seed %d. The failure may not be deterministic' % args.seed)
return 1
else:
util.get_logger().error('No failing test found for seed %d with %d ops. Try specifying a larger --num-ops parameter.' % (args.seed, args.num_ops))
util.get_logger().error('No failing test found for seed %d with %d ops. Try specifying a larger --num-ops parameter.'
% (args.seed, args.num_ops))
return 0
elif result == 0:
@ -365,30 +381,45 @@ def bisect(test_runner, args):
util.get_logger().info('Test with %d operations failed with error code %d\n' % (test_runner.args.num_ops, result))
upper_bound = test_runner.args.num_ops
def parse_args(argv):
parser = argparse.ArgumentParser(description='FoundationDB Binding API Tester')
parser.add_argument('--test-name', default='scripted', help='The name of the test to run. Must be the name of a test specified in the tests folder. (default=\'scripted\')')
parser.add_argument('--test-name', default='scripted',
help='The name of the test to run. Must be the name of a test specified in the tests folder. (default=\'scripted\')')
parser.add_argument(metavar='tester1', dest='test1', help='Name of the first tester to invoke')
parser.add_argument('--compare', metavar='tester2', nargs='?', type=str, default=None, const='python', dest='test2', help='When specified, a second tester will be run and compared against the first. This flag takes an optional argument for the second tester to invoke (default = \'python\').')
parser.add_argument('--print-test', action='store_true', help='Instead of running a test, prints the set of instructions generated for that test. Unless --all is specified, all setup, finalization, PUSH, and SWAP instructions will be excluded.')
parser.add_argument('--compare', metavar='tester2', nargs='?', type=str, default=None, const='python', dest='test2',
help='When specified, a second tester will be run and compared against the first. This flag takes an optional argument '
'for the second tester to invoke (default = \'python\').')
parser.add_argument('--print-test', action='store_true',
help='Instead of running a test, prints the set of instructions generated for that test. Unless --all is specified, all '
'setup, finalization, PUSH, and SWAP instructions will be excluded.')
parser.add_argument('--all', dest='print_all', action='store_true', help='Causes --print-test to print all instructions.')
parser.add_argument('--bisect', action='store_true', help='Run the specified test varying the number of operations until a minimal failing test is found. Does not work for concurrent tests.')
parser.add_argument('--bisect', action='store_true',
help='Run the specified test varying the number of operations until a minimal failing test is found. Does not work for '
'concurrent tests.')
parser.add_argument('--insert-only', action='store_true', help='Insert the test instructions into the database, but do not run it.')
parser.add_argument('--concurrency', type=int, default=1, help='Number of concurrent test threads to run. (default = 1).')
parser.add_argument('--num-ops', type=int, default=100, help='The number of operations to generate per thread (default = 100)')
parser.add_argument('--seed', type=int, help='The random seed to use for generating the test')
parser.add_argument('--max-int-bits', type=int, default=None, help='Maximum number of bits to use for int types in testers. By default, the largest value supported by the testers being run will be chosen.')
parser.add_argument('--api-version', default=None, type=int, help='The API version that the testers should use. Not supported in scripted mode. (default = random version supported by all testers)')
parser.add_argument('--max-int-bits', type=int, default=None,
help='Maximum number of bits to use for int types in testers. By default, the largest value supported by the testers being '
'run will be chosen.')
parser.add_argument('--api-version', default=None, type=int,
help='The API version that the testers should use. Not supported in scripted mode. (default = random version supported by '
'all testers)')
parser.add_argument('--cluster-file', type=str, default=None, help='The cluster file for the cluster being connected to. (default None)')
parser.add_argument('--timeout', type=int, default=600, help='The timeout in seconds for running each individual tester. (default 600)')
parser.add_argument('--enable-client-trace-logging', nargs='?', type=str, default=None, const='.', help='Enables trace file output. This flag takes an optional argument specifying the output directory (default = \'.\').')
parser.add_argument('--instruction-prefix', type=str, default='test_spec', help='The prefix under which the main thread of test instructions are inserted (default=\'test_spec\').')
parser.add_argument('--output-subspace', type=str, default='tester_output', help='The string used to create the output subspace for the testers. The subspace will be of the form (<output_subspace>,). (default=\'tester_output\')')
parser.add_argument('--enable-client-trace-logging', nargs='?', type=str, default=None, const='.',
help='Enables trace file output. This flag takes an optional argument specifying the output directory (default = \'.\').')
parser.add_argument('--instruction-prefix', type=str, default='test_spec',
help='The prefix under which the main thread of test instructions are inserted (default=\'test_spec\').')
parser.add_argument('--output-subspace', type=str, default='tester_output',
help='The string used to create the output subspace for the testers. The subspace will be of the form (<output_subspace>,). '
'(default=\'tester_output\')')
parser.add_argument('--logging-level', type=str, default='INFO', choices=['ERROR', 'WARNING', 'INFO', 'DEBUG'], help='Specifies the level of detail in the tester output (default=\'INFO\').')
parser.add_argument('--logging-level', type=str, default='INFO',
choices=['ERROR', 'WARNING', 'INFO', 'DEBUG'], help='Specifies the level of detail in the tester output (default=\'INFO\').')
# SOMEDAY: this applies only to the scripted test. Should we invoke test files specifically (as in circus),
# or invoke them here and allow tests to add arguments?
@ -396,6 +427,7 @@ def parse_args(argv):
return parser.parse_args(argv)
def validate_args(args):
if args.insert_only and args.bisect:
raise Exception('--bisect cannot be used with --insert-only')
@ -408,6 +440,7 @@ def validate_args(args):
if args.concurrency > 1 and args.test2:
raise Exception('--compare cannot be used with concurrent tests')
def main(argv):
args = parse_args(argv)
try:
@ -444,9 +477,11 @@ def main(argv):
util.get_logger().debug(traceback.format_exc())
exit(3)
except:
except BaseException:
util.get_logger().error('\nERROR: %s' % sys.exc_info()[0])
util.get_logger().info(traceback.format_exc())
exit(3)
if __name__ == '__main__': sys.exit(main(sys.argv[1:]))
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))

View File

@ -4,13 +4,13 @@
# 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.
@ -20,9 +20,10 @@
import os
MAX_API_VERSION = 510
COMMON_TYPES = [ 'null', 'bytes', 'string', 'int', 'uuid', 'bool', 'float', 'double', 'tuple' ]
ALL_TYPES = COMMON_TYPES + [ 'versionstamp' ]
MAX_API_VERSION = 520
COMMON_TYPES = ['null', 'bytes', 'string', 'int', 'uuid', 'bool', 'float', 'double', 'tuple']
ALL_TYPES = COMMON_TYPES + ['versionstamp']
class Tester:
def __init__(self, name, cmd, max_int_bits=64, min_api_version=0, max_api_version=MAX_API_VERSION, threads_enabled=True, types=COMMON_TYPES):
@ -44,22 +45,24 @@ class Tester:
else:
return Tester(test_name_or_args.split(' ')[0], test_name_or_args)
def _absolute_path(path):
return os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', path)
_java_cmd = 'java -ea -cp %s:%s com.apple.foundationdb.test.' % (
_absolute_path('java/foundationdb-client.jar'),
_absolute_path('java/foundationdb-tests.jar'))
_absolute_path('java/foundationdb-client.jar'),
_absolute_path('java/foundationdb-tests.jar'))
# We could set min_api_version lower on some of these if the testers were updated to support them
testers = {
'python' : Tester('python', 'python ' + _absolute_path('python/tests/tester.py'), 2040, 23, MAX_API_VERSION, types=ALL_TYPES),
'python3' : Tester('python3', 'python3 ' + _absolute_path('python/tests/tester.py'), 2040, 23, MAX_API_VERSION, types=ALL_TYPES),
'node' : Tester('node', _absolute_path('nodejs/tests/tester.js'), 53, 500, MAX_API_VERSION),
'streamline' : Tester('streamline', _absolute_path('nodejs/tests/streamline_tester._js'), 53, 500, MAX_API_VERSION),
'ruby' : Tester('ruby', _absolute_path('ruby/tests/tester.rb'), 64, 23, MAX_API_VERSION),
'java' : Tester('java', _java_cmd + 'StackTester', 2040, 510, MAX_API_VERSION, types=ALL_TYPES),
'java_async' : Tester('java', _java_cmd + 'AsyncStackTester', 2040, 510, MAX_API_VERSION, types=ALL_TYPES),
'go' : Tester('go', _absolute_path('go/build/bin/_stacktester'), 63, 200, MAX_API_VERSION),
'flow' : Tester('flow', _absolute_path('flow/bin/fdb_flow_tester'), 63, 500, MAX_API_VERSION),
'python': Tester('python', 'python ' + _absolute_path('python/tests/tester.py'), 2040, 23, MAX_API_VERSION, types=ALL_TYPES),
'python3': Tester('python3', 'python3 ' + _absolute_path('python/tests/tester.py'), 2040, 23, MAX_API_VERSION, types=ALL_TYPES),
'node': Tester('node', _absolute_path('nodejs/tests/tester.js'), 53, 500, MAX_API_VERSION),
'streamline': Tester('streamline', _absolute_path('nodejs/tests/streamline_tester._js'), 53, 500, MAX_API_VERSION),
'ruby': Tester('ruby', _absolute_path('ruby/tests/tester.rb'), 64, 23, MAX_API_VERSION),
'java': Tester('java', _java_cmd + 'StackTester', 2040, 510, MAX_API_VERSION, types=ALL_TYPES),
'java_async': Tester('java', _java_cmd + 'AsyncStackTester', 2040, 510, MAX_API_VERSION, types=ALL_TYPES),
'go': Tester('go', _absolute_path('go/build/bin/_stacktester'), 63, 200, MAX_API_VERSION),
'flow': Tester('flow', _absolute_path('flow/bin/fdb_flow_tester'), 63, 500, MAX_API_VERSION),
}

View File

@ -4,13 +4,13 @@
# 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.
@ -28,11 +28,12 @@ from bindingtester import util
fdb.api_version(FDB_API_VERSION)
class ResultSpecification(object):
def __init__(self, subspace, key_start_index=0, ordering_index=None, global_error_filter=None):
self.subspace = subspace
self.key_start_index = key_start_index
self.ordering_index = ordering_index
self.ordering_index = ordering_index
if global_error_filter is not None:
error_str = '|'.join(['%d' % e for e in global_error_filter])
@ -45,7 +46,7 @@ class ResultSpecification(object):
return False
return self.error_regex.search(str) is not None
class Test(object):
def __init__(self, subspace, min_api_version=0, max_api_version=int(1e9)):
@ -54,7 +55,7 @@ class Test(object):
self.max_api_version = max_api_version
# Returns nothing
def setup(self, args):
def setup(self, args):
pass
# Returns an instance of TestInstructions
@ -75,7 +76,7 @@ class Test(object):
def get_expected_results(self):
return {}
# Returns a list of error strings
# Returns a list of error strings
def validate(self, db, args):
return []
@ -88,6 +89,7 @@ class Test(object):
return test_class[0](subspace)
class Instruction(object):
def __init__(self, operation):
self.operation = operation
@ -103,6 +105,7 @@ class Instruction(object):
def __repr__(self):
return repr(self.operation)
class PushInstruction(Instruction):
def __init__(self, argument):
self.operation = 'PUSH'
@ -115,6 +118,7 @@ class PushInstruction(Instruction):
def __repr__(self):
return '%r %r' % (self.operation, self.argument)
class TestInstructions(object):
def __init__(self):
pass
@ -126,13 +130,14 @@ class TestInstructions(object):
def insert_operations(self, db, subspace):
pass
class InstructionSet(TestInstructions, list):
def __init__(self):
TestInstructions.__init__(self)
list.__init__(self)
self.core_test_begin = 0
self.core_test_end = None
self.core_test_end = None
def push_args(self, *args):
self.extend([PushInstruction(arg) for arg in reversed(args)])
@ -144,7 +149,7 @@ class InstructionSet(TestInstructions, list):
list.append(self, Instruction(instruction))
def get_threads(self, subspace):
return { subspace : self }
return {subspace: self}
def setup_complete(self):
self.core_test_begin = len(self)
@ -153,16 +158,17 @@ class InstructionSet(TestInstructions, list):
self.core_test_end = len(self)
def core_instructions(self):
return self[self.core_test_begin : self.core_test_end]
return self[self.core_test_begin: self.core_test_end]
@fdb.transactional
def _insert_operations_transactional(self, tr, subspace, start, count):
for i, instruction in enumerate(self[start : start+count]):
for i, instruction in enumerate(self[start: start + count]):
tr[subspace.pack((start + i,))] = instruction.to_value()
def insert_operations(self, db, subspace):
for i in range(0, int(math.ceil(len(self) / 1000.0))):
self._insert_operations_transactional(db, subspace, i*1000, 1000)
self._insert_operations_transactional(db, subspace, i * 1000, 1000)
class ThreadedInstructionSet(TestInstructions):
def __init__(self):
@ -194,4 +200,5 @@ class ThreadedInstructionSet(TestInstructions):
self.threads[subspace] = thread_instructions
return thread_instructions
util.import_subclasses(__file__, 'bindingtester.tests')

View File

@ -4,13 +4,13 @@
# 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.
@ -18,7 +18,6 @@
# limitations under the License.
#
import ctypes
import random
import struct
@ -32,11 +31,12 @@ from bindingtester.tests import test_util
fdb.api_version(FDB_API_VERSION)
class ApiTest(Test):
def __init__(self, subspace):
super(ApiTest, self).__init__(subspace)
self.workspace = self.subspace['workspace'] # The keys and values here must match between subsequent runs of the same test
self.scratch = self.subspace['scratch'] # The keys and values here can differ between runs
self.workspace = self.subspace['workspace'] # The keys and values here must match between subsequent runs of the same test
self.scratch = self.subspace['scratch'] # The keys and values here can differ between runs
self.stack_subspace = self.subspace['stack']
self.versionstamped_values = self.scratch['versionstamped_values']
@ -78,7 +78,7 @@ class ApiTest(Test):
self.key_depth = max(0, self.key_depth - num)
self.outstanding_ops = [i for i in self.outstanding_ops if i[0] <= self.stack_size]
def ensure_string(self, instructions, num):
while self.string_depth < num:
instructions.push_args(self.random.random_string(random.randint(0, 100)))
@ -97,7 +97,7 @@ class ApiTest(Test):
tup = self.random.random_tuple(5)
self.generated_keys.append(tup)
return self.workspace.pack(tup)
return self.workspace.pack(tup)
def ensure_key(self, instructions, num):
while self.key_depth < num:
@ -131,7 +131,7 @@ class ApiTest(Test):
def wait_for_reads(self, instructions):
while len(self.outstanding_ops) > 0 and self.outstanding_ops[-1][0] <= self.stack_size:
read = self.outstanding_ops.pop()
#print '%d. waiting for read at instruction %r' % (len(instructions), read)
# print '%d. waiting for read at instruction %r' % (len(instructions), read)
test_util.to_front(instructions, self.stack_size - read[0])
instructions.append('WAIT_FUTURE')
@ -168,7 +168,7 @@ class ApiTest(Test):
op_choices += resets
idempotent_atomic_ops = [u'BIT_AND', u'BIT_OR', u'MAX', u'MIN', u'BYTE_MIN', u'BYTE_MAX']
atomic_ops = idempotent_atomic_ops + [u'ADD', u'BIT_XOR']
atomic_ops = idempotent_atomic_ops + [u'ADD', u'BIT_XOR', u'APPEND_IF_FITS']
if args.concurrency > 1:
self.max_keys = random.randint(100, 1000)
@ -187,7 +187,7 @@ class ApiTest(Test):
index = len(instructions)
read_performed = False
#print 'Adding instruction %s at %d' % (op, index)
# print 'Adding instruction %s at %d' % (op, index)
if args.concurrency == 1 and (op in database_mutations):
self.wait_for_reads(instructions)
@ -211,7 +211,7 @@ class ApiTest(Test):
instructions.push_args(random.randint(0, 5000))
instructions.append(op)
self.outstanding_ops.append((self.stack_size, len(instructions)-1))
self.outstanding_ops.append((self.stack_size, len(instructions) - 1))
if args.concurrency == 1:
self.wait_for_reads(instructions)
@ -236,7 +236,7 @@ class ApiTest(Test):
test_util.to_front(instructions, 3)
instructions.append(op)
#Don't add key here because we may be outside of our prefix
# Don't add key here because we may be outside of our prefix
self.add_strings(1)
self.can_set_version = False
read_performed = True
@ -249,7 +249,7 @@ class ApiTest(Test):
test_util.to_front(instructions, 4)
instructions.append(op)
if range_params[0] >= 1 and range_params[0] <= 1000: # avoid adding a string if the limit is large
if range_params[0] >= 1 and range_params[0] <= 1000: # avoid adding a string if the limit is large
self.add_strings(1)
else:
self.add_stack_items(1)
@ -258,14 +258,14 @@ class ApiTest(Test):
read_performed = True
elif op == 'GET_RANGE_STARTS_WITH' or op == 'GET_RANGE_STARTS_WITH_SNAPSHOT' or op == 'GET_RANGE_STARTS_WITH_DATABASE':
#TODO: not tested well
# TODO: not tested well
self.ensure_key(instructions, 1)
range_params = self.random.random_range_params()
instructions.push_args(*range_params)
test_util.to_front(instructions, 3)
instructions.append(op)
if range_params[0] >= 1 and range_params[0] <= 1000: # avoid adding a string if the limit is large
if range_params[0] >= 1 and range_params[0] <= 1000: # avoid adding a string if the limit is large
self.add_strings(1)
else:
self.add_stack_items(1)
@ -285,7 +285,7 @@ class ApiTest(Test):
test_util.to_front(instructions, 9)
instructions.append(op)
if range_params[0] >= 1 and range_params[0] <= 1000: # avoid adding a string if the limit is large
if range_params[0] >= 1 and range_params[0] <= 1000: # avoid adding a string if the limit is large
self.add_strings(1)
else:
self.add_stack_items(1)
@ -302,8 +302,8 @@ class ApiTest(Test):
self.ensure_key_value(instructions)
instructions.append(op)
if op == 'SET_DATABASE':
self.add_stack_items(1)
self.add_stack_items(1)
elif op == 'SET_READ_VERSION':
if self.has_version and self.can_set_version:
instructions.append(op)
@ -316,7 +316,7 @@ class ApiTest(Test):
self.add_stack_items(1)
elif op == 'CLEAR_RANGE' or op == 'CLEAR_RANGE_DATABASE':
#Protect against inverted range
# Protect against inverted range
key1 = self.workspace.pack(self.random.random_tuple(5))
key2 = self.workspace.pack(self.random.random_tuple(5))
@ -334,7 +334,7 @@ class ApiTest(Test):
instructions.append(op)
if op == 'CLEAR_RANGE_STARTS_WITH_DATABASE':
self.add_stack_items(1)
elif op == 'ATOMIC_OP' or op == 'ATOMIC_OP_DATABASE':
self.ensure_key_value(instructions)
if op == 'ATOMIC_OP' or args.concurrency > 1:
@ -351,10 +351,10 @@ class ApiTest(Test):
key1 = self.versionstamped_values.pack((rand_str1,))
split = random.randint(0, 70)
rand_str2 = self.random.random_string(20+split) + fdb.tuple.Versionstamp._UNSET_TR_VERSION + self.random.random_string(70-split)
rand_str2 = self.random.random_string(20 + split) + fdb.tuple.Versionstamp._UNSET_TR_VERSION + self.random.random_string(70 - split)
key2 = self.versionstamped_keys.pack() + rand_str2
index = key2.find(fdb.tuple.Versionstamp._UNSET_TR_VERSION)
key2 += chr(index%256)+chr(index/256)
key2 += chr(index % 256) + chr(index / 256)
instructions.push_args(u'SET_VERSIONSTAMPED_VALUE', key1, fdb.tuple.Versionstamp._UNSET_TR_VERSION + rand_str2)
instructions.append('ATOMIC_OP')
@ -436,8 +436,8 @@ class ApiTest(Test):
version_key = self.versionstamped_keys.pack(tup)
first_incomplete = version_key.find(fdb.tuple.Versionstamp._UNSET_TR_VERSION)
second_incomplete = -1 if first_incomplete < 0 else version_key.find(fdb.tuple.Versionstamp._UNSET_TR_VERSION,
first_incomplete + len(fdb.tuple.Versionstamp._UNSET_TR_VERSION) + 1)
second_incomplete = -1 if first_incomplete < 0 else \
version_key.find(fdb.tuple.Versionstamp._UNSET_TR_VERSION, first_incomplete + len(fdb.tuple.Versionstamp._UNSET_TR_VERSION) + 1)
# If there is exactly one incomplete versionstamp, perform the versionstamped key operation.
if first_incomplete >= 0 and second_incomplete < 0:
@ -449,7 +449,8 @@ class ApiTest(Test):
instructions.append('ATOMIC_OP')
version_value_key = self.versionstamped_values.pack((rand_str,))
instructions.push_args(u'SET_VERSIONSTAMPED_VALUE', version_value_key, fdb.tuple.Versionstamp._UNSET_TR_VERSION + fdb.tuple.pack(tup))
instructions.push_args(u'SET_VERSIONSTAMPED_VALUE', version_value_key,
fdb.tuple.Versionstamp._UNSET_TR_VERSION + fdb.tuple.pack(tup))
instructions.append('ATOMIC_OP')
self.can_use_key_selectors = False
@ -469,7 +470,7 @@ class ApiTest(Test):
instructions.append(op)
self.add_strings(len(tups))
#Use SUB to test if integers are correctly unpacked
# Use SUB to test if integers are correctly unpacked
elif op == 'SUB':
a = self.random.random_int() / 2
b = self.random.random_int() / 2
@ -512,7 +513,7 @@ class ApiTest(Test):
assert False
if read_performed and op not in database_reads:
self.outstanding_ops.append((self.stack_size, len(instructions)-1))
self.outstanding_ops.append((self.stack_size, len(instructions) - 1))
if args.concurrency == 1 and (op in database_reads or op in database_mutations):
instructions.append('WAIT_FUTURE')
@ -536,7 +537,7 @@ class ApiTest(Test):
def check_versionstamps(self, tr, begin_key, limit):
next_begin = None
incorrect_versionstamps = 0
for k,v in tr.get_range(begin_key, self.versionstamped_values.range().stop, limit=limit):
for k, v in tr.get_range(begin_key, self.versionstamped_values.range().stop, limit=limit):
next_begin = k + '\x00'
tup = fdb.tuple.unpack(k)
key = self.versionstamped_keys.pack() + v[10:].replace(fdb.tuple.Versionstamp._UNSET_TR_VERSION, v[:10], 1)
@ -545,7 +546,6 @@ class ApiTest(Test):
util.get_logger().error(' %s != %s', repr(tr[key]), repr(tup[-1]))
incorrect_versionstamps += 1
return (next_begin, incorrect_versionstamps)
def validate(self, db, args):
@ -564,8 +564,7 @@ class ApiTest(Test):
return errors
def get_result_specifications(self):
return [
ResultSpecification(self.workspace, global_error_filter=[1007, 1021]),
ResultSpecification(self.stack_subspace, key_start_index=1, ordering_index=1, global_error_filter=[1007, 1021])
return [
ResultSpecification(self.workspace, global_error_filter=[1007, 1021]),
ResultSpecification(self.stack_subspace, key_start_index=1, ordering_index=1, global_error_filter=[1007, 1021])
]

View File

@ -4,13 +4,13 @@
# 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.
@ -32,6 +32,7 @@ from bindingtester.tests.directory_util import DirListEntry
fdb.api_version(FDB_API_VERSION)
class DirectoryTest(Test):
def __init__(self, subspace):
@ -71,12 +72,12 @@ class DirectoryTest(Test):
instructions = InstructionSet()
op_choices = ['NEW_TRANSACTION', 'COMMIT']
general = ['DIRECTORY_CREATE_SUBSPACE', 'DIRECTORY_CREATE_LAYER']
op_choices += general
directory_mutations = ['DIRECTORY_CREATE_OR_OPEN', 'DIRECTORY_CREATE', 'DIRECTORY_MOVE', 'DIRECTORY_MOVE_TO',
directory_mutations = ['DIRECTORY_CREATE_OR_OPEN', 'DIRECTORY_CREATE', 'DIRECTORY_MOVE', 'DIRECTORY_MOVE_TO',
'DIRECTORY_REMOVE', 'DIRECTORY_REMOVE_IF_EXISTS']
directory_reads = ['DIRECTORY_EXISTS', 'DIRECTORY_OPEN', 'DIRECTORY_LIST']
@ -105,17 +106,18 @@ class DirectoryTest(Test):
# Generate some directories that we are going to create in advance. This tests that other bindings
# are compatible with the Python implementation
self.prepopulated_dirs = [ (generate_path(min_length=1), self.generate_layer()) for i in range(5) ]
self.prepopulated_dirs = [(generate_path(min_length=1), self.generate_layer()) for i in range(5)]
for path, layer in self.prepopulated_dirs:
instructions.push_args(layer)
instructions.push_args(*test_util.with_length(path))
instructions.append('DIRECTORY_OPEN')
#print '%d. Selected %s, dir=%s, has_known_prefix=%s, dir_list_len=%d' % (len(instructions), 'DIRECTORY_OPEN', repr(self.dir_index), False, len(self.dir_list))
# print '%d. Selected %s, dir=%s, has_known_prefix=%s, dir_list_len=%d' \
# % (len(instructions), 'DIRECTORY_OPEN', repr(self.dir_index), False, len(self.dir_list))
self.dir_list.append(self.dir_list[0].add_child(path, default_path, self.root, DirListEntry(True, True, has_known_prefix=False)))
instructions.setup_complete()
for i in range(args.num_ops):
if random.random() < 0.5:
self.dir_index = random.randrange(0, len(self.dir_list))
@ -131,7 +133,8 @@ class DirectoryTest(Test):
op = random.choice(choices)
dir_entry = self.dir_list[self.dir_index]
#print '%d. Selected %s, dir=%s, has_known_prefix=%s, dir_list_len=%d' % (len(instructions), op, repr(self.dir_index), repr(dir_entry.has_known_prefix), len(self.dir_list))
# print '%d. Selected %s, dir=%s, has_known_prefix=%s, dir_list_len=%d' \
# % (len(instructions), op, repr(self.dir_index), repr(dir_entry.has_known_prefix), len(self.dir_list))
if op.endswith('_DATABASE') or op.endswith('_SNAPSHOT'):
root_op = op[0:-9]
@ -160,7 +163,7 @@ class DirectoryTest(Test):
indices.append(len(self.dir_list))
self.dir_list.append(DirListEntry(False, True))
instructions.push_args(random.choice([0,1]))
instructions.push_args(random.choice([0, 1]))
instructions.push_args(*indices)
instructions.append(op)
self.dir_list.append(DirListEntry(True, False, False))
@ -172,7 +175,7 @@ class DirectoryTest(Test):
test_util.blocking_commit(instructions)
path = generate_path()
op_args = test_util.with_length(path) + (self.generate_layer(),)
op_args = test_util.with_length(path) + (self.generate_layer(),)
directory_util.push_instruction_and_record_prefix(instructions, op, op_args, path, len(self.dir_list), self.random, self.prefix_log)
if not op.endswith('_DATABASE') and args.concurrency == 1:
@ -189,18 +192,19 @@ class DirectoryTest(Test):
# Because allocated prefixes are non-deterministic, we cannot have overlapping
# transactions that allocate/remove these prefixes in a comparison test
if op.endswith('_DATABASE') and args.concurrency == 1: # and allow_empty_prefix:
if op.endswith('_DATABASE') and args.concurrency == 1: # and allow_empty_prefix:
test_util.blocking_commit(instructions)
path = generate_path()
op_args = test_util.with_length(path) + (layer, prefix)
op_args = test_util.with_length(path) + (layer, prefix)
if prefix is None:
directory_util.push_instruction_and_record_prefix(instructions, op, op_args, path, len(self.dir_list), self.random, self.prefix_log)
directory_util.push_instruction_and_record_prefix(
instructions, op, op_args, path, len(self.dir_list), self.random, self.prefix_log)
else:
instructions.push_args(*op_args)
instructions.append(op)
if not op.endswith('_DATABASE') and args.concurrency == 1: # and allow_empty_prefix:
if not op.endswith('_DATABASE') and args.concurrency == 1: # and allow_empty_prefix:
test_util.blocking_commit(instructions)
self.dir_list.append(dir_entry.add_child(path, default_path, self.root, DirListEntry(True, True, bool(prefix))))
@ -228,13 +232,14 @@ class DirectoryTest(Test):
new_path = generate_path()
instructions.push_args(*test_util.with_length(new_path))
instructions.append(op)
self.dir_list.append(dir_entry.root.add_child(new_path, default_path, self.root, DirListEntry(True, True, dir_entry.has_known_prefix)))
self.dir_list.append(dir_entry.root.add_child(new_path, default_path, self.root,
DirListEntry(True, True, dir_entry.has_known_prefix)))
# Make sure that the default directory subspace still exists after moving the current directory
self.ensure_default_directory_subspace(instructions, default_path)
# FIXME: There is currently a problem with removing partitions. In these generated tests, it's possible
# for a removed partition to resurrect itself and insert keys into the database using its allocated
# for a removed partition to resurrect itself and insert keys into the database using its allocated
# prefix. The result is non-deterministic HCA errors.
elif root_op == 'DIRECTORY_REMOVE' or root_op == 'DIRECTORY_REMOVE_IF_EXISTS':
# Because allocated prefixes are non-deterministic, we cannot have overlapping
@ -242,7 +247,7 @@ class DirectoryTest(Test):
if op.endswith('_DATABASE') and args.concurrency == 1:
test_util.blocking_commit(instructions)
path = ()
path = ()
count = random.randint(0, 1)
if count == 1:
path = generate_path()
@ -256,14 +261,14 @@ class DirectoryTest(Test):
self.ensure_default_directory_subspace(instructions, default_path)
elif root_op == 'DIRECTORY_LIST' or root_op == 'DIRECTORY_EXISTS':
path = ()
path = ()
count = random.randint(0, 1)
if count == 1:
path = generate_path()
instructions.push_args(*test_util.with_length(path))
instructions.push_args(count)
instructions.append(op)
elif root_op == 'DIRECTORY_PACK_KEY':
t = self.random.random_tuple(5)
instructions.push_args(*test_util.with_length(t))
@ -305,10 +310,10 @@ class DirectoryTest(Test):
instructions.push_args(self.directory_log.key())
instructions.append('DIRECTORY_LOG_DIRECTORY')
if dir_entry.has_known_prefix and dir_entry.is_subspace:
#print '%d. Logging subspace: %d' % (i, dir_entry.dir_id)
# print '%d. Logging subspace: %d' % (i, dir_entry.dir_id)
instructions.push_args(self.subspace_log.key())
instructions.append('DIRECTORY_LOG_SUBSPACE')
if (i+1) % 100 == 0:
if (i + 1) % 100 == 0:
test_util.blocking_commit(instructions)
instructions.push_args(self.stack_subspace.key())
@ -332,18 +337,21 @@ class DirectoryTest(Test):
# If a partition is created, allocates a prefix, and then is removed, subsequent prefix
# allocations could collide with prior ones. We can get around this by not allowing
# a removed directory (or partition) to be used, but that weakens the test in another way.
#errors += directory_util.check_for_duplicate_prefixes(db, self.prefix_log)
# errors += directory_util.check_for_duplicate_prefixes(db, self.prefix_log)
return errors
def get_result_specfications(self):
return [
ResultSpecification(self.stack, key_start_index=1, ordering_index=1),
ResultSpecification(self.directory_log, ordering_index=0),
ResultSpecification(self.subspace_log, ordering_index=0)
def get_result_specifications(self):
return [
ResultSpecification(self.stack_subspace, key_start_index=1, ordering_index=1),
ResultSpecification(self.directory_log, ordering_index=0),
ResultSpecification(self.subspace_log, ordering_index=0)
]
# Utility functions
def generate_path(min_length = 0):
def generate_path(min_length=0):
length = int(random.random() * random.random() * (4 - min_length)) + min_length
path = ()
for i in range(length):
@ -351,9 +359,10 @@ def generate_path(min_length = 0):
path = path + (u'',)
else:
path = path + (random.choice([u'1', u'2', u'3']),)
return path
def generate_prefix(allow_empty=True, is_partition=False):
if allow_empty and random.random() < 0.8:
return None
@ -364,7 +373,7 @@ def generate_prefix(allow_empty=True, is_partition=False):
if not is_partition:
first = chr(random.randint(ord('\x1d'), 255) % 255)
return first + ''.join(chr(random.randrange(0, 256)) for i in range(0, length-1))
return first + ''.join(chr(random.randrange(0, 256)) for i in range(0, length - 1))
else:
return ''.join(chr(random.randrange(ord('\x02'), ord('\x14'))) for i in range(0, length))
else:

View File

@ -4,13 +4,13 @@
# 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.
@ -30,6 +30,7 @@ from bindingtester.tests import test_util, directory_util
fdb.api_version(FDB_API_VERSION)
class DirectoryHcaTest(Test):
def __init__(self, subspace):
super(DirectoryHcaTest, self).__init__(subspace)
@ -39,7 +40,7 @@ class DirectoryHcaTest(Test):
def setup(self, args):
self.random = test_util.RandomGenerator(args.max_int_bits, args.api_version, args.types)
self.transactions = ['tr%d' % i for i in range(3)] # SOMEDAY: parameterize this number?
self.transactions = ['tr%d' % i for i in range(3)] # SOMEDAY: parameterize this number?
self.barrier_num = 0
self.max_directories_per_transaction = 30
@ -58,7 +59,7 @@ class DirectoryHcaTest(Test):
def barrier(self, instructions, thread_number, thread_ending=False):
if not thread_ending:
instructions.push_args(self.coordination[(self.barrier_num+1)][thread_number].key(), '')
instructions.push_args(self.coordination[(self.barrier_num + 1)][thread_number].key(), '')
instructions.append('SET_DATABASE')
instructions.append('WAIT_FUTURE')
@ -101,8 +102,9 @@ class DirectoryHcaTest(Test):
for i in range(num_directories):
path = (self.random.random_unicode_str(16),)
op_args = test_util.with_length(path) + ('', None)
directory_util.push_instruction_and_record_prefix(instructions, 'DIRECTORY_CREATE', op_args, path, num_dirs, self.random, self.prefix_log)
op_args = test_util.with_length(path) + ('', None)
directory_util.push_instruction_and_record_prefix(instructions, 'DIRECTORY_CREATE',
op_args, path, num_dirs, self.random, self.prefix_log)
num_dirs += 1
current_op += num_directories
@ -127,4 +129,3 @@ class DirectoryHcaTest(Test):
errors += directory_util.validate_hca_state(db)
return errors

View File

@ -4,13 +4,13 @@
# 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.
@ -34,8 +34,9 @@ DEFAULT_DIRECTORY_INDEX = 4
DEFAULT_DIRECTORY_PREFIX = 'default'
DIRECTORY_ERROR_STRING = 'DIRECTORY_ERROR'
class DirListEntry:
dir_id = 0 # Used for debugging
dir_id = 0 # Used for debugging
def __init__(self, is_directory, is_subspace, has_known_prefix=True, path=(), root=None):
self.root = root or self
@ -53,45 +54,46 @@ class DirListEntry:
def add_child(self, subpath, default_path, root, child):
if default_path in root.children:
#print 'Adding child %r to default directory %r at %r' % (child, root.children[DirectoryTest.DEFAULT_DIRECTORY_PATH].path, subpath)
# print 'Adding child %r to default directory %r at %r' % (child, root.children[DirectoryTest.DEFAULT_DIRECTORY_PATH].path, subpath)
c = root.children[default_path]._add_child_impl(subpath, child)
child.has_known_prefix = c.has_known_prefix and child.has_known_prefix
#print 'Added %r' % c
# print 'Added %r' % c
#print 'Adding child %r to directory %r at %r' % (child, self.path, subpath)
# print 'Adding child %r to directory %r at %r' % (child, self.path, subpath)
c = self._add_child_impl(subpath, child)
#print 'Added %r' % c
# print 'Added %r' % c
return c
def _add_child_impl(self, subpath, child):
#print '%d, %d. Adding child (recursive): %s %s' % (self.dir_id, child.dir_id, repr(self.path), repr(subpath))
# print '%d, %d. Adding child (recursive): %s %s' % (self.dir_id, child.dir_id, repr(self.path), repr(subpath))
if len(subpath) == 0:
self.has_known_prefix = self.has_known_prefix and child.has_known_prefix
#print '%d, %d. Setting child: %d' % (self.dir_id, child.dir_id, self.has_known_prefix)
# print '%d, %d. Setting child: %d' % (self.dir_id, child.dir_id, self.has_known_prefix)
self._merge_children(child)
return self
else:
if not subpath[0] in self.children:
#print '%d, %d. Path %s was absent (%s)' % (self.dir_id, child.dir_id, repr(self.path + subpath[0:1]), repr(self.children))
subdir = DirListEntry(True, True, path = self.path+subpath[0:1], root = self.root)
# print '%d, %d. Path %s was absent (%s)' % (self.dir_id, child.dir_id, repr(self.path + subpath[0:1]), repr(self.children))
subdir = DirListEntry(True, True, path=self.path + subpath[0:1], root=self.root)
subdir.has_known_prefix = len(subpath) == 1
self.children[subpath[0]] = subdir
else:
subdir = self.children[subpath[0]]
subdir.has_known_prefix = False
#print '%d, %d. Path was present' % (self.dir_id, child.dir_id)
# print '%d, %d. Path was present' % (self.dir_id, child.dir_id)
return subdir._add_child_impl(subpath[1:], child)
def _merge_children(self, other):
for c in other.children:
if not c in self.children:
if c not in self.children:
self.children[c] = other.children[c]
else:
self.children[c].has_known_prefix = self.children[c].has_known_prefix and other.children[c].has_known_prefix
self.children[c]._merge_children(other.children[c])
def setup_directories(instructions, default_path, random):
dir_list = [DirListEntry(True, False, True)]
instructions.push_args(0, '\xfe')
@ -114,6 +116,7 @@ def setup_directories(instructions, default_path, random):
return dir_list
def create_default_directory_subspace(instructions, path, random):
test_util.blocking_commit(instructions)
instructions.push_args(3)
@ -125,6 +128,7 @@ def create_default_directory_subspace(instructions, path, random):
instructions.push_args(DEFAULT_DIRECTORY_INDEX)
instructions.append('DIRECTORY_CHANGE')
def push_instruction_and_record_prefix(instructions, op, op_args, path, dir_index, random, subspace):
if not op.endswith('_DATABASE'):
instructions.push_args(1, *test_util.with_length(path))
@ -141,17 +145,18 @@ def push_instruction_and_record_prefix(instructions, op, op_args, path, dir_inde
instructions.push_args(1, '', random.random_string(16), '')
instructions.append('DIRECTORY_PACK_KEY')
test_util.to_front(instructions, 3) # move the existence result up to the front of the stack
test_util.to_front(instructions, 3) # move the existence result up to the front of the stack
t = util.subspace_to_tuple(subspace)
instructions.push_args(len(t) + 3, *t)
instructions.append('TUPLE_PACK') # subspace[<exists>][<packed_key>][random.random_string(16)] = ''
instructions.append('TUPLE_PACK') # subspace[<exists>][<packed_key>][random.random_string(16)] = ''
instructions.append('SET')
instructions.push_args(DEFAULT_DIRECTORY_INDEX)
instructions.append('DIRECTORY_CHANGE')
def check_for_duplicate_prefixes(db, subspace):
last_prefix = None
start_key = subspace[0].range().start
@ -164,18 +169,19 @@ def check_for_duplicate_prefixes(db, subspace):
break
start_key = fdb.KeySelector.first_greater_than(prefixes[-1].key)
prefixes = [subspace[0].unpack(kv.key)[0] for kv in prefixes]
prefixes = [p for p in prefixes if not (p.startswith(DEFAULT_DIRECTORY_PREFIX) or p == DIRECTORY_ERROR_STRING)]
count += len(prefixes)
prefixes = [last_prefix] + prefixes
duplicates.update([p for i,p in enumerate(prefixes[1:]) if p == prefixes[i]])
duplicates.update([p for i, p in enumerate(prefixes[1:]) if p == prefixes[i]])
last_prefix = prefixes[-1]
util.get_logger().info('Checked %d directory prefixes for duplicates' % count)
return ['The prefix %r was allocated multiple times' % d[:-2] for d in set(duplicates)]
def validate_hca_state(db):
hca = fdb.Subspace(('\xfe', 'hca'), '\xfe')
counters = hca[0]
@ -184,7 +190,7 @@ def validate_hca_state(db):
last_counter = db.get_range(counters.range().start, counters.range().stop, limit=1, reverse=True)
[(start, reported_count)] = [(counters.unpack(kv.key)[0], struct.unpack('<q', kv.value)[0]) for kv in last_counter] or [(0, 0)]
actual_count = len(db[recent[start] : recent.range().stop])
actual_count = len(db[recent[start]: recent.range().stop])
if actual_count > reported_count:
return ['The HCA reports %d prefixes allocated in current window, but it actually allocated %d' % (reported_count, actual_count)]

View File

@ -4,13 +4,13 @@
# 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.
@ -31,22 +31,24 @@ from bindingtester.tests import test_util
fdb.api_version(FDB_API_VERSION)
# SOMEDAY: This should probably be broken up into smaller tests
class ScriptedTest(Test):
TEST_API_VERSION = 510
TEST_API_VERSION = 520
def __init__(self, subspace):
super(ScriptedTest, self).__init__(subspace, ScriptedTest.TEST_API_VERSION, ScriptedTest.TEST_API_VERSION)
self.workspace = self.subspace['workspace']
self.results_subspace = self.subspace['results']
#self.thread_subspace = self.subspace['threads'] # TODO: update START_THREAD so that we can create threads in subspaces
# self.thread_subspace = self.subspace['threads'] # TODO: update START_THREAD so that we can create threads in subspaces
def setup(self, args):
if args.concurrency > 1:
raise Exception('Scripted tests cannot be run with a concurrency greater than 1')
# SOMEDAY: this is only a limitation because we don't know how many operations the bisection should start with
# it should be fixable.
#
#
# We also need to enable the commented out support for num_ops in this file and make it so the default value runs
# the entire test
if args.bisect:
@ -58,7 +60,7 @@ class ScriptedTest(Test):
test_instructions = ThreadedInstructionSet()
main_thread = test_instructions.create_thread()
foo = [self.workspace.pack(('foo%d' % i,)) for i in range(0,6)]
foo = [self.workspace.pack(('foo%d' % i,)) for i in range(0, 6)]
main_thread.append('NEW_TRANSACTION')
main_thread.push_args(1020)
@ -270,8 +272,8 @@ class ScriptedTest(Test):
stampKey = 'stampedXXXXXXXXXXsuffix'
stampKeyIndex = stampKey.find('XXXXXXXXXX')
stampKeyStr = chr(stampKeyIndex%256) + chr(stampKeyIndex/256)
main_thread.push_args(u'SET_VERSIONSTAMPED_KEY', stampKey + stampKeyStr, 'stampedBar')
stampKeyStr = chr(stampKeyIndex % 256) + chr(stampKeyIndex / 256)
main_thread.push_args(u'SET_VERSIONSTAMPED_KEY', stampKey + stampKeyStr, 'stampedBar')
main_thread.append('ATOMIC_OP')
main_thread.push_args(u'SET_VERSIONSTAMPED_VALUE', 'stampedValue', 'XXXXXXXXXX')
main_thread.append('ATOMIC_OP')
@ -305,7 +307,7 @@ class ScriptedTest(Test):
if not args.no_threads:
wait_key = 'waitKey'
#threads = [self.thread_subspace[i] for i in range(0, 2)]
# threads = [self.thread_subspace[i] for i in range(0, 2)]
threads = ['thread_spec%d' % i for i in range(0, 2)]
for thread_spec in threads:
main_thread.push_args(self.workspace.pack((wait_key, thread_spec)), '')
@ -314,11 +316,12 @@ class ScriptedTest(Test):
for thread_spec in threads:
main_thread.push_args(thread_spec)
#if len(main_thread) < args.num_ops:
# if len(main_thread) < args.num_ops:
main_thread.append('START_THREAD')
thread = test_instructions.create_thread(fdb.Subspace((thread_spec,)))
thread.append('NEW_TRANSACTION')
thread.push_args(foo[1], foo[1], 'bar%s' % thread_spec, self.workspace.pack((wait_key, thread_spec)), self.workspace.pack((wait_key, thread_spec)))
thread.push_args(foo[1], foo[1], 'bar%s' % thread_spec, self.workspace.pack(
(wait_key, thread_spec)), self.workspace.pack((wait_key, thread_spec)))
thread.append('GET')
thread.append('POP')
thread.append('SET')
@ -333,20 +336,20 @@ class ScriptedTest(Test):
thread.push_args(foo[1])
thread.append('GET')
self.add_result(thread, args, 'barthread_spec0', 'barthread_spec1')
main_thread.append('EMPTY_STACK')
#if len(main_thread) > args.num_ops:
#main_thread[args.num_ops:] = []
# if len(main_thread) > args.num_ops:
# main_thread[args.num_ops:] = []
return test_instructions
def get_result_specifications(self):
return [
ResultSpecification(self.results_subspace, ordering_index=0, global_error_filter=[1007, 1021])
return [
ResultSpecification(self.results_subspace, ordering_index=0, global_error_filter=[1007, 1021])
]
def get_expected_results(self):
return { self.results_subspace : self.results }
return {self.results_subspace: self.results}
def append_range_test(self, instructions, args, num_pairs, kv_length):
instructions.append('NEW_TRANSACTION')
@ -355,7 +358,7 @@ class ScriptedTest(Test):
instructions.append('CLEAR_RANGE_STARTS_WITH')
kvpairs = []
for i in range(0, num_pairs*2):
for i in range(0, num_pairs * 2):
kvpairs.append(self.workspace.pack(('foo', ''.join(chr(random.randint(0, 254)) for i in range(0, kv_length)))))
kvpairs = list(set(kvpairs))
@ -364,7 +367,7 @@ class ScriptedTest(Test):
kvpairs.sort()
instructions.push_args(*kvpairs)
for i in range(0, len(kvpairs)/2):
for i in range(0, len(kvpairs) / 2):
instructions.append('SET')
if i % 100 == 99:
test_util.blocking_commit(instructions)
@ -388,8 +391,7 @@ class ScriptedTest(Test):
instructions.push_args(key)
instructions.append('SET_DATABASE')
#if len(instructions) <= args.num_ops:
# if len(instructions) <= args.num_ops:
self.results.append(Result(self.results_subspace, key, values))
instructions.append('POP')

View File

@ -4,13 +4,13 @@
# 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.
@ -31,6 +31,7 @@ from bindingtester import util
from bindingtester import FDB_API_VERSION
from bindingtester.known_testers import COMMON_TYPES
class RandomGenerator(object):
def __init__(self, max_int_bits=64, api_version=FDB_API_VERSION, types=COMMON_TYPES):
self.max_int_bits = max_int_bits
@ -41,13 +42,13 @@ class RandomGenerator(object):
return u''.join(self.random_unicode_char() for i in range(0, length))
def random_int(self):
num_bits = random.randint(0, self.max_int_bits) # This way, we test small numbers with higher probability
num_bits = random.randint(0, self.max_int_bits) # This way, we test small numbers with higher probability
max_value = (1 << num_bits) - 1
min_value = -max_value - 1
num = random.randint(min_value, max_value)
#util.get_logger().debug('generating int (%d): %d - %s' % (num_bits, num, repr(fdb.tuple.pack((num,)))))
# util.get_logger().debug('generating int (%d): %d - %s' % (num_bits, num, repr(fdb.tuple.pack((num,)))))
return num
def random_float(self, exp_bits):
@ -57,7 +58,7 @@ class RandomGenerator(object):
else:
# Choose a value from all over the range of acceptable floats for this precision.
sign = -1 if random.random() < 0.5 else 1
exponent = random.randint(-(1 << (exp_bits-1))-10, (1 << (exp_bits-1) - 1))
exponent = random.randint(-(1 << (exp_bits - 1)) - 10, (1 << (exp_bits - 1) - 1))
mantissa = random.random()
return sign * math.pow(2, exponent) * mantissa
@ -117,12 +118,12 @@ class RandomGenerator(object):
smaller_size = random.randint(1, len(to_add))
tuples.append(to_add[:smaller_size])
else:
non_empty = filter(lambda (i,x): (isinstance(x, list) or isinstance(x, tuple)) and len(x) > 0, enumerate(to_add))
non_empty = filter(lambda (_, x): (isinstance(x, list) or isinstance(x, tuple)) and len(x) > 0, enumerate(to_add))
if len(non_empty) > 0 and random.random() < 0.25:
# Add a smaller list to test prefixes of nested structures.
idx, choice = random.choice(non_empty)
smaller_size = random.randint(0, len(to_add[idx]))
tuples.append(to_add[:idx] + (choice[:smaller_size],) + to_add[idx+1:])
tuples.append(to_add[:idx] + (choice[:smaller_size],) + to_add[idx + 1:])
random.shuffle(tuples)
return tuples
@ -133,7 +134,7 @@ class RandomGenerator(object):
elif random.random() < 0.75:
limit = 0
else:
limit = random.randint(1e8, (1<<31)-1)
limit = random.randint(1e8, (1 << 31) - 1)
return (limit, random.randint(0, 1), random.randint(-2, 4))
@ -149,13 +150,13 @@ class RandomGenerator(object):
if length == 0:
return ''
return chr(random.randint(0, 254)) + ''.join(chr(random.randint(0, 255)) for i in range(0, length-1))
return chr(random.randint(0, 254)) + ''.join(chr(random.randint(0, 255)) for i in range(0, length - 1))
def random_unicode_char(self):
while True:
if random.random() < 0.05:
# Choose one of these special character sequences.
specials = [u'\U0001f4a9', u'\U0001f63c', u'\U0001f3f3\ufe0f\u200d\U0001f308', u'\U0001f1f5\U0001f1f2', u'\uf8ff',
specials = [u'\U0001f4a9', u'\U0001f63c', u'\U0001f3f3\ufe0f\u200d\U0001f308', u'\U0001f1f5\U0001f1f2', u'\uf8ff',
u'\U0002a2b2', u'\u05e9\u05dc\u05d5\u05dd']
return random.choice(specials)
c = random.randint(0, 0xffff)
@ -166,11 +167,13 @@ class RandomGenerator(object):
def error_string(error_code):
return fdb.tuple.pack(('ERROR', str(error_code)))
def blocking_commit(instructions):
instructions.append('COMMIT')
instructions.append('WAIT_FUTURE')
instructions.append('RESET')
def to_front(instructions, index):
if index == 0:
pass
@ -178,19 +181,19 @@ def to_front(instructions, index):
instructions.push_args(1)
instructions.append('SWAP')
elif index == 2:
instructions.push_args(index-1)
instructions.push_args(index - 1)
instructions.append('SWAP')
instructions.push_args(index)
instructions.append('SWAP')
else:
instructions.push_args(index-1)
instructions.push_args(index - 1)
instructions.append('SWAP')
instructions.push_args(index)
instructions.append('SWAP')
instructions.push_args(index-1)
instructions.push_args(index - 1)
instructions.append('SWAP')
to_front(instructions, index-1)
to_front(instructions, index - 1)
def with_length(tup):
return (len(tup),) + tup

View File

@ -4,13 +4,13 @@
# 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.
@ -25,6 +25,7 @@ import glob
import fdb
def initialize_logger_level(logging_level):
logger = get_logger()
@ -39,9 +40,11 @@ def initialize_logger_level(logging_level):
elif logging_level == "ERROR":
logger.setLevel(logging.ERROR)
def get_logger():
return logging.getLogger('foundationdb.bindingtester')
# Attempts to get the name associated with a process termination signal
def signal_number_to_name(signal_num):
name = []
@ -53,6 +56,7 @@ def signal_number_to_name(signal_num):
else:
return str(signal_num)
def import_subclasses(filename, module_path):
for f in glob.glob(os.path.join(os.path.dirname(filename), '*.py')):
fn = os.path.basename(f)
@ -60,6 +64,7 @@ def import_subclasses(filename, module_path):
continue
__import__('%s.%s' % (module_path, os.path.splitext(fn)[0]))
# Attempts to unpack a subspace
# This throws an exception if the subspace cannot be unpacked as a tuple
# As a result, the binding tester cannot use subspaces that have non-tuple raw prefixes
@ -69,4 +74,3 @@ def subspace_to_tuple(subspace):
except Exception as e:
get_logger().debug(e)
raise Exception('The binding tester does not support subspaces with non-tuple raw prefixes')

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.
@ -18,7 +18,7 @@
* limitations under the License.
*/
#define FDB_API_VERSION 510
#define FDB_API_VERSION 520
#include "fdbclient/MultiVersionTransaction.h"
#include "foundationdb/fdb_c.h"

View File

@ -4,13 +4,13 @@
* 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.
@ -28,10 +28,10 @@
#endif
#if !defined(FDB_API_VERSION)
#error You must #define FDB_API_VERSION prior to including fdb_c.h (current version is 510)
#error You must #define FDB_API_VERSION prior to including fdb_c.h (current version is 520)
#elif FDB_API_VERSION < 13
#error API version no longer supported (upgrade to 13)
#elif FDB_API_VERSION > 510
#elif FDB_API_VERSION > 520
#error Requested API version requires a newer version of this header
#endif

View File

@ -5,13 +5,13 @@
# 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.
@ -27,19 +27,21 @@ import sys
functions = {}
func_re = re.compile("^\s*FDB_API_(?:CHANGED|REMOVED)\s*\(\s*([^,]*),\s*([^)]*)\).*")
func_re = re.compile(
"^\s*FDB_API_(?:CHANGED|REMOVED)\s*\(\s*([^,]*),\s*([^)]*)\).*")
with open(source, 'r') as srcfile:
for l in srcfile:
m = func_re.match(l)
if m:
func, ver = m.groups()
if not func in functions:
if func not in functions:
functions[func] = []
ver = int(ver)
if not ver in functions[func]:
if ver not in functions[func]:
functions[func].append(ver)
def write_windows_asm(asmfile, functions):
asmfile.write(".data\n")
for f in functions:
@ -55,6 +57,7 @@ def write_windows_asm(asmfile, functions):
asmfile.write("\nEND\n")
def write_unix_asm(asmfile, functions, prefix):
asmfile.write(".intel_syntax noprefix\n")
@ -70,13 +73,17 @@ def write_unix_asm(asmfile, functions, prefix):
for f in functions:
asmfile.write("\n.globl %s%s\n" % (prefix, f))
asmfile.write("%s%s:\n" % (prefix, f))
asmfile.write("\tmov r11, qword ptr [%sfdb_api_ptr_%s@GOTPCREL+rip]\n" % (prefix, f))
asmfile.write(
"\tmov r11, qword ptr [%sfdb_api_ptr_%s@GOTPCREL+rip]\n" % (prefix, f))
asmfile.write("\tmov r11, qword ptr [r11]\n")
asmfile.write("\tjmp r11\n")
with open(asm, 'w') as asmfile, open(h, 'w') as hfile:
hfile.write("void fdb_api_ptr_unimpl() { fprintf(stderr, \"UNIMPLEMENTED FDB API FUNCTION\\n\"); abort(); }\n\n")
hfile.write("void fdb_api_ptr_removed() { fprintf(stderr, \"REMOVED FDB API FUNCTION\\n\"); abort(); }\n\n")
hfile.write(
"void fdb_api_ptr_unimpl() { fprintf(stderr, \"UNIMPLEMENTED FDB API FUNCTION\\n\"); abort(); }\n\n")
hfile.write(
"void fdb_api_ptr_removed() { fprintf(stderr, \"REMOVED FDB API FUNCTION\\n\"); abort(); }\n\n")
if platform == "linux":
write_unix_asm(asmfile, functions, '')
@ -90,4 +97,4 @@ with open(asm, 'w') as asmfile, open(h, 'w') as hfile:
hfile.write("extern \"C\" ")
hfile.write("void* fdb_api_ptr_%s = (void*)&fdb_api_ptr_unimpl;\n" % f)
for v in functions[f]:
hfile.write("#define %s_v%d_PREV %s_v%d\n" % (f, v, f, v-1))
hfile.write("#define %s_v%d_PREV %s_v%d\n" % (f, v, f, v - 1))

View File

@ -4,13 +4,13 @@
# 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.
@ -26,6 +26,8 @@ fdb_c_LIBS := lib/libfdbclient.a lib/libfdbrpc.a lib/libflow.a
fdb_c_tests_LIBS := -Llib -lfdb_c
fdb_c_tests_HEADERS := -Ibindings/c
CLEAN_TARGETS += fdb_c_tests_clean
ifeq ($(PLATFORM),linux)
fdb_c_LIBS += lib/libstdc++.a -lm -lpthread -lrt -ldl
fdb_c_LDFLAGS += -Wl,--version-script=bindings/c/fdb_c.map -static-libgcc -Wl,-z,nodelete
@ -98,4 +100,7 @@ packages/fdb-c-tests-$(VERSION)-$(PLATFORM).tar.gz: bin/fdb_c_performance_test b
fdb_c_tests: packages/fdb-c-tests-$(VERSION)-$(PLATFORM).tar.gz
fdb_c_tests_clean:
@rm -f packages/fdb-c-tests-$(VERSION)-$(PLATFORM).tar.gz
packages: fdb_c_tests

View File

@ -4,13 +4,13 @@
* 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.
@ -602,7 +602,7 @@ void runTests(struct ResultSet *rs) {
int main(int argc, char **argv) {
srand(time(NULL));
struct ResultSet *rs = newResultSet();
checkError(fdb_select_api_version(510), "select API version", rs);
checkError(fdb_select_api_version(520), "select API version", rs);
printf("Running performance test at client version: %s\n", fdb_get_client_version());
valueStr = (uint8_t*)malloc((sizeof(uint8_t))*valueSize);

View File

@ -4,13 +4,13 @@
* 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.
@ -243,7 +243,7 @@ void runTests(struct ResultSet *rs) {
int main(int argc, char **argv) {
srand(time(NULL));
struct ResultSet *rs = newResultSet();
checkError(fdb_select_api_version(510), "select API version", rs);
checkError(fdb_select_api_version(520), "select API version", rs);
printf("Running RYW Benchmark test at client version: %s\n", fdb_get_client_version());
keys = generateKeys(numKeys, keySize);

View File

@ -4,13 +4,13 @@
* 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.
@ -27,7 +27,7 @@
#include <pthread.h>
#ifndef FDB_API_VERSION
#define FDB_API_VERSION 510
#define FDB_API_VERSION 520
#endif
#include <foundationdb/fdb_c.h>

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.
@ -140,8 +140,13 @@ namespace FDB {
API::API(int version) : version(version) {}
API* API::selectAPIVersion(int apiVersion) {
if(API::instance && apiVersion != API::instance->version) {
throw api_version_already_set();
if(API::instance) {
if(apiVersion != API::instance->version) {
throw api_version_already_set();
}
else {
return API::instance;
}
}
if(apiVersion < 500 || apiVersion > FDB_API_VERSION) {
@ -150,13 +155,23 @@ namespace FDB {
throw_on_error( fdb_select_api_version_impl(apiVersion, FDB_API_VERSION) );
if(!API::instance) {
API::instance = new API(apiVersion);
}
API::instance = new API(apiVersion);
return API::instance;
}
bool API::isAPIVersionSelected() {
return API::instance != NULL;
}
API* API::getInstance() {
if(API::instance == NULL) {
throw api_version_unset();
}
else {
return API::instance;
}
}
void API::setupNetwork() {
throw_on_error( fdb_setup_network() );
}
@ -183,6 +198,10 @@ namespace FDB {
return Reference<Cluster>( new Cluster(c) );
}
int API::getAPIVersion() const {
return version;
}
Reference<DatabaseContext> Cluster::createDatabase() {
const char *dbName = "DB";
CFuture f( fdb_cluster_create_database( c, (uint8_t*)dbName, (int)strlen(dbName) ) );

View File

@ -4,13 +4,13 @@
* 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.
@ -23,7 +23,7 @@
#include <flow/flow.h>
#define FDB_API_VERSION 510
#define FDB_API_VERSION 520
#include <bindings/c/foundationdb/fdb_c.h>
#undef DLLEXPORT
@ -64,6 +64,8 @@ namespace FDB {
class API {
public:
static API* selectAPIVersion(int apiVersion);
static API* getInstance();
static bool isAPIVersionSelected();
void setNetworkOption(FDBNetworkOption option, Optional<StringRef> value = Optional<StringRef>());
@ -74,6 +76,7 @@ namespace FDB {
Reference<Cluster> createCluster( std::string const& connFilename );
bool evaluatePredicate(FDBErrorPredicate pred, Error const& e);
int getAPIVersion() const;
private:
static API* instance;

View File

@ -4,13 +4,13 @@
# 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.
@ -1510,6 +1510,25 @@ struct UnitTestsFunc : InstructionFunc {
ASSERT(data->api->evaluatePredicate(FDBErrorPredicate::FDB_ERROR_PREDICATE_RETRYABLE, Error(1020)));
ASSERT(!data->api->evaluatePredicate(FDBErrorPredicate::FDB_ERROR_PREDICATE_RETRYABLE, Error(10)));
ASSERT(API::isAPIVersionSelected());
state API *fdb = API::getInstance();
ASSERT(fdb->getAPIVersion() <= FDB_API_VERSION);
try {
API::selectAPIVersion(fdb->getAPIVersion() + 1);
ASSERT(false);
}
catch(Error &e) {
ASSERT(e.code() == error_code_api_version_already_set);
}
try {
API::selectAPIVersion(fdb->getAPIVersion() - 1);
ASSERT(false);
}
catch(Error &e) {
ASSERT(e.code() == error_code_api_version_already_set);
}
API::selectAPIVersion(fdb->getAPIVersion());
state Reference<Transaction> tr(new Transaction(data->db));
tr->setOption(FDBTransactionOption::FDB_TR_OPTION_PRIORITY_SYSTEM_IMMEDIATE);
tr->setOption(FDBTransactionOption::FDB_TR_OPTION_PRIORITY_SYSTEM_IMMEDIATE);
@ -1574,7 +1593,7 @@ ACTOR static Future<Void> doInstructions(Reference<FlowTesterData> data) {
try {
if(LOG_INSTRUCTIONS) {
if(op != LiteralStringRef("SWAP") && op != LiteralStringRef("PUSH")) {
printf("%lu. %s\n", idx, tupleToString(opTuple).c_str());
printf("%zu. %s\n", idx, tupleToString(opTuple).c_str());
fflush(stdout);
}
}
@ -1654,6 +1673,7 @@ void populateAtomicOpMap() {
optionInfo["BIT_OR"] = FDBMutationType::FDB_MUTATION_TYPE_BIT_OR;
optionInfo["XOR"] = FDBMutationType::FDB_MUTATION_TYPE_XOR;
optionInfo["BIT_XOR"] = FDBMutationType::FDB_MUTATION_TYPE_BIT_XOR;
optionInfo["APPEND_IF_FITS"] = FDBMutationType::FDB_MUTATION_TYPE_APPEND_IF_FITS;
optionInfo["MAX"] = FDBMutationType::FDB_MUTATION_TYPE_MAX;
optionInfo["MIN"] = FDBMutationType::FDB_MUTATION_TYPE_MIN;
optionInfo["SET_VERSIONSTAMPED_KEY"] = FDBMutationType::FDB_MUTATION_TYPE_SET_VERSIONSTAMPED_KEY;
@ -1681,7 +1701,18 @@ ACTOR void startTest(std::string clusterFilename, StringRef prefix, int apiVersi
// This is "our" network
g_network = newNet2(NetworkAddress(), false);
ASSERT(!API::isAPIVersionSelected());
try {
API::getInstance();
ASSERT(false);
}
catch(Error& e) {
ASSERT(e.code() == error_code_api_version_unset);
}
API *fdb = API::selectAPIVersion(apiVersion);
ASSERT(API::isAPIVersionSelected());
ASSERT(fdb->getAPIVersion() == apiVersion);
//fdb->setNetworkOption(FDBNetworkOption::FDB_NET_OPTION_TRACE_ENABLE);
// We have to start the fdb_flow network and thread separately!

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
# 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.

View File

@ -1,14 +1,14 @@
fdb-go
======
[Go language](http://golang.org) bindings for [FoundationDB](http://foundationdb.org/documentation/), a distributed key-value store with ACID transactions.
[Go language](http://golang.org) bindings for [FoundationDB](https://www.foundationdb.org/documentation/), a distributed key-value store with ACID transactions.
This package requires:
- Go 1.1+ with CGO enabled
- FoundationDB C API 2.0.x, 3.0.x, or 4.x.y (part of the [FoundationDB clients package](https://files.foundationdb.org/fdb-c/))
- FoundationDB C API 2.0.x, 3.0.x, or 4.x.y (part of the [FoundationDB clients package](https://www.foundationdb.org/downloads/fdb-c/))
Use of this package requires the selection of a FoundationDB API version at runtime. This package currently supports FoundationDB API versions 200-510.
Use of this package requires the selection of a FoundationDB API version at runtime. This package currently supports FoundationDB API versions 200-520.
To build this package, in the top level of this repository run:
@ -27,5 +27,5 @@ of downloading from the remote repository.
Documentation
-------------
* [API documentation](https://foundationdb.org/documentation/godoc/fdb.html)
* [Tutorial](https://foundationdb.org/documentation/class-scheduling-go.html)
* [API documentation](https://www.foundationdb.org/documentation/godoc/fdb.html)
* [Tutorial](https://www.foundationdb.org/documentation/class-scheduling-go.html)

View File

@ -4,13 +4,13 @@
# 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.
@ -25,7 +25,7 @@ GOPATH := $(CURDIR)/bindings/go/build
GO_IMPORT_PATH := github.com/apple/foundationdb/bindings/go/src
GO_DEST := $(GOPATH)/src/$(GO_IMPORT_PATH)
.PHONY: fdb_go fdb_go_path fdb_go_tester fdb_go_tester_clean godoc godoc_clean
.PHONY: fdb_go fdb_go_path fdb_go_fmt fdb_go_fmt_check fdb_go_tester fdb_go_tester_clean godoc godoc_clean
# We only override if the environment didn't set it (this is used by
# the fdbwebsite documentation build process)
@ -49,12 +49,23 @@ GO_PACKAGE_OBJECTS := $(addprefix $(GO_PACKAGE_OUTDIR)/,$(GO_PACKAGES:=.a))
GO_SRC := $(shell find $(CURDIR)/bindings/go/src -name '*.go')
fdb_go: $(GO_PACKAGE_OBJECTS) $(GO_SRC)
fdb_go: $(GO_PACKAGE_OBJECTS) $(GO_SRC) fdb_go_fmt_check
fdb_go_path: $(GO_SRC)
fdb_go_fmt: $(GO_SRC)
@echo "Formatting fdb_go"
@gofmt -w $(GO_SRC)
fdb_go_fmt_check: $(GO_SRC)
@echo "Checking fdb_go"
@bash -c 'fmtoutstr=$$(gofmt -l $(GO_SRC)) ; if [[ -n "$${fmtoutstr}" ]] ; then echo "Detected go formatting violations for the following files:" ; echo "$${fmtoutstr}" ; echo "Try running: make fdb_go_fmt"; exit 1 ; fi'
$(GO_DEST)/.stamp: $(GO_SRC)
@echo "Creating fdb_go_path"
@mkdir -p $(GO_DEST)
@cp -r bindings/go/src/* $(GO_DEST)
@touch $(GO_DEST)/.stamp
fdb_go_path: $(GO_DEST)/.stamp
fdb_go_clean:
@echo "Cleaning fdb_go"
@ -66,31 +77,31 @@ fdb_go_tester_clean:
@echo "Cleaning fdb_go_tester"
@rm -rf $(GOPATH)/bin
$(GOPATH)/bin/_stacktester: fdb_go_path $(GO_SRC) $(GO_PACKAGE_OBJECTS) $(GO_DEST)/fdb/generated.go
$(GOPATH)/bin/_stacktester: $(GO_DEST)/.stamp $(GO_SRC) $(GO_PACKAGE_OBJECTS) $(GO_DEST)/fdb/generated.go
@echo "Compiling $(basename $(notdir $@))"
@go install $(GO_IMPORT_PATH)/_stacktester
$(GO_PACKAGE_OUTDIR)/fdb/tuple.a: fdb_go_path $(GO_SRC) $(GO_PACKAGE_OUTDIR)/fdb.a $(GO_DEST)/fdb/generated.go
$(GO_PACKAGE_OUTDIR)/fdb/tuple.a: $(GO_DEST)/.stamp $(GO_SRC) $(GO_PACKAGE_OUTDIR)/fdb.a $(GO_DEST)/fdb/generated.go
@echo "Compiling fdb/tuple"
@go install $(GO_IMPORT_PATH)/fdb/tuple
$(GO_PACKAGE_OUTDIR)/fdb/subspace.a: fdb_go_path $(GO_SRC) $(GO_PACKAGE_OUTDIR)/fdb.a $(GO_PACKAGE_OUTDIR)/fdb/tuple.a $(GO_DEST)/fdb/generated.go
$(GO_PACKAGE_OUTDIR)/fdb/subspace.a: $(GO_DEST)/.stamp $(GO_SRC) $(GO_PACKAGE_OUTDIR)/fdb.a $(GO_PACKAGE_OUTDIR)/fdb/tuple.a $(GO_DEST)/fdb/generated.go
@echo "Compiling fdb/subspace"
@go install $(GO_IMPORT_PATH)/fdb/subspace
$(GO_PACKAGE_OUTDIR)/fdb/directory.a: fdb_go_path $(GO_SRC) $(GO_PACKAGE_OUTDIR)/fdb.a $(GO_PACKAGE_OUTDIR)/fdb/tuple.a $(GO_PACKAGE_OUTDIR)/fdb/subspace.a $(GO_DEST)/fdb/generated.go
$(GO_PACKAGE_OUTDIR)/fdb/directory.a: $(GO_DEST)/.stamp $(GO_SRC) $(GO_PACKAGE_OUTDIR)/fdb.a $(GO_PACKAGE_OUTDIR)/fdb/tuple.a $(GO_PACKAGE_OUTDIR)/fdb/subspace.a $(GO_DEST)/fdb/generated.go
@echo "Compiling fdb/directory"
@go install $(GO_IMPORT_PATH)/fdb/directory
$(GO_PACKAGE_OUTDIR)/fdb.a: fdb_go_path $(GO_SRC) $(GO_DEST)/fdb/generated.go
$(GO_PACKAGE_OUTDIR)/fdb.a: $(GO_DEST)/.stamp lib/libfdb_c.$(DLEXT) $(GO_SRC) $(GO_DEST)/fdb/generated.go
@echo "Compiling fdb"
@go install $(GO_IMPORT_PATH)/fdb
$(GO_DEST)/fdb/generated.go: fdb_go_path lib/libfdb_c.$(DLEXT) bindings/go/src/_util/translate_fdb_options.go fdbclient/vexillographer/fdb.options
$(GO_DEST)/fdb/generated.go: $(GO_DEST)/.stamp bindings/go/src/_util/translate_fdb_options.go fdbclient/vexillographer/fdb.options
@echo "Building $@"
@go run bindings/go/src/_util/translate_fdb_options.go < fdbclient/vexillographer/fdb.options > $@
godoc: fdb_go_path $(GO_SRC)
godoc: fdb_go_path $(GO_SRC) $(GO_DEST)/fdb/generated.go
@echo "Generating Go Documentation"
@rm -rf $(GODOC_DIR)/godoc
@mkdir -p $(GODOC_DIR)/godoc
@ -105,6 +116,12 @@ godoc: fdb_go_path $(GO_SRC)
@(sed -i -e 's_a href="tuple/"_a href="fdb.tuple.html"_' $(GODOC_DIR)/godoc/fdb.html)
@(sed -i -e 's_a href="subspace/"_a href="fdb.subspace.html"_' $(GODOC_DIR)/godoc/fdb.html)
@(sed -i -e 's_a href="directory/"_a href="fdb.directory.html"_' $(GODOC_DIR)/godoc/fdb.html)
@(sed -i -e 's_a href="/pkg/builtin_a href="https://godoc.org/pkg/builtin_g;s_a href="/src/github.com/apple/foundationdb_a href="https://github.com/apple/foundationdb/tree/master_g;s_a href="/pkg/github.com/apple/foundationdb/bindings/go/src/fdb/_a href="./fdb.html_g' $(GODOC_DIR)/godoc/fdb.html)
@(sed -i -e 's_a href="/pkg/builtin_a href="https://godoc.org/pkg/builtin_g;s_a href="/src/github.com/apple/foundationdb_a href="https://github.com/apple/foundationdb/tree/master_g;s_a href="/pkg/github.com/apple/foundationdb/bindings/go/src/fdb/_a href="./fdb.html_g' $(GODOC_DIR)/godoc/fdb.directory.html)
@(sed -i -e 's_a href="/pkg/builtin_a href="https://godoc.org/pkg/builtin_g;s_a href="/src/github.com/apple/foundationdb_a href="https://github.com/apple/foundationdb/tree/master_g;s_a href="/pkg/github.com/apple/foundationdb/bindings/go/src/fdb/_a href="./fdb.html_g' $(GODOC_DIR)/godoc/fdb.subspace.html)
@(sed -i -e 's_a href="/pkg/builtin_a href="https://godoc.org/pkg/builtin_g;s_a href="/src/github.com/apple/foundationdb_a href="https://github.com/apple/foundationdb/tree/master_g;s_a href="/pkg/github.com/apple/foundationdb/bindings/go/src/fdb/_a href="./fdb.html_g' $(GODOC_DIR)/godoc/fdb.tuple.html)
godoc_clean:
@echo "Cleaning Go Documentation"

View File

@ -4,13 +4,13 @@
* 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.
@ -21,12 +21,12 @@
package main
import (
"github.com/apple/foundationdb/bindings/go/src/fdb"
"github.com/apple/foundationdb/bindings/go/src/fdb/tuple"
"github.com/apple/foundationdb/bindings/go/src/fdb/subspace"
"github.com/apple/foundationdb/bindings/go/src/fdb/directory"
"strings"
"bytes"
"github.com/apple/foundationdb/bindings/go/src/fdb"
"github.com/apple/foundationdb/bindings/go/src/fdb/directory"
"github.com/apple/foundationdb/bindings/go/src/fdb/subspace"
"github.com/apple/foundationdb/bindings/go/src/fdb/tuple"
"strings"
)
func (sm *StackMachine) popTuples(count int) []tuple.Tuple {
@ -60,8 +60,8 @@ func tuplePackStrings(s []string) []byte {
}
type DirectoryExtension struct {
list []interface{}
index int64
list []interface{}
index int64
errorIndex int64
}
@ -93,15 +93,15 @@ func (sm *StackMachine) maybePath() []string {
return path
}
var createOps = map[string]bool {
var createOps = map[string]bool{
"CREATE_SUBSPACE": true,
"CREATE_LAYER": true,
"CREATE_OR_OPEN": true,
"CREATE": true,
"OPEN": true,
"MOVE": true,
"MOVE_TO": true,
"OPEN_SUBSPACE": true,
"CREATE_LAYER": true,
"CREATE_OR_OPEN": true,
"CREATE": true,
"OPEN": true,
"MOVE": true,
"MOVE_TO": true,
"OPEN_SUBSPACE": true,
}
func (de *DirectoryExtension) processOp(sm *StackMachine, op string, isDB bool, idx int, t fdb.Transactor, rt fdb.ReadTransactor) {
@ -142,7 +142,9 @@ func (de *DirectoryExtension) processOp(sm *StackMachine, op string, isDB bool,
layer = l.([]byte)
}
d, e := de.cwd().CreateOrOpen(t, tupleToPath(tuples[0]), layer)
if e != nil { panic(e) }
if e != nil {
panic(e)
}
de.store(d)
case op == "CREATE":
tuples := sm.popTuples(1)
@ -159,7 +161,9 @@ func (de *DirectoryExtension) processOp(sm *StackMachine, op string, isDB bool,
// p.([]byte) itself may be nil, but CreatePrefix handles that appropriately
d, e = de.cwd().CreatePrefix(t, tupleToPath(tuples[0]), layer, p.([]byte))
}
if e != nil { panic(e) }
if e != nil {
panic(e)
}
de.store(d)
case op == "OPEN":
tuples := sm.popTuples(1)
@ -169,7 +173,9 @@ func (de *DirectoryExtension) processOp(sm *StackMachine, op string, isDB bool,
layer = l.([]byte)
}
d, e := de.cwd().Open(rt, tupleToPath(tuples[0]), layer)
if e != nil { panic(e) }
if e != nil {
panic(e)
}
de.store(d)
case op == "CHANGE":
i := sm.waitAndPop().item.(int64)
@ -182,12 +188,16 @@ func (de *DirectoryExtension) processOp(sm *StackMachine, op string, isDB bool,
case op == "MOVE":
tuples := sm.popTuples(2)
d, e := de.cwd().Move(t, tupleToPath(tuples[0]), tupleToPath(tuples[1]))
if e != nil { panic(e) }
if e != nil {
panic(e)
}
de.store(d)
case op == "MOVE_TO":
tuples := sm.popTuples(1)
d, e := de.cwd().MoveTo(t, tupleToPath(tuples[0]))
if e != nil { panic(e) }
if e != nil {
panic(e)
}
de.store(d)
case strings.HasPrefix(op, "REMOVE"):
path := sm.maybePath()
@ -197,9 +207,11 @@ func (de *DirectoryExtension) processOp(sm *StackMachine, op string, isDB bool,
// doesn't end up committing the version key. (Other languages have
// separate remove() and remove_if_exists() so don't have this tricky
// issue).
_, e := t.Transact(func (tr fdb.Transaction) (interface{}, error) {
_, e := t.Transact(func(tr fdb.Transaction) (interface{}, error) {
ok, e := de.cwd().Remove(tr, path)
if e != nil { panic(e) }
if e != nil {
panic(e)
}
switch op[6:] {
case "":
if !ok {
@ -209,16 +221,24 @@ func (de *DirectoryExtension) processOp(sm *StackMachine, op string, isDB bool,
}
return nil, nil
})
if e != nil { panic(e) }
if e != nil {
panic(e)
}
case op == "LIST":
subs, e := de.cwd().List(rt, sm.maybePath())
if e != nil { panic(e) }
if e != nil {
panic(e)
}
t := make(tuple.Tuple, len(subs))
for i, s := range subs { t[i] = s }
for i, s := range subs {
t[i] = s
}
sm.store(idx, t.Pack())
case op == "EXISTS":
b, e := de.cwd().Exists(rt, sm.maybePath())
if e != nil { panic(e) }
if e != nil {
panic(e)
}
if b {
sm.store(idx, int64(1))
} else {
@ -229,8 +249,10 @@ func (de *DirectoryExtension) processOp(sm *StackMachine, op string, isDB bool,
sm.store(idx, de.css().Pack(tuples[0]))
case op == "UNPACK_KEY":
t, e := de.css().Unpack(fdb.Key(sm.waitAndPop().item.([]byte)))
if e != nil { panic(e) }
for _, el := range(t) {
if e != nil {
panic(e)
}
for _, el := range t {
sm.store(idx, el)
}
case op == "RANGE":
@ -252,7 +274,7 @@ func (de *DirectoryExtension) processOp(sm *StackMachine, op string, isDB bool,
k := sm.waitAndPop().item.([]byte)
k = append(k, tuple.Tuple{de.index}.Pack()...)
v := de.css().Bytes()
t.Transact(func (tr fdb.Transaction) (interface{}, error) {
t.Transact(func(tr fdb.Transaction) (interface{}, error) {
tr.Set(fdb.Key(k), v)
return nil, nil
})
@ -266,7 +288,9 @@ func (de *DirectoryExtension) processOp(sm *StackMachine, op string, isDB bool,
k3 := ss.Pack(tuple.Tuple{"exists"})
var v3 []byte
exists, e := de.cwd().Exists(rt, nil)
if e != nil { panic(e) }
if e != nil {
panic(e)
}
if exists {
v3 = tuple.Tuple{1}.Pack()
} else {
@ -276,10 +300,12 @@ func (de *DirectoryExtension) processOp(sm *StackMachine, op string, isDB bool,
var subs []string
if exists {
subs, e = de.cwd().List(rt, nil)
if e != nil { panic(e) }
if e != nil {
panic(e)
}
}
v4 := tuplePackStrings(subs)
t.Transact(func (tr fdb.Transaction) (interface{}, error) {
t.Transact(func(tr fdb.Transaction) (interface{}, error) {
tr.Set(k1, v1)
tr.Set(k2, v2)
tr.Set(k3, v3)

View File

@ -4,13 +4,13 @@
* 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.
@ -24,23 +24,23 @@ import (
"bytes"
"encoding/binary"
"encoding/hex"
"fmt"
"github.com/apple/foundationdb/bindings/go/src/fdb"
"github.com/apple/foundationdb/bindings/go/src/fdb/tuple"
"log"
"fmt"
"os"
"reflect"
"runtime"
"sort"
"strconv"
"strings"
"sync"
"runtime"
"reflect"
"time"
"strconv"
)
const verbose bool = false
var trMap = map[string]fdb.Transaction {}
var trMap = map[string]fdb.Transaction{}
var trMapLock = sync.RWMutex{}
// Make tuples sortable by byte-order
@ -69,17 +69,17 @@ func int64ToBool(i int64) bool {
type stackEntry struct {
item interface{}
idx int
idx int
}
type StackMachine struct {
prefix []byte
trName string
stack []stackEntry
prefix []byte
trName string
stack []stackEntry
lastVersion int64
threads sync.WaitGroup
verbose bool
de *DirectoryExtension
threads sync.WaitGroup
verbose bool
de *DirectoryExtension
}
func newStackMachine(prefix []byte, verbose bool) *StackMachine {
@ -99,7 +99,7 @@ func (sm *StackMachine) waitAndPop() (ret stackEntry) {
}
}()
ret, sm.stack = sm.stack[len(sm.stack) - 1], sm.stack[:len(sm.stack) - 1]
ret, sm.stack = sm.stack[len(sm.stack)-1], sm.stack[:len(sm.stack)-1]
switch el := ret.item.(type) {
case []byte:
ret.item = el
@ -150,9 +150,9 @@ func (sm *StackMachine) popPrefixRange() fdb.ExactRange {
}
func (sm *StackMachine) pushRange(idx int, sl []fdb.KeyValue, prefixFilter []byte) {
var t tuple.Tuple = make(tuple.Tuple, 0, len(sl) * 2)
var t tuple.Tuple = make(tuple.Tuple, 0, len(sl)*2)
for _, kv := range(sl) {
for _, kv := range sl {
if prefixFilter == nil || bytes.HasPrefix(kv.Key, prefixFilter) {
t = append(t, kv.Key)
t = append(t, kv.Value)
@ -240,7 +240,7 @@ func (sm *StackMachine) dumpStack() {
}
}
func (sm *StackMachine) executeMutation(t fdb.Transactor, f func (fdb.Transaction) (interface{}, error), isDB bool, idx int) {
func (sm *StackMachine) executeMutation(t fdb.Transactor, f func(fdb.Transaction) (interface{}, error), isDB bool, idx int) {
_, e := t.Transact(f)
if e != nil {
panic(e)
@ -250,8 +250,8 @@ func (sm *StackMachine) executeMutation(t fdb.Transactor, f func (fdb.Transactio
}
}
func (sm *StackMachine) checkWatches(watches [4]fdb.FutureNil, expected bool) (bool) {
for _, watch := range(watches) {
func (sm *StackMachine) checkWatches(watches [4]fdb.FutureNil, expected bool) bool {
for _, watch := range watches {
if watch.IsReady() || expected {
e := watch.Get()
if e != nil {
@ -283,7 +283,9 @@ func (sm *StackMachine) testWatches() {
tr.Set(fdb.Key("w3"), []byte("3"))
return nil, nil
})
if e != nil { panic(e) }
if e != nil {
panic(e)
}
var watches [4]fdb.FutureNil
@ -297,7 +299,9 @@ func (sm *StackMachine) testWatches() {
tr.Clear(fdb.Key("w1"))
return nil, nil
})
if e != nil { panic(e) }
if e != nil {
panic(e)
}
time.Sleep(5 * time.Second)
@ -312,7 +316,9 @@ func (sm *StackMachine) testWatches() {
tr.BitXor(fdb.Key("w3"), []byte("\xff\xff"))
return nil, nil
})
if e != nil { panic(e) }
if e != nil {
panic(e)
}
if sm.checkWatches(watches, true) {
return
@ -322,21 +328,23 @@ func (sm *StackMachine) testWatches() {
func (sm *StackMachine) testLocality() {
_, e := db.Transact(func(tr fdb.Transaction) (interface{}, error) {
tr.Options().SetTimeout(60*1000)
tr.Options().SetTimeout(60 * 1000)
tr.Options().SetReadSystemKeys()
boundaryKeys, e := db.LocalityGetBoundaryKeys(fdb.KeyRange{fdb.Key(""), fdb.Key("\xff\xff")}, 0, 0)
if e != nil { panic(e) }
if e != nil {
panic(e)
}
for i:=0; i<len(boundaryKeys)-1 ; i++ {
for i := 0; i < len(boundaryKeys)-1; i++ {
start := boundaryKeys[i]
end := tr.GetKey(fdb.LastLessThan(boundaryKeys[i+1])).MustGet()
startAddresses := tr.LocalityGetAddressesForKey(start).MustGet()
endAddresses := tr.LocalityGetAddressesForKey(end).MustGet()
for _, address1 := range(startAddresses) {
for _, address1 := range startAddresses {
found := false
for _, address2 := range(endAddresses) {
for _, address2 := range endAddresses {
if address1 == address2 {
found = true
break
@ -351,7 +359,9 @@ func (sm *StackMachine) testLocality() {
return nil, nil
})
if e != nil { panic(e) }
if e != nil {
panic(e)
}
}
func (sm *StackMachine) logStack(entries map[int]stackEntry, prefix []byte) {
@ -377,7 +387,9 @@ func (sm *StackMachine) logStack(entries map[int]stackEntry, prefix []byte) {
return nil, nil
})
if e != nil { panic(e) }
if e != nil {
panic(e)
}
return
}
@ -467,28 +479,28 @@ func (sm *StackMachine) processInst(idx int, inst tuple.Tuple) {
case op == "PUSH":
sm.store(idx, inst[1])
case op == "DUP":
entry := sm.stack[len(sm.stack) - 1]
entry := sm.stack[len(sm.stack)-1]
sm.store(entry.idx, entry.item)
case op == "EMPTY_STACK":
sm.stack = []stackEntry{}
sm.stack = make([]stackEntry, 0)
case op == "SWAP":
idx := sm.waitAndPop().item.(int64)
sm.stack[len(sm.stack) - 1], sm.stack[len(sm.stack) - 1 - int(idx)] = sm.stack[len(sm.stack) - 1 - int(idx)], sm.stack[len(sm.stack) - 1]
sm.stack[len(sm.stack)-1], sm.stack[len(sm.stack)-1-int(idx)] = sm.stack[len(sm.stack)-1-int(idx)], sm.stack[len(sm.stack)-1]
case op == "POP":
sm.stack = sm.stack[:len(sm.stack) - 1]
sm.stack = sm.stack[:len(sm.stack)-1]
case op == "SUB":
sm.store(idx, sm.waitAndPop().item.(int64) - sm.waitAndPop().item.(int64))
sm.store(idx, sm.waitAndPop().item.(int64)-sm.waitAndPop().item.(int64))
case op == "CONCAT":
str1 := sm.waitAndPop().item
str2 := sm.waitAndPop().item
switch str1.(type) {
case string:
sm.store(idx, str1.(string) + str2.(string))
case []byte:
sm.store(idx, append(str1.([]byte), str2.([]byte)...))
default:
panic("Invalid CONCAT parameter")
case string:
sm.store(idx, str1.(string)+str2.(string))
case []byte:
sm.store(idx, append(str1.([]byte), str2.([]byte)...))
default:
panic("Invalid CONCAT parameter")
}
case op == "NEW_TRANSACTION":
sm.newTransaction()
@ -497,16 +509,18 @@ func (sm *StackMachine) processInst(idx int, inst tuple.Tuple) {
case op == "ON_ERROR":
sm.store(idx, sm.currentTransaction().OnError(fdb.Error{int(sm.waitAndPop().item.(int64))}))
case op == "GET_READ_VERSION":
_, e = rt.ReadTransact(func (rtr fdb.ReadTransaction) (interface{}, error) {
_, e = rt.ReadTransact(func(rtr fdb.ReadTransaction) (interface{}, error) {
sm.lastVersion = rtr.GetReadVersion().MustGet()
sm.store(idx, []byte("GOT_READ_VERSION"))
return nil, nil
})
if e != nil { panic(e) }
if e != nil {
panic(e)
}
case op == "SET":
key := fdb.Key(sm.waitAndPop().item.([]byte))
value := sm.waitAndPop().item.([]byte)
sm.executeMutation(t, func (tr fdb.Transaction) (interface{}, error) {
sm.executeMutation(t, func(tr fdb.Transaction) (interface{}, error) {
tr.Set(key, value)
return nil, nil
}, isDB, idx)
@ -525,10 +539,12 @@ func (sm *StackMachine) processInst(idx int, inst tuple.Tuple) {
sm.logStack(entries, prefix)
case op == "GET":
key := fdb.Key(sm.waitAndPop().item.([]byte))
res, e := rt.ReadTransact(func (rtr fdb.ReadTransaction) (interface{}, error) {
res, e := rt.ReadTransact(func(rtr fdb.ReadTransaction) (interface{}, error) {
return rtr.Get(key), nil
})
if e != nil { panic(e) }
if e != nil {
panic(e)
}
sm.store(idx, res.(fdb.FutureByteSlice))
case op == "COMMIT":
@ -537,7 +553,7 @@ func (sm *StackMachine) processInst(idx int, inst tuple.Tuple) {
sm.currentTransaction().Reset()
case op == "CLEAR":
key := fdb.Key(sm.waitAndPop().item.([]byte))
sm.executeMutation(t, func (tr fdb.Transaction) (interface{}, error) {
sm.executeMutation(t, func(tr fdb.Transaction) (interface{}, error) {
tr.Clear(key)
return nil, nil
}, isDB, idx)
@ -557,10 +573,12 @@ func (sm *StackMachine) processInst(idx int, inst tuple.Tuple) {
case op == "GET_KEY":
sel := sm.popSelector()
prefix := sm.waitAndPop().item.([]byte)
res, e := rt.ReadTransact(func (rtr fdb.ReadTransaction) (interface{}, error) {
res, e := rt.ReadTransact(func(rtr fdb.ReadTransaction) (interface{}, error) {
return rtr.GetKey(sel).MustGet(), nil
})
if e != nil { panic(e) }
if e != nil {
panic(e)
}
key := res.(fdb.Key)
@ -570,7 +588,9 @@ func (sm *StackMachine) processInst(idx int, inst tuple.Tuple) {
sm.store(idx, prefix)
} else {
s, e := fdb.Strinc(prefix)
if e != nil { panic(e) }
if e != nil {
panic(e)
}
sm.store(idx, s)
}
case strings.HasPrefix(op, "GET_RANGE"):
@ -591,10 +611,12 @@ func (sm *StackMachine) processInst(idx int, inst tuple.Tuple) {
prefix = sm.waitAndPop().item.([]byte)
}
res, e := rt.ReadTransact(func (rtr fdb.ReadTransaction) (interface{}, error) {
res, e := rt.ReadTransact(func(rtr fdb.ReadTransaction) (interface{}, error) {
return rtr.GetRange(r, ro).GetSliceOrPanic(), nil
})
if e != nil { panic(e) }
if e != nil {
panic(e)
}
sm.pushRange(idx, res.([]fdb.KeyValue), prefix)
case strings.HasPrefix(op, "CLEAR_RANGE"):
@ -607,7 +629,7 @@ func (sm *StackMachine) processInst(idx int, inst tuple.Tuple) {
er = sm.popKeyRange()
}
sm.executeMutation(t, func (tr fdb.Transaction) (interface{}, error) {
sm.executeMutation(t, func(tr fdb.Transaction) (interface{}, error) {
tr.ClearRange(er)
return nil, nil
}, isDB, idx)
@ -623,7 +645,7 @@ func (sm *StackMachine) processInst(idx int, inst tuple.Tuple) {
if e != nil {
panic(e)
}
for _, el := range(t) {
for _, el := range t {
sm.store(idx, []byte(tuple.Tuple{el}.Pack()))
}
case op == "TUPLE_SORT":
@ -681,7 +703,7 @@ func (sm *StackMachine) processInst(idx int, inst tuple.Tuple) {
if e != nil {
panic(e)
}
db.Transact(func (tr fdb.Transaction) (interface{}, error) {
db.Transact(func(tr fdb.Transaction) (interface{}, error) {
v := tr.GetRange(er, fdb.RangeOptions{}).GetSliceOrPanic()
if len(v) != 0 {
panic(fdb.Error{1020})
@ -718,7 +740,7 @@ func (sm *StackMachine) processInst(idx int, inst tuple.Tuple) {
key := fdb.Key(sm.waitAndPop().item.([]byte))
ival := sm.waitAndPop().item
value := ival.([]byte)
sm.executeMutation(t, func (tr fdb.Transaction) (interface{}, error) {
sm.executeMutation(t, func(tr fdb.Transaction) (interface{}, error) {
reflect.ValueOf(tr).MethodByName(opname).Call([]reflect.Value{reflect.ValueOf(key), reflect.ValueOf(value)})
return nil, nil
}, isDB, idx)
@ -730,6 +752,33 @@ func (sm *StackMachine) processInst(idx int, inst tuple.Tuple) {
db.Options().SetLocationCacheSize(100001)
db.Options().SetMaxWatches(10001)
if !fdb.IsAPIVersionSelected() {
log.Fatal("API version should be selected")
}
apiVersion := fdb.MustGetAPIVersion()
if apiVersion == 0 {
log.Fatal("API version is 0")
}
e1 := fdb.APIVersion(apiVersion + 1)
if e1 != nil {
fdbE := e1.(fdb.Error)
if fdbE.Code != 2201 {
panic(e1)
}
} else {
log.Fatal("Was not stopped from selecting two API versions")
}
e2 := fdb.APIVersion(apiVersion - 1)
if e2 != nil {
fdbE := e2.(fdb.Error)
if fdbE.Code != 2201 {
panic(e2)
}
} else {
log.Fatal("Was not stopped from selecting two API versions")
}
fdb.MustAPIVersion(apiVersion)
_, e := db.Transact(func(tr fdb.Transaction) (interface{}, error) {
tr.Options().SetPrioritySystemImmediate()
tr.Options().SetPriorityBatch()
@ -740,7 +789,7 @@ func (sm *StackMachine) processInst(idx int, inst tuple.Tuple) {
tr.Options().SetReadSystemKeys()
tr.Options().SetAccessSystemKeys()
tr.Options().SetDurabilityDevNullIsWebScale()
tr.Options().SetTimeout(60*1000)
tr.Options().SetTimeout(60 * 1000)
tr.Options().SetRetryLimit(50)
tr.Options().SetMaxRetryDelay(100)
tr.Options().SetUsedDuringCommitProtectionDisable()
@ -751,7 +800,9 @@ func (sm *StackMachine) processInst(idx int, inst tuple.Tuple) {
return tr.Get(fdb.Key("\xff")).MustGet(), nil
})
if e != nil { panic(e) }
if e != nil {
panic(e)
}
sm.testWatches()
sm.testLocality()
@ -772,7 +823,7 @@ func (sm *StackMachine) processInst(idx int, inst tuple.Tuple) {
}
func (sm *StackMachine) Run() {
r, e := db.Transact(func (tr fdb.Transaction) (interface{}, error) {
r, e := db.Transact(func(tr fdb.Transaction) (interface{}, error) {
return tr.GetRange(tuple.Tuple{sm.prefix}, fdb.RangeOptions{}).GetSliceOrPanic(), nil
})
if e != nil {
@ -781,7 +832,7 @@ func (sm *StackMachine) Run() {
instructions := r.([]fdb.KeyValue)
for i, kv := range(instructions) {
for i, kv := range instructions {
inst, _ := tuple.Unpack(fdb.Key(kv.Value))
if sm.verbose {
@ -811,10 +862,17 @@ func main() {
log.Fatal(e)
}
if fdb.IsAPIVersionSelected() {
log.Fatal("API version already selected")
}
e = fdb.APIVersion(apiVersion)
if e != nil {
log.Fatal(e)
}
if fdb.MustGetAPIVersion() != apiVersion {
log.Fatal("API version not equal to value selected")
}
db, e = fdb.Open(clusterFile, []byte("DB"))
if e != nil {

View File

@ -4,13 +4,13 @@
* 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.
@ -24,26 +24,26 @@ package main
import (
"encoding/xml"
"io/ioutil"
"fmt"
"go/doc"
"io/ioutil"
"log"
"strings"
"os"
"strings"
"unicode"
"unicode/utf8"
"go/doc"
)
type Option struct {
Name string `xml:"name,attr"`
Code int `xml:"code,attr"`
ParamType string `xml:"paramType,attr"`
ParamDesc string `xml:"paramDescription,attr"`
Name string `xml:"name,attr"`
Code int `xml:"code,attr"`
ParamType string `xml:"paramType,attr"`
ParamDesc string `xml:"paramDescription,attr"`
Description string `xml:"description,attr"`
Hidden bool `xml:"hidden,attr"`
Hidden bool `xml:"hidden,attr"`
}
type Scope struct {
Name string `xml:"name,attr"`
Name string `xml:"name,attr"`
Option []Option
}
type Options struct {
@ -114,12 +114,12 @@ func translateName(old string) string {
return strings.Replace(strings.Title(strings.Replace(old, "_", " ", -1)), " ", "", -1)
}
func lowerFirst (s string) string {
if s == "" {
return ""
}
r, n := utf8.DecodeRuneInString(s)
return string(unicode.ToLower(r)) + s[n:]
func lowerFirst(s string) string {
if s == "" {
return ""
}
r, n := utf8.DecodeRuneInString(s)
return string(unicode.ToLower(r)) + s[n:]
}
func writeMutation(opt Option) {
@ -139,7 +139,7 @@ func writeEnum(scope Scope, opt Option, delta int) {
doc.ToText(os.Stdout, opt.Description, " // ", "", 73)
// fmt.Printf(" // %s\n", opt.Description)
}
fmt.Printf(" %s %s = %d\n", scope.Name + translateName(opt.Name), scope.Name, opt.Code + delta)
fmt.Printf(" %s %s = %d\n", scope.Name+translateName(opt.Name), scope.Name, opt.Code+delta)
}
func main() {
@ -182,11 +182,11 @@ func int64ToBytes(i int64) ([]byte, error) {
}
`)
for _, scope := range(v.Scope) {
for _, scope := range v.Scope {
if strings.HasSuffix(scope.Name, "Option") {
receiver := scope.Name + "s"
for _, opt := range(scope.Option) {
for _, opt := range scope.Option {
if opt.Description != "Deprecated" && !opt.Hidden { // Eww
writeOpt(receiver, opt)
}
@ -195,7 +195,7 @@ func int64ToBytes(i int64) ([]byte, error) {
}
if scope.Name == "MutationType" {
for _, opt := range(scope.Option) {
for _, opt := range scope.Option {
if opt.Description != "Deprecated" && !opt.Hidden { // Eww
writeMutation(opt)
}
@ -218,7 +218,7 @@ func int64ToBytes(i int64) ([]byte, error) {
type %s int
const (
`, scope.Name)
for _, opt := range(scope.Option) {
for _, opt := range scope.Option {
if !opt.Hidden {
writeEnum(scope, opt, d)
}

View File

@ -4,13 +4,13 @@
* 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.
@ -23,7 +23,7 @@
package fdb
/*
#define FDB_API_VERSION 510
#define FDB_API_VERSION 520
#include <foundationdb/fdb_c.h>
*/
import "C"

View File

@ -4,13 +4,13 @@
* 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.
@ -23,7 +23,7 @@
package fdb
/*
#define FDB_API_VERSION 510
#define FDB_API_VERSION 520
#include <foundationdb/fdb_c.h>
*/
import "C"

View File

@ -4,13 +4,13 @@
* 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.
@ -23,10 +23,10 @@
package directory
import (
"bytes"
"encoding/binary"
"github.com/apple/foundationdb/bindings/go/src/fdb"
"github.com/apple/foundationdb/bindings/go/src/fdb/subspace"
"encoding/binary"
"bytes"
"math/rand"
"sync"
)
@ -53,14 +53,18 @@ func windowSize(start int64) int64 {
// can't be too small. So start small and scale up. We don't want this to
// ever get *too* big because we have to store about window_size/2 recent
// items.
if start < 255 { return 64 }
if start < 65535 { return 1024 }
if start < 255 {
return 64
}
if start < 65535 {
return 1024
}
return 8192
}
func (hca highContentionAllocator) allocate(tr fdb.Transaction, s subspace.Subspace) (subspace.Subspace, error) {
for {
rr := tr.Snapshot().GetRange(hca.counters, fdb.RangeOptions{Limit:1, Reverse:true})
rr := tr.Snapshot().GetRange(hca.counters, fdb.RangeOptions{Limit: 1, Reverse: true})
kvs := rr.GetSliceOrPanic()
var start int64
@ -106,7 +110,7 @@ func (hca highContentionAllocator) allocate(tr fdb.Transaction, s subspace.Subsp
}
window = windowSize(start)
if count * 2 < window {
if count*2 < window {
break
}
@ -124,7 +128,7 @@ func (hca highContentionAllocator) allocate(tr fdb.Transaction, s subspace.Subsp
allocatorMutex.Lock()
latestCounter := tr.Snapshot().GetRange(hca.counters, fdb.RangeOptions{Limit:1, Reverse:true})
latestCounter := tr.Snapshot().GetRange(hca.counters, fdb.RangeOptions{Limit: 1, Reverse: true})
candidateValue := tr.Get(key)
tr.Options().SetNextWriteNoWriteConflictRange()
tr.Set(key, []byte(""))

View File

@ -4,13 +4,13 @@
* 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.
@ -26,7 +26,7 @@
//
// For general guidance on directory usage, see the Directories section of the
// Developer Guide
// (https://foundationdb.org/documentation/developer-guide.html#developer-guide-directories).
// (https://www.foundationdb.org/documentation/developer-guide.html#developer-guide-directories).
//
// Directories are identified by hierarchical paths analogous to the paths in a
// Unix-like file system. A path is represented as a slice of strings. Each
@ -40,9 +40,9 @@
package directory
import (
"errors"
"github.com/apple/foundationdb/bindings/go/src/fdb"
"github.com/apple/foundationdb/bindings/go/src/fdb/subspace"
"errors"
)
const (

View File

@ -4,13 +4,13 @@
* 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.
@ -23,23 +23,23 @@
package directory
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"github.com/apple/foundationdb/bindings/go/src/fdb"
"github.com/apple/foundationdb/bindings/go/src/fdb/subspace"
"github.com/apple/foundationdb/bindings/go/src/fdb/tuple"
"encoding/binary"
"bytes"
"fmt"
"errors"
)
type directoryLayer struct {
nodeSS subspace.Subspace
nodeSS subspace.Subspace
contentSS subspace.Subspace
allowManualPrefixes bool
allocator highContentionAllocator
rootNode subspace.Subspace
rootNode subspace.Subspace
path []string
}
@ -130,13 +130,17 @@ func (dl directoryLayer) createOrOpen(rtr fdb.ReadTransaction, tr *fdb.Transacti
prefix = newss.Bytes()
pf, e := dl.isPrefixFree(rtr.Snapshot(), prefix)
if e != nil { return nil, e }
if e != nil {
return nil, e
}
if !pf {
return nil, errors.New("the directory layer has manually allocated prefixes that conflict with the automatic prefix allocator")
}
} else {
pf, e := dl.isPrefixFree(rtr, prefix)
if e != nil { return nil, e }
if e != nil {
return nil, e
}
if !pf {
return nil, errors.New("the given prefix is already in use")
}
@ -171,7 +175,7 @@ func (dl directoryLayer) createOrOpen(rtr fdb.ReadTransaction, tr *fdb.Transacti
}
func (dl directoryLayer) CreateOrOpen(t fdb.Transactor, path []string, layer []byte) (DirectorySubspace, error) {
r, e := t.Transact(func (tr fdb.Transaction) (interface{}, error) {
r, e := t.Transact(func(tr fdb.Transaction) (interface{}, error) {
return dl.createOrOpen(tr, &tr, path, layer, nil, true, true)
})
if e != nil {
@ -181,7 +185,7 @@ func (dl directoryLayer) CreateOrOpen(t fdb.Transactor, path []string, layer []b
}
func (dl directoryLayer) Create(t fdb.Transactor, path []string, layer []byte) (DirectorySubspace, error) {
r, e := t.Transact(func (tr fdb.Transaction) (interface{}, error) {
r, e := t.Transact(func(tr fdb.Transaction) (interface{}, error) {
return dl.createOrOpen(tr, &tr, path, layer, nil, true, false)
})
if e != nil {
@ -194,7 +198,7 @@ func (dl directoryLayer) CreatePrefix(t fdb.Transactor, path []string, layer []b
if prefix == nil {
prefix = []byte{}
}
r, e := t.Transact(func (tr fdb.Transaction) (interface{}, error) {
r, e := t.Transact(func(tr fdb.Transaction) (interface{}, error) {
return dl.createOrOpen(tr, &tr, path, layer, prefix, true, false)
})
if e != nil {
@ -204,7 +208,7 @@ func (dl directoryLayer) CreatePrefix(t fdb.Transactor, path []string, layer []b
}
func (dl directoryLayer) Open(rt fdb.ReadTransactor, path []string, layer []byte) (DirectorySubspace, error) {
r, e := rt.ReadTransact(func (rtr fdb.ReadTransaction) (interface{}, error) {
r, e := rt.ReadTransact(func(rtr fdb.ReadTransaction) (interface{}, error) {
return dl.createOrOpen(rtr, nil, path, layer, nil, false, true)
})
if e != nil {
@ -214,7 +218,7 @@ func (dl directoryLayer) Open(rt fdb.ReadTransactor, path []string, layer []byte
}
func (dl directoryLayer) Exists(rt fdb.ReadTransactor, path []string) (bool, error) {
r, e := rt.ReadTransact(func (rtr fdb.ReadTransaction) (interface{}, error) {
r, e := rt.ReadTransact(func(rtr fdb.ReadTransaction) (interface{}, error) {
if e := dl.checkVersion(rtr, nil); e != nil {
return false, e
}
@ -241,7 +245,7 @@ func (dl directoryLayer) Exists(rt fdb.ReadTransactor, path []string) (bool, err
}
func (dl directoryLayer) List(rt fdb.ReadTransactor, path []string) ([]string, error) {
r, e := rt.ReadTransact(func (rtr fdb.ReadTransaction) (interface{}, error) {
r, e := rt.ReadTransact(func(rtr fdb.ReadTransaction) (interface{}, error) {
if e := dl.checkVersion(rtr, nil); e != nil {
return nil, e
}
@ -272,7 +276,7 @@ func (dl directoryLayer) MoveTo(t fdb.Transactor, newAbsolutePath []string) (Dir
}
func (dl directoryLayer) Move(t fdb.Transactor, oldPath []string, newPath []string) (DirectorySubspace, error) {
r, e := t.Transact(func (tr fdb.Transaction) (interface{}, error) {
r, e := t.Transact(func(tr fdb.Transaction) (interface{}, error) {
if e := dl.checkVersion(tr, &tr); e != nil {
return nil, e
}
@ -330,7 +334,7 @@ func (dl directoryLayer) Move(t fdb.Transactor, oldPath []string, newPath []stri
}
func (dl directoryLayer) Remove(t fdb.Transactor, path []string) (bool, error) {
r, e := t.Transact(func (tr fdb.Transaction) (interface{}, error) {
r, e := t.Transact(func(tr fdb.Transaction) (interface{}, error) {
if e := dl.checkVersion(tr, &tr); e != nil {
return false, e
}
@ -375,9 +379,13 @@ func (dl directoryLayer) removeRecursive(tr fdb.Transaction, node subspace.Subsp
}
p, e := dl.nodeSS.Unpack(node)
if e != nil { return e }
if e != nil {
return e
}
kr, e := fdb.PrefixRange(p[0].([]byte))
if e != nil { return e }
if e != nil {
return e
}
tr.ClearRange(kr)
tr.ClearRange(node)
@ -445,7 +453,7 @@ func (dl directoryLayer) nodeContainingKey(rtr fdb.ReadTransaction, key []byte)
bk, _ := dl.nodeSS.FDBRangeKeys()
kr := fdb.KeyRange{bk, fdb.Key(append(dl.nodeSS.Pack(tuple.Tuple{key}), 0x00))}
kvs := rtr.GetRange(kr, fdb.RangeOptions{Reverse:true, Limit:1}).GetSliceOrPanic()
kvs := rtr.GetRange(kr, fdb.RangeOptions{Reverse: true, Limit: 1}).GetSliceOrPanic()
if len(kvs) == 1 {
pp, e := dl.nodeSS.Unpack(kvs[0].Key)
if e != nil {
@ -540,7 +548,7 @@ func (dl directoryLayer) contentsOfNode(node subspace.Subspace, path []string, l
}
prefix := p[0]
newPath := make([]string, len(dl.path) + len(path))
newPath := make([]string, len(dl.path)+len(path))
copy(newPath, dl.path)
copy(newPath[len(dl.path):], path)
@ -548,7 +556,7 @@ func (dl directoryLayer) contentsOfNode(node subspace.Subspace, path []string, l
ss := subspace.FromBytes(pb)
if bytes.Compare(layer, []byte("partition")) == 0 {
nssb := make([]byte, len(pb) + 1)
nssb := make([]byte, len(pb)+1)
copy(nssb, pb)
nssb[len(pb)] = 0xFE
ndl := NewDirectoryLayer(subspace.FromBytes(nssb), ss, false).(directoryLayer)
@ -560,7 +568,9 @@ func (dl directoryLayer) contentsOfNode(node subspace.Subspace, path []string, l
}
func (dl directoryLayer) nodeWithPrefix(prefix []byte) subspace.Subspace {
if prefix == nil { return nil }
if prefix == nil {
return nil
}
return dl.nodeSS.Sub(prefix)
}
@ -576,9 +586,9 @@ func (dl directoryLayer) find(rtr fdb.ReadTransaction, path []string) *node {
}
func (dl directoryLayer) partitionSubpath(lpath, rpath []string) []string {
r := make([]string, len(lpath) - len(dl.path) + len(rpath))
r := make([]string, len(lpath)-len(dl.path)+len(rpath))
copy(r, lpath[len(dl.path):])
copy(r[len(lpath) - len(dl.path):], rpath)
copy(r[len(lpath)-len(dl.path):], rpath)
return r
}

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.
@ -38,8 +38,8 @@ type DirectorySubspace interface {
type directorySubspace struct {
subspace.Subspace
dl directoryLayer
path []string
dl directoryLayer
path []string
layer []byte
}

View File

@ -4,13 +4,13 @@
* 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.
@ -23,16 +23,16 @@
package directory
import (
"bytes"
"github.com/apple/foundationdb/bindings/go/src/fdb"
"github.com/apple/foundationdb/bindings/go/src/fdb/subspace"
"bytes"
)
type node struct {
subspace subspace.Subspace
path []string
subspace subspace.Subspace
path []string
targetPath []string
_layer fdb.FutureByteSlice
_layer fdb.FutureByteSlice
}
func (n *node) exists() bool {

View File

@ -4,13 +4,13 @@
* 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.
@ -25,12 +25,12 @@ Package fdb provides an interface to FoundationDB databases (version 2.0 or high
To build and run programs using this package, you must have an installed copy of
the FoundationDB client libraries (version 2.0.0 or later), available for Linux,
Windows and OS X at https://files.foundationdb.org/fdb-c/.
Windows and OS X at https://www.foundationdb.org/downloads/fdb-c/.
This documentation specifically applies to the FoundationDB Go binding. For more
extensive guidance to programming with FoundationDB, as well as API
documentation for the other FoundationDB interfaces, please see
https://foundationdb.org/documentation/index.html.
https://www.foundationdb.org/documentation/index.html.
Basic Usage
@ -198,7 +198,7 @@ operations perform different transformations. Like other database operations, an
atomic operation is used within a transaction.
For more information on atomic operations in FoundationDB, please see
https://foundationdb.org/documentation/developer-guide.html#atomic-operations. The
https://www.foundationdb.org/documentation/developer-guide.html#atomic-operations. The
operands to atomic operations in this API must be provided as appropriately
encoded byte slices. To convert a Go type to a byte slice, see the binary
package.

View File

@ -4,13 +4,13 @@
* 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.
@ -23,7 +23,7 @@
package fdb
/*
#define FDB_API_VERSION 510
#define FDB_API_VERSION 520
#include <foundationdb/fdb_c.h>
*/
import "C"
@ -37,7 +37,7 @@ import (
// as a panic from any FoundationDB API function whose name ends with OrPanic.
//
// You may compare the Code field of an Error against the list of FoundationDB
// error codes at https://foundationdb.org/documentation/api-error-codes.html,
// error codes at https://www.foundationdb.org/documentation/api-error-codes.html,
// but generally an Error should be passed to (Transaction).OnError. When using
// (Database).Transact, non-fatal errors will be retried automatically.
type Error struct {
@ -53,7 +53,7 @@ func (e Error) Error() string {
var (
errNetworkNotSetup = Error{2008}
errAPIVersionUnset = Error{2200}
errAPIVersionAlreadySet = Error{2201}
errAPIVersionUnset = Error{2200}
errAPIVersionAlreadySet = Error{2201}
errAPIVersionNotSupported = Error{2203}
)

View File

@ -4,13 +4,13 @@
* 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.
@ -23,18 +23,18 @@
package fdb
/*
#define FDB_API_VERSION 510
#define FDB_API_VERSION 520
#include <foundationdb/fdb_c.h>
#include <stdlib.h>
*/
import "C"
import (
"fmt"
"log"
"runtime"
"sync"
"unsafe"
"fmt"
"log"
)
/* Would put this in futures.go but for the documented issue with
@ -53,7 +53,7 @@ type Transactor interface {
// Transact executes the caller-provided function, providing it with a
// Transaction (itself a Transactor, allowing composition of transactional
// functions).
Transact(func (Transaction) (interface{}, error)) (interface{}, error)
Transact(func(Transaction) (interface{}, error)) (interface{}, error)
// All Transactors are also ReadTransactors, allowing them to be used with
// read-only transactional functions.
@ -68,7 +68,7 @@ type ReadTransactor interface {
// ReadTransact executes the caller-provided function, providing it with a
// ReadTransaction (itself a ReadTransactor, allowing composition of
// read-only transactional functions).
ReadTransact(func (ReadTransaction) (interface{}, error)) (interface{}, error)
ReadTransact(func(ReadTransaction) (interface{}, error)) (interface{}, error)
}
func setOpt(setter func(*C.uint8_t, C.int) C.fdb_error_t, param []byte) error {
@ -109,7 +109,7 @@ func (opt NetworkOptions) setOpt(code int, param []byte) error {
// library, an error will be returned. APIVersion must be called prior to any
// other functions in the fdb package.
//
// Currently, this package supports API versions 200 through 510.
// Currently, this package supports API versions 200 through 520.
//
// Warning: When using the multi-version client API, setting an API version that
// is not supported by a particular client library will prevent that client from
@ -117,7 +117,7 @@ func (opt NetworkOptions) setOpt(code int, param []byte) error {
// the API version of your application after upgrading your client until the
// cluster has also been upgraded.
func APIVersion(version int) error {
headerVersion := 510
headerVersion := 520
networkMutex.Lock()
defer networkMutex.Unlock()
@ -129,7 +129,7 @@ func APIVersion(version int) error {
return errAPIVersionAlreadySet
}
if version < 200 || version > 510 {
if version < 200 || version > 520 {
return errAPIVersionNotSupported
}
@ -152,6 +152,25 @@ func APIVersion(version int) error {
return nil
}
// Determines if an API version has already been selected, i.e., if
// APIVersion or MustAPIVersion have already been called.
func IsAPIVersionSelected() bool {
return apiVersion != 0
}
// Returns the API version that has been selected through APIVersion
// or MustAPIVersion. If the version has already been selected, then
// the first value returned is the API version and the error is
// nil. If the API version has not yet been set, then the error
// will be non-nil.
func GetAPIVersion() (int, error) {
if IsAPIVersionSelected() {
return apiVersion, nil
} else {
return 0, errAPIVersionUnset
}
}
// MustAPIVersion is like APIVersion but panics if the API version is not
// supported.
func MustAPIVersion(version int) {
@ -161,6 +180,16 @@ func MustAPIVersion(version int) {
}
}
// MustGetAPIVersion is like GetAPIVersion but panics if the API version
// has not yet been set.
func MustGetAPIVersion() int {
apiVersion, err := GetAPIVersion()
if err != nil {
panic(err)
}
return apiVersion
}
var apiVersion int
var networkStarted bool
var networkMutex sync.Mutex

View File

@ -4,13 +4,13 @@
* 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.
@ -23,8 +23,8 @@
package fdb_test
import (
"github.com/apple/foundationdb/bindings/go/src/fdb"
"fmt"
"github.com/apple/foundationdb/bindings/go/src/fdb"
"testing"
)
@ -52,7 +52,7 @@ func ExampleVersionstamp(t *testing.T) {
fdb.MustAPIVersion(400)
db := fdb.MustOpenDefault()
setVs := func(t fdb.Transactor, key fdb.Key ) (fdb.FutureKey, error) {
setVs := func(t fdb.Transactor, key fdb.Key) (fdb.FutureKey, error) {
fmt.Printf("setOne called with: %T\n", t)
ret, e := t.Transact(func(tr fdb.Transaction) (interface{}, error) {
tr.SetVersionstampedValue(key, []byte("blahblahbl"))
@ -100,7 +100,7 @@ func ExampleTransactor() {
setMany := func(t fdb.Transactor, value []byte, keys ...fdb.Key) error {
fmt.Printf("setMany called with: %T\n", t)
_, e := t.Transact(func(tr fdb.Transaction) (interface{}, error) {
for _, key := range(keys) {
for _, key := range keys {
setOne(tr, key, value)
}
return nil, nil

View File

@ -4,13 +4,13 @@
* 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.
@ -24,7 +24,7 @@ package fdb
/*
#cgo LDFLAGS: -lfdb_c -lm
#define FDB_API_VERSION 510
#define FDB_API_VERSION 520
#include <foundationdb/fdb_c.h>
#include <string.h>
@ -41,9 +41,9 @@ package fdb
import "C"
import (
"unsafe"
"sync"
"runtime"
"sync"
"unsafe"
)
// A Future represents a value (or error) to be available at some later
@ -253,7 +253,7 @@ type futureKeyValueArray struct {
}
func stringRefToSlice(ptr unsafe.Pointer) []byte {
size := *((*C.int)(unsafe.Pointer(uintptr(ptr)+8)))
size := *((*C.int)(unsafe.Pointer(uintptr(ptr) + 8)))
if size == 0 {
return []byte{}
@ -278,13 +278,13 @@ func (f futureKeyValueArray) Get() ([]KeyValue, bool, error) {
ret := make([]KeyValue, int(count))
for i := 0; i < int(count); i++ {
kvptr := unsafe.Pointer(uintptr(unsafe.Pointer(kvs)) + uintptr(i * 24))
kvptr := unsafe.Pointer(uintptr(unsafe.Pointer(kvs)) + uintptr(i*24))
ret[i].Key = stringRefToSlice(kvptr)
ret[i].Value = stringRefToSlice(unsafe.Pointer(uintptr(kvptr) + 12))
}
return ret, (more != 0), nil
return ret, (more != 0), nil
}
// FutureInt64 represents the asynchronous result of a function that returns a
@ -361,7 +361,7 @@ func (f futureStringSlice) Get() ([]string, error) {
ret := make([]string, int(count))
for i := 0; i < int(count); i++ {
ret[i] = C.GoString((*C.char)(*(**C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(strings))+uintptr(i*8)))))
ret[i] = C.GoString((*C.char)(*(**C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(strings)) + uintptr(i*8)))))
}
return ret, nil

View File

@ -4,13 +4,13 @@
* 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.
@ -34,11 +34,11 @@ type Selectable interface {
//
// The most common key selectors are constructed with the functions documented
// below. For details of how KeySelectors are specified and resolved, see
// https://foundationdb.org/documentation/developer-guide.html#key-selectors.
// https://www.foundationdb.org/documentation/developer-guide.html#key-selectors.
type KeySelector struct {
Key KeyConvertible
Key KeyConvertible
OrEqual bool
Offset int
Offset int
}
func (ks KeySelector) FDBKeySelector() KeySelector {

View File

@ -4,13 +4,13 @@
* 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.
@ -23,7 +23,7 @@
package fdb
/*
#define FDB_API_VERSION 510
#define FDB_API_VERSION 520
#include <foundationdb/fdb_c.h>
*/
import "C"
@ -34,7 +34,7 @@ import (
// KeyValue represents a single key-value pair in the database.
type KeyValue struct {
Key Key
Key Key
Value []byte
}
@ -121,11 +121,11 @@ func (sr SelectorRange) FDBRangeKeySelectors() (Selectable, Selectable) {
// A RangeResult should not be returned from a transactional function passed to
// the Transact method of a Transactor.
type RangeResult struct {
t *transaction
sr SelectorRange
options RangeOptions
t *transaction
sr SelectorRange
options RangeOptions
snapshot bool
f *futureKeyValueArray
f *futureKeyValueArray
}
// GetSliceWithError returns a slice of KeyValue objects satisfying the range
@ -173,12 +173,12 @@ func (rr RangeResult) GetSliceOrPanic() []KeyValue {
// range specified in the read that returned this RangeResult.
func (rr RangeResult) Iterator() *RangeIterator {
return &RangeIterator{
t: rr.t,
f: rr.f,
sr: rr.sr,
options: rr.options,
t: rr.t,
f: rr.f,
sr: rr.sr,
options: rr.options,
iteration: 1,
snapshot: rr.snapshot,
snapshot: rr.snapshot,
}
}
@ -193,17 +193,17 @@ func (rr RangeResult) Iterator() *RangeIterator {
// RangeResult and used concurrently. RangeIterator should not be returned from
// a transactional function passed to the Transact method of a Transactor.
type RangeIterator struct {
t *transaction
f *futureKeyValueArray
sr SelectorRange
options RangeOptions
t *transaction
f *futureKeyValueArray
sr SelectorRange
options RangeOptions
iteration int
done bool
more bool
kvs []KeyValue
index int
err error
snapshot bool
done bool
more bool
kvs []KeyValue
index int
err error
snapshot bool
}
// Advance attempts to advance the iterator to the next key-value pair. Advance

View File

@ -4,13 +4,13 @@
* 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.
@ -28,7 +28,7 @@ package fdb
// transaction conflicts but making it harder to reason about concurrency.
//
// For more information on snapshot reads, see
// https://foundationdb.org/documentation/developer-guide.html#snapshot-reads.
// https://www.foundationdb.org/documentation/developer-guide.html#snapshot-reads.
type Snapshot struct {
*transaction
}
@ -46,7 +46,7 @@ type Snapshot struct {
//
// See the ReadTransactor interface for an example of using ReadTransact with
// Transaction, Snapshot and Database objects.
func (s Snapshot) ReadTransact(f func (ReadTransaction) (interface{}, error)) (r interface{}, e error) {
func (s Snapshot) ReadTransact(f func(ReadTransaction) (interface{}, error)) (r interface{}, e error) {
defer panicToError(&e)
r, e = f(s)

View File

@ -4,13 +4,13 @@
* 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.
@ -29,14 +29,14 @@
// As a best practice, API clients should use at least one subspace for
// application data. For general guidance on subspace usage, see the Subspaces
// section of the Developer Guide
// (https://foundationdb.org/documentation/developer-guide.html#developer-guide-sub-keyspaces).
// (https://www.foundationdb.org/documentation/developer-guide.html#developer-guide-sub-keyspaces).
package subspace
import (
"github.com/apple/foundationdb/bindings/go/src/fdb"
"github.com/apple/foundationdb/bindings/go/src/fdb/tuple"
"bytes"
"errors"
"github.com/apple/foundationdb/bindings/go/src/fdb"
"github.com/apple/foundationdb/bindings/go/src/fdb/tuple"
)
// Subspace represents a well-defined region of keyspace in a FoundationDB
@ -134,7 +134,7 @@ func (s subspace) FDBRangeKeySelectors() (fdb.Selectable, fdb.Selectable) {
}
func concat(a []byte, b ...byte) []byte {
r := make([]byte, len(a) + len(b))
r := make([]byte, len(a)+len(b))
copy(r, a)
copy(r[len(a):], b)
return r

View File

@ -4,13 +4,13 @@
* 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.
@ -23,7 +23,7 @@
package fdb
/*
#define FDB_API_VERSION 510
#define FDB_API_VERSION 520
#include <foundationdb/fdb_c.h>
*/
import "C"
@ -70,7 +70,7 @@ type Transaction struct {
type transaction struct {
ptr *C.FDBTransaction
db Database
db Database
}
// TransactionOptions is a handle with which to set options that affect a
@ -110,7 +110,7 @@ func (t Transaction) GetDatabase() Database {
//
// See the Transactor interface for an example of using Transact with
// Transaction and Database objects.
func (t Transaction) Transact(f func (Transaction) (interface{}, error)) (r interface{}, e error) {
func (t Transaction) Transact(f func(Transaction) (interface{}, error)) (r interface{}, e error) {
defer panicToError(&e)
r, e = f(t)
@ -171,7 +171,7 @@ func (t Transaction) SetReadVersion(version int64) {
// but making it harder to reason about concurrency.
//
// For more information on snapshot reads, see
// https://foundationdb.org/documentation/developer-guide.html#using-snapshot-reads.
// https://www.foundationdb.org/documentation/developer-guide.html#using-snapshot-reads.
func (t Transaction) Snapshot() Snapshot {
return Snapshot{t.transaction}
}
@ -196,7 +196,7 @@ func (t Transaction) OnError(e Error) FutureNil {
// As with other client/server databases, in some failure scenarios a client may
// be unable to determine whether a transaction succeeded. For more information,
// see
// https://foundationdb.org/documentation/developer-guide.html#developer-guide-unknown-results.
// https://www.foundationdb.org/documentation/developer-guide.html#developer-guide-unknown-results.
func (t Transaction) Commit() FutureNil {
return &futureNil{newFuture(C.fdb_transaction_commit(t.ptr))}
}
@ -260,11 +260,11 @@ func (t *transaction) getRange(r Range, options RangeOptions, snapshot bool) Ran
f := t.doGetRange(r, options, snapshot, 1)
begin, end := r.FDBRangeKeySelectors()
return RangeResult{
t: t,
sr: SelectorRange{begin, end},
options: options,
t: t,
sr: SelectorRange{begin, end},
options: options,
snapshot: snapshot,
f: &f,
f: &f,
}
}
@ -396,13 +396,13 @@ func addConflictRange(t *transaction, er ExactRange, crtype conflictRangeType) e
// conflict.
//
// For more information on conflict ranges, see
// https://foundationdb.org/documentation/developer-guide.html#conflict-ranges.
// https://www.foundationdb.org/documentation/developer-guide.html#conflict-ranges.
func (t Transaction) AddReadConflictRange(er ExactRange) error {
return addConflictRange(t.transaction, er, conflictRangeTypeRead)
}
func copyAndAppend(orig []byte, b byte) []byte {
ret := make([]byte, len(orig) + 1)
ret := make([]byte, len(orig)+1)
copy(ret, orig)
ret[len(orig)] = b
return ret
@ -413,7 +413,7 @@ func copyAndAppend(orig []byte, b byte) []byte {
// this key could cause the transaction to fail with a conflict.
//
// For more information on conflict ranges, see
// https://foundationdb.org/documentation/developer-guide.html#conflict-ranges.
// https://www.foundationdb.org/documentation/developer-guide.html#conflict-ranges.
func (t Transaction) AddReadConflictKey(key KeyConvertible) error {
return addConflictRange(t.transaction, KeyRange{key, Key(copyAndAppend(key.FDBKey(), 0x00))}, conflictRangeTypeRead)
}
@ -424,7 +424,7 @@ func (t Transaction) AddReadConflictKey(key KeyConvertible) error {
// conflict.
//
// For more information on conflict ranges, see
// https://foundationdb.org/documentation/developer-guide.html#conflict-ranges.
// https://www.foundationdb.org/documentation/developer-guide.html#conflict-ranges.
func (t Transaction) AddWriteConflictRange(er ExactRange) error {
return addConflictRange(t.transaction, er, conflictRangeTypeWrite)
}
@ -434,7 +434,7 @@ func (t Transaction) AddWriteConflictRange(er ExactRange) error {
// read this key could fail with a conflict.
//
// For more information on conflict ranges, see
// https://foundationdb.org/documentation/developer-guide.html#conflict-ranges.
// https://www.foundationdb.org/documentation/developer-guide.html#conflict-ranges.
func (t Transaction) AddWriteConflictKey(key KeyConvertible) error {
return addConflictRange(t.transaction, KeyRange{key, Key(copyAndAppend(key.FDBKey(), 0x00))}, conflictRangeTypeWrite)
}

View File

@ -4,13 +4,13 @@
* 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.
@ -27,7 +27,7 @@
// of higher-level data models.
//
// For general guidance on tuple usage, see the Tuple section of Data Modeling
// (https://foundationdb.org/documentation/data-modeling.html#data-modeling-tuples).
// (https://www.foundationdb.org/documentation/data-modeling.html#data-modeling-tuples).
//
// FoundationDB tuples can currently encode byte and unicode strings, integers
// and NULL values. In Go these are represented as []byte, string, int64 and
@ -35,9 +35,9 @@
package tuple
import (
"fmt"
"encoding/binary"
"bytes"
"encoding/binary"
"fmt"
"github.com/apple/foundationdb/bindings/go/src/fdb"
)
@ -68,33 +68,33 @@ type UUID [16]byte
// Type codes: These prefix the different elements in a packed Tuple
// to indicate what type they are.
const nilCode = 0x00
const bytesCode = 0x01
const stringCode = 0x02
const nestedCode = 0x05
const nilCode = 0x00
const bytesCode = 0x01
const stringCode = 0x02
const nestedCode = 0x05
const intZeroCode = 0x14
const posIntEnd = 0x1c
const posIntEnd = 0x1c
const negIntStart = 0x0c
const floatCode = 0x20
const doubleCode = 0x21
const falseCode = 0x26
const trueCode = 0x27
const uuidCode = 0x30
const floatCode = 0x20
const doubleCode = 0x21
const falseCode = 0x26
const trueCode = 0x27
const uuidCode = 0x30
var sizeLimits = []uint64{
1 << (0 * 8) - 1,
1 << (1 * 8) - 1,
1 << (2 * 8) - 1,
1 << (3 * 8) - 1,
1 << (4 * 8) - 1,
1 << (5 * 8) - 1,
1 << (6 * 8) - 1,
1 << (7 * 8) - 1,
1 << (8 * 8) - 1,
1<<(0*8) - 1,
1<<(1*8) - 1,
1<<(2*8) - 1,
1<<(3*8) - 1,
1<<(4*8) - 1,
1<<(5*8) - 1,
1<<(6*8) - 1,
1<<(7*8) - 1,
1<<(8*8) - 1,
}
func adjustFloatBytes(b []byte, encode bool) {
if (encode && b[0] & 0x80 != 0x00) || (!encode && b[0] & 0x80 == 0x00) {
if (encode && b[0]&0x80 != 0x00) || (!encode && b[0]&0x80 == 0x00) {
// Negative numbers: flip all of the bytes.
for i := 0; i < len(b); i++ {
b[i] = b[i] ^ 0xff
@ -131,11 +131,11 @@ func encodeInt(buf *bytes.Buffer, i int64) {
switch {
case i > 0:
n = bisectLeft(uint64(i))
buf.WriteByte(byte(intZeroCode+n))
buf.WriteByte(byte(intZeroCode + n))
binary.Write(&ibuf, binary.BigEndian, i)
case i < 0:
n = bisectLeft(uint64(-i))
buf.WriteByte(byte(0x14-n))
buf.WriteByte(byte(0x14 - n))
binary.Write(&ibuf, binary.BigEndian, int64(sizeLimits[n])+i)
}
@ -170,7 +170,7 @@ func encodeTuple(buf *bytes.Buffer, t Tuple, nested bool) {
buf.WriteByte(nestedCode)
}
for i, e := range(t) {
for i, e := range t {
switch e := e.(type) {
case Tuple:
encodeTuple(buf, e, true)
@ -232,7 +232,7 @@ func findTerminator(b []byte) int {
for {
idx := bytes.IndexByte(bp, 0x00)
length += idx
if idx + 1 == len(bp) || bp[idx+1] != 0xFF {
if idx+1 == len(bp) || bp[idx+1] != 0xFF {
break
}
length += 2
@ -276,7 +276,7 @@ func decodeInt(b []byte) (int64, int) {
ret -= int64(sizeLimits[n])
}
return ret, n+1
return ret, n + 1
}
func decodeFloat(b []byte) (float32, int) {
@ -317,11 +317,11 @@ func decodeTuple(b []byte, nested bool) (Tuple, int, error) {
if !nested {
el = nil
off = 1
} else if i + 1 < len(b) && b[i+1] == 0xff {
} else if i+1 < len(b) && b[i+1] == 0xff {
el = nil
off = 2
} else {
return t, i+1, nil
return t, i + 1, nil
}
case b[i] == bytesCode:
el, off = decodeBytes(b[i:])
@ -330,12 +330,12 @@ func decodeTuple(b []byte, nested bool) (Tuple, int, error) {
case negIntStart <= b[i] && b[i] <= posIntEnd:
el, off = decodeInt(b[i:])
case b[i] == floatCode:
if i + 5 > len(b) {
if i+5 > len(b) {
return nil, i, fmt.Errorf("insufficient bytes to decode float starting at position %d of byte array for tuple", i)
}
el, off = decodeFloat(b[i:])
case b[i] == doubleCode:
if i + 9 > len(b) {
if i+9 > len(b) {
return nil, i, fmt.Errorf("insufficient bytes to decode double starting at position %d of byte array for tuple", i)
}
el, off = decodeDouble(b[i:])
@ -346,7 +346,7 @@ func decodeTuple(b []byte, nested bool) (Tuple, int, error) {
el = false
off = 1
case b[i] == uuidCode:
if i + 17 > len(b) {
if i+17 > len(b) {
return nil, i, fmt.Errorf("insufficient bytes to decode UUID starting at position %d of byte array for tuple", i)
}
el, off = decodeUUID(b[i:])
@ -401,7 +401,7 @@ func (t Tuple) FDBRangeKeySelectors() (fdb.Selectable, fdb.Selectable) {
}
func concat(a []byte, b ...byte) []byte {
r := make([]byte, len(a) + len(b))
r := make([]byte, len(a)+len(b))
copy(r, a)
copy(r[len(a):], b)
return r

View File

@ -4,13 +4,13 @@
* 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.
@ -21,7 +21,7 @@
#include <jni.h>
#include <string.h>
#define FDB_API_VERSION 510
#define FDB_API_VERSION 520
#include <foundationdb/fdb_c.h>

View File

@ -4,13 +4,13 @@
# 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.
@ -38,13 +38,14 @@ else
endif
ifeq ($(PLATFORM),linux)
fdb_java_CFLAGS += -I/usr/lib/jvm/java-8-openjdk-amd64/include -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux
JAVA_HOME ?= /usr/lib/jvm/java-8-openjdk-amd64
fdb_java_CFLAGS += -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux
fdb_java_LDFLAGS += -static-libgcc
java_ARCH := amd64
else ifeq ($(PLATFORM),osx)
# FIXME: Surely there is a better way to grab the JNI headers on any version of macOS.
fdb_java_CFLAGS += -I/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers
JAVA_HOME ?= $(shell /usr/libexec/java_home)
fdb_java_CFLAGS += -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/darwin
java_ARCH := x86_64
endif
@ -110,7 +111,7 @@ javadoc: $(JAVA_SOURCES) bindings/java/src/main/overview.html
-windowtitle "FoundationDB Java Client API" \
-doctitle "FoundationDB Java Client API" \
-link "http://docs.oracle.com/javase/8/docs/api" \
com.apple.foundationdb.org.apple.foundationdb.async com.apple.foundationdb.tuple com.apple.foundationdb.directory com.apple.foundationdb.subspace
com.apple.foundationdb com.apple.foundationdb.async com.apple.foundationdb.tuple com.apple.foundationdb.directory com.apple.foundationdb.subspace
javadoc_clean:
@rm -rf $(JAVADOC_DIR)/javadoc

View File

@ -10,13 +10,13 @@
<packaging>jar</packaging>
<name>foundationdb-java</name>
<description>Java bindings for the FoundationDB database. These bindings require the FoundationDB client, which is under a different license. The client can be obtained from https://files.foundationdb.org/fdb-c/.</description>
<description>Java bindings for the FoundationDB database. These bindings require the FoundationDB client, which is under a different license. The client can be obtained from https://www.foundationdb.org/downloads/fdb-c/.</description>
<inceptionYear>2010</inceptionYear>
<url>http://foundationdb.org</url>
<url>https://www.foundationdb.org</url>
<organization>
<name>FoundationDB</name>
<url>http://foundationdb.org</url>
<url>https://www.foundationdb.org</url>
</organization>
<developers>

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.
@ -83,6 +83,8 @@ public class Cluster extends NativeObjectWrapper {
/**
* Creates a connection to a specific database on an <i>FDB</i> cluster.
*
* @param e the {@link Executor} to use when executing asynchronous callbacks for the database
*
* @return a {@code Future} that will be set to a {@code Database} upon
* successful connection.
*/

View File

@ -4,13 +4,13 @@
* 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.
@ -80,6 +80,9 @@ public interface Database extends AutoCloseable, TransactionContext {
*
* @param retryable the block of logic to execute in a {@link Transaction} against
* this database
* @param <T> the return type of {@code retryable}
*
* @return the result of the last run of {@code retryable}
*/
@Override
default <T> T read(Function<? super ReadTransaction, T> retryable) {
@ -94,6 +97,8 @@ public interface Database extends AutoCloseable, TransactionContext {
* @param retryable the block of logic to execute in a {@link Transaction} against
* this database
* @param e the {@link Executor} to use for asynchronous callbacks
* @param <T> the return type of {@code retryable}
* @return the result of the last run of {@code retryable}
*
* @see #read(Function)
*/
@ -113,6 +118,10 @@ public interface Database extends AutoCloseable, TransactionContext {
*
* @param retryable the block of logic to execute in a {@link ReadTransaction} against
* this database
* @param <T> the return type of {@code retryable}
*
* @return a {@code CompletableFuture} that will be set to the value returned by the last call
* to {@code retryable}
*/
@Override
default <T> CompletableFuture<T> readAsync(
@ -128,7 +137,11 @@ public interface Database extends AutoCloseable, TransactionContext {
* @param retryable the block of logic to execute in a {@link ReadTransaction} against
* this database
* @param e the {@link Executor} to use for asynchronous callbacks
*
* @param <T> the return type of {@code retryable}
*
* @return a {@code CompletableFuture} that will be set to the value returned by the last call
* to {@code retryable}
*
* @see #readAsync(Function)
*/
<T> CompletableFuture<T> readAsync(
@ -147,11 +160,14 @@ public interface Database extends AutoCloseable, TransactionContext {
* be unable to determine whether a transaction succeeded. In these cases, your
* transaction may be executed twice. For more information about how to reason
* about these situations see
* <a href="/foundationdb/developer-guide.html#transactions-with-unknown-results"
* <a href="/developer-guide.html#transactions-with-unknown-results"
* target="_blank">the FounationDB Developer Guide</a>
*
* @param retryable the block of logic to execute in a {@link Transaction} against
* this database
* @param <T> the return type of {@code retryable}
*
* @return the result of the last run of {@code retryable}
*/
@Override
default <T> T run(Function<? super Transaction, T> retryable) {
@ -166,6 +182,9 @@ public interface Database extends AutoCloseable, TransactionContext {
* @param retryable the block of logic to execute in a {@link Transaction} against
* this database
* @param e the {@link Executor} to use for asynchronous callbacks
* @param <T> the return type of {@code retryable}
*
* @return the result of the last run of {@code retryable}
*/
<T> T run(Function<? super Transaction, T> retryable, Executor e);
@ -183,7 +202,7 @@ public interface Database extends AutoCloseable, TransactionContext {
* be unable to determine whether a transaction succeeded. In these cases, your
* transaction may be executed twice. For more information about how to reason
* about these situations see
* <a href="/foundationdb/developer-guide.html#transactions-with-unknown-results"
* <a href="/developer-guide.html#transactions-with-unknown-results"
* target="_blank">the FounationDB Developer Guide</a><br>
* <br>
* Any errors encountered executing {@code retryable}, or received from the
@ -191,6 +210,10 @@ public interface Database extends AutoCloseable, TransactionContext {
*
* @param retryable the block of logic to execute in a {@link Transaction} against
* this database
* @param <T> the return type of {@code retryable}
*
* @return a {@code CompletableFuture} that will be set to the value returned by the last call
* to {@code retryable}
*/
@Override
default <T> CompletableFuture<T> runAsync(
@ -206,6 +229,10 @@ public interface Database extends AutoCloseable, TransactionContext {
* @param retryable the block of logic to execute in a {@link Transaction} against
* this database
* @param e the {@link Executor} to use for asynchronous callbacks
* @param <T> the return type of {@code retryable}
*
* @return a {@code CompletableFuture} that will be set to the value returned by the last call
* to {@code retryable}
*
* @see #run(Function)
*/

View File

@ -4,13 +4,13 @@
* 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.
@ -35,7 +35,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* This call is required before using any other part of the API. The call allows
* an error to be thrown at this point to prevent client code from accessing a later library
* with incorrect assumptions from the current version. The API version documented here is version
* {@code 510}.<br><br>
* {@code 520}.<br><br>
* FoundationDB encapsulates multiple versions of its interface by requiring
* the client to explicitly specify the version of the API it uses. The purpose
* of this design is to allow you to upgrade the server, client libraries, or
@ -81,7 +81,7 @@ public class FDB {
public static final ExecutorService DEFAULT_EXECUTOR;
final int apiVersion;
private final int apiVersion;
private volatile boolean netStarted = false;
private volatile boolean netStopped = false;
volatile boolean warnOnUnclosed = true;
@ -123,6 +123,37 @@ public class FDB {
return options;
}
/**
* Determines if the API version has already been selected. That is, this
* will return {@code true} if the user has already called
* {@link #selectAPIVersion(int) selectAPIVersion()} and that call
* has completed successfully.
*
* @return {@code true} if an API version has been selected and {@code false} otherwise
*/
public static boolean isAPIVersionSelected() {
return singleton != null;
}
/**
* Return the instance of the FDB API singleton. This method will always return
* a non-{@code null} value for the singleton, but if the
* {@link #selectAPIVersion(int) selectAPIVersion()} method has not yet been
* called, it will throw an {@link FDBException} indicating that an API
* version has not yet been set.
*
* @return the FoundationDB API object
* @throws FDBException if {@link #selectAPIVersion(int) selectAPIVersion()} has not been called
*/
public static FDB instance() throws FDBException {
if(singleton != null) {
return singleton;
}
else {
throw new FDBException("API version is not set", 2200);
}
}
/**
* Select the version for the client API. An exception will be thrown if the
* requested version is not supported by this implementation of the API. As
@ -142,7 +173,7 @@ public class FDB {
*/
public static synchronized FDB selectAPIVersion(final int version) throws FDBException {
if(singleton != null) {
if(version != singleton.apiVersion) {
if(version != singleton.getAPIVersion()) {
throw new IllegalArgumentException(
"FoundationDB API already started at different version");
}
@ -150,8 +181,8 @@ public class FDB {
}
if(version < 510)
throw new IllegalArgumentException("API version not supported (minimum 510)");
if(version > 510)
throw new IllegalArgumentException("API version not supported (maximum 510)");
if(version > 520)
throw new IllegalArgumentException("API version not supported (maximum 520)");
Select_API_version(version);
FDB fdb = new FDB(version);
@ -169,18 +200,21 @@ public class FDB {
this.warnOnUnclosed = warnOnUnclosed;
}
// Singleton is initialized to null and only set once by a call to selectAPIVersion
static FDB getInstance() {
if(singleton != null) {
return singleton;
}
throw new IllegalStateException("API version has not been selected");
/**
* Returns the API version that was selected by the {@link #selectAPIVersion(int) selectAPIVersion()}
* call. This can be used to guard different parts of client code against different versions
* of the FoundationDB API to allow for libraries using FoundationDB to be compatible across
* several versions.
*
* @return the FoundationDB API version that has been loaded
*/
public int getAPIVersion() {
return apiVersion;
}
/**
* Connects to the cluster specified by the
* <a href="/foundationdb/api-general.html#default-cluster-file" target="_blank">default fdb.cluster file</a>.
* <a href="/administration.html#default-cluster-file" target="_blank">default fdb.cluster file</a>.
* 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.
*
@ -199,9 +233,9 @@ public class FDB {
* {@link #startNetwork()} had been called.
*
* @param clusterFilePath the
* <a href="/foundationdb/api-general.html#foundationdb-cluster-file" target="_blank">cluster file</a>
* <a href="/administration.html#foundationdb-cluster-file" target="_blank">cluster file</a>
* defining the FoundationDB cluster. This can be {@code null} if the
* <a href="/foundationdb/api-general.html#default-cluster-file" target="_blank">default fdb.cluster file</a>
* <a href="/administration.html#default-cluster-file" target="_blank">default fdb.cluster file</a>
* is to be used.
*
* @return a {@code CompletableFuture} that will be set to a FoundationDB {@code Cluster}.
@ -220,9 +254,9 @@ public class FDB {
* are produced from using the resulting {@link Cluster}.
*
* @param clusterFilePath the
* <a href="/foundationdb/api-general.html#foundationdb-cluster-file" target="_blank">cluster file</a>
* <a href="/administration.html#foundationdb-cluster-file" target="_blank">cluster file</a>
* defining the FoundationDB cluster. This can be {@code null} if the
* <a href="/foundationdb/api-general.html#default-cluster-file" target="_blank">default fdb.cluster file</a>
* <a href="/administration.html#default-cluster-file" target="_blank">default fdb.cluster file</a>
* is to be used.
* @param e used to run the FDB network thread
*
@ -245,7 +279,7 @@ public class FDB {
/**
* Initializes networking, connects with the
* <a href="/foundationdb/api-general.html#default-cluster-file" target="_blank">default fdb.cluster file</a>,
* <a href="/administration.html#default-cluster-file" target="_blank">default fdb.cluster file</a>,
* and opens the database.
*
* @return a {@code CompletableFuture} that will be set to a FoundationDB {@link Database}
@ -259,9 +293,9 @@ public class FDB {
* and opens the database.
*
* @param clusterFilePath the
* <a href="/foundationdb/api-general.html#foundationdb-cluster-file" target="_blank">cluster file</a>
* <a href="/administration.html#foundationdb-cluster-file" target="_blank">cluster file</a>
* defining the FoundationDB cluster. This can be {@code null} if the
* <a href="/foundationdb/api-general.html#default-cluster-file" target="_blank">default fdb.cluster file</a>
* <a href="/administration.html#default-cluster-file" target="_blank">default fdb.cluster file</a>
* is to be used.
*
* @return a {@code CompletableFuture} that will be set to a FoundationDB {@link Database}
@ -275,9 +309,9 @@ public class FDB {
* and opens the database.
*
* @param clusterFilePath the
* <a href="/foundationdb/api-general.html#foundationdb-cluster-file" target="_blank">cluster file</a>
* <a href="/administration.html#foundationdb-cluster-file" target="_blank">cluster file</a>
* defining the FoundationDB cluster. This can be {@code null} if the
* <a href="/foundationdb/api-general.html#default-cluster-file" target="_blank">default fdb.cluster file</a>
* <a href="/administration.html#default-cluster-file" target="_blank">default fdb.cluster file</a>
* is to be used.
* @param e the {@link Executor} to use to execute asynchronous callbacks
*
@ -329,12 +363,14 @@ public class FDB {
* event loop is a blocking operation that is not
* expected to terminate until the program is complete. This will therefore consume an
* entire thread from {@code e} if {@code e} is a thread pool or will completely block
* operation of a single threaded {@code Executor}.<br>
* the single thread of a single-threaded {@code Executor}.<br>
* <br>
* Manual configuration of the networking engine can be achieved through calls on
* {@link NetworkOptions}. These options should be set before a call
* to this method.
*
* @param e the {@link Executor} to use to execute network operations on
*
* @see NetworkOptions
*
* @throws IllegalStateException if the network has already been stopped

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.
@ -32,7 +32,10 @@ import com.apple.foundationdb.tuple.ByteArrayUtil;
* {@link Transaction#getRange(KeySelector, KeySelector) getRange()}.<br>
* <br>
* For more about how key selectors work in practice, see
* <a href="/foundationdb/developer-guide.html#key-selectors" target="_blank">the KeySelector documentation</a>.
* <a href="/developer-guide.html#key-selectors" target="_blank">the KeySelector documentation</a>.
* Note that the way the key selectors are resolved is somewhat non-intuitive, so
* users who wish to use a key selector other than the default ones described below should
* probably consult that documentation before proceeding.
* <br>
* <br>
* Generally one of the following static methods should be used to construct a {@code KeySelector}:
@ -52,13 +55,25 @@ public class KeySelector {
/**
* Constructs a new {@code KeySelector} from the given parameters. Client code
* will not generally call this constructor.
* will not generally call this constructor. A key selector can be used to
* specify a key that will be resolved at runtime based on a starting key and
* an offset. When this is passed as an argument to a {@link Transaction}'s
* {@link Transaction#getKey(KeySelector) getKey()} or
* {@link Transaction#getRange(KeySelector, KeySelector) getRange()}
* methods, the key selector will be resolved to a key within the
* database. This is done in a manner equivalent to finding the last key that is
* less than (or less than or equal to, if {@code orEqual} is
* {@code true}) the base {@code key} specified here and then
* returning the key that is {@code offset} keys greater than that
* key.
*
* @param key the base key to reference
* @param orEqual <code>true</code> if the key should be considered for equality
* @param offset the number of keys to offset from once the key is found
* @param orEqual {@code true} if the key selector should resolve to
* {@code key} (if {@code key} is present) before accounting for the offset
* @param offset the offset (in number of keys) that the selector will advance after
* resolving to a key based on the {@code key} and {@code orEqual} parameters
*/
public KeySelector(byte[] key, boolean orEqual,int offset) {
public KeySelector(byte[] key, boolean orEqual, int offset) {
this.key = key;
this.orEqual = orEqual;
this.offset = offset;
@ -119,7 +134,7 @@ public class KeySelector {
* poor choice for iterating through a large range. (Instead, use the keys
* returned from a range query operation
* themselves to create a new beginning {@code KeySelector}.) For more information see
* <a href="/foundationdb/developer-guide.html#key-selectors" target="_blank">the KeySelector documentation</a>.
* <a href="/developer-guide.html#key-selectors" target="_blank">the KeySelector documentation</a>.
*
* @param offset the number of keys to offset the {@code KeySelector}. This number can be
* negative.
@ -157,7 +172,11 @@ public class KeySelector {
}
/**
* Returns the key offset for this {@code KeySelector}. For internal use.
* Returns the key offset parameter for this {@code KeySelector}. See
* the {@link #KeySelector(byte[], boolean, int) KeySelector constructor}
* for more details.
*
* @return the key offset for this {@code KeySelector}
*/
public int getOffset() {
return offset;

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.
@ -221,7 +221,7 @@ public class LocalityUtil {
@Override
protected void finalize() throws Throwable {
try {
if(FDB.getInstance().warnOnUnclosed && !closed) {
if(FDB.instance().warnOnUnclosed && !closed) {
System.err.println("CloseableAsyncIterator not closed (getBoundaryKeys)");
}
if(!closed) {

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.
@ -47,7 +47,7 @@ abstract class NativeObjectWrapper implements AutoCloseable {
public void checkUnclosed(String context) {
try {
if(FDB.getInstance().warnOnUnclosed && !closed) {
if(FDB.instance().warnOnUnclosed && !closed) {
System.err.println(context + " not closed");
}
}

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.

View File

@ -4,13 +4,13 @@
* 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.
@ -43,6 +43,7 @@ public interface ReadTransactionContext {
*
* @param retryable the block of logic to execute against a {@link ReadTransaction}
* in this context
* @param <T> the return type of {@code retryable}
*
* @return a result of the last call to {@code retryable}
*/
@ -56,6 +57,7 @@ public interface ReadTransactionContext {
*
* @param retryable the block of logic to execute against a {@link ReadTransaction}
* in this context
* @param <T> the return type of {@code retryable}
*
* @return a {@code CompletableFuture} that will be set to the value returned by the last call
* to {@code retryable}

View File

@ -4,13 +4,13 @@
* 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.
@ -34,12 +34,12 @@ import com.apple.foundationdb.tuple.Tuple;
* the underlying database if and when the transaction is committed. Read operations do see the
* effects of previous write operations on the same transaction. Committing a transaction usually
* succeeds in the absence of
* <a href="/foundationdb/developer-guide.html#transaction-conflicts" target="_blank">conflicts</a>.<br>
* <a href="/developer-guide.html#developer-guide-transaction-conflicts" target="_blank">conflicts</a>.<br>
* <br>
* Transactions group operations into a unit with the properties of atomicity, isolation, and
* durability. Transactions also provide the ability to maintain an application's invariants or
* integrity constraints, supporting the property of consistency. Together these properties are
* known as <a href="/foundationdb/developer-guide.html#acid" target="_blank">ACID</a>.<br>
* known as <a href="/developer-guide.html#acid" target="_blank">ACID</a>.<br>
* <br>
* Transactions are also causally consistent: once a transaction has been successfully committed,
* all subsequently created transactions will see the modifications made by it.
@ -49,7 +49,7 @@ import com.apple.foundationdb.tuple.Tuple;
* <br>
* Keys and values in FoundationDB are byte arrays. To encode other data types, see the
* {@link Tuple Tuple API} and
* <a href="/foundationdb/data-modeling.html#tuples" target="_blank">tuple layer documentation</a>.<br>
* <a href="/data-modeling.html#data-modeling-tuples" target="_blank">tuple layer documentation</a>.<br>
* <br>
* When used as a {@link TransactionContext}, the methods {@code run()} and
* {@code runAsync()} on a {@code Transaction} will simply attempt the operations
@ -79,11 +79,13 @@ public interface Transaction extends AutoCloseable, ReadTransaction, Transaction
/**
* Return special-purpose, read-only view of the database. Reads done through this interface are known as "snapshot reads".
* Snapshot reads selectively relax FoundationDB's isolation property, reducing
* <a href="/foundationdb/developer-guide.html#transaction-conflicts" target="_blank">Transaction conflicts</a>
* <a href="/developer-guide.html#transaction-conflicts" target="_blank">Transaction conflicts</a>
* but making reasoning about concurrency harder.<br>
* <br>
* For more information about how to use snapshot reads correctly, see
* <a href="/foundationdb/developer-guide.html#using-snapshot-reads" target="_blank">Using snapshot reads</a>.
* <a href="/developer-guide.html#using-snapshot-reads" target="_blank">Using snapshot reads</a>.
*
* @return a read-only view of this {@code Transaction} with relaxed isolation properties
*/
ReadTransaction snapshot();
@ -143,8 +145,9 @@ public interface Transaction extends AutoCloseable, ReadTransaction, Transaction
*
* @param key the key whose value is to be set
* @param value the value to set in the database
* @throws IllegalArgumentException
* @throws FDBException
*
* @throws IllegalArgumentException if {@code key} or {@code value} is {@code null}
* @throws FDBException if the set operation otherwise fails
*/
void set(byte[] key, byte[] value);
@ -153,8 +156,9 @@ public interface Transaction extends AutoCloseable, ReadTransaction, Transaction
* database until {@link #commit} is called.
*
* @param key the key whose value is to be cleared
* @throws IllegalArgumentException
* @throws FDBException
*
* @throws IllegalArgumentException if {@code key} is {@code null}
* @throws FDBException if clear operation otherwise fails
*/
void clear(byte[] key);
@ -167,8 +171,9 @@ public interface Transaction extends AutoCloseable, ReadTransaction, Transaction
*
* @param beginKey the first clear
* @param endKey the key one past the last key to clear
* @throws IllegalArgumentException
* @throws FDBException
*
* @throws IllegalArgumentException if {@code beginKey} or {@code endKey} is {@code null}
* @throws FDBException if the clear operation otherwise fails
*/
void clear(byte[] beginKey, byte[] endKey);
@ -181,7 +186,7 @@ public interface Transaction extends AutoCloseable, ReadTransaction, Transaction
*
* @param range the range of keys to clear
*
* @throws FDBException
* @throws FDBException if the clear operation fails
*/
void clear(Range range);
@ -191,7 +196,7 @@ public interface Transaction extends AutoCloseable, ReadTransaction, Transaction
*
* @param prefix the starting bytes from the keys to be cleared.
*
* @throws FDBException
* @throws FDBException if the clear-range operation fails
*/
@Deprecated
void clearRangeStartsWith(byte[] prefix);
@ -209,15 +214,15 @@ public interface Transaction extends AutoCloseable, ReadTransaction, Transaction
* read. It can only cause other transactions performing reads of the key
* to conflict.<br>
* <br>
* By combining these logical steps into a single, read-free operation,
* FoundationDB can guarantee that the transaction will not conflict due to
* the operation. This makes atomic operations ideal for operating on keys
* that are frequently modified. A common example is the use of a key-value
* pair as a counter.<br>
* <br>
* <b>Note:</b> If a transaction uses both an atomic operation and a serializable
* read on the same key, the benefits of using the atomic operation (for both
* conflict checking and performance) are lost.
* By combining these logical steps into a single, read-free operation,
* FoundationDB can guarantee that the transaction will not conflict due to
* the operation. This makes atomic operations ideal for operating on keys
* that are frequently modified. A common example is the use of a key-value
* pair as a counter.<br>
* <br>
* <b>Note:</b> If a transaction uses both an atomic operation and a serializable
* read on the same key, the benefits of using the atomic operation (for both
* conflict checking and performance) are lost.
*
* The behavior of each {@link MutationType} is documented at its definition.
*
@ -232,10 +237,7 @@ public interface Transaction extends AutoCloseable, ReadTransaction, Transaction
* {@code Database}'s {@link Database#run(Function) run()} calls for managing
* transactional access to FoundationDB.
*
* @return a {@code CompletableFuture} that, when set without error, guarantees the
* {@code Transaction}'s modifications committed durably to the
* database. If the commit failed, it will throw an {@link FDBException}.
* <br><br>
* <p>
* As with other client/server databases, in some failure scenarios a client may
* be unable to determine whether a transaction succeeded. In these cases, an
* {@link FDBException} will be thrown with error code {@code commit_unknown_result} (1021).
@ -243,11 +245,18 @@ public interface Transaction extends AutoCloseable, ReadTransaction, Transaction
* retry loops that don't specifically detect {@code commit_unknown_result} could end
* up executing a transaction twice. For more information, see the FoundationDB
* Developer Guide documentation.
* </p>
*
* If any operation is performed on a transaction after a commit has been
* <p>
* If any operation is performed on a transaction after a commit has been
* issued but before it has returned, both the commit and the operation will
* throw an error code {@code used_during_commit}(2017). In this case, all
* throw an error code {@code used_during_commit} (2017). In this case, all
* subsequent operations on this transaction will throw this error.
* </p>
*
* @return a {@code CompletableFuture} that, when set without error, guarantees the
* {@code Transaction}'s modifications committed durably to the
* database. If the commit failed, it will throw an {@link FDBException}.
*/
CompletableFuture<Void> commit();
@ -355,7 +364,10 @@ public interface Transaction extends AutoCloseable, ReadTransaction, Transaction
* Run a function once against this {@code Transaction}. This call blocks while
* user code is executing, returning the result of that code on completion.
*
* @return the return value of {@code retryable}
* @param retryable the block of logic to execute against this {@code Transaction}
* @param <T> the return type of {@code retryable}
*
* @return a result of the single call to {@code retryable}
*/
@Override
<T> T run(Function<? super Transaction, T> retryable);
@ -364,6 +376,9 @@ public interface Transaction extends AutoCloseable, ReadTransaction, Transaction
* Run a function once against this {@code Transaction}. This call returns
* immediately with a {@code CompletableFuture} handle to the result.
*
* @param retryable the block of logic to execute against this {@code Transaction}
* @param <T> the return type of {@code retryable}
*
* @return a {@code CompletableFuture} that will be set to the return value of {@code retryable}
*/
@Override

Some files were not shown because too many files have changed in this diff Show More