Merge branch 'public-master' into feature-redwood

# Conflicts:
#	fdbserver/DatabaseConfiguration.cpp
#	fdbserver/OldTLogServer.actor.cpp
#	fdbserver/fdbserver.vcxproj
#	fdbserver/fdbserver.vcxproj.filters
This commit is contained in:
Stephen Atherton 2018-04-24 17:22:21 -07:00
commit af61d3596d
320 changed files with 13119 additions and 14377 deletions

66
.clang-format Normal file
View File

@ -0,0 +1,66 @@
Language: Cpp
# BasedOnStyle: Mozilla
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: false
AlignOperands: true
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: true
BinPackArguments: true
BinPackParameters: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:|^ clang-format: ignore$|^TraceEvent'
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 2
ContinuationIndentWidth: 4
Cpp11BracedListStyle: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IndentCaseLabels: false
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: false
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
ReflowComments: true
SortIncludes: false
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 4
UseTab: ForIndentation

8
.gitignore vendored
View File

@ -6,8 +6,6 @@ bindings/flow/bin/
bindings/java/foundationdb-client*.jar
bindings/java/foundationdb-tests*.jar
bindings/java/fdb-java-*-sources.jar
bindings/nodejs/build/
bindings/nodejs/modules/
packaging/msi/FDBInstaller.msi
# Generated source, build, and packaging files
@ -16,7 +14,6 @@ packaging/msi/FDBInstaller.msi
*.g.S
*.g.asm
*.pom
bindings/go/src/fdb/generated.go
bindings/java/pom*.xml
bindings/java/src*/main/overview.html
bindings/java/src*/main/com/apple/foundationdb/*Options.java
@ -24,7 +21,6 @@ bindings/java/src*/main/com/apple/foundationdb/StreamingMode.java
bindings/java/src*/main/com/apple/foundationdb/MutationType.java
bindings/java/src*/main/com/apple/foundationdb/ConflictRangeType.java
bindings/java/src*/main/com/apple/foundationdb/FDBException.java
bindings/nodejs/package.json
bindings/python/fdb/fdb*options.py
bindings/python/dist/
bindings/python/setup.py
@ -52,12 +48,8 @@ bindings/go/godoc
bindings/java/.classstamp*
bindings/java/classes*/
bindings/java/javadoc*/
bindings/nodejs/fdb_node.stamp
bindings/nodejs/node_modules/
# Testing and logging
bindings/nodejs/fdb_node*.log
bindings/nodejs/npm-debug.log
packaging/msi/*.log
packaging/msi/obj
simfdb

71
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,71 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
education, socio-economic status, nationality, personal appearance, race,
religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at fdb-conduct@group.apple.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 1.4,
available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct.html](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html)

68
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,68 @@
# Contributing to FoundationDB
Welcome to the FoundationDB community, and thank you for contributing! The following guide outlines the basics of how to get involved.
If you have questions, we encourage you to engage in discussion on the [community forums](https://forums.foundationdb.org). Pull requests to update and expand this guide are also welcome.
#### Table of Contents
* [Before you get started](#before-you-get-started)
* [Community Guidelines](#community-guidelines)
* [Project Licensing](#project-licensing)
* [Governance and Decision Making](#governance-and-decision-making)
* [Contributing](#contributing)
* [Opening a Pull Request](#opening-a-pull-request)
* [Reporting Issues](#reporting-issues)
* [Project Communication](#project-communication)
* [Community Forums](#community-forums)
* [Using GitHub Issues and Community Forums](#using-github-issues-and-community-forums)
* [Project and Development Updates](#project-and-development-updates)
## Before you get started
### Community Guidelines
We want the FoundationDB community to be as welcoming and inclusive as possible, and have adopted a [Code of Conduct](CODE_OF_CONDUCT.md) that we ask all community members to read and observe.
### Project Licensing
By submitting a pull request, you represent that you have the right to license your contribution to Apple and the community, and agree by submitting the patch that your contributions are licensed under the Apache 2.0 license.
### Governance and Decision Making
At project launch, FoundationDB has a light governance structure. The intention is for the community to evolve quickly and adopt additional processes as participation grows. Stay tuned, and stay engaged! Your feedback is welcome.
We draw inspiration from the Apache Software Foundation's informal motto: ["community over code"](https://blogs.apache.org/foundation/entry/asf_15_community_over_code), and their emphasis on meritocratic rules. You'll also observe that some initial community structure is [inspired by the Swift community](https://swift.org/community/#community-structure).
The project technical lead is Ben Collins (bbc@apple.com).
Members of the Apple FoundationDB team are part of the initial core committers helping review individual contributions; you'll see them commenting on your pull requests. Future committers to the open source project, and the process for adding individuals in this role will be formalized in the future.
## Contributing
### Opening a Pull Request
We love pull requests! For minor changes, feel free to open up a PR directly. For larger feature development and any changes that may require community discussion, we ask that you discuss your ideas on the [community forums](https://forums.foundationdb.org) prior to opening a PR, and then reference that thread within your PR comment.
Upon release, no community CI is available. Tests can be run locally, and core committers will validate pull requests prior to merging them.
### Reporting issues
Please refer to the section below on [using GitHub issues and the community forums](#using-github-issues-and-community-forums) for more info.
#### Security issues
To report a security issue, please **DO NOT** start by filing a public issue or posting to the forums; instead send a private email to [fdb-oss-security@group.apple.com](mailto:fdb-oss-security@group.apple.com).
## Project Communication
### Community Forums
We encourage your participation asking questions and helping improve the FoundationDB project. Check out the [FoundationDB community forums](https://forums.foundationdb.org), which serve a similar function as mailing lists in many open source projects. The forums are organized into three sections:
* [Development](https://forums.foundationdb.org/c/development): For discussing the internals and development of the FoundationDB core, as well as layers.
* [Using FoundationDB](https://forums.foundationdb.org/c/using-foundationdb): For discussing user-facing topics. Getting started and have a question? This is the place for you.
* [Site Feedback](https://forums.foundationdb.org/c/site-feedback): A category for discussing the forums and the OSS project, its organization, how it works, and how we can improve it.
### Using GitHub Issues and Community Forums
GitHub issues and the community forums both offer features to facilitate discussion. To clarify how and when to use each tool, here's a quick summary of how we think about them:
GitHub Issues should be used for tracking tasks. If you know the specific code that needs to be changed, then it should go to GitHub Issues. Everything else should go to the Forums. For example:
* I am experiencing some weird behavior, which I think is a bug, but I don't know where exactly (mysteries and unexpected behaviors): *Forums*
* I see a bug in this piece of code: *GitHub Issues*
* Feature requests and design documents: *Forums*
* Implementing an agreed upon feature: *GitHub Issues*
### Project and Development Updates
Stay connected to the project and the community! For project and community updates, follow the [FoundationDB project blog](https://www.foundationdb.org/blog/). Development announcements will be made via the community forums' [dev-announce](https://forums.foundationdb.org/c/development/dev-announce) section.

6
FDBLibTLS/FDBLibTLS.map Normal file
View File

@ -0,0 +1,6 @@
{
global:
get_plugin;
local:
*;
};

View File

@ -0,0 +1 @@
_get_plugin

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|X64">
<Configuration>Debug</Configuration>
<Platform>X64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|X64">
<Configuration>Release</Configuration>
<Platform>X64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClInclude Include="FDBLibTLSPlugin.h" />
<ClCompile Include="FDBLibTLSPlugin.cpp" />
<ClInclude Include="FDBLibTLSPolicy.h" />
<ClCompile Include="FDBLibTLSPolicy.cpp" />
<ClInclude Include="FDBLibTLSSession.h" />
<ClCompile Include="FDBLibTLSSession.cpp" />
</ItemGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|X64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|X64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140_xp</PlatformToolset>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,50 @@
/*
* FDBLibTLSPlugin.cpp
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "boost/config.hpp"
#include "FDBLibTLSPlugin.h"
#include "FDBLibTLSPolicy.h"
#include <string.h>
FDBLibTLSPlugin::FDBLibTLSPlugin() {
// tls_init is not currently thread safe - caller's responsibility.
rc = tls_init();
}
FDBLibTLSPlugin::~FDBLibTLSPlugin() {
}
ITLSPolicy *FDBLibTLSPlugin::create_policy(ITLSLogFunc logf) {
if (rc < 0) {
// Log the failure from tls_init during our constructor.
logf("FDBLibTLSInitError", NULL, true, "LibTLSErrorMessage", "failed to initialize libtls", NULL);
return NULL;
}
return new FDBLibTLSPolicy(Reference<FDBLibTLSPlugin>::addRef(this), logf);
}
extern "C" BOOST_SYMBOL_EXPORT void *get_plugin(const char *plugin_type_name_and_version) {
if (strcmp(plugin_type_name_and_version, FDBLibTLSPlugin::get_plugin_type_name_and_version()) == 0) {
return new FDBLibTLSPlugin;
}
return NULL;
}

View File

@ -1,5 +1,5 @@
/*
* FdbError.h
* FDBLibTLSPlugin.h
*
* This source file is part of the FoundationDB open source project
*
@ -18,23 +18,26 @@
* limitations under the License.
*/
#ifndef FDB_LIBTLS_PLUGIN_H
#define FDB_LIBTLS_PLUGIN_H
#ifndef FDB_NODE_FDB_ERROR_H
#define FDB_NODE_FDB_ERROR_H
#pragma once
#include "Version.h"
#include "ITLSPlugin.h"
#include "ReferenceCounted.h"
#include <foundationdb/fdb_c.h>
#include <node.h>
#include <tls.h>
class FdbError {
public:
static v8::Handle<v8::Value> NewInstance(fdb_error_t code, const char *description);
struct FDBLibTLSPlugin : ITLSPlugin, ReferenceCounted<FDBLibTLSPlugin> {
FDBLibTLSPlugin();
virtual ~FDBLibTLSPlugin();
static void Init( v8::Handle<v8::Object> module );
virtual void addref() { ReferenceCounted<FDBLibTLSPlugin>::addref(); }
virtual void delref() { ReferenceCounted<FDBLibTLSPlugin>::delref(); }
private:
FdbError(); // not implemented by design
virtual ITLSPolicy *create_policy(ITLSLogFunc logf);
int rc;
};
#endif
#endif /* FDB_LIBTLS_PLUGIN_H */

View File

@ -0,0 +1,420 @@
/*
* FDBLibTLSPolicy.cpp
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "FDBLibTLSPolicy.h"
#include "FDBLibTLSSession.h"
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/objects.h>
#include <openssl/obj_mac.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <algorithm>
#include <exception>
#include <map>
#include <string>
#include <vector>
FDBLibTLSPolicy::FDBLibTLSPolicy(Reference<FDBLibTLSPlugin> plugin, ITLSLogFunc logf):
plugin(plugin), logf(logf), tls_cfg(NULL), session_created(false), cert_data_set(false),
key_data_set(false), verify_peers_set(false), verify_cert(true), verify_time(true) {
if ((tls_cfg = tls_config_new()) == NULL) {
logf("FDBLibTLSConfigError", NULL, true, NULL);
throw std::runtime_error("FDBLibTLSConfigError");
}
// Require client certificates for authentication.
tls_config_verify_client(tls_cfg);
// Name verification is always manually handled (if requested via configuration).
tls_config_insecure_noverifyname(tls_cfg);
}
FDBLibTLSPolicy::~FDBLibTLSPolicy() {
tls_config_free(tls_cfg);
}
ITLSSession* FDBLibTLSPolicy::create_session(bool is_client, TLSSendCallbackFunc send_func, void* send_ctx, TLSRecvCallbackFunc recv_func, void* recv_ctx, void* uid) {
session_created = true;
try {
return new FDBLibTLSSession(Reference<FDBLibTLSPolicy>::addRef(this), is_client, send_func, send_ctx, recv_func, recv_ctx, uid);
} catch ( ... ) {
return NULL;
}
}
static int hexValue(char c) {
static char const digits[] = "0123456789ABCDEF";
if (c >= 'a' && c <= 'f')
c -= ('a' - 'A');
int value = std::find(digits, digits + 16, c) - digits;
if (value >= 16) {
throw std::runtime_error("hexValue");
}
return value;
}
// Does not handle "raw" form (e.g. #28C4D1), only escaped text
static std::string de4514(std::string const& input, int start, int& out_end) {
std::string output;
if(input[start] == '#' || input[start] == ' ') {
out_end = start;
return output;
}
int space_count = 0;
for(int p = start; p < input.size();) {
switch(input[p]) {
case '\\': // Handle escaped sequence
// Backslash escaping nothing!
if(p == input.size() - 1) {
out_end = p;
goto FIN;
}
switch(input[p+1]) {
case ' ':
case '"':
case '#':
case '+':
case ',':
case ';':
case '<':
case '=':
case '>':
case '\\':
output += input[p+1];
p += 2;
space_count = 0;
continue;
default:
// Backslash escaping pair of hex digits requires two characters
if(p == input.size() - 2) {
out_end = p;
goto FIN;
}
try {
output += hexValue(input[p+1]) * 16 + hexValue(input[p+2]);
p += 3;
space_count = 0;
continue;
} catch( ... ) {
out_end = p;
goto FIN;
}
}
case '"':
case '+':
case ',':
case ';':
case '<':
case '>':
case 0:
// All of these must have been escaped
out_end = p;
goto FIN;
default:
// Character is what it is
output += input[p];
if(input[p] == ' ')
space_count++;
else
space_count = 0;
p++;
}
}
out_end = input.size();
FIN:
out_end -= space_count;
output.resize(output.size() - space_count);
return output;
}
static std::pair<std::string, std::string> splitPair(std::string const& input, char c) {
int p = input.find_first_of(c);
if(p == input.npos) {
throw std::runtime_error("splitPair");
}
return std::make_pair(input.substr(0, p), input.substr(p+1, input.size()));
}
static int abbrevToNID(std::string const& sn) {
int nid = NID_undef;
if (sn == "C" || sn == "CN" || sn == "L" || sn == "ST" || sn == "O" || sn == "OU")
nid = OBJ_sn2nid(sn.c_str());
if (nid == NID_undef)
throw std::runtime_error("abbrevToNID");
return nid;
}
void FDBLibTLSPolicy::parse_verify(std::string input) {
int s = 0;
while (s < input.size()) {
int eq = input.find('=', s);
if (eq == input.npos)
throw std::runtime_error("parse_verify");
std::string term = input.substr(s, eq - s);
if (term.find("Check.") == 0) {
if (eq + 2 > input.size())
throw std::runtime_error("parse_verify");
if (eq + 2 != input.size() && input[eq + 2] != ',')
throw std::runtime_error("parse_verify");
bool* flag;
if (term == "Check.Valid")
flag = &verify_cert;
else if (term == "Check.Unexpired")
flag = &verify_time;
else
throw std::runtime_error("parse_verify");
if (input[eq + 1] == '0')
*flag = false;
else if (input[eq + 1] == '1')
*flag = true;
else
throw std::runtime_error("parse_verify");
s = eq + 3;
} else {
std::map<int, std::string>* criteria = &subject_criteria;
if (term.find('.') != term.npos) {
auto scoped = splitPair(term, '.');
if (scoped.first == "S" || scoped.first == "Subject")
criteria = &subject_criteria;
else if (scoped.first == "I" || scoped.first == "Issuer")
criteria = &issuer_criteria;
else
throw std::runtime_error("parse_verify");
term = scoped.second;
}
int remain;
auto unesc = de4514(input, eq + 1, remain);
if (remain == eq + 1)
throw std::runtime_error("parse_verify");
criteria->insert(std::make_pair(abbrevToNID(term), unesc));
if (remain != input.size() && input[remain] != ',')
throw std::runtime_error("parse_verify");
s = remain + 1;
}
}
}
void FDBLibTLSPolicy::reset_verify() {
verify_cert = true;
verify_time = true;
subject_criteria = {};
issuer_criteria = {};
}
int password_cb(char *buf, int size, int rwflag, void *u) {
// A no-op password callback is provided simply to stop libcrypto
// from trying to use its own password reading functionality.
return 0;
}
bool FDBLibTLSPolicy::set_cert_data(const uint8_t* cert_data, int cert_len) {
struct stack_st_X509 *certs = NULL;
unsigned long errnum;
X509 *cert = NULL;
BIO *bio = NULL;
long data_len;
char *data;
bool rc = false;
// The cert data contains one or more PEM encoded certificates - the
// first certificate is for this host, with any additional certificates
// being the full certificate chain. As such, the last certificate
// is the trusted root certificate. If only one certificate is provided
// then it is required to be a self-signed certificate, which is also
// treated as the trusted root.
if (cert_data_set) {
logf("FDBLibTLSCertAlreadySet", NULL, true, NULL);
goto err;
}
if (session_created) {
logf("FDBLibTLSPolicyAlreadyActive", NULL, true, NULL);
goto err;
}
if ((certs = sk_X509_new_null()) == NULL) {
logf("FDBLibTLSOutOfMemory", NULL, true, NULL);
goto err;
}
if ((bio = BIO_new_mem_buf((void *)cert_data, cert_len)) == NULL) {
logf("FDBLibTLSOutOfMemory", NULL, true, NULL);
goto err;
}
ERR_clear_error();
while ((cert = PEM_read_bio_X509(bio, NULL, password_cb, NULL)) != NULL) {
if (!sk_X509_push(certs, cert)) {
logf("FDBLibTLSOutOfMemory", NULL, true, NULL);
goto err;
}
}
// Ensure that the NULL cert was caused by EOF and not some other failure.
errnum = ERR_peek_last_error();
if (ERR_GET_LIB(errnum) != ERR_LIB_PEM || ERR_GET_REASON(errnum) != PEM_R_NO_START_LINE) {
char errbuf[256];
ERR_error_string_n(errnum, errbuf, sizeof(errbuf));
logf("FDBLibTLSCertDataError", NULL, true, "LibcryptoErrorMessage", errbuf, NULL);
goto err;
}
if (sk_X509_num(certs) < 1) {
logf("FDBLibTLSNoCerts", NULL, true, NULL);
goto err;
}
BIO_free_all(bio);
if ((bio = BIO_new(BIO_s_mem())) == NULL) {
logf("FDBLibTLSOutOfMemory", NULL, true, NULL);
goto err;
}
if (!PEM_write_bio_X509(bio, sk_X509_value(certs, sk_X509_num(certs) - 1))) {
logf("FDBLibTLSCertWriteError", NULL, true, NULL);
goto err;
}
if ((data_len = BIO_get_mem_data(bio, &data)) <= 0) {
logf("FDBLibTLSCertError", NULL, true, NULL);
goto err;
}
if (tls_config_set_ca_mem(tls_cfg, (const uint8_t *)data, data_len) == -1) {
logf("FDBLibTLSSetCAError", NULL, true, "LibTLSErrorMessage", tls_config_error(tls_cfg), NULL);
goto err;
}
if (sk_X509_num(certs) > 1) {
BIO_free_all(bio);
if ((bio = BIO_new(BIO_s_mem())) == NULL) {
logf("FDBLibTLSOutOfMemory", NULL, true, NULL);
goto err;
}
for (int i = 0; i < sk_X509_num(certs) - 1; i++) {
if (!PEM_write_bio_X509(bio, sk_X509_value(certs, i))) {
logf("FDBLibTLSCertWriteError", NULL, true, NULL);
goto err;
}
}
if ((data_len = BIO_get_mem_data(bio, &data)) <= 0) {
logf("FDBLibTLSCertError", NULL, true, NULL);
goto err;
}
}
if (tls_config_set_cert_mem(tls_cfg, (const uint8_t *)data, data_len) == -1) {
logf("FDBLibTLSSetCertError", NULL, true, "LibTLSErrorMessage", tls_config_error(tls_cfg), NULL);
goto err;
}
rc = true;
err:
sk_X509_pop_free(certs, X509_free);
X509_free(cert);
BIO_free_all(bio);
return rc;
}
bool FDBLibTLSPolicy::set_key_data(const uint8_t* key_data, int key_len) {
if (key_data_set) {
logf("FDBLibTLSKeyAlreadySet", NULL, true, NULL);
return false;
}
if (session_created) {
logf("FDBLibTLSPolicyAlreadyActive", NULL, true, NULL);
return false;
}
if (tls_config_set_key_mem(tls_cfg, key_data, key_len) == -1) {
logf("FDBLibTLSKeyError", NULL, true, "LibTLSErrorMessage", tls_config_error(tls_cfg), NULL);
return false;
}
key_data_set = true;
return true;
}
bool FDBLibTLSPolicy::set_verify_peers(const uint8_t* verify_peers, int verify_peers_len) {
if (verify_peers_set) {
logf("FDBLibTLSVerifyPeersAlreadySet", NULL, true, NULL);
return false;
}
if (session_created) {
logf("FDBLibTLSPolicyAlreadyActive", NULL, true, NULL);
return false;
}
try {
parse_verify(std::string((const char*)verify_peers, verify_peers_len));
} catch ( const std::runtime_error& e ) {
reset_verify();
logf("FDBLibTLSVerifyPeersParseError", NULL, true, "Config", verify_peers, NULL);
return false;
}
if (!verify_cert)
tls_config_insecure_noverifycert(tls_cfg);
if (!verify_time)
tls_config_insecure_noverifytime(tls_cfg);
verify_peers_set = true;
return true;
}

View File

@ -0,0 +1,67 @@
/*
* FDBLibTLSPolicy.h
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FDB_LIBTLS_POLICY_H
#define FDB_LIBTLS_POLICY_H
#pragma once
#include "FDBLibTLSPlugin.h"
#include "ITLSPlugin.h"
#include "ReferenceCounted.h"
#include <map>
#include <string>
struct FDBLibTLSPolicy: ITLSPolicy, ReferenceCounted<FDBLibTLSPolicy> {
FDBLibTLSPolicy(Reference<FDBLibTLSPlugin> plugin, ITLSLogFunc logf);
virtual ~FDBLibTLSPolicy();
virtual void addref() { ReferenceCounted<FDBLibTLSPolicy>::addref(); }
virtual void delref() { ReferenceCounted<FDBLibTLSPolicy>::delref(); }
Reference<FDBLibTLSPlugin> plugin;
ITLSLogFunc logf;
virtual ITLSSession* create_session(bool is_client, TLSSendCallbackFunc send_func, void* send_ctx, TLSRecvCallbackFunc recv_func, void* recv_ctx, void* uid);
void parse_verify(std::string input);
void reset_verify(void);
virtual bool set_cert_data(const uint8_t* cert_data, int cert_len);
virtual bool set_key_data(const uint8_t* key_data, int key_len);
virtual bool set_verify_peers(const uint8_t* verify_peers, int verify_peers_len);
struct tls_config *tls_cfg;
bool session_created;
bool cert_data_set;
bool key_data_set;
bool verify_peers_set;
bool verify_cert;
bool verify_time;
std::map<int, std::string> subject_criteria;
std::map<int, std::string> issuer_criteria;
};
#endif /* FDB_LIBTLS_POLICY_H */

View File

@ -0,0 +1,275 @@
/*
* FDBLibTLSSession.cpp
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "FDBLibTLSSession.h"
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <exception>
#include <iostream>
#include <string.h>
#include <limits.h>
static ssize_t tls_read_func(struct tls *ctx, void *buf, size_t buflen, void *cb_arg)
{
FDBLibTLSSession *session = (FDBLibTLSSession *)cb_arg;
int rv = session->recv_func(session->recv_ctx, (uint8_t *)buf, buflen);
if (rv < 0)
return 0;
if (rv == 0)
return TLS_WANT_POLLIN;
return (ssize_t)rv;
}
static ssize_t tls_write_func(struct tls *ctx, const void *buf, size_t buflen, void *cb_arg)
{
FDBLibTLSSession *session = (FDBLibTLSSession *)cb_arg;
int rv = session->send_func(session->send_ctx, (const uint8_t *)buf, buflen);
if (rv < 0)
return 0;
if (rv == 0)
return TLS_WANT_POLLOUT;
return (ssize_t)rv;
}
FDBLibTLSSession::FDBLibTLSSession(Reference<FDBLibTLSPolicy> policy, bool is_client, TLSSendCallbackFunc send_func, void* send_ctx, TLSRecvCallbackFunc recv_func, void* recv_ctx, void* uid) :
tls_ctx(NULL), tls_sctx(NULL), policy(policy), send_func(send_func), send_ctx(send_ctx), recv_func(recv_func), recv_ctx(recv_ctx), handshake_completed(false), uid(uid) {
if (is_client) {
if ((tls_ctx = tls_client()) == NULL) {
policy->logf("FDBLibTLSClientError", uid, true, NULL);
throw std::runtime_error("FDBLibTLSClientError");
}
if (tls_configure(tls_ctx, policy->tls_cfg) == -1) {
policy->logf("FDBLibTLSConfigureError", uid, true, "LibTLSErrorMessage", tls_error(tls_ctx), NULL);
tls_free(tls_ctx);
throw std::runtime_error("FDBLibTLSConfigureError");
}
if (tls_connect_cbs(tls_ctx, tls_read_func, tls_write_func, this, NULL) == -1) {
policy->logf("FDBLibTLSConnectError", uid, true, "LibTLSErrorMessage", tls_error(tls_ctx), NULL);
tls_free(tls_ctx);
throw std::runtime_error("FDBLibTLSConnectError");
}
} else {
if ((tls_sctx = tls_server()) == NULL) {
policy->logf("FDBLibTLSServerError", uid, true, NULL);
throw std::runtime_error("FDBLibTLSServerError");
}
if (tls_configure(tls_sctx, policy->tls_cfg) == -1) {
policy->logf("FDBLibTLSConfigureError", uid, true, "LibTLSErrorMessage", tls_error(tls_sctx), NULL);
tls_free(tls_sctx);
throw std::runtime_error("FDBLibTLSConfigureError");
}
if (tls_accept_cbs(tls_sctx, &tls_ctx, tls_read_func, tls_write_func, this) == -1) {
policy->logf("FDBLibTLSAcceptError", uid, true, "LibTLSErrorMessage", tls_error(tls_sctx), NULL);
tls_free(tls_sctx);
throw std::runtime_error("FDBLibTLSAcceptError");
}
}
}
FDBLibTLSSession::~FDBLibTLSSession() {
// This would ideally call tls_close(), however that means either looping
// in a destructor or doing it opportunistically...
tls_free(tls_ctx);
tls_free(tls_sctx);
}
int password_cb(char *buf, int size, int rwflag, void *u);
bool match_criteria(X509_NAME *name, int nid, const char *value, size_t len) {
unsigned char *name_entry_utf8 = NULL, *criteria_utf8 = NULL;
int name_entry_utf8_len, criteria_utf8_len;
ASN1_STRING *criteria = NULL;
X509_NAME_ENTRY *name_entry;
BIO *bio;
bool rc = false;
int idx;
if ((criteria = ASN1_IA5STRING_new()) == NULL)
goto err;
if (ASN1_STRING_set(criteria, value, len) != 1)
goto err;
// If name does not exist, or has multiple of this RDN, refuse to proceed.
if ((idx = X509_NAME_get_index_by_NID(name, nid, -1)) < 0)
goto err;
if (X509_NAME_get_index_by_NID(name, nid, idx) != -1)
goto err;
if ((name_entry = X509_NAME_get_entry(name, idx)) == NULL)
goto err;
// Convert both to UTF8 and compare.
if ((criteria_utf8_len = ASN1_STRING_to_UTF8(&criteria_utf8, criteria)) < 1)
goto err;
if ((name_entry_utf8_len = ASN1_STRING_to_UTF8(&name_entry_utf8, name_entry->value)) < 1)
goto err;
if (criteria_utf8_len == name_entry_utf8_len &&
memcmp(criteria_utf8, name_entry_utf8, criteria_utf8_len) == 0)
rc = true;
err:
ASN1_STRING_free(criteria);
free(criteria_utf8);
free(name_entry_utf8);
return rc;
}
bool FDBLibTLSSession::check_criteria() {
X509_NAME *subject, *issuer;
const uint8_t *cert_pem;
size_t cert_pem_len;
X509 *cert = NULL;
BIO *bio = NULL;
bool rc = false;
// If certificate verification is disabled, there's nothing more to do.
if (!policy->verify_cert)
return true;
// If no criteria have been specified, then we're done.
if (policy->subject_criteria.size() == 0 && policy->issuer_criteria.size() == 0)
return true;
if ((cert_pem = tls_peer_cert_chain_pem(tls_ctx, &cert_pem_len)) == NULL) {
policy->logf("FDBLibTLSNoCertError", uid, true, NULL);
goto err;
}
if ((bio = BIO_new_mem_buf((void *)cert_pem, cert_pem_len)) == NULL) {
policy->logf("FDBLibTLSOutOfMemory", NULL, true, NULL);
goto err;
}
if ((cert = PEM_read_bio_X509(bio, NULL, password_cb, NULL)) == NULL) {
policy->logf("FDBLibTLSCertPEMError", uid, true, NULL);
goto err;
}
// Check subject criteria.
if ((subject = X509_get_subject_name(cert)) == NULL) {
policy->logf("FDBLibTLSCertSubjectError", uid, true, NULL);
goto err;
}
for (auto &pair: policy->subject_criteria) {
if (!match_criteria(subject, pair.first, pair.second.c_str(), pair.second.size())) {
policy->logf("FDBLibTLSCertSubjectMatchFailure", uid, true, NULL);
goto err;
}
}
// Check issuer criteria.
if ((issuer = X509_get_issuer_name(cert)) == NULL) {
policy->logf("FDBLibTLSCertIssuerError", uid, true, NULL);
goto err;
}
for (auto &pair: policy->issuer_criteria) {
if (!match_criteria(issuer, pair.first, pair.second.c_str(), pair.second.size())) {
policy->logf("FDBLibTLSCertIssuerMatchFailure", uid, true, NULL);
goto err;
}
}
// If we got this far, everything checked out...
rc = true;
err:
BIO_free_all(bio);
X509_free(cert);
return rc;
}
int FDBLibTLSSession::handshake() {
int rv = tls_handshake(tls_ctx);
switch (rv) {
case 0:
if (!check_criteria())
return FAILED;
handshake_completed = true;
return SUCCESS;
case TLS_WANT_POLLIN:
return WANT_READ;
case TLS_WANT_POLLOUT:
return WANT_WRITE;
default:
policy->logf("FDBLibTLSHandshakeError", uid, false, "LibTLSErrorMessage", tls_error(tls_ctx), NULL);
return FAILED;
}
}
int FDBLibTLSSession::read(uint8_t* data, int length) {
if (!handshake_completed) {
policy->logf("FDBLibTLSReadHandshakeError", uid, true, NULL);
return FAILED;
}
ssize_t n = tls_read(tls_ctx, data, length);
if (n > 0) {
if (n > INT_MAX) {
policy->logf("FDBLibTLSReadOverflow", uid, true, NULL);
return FAILED;
}
return (int)n;
}
if (n == 0) {
policy->logf("FDBLibTLSReadEOF", uid, false, NULL);
return FAILED;
}
if (n == TLS_WANT_POLLIN)
return WANT_READ;
if (n == TLS_WANT_POLLOUT)
return WANT_WRITE;
policy->logf("FDBLibTLSReadError", uid, false, "LibTLSErrorMessage", tls_error(tls_ctx), NULL);
return FAILED;
}
int FDBLibTLSSession::write(const uint8_t* data, int length) {
if (!handshake_completed) {
policy->logf("FDBLibTLSWriteHandshakeError", uid, true, NULL);
return FAILED;
}
ssize_t n = tls_write(tls_ctx, data, length);
if (n > 0) {
if (n > INT_MAX) {
policy->logf("FDBLibTLSWriteOverflow", uid, true, NULL);
return FAILED;
}
return (int)n;
}
if (n == 0) {
policy->logf("FDBLibTLSWriteEOF", uid, false, NULL);
return FAILED;
}
if (n == TLS_WANT_POLLIN)
return WANT_READ;
if (n == TLS_WANT_POLLOUT)
return WANT_WRITE;
policy->logf("FDBLibTLSWriteError", uid, false, "LibTLSErrorMessage", tls_error(tls_ctx), NULL);
return FAILED;
}

View File

@ -0,0 +1,61 @@
/*
* FDBLibTLSSession.h
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FDB_LIBTLS_SESSION_H
#define FDB_LIBTLS_SESSION_H
#pragma once
#include "ITLSPlugin.h"
#include "ReferenceCounted.h"
#include "FDBLibTLSPolicy.h"
#include <tls.h>
struct FDBLibTLSSession : ITLSSession, ReferenceCounted<FDBLibTLSSession> {
FDBLibTLSSession(Reference<FDBLibTLSPolicy> policy, bool is_client, TLSSendCallbackFunc send_func, void* send_ctx, TLSRecvCallbackFunc recv_func, void* recv_ctx, void* uid);
virtual ~FDBLibTLSSession();
virtual void addref() { ReferenceCounted<FDBLibTLSSession>::addref(); }
virtual void delref() { ReferenceCounted<FDBLibTLSSession>::delref(); }
bool check_criteria();
virtual int handshake();
virtual int read(uint8_t* data, int length);
virtual int write(const uint8_t* data, int length);
Reference<FDBLibTLSPolicy> policy;
struct tls *tls_ctx;
struct tls *tls_sctx;
TLSSendCallbackFunc send_func;
void* send_ctx;
TLSRecvCallbackFunc recv_func;
void* recv_ctx;
bool handshake_completed;
void* uid;
};
#endif /* FDB_LIBTLS_SESSION_H */

140
FDBLibTLS/ITLSPlugin.h Normal file
View File

@ -0,0 +1,140 @@
/*
* ITLSPlugin.h
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FDB_ITLSPLUGIN_H
#define FDB_ITLSPLUGIN_H
#pragma once
#include <stdint.h>
struct ITLSSession {
enum { SUCCESS = 0, WANT_READ = -1, WANT_WRITE = -2, FAILED = -3 };
virtual void addref() = 0;
virtual void delref() = 0;
// handshake should return SUCCESS if the handshake is complete,
// FAILED on fatal error, or one of WANT_READ or WANT_WRITE if the
// handshake should be reattempted after more data can be
// read/written on the underlying connection.
virtual int handshake() = 0;
// read should return the (non-zero) number of bytes read,
// WANT_READ or WANT_WRITE if the operation is blocked by the
// underlying stream, or FAILED if there is an error (including a
// closed connection).
virtual int read(uint8_t* data, int length) = 0;
// write should return the (non-zero) number of bytes written, or
// WANT_READ or WANT_WRITE if the operation is blocked by the
// underlying stream, or FAILED if there is an error.
virtual int write(const uint8_t* data, int length) = 0;
};
// Returns the number of bytes sent (possibly 0), or -1 on error
// (including connection close)
typedef int (*TLSSendCallbackFunc)(void* ctx, const uint8_t* buf, int len);
// Returns the number of bytes read (possibly 0), or -1 on error
// (including connection close)
typedef int (*TLSRecvCallbackFunc)(void* ctx, uint8_t* buf, int len);
struct ITLSPolicy {
virtual void addref() = 0;
virtual void delref() = 0;
// set_cert_data should import the provided certificate list and
// associate it with this policy. cert_data will point to a PEM
// encoded certificate list, ordered such that each certificate
// certifies the one before it.
//
// cert_data may additionally contain key information, which must
// be ignored.
//
// set_cert_data should return true if the operation succeeded,
// and false otherwise. After the first call to create_session for
// a given policy, set_cert_data should immediately return false
// if called.
virtual bool set_cert_data(const uint8_t* cert_data, int cert_len) = 0;
// set_key_data should import the provided private key and
// associate it with this policy. key_data will point to a PEM
// encoded key.
//
// key_data may additionally contain certificate information,
// which must be ignored.
//
// set_key_data should return true if the operation succeeded, and
// false otherwise. After the first call to create_session for a
// given policy, set_key_data should immediately return false if
// called.
virtual bool set_key_data(const uint8_t* key_data, int key_len) = 0;
// set_verify_peers should modify the validation rules for
// verifying a peer during connection handshake. The format of
// verify_peers is implementation specific.
//
// set_verify_peers should return true if the operation succeed,
// and false otherwise. After the first call to create_session for
// a given policy, set_verify_peers should immediately return
// false if called.
virtual bool set_verify_peers(const uint8_t* verify_peers, int verify_peers_len) = 0;
// create_session should return a new object that implements
// ITLSSession, associated with this policy. After the first call
// to create_session for a given policy, further calls to
// ITLSPolicy::set_* will fail and return false.
//
// The newly created session should use send_func and recv_func to
// send and receive data on the underlying transport, and must
// provide send_ctx/recv_ctx to the callbacks.
//
// uid should only be provided when invoking an ITLSLogFunc, which
// will use it to identify this session.
virtual ITLSSession* create_session(bool is_client, TLSSendCallbackFunc send_func, void* send_ctx, TLSRecvCallbackFunc recv_func, void* recv_ctx, void* uid ) = 0;
};
// Logs a message/error to the appropriate trace log.
//
// event must be a valid XML attribute value. uid may be NULL or the
// uid provided to ITLSPolicy::create_session by the caller. is_error
// should be true for errors and false for informational messages. The
// remaining arguments must be pairs of (const char*); the first of
// each pair must be a valid XML attribute name, and the second a
// valid XML attribute value. The final parameter must be NULL.
typedef void (*ITLSLogFunc)(const char* event, void* uid, bool is_error, ...);
struct ITLSPlugin {
virtual void addref() = 0;
virtual void delref() = 0;
// create_policy should return a new object that implements
// ITLSPolicy.
//
// The newly created policy, and any session further created from
// the policy, should use logf to log any messages or errors that
// occur.
virtual ITLSPolicy* create_policy( ITLSLogFunc logf ) = 0;
static inline const char* get_plugin_type_name_and_version() { return "ITLSPlugin"; }
};
#endif /* FDB_ITLSPLUGIN_H */

109
FDBLibTLS/Makefile Normal file
View File

@ -0,0 +1,109 @@
PROJECTPATH = $(dir $(realpath $(firstword $(MAKEFILE_LIST))))
PLUGINPATH = $(PROJECTPATH)/$(PLUGIN)
CFLAGS ?= -O2 -g
CXXFLAGS ?= -std=c++0x
CFLAGS += -I/usr/local/include
LDFLAGS += -L/usr/local/lib
LIBS += -ltls -lssl -lcrypto
PLATFORM := $(shell uname)
ifneq ($(PLATFORM),Darwin)
PLATFORM := $(shell uname -o)
endif
ifeq ($(PLATFORM),Cygwin)
HOST := x86_64-w64-mingw32
CC := $(HOST)-gcc
CXX := $(HOST)-g++
STRIP := $(HOST)-strip --strip-all
DYEXT = dll
PLUGINPATH = $(PLUGIN)
LIBS += -static-libstdc++ -static-libgcc
LIBS += -lws2_32
LINK_LDFLAGS = -shared
LINK_LDFLAGS += -Wl,-soname,$(PLUGIN)
LINK_LDFLAGS += -Wl,--version-script=FDBLibTLS.map
LINK_LDFLAGS += -Wl,-Bstatic $(LIBS) -Wl,-Bdynamic
else ifeq ($(PLATFORM),Darwin)
CC := clang
CXX := clang++
STRIP := strip -S -x
CFLAGS += -fPIC
DYEXT = dylib
vpath %.a /usr/local/lib
.LIBPATTERNS = lib%.a lib%.dylib lib%.so
LINK_LDFLAGS = -shared
LINK_LDFLAGS += -Wl,-exported_symbols_list,FDBLibTLS.symbols
LINK_LDFLAGS += -Wl,-dylib_install_name,$(PLUGIN)
LINK_LDFLAGS += $(LIBS)
else ifeq ($(PLATFORM),GNU/Linux)
CC := clang
CXX := clang++
STRIP := strip --strip-all
CFLAGS += -fPIC
DYEXT = so
LIBS += -static-libstdc++ -static-libgcc -lrt
LINK_LDFLAGS = -shared
LINK_LDFLAGS += -Wl,-soname,$(PLUGIN)
LINK_LDFLAGS += -Wl,--version-script=FDBLibTLS.map
LINK_LDFLAGS += -Wl,-Bstatic $(LIBS) -Wl,-Bdynamic
else
$(error Unknown platform $(PLATFORM))
endif
PLUGIN := FDBLibTLS.$(DYEXT)
OBJECTS := FDBLibTLSPlugin.o FDBLibTLSPolicy.o FDBLibTLSSession.o
LINKLINE := $(CXXFLAGS) $(CFLAGS) $(LDFLAGS) $(OBJECTS) $(LINK_LDFLAGS) -o $(PLUGIN)
all: $(PLUGIN)
build-depends-linux:
apt install clang make libboost-dev
clean:
@rm -f *.o *.d $(PLUGIN) plugin-test verify-test
@rm -rf *.dSYM
DEPS := $(patsubst %.o,%.d,$(OBJECTS))
-include $(DEPS)
$(OBJECTS): %.o: %.cpp Makefile
@echo "Compiling $<"
@$(CXX) $(CXXFLAGS) $(CFLAGS) $(INCLUDES) -c $< -o $@ -MD -MP
$(PLUGIN): $(OBJECTS) Makefile
@echo "Linking $@"
@$(CXX) $(LINKLINE)
@echo "Stripping $@"
@$(STRIP) $@
test: test-plugin test-verify
test-plugin: plugin-test.cpp $(PLUGIN) Makefile
@echo "Compiling plugin-test"
@$(CXX) $(CXXFLAGS) $(CFLAGS) plugin-test.cpp -ldl -o plugin-test
@echo "Running plugin-test..."
@$(PROJECTPATH)/plugin-test $(PLUGINPATH)
test-verify: verify-test.cpp $(OBJECTS) Makefile
@echo "Compiling verify-test"
@$(CXX) $(CXXFLAGS) $(CFLAGS) $(LDFLAGS) $(OBJECTS) verify-test.cpp $(LIBS) -o verify-test
@echo "Running verify-test..."
@$(PROJECTPATH)/verify-test

View File

@ -0,0 +1,108 @@
/*
* ReferenceCounted.h
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FDB_REFERENCE_COUNTED_H
#define FDB_REFERENCE_COUNTED_H
#pragma once
#include <stdlib.h>
template <class T>
struct ReferenceCounted {
void addref() { ++referenceCount; }
void delref() { if (--referenceCount == 0) { delete (T*)this; } }
ReferenceCounted() : referenceCount(1) {}
private:
ReferenceCounted(const ReferenceCounted&) = delete;
void operator=(const ReferenceCounted&) = delete;
int32_t referenceCount;
};
template <class P>
void addref(P* ptr) { ptr->addref(); }
template <class P>
void delref(P* ptr) { ptr->delref(); }
template <class P>
struct Reference {
Reference() : ptr(NULL) {}
explicit Reference( P* ptr ) : ptr(ptr) {}
static Reference<P> addRef( P* ptr ) { ptr->addref(); return Reference(ptr); }
Reference(const Reference& r) : ptr(r.getPtr()) { if (ptr) addref(ptr); }
Reference(Reference && r) : ptr(r.getPtr()) { r.ptr = NULL; }
template <class Q>
Reference(const Reference<Q>& r) : ptr(r.getPtr()) { if (ptr) addref(ptr); }
template <class Q>
Reference(Reference<Q> && r) : ptr(r.getPtr()) { r.setPtrUnsafe(NULL); }
~Reference() { if (ptr) delref(ptr); }
Reference& operator=(const Reference& r) {
P* oldPtr = ptr;
P* newPtr = r.ptr;
if (oldPtr != newPtr) {
if (newPtr) addref(newPtr);
ptr = newPtr;
if (oldPtr) delref(oldPtr);
}
return *this;
}
Reference& operator=(Reference&& r) {
P* oldPtr = ptr;
P* newPtr = r.ptr;
if (oldPtr != newPtr) {
r.ptr = NULL;
ptr = newPtr;
if (oldPtr) delref(oldPtr);
}
return *this;
}
void clear() {
P* oldPtr = ptr;
if (oldPtr) {
ptr = NULL;
delref(oldPtr);
}
}
P* operator->() const { return ptr; }
P& operator*() const { return *ptr; }
P* getPtr() const { return ptr; }
void setPtrUnsafe( P* p ) { ptr = p; }
P* extractPtr() { auto *p = ptr; ptr = NULL; return p; }
bool boolean_test() const { return ptr != 0; }
private:
P *ptr;
};
template <class P>
bool operator==( const Reference<P>& lhs, const Reference<P>& rhs ) {
return lhs.getPtr() == rhs.getPtr();
}
#endif /* FDB_REFERENCE_COUNTED_H */

11
FDBLibTLS/local.mk Normal file
View File

@ -0,0 +1,11 @@
FDBLibTLS_CFLAGS := -fPIC -I/usr/local/include -I$(BOOSTDIR)
FDBLibTLS_STATIC_LIBS := -ltls -lssl -lcrypto
FDBLibTLS_LDFLAGS := -L/usr/local/lib -static-libstdc++ -static-libgcc -lrt
FDBLibTLS_LDFLAGS += -Wl,-soname,FDBLibTLS.so -Wl,--version-script=FDBLibTLS/FDBLibTLS.map
# The plugin isn't a typical library, so it feels more sensible to have a copy
# of it in bin/.
bin/FDBLibTLS.$(DLEXT): lib/libFDBLibTLS.$(DLEXT)
@cp $< $@
TARGETS += bin/FDBLibTLS.$(DLEXT)

585
FDBLibTLS/plugin-test.cpp Normal file
View File

@ -0,0 +1,585 @@
/*
* plugin-test.cpp
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <exception>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <stdarg.h>
#include <dlfcn.h>
#include <boost/circular_buffer.hpp>
#include "ITLSPlugin.h"
#include "ReferenceCounted.h"
#include "FDBLibTLSPlugin.h"
#define TESTDATA "./testdata/"
static std::string load_file(std::string path)
{
std::ifstream fs(path);
std::stringstream ss;
ss << fs.rdbuf();
fs.close();
return ss.str();
}
struct FDBLibTLSClientServerTest {
FDBLibTLSClientServerTest(bool client_success, bool server_success, std::string client_path, std::string server_path, std::string client_verify, std::string server_verify):
client_success(client_success), server_success(server_success), client_verify(client_verify), server_verify(server_verify) {
client_data = load_file(TESTDATA + client_path);
server_data = load_file(TESTDATA + server_path);
}
~FDBLibTLSClientServerTest() {}
bool client_success;
bool server_success;
std::string client_data;
std::string client_verify;
std::string server_data;
std::string server_verify;
};
struct FDBLibTLSPluginTest {
FDBLibTLSPluginTest(Reference<ITLSPlugin> plugin, ITLSLogFunc logf);
~FDBLibTLSPluginTest();
Reference<ITLSPlugin> plugin;
ITLSLogFunc logf;
boost::circular_buffer<uint8_t> client_buffer;
boost::circular_buffer<uint8_t> server_buffer;
int circular_read(boost::circular_buffer<uint8_t> *cb, uint8_t* buf, int len);
int circular_write(boost::circular_buffer<uint8_t> *cb, const uint8_t* buf, int len);
int client_read(uint8_t* buf, int len);
int client_write(const uint8_t* buf, int len);
int server_read(uint8_t* buf, int len);
int server_write(const uint8_t* buf, int len);
Reference<ITLSPolicy> create_policy(void);
Reference<ITLSSession> create_client_session(Reference<ITLSPolicy> policy);
Reference<ITLSSession> create_server_session(Reference<ITLSPolicy> policy);
void circular_reset(void);
void circular_self_test(void);
int client_server_test(FDBLibTLSClientServerTest const& cst);
int set_cert_data_test(void);
};
FDBLibTLSPluginTest::FDBLibTLSPluginTest(Reference<ITLSPlugin> plugin, ITLSLogFunc logf) :
plugin(plugin), logf(logf)
{
circular_reset();
circular_self_test();
}
FDBLibTLSPluginTest::~FDBLibTLSPluginTest()
{
}
int FDBLibTLSPluginTest::circular_read(boost::circular_buffer<uint8_t> *cb, uint8_t* buf, int len)
{
int n = 0;
for (n = 0; n < len; n++) {
if (cb->empty())
break;
buf[n] = (*cb)[0];
cb->pop_front();
}
return n;
}
int FDBLibTLSPluginTest::circular_write(boost::circular_buffer<uint8_t> *cb, const uint8_t* buf, int len)
{
int n = 0;
for (n = 0; n < len; n++) {
if (cb->full())
break;
cb->push_back(buf[n]);
}
return n;
}
int FDBLibTLSPluginTest::client_read(uint8_t* buf, int len)
{
// Read bytes from the server from the client's buffer.
return circular_read(&client_buffer, buf, len);
}
int FDBLibTLSPluginTest::client_write(const uint8_t* buf, int len)
{
// Write bytes from the client into the server's buffer.
return circular_write(&server_buffer, buf, len);
}
int FDBLibTLSPluginTest::server_read(uint8_t* buf, int len)
{
// Read bytes from the client from the server's buffer.
return circular_read(&server_buffer, buf, len);
}
int FDBLibTLSPluginTest::server_write(const uint8_t* buf, int len)
{
// Write bytes from the server into the client's buffer.
return circular_write(&client_buffer, buf, len);
}
void FDBLibTLSPluginTest::circular_reset()
{
client_buffer = boost::circular_buffer<uint8_t>(1024);
server_buffer = boost::circular_buffer<uint8_t>(1024);
}
void FDBLibTLSPluginTest::circular_self_test()
{
uint8_t buf[1024] = {1, 2, 3};
std::cerr << "INFO: running circular buffer self tests...\n";
assert(server_read(buf, 3) == 0);
buf[0] = 1, buf[1] = 2, buf[2] = 3;
assert(client_write(buf, 2) == 2);
buf[0] = buf[1] = buf[2] = 255;
assert(server_read(buf, 3) == 2);
assert(buf[0] == 1 && buf[1] == 2 && buf[2] == 255);
assert(client_write(buf, 1024) == 1024);
assert(client_write(buf, 1) == 0);
assert(server_read(buf, 1) == 1);
assert(client_write(buf, 1) == 1);
assert(client_write(buf, 1) == 0);
assert(server_read(buf, 1024) == 1024);
assert(server_read(buf, 1024) == 0);
assert(client_read(buf, 3) == 0);
buf[0] = 1, buf[1] = 2, buf[2] = 3;
assert(server_write(buf, 2) == 2);
buf[0] = buf[1] = buf[2] = 255;
assert(client_read(buf, 3) == 2);
assert(buf[0] == 1 && buf[1] == 2 && buf[2] == 255);
assert(server_write(buf, 1024) == 1024);
assert(server_write(buf, 1) == 0);
assert(client_read(buf, 1) == 1);
assert(server_write(buf, 1) == 1);
assert(server_write(buf, 1) == 0);
assert(client_read(buf, 1024) == 1024);
assert(client_read(buf, 1024) == 0);
}
Reference<ITLSPolicy> FDBLibTLSPluginTest::create_policy(void)
{
return Reference<ITLSPolicy>(plugin->create_policy((ITLSLogFunc)logf));
}
static int client_send_func(void* ctx, const uint8_t* buf, int len) {
FDBLibTLSPluginTest *pt = (FDBLibTLSPluginTest *)ctx;
try {
return pt->client_write(buf, len);
} catch ( const std::runtime_error& e ) {
return -1;
}
}
static int client_recv_func(void* ctx, uint8_t* buf, int len) {
FDBLibTLSPluginTest *pt = (FDBLibTLSPluginTest *)ctx;
try {
return pt->client_read(buf, len);
} catch ( const std::runtime_error& e ) {
return -1;
}
}
Reference<ITLSSession> FDBLibTLSPluginTest::create_client_session(Reference<ITLSPolicy> policy)
{
return Reference<ITLSSession>(policy->create_session(true, client_send_func, this, client_recv_func, this, NULL));
}
static int server_send_func(void* ctx, const uint8_t* buf, int len) {
FDBLibTLSPluginTest *pt = (FDBLibTLSPluginTest *)ctx;
try {
return pt->server_write(buf, len);
} catch ( const std::runtime_error& e ) {
return -1;
}
}
static int server_recv_func(void* ctx, uint8_t* buf, int len) {
FDBLibTLSPluginTest *pt = (FDBLibTLSPluginTest *)ctx;
try {
return pt->server_read(buf, len);
} catch ( const std::runtime_error& e ) {
return -1;
}
}
Reference<ITLSSession> FDBLibTLSPluginTest::create_server_session(Reference<ITLSPolicy> policy)
{
return Reference<ITLSSession>(policy->create_session(false, server_send_func, this, server_recv_func, this, NULL));
}
int FDBLibTLSPluginTest::client_server_test(FDBLibTLSClientServerTest const& cst)
{
circular_reset();
Reference<ITLSPolicy> client_policy = create_policy();
if (!client_policy->set_cert_data((const uint8_t*)&cst.client_data[0], cst.client_data.size())) {
std::cerr << "FAIL: failed to set client cert data\n";
return 1;
}
if (!client_policy->set_key_data((const uint8_t*)&cst.client_data[0], cst.client_data.size())) {
std::cerr << "FAIL: failed to set client key data\n";
return 1;
}
if (!client_policy->set_verify_peers((const uint8_t*)&cst.client_verify[0], cst.client_verify.size())) {
std::cerr << "FAIL: failed to set client key data\n";
return 1;
}
Reference<ITLSPolicy> server_policy = create_policy();
if (!server_policy->set_cert_data((const uint8_t*)&cst.server_data[0], cst.server_data.size())) {
std::cerr << "FAIL: failed to set server cert data\n";
return 1;
}
if (!server_policy->set_key_data((const uint8_t*)&cst.server_data[0], cst.server_data.size())) {
std::cerr << "FAIL: failed to set server key data\n";
return 1;
}
if (!server_policy->set_verify_peers((const uint8_t*)&cst.server_verify[0], cst.server_verify.size())) {
std::cerr << "FAIL: failed to set client key data\n";
return 1;
}
Reference<ITLSSession> client_session = create_client_session(client_policy);
Reference<ITLSSession> server_session = create_server_session(server_policy);
if (client_session.getPtr() == NULL || server_session.getPtr() == NULL)
return 1;
std::cerr << "INFO: starting TLS handshake...\n";
bool client_done = false, server_done = false;
bool client_failed = false, server_failed = false;
int rc, i = 0;
do {
if (!client_done) {
rc = client_session->handshake();
if (rc == ITLSSession::SUCCESS) {
client_done = true;
} else if (rc == ITLSSession::FAILED) {
if (cst.client_success) {
std::cerr << "FAIL: failed to complete client handshake\n";
return 1;
} else {
std::cerr << "INFO: failed to complete client handshake (as expected)\n";
client_failed = true;
client_done = true;
}
} else if (rc != ITLSSession::WANT_READ && rc != ITLSSession::WANT_WRITE) {
std::cerr << "FAIL: client handshake returned unknown value: " << rc << "\n";
return 1;
}
}
if (!server_done) {
rc = server_session->handshake();
if (rc == ITLSSession::SUCCESS) {
server_done = true;
} else if (rc == ITLSSession::FAILED) {
if (cst.server_success) {
std::cerr << "FAIL: failed to complete server handshake\n";
return 1;
} else {
std::cerr << "INFO: failed to complete server handshake (as expected)\n";
server_failed = true;
server_done = true;
}
} else if (rc != ITLSSession::WANT_READ && rc != ITLSSession::WANT_WRITE) {
std::cerr << "FAIL: server handshake returned unknown value: " << rc << "\n";
return 1;
}
}
} while (i++ < 100 && (!client_done || !server_done));
if (!client_done || !server_done) {
std::cerr << "FAIL: failed to complete handshake\n";
return 1;
}
if (!cst.client_success && !client_failed)
std::cerr << "FAIL: client handshake succeeded when it should have failed\n";
if (!cst.server_success && !server_failed)
std::cerr << "FAIL: server handshake succeeded when it should have failed\n";
if (!cst.client_success || !cst.server_success)
return 0;
std::cerr << "INFO: handshake completed successfully\n";
//
// Write on client and read on server.
//
std::cerr << "INFO: starting client write test...\n";
std::string client_msg("FDBLibTLSPlugin Client Write Test");
std::string server_msg;
size_t cn = 0, sn = 0;
uint8_t buf[16];
client_done = false, server_done = false;
i = 0;
do {
if (!client_done) {
rc = client_session->write((const uint8_t*)&client_msg[cn], client_msg.size()-cn);
if (rc > 0) {
cn += rc;
if (cn >= client_msg.size())
client_done = true;
} else if (rc == ITLSSession::FAILED) {
std::cerr << "FAIL: failed to complete client write\n";
return 1;
} else if (rc != ITLSSession::WANT_READ && rc != ITLSSession::WANT_WRITE) {
std::cerr << "FAIL: client write returned unknown value: " << rc << "\n";
return 1;
}
}
if (!server_done) {
rc = server_session->read(buf, sizeof(buf));
if (rc > 0) {
sn += rc;
for (int j = 0; j < rc; j++)
server_msg += buf[j];
if (sn >= client_msg.size())
server_done = true;
} else if (rc == ITLSSession::FAILED) {
std::cerr << "FAIL: failed to complete server read\n";
return 1;
} else if (rc != ITLSSession::WANT_READ && rc != ITLSSession::WANT_WRITE) {
std::cerr << "FAIL: server read returned unknown value: " << rc << "\n";
return 1;
}
}
} while (i++ < 100 && (!client_done || !server_done));
if (client_msg != server_msg) {
std::cerr << "FAIL: got client msg '" << server_msg << "' want '" << client_msg << "'\n";
return 1;
}
std::cerr << "INFO: client write test completed successfully\n";
//
// Write on server and read on client.
//
std::cerr << "INFO: starting server write test...\n";
server_msg = "FDBLibTLSPlugin Server Write Test";
client_msg.clear();
cn = 0, sn = 0;
client_done = false, server_done = false;
i = 0;
do {
if (!server_done) {
rc = server_session->write((const uint8_t*)&server_msg[cn], server_msg.size()-cn);
if (rc > 0) {
cn += rc;
if (cn >= server_msg.size())
server_done = true;
} else if (rc == ITLSSession::FAILED) {
std::cerr << "FAIL: failed to complete server write\n";
return 1;
} else if (rc != ITLSSession::WANT_READ && rc != ITLSSession::WANT_WRITE) {
std::cerr << "FAIL: server write returned unknown value: " << rc << "\n";
return 1;
}
}
if (!client_done) {
rc = client_session->read(buf, sizeof(buf));
if (rc > 0) {
sn += rc;
for (int j = 0; j < rc; j++)
client_msg += buf[j];
if (sn >= server_msg.size())
client_done = true;
} else if (rc == ITLSSession::FAILED) {
std::cerr << "FAIL: failed to complete client read\n";
return 1;
} else if (rc != ITLSSession::WANT_READ && rc != ITLSSession::WANT_WRITE) {
std::cerr << "FAIL: client read returned unknown value: " << rc << "\n";
return 1;
}
}
} while (i++ < 100 && (!client_done || !server_done));
if (server_msg != client_msg) {
std::cerr << "FAIL: got server msg '" << client_msg << "' want '" << server_msg << "'\n";
return 1;
}
std::cerr << "INFO: server write test completed successfully\n";
return 0;
}
static void logf(const char* event, void* uid, int is_error, ...) {
va_list args;
std::string log_type ("INFO");
if (is_error)
log_type = "ERROR";
std::cerr << log_type << ": " << event;
va_start(args, is_error);
const char *s = va_arg(args, const char *);
while (s != NULL) {
std::cerr << " " << s;
s = va_arg(args, const char *);
}
std::cerr << "\n";
va_end(args);
}
int main(int argc, char **argv)
{
void *pluginSO = NULL;
void *(*getPlugin)(const char*);
int failed = 0;
if (argc != 2) {
std::cerr << "usage: " << argv[0] << " <plugin_path>\n";
exit(1);
}
pluginSO = dlopen(argv[1], RTLD_LAZY | RTLD_LOCAL);
if (pluginSO == NULL) {
std::cerr << "failed to load plugin '" << argv[1] << "': " << dlerror() << "\n";
exit(1);
}
getPlugin = (void*(*)(const char*))dlsym( pluginSO, "get_plugin" );
if (getPlugin == NULL) {
std::cerr << "plugin '" << argv[1] << "' does not provide get_plugin()\n";
exit(1);
}
Reference<ITLSPlugin> plugin = Reference<ITLSPlugin>((ITLSPlugin *)getPlugin(ITLSPlugin::get_plugin_type_name_and_version()));
std::vector<FDBLibTLSClientServerTest> tests = {
// Valid - all use single root CA.
FDBLibTLSClientServerTest(true, true, "test-1-client.pem", "test-1-server.pem", "", ""),
FDBLibTLSClientServerTest(true, true, "test-1-client.pem", "test-2-server.pem", "", ""),
FDBLibTLSClientServerTest(true, true, "test-2-client.pem", "test-2-server.pem", "", ""),
FDBLibTLSClientServerTest(true, true, "test-2-client.pem", "test-1-server.pem", "", ""),
// Certificates terminate at different intermediate CAs.
FDBLibTLSClientServerTest(false, false, "test-4-client.pem", "test-5-server.pem", "", ""),
FDBLibTLSClientServerTest(false, false, "test-5-client.pem", "test-4-server.pem", "", ""),
FDBLibTLSClientServerTest(true, true, "test-4-client.pem", "test-5-server.pem",
"Check.Valid=0", "Check.Valid=0"),
FDBLibTLSClientServerTest(true, true, "test-5-client.pem", "test-4-server.pem",
"Check.Valid=0", "Check.Valid=0"),
// Expired certificates.
FDBLibTLSClientServerTest(false, false, "test-1-client.pem", "test-3-server.pem", "", ""),
FDBLibTLSClientServerTest(false, false, "test-3-client.pem", "test-1-server.pem", "", ""),
FDBLibTLSClientServerTest(true, true, "test-1-client.pem", "test-3-server.pem", "Check.Unexpired=0", ""),
FDBLibTLSClientServerTest(true, true, "test-3-client.pem", "test-1-server.pem", "", "Check.Unexpired=0"),
FDBLibTLSClientServerTest(true, true, "test-1-client.pem", "test-3-server.pem", "Check.Valid=0", ""),
FDBLibTLSClientServerTest(true, true, "test-3-client.pem", "test-1-server.pem", "", "Check.Valid=0"),
// Match on specific subject and/or issuer.
FDBLibTLSClientServerTest(true, true, "test-1-client.pem", "test-1-server.pem", "C=US", ""),
FDBLibTLSClientServerTest(false, true, "test-1-client.pem", "test-2-server.pem", "C=US", ""),
FDBLibTLSClientServerTest(true, true, "test-1-client.pem", "test-2-server.pem", "C=AU", ""),
FDBLibTLSClientServerTest(true, true, "test-1-client.pem", "test-2-server.pem",
"CN=FDB LibTLS Plugin Test Server 2\\, \\80 \\<\\01\\+\\02=\\03\\>", ""),
FDBLibTLSClientServerTest(false, true, "test-1-client.pem", "test-2-server.pem",
"CN=FDB LibTLS Plugin Test Server 2\\, \\80 \\<\\01\\+\\02=\\04\\>", ""),
FDBLibTLSClientServerTest(false, true, "test-1-client.pem", "test-2-server.pem",
"CN=FDB LibTLS Plugin Test Server 2\\, \\81 \\<\\01\\+\\02=\\04\\>", ""),
FDBLibTLSClientServerTest(false, true, "test-1-client.pem", "test-2-server.pem",
"CN=FDB LibTLS Plugin Test Server 2\\, \\80 \\<\\01\\+\\02=\\04", ""),
FDBLibTLSClientServerTest(true, true, "test-1-client.pem", "test-2-server.pem",
"CN=FDB LibTLS Plugin Test Server 2\\, \\80 \\<\\01\\+\\02=\\03\\>",
"CN=FDB LibTLS Plugin Test Client 1"),
FDBLibTLSClientServerTest(true, true, "test-1-client.pem", "test-1-server.pem",
"", "CN=FDB LibTLS Plugin Test Client 1"),
FDBLibTLSClientServerTest(true, false, "test-2-client.pem", "test-1-server.pem",
"", "O=Apple Pty Limited,OU=FDC Team"),
FDBLibTLSClientServerTest(true, true, "test-2-client.pem", "test-1-server.pem",
"O=Apple Inc.,OU=FDB Team", "O=Apple Pty Limited,OU=FDB Team"),
FDBLibTLSClientServerTest(false, false, "test-2-client.pem", "test-1-server.pem",
"O=Apple Inc.,OU=FDC Team", "O=Apple Pty Limited,OU=FDC Team"),
FDBLibTLSClientServerTest(true, true, "test-1-client.pem", "test-1-server.pem",
"I.C=US,I.ST=California,I.L=Cupertino,I.O=Apple Inc.,I.OU=FDB Team",
"I.C=US,I.ST=California,I.L=Cupertino,I.O=Apple Inc.,I.OU=FDB Team"),
FDBLibTLSClientServerTest(false, false, "test-1-client.pem", "test-1-server.pem",
"I.C=US,I.ST=California,I.L=Cupertino,I.O=Apple Inc.,I.OU=FDC Team",
"I.C=US,I.ST=California,I.L=Cupertino,I.O=Apple Inc.,I.OU=FDC Team"),
FDBLibTLSClientServerTest(true, true, "test-1-client.pem", "test-1-server.pem",
"I.CN=FDB LibTLS Plugin Test Intermediate CA 1",
"I.CN=FDB LibTLS Plugin Test Intermediate CA 1"),
FDBLibTLSClientServerTest(false, true, "test-1-client.pem", "test-1-server.pem",
"I.CN=FDB LibTLS Plugin Test Intermediate CA 2",
"I.CN=FDB LibTLS Plugin Test Intermediate CA 1"),
FDBLibTLSClientServerTest(true, true, "test-1-client.pem", "test-2-server.pem",
"I.CN=FDB LibTLS Plugin Test Intermediate CA 2",
"I.CN=FDB LibTLS Plugin Test Intermediate CA 1"),
FDBLibTLSClientServerTest(true, true, "test-1-client.pem", "test-2-server.pem",
"CN=FDB LibTLS Plugin Test Server 2\\, \\80 \\<\\01\\+\\02=\\03\\>,I.CN=FDB LibTLS Plugin Test Intermediate CA 2",
"I.CN=FDB LibTLS Plugin Test Intermediate CA 1,O=Apple Inc.,I.C=US,S.C=US"),
FDBLibTLSClientServerTest(false, true, "test-1-client.pem", "test-2-server.pem",
"CN=FDB LibTLS Plugin Test Server 2\\, \\80 \\<\\01\\+\\02=\\03\\>,I.CN=FDB LibTLS Plugin Test Intermediate CA 1",
"I.CN=FDB LibTLS Plugin Test Intermediate CA 1,O=Apple Inc.,I.C=US,S.C=US"),
};
FDBLibTLSPluginTest *pt = new FDBLibTLSPluginTest(plugin, (ITLSLogFunc)logf);
int test_num = 1;
for (auto &test: tests) {
std::cerr << "== Test " << test_num++ << " ==\n";
failed |= pt->client_server_test(test);
}
delete pt;
return (failed);
}

View File

@ -0,0 +1,178 @@
#!/bin/sh
#
# make-tests-certs.sh
#
# This source file is part of the FoundationDB open source project
#
# Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
set -e
set -u
readonly SUBJECT="/C=US/ST=California/L=Cupertino/O=Apple Inc./OU=FDB Team/CN=FDB LibTLS Plugin Test"
readonly SUBJECT_ALT="/C=AU/ST=New South Wales/L=Sydney/O=Apple Pty Limited/OU=FDB Team/CN=FDB LibTLS Plugin Test"
readonly TMPDIR=$(mktemp -d)
cleanup() {
rm -rf "${TMPDIR}"
}
trap cleanup EXIT INT
make_bundle() {
local bundle_file=$1;
local key_file=$2;
shift 2;
printf '' > "${bundle_file}"
for f in $@; do
openssl x509 -nameopt oneline -subject -issuer -noout -in "${TMPDIR}/${f}" >> "${bundle_file}"
done
for f in $@; do
cat "${TMPDIR}/${f}" >> "${bundle_file}"
done
cat "${TMPDIR}/${key_file}" >> "${bundle_file}"
}
echo '100001' > "${TMPDIR}/certserial"
cat > "${TMPDIR}/openssl.cnf" <<EOF
[ca]
default_ca = fdb_test_ca
[req]
distinguished_name = req_distinguished_name
[req_distinguished_name]
[fdb_test_ca]
unique_subject = no
database = ${TMPDIR}/certindex
default_md = sha256
new_certs_dir = ${TMPDIR}/
policy = fdb_test_ca_policy
serial = ${TMPDIR}/certserial
[fdb_test_ca_policy]
[fdb_v3_ca]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, cRLSign, keyCertSign
[fdb_v3_other]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:false
keyUsage = critical, digitalSignature
EOF
# Root CA.
openssl req -new -days 3650 -nodes -newkey rsa:2048 -sha256 -x509 \
-subj "${SUBJECT} Root CA" -keyout "${TMPDIR}/ca-root.key" \
-config "${TMPDIR}/openssl.cnf" -extensions fdb_v3_ca \
-out "${TMPDIR}/ca-root.crt"
# Intermediate CA 1.
openssl req -new -days 3650 -nodes -newkey rsa:2048 -sha256 \
-subj "${SUBJECT} Intermediate CA 1" -keyout "${TMPDIR}/ca-int-1.key" \
-out "${TMPDIR}/ca-int-1.csr"
openssl x509 -req -days 3650 -CA "${TMPDIR}/ca-root.crt" -CAkey "${TMPDIR}/ca-root.key" \
-extfile "${TMPDIR}/openssl.cnf" -extensions fdb_v3_ca -days 3650 \
-CAcreateserial -in "${TMPDIR}/ca-int-1.csr" -out "${TMPDIR}/ca-int-1.crt"
# Intermediate CA 2.
openssl req -new -days 3650 -nodes -newkey rsa:2048 -sha256 \
-subj "${SUBJECT} Intermediate CA 2" -keyout "${TMPDIR}/ca-int-2.key" \
-out "${TMPDIR}/ca-int-2.csr"
openssl x509 -req -days 3650 -CA "${TMPDIR}/ca-root.crt" -CAkey "${TMPDIR}/ca-root.key" \
-extfile "${TMPDIR}/openssl.cnf" -extensions fdb_v3_ca -days 3650 \
-CAcreateserial -in "${TMPDIR}/ca-int-2.csr" -out "${TMPDIR}/ca-int-2.crt"
# Server 1.
openssl req -new -days 3650 -nodes -newkey rsa:2048 -sha256 \
-subj "${SUBJECT} Server 1" -keyout "${TMPDIR}/server-1.key" \
-out "${TMPDIR}/server-1.csr"
openssl x509 -req -days 3650 -CA "${TMPDIR}/ca-int-1.crt" -CAkey "${TMPDIR}/ca-int-1.key" \
-extfile "${TMPDIR}/openssl.cnf" -extensions fdb_v3_other -days 3650 \
-CAcreateserial -in "${TMPDIR}/server-1.csr" -out "${TMPDIR}/server-1.crt"
# Server 2.
openssl req -new -days 3650 -nodes -newkey rsa:2048 -sha256 \
-subj "$(printf "${SUBJECT_ALT} Server 2, \200 <\001+\002=\003>")" -keyout "${TMPDIR}/server-2.key" \
-out "${TMPDIR}/server-2.csr"
openssl x509 -req -days 3650 -CA "${TMPDIR}/ca-int-2.crt" -CAkey "${TMPDIR}/ca-int-2.key" \
-extfile "${TMPDIR}/openssl.cnf" -extensions fdb_v3_other \
-CAcreateserial -in "${TMPDIR}/server-2.csr" -out "${TMPDIR}/server-2.crt"
# Server 3 (expired).
openssl req -new -days 1 -nodes -newkey rsa:2048 -sha256 \
-subj "${SUBJECT} Server 3" -keyout "${TMPDIR}/server-3.key" \
-out "${TMPDIR}/server-3.csr"
cp /dev/null "${TMPDIR}/certindex"
printf "y\ny\n" | openssl ca -cert "${TMPDIR}/ca-int-1.crt" -keyfile "${TMPDIR}/ca-int-1.key" \
-startdate 20170101000000Z -enddate 20171231000000Z \
-config "${TMPDIR}/openssl.cnf" -notext \
-in "${TMPDIR}/server-3.csr" -out "${TMPDIR}/server-3.crt"
# Client 1.
openssl req -new -days 3650 -nodes -newkey rsa:2048 -sha256 \
-subj "${SUBJECT} Client 1" -keyout "${TMPDIR}/client-1.key" \
-out "${TMPDIR}/client-1.csr"
openssl x509 -req -days 3650 -CA "${TMPDIR}/ca-int-1.crt" -CAkey "${TMPDIR}/ca-int-1.key" \
-extfile "${TMPDIR}/openssl.cnf" -extensions fdb_v3_other \
-CAcreateserial -in "${TMPDIR}/client-1.csr" -out "${TMPDIR}/client-1.crt"
# Client 2.
openssl req -new -days 3650 -nodes -newkey rsa:2048 -sha256 \
-subj "$(printf "${SUBJECT_ALT} Client 2, \200 <\001+\002=\003>")" -keyout "${TMPDIR}/client-2.key" \
-out "${TMPDIR}/client-2.csr"
openssl x509 -req -days 3650 -CA "${TMPDIR}/ca-int-2.crt" -CAkey "${TMPDIR}/ca-int-2.key" \
-extfile "${TMPDIR}/openssl.cnf" -extensions fdb_v3_other \
-CAcreateserial -in "${TMPDIR}/client-2.csr" -out "${TMPDIR}/client-2.crt"
# Client 3 (expired).
openssl req -new -days 1 -nodes -newkey rsa:2048 -sha256 \
-subj "${SUBJECT} Client 3" -keyout "${TMPDIR}/client-3.key" \
-out "${TMPDIR}/client-3.csr"
cp /dev/null "${TMPDIR}/certindex"
printf "y\ny\n" | openssl ca -cert "${TMPDIR}/ca-int-1.crt" -keyfile "${TMPDIR}/ca-int-1.key" \
-startdate 20170101000000Z -enddate 20171231000000Z \
-config "${TMPDIR}/openssl.cnf" \
-in "${TMPDIR}/client-3.csr" -out "${TMPDIR}/client-3.crt"
#
# Test Bundles
#
make_bundle 'test-1-server.pem' 'server-1.key' 'server-1.crt' 'ca-int-1.crt' 'ca-root.crt'
make_bundle 'test-1-client.pem' 'client-1.key' 'client-1.crt' 'ca-int-1.crt' 'ca-root.crt'
make_bundle 'test-2-server.pem' 'server-2.key' 'server-2.crt' 'ca-int-2.crt' 'ca-root.crt'
make_bundle 'test-2-client.pem' 'client-2.key' 'client-2.crt' 'ca-int-2.crt' 'ca-root.crt'
# Expired client/server.
make_bundle 'test-3-client.pem' 'client-3.key' 'client-3.crt' 'ca-int-1.crt' 'ca-root.crt'
make_bundle 'test-3-server.pem' 'server-3.key' 'server-3.crt' 'ca-int-1.crt' 'ca-root.crt'
# Bundles that terminate at intermediate 1.
make_bundle 'test-4-server.pem' 'server-1.key' 'server-1.crt' 'ca-int-1.crt'
make_bundle 'test-4-client.pem' 'client-1.key' 'client-1.crt' 'ca-int-1.crt'
# Bundles that terminate at intermediate 2.
make_bundle 'test-5-server.pem' 'server-2.key' 'server-2.crt' 'ca-int-2.crt'
make_bundle 'test-5-client.pem' 'client-2.key' 'client-2.crt' 'ca-int-2.crt'

106
FDBLibTLS/testdata/test-1-client.pem vendored Normal file
View File

@ -0,0 +1,106 @@
subject= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Client 1
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Intermediate CA 1
subject= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Intermediate CA 1
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Root CA
subject= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Root CA
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Root CA
-----BEGIN CERTIFICATE-----
MIID/jCCAuagAwIBAgIJALOPTrQGpeslMA0GCSqGSIb3DQEBBQUAMIGRMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5v
MRMwEQYDVQQKDApBcHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTExMC8GA1UE
AwwoRkRCIExpYlRMUyBQbHVnaW4gVGVzdCBJbnRlcm1lZGlhdGUgQ0EgMTAeFw0x
ODA0MDcxNDE2MDJaFw0yODA0MDQxNDE2MDJaMIGIMQswCQYDVQQGEwJVUzETMBEG
A1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5vMRMwEQYDVQQKDApB
cHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTEoMCYGA1UEAwwfRkRCIExpYlRM
UyBQbHVnaW4gVGVzdCBDbGllbnQgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBALVkdxOmWcd959NyirJ1iz7q5fkjdRUV+88KMMehQWc3f50GJIQ+eZo+
7RhwVE+n8nd0i5iGfyY6LRuupdwoQUxoZ/5rUIDGKspNO62DVRW+tZqzpEa1+ub5
75BMoc7I7l9sXDkuiMu1OYcPNKMv4F3mf+B3ourLqjUekKlUv8XIZXAvN+R19HlR
FM8vs8rnhQXx7iWVP91frDvyD8G7lOf6R7R4homnB37kLom8WU+fCmcyA6em0qX0
JeVP6xk2qXU1cMs7DL8WftdrWHv+a73/l4hytQHo5OvtGaLZhpPYpC/FMSaFHVSM
irWSFK+ZtvaLi3LXc2HGANMokjPoRf8CAwEAAaNgMF4wHQYDVR0OBBYEFPtTL9KZ
jn49cLediy1ixz7AXOI3MB8GA1UdIwQYMBaAFCXTF7f83Hd7xm9gR+O4QrvjNo8Q
MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3DQEBBQUAA4IB
AQA17a4d/tSWIlTkIfkrXziD21+1OsN6/dUrWQK7kxtEe21QXIutccW4bwpM0JDB
M+bZiWkdgQ15+ZotX5UXlBcx9WWDU5RqSO06hhXu5b8gZwfVF4Od6tBdVxkn4KbU
0YujOZrL8fDOrQHqCO7nhNlYgcEn7bKF5wjtOoiKhtA9sLSIZQR5g32kkJXXGvcY
lLWMXygEg9FMQoldW9RHq4GbUiYEeqEq6k4S7cE03R1lvmQEOOAJ2S7LnaS4UHQT
GmW6uvLnJJrG4HB9JGE+y1e9M+C7Enzhi39RGd8ylignGimkdw/1UEWnvKGCqoU7
ufWGF7eUV8dCqO+jYghIY8rA
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEADCCAuigAwIBAgIJALOPTrQGpeshMA0GCSqGSIb3DQEBBQUAMIGHMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5v
MRMwEQYDVQQKDApBcHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTEnMCUGA1UE
AwweRkRCIExpYlRMUyBQbHVnaW4gVGVzdCBSb290IENBMB4XDTE4MDQwNzE0MTYw
MVoXDTI4MDQwNDE0MTYwMVowgZExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
Zm9ybmlhMRIwEAYDVQQHDAlDdXBlcnRpbm8xEzARBgNVBAoMCkFwcGxlIEluYy4x
ETAPBgNVBAsMCEZEQiBUZWFtMTEwLwYDVQQDDChGREIgTGliVExTIFBsdWdpbiBU
ZXN0IEludGVybWVkaWF0ZSBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAyOwdOcYcH3wYou13CchsXh3lLWA85E550tT6/WwDnslQjiMZHFrKvUT2
B8CUOR3Fr+4RG+cdw80rgojYEUuHKwmIGyjo5IotdaYbWzf6mvYThlIPPudCCkSU
CTtqPv8Oq4QdIpCxHdix0MINKu7c+qt1rUwnDFQSv/gHhVnNxT4r8pwVp6T4hwka
2YQaRNjzUuuFinMub0UtxnUX0rH8X5STlOSVn4Ksjo0OhQzsGEYDx86jVAXjgGcb
2CgGGctgq04hVrngP5ahT1Xeh9YycMlQJXsckJJBxfUJebIjANSRyzxI5fYt+ZkY
qoG5VLPREUQknxcpbT7Rsj0n+k0RhwIDAQABo2MwYTAdBgNVHQ4EFgQUJdMXt/zc
d3vGb2BH47hCu+M2jxAwHwYDVR0jBBgwFoAUnqtGja3O5jGlh5vHgp3Tf8NCPKkw
DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQAD
ggEBAGwW7bRqB7aYUGsD1MOE9d5slp6Iw6wKyNLdg+mzoV+iCV2ZM7ejNRButiAy
vPOxSQwXcibLm/g599e+LY1TiI1XXPbL2bFnTcnThqpHHFe+eRrDgqxO8qJyrcBp
EfyMCJWq7jFg4bWoYTpLeC/RAKyi9fxlqY1NzQCp1bG3LiaDJ5VJd4uwkgX2a0yN
3e0XEFNi7r4u4IHejwFjKWrDg8sstjbY+XOYC4EVQyUsbzeKZKSqnOdR2Jv1QZHH
5O24G/efIFpsA6MVUOfRk0eq0RfKX7CdHn2a5p8aC6E6YMDhXL6xo146n49t9sYD
HMUnfG6AEboTBa/l+zwCG/u4f/Y=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIID9jCCAt6gAwIBAgIJALfRa36cuemYMA0GCSqGSIb3DQEBCwUAMIGHMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5v
MRMwEQYDVQQKDApBcHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTEnMCUGA1UE
AwweRkRCIExpYlRMUyBQbHVnaW4gVGVzdCBSb290IENBMB4XDTE4MDQwNzE0MTYw
MVoXDTI4MDQwNDE0MTYwMVowgYcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
Zm9ybmlhMRIwEAYDVQQHDAlDdXBlcnRpbm8xEzARBgNVBAoMCkFwcGxlIEluYy4x
ETAPBgNVBAsMCEZEQiBUZWFtMScwJQYDVQQDDB5GREIgTGliVExTIFBsdWdpbiBU
ZXN0IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/J+sL
7POoXNdzYRsMZCI5juxMPOVue5vU2QPU9z/PHBsBICX6tVsCnkzk5CLdM6TxofgX
F+MqRKxtcIqxBcKjjVecJlqHuNY+jS2r8UjcoQm+EQ5RsBWu8yaSnXIiZTccQNjB
5T2awwt9Ptbn946MZfq6oEnn4ZPByu9/nCrlk7QXTkuGdpTnC6paQWt/lVxZfELM
i0g76/K/f3e2Lv9UCvlxKOwFMye9XjwF3ekEmUuio5JZEdn+LIs9zB1zehFhGlYB
TUXnkZ0LTOPbH9OxsOli04n31/n7UbYq1BSuoiXx5A2eHOunMppa0NDg7oXmDSKE
A1zo+QtIu1YPXaLdAgMBAAGjYzBhMB0GA1UdDgQWBBSeq0aNrc7mMaWHm8eCndN/
w0I8qTAfBgNVHSMEGDAWgBSeq0aNrc7mMaWHm8eCndN/w0I8qTAPBgNVHRMBAf8E
BTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAIOw1jC39
VW+1fqGT+n44Y6Oh66lAowIvi/BEOW1I4iPAjkr0g6FbbdKeq0VLL7aMMu+q/AOv
UETv7MdVh9xjTLqWZGN0R3Lr/n6ButI3E7MLKL5ByLNCoOhF42aBLINkpKSNFRrQ
40iNoHm3BaNRLKS7poCk5HFkEMjvxdQ1AenNbUa21DTh7y9arHF4CPfi8Ity29jW
ED8jYK/+bWIaO+YhGkRh8UuD3o5WnOti+9QK56qxkPtkqVTh9vMVHfD0DgVeLvMN
nZpTplLTfhjzyFJELwE/U+HJ6KIslmqwarJ1Sla+1gHCmJEbzbsrnb6bLtrHtXCZ
XvmR6B5iRkDVpw==
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC1ZHcTplnHfefT
coqydYs+6uX5I3UVFfvPCjDHoUFnN3+dBiSEPnmaPu0YcFRPp/J3dIuYhn8mOi0b
rqXcKEFMaGf+a1CAxirKTTutg1UVvrWas6RGtfrm+e+QTKHOyO5fbFw5LojLtTmH
DzSjL+Bd5n/gd6Lqy6o1HpCpVL/FyGVwLzfkdfR5URTPL7PK54UF8e4llT/dX6w7
8g/Bu5Tn+ke0eIaJpwd+5C6JvFlPnwpnMgOnptKl9CXlT+sZNql1NXDLOwy/Fn7X
a1h7/mu9/5eIcrUB6OTr7Rmi2YaT2KQvxTEmhR1UjIq1khSvmbb2i4ty13NhxgDT
KJIz6EX/AgMBAAECggEAEm2Mc2CZCl1OKfsfABZU+SVgC7mAcY30MQp1/jHxtQy8
WDWBjDXUoMj3yV3QEu+bAGvEqtAvJrEOWBucGgu05pBM0FoSqaJ4QmkqQOxwvm7L
gFXzwINIZCLMJbrDTYC4RtV5YQ3LM/bLS19OF64Lez6piyJcWMIsHo1mYO2NNgiD
7f1x1uQw46Q0YHWeoHY58MPfmgfKsqnJDWc8cCuU9fJOWeU4dVrfW8dh9WVAoLZ7
qAM5vvap11Qk8RXaRnmLjxN6H1M7iVNfcLVNKfG6XOBBepYjZr/qMkuN3ONuqBHl
fC3Zia2zQZRfiuPspX0KhjCfYAKbIZC6oyrQM2uXgQKBgQDoD5voZiCOeGXJEMUk
9JV4V8A96aE0xxy+OHMogVpysxBO4V0Nh0krSLTt9NXnpjawZQ+3pLQ4+2J2XM2e
fJuJJ7Z+Mhjv6epnMM7FoxK1VF7oe+LE7Yk/kg/moCuVS/XhLdQrhZVBJhfEADS3
oFybf7Q6rJYtN3OYsiFymyneHwKBgQDIGsY5kGdmx27LS5rPMwdw632TF8G5BGbu
C3ty7LYkOWb/9/V4cuWjW4eLJQqCWbJQrzOvg0coxwXLUuEQik+IP2IkF0YlRS43
VJuULwOxi3Cbj51RoapHhmYTO9fe2A1N9oJMAqEUHY1q/r9txPcguRWyuH2Yv9Ih
OzHnc2DcIQKBgQCGW0MxMq/2zM5hs0vxMYq4ulWbgwDKxd1mZNiHwxzS+8mdYe22
P3WlkdrvSqnuDNXtGxYWhU2zEBjZ3rFN6WdD6bJHLkox3YTRafjNhLT4N3kbsV6C
FeU44SBDrsiNEAWz8gy9hgH8TknEOTpMdpQnk7CNqA7q7wgGiFvFNwDukQKBgG7i
R03Gs0XE5aRJtPN0N39fPyqvU24O/mqSekno2dWg6W6WHLQuFwo6whVc5UHuKl2D
eISdnmT+RDuzJXxg6El7tgqByyEEAOQwQjYPB2Du/+tz3Z1KlG0mEJI/6xNVbany
G6m7Gz9mUOMlXzaYmsjLRzbN/OsUAIDhqHm0+cuBAoGAZCND80akS3xr3yC87GyX
aA0RoHXbdB6dbP8Y6XYDXR4QFIA4kXwY5cCLaZA/0hP5FOzDhORmaoaPM8vUdNyb
IYvbw2H6tODiU5oICWY6+HQQ2nXikucI4HDYDLbsiV2htZkEmBYWLilYq0Tb8jC5
u+ehIIvZYLqKaY1GaKmF86A=
-----END PRIVATE KEY-----

106
FDBLibTLS/testdata/test-1-server.pem vendored Normal file
View File

@ -0,0 +1,106 @@
subject= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Server 1
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Intermediate CA 1
subject= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Intermediate CA 1
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Root CA
subject= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Root CA
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Root CA
-----BEGIN CERTIFICATE-----
MIID/jCCAuagAwIBAgIJALOPTrQGpesjMA0GCSqGSIb3DQEBBQUAMIGRMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5v
MRMwEQYDVQQKDApBcHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTExMC8GA1UE
AwwoRkRCIExpYlRMUyBQbHVnaW4gVGVzdCBJbnRlcm1lZGlhdGUgQ0EgMTAeFw0x
ODA0MDcxNDE2MDJaFw0yODA0MDQxNDE2MDJaMIGIMQswCQYDVQQGEwJVUzETMBEG
A1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5vMRMwEQYDVQQKDApB
cHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTEoMCYGA1UEAwwfRkRCIExpYlRM
UyBQbHVnaW4gVGVzdCBTZXJ2ZXIgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBAJp26QAmlMusO7C8Py/I117r3kHvB+My5kIrj8g9sKpktwTzmsJGpvJU
EaKISEdBsJHLGnZJhwIhr/+MG4WDEM4oFNCtBQZznV3wjIQWq1w4IO8/f3+nBPpW
f14fjs1E911Uo/ZOL9bxvh1SIHkS6itgJi+tgVPx7C3s3W3mC5nU3omsE+Rx4DDm
KUq1kyN1ELBIAceQ4wTmQ5B8dv6MSW7zt8Jdrhfhg2GJIPPB6XUZJ2yIOvgu55GW
J5sMPa0uNDfCsWJ37fzFm+XJ/D96t7x8I49IyfzbIgcU9JYFlcqkryvKh5IpQGGm
H/I6adIWa5xWpMhB2PA6kgtDD07Hu2sCAwEAAaNgMF4wHQYDVR0OBBYEFJ7S+FUz
9ngzH/TNPVeM/cE7LeBGMB8GA1UdIwQYMBaAFCXTF7f83Hd7xm9gR+O4QrvjNo8Q
MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3DQEBBQUAA4IB
AQAx6WHwikVFAH0TRYCznwO6He+0t2pnlyfrI+24N28tzupMSrRPs086UbLgHLz1
lbkYdheeOkLPzjWi5vfymL1Oua3E2iAXWEpMb4Sg7E5SVHp9yt6gZ0DTVwR+Gcu7
uooroidAG3OFeOXL5ivU5J5ipaoEAiLprpKxtPzo4z/TxIqw3kJISC56qw9VTJNQ
TQZvneUecykdIZuH61ih0cJLe5WRkEs/63Dgl8TBYiVDbvBSGRbsXoAXcspVlc2x
XOLey5IVJ4/TH5ZBobShC6J1KrjZTNYvUgc44CocOgrc0ePPiQzB7JXxR1H8ATGl
yKjWqT2PkrfHmjdcmsi2GIVt
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEADCCAuigAwIBAgIJALOPTrQGpeshMA0GCSqGSIb3DQEBBQUAMIGHMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5v
MRMwEQYDVQQKDApBcHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTEnMCUGA1UE
AwweRkRCIExpYlRMUyBQbHVnaW4gVGVzdCBSb290IENBMB4XDTE4MDQwNzE0MTYw
MVoXDTI4MDQwNDE0MTYwMVowgZExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
Zm9ybmlhMRIwEAYDVQQHDAlDdXBlcnRpbm8xEzARBgNVBAoMCkFwcGxlIEluYy4x
ETAPBgNVBAsMCEZEQiBUZWFtMTEwLwYDVQQDDChGREIgTGliVExTIFBsdWdpbiBU
ZXN0IEludGVybWVkaWF0ZSBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAyOwdOcYcH3wYou13CchsXh3lLWA85E550tT6/WwDnslQjiMZHFrKvUT2
B8CUOR3Fr+4RG+cdw80rgojYEUuHKwmIGyjo5IotdaYbWzf6mvYThlIPPudCCkSU
CTtqPv8Oq4QdIpCxHdix0MINKu7c+qt1rUwnDFQSv/gHhVnNxT4r8pwVp6T4hwka
2YQaRNjzUuuFinMub0UtxnUX0rH8X5STlOSVn4Ksjo0OhQzsGEYDx86jVAXjgGcb
2CgGGctgq04hVrngP5ahT1Xeh9YycMlQJXsckJJBxfUJebIjANSRyzxI5fYt+ZkY
qoG5VLPREUQknxcpbT7Rsj0n+k0RhwIDAQABo2MwYTAdBgNVHQ4EFgQUJdMXt/zc
d3vGb2BH47hCu+M2jxAwHwYDVR0jBBgwFoAUnqtGja3O5jGlh5vHgp3Tf8NCPKkw
DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQAD
ggEBAGwW7bRqB7aYUGsD1MOE9d5slp6Iw6wKyNLdg+mzoV+iCV2ZM7ejNRButiAy
vPOxSQwXcibLm/g599e+LY1TiI1XXPbL2bFnTcnThqpHHFe+eRrDgqxO8qJyrcBp
EfyMCJWq7jFg4bWoYTpLeC/RAKyi9fxlqY1NzQCp1bG3LiaDJ5VJd4uwkgX2a0yN
3e0XEFNi7r4u4IHejwFjKWrDg8sstjbY+XOYC4EVQyUsbzeKZKSqnOdR2Jv1QZHH
5O24G/efIFpsA6MVUOfRk0eq0RfKX7CdHn2a5p8aC6E6YMDhXL6xo146n49t9sYD
HMUnfG6AEboTBa/l+zwCG/u4f/Y=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIID9jCCAt6gAwIBAgIJALfRa36cuemYMA0GCSqGSIb3DQEBCwUAMIGHMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5v
MRMwEQYDVQQKDApBcHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTEnMCUGA1UE
AwweRkRCIExpYlRMUyBQbHVnaW4gVGVzdCBSb290IENBMB4XDTE4MDQwNzE0MTYw
MVoXDTI4MDQwNDE0MTYwMVowgYcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
Zm9ybmlhMRIwEAYDVQQHDAlDdXBlcnRpbm8xEzARBgNVBAoMCkFwcGxlIEluYy4x
ETAPBgNVBAsMCEZEQiBUZWFtMScwJQYDVQQDDB5GREIgTGliVExTIFBsdWdpbiBU
ZXN0IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/J+sL
7POoXNdzYRsMZCI5juxMPOVue5vU2QPU9z/PHBsBICX6tVsCnkzk5CLdM6TxofgX
F+MqRKxtcIqxBcKjjVecJlqHuNY+jS2r8UjcoQm+EQ5RsBWu8yaSnXIiZTccQNjB
5T2awwt9Ptbn946MZfq6oEnn4ZPByu9/nCrlk7QXTkuGdpTnC6paQWt/lVxZfELM
i0g76/K/f3e2Lv9UCvlxKOwFMye9XjwF3ekEmUuio5JZEdn+LIs9zB1zehFhGlYB
TUXnkZ0LTOPbH9OxsOli04n31/n7UbYq1BSuoiXx5A2eHOunMppa0NDg7oXmDSKE
A1zo+QtIu1YPXaLdAgMBAAGjYzBhMB0GA1UdDgQWBBSeq0aNrc7mMaWHm8eCndN/
w0I8qTAfBgNVHSMEGDAWgBSeq0aNrc7mMaWHm8eCndN/w0I8qTAPBgNVHRMBAf8E
BTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAIOw1jC39
VW+1fqGT+n44Y6Oh66lAowIvi/BEOW1I4iPAjkr0g6FbbdKeq0VLL7aMMu+q/AOv
UETv7MdVh9xjTLqWZGN0R3Lr/n6ButI3E7MLKL5ByLNCoOhF42aBLINkpKSNFRrQ
40iNoHm3BaNRLKS7poCk5HFkEMjvxdQ1AenNbUa21DTh7y9arHF4CPfi8Ity29jW
ED8jYK/+bWIaO+YhGkRh8UuD3o5WnOti+9QK56qxkPtkqVTh9vMVHfD0DgVeLvMN
nZpTplLTfhjzyFJELwE/U+HJ6KIslmqwarJ1Sla+1gHCmJEbzbsrnb6bLtrHtXCZ
XvmR6B5iRkDVpw==
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCadukAJpTLrDuw
vD8vyNde695B7wfjMuZCK4/IPbCqZLcE85rCRqbyVBGiiEhHQbCRyxp2SYcCIa//
jBuFgxDOKBTQrQUGc51d8IyEFqtcOCDvP39/pwT6Vn9eH47NRPddVKP2Ti/W8b4d
UiB5EuorYCYvrYFT8ewt7N1t5guZ1N6JrBPkceAw5ilKtZMjdRCwSAHHkOME5kOQ
fHb+jElu87fCXa4X4YNhiSDzwel1GSdsiDr4LueRliebDD2tLjQ3wrFid+38xZvl
yfw/ere8fCOPSMn82yIHFPSWBZXKpK8ryoeSKUBhph/yOmnSFmucVqTIQdjwOpIL
Qw9Ox7trAgMBAAECggEAOZAMvsCh/NDfobpVddJL6JTPzBRvBQ1H3+rp9z5+ItHL
nq3Fw5aeynnn5IETJnLlgT+GSgSWqoWxV/N3oia40YsATs/bqo7VW1e0ldj43TIR
m/c25XRxl3U6m/H4vqhv4rkTLUvv6hNGvRiI/3W8DJQVRvlK0+S5FlhKIJV1R0sH
tp5vmaPp09Ln+NVno3u3iaYkVgVME4Ukul2i03sQ9OgvZSBCaVr//fMpiPdBeeN6
QY6XHjeGQRnP/UdzMYJ4Qz1yovL1ntneaTMdz/GkKuAFoNNh8Vr2kiEskW17OWPB
ZGcIT6YpBEPo34xXUhUQt7ylFPxGH+zZyHZ3vb8j6QKBgQDJPeu/iPg+M5nz5gO5
ge9gzYrhxK/1mwbFlD7qt1NjOSm6xWxUcss3STjuG7jB0c+NopIUoq/egsUnxrRm
4l17uOCYNLbhTJ2ynfv6QnUMxW5Xkve3DkLa2bze/fhMUywTy8N4A7z0+y35qzm3
lY4rLmQOQKPkmqWRnxU1u8fjFQKBgQDEfpOZ0fp2D/1gTG+D+/zrMEbjnNn3ZO8I
wrjoXwRxcRggt7lJhxgQpwtDr98IqYkDzX7bvyMFJuyTii3NM6NYycpA1pHX70B/
xMvOcrgJnIUAoJ7nl43Or7s8bFTPDLaD9PNGHjrlkF3JOXqSKEbw367jHVOa4SYr
OjrogjrEfwKBgQDHU2a7ax5+9btqggx0ZQfGOTBzmM60lZ3qe4CqGXUl1YvIrB01
tBImq4cRCTJB/9/1qO3KNK2/1oUTddRgB5ySnDcRaz0tASc9sQ/Q/JxVTwSRB0gG
78A2Zu6VbLbQWp1Q6kWtDP7PJC+QmRFtDlwn1yZRm6L6HlcaWpi2hU1iVQKBgCEu
ashv8Aad3qCzZ6V3GReyOFZZd2lSjxcAou8ClKJ/gZ6Mx+pFuOee/cT5XwV8c5nD
yuda2JQXJZ4omGFtlej5coEOeuRnD5JD7lK3hqKA3ujjNtJPAnBjto+Wj5/DOtL/
u1Ec6782aNABN9SUnp4wd7z8h9DAsoxcMfRvgXMLAoGBAJ9gGttfqZbuPz9V0rAo
p05SPPado1i5+2dUOScIbNB6+vQij9IlR2Tzu1T9DwzrBqTDPPmSggeA/JXeTvh6
Skb9fDukizeDfwPYUN2gljhiJEqFdpRBr5vP0lFi291+a0jMW1zldrumxCcGKMyU
D5ReKLp/zSQSQi/Wt4FF1II7
-----END PRIVATE KEY-----

106
FDBLibTLS/testdata/test-2-client.pem vendored Normal file
View File

@ -0,0 +1,106 @@
subject= C = AU, ST = New South Wales, L = Sydney, O = Apple Pty Limited, OU = FDB Team, CN = "FDB LibTLS Plugin Test Client 2, \C2\80 <\01+\02=\03>"
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Intermediate CA 2
subject= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Intermediate CA 2
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Root CA
subject= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Root CA
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Root CA
-----BEGIN CERTIFICATE-----
MIIEEzCCAvugAwIBAgIJALOPTrQGpesmMA0GCSqGSIb3DQEBBQUAMIGRMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5v
MRMwEQYDVQQKDApBcHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTExMC8GA1UE
AwwoRkRCIExpYlRMUyBQbHVnaW4gVGVzdCBJbnRlcm1lZGlhdGUgQ0EgMjAeFw0x
ODA0MDcxNDE2MDJaFw0yODA0MDQxNDE2MDJaMIGdMQswCQYDVQQGEwJBVTEYMBYG
A1UECAwPTmV3IFNvdXRoIFdhbGVzMQ8wDQYDVQQHDAZTeWRuZXkxGjAYBgNVBAoM
EUFwcGxlIFB0eSBMaW1pdGVkMREwDwYDVQQLDAhGREIgVGVhbTE0MDIGA1UEAwwr
RkRCIExpYlRMUyBQbHVnaW4gVGVzdCBDbGllbnQgMiwgwoAgPAErAj0DPjCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALanLExQi/yK2PRyu6Mvdw2MRxUs
26kJftYuK7KtYyltTO3vtj4kNKg1vZI1eezhqr2Ta/1DzE76eLVs8EOW0LAb5oWM
zXdYBXBX4vG+K7pYfjuvZUd6jfX2bHW10xC96HgDTfRn6dof8GR0fILJ6DoEcyI3
82xnKKxTsgAuXU4uvcsl0g0F78nXuIbk8ZktTV3LIdbOCIcLQfG7DdDyAfEA0T7Q
Vg6eeLknIUvPePxyWkUdYeSCDP2d+3NIlHMxNPmH1q3+fCsEsy/kqdVO9e6KrZla
CKqnc6yYTXvTffpPepC3Igz678iGg3dv9rLj0i4fyTr4tEOTJebO9Ka3TbMCAwEA
AaNgMF4wHQYDVR0OBBYEFKO2/D1IhG8KWFwR6OdyoFqEzIWAMB8GA1UdIwQYMBaA
FJFP+HFpDrD0BRU0yE606s6xkqFBMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQD
AgeAMA0GCSqGSIb3DQEBBQUAA4IBAQAQV3FjsvZvwi5Oi/oSc7Du/BQS9nQ/D4j6
IeYpd3M0y50awZB83BReYrhdC907xKkLRD0R8oEPDEg5SaSj3vRML4kaUUqnEINW
4JQtv4wNO9CagYriGg8ygQa0xd683svHeXDet3ov11XN/Ms8lfDiOUp2291HgeTW
8hqn1DaNfZrCb3EkdoNThwVKIUzQtEPBuPkLE+XT8kZP5d8KHmv8/9L39NdZY32d
fzKGBeCxZ34pQS0cTap3rZ02nDfV2vNevODRyuqdhs7EQps2Oe1IfPB9GSE0OFUQ
tdphxSjsv1BcHpTwBDpIITKarnceMIKxQjcZU3yPv5ibIaGCgZOt
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEADCCAuigAwIBAgIJALOPTrQGpesiMA0GCSqGSIb3DQEBBQUAMIGHMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5v
MRMwEQYDVQQKDApBcHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTEnMCUGA1UE
AwweRkRCIExpYlRMUyBQbHVnaW4gVGVzdCBSb290IENBMB4XDTE4MDQwNzE0MTYw
MVoXDTI4MDQwNDE0MTYwMVowgZExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
Zm9ybmlhMRIwEAYDVQQHDAlDdXBlcnRpbm8xEzARBgNVBAoMCkFwcGxlIEluYy4x
ETAPBgNVBAsMCEZEQiBUZWFtMTEwLwYDVQQDDChGREIgTGliVExTIFBsdWdpbiBU
ZXN0IEludGVybWVkaWF0ZSBDQSAyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEApTSBCiUb0amf+QRV2WY6b3bK93D/PSrm4KR/2m2V0lciU1DAk00/kZ52
ZIZmq8g9EaE2+CaDtU0fMvDZpaZD+vTFRwsx4varehq0ZwX9Wt25i/3G/eGLNlD3
9E4tDNruK5UQjum4nJ0SV+AdFEGkSfeU3ZJEHYH0NrcbyAUbh0KeWCSwHiYiFJJf
gBYwRq/HdKNoS/4YvLXzTLR7BSm3YcqWlO5tdkJ2lcT/7Th/Hq1TCW/FKwdQJJBq
JrbOYGlMrf1pLO7Drei/xhsYkwTQ899MhSjkBRhc+401p41Mky0n8wLkuPJGhoY3
9QUOjT+Rmvq5yryg0eWGiFquk6Ru5QIDAQABo2MwYTAdBgNVHQ4EFgQUkU/4cWkO
sPQFFTTITrTqzrGSoUEwHwYDVR0jBBgwFoAUnqtGja3O5jGlh5vHgp3Tf8NCPKkw
DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQAD
ggEBAJfCHU7dm2/2ASyt3wyxivQLxlV6FsEZcF7HcpbbxuB73frGOL4kEoOxvr2X
fBGyjlPMotbc1MeAalAv+hVHdcAcBFPF7lxtYiV6D7YI5T5yVbWSASG3+DMAiW6S
GdQi2eyeh00nH7Y1IkW+yaky0enBtWLzrw+XzHl6xT6DIEJnir//PNxvgXTJ5sjk
6eFAm8HJIqkNQmgfChMQfUH6nm66WwULW6I117RCSkXhIgxZ7wzDq8bXcEdXCrZk
yy5ket9OiVpbd38JgdYirBLmCQVq0uDOOPLz4ZJmNCzQzEt+38AAK2azAk/eb8W9
JaKWH+5V8lhlyGw1zQKdNEP/wg8=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIID9jCCAt6gAwIBAgIJALfRa36cuemYMA0GCSqGSIb3DQEBCwUAMIGHMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5v
MRMwEQYDVQQKDApBcHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTEnMCUGA1UE
AwweRkRCIExpYlRMUyBQbHVnaW4gVGVzdCBSb290IENBMB4XDTE4MDQwNzE0MTYw
MVoXDTI4MDQwNDE0MTYwMVowgYcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
Zm9ybmlhMRIwEAYDVQQHDAlDdXBlcnRpbm8xEzARBgNVBAoMCkFwcGxlIEluYy4x
ETAPBgNVBAsMCEZEQiBUZWFtMScwJQYDVQQDDB5GREIgTGliVExTIFBsdWdpbiBU
ZXN0IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/J+sL
7POoXNdzYRsMZCI5juxMPOVue5vU2QPU9z/PHBsBICX6tVsCnkzk5CLdM6TxofgX
F+MqRKxtcIqxBcKjjVecJlqHuNY+jS2r8UjcoQm+EQ5RsBWu8yaSnXIiZTccQNjB
5T2awwt9Ptbn946MZfq6oEnn4ZPByu9/nCrlk7QXTkuGdpTnC6paQWt/lVxZfELM
i0g76/K/f3e2Lv9UCvlxKOwFMye9XjwF3ekEmUuio5JZEdn+LIs9zB1zehFhGlYB
TUXnkZ0LTOPbH9OxsOli04n31/n7UbYq1BSuoiXx5A2eHOunMppa0NDg7oXmDSKE
A1zo+QtIu1YPXaLdAgMBAAGjYzBhMB0GA1UdDgQWBBSeq0aNrc7mMaWHm8eCndN/
w0I8qTAfBgNVHSMEGDAWgBSeq0aNrc7mMaWHm8eCndN/w0I8qTAPBgNVHRMBAf8E
BTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAIOw1jC39
VW+1fqGT+n44Y6Oh66lAowIvi/BEOW1I4iPAjkr0g6FbbdKeq0VLL7aMMu+q/AOv
UETv7MdVh9xjTLqWZGN0R3Lr/n6ButI3E7MLKL5ByLNCoOhF42aBLINkpKSNFRrQ
40iNoHm3BaNRLKS7poCk5HFkEMjvxdQ1AenNbUa21DTh7y9arHF4CPfi8Ity29jW
ED8jYK/+bWIaO+YhGkRh8UuD3o5WnOti+9QK56qxkPtkqVTh9vMVHfD0DgVeLvMN
nZpTplLTfhjzyFJELwE/U+HJ6KIslmqwarJ1Sla+1gHCmJEbzbsrnb6bLtrHtXCZ
XvmR6B5iRkDVpw==
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC2pyxMUIv8itj0
crujL3cNjEcVLNupCX7WLiuyrWMpbUzt77Y+JDSoNb2SNXns4aq9k2v9Q8xO+ni1
bPBDltCwG+aFjM13WAVwV+Lxviu6WH47r2VHeo319mx1tdMQveh4A030Z+naH/Bk
dHyCyeg6BHMiN/NsZyisU7IALl1OLr3LJdINBe/J17iG5PGZLU1dyyHWzgiHC0Hx
uw3Q8gHxANE+0FYOnni5JyFLz3j8clpFHWHkggz9nftzSJRzMTT5h9at/nwrBLMv
5KnVTvXuiq2ZWgiqp3OsmE170336T3qQtyIM+u/IhoN3b/ay49IuH8k6+LRDkyXm
zvSmt02zAgMBAAECggEAU2sYHSZwOH+FRGcd8RJdcg+N60rYa2QNzG27wVfUwPfN
OaHP/qN0dRpOIPdRXvFVlE0+9aVAKxXTiTBers+zMascZgP/VrEZksxgtn1e5TVD
OakKPVHogdvwfvXylmPVRvJjaOsIb3lExew5bVYfPFgJ6Sfagbi/Z6y1z8VdEbYb
mI34KSZA4bBAMAHPZLa9TGEx/vbPsBlqpU6k8lcoy3cTkO5fCZW4ZZIpwBwef4uJ
UozhRgtTtRBiUpk0F9IoOXonZY1Dtpg+HcDMti/FYgahBVe1hadJ+lbVTxH6GxyI
NJYvptdq5S99UOoJDmCCih0v0ZCUNYWoO0I0vzNncQKBgQDemN7es2fIBstiPjOf
p103DF5j9Uxq5YH9B3wli0CXf6Z2w5uosONoJWgJZKsHJ6f+YSuHsoE/eCrFF3U9
lxT9Nie/wYYIGedly/VR143aCdiTXI44m5gxXgwaUcjvY1DpWyEAAmr5XNdoyZ5n
LNTvOTb4vVo9SgDU7II7rdpRmwKBgQDSD9aBtIy/650suQK/9RiXRU0Kg7LXXVM5
lavPgLvH55lufJeGSa8+ofCNeo31N4AaVuU4lkGeny9tLNBQbYAoyAz0lf51qK7B
1u5JqBDyRrIpdkqwbT0FT1pu1LA3+Qg0KQBrTCnOx+YyyVSivR4YMZzJjmwZGKMg
BWOi0PzhyQKBgGR44dfpaIWbs39zjf+ZHnTza0N4+/YgA60/DKUxloULRArFPeRF
e0+N2siqnJvNJYGnQGuugbIxPjTZ4rxbDklAgW6HHkVX099Z0TAQuGFbIltZYoRg
jrBxv8q9cZHD5Uh/LoT/kmNdqYkNwCbX0IDt9UcOyMVzOq7g1eO0FB/TAoGBAMaG
tWIsMwGHOip0SAcHKtB8bI1NXo5v4yH/NDuOHOqXFcj383S02uzEu8XaV6Ozalx6
V3SdfTLem0IBIneApajlOGlIAQ9N9qu358ixECMJcYQCCiCnfQ4xqvQoCss7judN
ANpnRvPotMS2xkhvl6uh594NvlgRksnGjh3oibcRAoGBAJKiu5ajmIkelzAhFMEC
Slxhg/E+djJ1/SG/FaF8zIyTOxre/QUvmTwFKtHe6A5EfKQo9GCTuHuAcJ1U7eQP
l2BoY0POqJFpw3s/QOt4g/pOz0YjD9GD6awL5WDfO++s4mnI1Snc3wcu99N4Klax
htsaEUECJBUF0ZpIFad73s2f
-----END PRIVATE KEY-----

106
FDBLibTLS/testdata/test-2-server.pem vendored Normal file
View File

@ -0,0 +1,106 @@
subject= C = AU, ST = New South Wales, L = Sydney, O = Apple Pty Limited, OU = FDB Team, CN = "FDB LibTLS Plugin Test Server 2, \C2\80 <\01+\02=\03>"
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Intermediate CA 2
subject= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Intermediate CA 2
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Root CA
subject= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Root CA
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Root CA
-----BEGIN CERTIFICATE-----
MIIEEzCCAvugAwIBAgIJALOPTrQGpeskMA0GCSqGSIb3DQEBBQUAMIGRMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5v
MRMwEQYDVQQKDApBcHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTExMC8GA1UE
AwwoRkRCIExpYlRMUyBQbHVnaW4gVGVzdCBJbnRlcm1lZGlhdGUgQ0EgMjAeFw0x
ODA0MDcxNDE2MDJaFw0yODA0MDQxNDE2MDJaMIGdMQswCQYDVQQGEwJBVTEYMBYG
A1UECAwPTmV3IFNvdXRoIFdhbGVzMQ8wDQYDVQQHDAZTeWRuZXkxGjAYBgNVBAoM
EUFwcGxlIFB0eSBMaW1pdGVkMREwDwYDVQQLDAhGREIgVGVhbTE0MDIGA1UEAwwr
RkRCIExpYlRMUyBQbHVnaW4gVGVzdCBTZXJ2ZXIgMiwgwoAgPAErAj0DPjCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALAolQZIGMeL5w/Bu2X6lHWjO58u
+HUDtBmr37So4jazhZBSFDBg+QlRMiYGLev9EhvCrUsVcRwtvtcuMI3wfKl7qgbi
ZX8zmrzZ3YJo9U47NzCa05faOl8uSBvuXuXUBLU342WFP8XDB1W8yOBQMK73xoFv
DkcxURx9ZtOhdC3EgYKrFqOB1Azl1DB4gLV3h9rHW5QpQ8SqD9CyggcDBpDeZQIP
+4l5YFE9Nb4kEUTscz2wGn4TdHMmcnVpfUxp1Y2o8Umvh4llXHIPhximGb3JJ4QQ
Sir4ZXeeoooWoJG0sdlqVLroKav/VMGtEu9LyfbrNdKnTJq3ceVQ+HJ2hlMCAwEA
AaNgMF4wHQYDVR0OBBYEFH61Z8O9vFsVdhM4MBU3poX2UMTEMB8GA1UdIwQYMBaA
FJFP+HFpDrD0BRU0yE606s6xkqFBMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQD
AgeAMA0GCSqGSIb3DQEBBQUAA4IBAQCVbxlLGIBCo6/XXjqoMyZc7uQZJj7pGnwh
nIMs2izCLfax8j+QrThO2Qjn03zT/WF8eG6ibPbjgnw3VFwCkV6oQ+BXG6Yt0xqP
4rz1LzxSio6HSm26gSk4SQUsVoAtz3OImoTCFVfz+Mixe87pyVXXEEtCYvfU74H9
I1WGyNkWAxiJbqeIxF5PKoc3EdnT5mfdC6sdeGm7t2neeS8PDFQtJ4UfVIEK5z1C
MOfQILNkLX2nBYxNqKpV66zf68VZNN9002ZH2FITGqImpj74BEws3sheiuZySdoI
wnAwRnymIMfAmkf9C7Q2ugId0YMMyesaWrIwSlXlJOHGsA1VrBRD
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEADCCAuigAwIBAgIJALOPTrQGpesiMA0GCSqGSIb3DQEBBQUAMIGHMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5v
MRMwEQYDVQQKDApBcHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTEnMCUGA1UE
AwweRkRCIExpYlRMUyBQbHVnaW4gVGVzdCBSb290IENBMB4XDTE4MDQwNzE0MTYw
MVoXDTI4MDQwNDE0MTYwMVowgZExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
Zm9ybmlhMRIwEAYDVQQHDAlDdXBlcnRpbm8xEzARBgNVBAoMCkFwcGxlIEluYy4x
ETAPBgNVBAsMCEZEQiBUZWFtMTEwLwYDVQQDDChGREIgTGliVExTIFBsdWdpbiBU
ZXN0IEludGVybWVkaWF0ZSBDQSAyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEApTSBCiUb0amf+QRV2WY6b3bK93D/PSrm4KR/2m2V0lciU1DAk00/kZ52
ZIZmq8g9EaE2+CaDtU0fMvDZpaZD+vTFRwsx4varehq0ZwX9Wt25i/3G/eGLNlD3
9E4tDNruK5UQjum4nJ0SV+AdFEGkSfeU3ZJEHYH0NrcbyAUbh0KeWCSwHiYiFJJf
gBYwRq/HdKNoS/4YvLXzTLR7BSm3YcqWlO5tdkJ2lcT/7Th/Hq1TCW/FKwdQJJBq
JrbOYGlMrf1pLO7Drei/xhsYkwTQ899MhSjkBRhc+401p41Mky0n8wLkuPJGhoY3
9QUOjT+Rmvq5yryg0eWGiFquk6Ru5QIDAQABo2MwYTAdBgNVHQ4EFgQUkU/4cWkO
sPQFFTTITrTqzrGSoUEwHwYDVR0jBBgwFoAUnqtGja3O5jGlh5vHgp3Tf8NCPKkw
DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQAD
ggEBAJfCHU7dm2/2ASyt3wyxivQLxlV6FsEZcF7HcpbbxuB73frGOL4kEoOxvr2X
fBGyjlPMotbc1MeAalAv+hVHdcAcBFPF7lxtYiV6D7YI5T5yVbWSASG3+DMAiW6S
GdQi2eyeh00nH7Y1IkW+yaky0enBtWLzrw+XzHl6xT6DIEJnir//PNxvgXTJ5sjk
6eFAm8HJIqkNQmgfChMQfUH6nm66WwULW6I117RCSkXhIgxZ7wzDq8bXcEdXCrZk
yy5ket9OiVpbd38JgdYirBLmCQVq0uDOOPLz4ZJmNCzQzEt+38AAK2azAk/eb8W9
JaKWH+5V8lhlyGw1zQKdNEP/wg8=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIID9jCCAt6gAwIBAgIJALfRa36cuemYMA0GCSqGSIb3DQEBCwUAMIGHMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5v
MRMwEQYDVQQKDApBcHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTEnMCUGA1UE
AwweRkRCIExpYlRMUyBQbHVnaW4gVGVzdCBSb290IENBMB4XDTE4MDQwNzE0MTYw
MVoXDTI4MDQwNDE0MTYwMVowgYcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
Zm9ybmlhMRIwEAYDVQQHDAlDdXBlcnRpbm8xEzARBgNVBAoMCkFwcGxlIEluYy4x
ETAPBgNVBAsMCEZEQiBUZWFtMScwJQYDVQQDDB5GREIgTGliVExTIFBsdWdpbiBU
ZXN0IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/J+sL
7POoXNdzYRsMZCI5juxMPOVue5vU2QPU9z/PHBsBICX6tVsCnkzk5CLdM6TxofgX
F+MqRKxtcIqxBcKjjVecJlqHuNY+jS2r8UjcoQm+EQ5RsBWu8yaSnXIiZTccQNjB
5T2awwt9Ptbn946MZfq6oEnn4ZPByu9/nCrlk7QXTkuGdpTnC6paQWt/lVxZfELM
i0g76/K/f3e2Lv9UCvlxKOwFMye9XjwF3ekEmUuio5JZEdn+LIs9zB1zehFhGlYB
TUXnkZ0LTOPbH9OxsOli04n31/n7UbYq1BSuoiXx5A2eHOunMppa0NDg7oXmDSKE
A1zo+QtIu1YPXaLdAgMBAAGjYzBhMB0GA1UdDgQWBBSeq0aNrc7mMaWHm8eCndN/
w0I8qTAfBgNVHSMEGDAWgBSeq0aNrc7mMaWHm8eCndN/w0I8qTAPBgNVHRMBAf8E
BTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAIOw1jC39
VW+1fqGT+n44Y6Oh66lAowIvi/BEOW1I4iPAjkr0g6FbbdKeq0VLL7aMMu+q/AOv
UETv7MdVh9xjTLqWZGN0R3Lr/n6ButI3E7MLKL5ByLNCoOhF42aBLINkpKSNFRrQ
40iNoHm3BaNRLKS7poCk5HFkEMjvxdQ1AenNbUa21DTh7y9arHF4CPfi8Ity29jW
ED8jYK/+bWIaO+YhGkRh8UuD3o5WnOti+9QK56qxkPtkqVTh9vMVHfD0DgVeLvMN
nZpTplLTfhjzyFJELwE/U+HJ6KIslmqwarJ1Sla+1gHCmJEbzbsrnb6bLtrHtXCZ
XvmR6B5iRkDVpw==
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCwKJUGSBjHi+cP
wbtl+pR1ozufLvh1A7QZq9+0qOI2s4WQUhQwYPkJUTImBi3r/RIbwq1LFXEcLb7X
LjCN8Hype6oG4mV/M5q82d2CaPVOOzcwmtOX2jpfLkgb7l7l1AS1N+NlhT/FwwdV
vMjgUDCu98aBbw5HMVEcfWbToXQtxIGCqxajgdQM5dQweIC1d4fax1uUKUPEqg/Q
soIHAwaQ3mUCD/uJeWBRPTW+JBFE7HM9sBp+E3RzJnJ1aX1MadWNqPFJr4eJZVxy
D4cYphm9ySeEEEoq+GV3nqKKFqCRtLHZalS66Cmr/1TBrRLvS8n26zXSp0yat3Hl
UPhydoZTAgMBAAECggEAVD60NlLYduXzVNfDtVuHEFNGOjSOYfepc/V8gLubo6lr
IMAAI7rcnpYUM5cU8x0OQfRyR8wzUdSWxfWzBs6R78PSZoRzIcgeIl7Wzn0/g3BS
To5czuxwqgBKQAFZpPQmZDwcJfr5qqxAn8IvFweCoMqiRlhELcvqDIP0XxWBqDjc
TNJ988XzZXQmJbjjpWOkUBy2Uqz8lZt8MmxKFpW7SW4tBJwPphnorgjWfjCV/VEh
ORio0rG74NHFo4f1TSrdU2BcB2cbVJ4B+bcUYRdvYmS5bmokhGF8vir0l43gUEdz
Fyk6MaPrTI6cinqzenm3q/0eRvNhBE56U0tiGLn14QKBgQDkCkt1Y4LEboSwsVYl
IXriStqj9p9MOizihh0enhzRXTTQuLX82fNi+bh1LAluwv290Q57pvKa+hB/YciB
o4s7QfSojxQY9DxqvXN7CvxPWXHTyFY5sL4Rm807+C/a9rd39MxBynz9u/7YRvsA
s8v8Y/01qIHnTo+mpDvu6HttWwKBgQDFwdRkgstuE+dXZZe8g1ivh3RNPa968TE3
b8rzF9/nOJV7f6B/n6YEmHD/cHF5mm1bR+zt/jtf1NCRMpazchw3vT3JzQZYMDnM
SD6vxTs5rG47QLiNyTIRmmD4gsEWBpyvoyP8E/9QdfDT1bWI5zZnky9CquRlN+cu
J1bTsefEaQKBgGJsRxFNd91MThztDV9NSfptkFyAT1TZLxI+DEdwusNqVSdY8cNG
VpP7cC+yaAfURSwuFPAtqDxXfdNc4uuBKNDUsMInrubuUz1Gs5cBsNCWrFhZ+U1B
CWgUNMqTXiRFo/40PAyRVs003NOAH0m4UGyIw3rrVdX9xGaKMAv3b35NAoGATkkl
I4UDs1f9xQNaxi3Y9ePRjqJUzX6d1SxUU1eoM4ia5IDpsJwqxLb0RKrmwRT5JaGb
kbuLFazRxCkar38E3Kv1weWAFXlB6DTRXBPgFjzEhoBgjwCO6ZkLulVIysdjT8Rt
gmUINXn7FGENtFyTlP0XQHUWZVt0ETlRjgxni8ECgYBYv6MoSr0iPjQpxeKvwFDz
d9zE+ZXN+3GwtkI340lKRSc/f0Uq1TlC2w+DzjyyXcrBwubMQKTKcQQSH9f3YbMu
DuxVE9AXdlQ1gSQHGjS0qUWwsS/8Xcjk8ZuduAXPGr/MsvsW+FbbZqG8qdZTeMHu
MSTpOxu9HXC8SHML+y0cpw==
-----END PRIVATE KEY-----

150
FDBLibTLS/testdata/test-3-client.pem vendored Normal file
View File

@ -0,0 +1,150 @@
subject=
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Intermediate CA 1
subject= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Intermediate CA 1
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Root CA
subject= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Root CA
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Root CA
Certificate:
Data:
Version: 1 (0x0)
Serial Number: 1048578 (0x100002)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, ST=California, L=Cupertino, O=Apple Inc., OU=FDB Team, CN=FDB LibTLS Plugin Test Intermediate CA 1
Validity
Not Before: Jan 1 00:00:00 2017 GMT
Not After : Dec 31 00:00:00 2017 GMT
Subject:
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:e4:6f:67:4b:e7:d2:1b:0a:ec:f8:92:ae:1e:d4:
e9:00:6b:47:83:ad:4e:9e:e2:cc:52:b0:8a:04:46:
57:1f:f7:32:37:cc:f0:cd:ec:c0:b9:b9:27:b4:19:
33:a1:21:a7:4c:a2:6c:c7:56:31:c4:6a:4f:5f:fb:
92:6c:22:8f:c4:eb:3f:d1:2b:06:c7:7b:6b:90:83:
37:d3:59:1c:c0:da:de:85:a1:dc:e6:9d:e1:d8:fc:
6f:d4:c0:b4:6e:37:3d:d2:d7:4e:4e:04:09:6a:fb:
9f:d3:cf:b1:80:db:7a:78:97:65:e1:bc:8d:5a:fa:
ec:b1:b6:ee:3f:c9:03:83:ab:0a:9a:8e:03:29:88:
42:14:50:80:11:a7:d5:2d:87:c8:bd:25:32:9e:55:
fb:22:ef:9c:64:a8:a4:62:3b:d6:86:43:1a:22:a3:
1c:4b:ee:af:30:70:d3:9c:aa:da:b6:87:61:78:87:
32:0c:0b:b7:44:16:9b:44:1b:4e:6d:f3:98:99:f8:
ed:ae:41:02:5d:52:9a:98:49:c3:24:24:0b:18:7b:
bf:40:ce:37:65:0f:32:0c:1c:5a:47:4b:b0:3f:db:
17:b6:89:68:99:3c:0e:70:84:92:5c:33:cb:6d:2e:
67:c8:af:47:41:87:bd:37:87:88:00:65:1f:7e:7b:
d9:09
Exponent: 65537 (0x10001)
Signature Algorithm: sha256WithRSAEncryption
0b:5a:f7:7e:e5:93:4b:25:dc:01:eb:20:37:cb:bd:a9:71:3a:
af:6d:73:d9:9e:3c:8b:5c:6d:74:45:76:72:02:64:7e:e6:41:
bf:29:d7:cd:f8:a7:2d:87:32:6d:25:3f:14:11:2b:95:5a:2e:
a8:8b:ba:b1:f9:52:79:b4:5b:ea:fe:b0:ee:b0:9c:14:53:ba:
5d:64:aa:b9:d9:ca:17:b2:99:da:34:18:31:56:83:d9:21:8f:
20:9e:6a:7f:09:41:2f:36:fa:ab:e7:d1:6c:76:50:d4:51:69:
b9:93:ae:9a:eb:8a:6f:a9:91:21:58:a9:3d:53:e8:c1:2c:6f:
88:25:65:03:8a:90:9c:8e:58:5d:9a:e2:67:8e:6a:f6:11:19:
24:8d:89:b7:11:5e:a8:dc:21:35:7a:9a:78:8a:94:c2:29:84:
bb:b7:a5:8e:04:79:dc:db:9d:d7:a7:a3:b7:39:e6:c3:a5:be:
83:ad:59:3a:ee:ea:4a:8a:bd:6e:71:c9:e4:a7:46:d5:a3:fd:
a0:b1:a3:54:8d:bc:01:fb:68:4c:5a:a2:f5:79:44:f7:b9:e9:
7b:db:91:91:74:5b:68:f6:3a:b2:70:ee:e6:49:f4:f1:a6:53:
66:13:ce:2f:9e:88:45:66:34:ae:fc:0d:14:02:6f:6a:c9:ac:
b5:3f:89:bc
-----BEGIN CERTIFICATE-----
MIIDCDCCAfACAxAAAjANBgkqhkiG9w0BAQsFADCBkTELMAkGA1UEBhMCVVMxEzAR
BgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUN1cGVydGlubzETMBEGA1UECgwK
QXBwbGUgSW5jLjERMA8GA1UECwwIRkRCIFRlYW0xMTAvBgNVBAMMKEZEQiBMaWJU
TFMgUGx1Z2luIFRlc3QgSW50ZXJtZWRpYXRlIENBIDEwHhcNMTcwMTAxMDAwMDAw
WhcNMTcxMjMxMDAwMDAwWjAAMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEA5G9nS+fSGwrs+JKuHtTpAGtHg61OnuLMUrCKBEZXH/cyN8zwzezAubkntBkz
oSGnTKJsx1YxxGpPX/uSbCKPxOs/0SsGx3trkIM301kcwNrehaHc5p3h2Pxv1MC0
bjc90tdOTgQJavuf08+xgNt6eJdl4byNWvrssbbuP8kDg6sKmo4DKYhCFFCAEafV
LYfIvSUynlX7Iu+cZKikYjvWhkMaIqMcS+6vMHDTnKratodheIcyDAu3RBabRBtO
bfOYmfjtrkECXVKamEnDJCQLGHu/QM43ZQ8yDBxaR0uwP9sXtolomTwOcISSXDPL
bS5nyK9HQYe9N4eIAGUffnvZCQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQALWvd+
5ZNLJdwB6yA3y72pcTqvbXPZnjyLXG10RXZyAmR+5kG/KdfN+KcthzJtJT8UESuV
Wi6oi7qx+VJ5tFvq/rDusJwUU7pdZKq52coXspnaNBgxVoPZIY8gnmp/CUEvNvqr
59FsdlDUUWm5k66a64pvqZEhWKk9U+jBLG+IJWUDipCcjlhdmuJnjmr2ERkkjYm3
EV6o3CE1epp4ipTCKYS7t6WOBHnc253Xp6O3OebDpb6DrVk67upKir1uccnkp0bV
o/2gsaNUjbwB+2hMWqL1eUT3uel725GRdFto9jqycO7mSfTxplNmE84vnohFZjSu
/A0UAm9qyay1P4m8
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEADCCAuigAwIBAgIJALOPTrQGpeshMA0GCSqGSIb3DQEBBQUAMIGHMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5v
MRMwEQYDVQQKDApBcHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTEnMCUGA1UE
AwweRkRCIExpYlRMUyBQbHVnaW4gVGVzdCBSb290IENBMB4XDTE4MDQwNzE0MTYw
MVoXDTI4MDQwNDE0MTYwMVowgZExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
Zm9ybmlhMRIwEAYDVQQHDAlDdXBlcnRpbm8xEzARBgNVBAoMCkFwcGxlIEluYy4x
ETAPBgNVBAsMCEZEQiBUZWFtMTEwLwYDVQQDDChGREIgTGliVExTIFBsdWdpbiBU
ZXN0IEludGVybWVkaWF0ZSBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAyOwdOcYcH3wYou13CchsXh3lLWA85E550tT6/WwDnslQjiMZHFrKvUT2
B8CUOR3Fr+4RG+cdw80rgojYEUuHKwmIGyjo5IotdaYbWzf6mvYThlIPPudCCkSU
CTtqPv8Oq4QdIpCxHdix0MINKu7c+qt1rUwnDFQSv/gHhVnNxT4r8pwVp6T4hwka
2YQaRNjzUuuFinMub0UtxnUX0rH8X5STlOSVn4Ksjo0OhQzsGEYDx86jVAXjgGcb
2CgGGctgq04hVrngP5ahT1Xeh9YycMlQJXsckJJBxfUJebIjANSRyzxI5fYt+ZkY
qoG5VLPREUQknxcpbT7Rsj0n+k0RhwIDAQABo2MwYTAdBgNVHQ4EFgQUJdMXt/zc
d3vGb2BH47hCu+M2jxAwHwYDVR0jBBgwFoAUnqtGja3O5jGlh5vHgp3Tf8NCPKkw
DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQAD
ggEBAGwW7bRqB7aYUGsD1MOE9d5slp6Iw6wKyNLdg+mzoV+iCV2ZM7ejNRButiAy
vPOxSQwXcibLm/g599e+LY1TiI1XXPbL2bFnTcnThqpHHFe+eRrDgqxO8qJyrcBp
EfyMCJWq7jFg4bWoYTpLeC/RAKyi9fxlqY1NzQCp1bG3LiaDJ5VJd4uwkgX2a0yN
3e0XEFNi7r4u4IHejwFjKWrDg8sstjbY+XOYC4EVQyUsbzeKZKSqnOdR2Jv1QZHH
5O24G/efIFpsA6MVUOfRk0eq0RfKX7CdHn2a5p8aC6E6YMDhXL6xo146n49t9sYD
HMUnfG6AEboTBa/l+zwCG/u4f/Y=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIID9jCCAt6gAwIBAgIJALfRa36cuemYMA0GCSqGSIb3DQEBCwUAMIGHMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5v
MRMwEQYDVQQKDApBcHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTEnMCUGA1UE
AwweRkRCIExpYlRMUyBQbHVnaW4gVGVzdCBSb290IENBMB4XDTE4MDQwNzE0MTYw
MVoXDTI4MDQwNDE0MTYwMVowgYcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
Zm9ybmlhMRIwEAYDVQQHDAlDdXBlcnRpbm8xEzARBgNVBAoMCkFwcGxlIEluYy4x
ETAPBgNVBAsMCEZEQiBUZWFtMScwJQYDVQQDDB5GREIgTGliVExTIFBsdWdpbiBU
ZXN0IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/J+sL
7POoXNdzYRsMZCI5juxMPOVue5vU2QPU9z/PHBsBICX6tVsCnkzk5CLdM6TxofgX
F+MqRKxtcIqxBcKjjVecJlqHuNY+jS2r8UjcoQm+EQ5RsBWu8yaSnXIiZTccQNjB
5T2awwt9Ptbn946MZfq6oEnn4ZPByu9/nCrlk7QXTkuGdpTnC6paQWt/lVxZfELM
i0g76/K/f3e2Lv9UCvlxKOwFMye9XjwF3ekEmUuio5JZEdn+LIs9zB1zehFhGlYB
TUXnkZ0LTOPbH9OxsOli04n31/n7UbYq1BSuoiXx5A2eHOunMppa0NDg7oXmDSKE
A1zo+QtIu1YPXaLdAgMBAAGjYzBhMB0GA1UdDgQWBBSeq0aNrc7mMaWHm8eCndN/
w0I8qTAfBgNVHSMEGDAWgBSeq0aNrc7mMaWHm8eCndN/w0I8qTAPBgNVHRMBAf8E
BTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAIOw1jC39
VW+1fqGT+n44Y6Oh66lAowIvi/BEOW1I4iPAjkr0g6FbbdKeq0VLL7aMMu+q/AOv
UETv7MdVh9xjTLqWZGN0R3Lr/n6ButI3E7MLKL5ByLNCoOhF42aBLINkpKSNFRrQ
40iNoHm3BaNRLKS7poCk5HFkEMjvxdQ1AenNbUa21DTh7y9arHF4CPfi8Ity29jW
ED8jYK/+bWIaO+YhGkRh8UuD3o5WnOti+9QK56qxkPtkqVTh9vMVHfD0DgVeLvMN
nZpTplLTfhjzyFJELwE/U+HJ6KIslmqwarJ1Sla+1gHCmJEbzbsrnb6bLtrHtXCZ
XvmR6B5iRkDVpw==
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDkb2dL59IbCuz4
kq4e1OkAa0eDrU6e4sxSsIoERlcf9zI3zPDN7MC5uSe0GTOhIadMomzHVjHEak9f
+5JsIo/E6z/RKwbHe2uQgzfTWRzA2t6FodzmneHY/G/UwLRuNz3S105OBAlq+5/T
z7GA23p4l2XhvI1a+uyxtu4/yQODqwqajgMpiEIUUIARp9Uth8i9JTKeVfsi75xk
qKRiO9aGQxoioxxL7q8wcNOcqtq2h2F4hzIMC7dEFptEG05t85iZ+O2uQQJdUpqY
ScMkJAsYe79AzjdlDzIMHFpHS7A/2xe2iWiZPA5whJJcM8ttLmfIr0dBh703h4gA
ZR9+e9kJAgMBAAECggEBAKC87x+PQN18g6CpfdH+GPINiuXR9ieBCSsKRCOb50R7
6Z8wGyWbeUV2TsTAkv7HsnQPOqHNOfmuoKm2WKK0cxuqOV6SexO0+cxXONoDs2LU
342ChvDTmY7YmkxHSO7g+iS5EcV9u67G3gDp/Unhpjzis3Ly/ThOpmyqftztMgbb
6KKfgGi3VL+fZ2x8gQt0II2QcO6GIzrPcn9ruEM6tXJhQ50YaSCeCmseKBvKuWPW
b/Gj7wgYhsiMW+nt8QjVam99eCQ6Q94CsapWRdGpj1Nrd4ISREbqr8x4fmcbiSO6
6HZyUidxZIxr2Y4/BTd/BiIqXXdKAMoCVElmyE09P4ECgYEA9IkOkHq1jDLAmppd
fNSC/ndmITS0imvwzTTubXKOTn3yZHVxk2/ld83aauGA3UwAueW4Hh0hJdIWqC0d
IyaNj3EhcVbidyYwvXdChlPuQ1uccu/earhzsbaFwqNoLVgMrPcB5QcMKUs2/s4Q
tBXOqNlFjDZ+bkHQyGXtFYJzknECgYEA7yUcJqf2jB5e4LWG4Se4zD1E/ccZH3t8
nhuXa6nDsx2trZBknHpQmc85WzbBITD+LRaamlYpnB1Ueiyr7/Efamtls7NvnoQN
14cNFnnj5HooTHJHgNBuL/M3hr/q8uK4lR6bu/DOfzUfRGowX3pj+POB01ObPdm8
BUTFwmfJTBkCgYEAkakqccmGZxK8Q9t7oKX9uZJp1ZHNkT6m27WR6MP6HKtNPaXv
l4Fp0KlgV5Yn6qohLJq3x8hWPG8ea+MjnhKS9ETRRPAaShsHoXRuvhE0tg7V7GkR
tcRVtiAhIUWxAoGWW1lvWXuPNPHGupUIwhzTUyTJFrJHMWom8Zg1V0CzkyECgYEA
0JpPXwzejEUlv9+4owhyM34ygyg8KvEduBEbWWfBdKmryR2OFczAKBrRzlYJy3kg
DpaMD5qfOzV+bgAvjuKG496A3WrlL6HDLUD50qRKfQ9tvZll8+BcbWk8A0e/m1TX
bARCFoOsrNvaxWPXhEGPmSZYFc31OdOHJhViZ/z+Y2kCgYEAphx6cPXLMcgv0ivj
SgIG09vo3hGA5r06FkLtGL677CTvYsk/Equ5TkG0AIJ0acY9wiabk6zyM/9XjRAp
Nf8qYzhaMxJiyw+JEXmud4Dc41DqjGm9bLV4tKSR+7xzPBP9Q/QLxfRvArBOKhiX
L5fWmM5SQAoHsf124DTKckNirLI=
-----END PRIVATE KEY-----

101
FDBLibTLS/testdata/test-3-server.pem vendored Normal file
View File

@ -0,0 +1,101 @@
subject=
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Intermediate CA 1
subject= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Intermediate CA 1
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Root CA
subject= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Root CA
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Root CA
-----BEGIN CERTIFICATE-----
MIIDCDCCAfACAxAAATANBgkqhkiG9w0BAQsFADCBkTELMAkGA1UEBhMCVVMxEzAR
BgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUN1cGVydGlubzETMBEGA1UECgwK
QXBwbGUgSW5jLjERMA8GA1UECwwIRkRCIFRlYW0xMTAvBgNVBAMMKEZEQiBMaWJU
TFMgUGx1Z2luIFRlc3QgSW50ZXJtZWRpYXRlIENBIDEwHhcNMTcwMTAxMDAwMDAw
WhcNMTcxMjMxMDAwMDAwWjAAMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEA43+uFNDYKXQQ4fmSencxdm/mfM6FAlGwRBWotptutznfH0N+ulp5RhjRcbGb
AHwPOBBNEBSIV3LhdPXep3NcmSkfaMdnPEgrurI0DLYbxZryEXdJZyoueT+w4TNx
I5mNlZDKD5bH5rhV/dUAmK/+LpWuxWraWYaHBZBsuqpb0MF6IZJAN9Ve9JiKHeiY
6ecz/o9XIrFFeWKMncHwBV1taPPoG2Ksjv8UlqqehrYXG+md958MXf69dkuQJLCS
rojPOkhUroixvGiXJBRSFCyVhQxPCLyASsEv8qPEKMUiW4oY3w5R9RQmw97AHlA1
7xB4mGZTZEjUIOYDdd8LyuRpawIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAHMAsm
zLtFnDaYaOgJdPpi9VAUkZpbSXcA3a02PzOvLN9VV1Fogf1+F0zYFlWbiYGIwcI4
3YfuFr97/e0uEQd6pwGc8/a63q+CunGz+HPStWZm+2ZgmJhBH6i1RwmhA9rH6rGK
j2UghYIYT83gn6S2XSfUwzV8gCw+JjJwczcjGpOf9dRCAEsRDcRwUX7rI16cE2tZ
SLzYB/Kg3wSnUXTKXRJfg6VbVRPFXHQlRYpOxe2z5LWoTEo2uYuHgYO+DzSO9pEj
WgyKBwcc+L3zIZFYCqc9EN//QrLlXsiwSDVMvtzVnzvIQKcGF7OE22NyojTaMzQL
2h8UA9W0Mew5PTSl
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEADCCAuigAwIBAgIJALOPTrQGpeshMA0GCSqGSIb3DQEBBQUAMIGHMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5v
MRMwEQYDVQQKDApBcHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTEnMCUGA1UE
AwweRkRCIExpYlRMUyBQbHVnaW4gVGVzdCBSb290IENBMB4XDTE4MDQwNzE0MTYw
MVoXDTI4MDQwNDE0MTYwMVowgZExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
Zm9ybmlhMRIwEAYDVQQHDAlDdXBlcnRpbm8xEzARBgNVBAoMCkFwcGxlIEluYy4x
ETAPBgNVBAsMCEZEQiBUZWFtMTEwLwYDVQQDDChGREIgTGliVExTIFBsdWdpbiBU
ZXN0IEludGVybWVkaWF0ZSBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAyOwdOcYcH3wYou13CchsXh3lLWA85E550tT6/WwDnslQjiMZHFrKvUT2
B8CUOR3Fr+4RG+cdw80rgojYEUuHKwmIGyjo5IotdaYbWzf6mvYThlIPPudCCkSU
CTtqPv8Oq4QdIpCxHdix0MINKu7c+qt1rUwnDFQSv/gHhVnNxT4r8pwVp6T4hwka
2YQaRNjzUuuFinMub0UtxnUX0rH8X5STlOSVn4Ksjo0OhQzsGEYDx86jVAXjgGcb
2CgGGctgq04hVrngP5ahT1Xeh9YycMlQJXsckJJBxfUJebIjANSRyzxI5fYt+ZkY
qoG5VLPREUQknxcpbT7Rsj0n+k0RhwIDAQABo2MwYTAdBgNVHQ4EFgQUJdMXt/zc
d3vGb2BH47hCu+M2jxAwHwYDVR0jBBgwFoAUnqtGja3O5jGlh5vHgp3Tf8NCPKkw
DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQAD
ggEBAGwW7bRqB7aYUGsD1MOE9d5slp6Iw6wKyNLdg+mzoV+iCV2ZM7ejNRButiAy
vPOxSQwXcibLm/g599e+LY1TiI1XXPbL2bFnTcnThqpHHFe+eRrDgqxO8qJyrcBp
EfyMCJWq7jFg4bWoYTpLeC/RAKyi9fxlqY1NzQCp1bG3LiaDJ5VJd4uwkgX2a0yN
3e0XEFNi7r4u4IHejwFjKWrDg8sstjbY+XOYC4EVQyUsbzeKZKSqnOdR2Jv1QZHH
5O24G/efIFpsA6MVUOfRk0eq0RfKX7CdHn2a5p8aC6E6YMDhXL6xo146n49t9sYD
HMUnfG6AEboTBa/l+zwCG/u4f/Y=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIID9jCCAt6gAwIBAgIJALfRa36cuemYMA0GCSqGSIb3DQEBCwUAMIGHMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5v
MRMwEQYDVQQKDApBcHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTEnMCUGA1UE
AwweRkRCIExpYlRMUyBQbHVnaW4gVGVzdCBSb290IENBMB4XDTE4MDQwNzE0MTYw
MVoXDTI4MDQwNDE0MTYwMVowgYcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
Zm9ybmlhMRIwEAYDVQQHDAlDdXBlcnRpbm8xEzARBgNVBAoMCkFwcGxlIEluYy4x
ETAPBgNVBAsMCEZEQiBUZWFtMScwJQYDVQQDDB5GREIgTGliVExTIFBsdWdpbiBU
ZXN0IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/J+sL
7POoXNdzYRsMZCI5juxMPOVue5vU2QPU9z/PHBsBICX6tVsCnkzk5CLdM6TxofgX
F+MqRKxtcIqxBcKjjVecJlqHuNY+jS2r8UjcoQm+EQ5RsBWu8yaSnXIiZTccQNjB
5T2awwt9Ptbn946MZfq6oEnn4ZPByu9/nCrlk7QXTkuGdpTnC6paQWt/lVxZfELM
i0g76/K/f3e2Lv9UCvlxKOwFMye9XjwF3ekEmUuio5JZEdn+LIs9zB1zehFhGlYB
TUXnkZ0LTOPbH9OxsOli04n31/n7UbYq1BSuoiXx5A2eHOunMppa0NDg7oXmDSKE
A1zo+QtIu1YPXaLdAgMBAAGjYzBhMB0GA1UdDgQWBBSeq0aNrc7mMaWHm8eCndN/
w0I8qTAfBgNVHSMEGDAWgBSeq0aNrc7mMaWHm8eCndN/w0I8qTAPBgNVHRMBAf8E
BTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAIOw1jC39
VW+1fqGT+n44Y6Oh66lAowIvi/BEOW1I4iPAjkr0g6FbbdKeq0VLL7aMMu+q/AOv
UETv7MdVh9xjTLqWZGN0R3Lr/n6ButI3E7MLKL5ByLNCoOhF42aBLINkpKSNFRrQ
40iNoHm3BaNRLKS7poCk5HFkEMjvxdQ1AenNbUa21DTh7y9arHF4CPfi8Ity29jW
ED8jYK/+bWIaO+YhGkRh8UuD3o5WnOti+9QK56qxkPtkqVTh9vMVHfD0DgVeLvMN
nZpTplLTfhjzyFJELwE/U+HJ6KIslmqwarJ1Sla+1gHCmJEbzbsrnb6bLtrHtXCZ
XvmR6B5iRkDVpw==
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDjf64U0NgpdBDh
+ZJ6dzF2b+Z8zoUCUbBEFai2m263Od8fQ366WnlGGNFxsZsAfA84EE0QFIhXcuF0
9d6nc1yZKR9ox2c8SCu6sjQMthvFmvIRd0lnKi55P7DhM3EjmY2VkMoPlsfmuFX9
1QCYr/4ula7FatpZhocFkGy6qlvQwXohkkA31V70mIod6Jjp5zP+j1cisUV5Yoyd
wfAFXW1o8+gbYqyO/xSWqp6Gthcb6Z33nwxd/r12S5AksJKuiM86SFSuiLG8aJck
FFIULJWFDE8IvIBKwS/yo8QoxSJbihjfDlH1FCbD3sAeUDXvEHiYZlNkSNQg5gN1
3wvK5GlrAgMBAAECggEAAVjMKwthfD1XrD7SAy+Zd14KO0rttqnNJVoLealJ6oPJ
MmIv6eKHPUcAVm/6vvH9FRPjoOi+NeZUN2ENRGiGb9GygehMUCsNNzm+3SRm3bCh
JkFSie3SAJ3D6lFnphJOqEgHKjh2ToNg3vPX4Q+JrbTtJ/YN/OGzAvFr81721DGO
L7Hs6foBHKrLeibbguVRdc5zc/WtWjGPFhNAmR9qincM3Q9DrUUHjbJzTS1UXDVT
zssTUTZe9TLd4buqHjLLfmiPoTV8qzv5l4RwkmuuLIT+5mO7X41glwdOkBfk+Cum
BZjrjgTDXbqLNXjMsvXkG1hCZQ6qwdT4GINYlYSiQQKBgQD4pJf7xLaX53rj+LDc
HY3TbWDdyS7h7cq4ZoKa1xPt4Va3xIAIst20edTr6tBYtNygjFZwIkPFYGwdGKVK
CqbpzTxVl8p5I3uoUmIFDo8hX7ChLC928K9lfD62agU85ZfP9Vly4zvDG2sIvxpw
HUY/96VhdSG3fssWYvg3dYUGCQKBgQDqOuyrcTHaZujFMN+MIuUExgYOMS0R0O4T
zCMtWIEkjntSk4CBMsHSb/dZH3CbFB90GjS+WklfTBd6kZ8tBO35vtM6nz5NPCEr
2umqJR5hijHV2tB98qV9qJttJrH/z0VKuuZBa14S1rJwGpX9ZoOULwcOGK3VC9pQ
YnH7Wdjw0wKBgFtBZXqE7xL/ZS4IVzjiK+xeJ4Ae13MaKB3XmbWknG7hFkep+ee3
ZgFX+ZqAeukjsBnIh+zt1nu5cNSY+Akdsbb7mVo8tJYTPM5BNjJu7n8sNJJiuiTo
HyebGxUuAjAgf8BWZvbwiT2JcZYrNVPSmrbdeDg1miNTiMv1lO4d1q2pAoGBANq8
oFwSX24IAIR1+a2SwLDOhMUoI2Cp7ktKrecg6alL7drVqIH+9oYgzarK84u/JQh1
mJ/TDQYTtzFdYHrYSaybCgOKxtG1v3yG+QNNmquYNKXzrBSSTv2kQVGTe1LbK2h4
VaLuM3IAUa7jBQMZgvMVX89IOL3mTcAXzz3dT/zFAoGBAI/pVbABfPihWZ1MrmTN
pnRmQ0461J0WGT+fIgAPR+R+umckHaOVAGiSQomfNrUBbsydoZYu/by7GhIGsDeO
8XKwEP/HLRrABvZu4KLTxa+qTnW/t6BSIfFwQmrNMofxcFRbdzNAODKjyaJG2dqT
ksg9s2SxReRrGOeb43CAw5SC
-----END PRIVATE KEY-----

80
FDBLibTLS/testdata/test-4-client.pem vendored Normal file
View File

@ -0,0 +1,80 @@
subject= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Client 1
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Intermediate CA 1
subject= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Intermediate CA 1
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Root CA
-----BEGIN CERTIFICATE-----
MIID/jCCAuagAwIBAgIJALOPTrQGpeslMA0GCSqGSIb3DQEBBQUAMIGRMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5v
MRMwEQYDVQQKDApBcHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTExMC8GA1UE
AwwoRkRCIExpYlRMUyBQbHVnaW4gVGVzdCBJbnRlcm1lZGlhdGUgQ0EgMTAeFw0x
ODA0MDcxNDE2MDJaFw0yODA0MDQxNDE2MDJaMIGIMQswCQYDVQQGEwJVUzETMBEG
A1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5vMRMwEQYDVQQKDApB
cHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTEoMCYGA1UEAwwfRkRCIExpYlRM
UyBQbHVnaW4gVGVzdCBDbGllbnQgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBALVkdxOmWcd959NyirJ1iz7q5fkjdRUV+88KMMehQWc3f50GJIQ+eZo+
7RhwVE+n8nd0i5iGfyY6LRuupdwoQUxoZ/5rUIDGKspNO62DVRW+tZqzpEa1+ub5
75BMoc7I7l9sXDkuiMu1OYcPNKMv4F3mf+B3ourLqjUekKlUv8XIZXAvN+R19HlR
FM8vs8rnhQXx7iWVP91frDvyD8G7lOf6R7R4homnB37kLom8WU+fCmcyA6em0qX0
JeVP6xk2qXU1cMs7DL8WftdrWHv+a73/l4hytQHo5OvtGaLZhpPYpC/FMSaFHVSM
irWSFK+ZtvaLi3LXc2HGANMokjPoRf8CAwEAAaNgMF4wHQYDVR0OBBYEFPtTL9KZ
jn49cLediy1ixz7AXOI3MB8GA1UdIwQYMBaAFCXTF7f83Hd7xm9gR+O4QrvjNo8Q
MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3DQEBBQUAA4IB
AQA17a4d/tSWIlTkIfkrXziD21+1OsN6/dUrWQK7kxtEe21QXIutccW4bwpM0JDB
M+bZiWkdgQ15+ZotX5UXlBcx9WWDU5RqSO06hhXu5b8gZwfVF4Od6tBdVxkn4KbU
0YujOZrL8fDOrQHqCO7nhNlYgcEn7bKF5wjtOoiKhtA9sLSIZQR5g32kkJXXGvcY
lLWMXygEg9FMQoldW9RHq4GbUiYEeqEq6k4S7cE03R1lvmQEOOAJ2S7LnaS4UHQT
GmW6uvLnJJrG4HB9JGE+y1e9M+C7Enzhi39RGd8ylignGimkdw/1UEWnvKGCqoU7
ufWGF7eUV8dCqO+jYghIY8rA
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEADCCAuigAwIBAgIJALOPTrQGpeshMA0GCSqGSIb3DQEBBQUAMIGHMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5v
MRMwEQYDVQQKDApBcHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTEnMCUGA1UE
AwweRkRCIExpYlRMUyBQbHVnaW4gVGVzdCBSb290IENBMB4XDTE4MDQwNzE0MTYw
MVoXDTI4MDQwNDE0MTYwMVowgZExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
Zm9ybmlhMRIwEAYDVQQHDAlDdXBlcnRpbm8xEzARBgNVBAoMCkFwcGxlIEluYy4x
ETAPBgNVBAsMCEZEQiBUZWFtMTEwLwYDVQQDDChGREIgTGliVExTIFBsdWdpbiBU
ZXN0IEludGVybWVkaWF0ZSBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAyOwdOcYcH3wYou13CchsXh3lLWA85E550tT6/WwDnslQjiMZHFrKvUT2
B8CUOR3Fr+4RG+cdw80rgojYEUuHKwmIGyjo5IotdaYbWzf6mvYThlIPPudCCkSU
CTtqPv8Oq4QdIpCxHdix0MINKu7c+qt1rUwnDFQSv/gHhVnNxT4r8pwVp6T4hwka
2YQaRNjzUuuFinMub0UtxnUX0rH8X5STlOSVn4Ksjo0OhQzsGEYDx86jVAXjgGcb
2CgGGctgq04hVrngP5ahT1Xeh9YycMlQJXsckJJBxfUJebIjANSRyzxI5fYt+ZkY
qoG5VLPREUQknxcpbT7Rsj0n+k0RhwIDAQABo2MwYTAdBgNVHQ4EFgQUJdMXt/zc
d3vGb2BH47hCu+M2jxAwHwYDVR0jBBgwFoAUnqtGja3O5jGlh5vHgp3Tf8NCPKkw
DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQAD
ggEBAGwW7bRqB7aYUGsD1MOE9d5slp6Iw6wKyNLdg+mzoV+iCV2ZM7ejNRButiAy
vPOxSQwXcibLm/g599e+LY1TiI1XXPbL2bFnTcnThqpHHFe+eRrDgqxO8qJyrcBp
EfyMCJWq7jFg4bWoYTpLeC/RAKyi9fxlqY1NzQCp1bG3LiaDJ5VJd4uwkgX2a0yN
3e0XEFNi7r4u4IHejwFjKWrDg8sstjbY+XOYC4EVQyUsbzeKZKSqnOdR2Jv1QZHH
5O24G/efIFpsA6MVUOfRk0eq0RfKX7CdHn2a5p8aC6E6YMDhXL6xo146n49t9sYD
HMUnfG6AEboTBa/l+zwCG/u4f/Y=
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC1ZHcTplnHfefT
coqydYs+6uX5I3UVFfvPCjDHoUFnN3+dBiSEPnmaPu0YcFRPp/J3dIuYhn8mOi0b
rqXcKEFMaGf+a1CAxirKTTutg1UVvrWas6RGtfrm+e+QTKHOyO5fbFw5LojLtTmH
DzSjL+Bd5n/gd6Lqy6o1HpCpVL/FyGVwLzfkdfR5URTPL7PK54UF8e4llT/dX6w7
8g/Bu5Tn+ke0eIaJpwd+5C6JvFlPnwpnMgOnptKl9CXlT+sZNql1NXDLOwy/Fn7X
a1h7/mu9/5eIcrUB6OTr7Rmi2YaT2KQvxTEmhR1UjIq1khSvmbb2i4ty13NhxgDT
KJIz6EX/AgMBAAECggEAEm2Mc2CZCl1OKfsfABZU+SVgC7mAcY30MQp1/jHxtQy8
WDWBjDXUoMj3yV3QEu+bAGvEqtAvJrEOWBucGgu05pBM0FoSqaJ4QmkqQOxwvm7L
gFXzwINIZCLMJbrDTYC4RtV5YQ3LM/bLS19OF64Lez6piyJcWMIsHo1mYO2NNgiD
7f1x1uQw46Q0YHWeoHY58MPfmgfKsqnJDWc8cCuU9fJOWeU4dVrfW8dh9WVAoLZ7
qAM5vvap11Qk8RXaRnmLjxN6H1M7iVNfcLVNKfG6XOBBepYjZr/qMkuN3ONuqBHl
fC3Zia2zQZRfiuPspX0KhjCfYAKbIZC6oyrQM2uXgQKBgQDoD5voZiCOeGXJEMUk
9JV4V8A96aE0xxy+OHMogVpysxBO4V0Nh0krSLTt9NXnpjawZQ+3pLQ4+2J2XM2e
fJuJJ7Z+Mhjv6epnMM7FoxK1VF7oe+LE7Yk/kg/moCuVS/XhLdQrhZVBJhfEADS3
oFybf7Q6rJYtN3OYsiFymyneHwKBgQDIGsY5kGdmx27LS5rPMwdw632TF8G5BGbu
C3ty7LYkOWb/9/V4cuWjW4eLJQqCWbJQrzOvg0coxwXLUuEQik+IP2IkF0YlRS43
VJuULwOxi3Cbj51RoapHhmYTO9fe2A1N9oJMAqEUHY1q/r9txPcguRWyuH2Yv9Ih
OzHnc2DcIQKBgQCGW0MxMq/2zM5hs0vxMYq4ulWbgwDKxd1mZNiHwxzS+8mdYe22
P3WlkdrvSqnuDNXtGxYWhU2zEBjZ3rFN6WdD6bJHLkox3YTRafjNhLT4N3kbsV6C
FeU44SBDrsiNEAWz8gy9hgH8TknEOTpMdpQnk7CNqA7q7wgGiFvFNwDukQKBgG7i
R03Gs0XE5aRJtPN0N39fPyqvU24O/mqSekno2dWg6W6WHLQuFwo6whVc5UHuKl2D
eISdnmT+RDuzJXxg6El7tgqByyEEAOQwQjYPB2Du/+tz3Z1KlG0mEJI/6xNVbany
G6m7Gz9mUOMlXzaYmsjLRzbN/OsUAIDhqHm0+cuBAoGAZCND80akS3xr3yC87GyX
aA0RoHXbdB6dbP8Y6XYDXR4QFIA4kXwY5cCLaZA/0hP5FOzDhORmaoaPM8vUdNyb
IYvbw2H6tODiU5oICWY6+HQQ2nXikucI4HDYDLbsiV2htZkEmBYWLilYq0Tb8jC5
u+ehIIvZYLqKaY1GaKmF86A=
-----END PRIVATE KEY-----

80
FDBLibTLS/testdata/test-4-server.pem vendored Normal file
View File

@ -0,0 +1,80 @@
subject= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Server 1
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Intermediate CA 1
subject= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Intermediate CA 1
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Root CA
-----BEGIN CERTIFICATE-----
MIID/jCCAuagAwIBAgIJALOPTrQGpesjMA0GCSqGSIb3DQEBBQUAMIGRMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5v
MRMwEQYDVQQKDApBcHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTExMC8GA1UE
AwwoRkRCIExpYlRMUyBQbHVnaW4gVGVzdCBJbnRlcm1lZGlhdGUgQ0EgMTAeFw0x
ODA0MDcxNDE2MDJaFw0yODA0MDQxNDE2MDJaMIGIMQswCQYDVQQGEwJVUzETMBEG
A1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5vMRMwEQYDVQQKDApB
cHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTEoMCYGA1UEAwwfRkRCIExpYlRM
UyBQbHVnaW4gVGVzdCBTZXJ2ZXIgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBAJp26QAmlMusO7C8Py/I117r3kHvB+My5kIrj8g9sKpktwTzmsJGpvJU
EaKISEdBsJHLGnZJhwIhr/+MG4WDEM4oFNCtBQZznV3wjIQWq1w4IO8/f3+nBPpW
f14fjs1E911Uo/ZOL9bxvh1SIHkS6itgJi+tgVPx7C3s3W3mC5nU3omsE+Rx4DDm
KUq1kyN1ELBIAceQ4wTmQ5B8dv6MSW7zt8Jdrhfhg2GJIPPB6XUZJ2yIOvgu55GW
J5sMPa0uNDfCsWJ37fzFm+XJ/D96t7x8I49IyfzbIgcU9JYFlcqkryvKh5IpQGGm
H/I6adIWa5xWpMhB2PA6kgtDD07Hu2sCAwEAAaNgMF4wHQYDVR0OBBYEFJ7S+FUz
9ngzH/TNPVeM/cE7LeBGMB8GA1UdIwQYMBaAFCXTF7f83Hd7xm9gR+O4QrvjNo8Q
MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3DQEBBQUAA4IB
AQAx6WHwikVFAH0TRYCznwO6He+0t2pnlyfrI+24N28tzupMSrRPs086UbLgHLz1
lbkYdheeOkLPzjWi5vfymL1Oua3E2iAXWEpMb4Sg7E5SVHp9yt6gZ0DTVwR+Gcu7
uooroidAG3OFeOXL5ivU5J5ipaoEAiLprpKxtPzo4z/TxIqw3kJISC56qw9VTJNQ
TQZvneUecykdIZuH61ih0cJLe5WRkEs/63Dgl8TBYiVDbvBSGRbsXoAXcspVlc2x
XOLey5IVJ4/TH5ZBobShC6J1KrjZTNYvUgc44CocOgrc0ePPiQzB7JXxR1H8ATGl
yKjWqT2PkrfHmjdcmsi2GIVt
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEADCCAuigAwIBAgIJALOPTrQGpeshMA0GCSqGSIb3DQEBBQUAMIGHMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5v
MRMwEQYDVQQKDApBcHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTEnMCUGA1UE
AwweRkRCIExpYlRMUyBQbHVnaW4gVGVzdCBSb290IENBMB4XDTE4MDQwNzE0MTYw
MVoXDTI4MDQwNDE0MTYwMVowgZExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
Zm9ybmlhMRIwEAYDVQQHDAlDdXBlcnRpbm8xEzARBgNVBAoMCkFwcGxlIEluYy4x
ETAPBgNVBAsMCEZEQiBUZWFtMTEwLwYDVQQDDChGREIgTGliVExTIFBsdWdpbiBU
ZXN0IEludGVybWVkaWF0ZSBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAyOwdOcYcH3wYou13CchsXh3lLWA85E550tT6/WwDnslQjiMZHFrKvUT2
B8CUOR3Fr+4RG+cdw80rgojYEUuHKwmIGyjo5IotdaYbWzf6mvYThlIPPudCCkSU
CTtqPv8Oq4QdIpCxHdix0MINKu7c+qt1rUwnDFQSv/gHhVnNxT4r8pwVp6T4hwka
2YQaRNjzUuuFinMub0UtxnUX0rH8X5STlOSVn4Ksjo0OhQzsGEYDx86jVAXjgGcb
2CgGGctgq04hVrngP5ahT1Xeh9YycMlQJXsckJJBxfUJebIjANSRyzxI5fYt+ZkY
qoG5VLPREUQknxcpbT7Rsj0n+k0RhwIDAQABo2MwYTAdBgNVHQ4EFgQUJdMXt/zc
d3vGb2BH47hCu+M2jxAwHwYDVR0jBBgwFoAUnqtGja3O5jGlh5vHgp3Tf8NCPKkw
DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQAD
ggEBAGwW7bRqB7aYUGsD1MOE9d5slp6Iw6wKyNLdg+mzoV+iCV2ZM7ejNRButiAy
vPOxSQwXcibLm/g599e+LY1TiI1XXPbL2bFnTcnThqpHHFe+eRrDgqxO8qJyrcBp
EfyMCJWq7jFg4bWoYTpLeC/RAKyi9fxlqY1NzQCp1bG3LiaDJ5VJd4uwkgX2a0yN
3e0XEFNi7r4u4IHejwFjKWrDg8sstjbY+XOYC4EVQyUsbzeKZKSqnOdR2Jv1QZHH
5O24G/efIFpsA6MVUOfRk0eq0RfKX7CdHn2a5p8aC6E6YMDhXL6xo146n49t9sYD
HMUnfG6AEboTBa/l+zwCG/u4f/Y=
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCadukAJpTLrDuw
vD8vyNde695B7wfjMuZCK4/IPbCqZLcE85rCRqbyVBGiiEhHQbCRyxp2SYcCIa//
jBuFgxDOKBTQrQUGc51d8IyEFqtcOCDvP39/pwT6Vn9eH47NRPddVKP2Ti/W8b4d
UiB5EuorYCYvrYFT8ewt7N1t5guZ1N6JrBPkceAw5ilKtZMjdRCwSAHHkOME5kOQ
fHb+jElu87fCXa4X4YNhiSDzwel1GSdsiDr4LueRliebDD2tLjQ3wrFid+38xZvl
yfw/ere8fCOPSMn82yIHFPSWBZXKpK8ryoeSKUBhph/yOmnSFmucVqTIQdjwOpIL
Qw9Ox7trAgMBAAECggEAOZAMvsCh/NDfobpVddJL6JTPzBRvBQ1H3+rp9z5+ItHL
nq3Fw5aeynnn5IETJnLlgT+GSgSWqoWxV/N3oia40YsATs/bqo7VW1e0ldj43TIR
m/c25XRxl3U6m/H4vqhv4rkTLUvv6hNGvRiI/3W8DJQVRvlK0+S5FlhKIJV1R0sH
tp5vmaPp09Ln+NVno3u3iaYkVgVME4Ukul2i03sQ9OgvZSBCaVr//fMpiPdBeeN6
QY6XHjeGQRnP/UdzMYJ4Qz1yovL1ntneaTMdz/GkKuAFoNNh8Vr2kiEskW17OWPB
ZGcIT6YpBEPo34xXUhUQt7ylFPxGH+zZyHZ3vb8j6QKBgQDJPeu/iPg+M5nz5gO5
ge9gzYrhxK/1mwbFlD7qt1NjOSm6xWxUcss3STjuG7jB0c+NopIUoq/egsUnxrRm
4l17uOCYNLbhTJ2ynfv6QnUMxW5Xkve3DkLa2bze/fhMUywTy8N4A7z0+y35qzm3
lY4rLmQOQKPkmqWRnxU1u8fjFQKBgQDEfpOZ0fp2D/1gTG+D+/zrMEbjnNn3ZO8I
wrjoXwRxcRggt7lJhxgQpwtDr98IqYkDzX7bvyMFJuyTii3NM6NYycpA1pHX70B/
xMvOcrgJnIUAoJ7nl43Or7s8bFTPDLaD9PNGHjrlkF3JOXqSKEbw367jHVOa4SYr
OjrogjrEfwKBgQDHU2a7ax5+9btqggx0ZQfGOTBzmM60lZ3qe4CqGXUl1YvIrB01
tBImq4cRCTJB/9/1qO3KNK2/1oUTddRgB5ySnDcRaz0tASc9sQ/Q/JxVTwSRB0gG
78A2Zu6VbLbQWp1Q6kWtDP7PJC+QmRFtDlwn1yZRm6L6HlcaWpi2hU1iVQKBgCEu
ashv8Aad3qCzZ6V3GReyOFZZd2lSjxcAou8ClKJ/gZ6Mx+pFuOee/cT5XwV8c5nD
yuda2JQXJZ4omGFtlej5coEOeuRnD5JD7lK3hqKA3ujjNtJPAnBjto+Wj5/DOtL/
u1Ec6782aNABN9SUnp4wd7z8h9DAsoxcMfRvgXMLAoGBAJ9gGttfqZbuPz9V0rAo
p05SPPado1i5+2dUOScIbNB6+vQij9IlR2Tzu1T9DwzrBqTDPPmSggeA/JXeTvh6
Skb9fDukizeDfwPYUN2gljhiJEqFdpRBr5vP0lFi291+a0jMW1zldrumxCcGKMyU
D5ReKLp/zSQSQi/Wt4FF1II7
-----END PRIVATE KEY-----

80
FDBLibTLS/testdata/test-5-client.pem vendored Normal file
View File

@ -0,0 +1,80 @@
subject= C = AU, ST = New South Wales, L = Sydney, O = Apple Pty Limited, OU = FDB Team, CN = "FDB LibTLS Plugin Test Client 2, \C2\80 <\01+\02=\03>"
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Intermediate CA 2
subject= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Intermediate CA 2
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Root CA
-----BEGIN CERTIFICATE-----
MIIEEzCCAvugAwIBAgIJALOPTrQGpesmMA0GCSqGSIb3DQEBBQUAMIGRMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5v
MRMwEQYDVQQKDApBcHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTExMC8GA1UE
AwwoRkRCIExpYlRMUyBQbHVnaW4gVGVzdCBJbnRlcm1lZGlhdGUgQ0EgMjAeFw0x
ODA0MDcxNDE2MDJaFw0yODA0MDQxNDE2MDJaMIGdMQswCQYDVQQGEwJBVTEYMBYG
A1UECAwPTmV3IFNvdXRoIFdhbGVzMQ8wDQYDVQQHDAZTeWRuZXkxGjAYBgNVBAoM
EUFwcGxlIFB0eSBMaW1pdGVkMREwDwYDVQQLDAhGREIgVGVhbTE0MDIGA1UEAwwr
RkRCIExpYlRMUyBQbHVnaW4gVGVzdCBDbGllbnQgMiwgwoAgPAErAj0DPjCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALanLExQi/yK2PRyu6Mvdw2MRxUs
26kJftYuK7KtYyltTO3vtj4kNKg1vZI1eezhqr2Ta/1DzE76eLVs8EOW0LAb5oWM
zXdYBXBX4vG+K7pYfjuvZUd6jfX2bHW10xC96HgDTfRn6dof8GR0fILJ6DoEcyI3
82xnKKxTsgAuXU4uvcsl0g0F78nXuIbk8ZktTV3LIdbOCIcLQfG7DdDyAfEA0T7Q
Vg6eeLknIUvPePxyWkUdYeSCDP2d+3NIlHMxNPmH1q3+fCsEsy/kqdVO9e6KrZla
CKqnc6yYTXvTffpPepC3Igz678iGg3dv9rLj0i4fyTr4tEOTJebO9Ka3TbMCAwEA
AaNgMF4wHQYDVR0OBBYEFKO2/D1IhG8KWFwR6OdyoFqEzIWAMB8GA1UdIwQYMBaA
FJFP+HFpDrD0BRU0yE606s6xkqFBMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQD
AgeAMA0GCSqGSIb3DQEBBQUAA4IBAQAQV3FjsvZvwi5Oi/oSc7Du/BQS9nQ/D4j6
IeYpd3M0y50awZB83BReYrhdC907xKkLRD0R8oEPDEg5SaSj3vRML4kaUUqnEINW
4JQtv4wNO9CagYriGg8ygQa0xd683svHeXDet3ov11XN/Ms8lfDiOUp2291HgeTW
8hqn1DaNfZrCb3EkdoNThwVKIUzQtEPBuPkLE+XT8kZP5d8KHmv8/9L39NdZY32d
fzKGBeCxZ34pQS0cTap3rZ02nDfV2vNevODRyuqdhs7EQps2Oe1IfPB9GSE0OFUQ
tdphxSjsv1BcHpTwBDpIITKarnceMIKxQjcZU3yPv5ibIaGCgZOt
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEADCCAuigAwIBAgIJALOPTrQGpesiMA0GCSqGSIb3DQEBBQUAMIGHMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5v
MRMwEQYDVQQKDApBcHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTEnMCUGA1UE
AwweRkRCIExpYlRMUyBQbHVnaW4gVGVzdCBSb290IENBMB4XDTE4MDQwNzE0MTYw
MVoXDTI4MDQwNDE0MTYwMVowgZExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
Zm9ybmlhMRIwEAYDVQQHDAlDdXBlcnRpbm8xEzARBgNVBAoMCkFwcGxlIEluYy4x
ETAPBgNVBAsMCEZEQiBUZWFtMTEwLwYDVQQDDChGREIgTGliVExTIFBsdWdpbiBU
ZXN0IEludGVybWVkaWF0ZSBDQSAyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEApTSBCiUb0amf+QRV2WY6b3bK93D/PSrm4KR/2m2V0lciU1DAk00/kZ52
ZIZmq8g9EaE2+CaDtU0fMvDZpaZD+vTFRwsx4varehq0ZwX9Wt25i/3G/eGLNlD3
9E4tDNruK5UQjum4nJ0SV+AdFEGkSfeU3ZJEHYH0NrcbyAUbh0KeWCSwHiYiFJJf
gBYwRq/HdKNoS/4YvLXzTLR7BSm3YcqWlO5tdkJ2lcT/7Th/Hq1TCW/FKwdQJJBq
JrbOYGlMrf1pLO7Drei/xhsYkwTQ899MhSjkBRhc+401p41Mky0n8wLkuPJGhoY3
9QUOjT+Rmvq5yryg0eWGiFquk6Ru5QIDAQABo2MwYTAdBgNVHQ4EFgQUkU/4cWkO
sPQFFTTITrTqzrGSoUEwHwYDVR0jBBgwFoAUnqtGja3O5jGlh5vHgp3Tf8NCPKkw
DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQAD
ggEBAJfCHU7dm2/2ASyt3wyxivQLxlV6FsEZcF7HcpbbxuB73frGOL4kEoOxvr2X
fBGyjlPMotbc1MeAalAv+hVHdcAcBFPF7lxtYiV6D7YI5T5yVbWSASG3+DMAiW6S
GdQi2eyeh00nH7Y1IkW+yaky0enBtWLzrw+XzHl6xT6DIEJnir//PNxvgXTJ5sjk
6eFAm8HJIqkNQmgfChMQfUH6nm66WwULW6I117RCSkXhIgxZ7wzDq8bXcEdXCrZk
yy5ket9OiVpbd38JgdYirBLmCQVq0uDOOPLz4ZJmNCzQzEt+38AAK2azAk/eb8W9
JaKWH+5V8lhlyGw1zQKdNEP/wg8=
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC2pyxMUIv8itj0
crujL3cNjEcVLNupCX7WLiuyrWMpbUzt77Y+JDSoNb2SNXns4aq9k2v9Q8xO+ni1
bPBDltCwG+aFjM13WAVwV+Lxviu6WH47r2VHeo319mx1tdMQveh4A030Z+naH/Bk
dHyCyeg6BHMiN/NsZyisU7IALl1OLr3LJdINBe/J17iG5PGZLU1dyyHWzgiHC0Hx
uw3Q8gHxANE+0FYOnni5JyFLz3j8clpFHWHkggz9nftzSJRzMTT5h9at/nwrBLMv
5KnVTvXuiq2ZWgiqp3OsmE170336T3qQtyIM+u/IhoN3b/ay49IuH8k6+LRDkyXm
zvSmt02zAgMBAAECggEAU2sYHSZwOH+FRGcd8RJdcg+N60rYa2QNzG27wVfUwPfN
OaHP/qN0dRpOIPdRXvFVlE0+9aVAKxXTiTBers+zMascZgP/VrEZksxgtn1e5TVD
OakKPVHogdvwfvXylmPVRvJjaOsIb3lExew5bVYfPFgJ6Sfagbi/Z6y1z8VdEbYb
mI34KSZA4bBAMAHPZLa9TGEx/vbPsBlqpU6k8lcoy3cTkO5fCZW4ZZIpwBwef4uJ
UozhRgtTtRBiUpk0F9IoOXonZY1Dtpg+HcDMti/FYgahBVe1hadJ+lbVTxH6GxyI
NJYvptdq5S99UOoJDmCCih0v0ZCUNYWoO0I0vzNncQKBgQDemN7es2fIBstiPjOf
p103DF5j9Uxq5YH9B3wli0CXf6Z2w5uosONoJWgJZKsHJ6f+YSuHsoE/eCrFF3U9
lxT9Nie/wYYIGedly/VR143aCdiTXI44m5gxXgwaUcjvY1DpWyEAAmr5XNdoyZ5n
LNTvOTb4vVo9SgDU7II7rdpRmwKBgQDSD9aBtIy/650suQK/9RiXRU0Kg7LXXVM5
lavPgLvH55lufJeGSa8+ofCNeo31N4AaVuU4lkGeny9tLNBQbYAoyAz0lf51qK7B
1u5JqBDyRrIpdkqwbT0FT1pu1LA3+Qg0KQBrTCnOx+YyyVSivR4YMZzJjmwZGKMg
BWOi0PzhyQKBgGR44dfpaIWbs39zjf+ZHnTza0N4+/YgA60/DKUxloULRArFPeRF
e0+N2siqnJvNJYGnQGuugbIxPjTZ4rxbDklAgW6HHkVX099Z0TAQuGFbIltZYoRg
jrBxv8q9cZHD5Uh/LoT/kmNdqYkNwCbX0IDt9UcOyMVzOq7g1eO0FB/TAoGBAMaG
tWIsMwGHOip0SAcHKtB8bI1NXo5v4yH/NDuOHOqXFcj383S02uzEu8XaV6Ozalx6
V3SdfTLem0IBIneApajlOGlIAQ9N9qu358ixECMJcYQCCiCnfQ4xqvQoCss7judN
ANpnRvPotMS2xkhvl6uh594NvlgRksnGjh3oibcRAoGBAJKiu5ajmIkelzAhFMEC
Slxhg/E+djJ1/SG/FaF8zIyTOxre/QUvmTwFKtHe6A5EfKQo9GCTuHuAcJ1U7eQP
l2BoY0POqJFpw3s/QOt4g/pOz0YjD9GD6awL5WDfO++s4mnI1Snc3wcu99N4Klax
htsaEUECJBUF0ZpIFad73s2f
-----END PRIVATE KEY-----

80
FDBLibTLS/testdata/test-5-server.pem vendored Normal file
View File

@ -0,0 +1,80 @@
subject= C = AU, ST = New South Wales, L = Sydney, O = Apple Pty Limited, OU = FDB Team, CN = "FDB LibTLS Plugin Test Server 2, \C2\80 <\01+\02=\03>"
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Intermediate CA 2
subject= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Intermediate CA 2
issuer= C = US, ST = California, L = Cupertino, O = Apple Inc., OU = FDB Team, CN = FDB LibTLS Plugin Test Root CA
-----BEGIN CERTIFICATE-----
MIIEEzCCAvugAwIBAgIJALOPTrQGpeskMA0GCSqGSIb3DQEBBQUAMIGRMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5v
MRMwEQYDVQQKDApBcHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTExMC8GA1UE
AwwoRkRCIExpYlRMUyBQbHVnaW4gVGVzdCBJbnRlcm1lZGlhdGUgQ0EgMjAeFw0x
ODA0MDcxNDE2MDJaFw0yODA0MDQxNDE2MDJaMIGdMQswCQYDVQQGEwJBVTEYMBYG
A1UECAwPTmV3IFNvdXRoIFdhbGVzMQ8wDQYDVQQHDAZTeWRuZXkxGjAYBgNVBAoM
EUFwcGxlIFB0eSBMaW1pdGVkMREwDwYDVQQLDAhGREIgVGVhbTE0MDIGA1UEAwwr
RkRCIExpYlRMUyBQbHVnaW4gVGVzdCBTZXJ2ZXIgMiwgwoAgPAErAj0DPjCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALAolQZIGMeL5w/Bu2X6lHWjO58u
+HUDtBmr37So4jazhZBSFDBg+QlRMiYGLev9EhvCrUsVcRwtvtcuMI3wfKl7qgbi
ZX8zmrzZ3YJo9U47NzCa05faOl8uSBvuXuXUBLU342WFP8XDB1W8yOBQMK73xoFv
DkcxURx9ZtOhdC3EgYKrFqOB1Azl1DB4gLV3h9rHW5QpQ8SqD9CyggcDBpDeZQIP
+4l5YFE9Nb4kEUTscz2wGn4TdHMmcnVpfUxp1Y2o8Umvh4llXHIPhximGb3JJ4QQ
Sir4ZXeeoooWoJG0sdlqVLroKav/VMGtEu9LyfbrNdKnTJq3ceVQ+HJ2hlMCAwEA
AaNgMF4wHQYDVR0OBBYEFH61Z8O9vFsVdhM4MBU3poX2UMTEMB8GA1UdIwQYMBaA
FJFP+HFpDrD0BRU0yE606s6xkqFBMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQD
AgeAMA0GCSqGSIb3DQEBBQUAA4IBAQCVbxlLGIBCo6/XXjqoMyZc7uQZJj7pGnwh
nIMs2izCLfax8j+QrThO2Qjn03zT/WF8eG6ibPbjgnw3VFwCkV6oQ+BXG6Yt0xqP
4rz1LzxSio6HSm26gSk4SQUsVoAtz3OImoTCFVfz+Mixe87pyVXXEEtCYvfU74H9
I1WGyNkWAxiJbqeIxF5PKoc3EdnT5mfdC6sdeGm7t2neeS8PDFQtJ4UfVIEK5z1C
MOfQILNkLX2nBYxNqKpV66zf68VZNN9002ZH2FITGqImpj74BEws3sheiuZySdoI
wnAwRnymIMfAmkf9C7Q2ugId0YMMyesaWrIwSlXlJOHGsA1VrBRD
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEADCCAuigAwIBAgIJALOPTrQGpesiMA0GCSqGSIb3DQEBBQUAMIGHMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJQ3VwZXJ0aW5v
MRMwEQYDVQQKDApBcHBsZSBJbmMuMREwDwYDVQQLDAhGREIgVGVhbTEnMCUGA1UE
AwweRkRCIExpYlRMUyBQbHVnaW4gVGVzdCBSb290IENBMB4XDTE4MDQwNzE0MTYw
MVoXDTI4MDQwNDE0MTYwMVowgZExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
Zm9ybmlhMRIwEAYDVQQHDAlDdXBlcnRpbm8xEzARBgNVBAoMCkFwcGxlIEluYy4x
ETAPBgNVBAsMCEZEQiBUZWFtMTEwLwYDVQQDDChGREIgTGliVExTIFBsdWdpbiBU
ZXN0IEludGVybWVkaWF0ZSBDQSAyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEApTSBCiUb0amf+QRV2WY6b3bK93D/PSrm4KR/2m2V0lciU1DAk00/kZ52
ZIZmq8g9EaE2+CaDtU0fMvDZpaZD+vTFRwsx4varehq0ZwX9Wt25i/3G/eGLNlD3
9E4tDNruK5UQjum4nJ0SV+AdFEGkSfeU3ZJEHYH0NrcbyAUbh0KeWCSwHiYiFJJf
gBYwRq/HdKNoS/4YvLXzTLR7BSm3YcqWlO5tdkJ2lcT/7Th/Hq1TCW/FKwdQJJBq
JrbOYGlMrf1pLO7Drei/xhsYkwTQ899MhSjkBRhc+401p41Mky0n8wLkuPJGhoY3
9QUOjT+Rmvq5yryg0eWGiFquk6Ru5QIDAQABo2MwYTAdBgNVHQ4EFgQUkU/4cWkO
sPQFFTTITrTqzrGSoUEwHwYDVR0jBBgwFoAUnqtGja3O5jGlh5vHgp3Tf8NCPKkw
DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQAD
ggEBAJfCHU7dm2/2ASyt3wyxivQLxlV6FsEZcF7HcpbbxuB73frGOL4kEoOxvr2X
fBGyjlPMotbc1MeAalAv+hVHdcAcBFPF7lxtYiV6D7YI5T5yVbWSASG3+DMAiW6S
GdQi2eyeh00nH7Y1IkW+yaky0enBtWLzrw+XzHl6xT6DIEJnir//PNxvgXTJ5sjk
6eFAm8HJIqkNQmgfChMQfUH6nm66WwULW6I117RCSkXhIgxZ7wzDq8bXcEdXCrZk
yy5ket9OiVpbd38JgdYirBLmCQVq0uDOOPLz4ZJmNCzQzEt+38AAK2azAk/eb8W9
JaKWH+5V8lhlyGw1zQKdNEP/wg8=
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCwKJUGSBjHi+cP
wbtl+pR1ozufLvh1A7QZq9+0qOI2s4WQUhQwYPkJUTImBi3r/RIbwq1LFXEcLb7X
LjCN8Hype6oG4mV/M5q82d2CaPVOOzcwmtOX2jpfLkgb7l7l1AS1N+NlhT/FwwdV
vMjgUDCu98aBbw5HMVEcfWbToXQtxIGCqxajgdQM5dQweIC1d4fax1uUKUPEqg/Q
soIHAwaQ3mUCD/uJeWBRPTW+JBFE7HM9sBp+E3RzJnJ1aX1MadWNqPFJr4eJZVxy
D4cYphm9ySeEEEoq+GV3nqKKFqCRtLHZalS66Cmr/1TBrRLvS8n26zXSp0yat3Hl
UPhydoZTAgMBAAECggEAVD60NlLYduXzVNfDtVuHEFNGOjSOYfepc/V8gLubo6lr
IMAAI7rcnpYUM5cU8x0OQfRyR8wzUdSWxfWzBs6R78PSZoRzIcgeIl7Wzn0/g3BS
To5czuxwqgBKQAFZpPQmZDwcJfr5qqxAn8IvFweCoMqiRlhELcvqDIP0XxWBqDjc
TNJ988XzZXQmJbjjpWOkUBy2Uqz8lZt8MmxKFpW7SW4tBJwPphnorgjWfjCV/VEh
ORio0rG74NHFo4f1TSrdU2BcB2cbVJ4B+bcUYRdvYmS5bmokhGF8vir0l43gUEdz
Fyk6MaPrTI6cinqzenm3q/0eRvNhBE56U0tiGLn14QKBgQDkCkt1Y4LEboSwsVYl
IXriStqj9p9MOizihh0enhzRXTTQuLX82fNi+bh1LAluwv290Q57pvKa+hB/YciB
o4s7QfSojxQY9DxqvXN7CvxPWXHTyFY5sL4Rm807+C/a9rd39MxBynz9u/7YRvsA
s8v8Y/01qIHnTo+mpDvu6HttWwKBgQDFwdRkgstuE+dXZZe8g1ivh3RNPa968TE3
b8rzF9/nOJV7f6B/n6YEmHD/cHF5mm1bR+zt/jtf1NCRMpazchw3vT3JzQZYMDnM
SD6vxTs5rG47QLiNyTIRmmD4gsEWBpyvoyP8E/9QdfDT1bWI5zZnky9CquRlN+cu
J1bTsefEaQKBgGJsRxFNd91MThztDV9NSfptkFyAT1TZLxI+DEdwusNqVSdY8cNG
VpP7cC+yaAfURSwuFPAtqDxXfdNc4uuBKNDUsMInrubuUz1Gs5cBsNCWrFhZ+U1B
CWgUNMqTXiRFo/40PAyRVs003NOAH0m4UGyIw3rrVdX9xGaKMAv3b35NAoGATkkl
I4UDs1f9xQNaxi3Y9ePRjqJUzX6d1SxUU1eoM4ia5IDpsJwqxLb0RKrmwRT5JaGb
kbuLFazRxCkar38E3Kv1weWAFXlB6DTRXBPgFjzEhoBgjwCO6ZkLulVIysdjT8Rt
gmUINXn7FGENtFyTlP0XQHUWZVt0ETlRjgxni8ECgYBYv6MoSr0iPjQpxeKvwFDz
d9zE+ZXN+3GwtkI340lKRSc/f0Uq1TlC2w+DzjyyXcrBwubMQKTKcQQSH9f3YbMu
DuxVE9AXdlQ1gSQHGjS0qUWwsS/8Xcjk8ZuduAXPGr/MsvsW+FbbZqG8qdZTeMHu
MSTpOxu9HXC8SHML+y0cpw==
-----END PRIVATE KEY-----

157
FDBLibTLS/verify-test.cpp Normal file
View File

@ -0,0 +1,157 @@
/*
* verify-test.cpp
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <iostream>
#include <string>
#include <vector>
#include <openssl/obj_mac.h>
#include "ITLSPlugin.h"
#include "ReferenceCounted.h"
#include "FDBLibTLSPlugin.h"
#include "FDBLibTLSPolicy.h"
struct FDBLibTLSVerifyTest {
FDBLibTLSVerifyTest(std::string input):
input(input), valid(false), verify_cert(true), verify_time(true), subject_criteria({}), issuer_criteria({}) {};
FDBLibTLSVerifyTest(std::string input, bool verify_cert, bool verify_time, std::map<int, std::string> subject, std::map<int, std::string> issuer):
input(input), valid(true), verify_cert(verify_cert), verify_time(verify_time), subject_criteria(subject), issuer_criteria(issuer) {};
~FDBLibTLSVerifyTest() {};
int run();
std::string input;
bool valid;
bool verify_cert;
bool verify_time;
std::map<int, std::string> subject_criteria;
std::map<int, std::string> issuer_criteria;
};
static std::string printable( std::string const& val ) {
static char const digits[] = "0123456789ABCDEF";
std::string s;
for ( int i = 0; i < val.size(); i++ ) {
uint8_t b = val[i];
if (b >= 32 && b < 127 && b != '\\')
s += (char)b;
else if (b == '\\')
s += "\\\\";
else {
s += "\\x";
s += digits[(b >> 4) & 15];
s += digits[b & 15];
}
}
return s;
}
static std::string criteriaToString(std::map<int, std::string> const& criteria) {
std::string s;
for (auto &pair: criteria) {
s += "{" + std::to_string(pair.first) + ":" + printable(pair.second) + "}";
}
return "{" + s + "}";
}
static void logf(const char* event, void* uid, int is_error, ...) {
}
int FDBLibTLSVerifyTest::run() {
FDBLibTLSPlugin *plugin = new FDBLibTLSPlugin();
FDBLibTLSPolicy *policy = new FDBLibTLSPolicy(Reference<FDBLibTLSPlugin>::addRef(plugin), (ITLSLogFunc)logf);
bool rc = policy->set_verify_peers((const uint8_t *)input.c_str(), input.size());
if (rc != valid) {
if (valid) {
std::cerr << "FAIL: Verify test failed, but should have succeeded - '" << input << "'\n";
return 1;
} else {
std::cerr << "FAIL: Verify test should have failed, but succeeded - '" << input << "'\n";
return 1;
}
}
if (policy->verify_cert != verify_cert) {
std::cerr << "FAIL: Got verify cert " << policy->verify_cert << ", want " << verify_cert << "\n";
return 1;
}
if (policy->verify_time != verify_time) {
std::cerr << "FAIL: Got verify time " << policy->verify_time << ", want " << verify_time << "\n";
return 1;
}
if (policy->subject_criteria != subject_criteria) {
std::cerr << "FAIL: Got subject criteria " << criteriaToString(policy->subject_criteria) << ", want " << criteriaToString(subject_criteria) << "\n";
return 1;
}
if (policy->issuer_criteria != issuer_criteria) {
std::cerr << "FAIL: Got issuer criteria " << criteriaToString(policy->issuer_criteria) << ", want " << criteriaToString(issuer_criteria) << "\n";
return 1;
}
return 0;
}
int main(int argc, char **argv)
{
int failed = 0;
std::vector<FDBLibTLSVerifyTest> tests = {
FDBLibTLSVerifyTest("", true, true, {}, {}),
FDBLibTLSVerifyTest("Check.Valid=1", true, true, {}, {}),
FDBLibTLSVerifyTest("Check.Valid=0", false, true, {}, {}),
FDBLibTLSVerifyTest("Check.Unexpired=1", true, true, {}, {}),
FDBLibTLSVerifyTest("Check.Unexpired=0", true, false, {}, {}),
FDBLibTLSVerifyTest("Check.Valid=1,Check.Unexpired=0", true, false, {}, {}),
FDBLibTLSVerifyTest("Check.Unexpired=0,Check.Valid=0", false, false, {}, {}),
FDBLibTLSVerifyTest("Check.Unexpired=0,I.C=US,C=US,S.O=XYZCorp\\, LLC", true, false,
{{NID_countryName, "US"}, {NID_organizationName, "XYZCorp, LLC"}}, {{NID_countryName, "US"}}),
FDBLibTLSVerifyTest("Check.Unexpired=0,I.C=US,C=US,S.O=XYZCorp\\= LLC", true, false,
{{NID_countryName, "US"}, {NID_organizationName, "XYZCorp= LLC"}}, {{NID_countryName, "US"}}),
FDBLibTLSVerifyTest("Check.Unexpired=0,I.C=US,C=US,S.O=XYZCorp=LLC", true, false,
{{NID_countryName, "US"}, {NID_organizationName, "XYZCorp=LLC"}}, {{NID_countryName, "US"}}),
FDBLibTLSVerifyTest("I.C=US,C=US,Check.Unexpired=0,S.O=XYZCorp=LLC", true, false,
{{NID_countryName, "US"}, {NID_organizationName, "XYZCorp=LLC"}}, {{NID_countryName, "US"}}),
FDBLibTLSVerifyTest("I.C=US,C=US,S.O=XYZCorp\\, LLC", true, true,
{{NID_countryName, "US"}, {NID_organizationName, "XYZCorp, LLC"}}, {{NID_countryName, "US"}}),
FDBLibTLSVerifyTest("C=\\,S=abc", true, true, {{NID_countryName, ",S=abc"}}, {}),
FDBLibTLSVerifyTest("CN=\\61\\62\\63", true, true, {{NID_commonName, "abc"}}, {}),
FDBLibTLSVerifyTest("CN=a\\62c", true, true, {{NID_commonName, "abc"}}, {}),
FDBLibTLSVerifyTest("CN=a\\01c", true, true, {{NID_commonName, "a\001c"}}, {}),
// Invalid cases.
FDBLibTLSVerifyTest("Check.Invalid=0"),
FDBLibTLSVerifyTest("Valid=1"),
FDBLibTLSVerifyTest("C= US,S=abc"),
FDBLibTLSVerifyTest("C=#US,S=abc"),
FDBLibTLSVerifyTest("C=abc,S=\\"),
FDBLibTLSVerifyTest("XYZ=abc"),
FDBLibTLSVerifyTest("GN=abc"),
FDBLibTLSVerifyTest("CN=abc,Check.Expired=1"),
};
for (auto &test: tests)
failed |= test.run();
return (failed);
}

View File

@ -92,8 +92,8 @@ STATIC_LIBS :=
VPATH += $(addprefix :,$(filter-out lib,$(patsubst -L%,%,$(filter -L%,$(LDFLAGS)))))
CS_PROJECTS := flow/actorcompiler flow/coveragetool fdbclient/vexillographer
CPP_PROJECTS := flow fdbrpc fdbclient fdbbackup fdbserver fdbcli bindings/c bindings/java fdbmonitor bindings/flow/tester bindings/flow
OTHER_PROJECTS := bindings/python bindings/ruby bindings/nodejs bindings/go
CPP_PROJECTS := flow fdbrpc fdbclient fdbbackup fdbserver fdbcli bindings/c bindings/java fdbmonitor bindings/flow/tester bindings/flow FDBLibTLS
OTHER_PROJECTS := bindings/python bindings/ruby bindings/go
CS_MK_GENERATED := $(CS_PROJECTS:=/generated.mk)
CPP_MK_GENERATED := $(CPP_PROJECTS:=/generated.mk)
@ -127,7 +127,7 @@ else
endif
@echo "#define FDB_VT_PACKAGE_NAME \"$(PACKAGE_NAME)\"" >> $@
bindings: fdb_c fdb_python fdb_ruby fdb_java fdb_node fdb_flow fdb_flow_tester fdb_go fdb_go_tester
bindings: fdb_c fdb_python fdb_ruby fdb_java fdb_flow fdb_flow_tester fdb_go fdb_go_tester
Makefiles: $(MK_GENERATED)
@ -148,7 +148,7 @@ clean: $(CLEAN_TARGETS) docpreview_clean
@echo "Cleaning toplevel"
@rm -rf $(OBJDIR)
@rm -rf $(DEPSDIR)
@rm -rf lib/libstdc++.a
@rm -rf lib/
@rm -rf bin/coverage.*.xml
targets:
@ -174,13 +174,13 @@ lib/libstdc++.a: $(shell $(CC) -print-file-name=libstdc++_pic.a)
@ar rcs $@ .libstdc++/*.o
@rm -r .libstdc++
docpreview: javadoc godoc
docpreview: javadoc
TARGETS= $(MAKE) -C documentation docpreview
docpreview_clean:
CLEAN_TARGETS= $(MAKE) -C documentation docpreview_clean
packages/foundationdb-docs-$(VERSION).tar.gz: FORCE javadoc godoc
packages/foundationdb-docs-$(VERSION).tar.gz: FORCE javadoc
TARGETS= $(MAKE) -C documentation docpackage
@mkdir -p packages
@rm -f packages/foundationdb-docs-$(VERSION).tar.gz

View File

@ -1,3 +1,52 @@
# FoundationDB
<img alt="FoundationDB logo" src="documentation/FDB_logo.png?raw=true" width="400">
FoundationDB is a distributed database designed to handle large volumes of structured data across clusters of commodity servers. It organizes data as an ordered key-value store and employs ACID transactions for all operations. It is especially well-suited for read/write workloads but also has excellent performance for write-intensive workloads. Users interact with the database using API language binding.
To learn more about FoundationDB, visit [foundationdb.org](https://www.foundationdb.org/)
## Documentation
Documentation can be found online at <https://apple.github.io/foundationdb/>. The documentation covers details of API usage, background information on design philosophy, and extensive usage examples. Docs are built from the [source in this repo](documentation/sphinx/source).
## Forums
[The FoundationDB Forums](https://forums.foundationdb.org/) are the home for most of the discussion and communication about the FoundationDB project. We welcome your participation! We want FoundationDB to be a great project to be a part of and, as part of that, have established a [Code of Conduct](CODE_OF_CONDUCT.md) to establish what constitutes permissible modes of interaction.
## Contributing
Contributing to FoundationDB can be in contributions to the code base, sharing your experience and insights in the community on the Forums, or contributing to projects that make use of FoundationDB. Please see the [contributing guide](CONTRIBUTING.md) for more specifics.
## Getting Started
### Binary downloads
Developers interested in using the FoundationDB store for an application can get started easily by downloading and installing a binary package. Please see the [downloads page](https://www.foundationdb.org/download/) for a list of available packages.
### Compiling from source
Developers on a OS for which there is no binary package, or who would like to start hacking on the code can get started by compiling from source.
#### macOS
1. Check out this repo on your Mac.
1. Install the Xcode command-line tools.
1. Download version 1.52 of [Boost](https://sourceforge.net/projects/boost/files/boost/1.52.0/).
1. Set the `BOOSTDIR` environment variable to the location containing this boost installation.
1. Install [Mono](http://www.mono-project.com/download/stable/).
1. Install a [JDK](http://www.oracle.com/technetwork/java/javase/downloads/index.html). FoundationDB currently builds with Java 8.
1. Navigate to the directory where you checked out the foundationdb repo.
1. Run `make`.
#### Linux
1. Install [Docker](https://www.docker.com/).
1. Check out the foundationdb repo.
1. Build Linux docker image using the file `Dockerfile` located in the `build` source directory.
1. Run the docker image interactively [Docker Run](https://docs.docker.com/engine/reference/run/#general-form) with the directory containing the foundationdb repo mounted [Docker Mounts](https://docs.docker.com/storage/volumes/).
`docker run -it -v '/local/dir/path/foundationdb:/docker/dir/path/foundationdb' /bin/bash`
1. Navigate to the mounted directory containing the foundationdb repo.
`cd /docker/dir/path/foundationdb`
1. Run `make`.
This will build the fdbserver binary and the python bindings. If you want to build our other bindings, you will need to install a runtime for the language whose binding you want to build. Each binding has an `.mk` file which provides specific targets for that binding.

View File

@ -58,8 +58,6 @@ _java_cmd = 'java -ea -cp %s:%s com.apple.foundationdb.test.' % (
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),

View File

@ -25,7 +25,7 @@ BREAKONERROR="${BREAKONERROR:-0}"
RUNSCRIPTS="${RUNSCRIPTS:-1}"
RUNTESTS="${RUNTESTS:-1}"
RANDOMTEST="${RANDOMTEST:-0}"
BINDINGTESTS="${BINDINGTESTS:-python python3 java java_async ruby node go flow}"
BINDINGTESTS="${BINDINGTESTS:-python python3 java java_async ruby go flow}"
LOGLEVEL="${LOGLEVEL:-INFO}"
_BINDINGTESTS=(${BINDINGTESTS})
DISABLEDTESTS=()

View File

@ -24,7 +24,6 @@ function run_scripted() {
scripted ruby
scripted java
scripted java_async
scripted node
scripted go
scripted flow
}
@ -40,8 +39,6 @@ while `true`; do
run ruby
run java
run java_async
run node
#run streamline
run go
run flow
done

View File

@ -5,9 +5,9 @@ Your API test program must implement a simple stack machine that exercises the
FoundationDB API. The program is invoked with two or three arguments. The first
argument is a prefix that is the first element of a tuple, the second is the
API version, and the third argument is the path to a cluster file. If the
third argument is not specified, your program may assume that fdb.open() will
succeed with no arguments (an fdb.cluster file will exist in the current
directory). Otherwise, your program should connect to the cluster specified
third argument is not specified, your program may assume that `fdb.open()` will
succeed with no arguments (an fdb.cluster file will exist in the current
directory). Otherwise, your program should connect to the cluster specified
by the given cluster file.
Your stack machine should begin reading the range returned by the tuple range
@ -38,7 +38,7 @@ instructions:
and a peek operation. The stack is initialized to be empty.
- A current FDB transaction name (stored as a byte string). The transaction
name should be initialized to the prefix that instructions are being read
name should be initialized to the prefix that instructions are being read
from.
- A last seen FDB version, which is a 64-bit integer.
@ -47,44 +47,44 @@ instructions:
Data Operations
---------------
PUSH <item>
#### PUSH &lt;item&gt;
Pushes the provided item onto the stack.
DUP
#### DUP
Duplicates the top item on the stack. The instruction number for the
duplicate item should be the same as the original.
EMPTY_STACK
#### EMPTY_STACK
Discards all items in the stack.
SWAP
#### SWAP
Pops the top item off of the stack as INDEX. Swaps the items in the stack at
depth 0 and depth INDEX. Does not modify the instruction numbers of the
swapped items.
POP
#### POP
Pops and discards the top item on the stack.
SUB
#### SUB
Pops the top two items off of the stack as A and B and then pushes the
difference (A-B) onto the stack. A and B may be assumed to be integers.
CONCAT
#### CONCAT
Pops the top two items off the stack as A and B and then pushes the
Pops the top two items off the stack as A and B and then pushes the
concatenation of A and B onto the stack. A and B can be assumed to
be of the same type and will be either byte strings or unicode strings.
LOG_STACK
#### LOG_STACK
Pops the top item off the stack as PREFIX. Using a new transaction with normal
retry logic, inserts a key-value pair into the database for each item in the
retry logic, inserts a key-value pair into the database for each item in the
stack of the form:
PREFIX + tuple.pack((stackIndex, instructionNumber)) = tuple.pack((item,))
@ -96,8 +96,8 @@ LOG_STACK
then the value should be truncated to the first 40000 bytes of the packed
tuple.
When finished, the stack should be empty. Note that because the stack may be
large, it may be necessary to commit the transaction every so often (e.g.
When finished, the stack should be empty. Note that because the stack may be
large, it may be necessary to commit the transaction every so often (e.g.
after every 100 sets) to avoid past_version errors.
FoundationDB Operations
@ -117,7 +117,7 @@ should simulate it using an anonymous transaction. Remember that set and clear
operations must immediately commit (with appropriate retry behavior!).
Any error that bubbles out of these operations must be caught. In the event of
an error, you must push the packed tuple of the string "ERROR" and the error
an error, you must push the packed tuple of the string `"ERROR"` and the error
code (as a string, not an integer).
Some operations may allow you to push future values onto the stack. When popping
@ -132,25 +132,25 @@ futures must apply the following rules to the result:
- If the result is void (i.e. the future was just a signal of
completion), then its value should be the byte string
"RESULT_NOT_PRESENT"
`"RESULT_NOT_PRESENT"`
- If the result is from a GET operation in which no result was
returned, then its value is to be converted to the byte string
"RESULT_NOT_PRESENT"
`"RESULT_NOT_PRESENT"`
NEW_TRANSACTION
#### NEW_TRANSACTION
Creates a new transaction and stores it in the global transaction map
under the currently used transaction name.
USE_TRANSACTION
#### USE_TRANSACTION
Pop the top item off of the stack as TRANSACTION_NAME. Begin using the
transaction stored at TRANSACTION_NAME in the transaction map for future
operations. If no entry exists in the map for the given name, a new
transaction should be inserted.
ON_ERROR
#### ON_ERROR
Pops the top item off of the stack as ERROR_CODE. Passes ERROR_CODE in a
language-appropriate way to the on_error method of current transaction
@ -158,22 +158,22 @@ ON_ERROR
the error out as indicated above. May optionally push a future onto the
stack.
GET (_SNAPSHOT, _DATABASE)
#### GET (_SNAPSHOT, _DATABASE)
Pops the top item off of the stack as KEY and then looks up KEY in the
database using the get() method. May optionally push a future onto the
stack.
GET_KEY (_SNAPSHOT, _DATABASE)
#### GET_KEY (_SNAPSHOT, _DATABASE)
Pops the top four items off of the stack as KEY, OR_EQUAL, OFFSET, PREFIX
and then constructs a key selector. This key selector is then resolved
using the get_key() method to yield RESULT. If RESULT starts with PREFIX,
then RESULT is pushed onto the stack. Otherwise, if RESULT < PREFIX, PREFIX
and then constructs a key selector. This key selector is then resolved
using the get_key() method to yield RESULT. If RESULT starts with PREFIX,
then RESULT is pushed onto the stack. Otherwise, if RESULT < PREFIX, PREFIX
is pushed onto the stack. If RESULT > PREFIX, then strinc(PREFIX) is pushed
onto the stack. May optionally push a future onto the stack.
GET_RANGE (_SNAPSHOT, _DATABASE)
#### GET_RANGE (_SNAPSHOT, _DATABASE)
Pops the top five items off of the stack as BEGIN_KEY, END_KEY, LIMIT,
REVERSE and STREAMING_MODE. Performs a range read in a language-appropriate
@ -181,103 +181,103 @@ GET_RANGE (_SNAPSHOT, _DATABASE)
packed into a tuple as [k1,v1,k2,v2,...,kn,vn], and this single packed value
is pushed onto the stack.
GET_RANGE_STARTS_WITH (_SNAPSHOT, _DATABASE)
#### GET_RANGE_STARTS_WITH (_SNAPSHOT, _DATABASE)
Pops the top four items off of the stack as PREFIX, LIMIT, REVERSE and
STREAMING_MODE. Performs a prefix range read in a language-appropriate way
using these parameters. Output is pushed onto the stack as with GET_RANGE.
GET_RANGE_SELECTOR (_SNAPSHOT, _DATABASE)
#### GET_RANGE_SELECTOR (_SNAPSHOT, _DATABASE)
Pops the top ten items off of the stack as BEGIN_KEY, BEGIN_OR_EQUAL,
BEGIN_OFFSET, END_KEY, END_OR_EQUAL, END_OFFSET, LIMIT, REVERSE,
STREAMING_MODE, and PREFIX. Constructs key selectors BEGIN and END from
STREAMING_MODE, and PREFIX. Constructs key selectors BEGIN and END from
the first six parameters, and then performs a range read in a language-
appropriate way using BEGIN, END, LIMIT, REVERSE and STREAMING_MODE. Output
is pushed onto the stack as with GET_RANGE, excluding any keys that do not
appropriate way using BEGIN, END, LIMIT, REVERSE and STREAMING_MODE. Output
is pushed onto the stack as with GET_RANGE, excluding any keys that do not
begin with PREFIX.
GET_READ_VERSION (_SNAPSHOT)
#### GET_READ_VERSION (_SNAPSHOT)
Gets the current read version and stores it in the internal stack machine
state as the last seen version. Pushed the string "GOT_READ_VERSION" onto
the stack.
GET_VERSIONSTAMP
#### GET_VERSIONSTAMP
Calls get_versionstamp and pushes the resulting future onto the stack.
SET (_DATABASE)
#### SET (_DATABASE)
Pops the top two items off of the stack as KEY and VALUE. Sets KEY to have
the value VALUE. A SET_DATABASE call may optionally push a future onto the
stack.
SET_READ_VERSION
#### SET_READ_VERSION
Sets the current transaction read version to the internal state machine last
seen version.
CLEAR (_DATABASE)
#### CLEAR (_DATABASE)
Pops the top item off of the stack as KEY and then clears KEY from the
database. A CLEAR_DATABASE call may optionally push a future onto the stack.
CLEAR_RANGE (_DATABASE)
#### CLEAR_RANGE (_DATABASE)
Pops the top two items off of the stack as BEGIN_KEY and END_KEY. Clears the
range of keys from BEGIN_KEY to END_KEY in the database. A
CLEAR_RANGE_DATABASE call may optionally push a future onto the stack.
CLEAR_RANGE_STARTS_WITH (_DATABASE)
#### CLEAR_RANGE_STARTS_WITH (_DATABASE)
Pops the top item off of the stack as PREFIX and then clears all keys from
the database that begin with PREFIX. A CLEAR_RANGE_STARTS_WITH_DATABASE call
may optionally push a future onto the stack.
ATOMIC_OP (_DATABASE)
#### ATOMIC_OP (_DATABASE)
Pops the top three items off of the stack as OPTYPE, KEY, and VALUE.
Performs the atomic operation described by OPTYPE upon KEY with VALUE. An
ATOMIC_OP_DATABASE call may optionally push a future onto the stack.
READ_CONFLICT_RANGE and WRITE_CONFLICT_RANGE
#### READ_CONFLICT_RANGE and WRITE_CONFLICT_RANGE
Pops the top two items off of the stack as BEGIN_KEY and END_KEY. Adds a
read conflict range or write conflict range from BEGIN_KEY to END_KEY.
Pushes the byte string "SET_CONFLICT_RANGE" onto the stack.
READ_CONFLICT_KEY and WRITE_CONFLICT_KEY
#### READ_CONFLICT_KEY and WRITE_CONFLICT_KEY
Pops the top item off of the stack as KEY. Adds KEY as a read conflict key
or write conflict key. Pushes the byte string "SET_CONFLICT_KEY" onto the
stack.
DISABLE_WRITE_CONFLICT
#### DISABLE_WRITE_CONFLICT
Sets the NEXT_WRITE_NO_WRITE_CONFLICT_RANGE transaction option on the
current transaction. Does not modify the stack.
COMMIT
#### COMMIT
Commits the current transaction (with no retry behavior). May optionally
push a future onto the stack.
RESET
#### RESET
Resets the current transaction.
CANCEL
#### CANCEL
Cancels the current transaction.
GET_COMMITTED_VERSION
#### GET_COMMITTED_VERSION
Gets the committed version from the current transaction and stores it in the
internal stack machine state as the last seen version. Pushes the byte
string "GOT_COMMITTED_VERSION" onto the stack.
WAIT_FUTURE
#### WAIT_FUTURE
Pops the top item off the stack and pushes it back on. If the top item on
the stack is a future, this will have the side effect of waiting on the
@ -287,13 +287,13 @@ WAIT_FUTURE
Tuple Operations
----------------
TUPLE_PACK
#### TUPLE_PACK
Pops the top item off of the stack as N. Pops the next N items off of the
stack and packs them as the tuple [item0,item1,...,itemN], and then pushes
this single packed value onto the stack.
TUPLE_PACK_WITH_VERSIONSTAMP
#### TUPLE_PACK_WITH_VERSIONSTAMP
Pops the top item off of the stack as a byte string prefix. Pops the next item
off of the stack as N. Pops the next N items off of the stack and packs them
@ -307,20 +307,20 @@ TUPLE_PACK_WITH_VERSIONSTAMP
do not contain a 'Versionstamp' tuple-type do not have to implement this
operation.)
TUPLE_UNPACK
#### TUPLE_UNPACK
Pops the top item off of the stack as PACKED, and then unpacks PACKED into a
tuple. For each element of the tuple, packs it as a new tuple and pushes it
onto the stack.
TUPLE_RANGE
#### TUPLE_RANGE
Pops the top item off of the stack as N. Pops the next N items off of the
stack, and passes these items as a tuple (or array, or language-appropriate
structure) to the tuple range method. Pushes the begin and end elements of
the returned range onto the stack.
TUPLE_SORT
#### TUPLE_SORT
Pops the top item off of the stack as N. Pops the next N items off of the
stack as packed tuples (i.e., byte strings), unpacks them, sorts the tuples,
@ -330,25 +330,25 @@ TUPLE_SORT
use that to sort. Otherwise, it should sort them lexicographically by
their byte representation. The choice of function should not affect final sort order.
ENCODE_FLOAT
#### ENCODE_FLOAT
Pops the top item off of the stack. This will be a byte-string of length 4
containing the IEEE 754 encoding of a float in big-endian order.
This is then converted into a float and pushed onto the stack.
ENCODE_DOUBLE
#### ENCODE_DOUBLE
Pops the top item off of the stack. This will be a byte-string of length 8
containing the IEEE 754 encoding of a double in big-endian order.
This is then converted into a double and pushed onto the stack.
DECODE_FLOAT
#### DECODE_FLOAT
Pops the top item off of the stack. This will be a single-precision float.
This is converted into a (4 byte) byte-string of its IEEE 754 representation
in big-endian order, and pushed onto the stack.
DECODE_DOUBLE
#### DECODE_DOUBLE
Pops the top item off of the stack. This will be a double-precision float.
This is converted into a (8 byte) byte-string its IEEE 754 representation
@ -358,7 +358,7 @@ DECODE_DOUBLE
Thread Operations
-----------------
START_THREAD
#### START_THREAD
Pops the top item off of the stack as PREFIX. Creates a new stack machine
instance operating on the same database as the current stack machine, but
@ -366,7 +366,7 @@ START_THREAD
state. The new stack machine should begin executing instructions concurrent
with the current stack machine through a language-appropriate mechanism.
WAIT_EMPTY
#### WAIT_EMPTY
Pops the top item off of the stack as PREFIX. Blocks execution until the
range with prefix PREFIX is not present in the database. This should be
@ -378,7 +378,7 @@ WAIT_EMPTY
Miscellaneous
-------------
UNIT_TESTS
#### UNIT_TESTS
This is called during the scripted test to allow bindings to test features
which aren't supported by the stack tester. Things currently tested in the

View File

@ -8,19 +8,19 @@ directory testing state.
Additional State and Initialization
-----------------------------------
Your tester should store three additional pieces of state.
Your tester should store three additional pieces of state.
directory list - The items in this list should be accessible by index. The list
should support an append operation. It will be required to store Subspaces,
* directory list - The items in this list should be accessible by index. The list
should support an append operation. It will be required to store Subspaces,
DirectorySubspaces, and DirectoryLayers.
directory list index - an index into the directory list of the currently active
* directory list index - an index into the directory list of the currently active
directory.
error index - the index to use when the directory at directory list index is not
* error index - the index to use when the directory at directory list index is not
present
At the beginning of the test, the list should contain just the default directory
At the beginning of the test, the list should contain just the default directory
layer. The directory index and error index should both be set to 0.
Popping Tuples
@ -29,14 +29,14 @@ Popping Tuples
Some instructions will require you to pop N tuples. To do this, repeat the
following procedure N times:
Pop 1 item off the stack as M. Pop M items off the stack as
Pop 1 item off the stack as M. Pop M items off the stack as
tuple = [item1, ..., itemM].
Errors
------
In the even that you encounter an error when performing a directory layer
operation, you should push the byte string: "DIRECTORY_ERROR" onto the stack. If
operation, you should push the byte string: `"DIRECTORY_ERROR"` onto the stack. If
the operation being performed was supposed to append an item to the directory
list, then a null entry should be appended instead.
@ -46,65 +46,65 @@ New Instructions
Below are the new instructions that must be implemented to test the directory
layer. Some instructions specify that the current directory should be used
for the operation. In that case, use the object in the directory list specified
by the current directory list index. Operations that are not defined for a
by the current directory list index. Operations that are not defined for a
particular object will not be called (e.g. a DirectoryLayer will never be asked
to pack a key).
Directory/Subspace/Layer Creation
---------------------------------
DIRECTORY_CREATE_SUBSPACE
#### DIRECTORY_CREATE_SUBSPACE
Pop 1 tuple off the stack as [path]. Pop 1 additional item as [raw_prefix].
Create a subspace with path as the prefix tuple and the specified
Create a subspace with path as the prefix tuple and the specified
raw_prefix. Append it to the directory list.
DIRECTORY_CREATE_LAYER
#### DIRECTORY_CREATE_LAYER
Pop 3 items off the stack as [index1, index2, allow_manual_prefixes]. Let
node_subspace be the object in the directory list at index1 and
content_subspace be the object in the directory list at index2. Create a new
directory layer with the specified node_subspace and content_subspace. If
Pop 3 items off the stack as [index1, index2, allow_manual_prefixes]. Let
node_subspace be the object in the directory list at index1 and
content_subspace be the object in the directory list at index2. Create a new
directory layer with the specified node_subspace and content_subspace. If
allow_manual_prefixes is 1, then enable manual prefixes on the directory
layer. Append the resulting directory layer to the directory list.
If either of the two specified subspaces are null, then do not create a
If either of the two specified subspaces are null, then do not create a
directory layer and instead push null onto the directory list.
DIRECTORY_CREATE_OR_OPEN[_DATABASE]
#### DIRECTORY_CREATE_OR_OPEN[_DATABASE]
Use the current directory for this operation.
Pop 1 tuple off the stack as [path]. Pop 1 additional item as [layer].
create_or_open a directory with the specified path and layer. If layer is
Pop 1 tuple off the stack as [path]. Pop 1 additional item as [layer].
create_or_open a directory with the specified path and layer. If layer is
null, use the default value for that parameter.
DIRECTORY_CREATE[_DATABASE]
#### DIRECTORY_CREATE[_DATABASE]
Pop 1 tuple off the stack as [path]. Pop 2 additional items as
[layer, prefix]. create a directory with the specified path, layer,
and prefix. If either of layer or prefix is null, use the default value for
Pop 1 tuple off the stack as [path]. Pop 2 additional items as
[layer, prefix]. create a directory with the specified path, layer,
and prefix. If either of layer or prefix is null, use the default value for
that parameter (layer='', prefix=null).
DIRECTORY_OPEN[_DATABASE|_SNAPSHOT]
#### DIRECTORY_OPEN[_DATABASE|_SNAPSHOT]
Use the current directory for this operation.
Pop 1 tuple off the stack as [path]. Pop 1 additional item as [layer]. Open
a directory with the specified path and layer. If layer is null, use the
Pop 1 tuple off the stack as [path]. Pop 1 additional item as [layer]. Open
a directory with the specified path and layer. If layer is null, use the
default value (layer='').
Directory Management
--------------------
DIRECTORY_CHANGE
#### DIRECTORY_CHANGE
Pop the top item off the stack as [index]. Set the current directory list
index to index. In the event that the directory at this new index is null
(as the result of a previous error), set the directory list index to the
(as the result of a previous error), set the directory list index to the
error index.
DIRECTORY_SET_ERROR_INDEX
#### DIRECTORY_SET_ERROR_INDEX
Pop the top item off the stack as [error_index]. Set the current error index
to error_index.
@ -112,130 +112,130 @@ DIRECTORY_SET_ERROR_INDEX
Directory Operations
--------------------
DIRECTORY_MOVE[_DATABASE]
#### DIRECTORY_MOVE[_DATABASE]
Use the current directory for this operation.
Pop 2 tuples off the stack as [old_path, new_path]. Call move with the
Pop 2 tuples off the stack as [old_path, new_path]. Call move with the
specified old_path and new_path. Append the result onto the directory list.
DIRECTORY_MOVE_TO[_DATABASE]
#### DIRECTORY_MOVE_TO[_DATABASE]
Use the current directory for this operation.
Pop 1 tuple off the stack as [new_absolute_path]. Call moveTo with the
Pop 1 tuple off the stack as [new_absolute_path]. Call moveTo with the
specified new_absolute_path. Append the result onto the directory list.
DIRECTORY_REMOVE[_DATABASE]
#### DIRECTORY_REMOVE[_DATABASE]
Use the current directory for this operation.
Pop 1 item off the stack as [count] (either 0 or 1). If count is 1, pop 1
tuple off the stack as [path]. Call remove, passing it path if one was
tuple off the stack as [path]. Call remove, passing it path if one was
popped.
DIRECTORY_REMOVE_IF_EXISTS[_DATABASE]
#### DIRECTORY_REMOVE_IF_EXISTS[_DATABASE]
Use the current directory for this operation.
Pop 1 item off the stack as [count] (either 0 or 1). If count is 1, pop 1
tuple off the stack as [path]. Call remove_if_exits, passing it path if one
tuple off the stack as [path]. Call remove_if_exits, passing it path if one
was popped.
DIRECTORY_LIST[_DATABASE|_SNAPSHOT]
#### DIRECTORY_LIST[_DATABASE|_SNAPSHOT]
Use the current directory for this operation.
Pop 1 item off the stack as [count] (either 0 or 1). If count is 1, pop 1
tuple off the stack as [path]. Call list, passing it path if one was popped.
Pack the resulting list of directories using the tuple layer and push the
tuple off the stack as [path]. Call list, passing it path if one was popped.
Pack the resulting list of directories using the tuple layer and push the
packed string onto the stack.
DIRECTORY_EXISTS[_DATABASE|_SNAPSHOT]
#### DIRECTORY_EXISTS[_DATABASE|_SNAPSHOT]
Use the current directory for this operation.
Pop 1 item off the stack as [count] (either 0 or 1). If count is 1, pop 1
tuple off the stack as [path]. Call exists, passing it path if one
tuple off the stack as [path]. Call exists, passing it path if one
was popped. Push 1 onto the stack if the path exists and 0 if it does not.
Subspace Operations
-------------------
DIRECTORY_PACK_KEY
#### DIRECTORY_PACK_KEY
Use the current directory for this operation.
Pop 1 tuple off the stack as [key_tuple]. Pack key_tuple and push the result
onto the stack.
DIRECTORY_UNPACK_KEY
#### DIRECTORY_UNPACK_KEY
Use the current directory for this operation.
Pop 1 item off the stack as [key]. Unpack key and push the resulting tuple
onto the stack one item at a time.
DIRECTORY_RANGE
#### DIRECTORY_RANGE
Use the current directory for this operation.
Pop 1 tuple off the stack as [tuple]. Create a range using tuple and push
Pop 1 tuple off the stack as [tuple]. Create a range using tuple and push
range.begin and range.end onto the stack.
DIRECTORY_CONTAINS
#### DIRECTORY_CONTAINS
Use the current directory for this operation.
Pop 1 item off the stack as [key]. Check if the current directory contains
the specified key. Push 1 if it does and 0 if it doesn't.
DIRECTORY_OPEN_SUBSPACE
#### DIRECTORY_OPEN_SUBSPACE
Use the current directory for this operation.
Pop 1 tuple off the stack as [tuple]. Open the subspace of the current
Pop 1 tuple off the stack as [tuple]. Open the subspace of the current
directory specified by tuple and push it onto the directory list.
Directory Logging
--------------------
DIRECTORY_LOG_SUBSPACE
#### DIRECTORY_LOG_SUBSPACE
Use the current directory for this operation.
Pop 1 item off the stack as [prefix]. Let key equal
Pop 1 item off the stack as [prefix]. Let key equal
prefix + tuple.pack([dir_index]). Set key to be the result of calling
directory.key() in the current transaction.
directory.key() in the current transaction.
DIRECTORY_LOG_DIRECTORY
#### DIRECTORY_LOG_DIRECTORY
Use the current directory for this operation.
Pop 1 item off the stack as [raw_prefix]. Create a subspace log_subspace
Pop 1 item off the stack as [raw_prefix]. Create a subspace log_subspace
with path (dir_index) and the specified raw_prefix. Set:
tr[log_subspace[u'path']] = the tuple packed path of the directory.
tr[log_subspace[u'layer']] = the tuple packed layer of the directory.
tr[log_subspace[u'exists']] = the packed tuple containing a 1 if the
tr[log_subspace[u'exists']] = the packed tuple containing a 1 if the
directory exists and 0 if it doesn't.
tr[log_subspace[u'children']] the tuple packed list of children of the
tr[log_subspace[u'children']] the tuple packed list of children of the
directory.
Where log_subspace[u<str>] is the subspace packed tuple containing only the
Where log_subspace[u<str>] is the subspace packed tuple containing only the
single specified unicode string <str>.
Other
-----
DIRECTORY_STRIP_PREFIX
#### DIRECTORY_STRIP_PREFIX
Use the current directory for this operation.
Pop 1 item off the stack as [byte_array]. Call .key() on the current
subspace and store the result as [prefix]. Throw an error if the popped
array does not start with prefix. Otherwise, remove the prefix from the
Pop 1 item off the stack as [byte_array]. Call .key() on the current
subspace and store the result as [prefix]. Throw an error if the popped
array does not start with prefix. Otherwise, remove the prefix from the
popped array and push the result onto the stack.

View File

@ -102,5 +102,3 @@ 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

@ -1536,7 +1536,6 @@ struct UnitTestsFunc : InstructionFunc {
tr->setOption(FDBTransactionOption::FDB_TR_OPTION_CAUSAL_READ_RISKY);
tr->setOption(FDBTransactionOption::FDB_TR_OPTION_CAUSAL_WRITE_RISKY);
tr->setOption(FDBTransactionOption::FDB_TR_OPTION_READ_YOUR_WRITES_DISABLE);
tr->setOption(FDBTransactionOption::FDB_TR_OPTION_READ_AHEAD_DISABLE);
tr->setOption(FDBTransactionOption::FDB_TR_OPTION_READ_SYSTEM_KEYS);
tr->setOption(FDBTransactionOption::FDB_TR_OPTION_ACCESS_SYSTEM_KEYS);
tr->setOption(FDBTransactionOption::FDB_TR_OPTION_DURABILITY_DEV_NULL_IS_WEB_SCALE);

View File

@ -1,12 +1,12 @@
fdb-go
======
[Go language](http://golang.org) bindings for [FoundationDB](https://www.foundationdb.org/documentation/), a distributed key-value store with ACID transactions.
[Go language](http://golang.org) bindings for [FoundationDB](https://apple.github.io/foundationdb/index.html#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://www.foundationdb.org/downloads/fdb-c/))
- FoundationDB C API 2.0.x, 3.0.x, or 4.x.y (part of the [FoundationDB clients package](https://apple.github.io/foundationdb/downloads.html#c))
Use of this package requires the selection of a FoundationDB API version at runtime. This package currently supports FoundationDB API versions 200-520.
@ -27,5 +27,5 @@ of downloading from the remote repository.
Documentation
-------------
* [API documentation](https://www.foundationdb.org/documentation/godoc/fdb.html)
* [Tutorial](https://www.foundationdb.org/documentation/class-scheduling-go.html)
* [API documentation](https://godoc.org/github.com/apple/foundationdb/bindings/go/src/fdb)
* [Tutorial](https://apple.github.io/foundationdb/class-scheduling.html)

View File

@ -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_fmt fdb_go_fmt_check 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
# We only override if the environment didn't set it (this is used by
# the fdbwebsite documentation build process)
@ -47,7 +47,8 @@ GO_PACKAGE_OUTDIR := $(GOPATH)/pkg/$(GOPLATFORM)/$(GO_IMPORT_PATH)
GO_PACKAGES := fdb fdb/tuple fdb/subspace fdb/directory
GO_PACKAGE_OBJECTS := $(addprefix $(GO_PACKAGE_OUTDIR)/,$(GO_PACKAGES:=.a))
GO_SRC := $(shell find $(CURDIR)/bindings/go/src -name '*.go')
GO_GEN := $(CURDIR)/bindings/go/src/fdb/generated.go
GO_SRC := $(shell find $(CURDIR)/bindings/go/src -name '*.go') $(GO_GEN)
fdb_go: $(GO_PACKAGE_OBJECTS) $(GO_SRC) fdb_go_fmt_check
@ -77,53 +78,26 @@ fdb_go_tester_clean:
@echo "Cleaning fdb_go_tester"
@rm -rf $(GOPATH)/bin
$(GOPATH)/bin/_stacktester: $(GO_DEST)/.stamp $(GO_SRC) $(GO_PACKAGE_OBJECTS) $(GO_DEST)/fdb/generated.go
$(GOPATH)/bin/_stacktester: $(GO_DEST)/.stamp $(GO_SRC) $(GO_PACKAGE_OBJECTS)
@echo "Compiling $(basename $(notdir $@))"
@go install $(GO_IMPORT_PATH)/_stacktester
$(GO_PACKAGE_OUTDIR)/fdb/tuple.a: $(GO_DEST)/.stamp $(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
@echo "Compiling fdb/tuple"
@go install $(GO_IMPORT_PATH)/fdb/tuple
$(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
$(GO_PACKAGE_OUTDIR)/fdb/subspace.a: $(GO_DEST)/.stamp $(GO_SRC) $(GO_PACKAGE_OUTDIR)/fdb.a $(GO_PACKAGE_OUTDIR)/fdb/tuple.a
@echo "Compiling fdb/subspace"
@go install $(GO_IMPORT_PATH)/fdb/subspace
$(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
$(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
@echo "Compiling fdb/directory"
@go install $(GO_IMPORT_PATH)/fdb/directory
$(GO_PACKAGE_OUTDIR)/fdb.a: $(GO_DEST)/.stamp lib/libfdb_c.$(DLEXT) $(GO_SRC) $(GO_DEST)/fdb/generated.go
$(GO_PACKAGE_OUTDIR)/fdb.a: $(GO_DEST)/.stamp lib/libfdb_c.$(DLEXT) $(GO_SRC)
@echo "Compiling fdb"
@go install $(GO_IMPORT_PATH)/fdb
$(GO_DEST)/fdb/generated.go: $(GO_DEST)/.stamp bindings/go/src/_util/translate_fdb_options.go fdbclient/vexillographer/fdb.options
$(GO_GEN): 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) $(GO_DEST)/fdb/generated.go
@echo "Generating Go Documentation"
@rm -rf $(GODOC_DIR)/godoc
@mkdir -p $(GODOC_DIR)/godoc
@mkdir -p $(GODOC_DIR)/godoc/lib/godoc
@godoc -url "pkg/$(GO_IMPORT_PATH)/fdb" > $(GODOC_DIR)/godoc/fdb.html
@godoc -url "pkg/$(GO_IMPORT_PATH)/fdb/tuple" > $(GODOC_DIR)/godoc/fdb.tuple.html
@godoc -url "pkg/$(GO_IMPORT_PATH)/fdb/subspace" > $(GODOC_DIR)/godoc/fdb.subspace.html
@godoc -url "pkg/$(GO_IMPORT_PATH)/fdb/directory" > $(GODOC_DIR)/godoc/fdb.directory.html
@cp $(CURDIR)/bindings/go/godoc-resources/* $(GODOC_DIR)/godoc/lib/godoc
@echo "Mangling paths in Go Documentation"
@(find $(GODOC_DIR)/godoc/ -name *.html -exec sed -i '' -e 's_/lib_lib_' {} \;)
@(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"
@rm -rf $(GODOC_DIR)/godoc

View File

@ -785,7 +785,6 @@ func (sm *StackMachine) processInst(idx int, inst tuple.Tuple) {
tr.Options().SetCausalReadRisky()
tr.Options().SetCausalWriteRisky()
tr.Options().SetReadYourWritesDisable()
tr.Options().SetReadAheadDisable()
tr.Options().SetReadSystemKeys()
tr.Options().SetAccessSystemKeys()
tr.Options().SetDurabilityDevNullIsWebScale()

View File

@ -136,7 +136,7 @@ func (t Transaction) %s(key KeyConvertible, param []byte) {
func writeEnum(scope Scope, opt Option, delta int) {
fmt.Println()
if opt.Description != "" {
doc.ToText(os.Stdout, opt.Description, " // ", "", 73)
doc.ToText(os.Stdout, opt.Description, "\t// ", "", 73)
// fmt.Printf(" // %s\n", opt.Description)
}
fmt.Printf(" %s %s = %d\n", scope.Name+translateName(opt.Name), scope.Name, opt.Code+delta)
@ -157,14 +157,34 @@ func main() {
log.Fatal(err)
}
fmt.Print(`// DO NOT EDIT THIS FILE BY HAND. This file was generated using
// translate_fdb_options.go, part of the fdb-go repository, and a copy of the
// fdb.options file (installed as part of the FoundationDB client, typically
fmt.Print(`/*
* generated.go
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// DO NOT EDIT THIS FILE BY HAND. This file was generated using
// translate_fdb_options.go, part of the FoundationDB repository, and a copy of
// the fdb.options file (installed as part of the FoundationDB client, typically
// found as /usr/include/foundationdb/fdb.options).
// To regenerate this file, from the top level of an fdb-go repository checkout,
// run:
// $ go run _util/translate_fdb_options.go < /usr/include/foundationdb/fdb.options > fdb/generated.go
// To regenerate this file, from the top level of a FoundationDB repository
// checkout, run:
// $ go run bindings/go/src/_util/translate_fdb_options.go < fdbclient/vexillographer/fdb.options > bindings/go/src/fdb/generated.go
package fdb
@ -216,6 +236,7 @@ func int64ToBytes(i int64) ([]byte, error) {
fmt.Printf(`
type %s int
const (
`, scope.Name)
for _, opt := range scope.Option {

View File

@ -111,7 +111,7 @@ func retryable(wrapped func() (interface{}, error), onError func(Error) FutureNi
// retried or, if fatal, return the error to the caller.
//
// When working with Future objects in a transactional function, you may either
// explicity check and return error values using Get, or call MustGet. Transact
// explicitly check and return error values using Get, or call MustGet. Transact
// will recover a panicked Error and either retry the transaction or return the
// error.
//
@ -151,7 +151,7 @@ func (d Database) Transact(f func(Transaction) (interface{}, error)) (interface{
// retried or, if fatal, return the error to the caller.
//
// When working with Future objects in a read-only transactional function, you
// may either explicity check and return error values using Get, or call
// may either explicitly check and return error values using Get, or call
// MustGet. ReadTransact will recover a panicked Error and either retry the
// transaction or return the error.
//

View File

@ -26,7 +26,7 @@
//
// For general guidance on directory usage, see the Directories section of the
// Developer Guide
// (https://www.foundationdb.org/documentation/developer-guide.html#developer-guide-directories).
// (https://apple.github.io/foundationdb/developer-guide.html#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

View File

@ -27,6 +27,7 @@ import (
"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"
@ -78,9 +79,8 @@ func (dl directoryLayer) createOrOpen(rtr fdb.ReadTransaction, tr *fdb.Transacti
if prefix != nil && !dl.allowManualPrefixes {
if len(dl.path) == 0 {
return nil, errors.New("cannot specify a prefix unless manual prefixes are enabled")
} else {
return nil, errors.New("cannot specify a prefix in a partition")
}
return nil, errors.New("cannot specify a prefix in a partition")
}
if len(path) == 0 {
@ -562,9 +562,8 @@ func (dl directoryLayer) contentsOfNode(node subspace.Subspace, path []string, l
ndl := NewDirectoryLayer(subspace.FromBytes(nssb), ss, false).(directoryLayer)
ndl.path = newPath
return directoryPartition{ndl, dl}, nil
} else {
return directorySubspace{ss, dl, newPath, layer}, nil
}
return directorySubspace{ss, dl, newPath, layer}, nil
}
func (dl directoryLayer) nodeWithPrefix(prefix []byte) subspace.Subspace {

View File

@ -72,9 +72,8 @@ func (dp directoryPartition) GetLayer() []byte {
func (dp directoryPartition) getLayerForPath(path []string) directoryLayer {
if len(path) == 0 {
return dp.parentDirectoryLayer
} else {
return dp.directoryLayer
}
return dp.directoryLayer
}
func (dp directoryPartition) MoveTo(t fdb.Transactor, newAbsolutePath []string) (DirectorySubspace, error) {

View File

@ -30,7 +30,7 @@ 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://www.foundationdb.org/documentation/index.html.
https://apple.github.io/foundationdb/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://www.foundationdb.org/documentation/developer-guide.html#atomic-operations. The
https://apple.github.io/foundationdb/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

@ -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://www.foundationdb.org/documentation/api-error-codes.html,
// error codes at https://apple.github.io/foundationdb/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 {

View File

@ -139,9 +139,8 @@ func APIVersion(version int) error {
maxSupportedVersion := C.fdb_get_max_api_version()
if headerVersion > int(maxSupportedVersion) {
return fmt.Errorf("This version of the FoundationDB Go binding is not supported by the installed FoundationDB C library. The binding requires a library that supports API version %d, but the installed library supports a maximum version of %d.", version, maxSupportedVersion)
} else {
return fmt.Errorf("API version %d is not supported by the installed FoundationDB C library.", version)
}
return fmt.Errorf("API version %d is not supported by the installed FoundationDB C library.", version)
}
return Error{int(e)}
}
@ -166,9 +165,8 @@ func IsAPIVersionSelected() bool {
func GetAPIVersion() (int, error) {
if IsAPIVersionSelected() {
return apiVersion, nil
} else {
return 0, errAPIVersionUnset
}
return 0, errAPIVersionUnset
}
// MustAPIVersion is like APIVersion but panics if the API version is not
@ -355,9 +353,8 @@ func CreateCluster(clusterFile string) (Cluster, error) {
func byteSliceToPtr(b []byte) *C.uint8_t {
if len(b) > 0 {
return (*C.uint8_t)(unsafe.Pointer(&b[0]))
} else {
return nil
}
return nil
}
// A KeyConvertible can be converted to a FoundationDB Key. All functions in the

View File

@ -0,0 +1,514 @@
/*
* generated.go
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// DO NOT EDIT THIS FILE BY HAND. This file was generated using
// translate_fdb_options.go, part of the FoundationDB repository, and a copy of
// the fdb.options file (installed as part of the FoundationDB client, typically
// found as /usr/include/foundationdb/fdb.options).
// To regenerate this file, from the top level of a FoundationDB repository
// checkout, run:
// $ go run bindings/go/src/_util/translate_fdb_options.go < fdbclient/vexillographer/fdb.options > bindings/go/src/fdb/generated.go
package fdb
import (
"bytes"
"encoding/binary"
)
func int64ToBytes(i int64) ([]byte, error) {
buf := new(bytes.Buffer)
if e := binary.Write(buf, binary.LittleEndian, i); e != nil {
return nil, e
}
return buf.Bytes(), nil
}
// Enables trace output to a file in a directory of the clients choosing
//
// Parameter: path to output directory (or NULL for current working directory)
func (o NetworkOptions) SetTraceEnable(param string) error {
return o.setOpt(30, []byte(param))
}
// Sets the maximum size in bytes of a single trace output file. This value should be in the range ``[0, INT64_MAX]``. If the value is set to 0, there is no limit on individual file size. The default is a maximum size of 10,485,760 bytes.
//
// Parameter: max size of a single trace output file
func (o NetworkOptions) SetTraceRollSize(param int64) error {
b, e := int64ToBytes(param)
if e != nil {
return e
}
return o.setOpt(31, b)
}
// Sets the maximum size of all the trace output files put together. This value should be in the range ``[0, INT64_MAX]``. If the value is set to 0, there is no limit on the total size of the files. The default is a maximum size of 104,857,600 bytes. If the default roll size is used, this means that a maximum of 10 trace files will be written at a time.
//
// Parameter: max total size of trace files
func (o NetworkOptions) SetTraceMaxLogsSize(param int64) error {
b, e := int64ToBytes(param)
if e != nil {
return e
}
return o.setOpt(32, b)
}
// Sets the 'logGroup' attribute with the specified value for all events in the trace output files. The default log group is 'default'.
//
// Parameter: value of the logGroup attribute
func (o NetworkOptions) SetTraceLogGroup(param string) error {
return o.setOpt(33, []byte(param))
}
// Set internal tuning or debugging knobs
//
// Parameter: knob_name=knob_value
func (o NetworkOptions) SetKnob(param string) error {
return o.setOpt(40, []byte(param))
}
// Set the TLS plugin to load. This option, if used, must be set before any other TLS options
//
// Parameter: file path or linker-resolved name
func (o NetworkOptions) SetTLSPlugin(param string) error {
return o.setOpt(41, []byte(param))
}
// Set the certificate chain
//
// Parameter: certificates
func (o NetworkOptions) SetTLSCertBytes(param []byte) error {
return o.setOpt(42, param)
}
// Set the file from which to load the certificate chain
//
// Parameter: file path
func (o NetworkOptions) SetTLSCertPath(param string) error {
return o.setOpt(43, []byte(param))
}
// Set the private key corresponding to your own certificate
//
// Parameter: key
func (o NetworkOptions) SetTLSKeyBytes(param []byte) error {
return o.setOpt(45, param)
}
// Set the file from which to load the private key corresponding to your own certificate
//
// Parameter: file path
func (o NetworkOptions) SetTLSKeyPath(param string) error {
return o.setOpt(46, []byte(param))
}
// Set the peer certificate field verification criteria
//
// Parameter: verification pattern
func (o NetworkOptions) SetTLSVerifyPeers(param []byte) error {
return o.setOpt(47, param)
}
// Not yet implemented.
func (o NetworkOptions) SetBuggifyEnable() error {
return o.setOpt(48, nil)
}
// Not yet implemented.
func (o NetworkOptions) SetBuggifyDisable() error {
return o.setOpt(49, nil)
}
// Set the probability of a BUGGIFY section being active for the current execution. Only applies to code paths first traversed AFTER this option is changed.
//
// Parameter: probability expressed as a percentage between 0 and 100
func (o NetworkOptions) SetBuggifySectionActivatedProbability(param int64) error {
b, e := int64ToBytes(param)
if e != nil {
return e
}
return o.setOpt(50, b)
}
// Set the probability of an active BUGGIFY section being fired
//
// Parameter: probability expressed as a percentage between 0 and 100
func (o NetworkOptions) SetBuggifySectionFiredProbability(param int64) error {
b, e := int64ToBytes(param)
if e != nil {
return e
}
return o.setOpt(51, b)
}
// Disables the multi-version client API and instead uses the local client directly. Must be set before setting up the network.
func (o NetworkOptions) SetDisableMultiVersionClientApi() error {
return o.setOpt(60, nil)
}
// If set, callbacks from external client libraries can be called from threads created by the FoundationDB client library. Otherwise, callbacks will be called from either the thread used to add the callback or the network thread. Setting this option can improve performance when connected using an external client, but may not be safe to use in all environments. Must be set before setting up the network. WARNING: This feature is considered experimental at this time.
func (o NetworkOptions) SetCallbacksOnExternalThreads() error {
return o.setOpt(61, nil)
}
// Adds an external client library for use by the multi-version client API. Must be set before setting up the network.
//
// Parameter: path to client library
func (o NetworkOptions) SetExternalClientLibrary(param string) error {
return o.setOpt(62, []byte(param))
}
// Searches the specified path for dynamic libraries and adds them to the list of client libraries for use by the multi-version client API. Must be set before setting up the network.
//
// Parameter: path to directory containing client libraries
func (o NetworkOptions) SetExternalClientDirectory(param string) error {
return o.setOpt(63, []byte(param))
}
// Prevents connections through the local client, allowing only connections through externally loaded client libraries. Intended primarily for testing.
func (o NetworkOptions) SetDisableLocalClient() error {
return o.setOpt(64, nil)
}
// Disables logging of client statistics, such as sampled transaction activity.
func (o NetworkOptions) SetDisableClientStatisticsLogging() error {
return o.setOpt(70, nil)
}
// Enables debugging feature to perform slow task profiling. Requires trace logging to be enabled. WARNING: this feature is not recommended for use in production.
func (o NetworkOptions) SetEnableSlowTaskProfiling() error {
return o.setOpt(71, nil)
}
// Set the size of the client location cache. Raising this value can boost performance in very large databases where clients access data in a near-random pattern. Defaults to 100000.
//
// Parameter: Max location cache entries
func (o DatabaseOptions) SetLocationCacheSize(param int64) error {
b, e := int64ToBytes(param)
if e != nil {
return e
}
return o.setOpt(10, b)
}
// Set the maximum number of watches allowed to be outstanding on a database connection. Increasing this number could result in increased resource usage. Reducing this number will not cancel any outstanding watches. Defaults to 10000 and cannot be larger than 1000000.
//
// Parameter: Max outstanding watches
func (o DatabaseOptions) SetMaxWatches(param int64) error {
b, e := int64ToBytes(param)
if e != nil {
return e
}
return o.setOpt(20, b)
}
// Specify the machine ID that was passed to fdbserver processes running on the same machine as this client, for better location-aware load balancing.
//
// Parameter: Hexadecimal ID
func (o DatabaseOptions) SetMachineId(param string) error {
return o.setOpt(21, []byte(param))
}
// Specify the datacenter ID that was passed to fdbserver processes running in the same datacenter as this client, for better location-aware load balancing.
//
// Parameter: Hexadecimal ID
func (o DatabaseOptions) SetDatacenterId(param string) error {
return o.setOpt(22, []byte(param))
}
// The transaction, if not self-conflicting, may be committed a second time after commit succeeds, in the event of a fault
func (o TransactionOptions) SetCausalWriteRisky() error {
return o.setOpt(10, nil)
}
// The read version will be committed, and usually will be the latest committed, but might not be the latest committed in the event of a fault or partition
func (o TransactionOptions) SetCausalReadRisky() error {
return o.setOpt(20, nil)
}
// Not yet implemented.
func (o TransactionOptions) SetCausalReadDisable() error {
return o.setOpt(21, nil)
}
// The next write performed on this transaction will not generate a write conflict range. As a result, other transactions which read the key(s) being modified by the next write will not conflict with this transaction. Care needs to be taken when using this option on a transaction that is shared between multiple threads. When setting this option, write conflict ranges will be disabled on the next write operation, regardless of what thread it is on.
func (o TransactionOptions) SetNextWriteNoWriteConflictRange() error {
return o.setOpt(30, nil)
}
// Committing this transaction will bypass the normal load balancing across proxies and go directly to the specifically nominated 'first proxy'.
func (o TransactionOptions) SetCommitOnFirstProxy() error {
return o.setOpt(40, nil)
}
// Not yet implemented.
func (o TransactionOptions) SetCheckWritesEnable() error {
return o.setOpt(50, nil)
}
// Reads performed by a transaction will not see any prior mutations that occured in that transaction, instead seeing the value which was in the database at the transaction's read version. This option may provide a small performance benefit for the client, but also disables a number of client-side optimizations which are beneficial for transactions which tend to read and write the same keys within a single transaction.
func (o TransactionOptions) SetReadYourWritesDisable() error {
return o.setOpt(51, nil)
}
// Disables read-ahead caching for range reads. Under normal operation, a transaction will read extra rows from the database into cache if range reads are used to page through a series of data one row at a time (i.e. if a range read with a one row limit is followed by another one row range read starting immediately after the result of the first).
func (o TransactionOptions) SetReadAheadDisable() error {
return o.setOpt(52, nil)
}
// Not yet implemented.
func (o TransactionOptions) SetDurabilityDatacenter() error {
return o.setOpt(110, nil)
}
// Not yet implemented.
func (o TransactionOptions) SetDurabilityRisky() error {
return o.setOpt(120, nil)
}
// Not yet implemented.
func (o TransactionOptions) SetDurabilityDevNullIsWebScale() error {
return o.setOpt(130, nil)
}
// Specifies that this transaction should be treated as highest priority and that lower priority transactions should block behind this one. Use is discouraged outside of low-level tools
func (o TransactionOptions) SetPrioritySystemImmediate() error {
return o.setOpt(200, nil)
}
// Specifies that this transaction should be treated as low priority and that default priority transactions should be processed first. Useful for doing batch work simultaneously with latency-sensitive work
func (o TransactionOptions) SetPriorityBatch() error {
return o.setOpt(201, nil)
}
// This is a write-only transaction which sets the initial configuration. This option is designed for use by database system tools only.
func (o TransactionOptions) SetInitializeNewDatabase() error {
return o.setOpt(300, nil)
}
// Allows this transaction to read and modify system keys (those that start with the byte 0xFF)
func (o TransactionOptions) SetAccessSystemKeys() error {
return o.setOpt(301, nil)
}
// Allows this transaction to read system keys (those that start with the byte 0xFF)
func (o TransactionOptions) SetReadSystemKeys() error {
return o.setOpt(302, nil)
}
// Not yet implemented.
func (o TransactionOptions) SetDebugDump() error {
return o.setOpt(400, nil)
}
// Not yet implemented.
func (o TransactionOptions) SetDebugRetryLogging(param string) error {
return o.setOpt(401, []byte(param))
}
// Enables tracing for this transaction and logs results to the client trace logs. Client trace logging must be enabled to get log output.
//
// Parameter: String identifier to be used in the logs when tracing this transaction. The identifier must not exceed 100 characters.
func (o TransactionOptions) SetTransactionLoggingEnable(param string) error {
return o.setOpt(402, []byte(param))
}
// Set a timeout in milliseconds which, when elapsed, will cause the transaction automatically to be cancelled. Valid parameter values are ``[0, INT_MAX]``. If set to 0, will disable all timeouts. All pending and any future uses of the transaction will throw an exception. The transaction can be used again after it is reset. Like all transaction options, a timeout must be reset after a call to onError. This behavior allows the user to make the timeout dynamic.
//
// Parameter: value in milliseconds of timeout
func (o TransactionOptions) SetTimeout(param int64) error {
b, e := int64ToBytes(param)
if e != nil {
return e
}
return o.setOpt(500, b)
}
// Set a maximum number of retries after which additional calls to onError will throw the most recently seen error code. Valid parameter values are ``[-1, INT_MAX]``. If set to -1, will disable the retry limit. Like all transaction options, the retry limit must be reset after a call to onError. This behavior allows the user to make the retry limit dynamic.
//
// Parameter: number of times to retry
func (o TransactionOptions) SetRetryLimit(param int64) error {
b, e := int64ToBytes(param)
if e != nil {
return e
}
return o.setOpt(501, b)
}
// Set the maximum amount of backoff delay incurred in the call to onError if the error is retryable. Defaults to 1000 ms. Valid parameter values are ``[0, INT_MAX]``. Like all transaction options, the maximum retry delay must be reset after a call to onError. If the maximum retry delay is less than the current retry delay of the transaction, then the current retry delay will be clamped to the maximum retry delay.
//
// Parameter: value in milliseconds of maximum delay
func (o TransactionOptions) SetMaxRetryDelay(param int64) error {
b, e := int64ToBytes(param)
if e != nil {
return e
}
return o.setOpt(502, b)
}
// Snapshot read operations will see the results of writes done in the same transaction.
func (o TransactionOptions) SetSnapshotRywEnable() error {
return o.setOpt(600, nil)
}
// Snapshot read operations will not see the results of writes done in the same transaction.
func (o TransactionOptions) SetSnapshotRywDisable() error {
return o.setOpt(601, nil)
}
// The transaction can read and write to locked databases, and is resposible for checking that it took the lock.
func (o TransactionOptions) SetLockAware() error {
return o.setOpt(700, nil)
}
// By default, operations that are performed on a transaction while it is being committed will not only fail themselves, but they will attempt to fail other in-flight operations (such as the commit) as well. This behavior is intended to help developers discover situations where operations could be unintentionally executed after the transaction has been reset. Setting this option removes that protection, causing only the offending operation to fail.
func (o TransactionOptions) SetUsedDuringCommitProtectionDisable() error {
return o.setOpt(701, nil)
}
// The transaction can read from locked databases.
func (o TransactionOptions) SetReadLockAware() error {
return o.setOpt(702, nil)
}
type StreamingMode int
const (
// Client intends to consume the entire range and would like it all
// transferred as early as possible.
StreamingModeWantAll StreamingMode = -1
// The default. The client doesn't know how much of the range it is likely
// to used and wants different performance concerns to be balanced. Only a
// small portion of data is transferred to the client initially (in order to
// minimize costs if the client doesn't read the entire range), and as the
// caller iterates over more items in the range larger batches will be
// transferred in order to minimize latency.
StreamingModeIterator StreamingMode = 0
// Infrequently used. The client has passed a specific row limit and wants
// that many rows delivered in a single batch. Because of iterator operation
// in client drivers make request batches transparent to the user, consider
// ``WANT_ALL`` StreamingMode instead. A row limit must be specified if this
// mode is used.
StreamingModeExact StreamingMode = 1
// Infrequently used. Transfer data in batches small enough to not be much
// more expensive than reading individual rows, to minimize cost if
// iteration stops early.
StreamingModeSmall StreamingMode = 2
// Infrequently used. Transfer data in batches sized in between small and
// large.
StreamingModeMedium StreamingMode = 3
// Infrequently used. Transfer data in batches large enough to be, in a
// high-concurrency environment, nearly as efficient as possible. If the
// client stops iteration early, some disk and network bandwidth may be
// wasted. The batch size may still be too small to allow a single client to
// get high throughput from the database, so if that is what you need
// consider the SERIAL StreamingMode.
StreamingModeLarge StreamingMode = 4
// Transfer data in batches large enough that an individual client can get
// reasonable read bandwidth from the database. If the client stops
// iteration early, considerable disk and network bandwidth may be wasted.
StreamingModeSerial StreamingMode = 5
)
// Add performs an addition of little-endian integers. If the existing value in the database is not present or shorter than ``param``, it is first extended to the length of ``param`` with zero bytes. If ``param`` is shorter than the existing value in the database, the existing value is truncated to match the length of ``param``. The integers to be added must be stored in a little-endian representation. They can be signed in two's complement representation or unsigned. You can add to an integer at a known offset in the value by prepending the appropriate number of zero bytes to ``param`` and padding with zero bytes to match the length of the value. However, this offset technique requires that you know the addition will not cause the integer field within the value to overflow.
func (t Transaction) Add(key KeyConvertible, param []byte) {
t.atomicOp(key.FDBKey(), param, 2)
}
// BitAnd performs a bitwise ``and`` operation. If the existing value in the database is not present, then ``param`` is stored in the database. If the existing value in the database is shorter than ``param``, it is first extended to the length of ``param`` with zero bytes. If ``param`` is shorter than the existing value in the database, the existing value is truncated to match the length of ``param``.
func (t Transaction) BitAnd(key KeyConvertible, param []byte) {
t.atomicOp(key.FDBKey(), param, 6)
}
// BitOr performs a bitwise ``or`` operation. If the existing value in the database is not present or shorter than ``param``, it is first extended to the length of ``param`` with zero bytes. If ``param`` is shorter than the existing value in the database, the existing value is truncated to match the length of ``param``.
func (t Transaction) BitOr(key KeyConvertible, param []byte) {
t.atomicOp(key.FDBKey(), param, 7)
}
// BitXor performs a bitwise ``xor`` operation. If the existing value in the database is not present or shorter than ``param``, it is first extended to the length of ``param`` with zero bytes. If ``param`` is shorter than the existing value in the database, the existing value is truncated to match the length of ``param``.
func (t Transaction) BitXor(key KeyConvertible, param []byte) {
t.atomicOp(key.FDBKey(), param, 8)
}
// Max performs a little-endian comparison of byte strings. If the existing value in the database is not present or shorter than ``param``, it is first extended to the length of ``param`` with zero bytes. If ``param`` is shorter than the existing value in the database, the existing value is truncated to match the length of ``param``. The larger of the two values is then stored in the database.
func (t Transaction) Max(key KeyConvertible, param []byte) {
t.atomicOp(key.FDBKey(), param, 12)
}
// Min performs a little-endian comparison of byte strings. If the existing value in the database is not present, then ``param`` is stored in the database. If the existing value in the database is shorter than ``param``, it is first extended to the length of ``param`` with zero bytes. If ``param`` is shorter than the existing value in the database, the existing value is truncated to match the length of ``param``. The smaller of the two values is then stored in the database.
func (t Transaction) Min(key KeyConvertible, param []byte) {
t.atomicOp(key.FDBKey(), param, 13)
}
// SetVersionstampedKey transforms ``key`` using a versionstamp for the transaction. Sets the transformed key in the database to ``param``. A versionstamp is a 10 byte, unique, monotonically (but not sequentially) increasing value for each committed transaction. The first 8 bytes are the committed version of the database. The last 2 bytes are monotonic in the serialization order for transactions. WARNING: At this time versionstamps are compatible with the Tuple layer only in the Java and Python bindings. Note that this implies versionstamped keys may not be used with the Subspace and Directory layers except in those languages.
func (t Transaction) SetVersionstampedKey(key KeyConvertible, param []byte) {
t.atomicOp(key.FDBKey(), param, 14)
}
// SetVersionstampedValue transforms ``param`` using a versionstamp for the transaction. Sets ``key`` in the database to the transformed parameter. A versionstamp is a 10 byte, unique, monotonically (but not sequentially) increasing value for each committed transaction. The first 8 bytes are the committed version of the database. The last 2 bytes are monotonic in the serialization order for transactions. WARNING: At this time versionstamped values are not compatible with the Tuple layer.
func (t Transaction) SetVersionstampedValue(key KeyConvertible, param []byte) {
t.atomicOp(key.FDBKey(), param, 15)
}
// ByteMin performs lexicographic comparison of byte strings. If the existing value in the database is not present, then ``param`` is stored. Otherwise the smaller of the two values is then stored in the database.
func (t Transaction) ByteMin(key KeyConvertible, param []byte) {
t.atomicOp(key.FDBKey(), param, 16)
}
// ByteMax performs lexicographic comparison of byte strings. If the existing value in the database is not present, then ``param`` is stored. Otherwise the larger of the two values is then stored in the database.
func (t Transaction) ByteMax(key KeyConvertible, param []byte) {
t.atomicOp(key.FDBKey(), param, 17)
}
type conflictRangeType int
const (
// Used to add a read conflict range
conflictRangeTypeRead conflictRangeType = 0
// Used to add a write conflict range
conflictRangeTypeWrite conflictRangeType = 1
)
type ErrorPredicate int
const (
// Returns ``true`` if the error indicates the operations in the
// transactions should be retried because of transient error.
ErrorPredicateRetryable ErrorPredicate = 50000
// Returns ``true`` if the error indicates the transaction may have
// succeeded, though not in a way the system can verify.
ErrorPredicateMaybeCommitted ErrorPredicate = 50001
// Returns ``true`` if the error indicates the transaction has not
// committed, though in a way that can be retried.
ErrorPredicateRetryableNotCommitted ErrorPredicate = 50002
)

View File

@ -34,7 +34,7 @@ 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://www.foundationdb.org/documentation/developer-guide.html#key-selectors.
// https://apple.github.io/foundationdb/developer-guide.html#key-selectors.
type KeySelector struct {
Key KeyConvertible
OrEqual bool

View File

@ -247,7 +247,7 @@ func (ri *RangeIterator) fetchNextBatch() {
ri.sr.Begin = FirstGreaterThan(ri.kvs[ri.index-1].Key)
}
ri.iteration += 1
ri.iteration++
f := ri.t.doGetRange(ri.sr, ri.options, ri.snapshot, ri.iteration)
ri.f = &f
@ -265,7 +265,7 @@ func (ri *RangeIterator) Get() (kv KeyValue, e error) {
kv = ri.kvs[ri.index]
ri.index += 1
ri.index++
if ri.index == len(ri.kvs) {
ri.fetchNextBatch()
@ -291,7 +291,7 @@ func Strinc(prefix []byte) ([]byte, error) {
if prefix[i] != 0xFF {
ret := make([]byte, i+1)
copy(ret, prefix[:i+1])
ret[i] += 1
ret[i]++
return ret, nil
}
}

View File

@ -28,7 +28,7 @@ package fdb
// transaction conflicts but making it harder to reason about concurrency.
//
// For more information on snapshot reads, see
// https://www.foundationdb.org/documentation/developer-guide.html#snapshot-reads.
// https://apple.github.io/foundationdb/developer-guide.html#snapshot-reads.
type Snapshot struct {
*transaction
}

View File

@ -29,7 +29,7 @@
// 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://www.foundationdb.org/documentation/developer-guide.html#developer-guide-sub-keyspaces).
// (https://apple.github.io/foundationdb/developer-guide.html#subspaces).
package subspace
import (

View File

@ -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://www.foundationdb.org/documentation/developer-guide.html#using-snapshot-reads.
// https://apple.github.io/foundationdb/developer-guide.html#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://www.foundationdb.org/documentation/developer-guide.html#developer-guide-unknown-results.
// https://apple.github.io/foundationdb/developer-guide.html#transactions-with-unknown-results.
func (t Transaction) Commit() FutureNil {
return &futureNil{newFuture(C.fdb_transaction_commit(t.ptr))}
}
@ -352,9 +352,8 @@ func (t Transaction) Reset() {
func boolToInt(b bool) int {
if b {
return 1
} else {
return 0
}
return 0
}
func (t *transaction) getKey(sel KeySelector, snapshot int) FutureKey {
@ -396,7 +395,7 @@ func addConflictRange(t *transaction, er ExactRange, crtype conflictRangeType) e
// conflict.
//
// For more information on conflict ranges, see
// https://www.foundationdb.org/documentation/developer-guide.html#conflict-ranges.
// https://apple.github.io/foundationdb/developer-guide.html#conflict-ranges.
func (t Transaction) AddReadConflictRange(er ExactRange) error {
return addConflictRange(t.transaction, er, conflictRangeTypeRead)
}
@ -413,7 +412,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://www.foundationdb.org/documentation/developer-guide.html#conflict-ranges.
// https://apple.github.io/foundationdb/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 +423,7 @@ func (t Transaction) AddReadConflictKey(key KeyConvertible) error {
// conflict.
//
// For more information on conflict ranges, see
// https://www.foundationdb.org/documentation/developer-guide.html#conflict-ranges.
// https://apple.github.io/foundationdb/developer-guide.html#conflict-ranges.
func (t Transaction) AddWriteConflictRange(er ExactRange) error {
return addConflictRange(t.transaction, er, conflictRangeTypeWrite)
}
@ -434,7 +433,7 @@ func (t Transaction) AddWriteConflictRange(er ExactRange) error {
// read this key could fail with a conflict.
//
// For more information on conflict ranges, see
// https://www.foundationdb.org/documentation/developer-guide.html#conflict-ranges.
// https://apple.github.io/foundationdb/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

@ -27,7 +27,7 @@
// of higher-level data models.
//
// For general guidance on tuple usage, see the Tuple section of Data Modeling
// (https://www.foundationdb.org/documentation/data-modeling.html#data-modeling-tuples).
// (https://apple.github.io/foundationdb/data-modeling.html#tuples).
//
// FoundationDB tuples can currently encode byte and unicode strings, integers
// and NULL values. In Go these are represented as []byte, string, int64 and
@ -38,6 +38,7 @@ import (
"bytes"
"encoding/binary"
"fmt"
"github.com/apple/foundationdb/bindings/go/src/fdb"
)
@ -114,7 +115,7 @@ func encodeBytes(buf *bytes.Buffer, code byte, b []byte) {
func bisectLeft(u uint64) int {
var n int
for sizeLimits[n] < u {
n += 1
n++
}
return n
}
@ -356,7 +357,7 @@ func decodeTuple(b []byte, nested bool) (Tuple, int, error) {
if err != nil {
return nil, i, err
}
off += 1
off++
default:
return nil, i, fmt.Errorf("unable to decode tuple element with unknown typecode %02x", b[i])
}

View File

@ -30,11 +30,6 @@
<property name="option" value="eol"/>
<property name="ignoreEnums" value="false"/>
</module>
<!-- We have about 76 errors with value = "alone" and 27 with value = "same". We should pick one.
<module name="RightCurly">
<property name="option" value="same"/>
</module>
-->
<!-- Design -->
<!-- We might get some helpful errors if we turned this on, but not right now.

View File

@ -160,7 +160,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="/developer-guide.html#transactions-with-unknown-results"
* <a href="/foundationdb/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
@ -202,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="/developer-guide.html#transactions-with-unknown-results"
* <a href="/foundationdb/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

View File

@ -214,7 +214,7 @@ public class FDB {
/**
* Connects to the cluster specified by the
* <a href="/administration.html#default-cluster-file" target="_blank">default fdb.cluster file</a>.
* <a href="/foundationdb/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.
*
@ -233,9 +233,9 @@ public class FDB {
* {@link #startNetwork()} had been called.
*
* @param clusterFilePath the
* <a href="/administration.html#foundationdb-cluster-file" target="_blank">cluster file</a>
* <a href="/foundationdb/administration.html#foundationdb-cluster-file" target="_blank">cluster file</a>
* defining the FoundationDB cluster. This can be {@code null} if the
* <a href="/administration.html#default-cluster-file" target="_blank">default fdb.cluster file</a>
* <a href="/foundationdb/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}.
@ -254,9 +254,9 @@ public class FDB {
* are produced from using the resulting {@link Cluster}.
*
* @param clusterFilePath the
* <a href="/administration.html#foundationdb-cluster-file" target="_blank">cluster file</a>
* <a href="/foundationdb/administration.html#foundationdb-cluster-file" target="_blank">cluster file</a>
* defining the FoundationDB cluster. This can be {@code null} if the
* <a href="/administration.html#default-cluster-file" target="_blank">default fdb.cluster file</a>
* <a href="/foundationdb/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
*
@ -279,7 +279,7 @@ public class FDB {
/**
* Initializes networking, connects with the
* <a href="/administration.html#default-cluster-file" target="_blank">default fdb.cluster file</a>,
* <a href="/foundationdb/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}
@ -293,9 +293,9 @@ public class FDB {
* and opens the database.
*
* @param clusterFilePath the
* <a href="/administration.html#foundationdb-cluster-file" target="_blank">cluster file</a>
* <a href="/foundationdb/administration.html#foundationdb-cluster-file" target="_blank">cluster file</a>
* defining the FoundationDB cluster. This can be {@code null} if the
* <a href="/administration.html#default-cluster-file" target="_blank">default fdb.cluster file</a>
* <a href="/foundationdb/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}
@ -309,9 +309,9 @@ public class FDB {
* and opens the database.
*
* @param clusterFilePath the
* <a href="/administration.html#foundationdb-cluster-file" target="_blank">cluster file</a>
* <a href="/foundationdb/administration.html#foundationdb-cluster-file" target="_blank">cluster file</a>
* defining the FoundationDB cluster. This can be {@code null} if the
* <a href="/administration.html#default-cluster-file" target="_blank">default fdb.cluster file</a>
* <a href="/foundationdb/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
*

View File

@ -42,12 +42,12 @@ class JNIUtil {
OSX("osx", "x86_64", true);
private final String name;
private final String arch;
private final String arch;
private final boolean canDeleteEager;
OS(String name, String arch, boolean canDeleteEager) {
this.name = name;
this.arch = arch;
this.arch = arch;
this.canDeleteEager = canDeleteEager;
}
@ -55,9 +55,9 @@ class JNIUtil {
return this.name;
}
public String getArch() {
return this.arch;
}
public String getArch() {
return this.arch;
}
}
/**
@ -89,18 +89,18 @@ class JNIUtil {
OS os = getRunningOS();
String path = getPath(os, libName);
if ((os.getName().equals("linux") && !path.endsWith(".so")) || (os.getName().equals("windows") && !path.endsWith(".dll")) || (os.getName().equals("osx") && !path.endsWith(".jnilib") && !path.endsWith(".dylib"))) {
throw new IllegalStateException("OS sanity check failed. System property os.name reports " + os.getName()+" but System.mapLibraryName is looking for " + getLibName(libName));
}
if ((os.getName().equals("linux") && !path.endsWith(".so")) || (os.getName().equals("windows") && !path.endsWith(".dll")) || (os.getName().equals("osx") && !path.endsWith(".jnilib") && !path.endsWith(".dylib"))) {
throw new IllegalStateException("OS sanity check failed. System property os.name reports " + os.getName()+" but System.mapLibraryName is looking for " + getLibName(libName));
}
File exported;
File exported;
try {
exported = exportResource(path);
}
catch (IOException e) {
throw new UnsatisfiedLinkError(e.getMessage());
}
try {
exported = exportResource(path);
}
catch (IOException e) {
throw new UnsatisfiedLinkError(e.getMessage());
}
String filename = exported.getAbsolutePath();
System.load(filename);

View File

@ -32,7 +32,7 @@ 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="/developer-guide.html#key-selectors" target="_blank">the KeySelector documentation</a>.
* <a href="/foundationdb/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.
@ -134,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="/developer-guide.html#key-selectors" target="_blank">the KeySelector documentation</a>.
* <a href="/foundationdb/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.

View File

@ -21,17 +21,17 @@
package com.apple.foundationdb;
class RangeResultInfo {
RangeResultSummary getSummary() {
return f.getSummary();
}
RangeResultSummary getSummary() {
return f.getSummary();
}
RangeResult get() {
return f.getResults();
}
RangeResult get() {
return f.getResults();
}
RangeResultInfo(FutureResults f) {
this.f = f;
}
RangeResultInfo(FutureResults f) {
this.f = f;
}
private FutureResults f;
private FutureResults f;
}

View File

@ -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="/developer-guide.html#developer-guide-transaction-conflicts" target="_blank">conflicts</a>.<br>
* <a href="/foundationdb/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="/developer-guide.html#acid" target="_blank">ACID</a>.<br>
* known as <a href="/foundationdb/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="/data-modeling.html#data-modeling-tuples" target="_blank">tuple layer documentation</a>.<br>
* <a href="/foundationdb/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,11 @@ 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="/developer-guide.html#transaction-conflicts" target="_blank">Transaction conflicts</a>
* <a href="/foundationdb/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="/developer-guide.html#using-snapshot-reads" target="_blank">Using snapshot reads</a>.
* <a href="/foundationdb/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
*/

View File

@ -55,7 +55,7 @@ import com.apple.foundationdb.tuple.Tuple;
* to manage its subspaces.
*
* For general guidance on directory usage, see the discussion in the
* <a href="/developer-guide.html#developer-guide-directories" target="_blank">Developer Guide</a>.
* <a href="/foundationdb/developer-guide.html#developer-guide-directories" target="_blank">Developer Guide</a>.
* </p>
* <p>
* Directories are identified by hierarchical paths analogous to the paths
@ -526,7 +526,7 @@ public class DirectoryLayer implements Directory {
return AsyncUtil.collect(
AsyncUtil.mapIterable(tr.getRange(subdir.range()),
kv -> subdir.unpack(kv.getKey()).getString(0)
kv -> subdir.unpack(kv.getKey()).getString(0)
),
tr.getExecutor()
);

View File

@ -38,7 +38,7 @@ import com.apple.foundationdb.tuple.Tuple;
* </p>
*
* For general guidance on partition usage, see the
* <a href="/developer-guide.html#directory-partitions" target="_blank">Developer Guide</a>.
* <a href="/foundationdb/developer-guide.html#directory-partitions" target="_blank">Developer Guide</a>.
*/
class DirectoryPartition extends DirectorySubspace {

View File

@ -31,7 +31,7 @@
* used for the corresponding subspace. In effect, directories provide
* a level of indirection for access to subspaces.<br>
* <br>
* See <a href="/developer-guide.html#developer-guide-directories">general
* See <a href="/foundationdb/developer-guide.html#developer-guide-directories">general
* directory documentation</a> for information about how directories work and
* interact with other parts of the built-in keyspace management features.
*/

View File

@ -29,7 +29,7 @@
* assure that {@link com.apple.foundationdb.Transaction#commit()} has returned successfully
* before itself returning. If you are not able to use these functions for some reason
* please closely read and understand the other
* <a href="/data-modeling.html#data-modeling-tuples">developer
* <a href="/foundationdb/data-modeling.html#data-modeling-tuples">developer
* documentation on FoundationDB transactions</a>.
*/
package com.apple.foundationdb;

View File

@ -38,7 +38,7 @@ import com.apple.foundationdb.tuple.Versionstamp;
*
* <p>
* For general guidance on subspace usage, see the discussion in
* <a href="/developer-guide.html#developer-guide-sub-keyspaces" target="_blank">Developer Guide</a>.
* <a href="/foundationdb/developer-guide.html#developer-guide-sub-keyspaces" target="_blank">Developer Guide</a>.
* </p>
*
* <p>
@ -46,231 +46,231 @@ import com.apple.foundationdb.tuple.Versionstamp;
* </p>
*/
public class Subspace {
static final Tuple EMPTY_TUPLE = Tuple.from();
static final byte[] EMPTY_BYTES = new byte[0];
static final Tuple EMPTY_TUPLE = Tuple.from();
static final byte[] EMPTY_BYTES = new byte[0];
private final byte[] rawPrefix;
private final byte[] rawPrefix;
/**
* Constructor for a subspace formed with an empty prefix {@link Tuple}.
*/
public Subspace() {
this(EMPTY_TUPLE, EMPTY_BYTES);
}
/**
* Constructor for a subspace formed with an empty prefix {@link Tuple}.
*/
public Subspace() {
this(EMPTY_TUPLE, EMPTY_BYTES);
}
/**
* Constructor for a subspace formed with the specified prefix {@link Tuple}.
* Note that the {@link Tuple} {@code prefix} should not contain any incomplete
* {@link Versionstamp}s as any of its entries.
*
* @param prefix a {@link Tuple} used to form the subspace
* @throws IllegalArgumentException if {@code prefix} contains any incomplete {@link Versionstamp}s
*/
public Subspace(Tuple prefix) {
this(prefix, EMPTY_BYTES);
}
/**
* Constructor for a subspace formed with the specified prefix {@link Tuple}.
* Note that the {@link Tuple} {@code prefix} should not contain any incomplete
* {@link Versionstamp}s as any of its entries.
*
* @param prefix a {@link Tuple} used to form the subspace
* @throws IllegalArgumentException if {@code prefix} contains any incomplete {@link Versionstamp}s
*/
public Subspace(Tuple prefix) {
this(prefix, EMPTY_BYTES);
}
/**
* Constructor for a subspace formed with the specified byte string, which will
* be prepended to all packed keys.
*
* @param rawPrefix a byte array used as the prefix for all packed keys
*/
public Subspace(byte[] rawPrefix) {
this(EMPTY_TUPLE, rawPrefix);
}
/**
* Constructor for a subspace formed with the specified byte string, which will
* be prepended to all packed keys.
*
* @param rawPrefix a byte array used as the prefix for all packed keys
*/
public Subspace(byte[] rawPrefix) {
this(EMPTY_TUPLE, rawPrefix);
}
/**
* Constructor for a subspace formed with both a prefix {@link Tuple} and a
* prefix byte string. The prefix {@code Tuple} will be prepended to all
* {@code Tuples} packed by the {@code Subspace}, and the byte string prefix
* will be prepended to the packed result. Note that the {@link Tuple} {@code prefix}
* should not contain any incomplete {@link Versionstamp}s as any of its entries.
*
* @param prefix a {@code Tuple} used to form the subspace
* @param rawPrefix a byte array used as the prefix for all packed keys
* @throws IllegalArgumentException if {@code prefix} contains any incomplete {@link Versionstamp}s
*/
public Subspace(Tuple prefix, byte[] rawPrefix) {
this.rawPrefix = join(rawPrefix, prefix.pack());
}
/**
* Constructor for a subspace formed with both a prefix {@link Tuple} and a
* prefix byte string. The prefix {@code Tuple} will be prepended to all
* {@code Tuples} packed by the {@code Subspace}, and the byte string prefix
* will be prepended to the packed result. Note that the {@link Tuple} {@code prefix}
* should not contain any incomplete {@link Versionstamp}s as any of its entries.
*
* @param prefix a {@code Tuple} used to form the subspace
* @param rawPrefix a byte array used as the prefix for all packed keys
* @throws IllegalArgumentException if {@code prefix} contains any incomplete {@link Versionstamp}s
*/
public Subspace(Tuple prefix, byte[] rawPrefix) {
this.rawPrefix = join(rawPrefix, prefix.pack());
}
/**
* Returns true if this {@code Subspace} is equal to {@code rhs}.
* Two {@code Subspace}s are equal if they have the same prefix.
*
* @param rhs the object to check for equality
* @return {@code true} if this {@code Subspace} and {@code rhs} have equal prefixes
*/
@Override
public boolean equals(Object rhs) {
if(this == rhs) {
return true;
}
if(rhs == null || getClass() != rhs.getClass()) {
return false;
}
Subspace other = (Subspace)rhs;
return Arrays.equals(rawPrefix, other.rawPrefix);
}
/**
* Returns true if this {@code Subspace} is equal to {@code rhs}.
* Two {@code Subspace}s are equal if they have the same prefix.
*
* @param rhs the object to check for equality
* @return {@code true} if this {@code Subspace} and {@code rhs} have equal prefixes
*/
@Override
public boolean equals(Object rhs) {
if(this == rhs) {
return true;
}
if(rhs == null || getClass() != rhs.getClass()) {
return false;
}
Subspace other = (Subspace)rhs;
return Arrays.equals(rawPrefix, other.rawPrefix);
}
/**
* Create a human-readable string representation of this subspace. This is
* really only useful for debugging purposes, but it includes information
* on what raw prefix the subspace is using.
* @return a printable representation of the subspace
*/
@Override
public String toString() {
return "Subspace(rawPrefix=" + printable(rawPrefix) + ")";
}
/**
* Create a human-readable string representation of this subspace. This is
* really only useful for debugging purposes, but it includes information
* on what raw prefix the subspace is using.
* @return a printable representation of the subspace
*/
@Override
public String toString() {
return "Subspace(rawPrefix=" + printable(rawPrefix) + ")";
}
/**
* Returns a hash-table compatible hash of this subspace. This is based off
* of the hash of the underlying byte-array prefix.
* @return a hash of this subspace
*/
@Override
public int hashCode() {
return Arrays.hashCode(rawPrefix);
}
/**
* Returns a hash-table compatible hash of this subspace. This is based off
* of the hash of the underlying byte-array prefix.
* @return a hash of this subspace
*/
@Override
public int hashCode() {
return Arrays.hashCode(rawPrefix);
}
/**
* Gets a new subspace which is equivalent to this subspace with its prefix {@link Tuple} extended by
* the specified {@code Object}. The object will be inserted into a {@link Tuple} and passed to {@link #get(Tuple)}.
*
* @param obj an {@code Object} compatible with {@code Tuple}s
* @return a new subspace formed by joining this {@code Subspace}'s prefix to {@code obj}
*/
public Subspace get(Object obj) {
return get(Tuple.from(obj));
}
/**
* Gets a new subspace which is equivalent to this subspace with its prefix {@link Tuple} extended by
* the specified {@code Object}. The object will be inserted into a {@link Tuple} and passed to {@link #get(Tuple)}.
*
* @param obj an {@code Object} compatible with {@code Tuple}s
* @return a new subspace formed by joining this {@code Subspace}'s prefix to {@code obj}
*/
public Subspace get(Object obj) {
return get(Tuple.from(obj));
}
/**
* Gets a new subspace which is equivalent to this subspace with its prefix {@link Tuple} extended by
* the specified {@link Tuple}.
*
* @param tuple the {@link Tuple} used to form the new {@code Subspace}
* @return a new subspace formed by joining this {@code Subspace}'s prefix to {@code tuple}
*/
public Subspace get(Tuple tuple) {
return subspace(tuple);
}
/**
* Gets a new subspace which is equivalent to this subspace with its prefix {@link Tuple} extended by
* the specified {@link Tuple}.
*
* @param tuple the {@link Tuple} used to form the new {@code Subspace}
* @return a new subspace formed by joining this {@code Subspace}'s prefix to {@code tuple}
*/
public Subspace get(Tuple tuple) {
return subspace(tuple);
}
/**
* Gets the key encoding the prefix used for this {@code Subspace}. This is equivalent to
* {@link #pack}ing the empty {@link Tuple}.
*
* @return the key encoding the prefix used for this {@code Subspace}
*/
public byte[] getKey() {
return pack();
}
/**
* Gets the key encoding the prefix used for this {@code Subspace}. This is equivalent to
* {@link #pack}ing the empty {@link Tuple}.
*
* @return the key encoding the prefix used for this {@code Subspace}
*/
public byte[] getKey() {
return pack();
}
/**
* Gets the key encoding the prefix used for this {@code Subspace}.
*
* @return the key encoding the prefix used for this {@code Subspace}
*/
public byte[] pack() {
return Arrays.copyOf(rawPrefix, rawPrefix.length);
}
/**
* Gets the key encoding the prefix used for this {@code Subspace}.
*
* @return the key encoding the prefix used for this {@code Subspace}
*/
public byte[] pack() {
return Arrays.copyOf(rawPrefix, rawPrefix.length);
}
/**
* Gets the key encoding the specified {@code Object} in this {@code Subspace}. {@code obj} is
* inserted into a {@link Tuple} and packed with {@link #pack(Tuple)}.
*
* @param obj an {@code Object} to be packed that is compatible with {@link Tuple}s
* @return the key encoding the tuple derived from {@code obj}
*/
public byte[] pack(Object obj) {
return pack(Tuple.from(obj));
}
/**
* Gets the key encoding the specified {@code Object} in this {@code Subspace}. {@code obj} is
* inserted into a {@link Tuple} and packed with {@link #pack(Tuple)}.
*
* @param obj an {@code Object} to be packed that is compatible with {@link Tuple}s
* @return the key encoding the tuple derived from {@code obj}
*/
public byte[] pack(Object obj) {
return pack(Tuple.from(obj));
}
/**
* Gets the key encoding the specified tuple in this {@code Subspace}. For example, if you have a {@code Subspace}
* with prefix {@link Tuple} {@code ("users")} and you use it to pack the {@link Tuple} {@code ("Smith")},
* the result is the same as if you packed the {@link Tuple} {@code ("users", "Smith")}.
*
* @param tuple the {@code Tuple} to be packed
* @return the key encoding the specified tuple in this {@code Subspace}
*/
public byte[] pack(Tuple tuple) {
return tuple.pack(rawPrefix);
}
/**
* Gets the key encoding the specified tuple in this {@code Subspace}. For example, if you have a {@code Subspace}
* with prefix {@link Tuple} {@code ("users")} and you use it to pack the {@link Tuple} {@code ("Smith")},
* the result is the same as if you packed the {@link Tuple} {@code ("users", "Smith")}.
*
* @param tuple the {@code Tuple} to be packed
* @return the key encoding the specified tuple in this {@code Subspace}
*/
public byte[] pack(Tuple tuple) {
return tuple.pack(rawPrefix);
}
/**
* Gets the key encoding the specified tuple in this {@code Subspace} for use with
* {@link com.apple.foundationdb.MutationType#SET_VERSIONSTAMPED_KEY MutationType.SET_VERSIONSTAMPED_KEY}.
* There must be exactly one incomplete {@link Versionstamp} included in the given {@link Tuple}. It will
* create a key that is within this {@code Subspace} that can be provided as the {@code key} argument to
* {@link com.apple.foundationdb.Transaction#mutate(com.apple.foundationdb.MutationType, byte[], byte[]) Transaction.mutate()}
* with the {@link com.apple.foundationdb.MutationType#SET_VERSIONSTAMPED_KEY SET_VERSIONSTAMPED_KEY}
* mutation. This will throw an {@link IllegalArgumentException} if the {@link Tuple} does not
* contain an incomplete {@link Versionstamp} or if it contains multiple.
*
* @param tuple the {@code Tuple} to be packed
* @return the key encoding the specified tuple in this {@code Subspace}
* @throws IllegalArgumentException if {@code tuple} does not contain exactly one incomplete {@link Versionstamp}
*/
public byte[] packWithVersionstamp(Tuple tuple) {
return tuple.packWithVersionstamp(rawPrefix);
}
/**
* Gets the key encoding the specified tuple in this {@code Subspace} for use with
* {@link com.apple.foundationdb.MutationType#SET_VERSIONSTAMPED_KEY MutationType.SET_VERSIONSTAMPED_KEY}.
* There must be exactly one incomplete {@link Versionstamp} included in the given {@link Tuple}. It will
* create a key that is within this {@code Subspace} that can be provided as the {@code key} argument to
* {@link com.apple.foundationdb.Transaction#mutate(com.apple.foundationdb.MutationType, byte[], byte[]) Transaction.mutate()}
* with the {@link com.apple.foundationdb.MutationType#SET_VERSIONSTAMPED_KEY SET_VERSIONSTAMPED_KEY}
* mutation. This will throw an {@link IllegalArgumentException} if the {@link Tuple} does not
* contain an incomplete {@link Versionstamp} or if it contains multiple.
*
* @param tuple the {@code Tuple} to be packed
* @return the key encoding the specified tuple in this {@code Subspace}
* @throws IllegalArgumentException if {@code tuple} does not contain exactly one incomplete {@link Versionstamp}
*/
public byte[] packWithVersionstamp(Tuple tuple) {
return tuple.packWithVersionstamp(rawPrefix);
}
/**
* Gets the {@link Tuple} encoded by the given key, with this {@code Subspace}'s prefix {@link Tuple} and
* {@code raw prefix} removed.
*
* @param key The key being decoded
* @return the {@link Tuple} encoded by {@code key} with the prefix removed
*/
public Tuple unpack(byte[] key) {
if(!contains(key))
throw new IllegalArgumentException("Cannot unpack key that is not contained in subspace.");
/**
* Gets the {@link Tuple} encoded by the given key, with this {@code Subspace}'s prefix {@link Tuple} and
* {@code raw prefix} removed.
*
* @param key The key being decoded
* @return the {@link Tuple} encoded by {@code key} with the prefix removed
*/
public Tuple unpack(byte[] key) {
if(!contains(key))
throw new IllegalArgumentException("Cannot unpack key that is not contained in subspace.");
return Tuple.fromBytes(Arrays.copyOfRange(key, rawPrefix.length, key.length));
}
return Tuple.fromBytes(Arrays.copyOfRange(key, rawPrefix.length, key.length));
}
/**
* Gets a {@link Range} respresenting all keys strictly in the {@code Subspace}.
*
* @return the {@link Range} of keyspace corresponding to this {@code Subspace}
*/
public Range range() {
return range(EMPTY_TUPLE);
}
/**
* Gets a {@link Range} respresenting all keys strictly in the {@code Subspace}.
*
* @return the {@link Range} of keyspace corresponding to this {@code Subspace}
*/
public Range range() {
return range(EMPTY_TUPLE);
}
/**
* Gets a {@link Range} representing all keys in the {@code Subspace} strictly starting with
* the specified {@link Tuple}.
*
* @param tuple the {@code Tuple} whose sub-keys we are searching for
* @return the {@link Range} of keyspace corresponding to {@code tuple}
*/
public Range range(Tuple tuple) {
Range p = tuple.range();
return new Range(join(rawPrefix, p.begin), join(rawPrefix, p.end));
}
/**
* Gets a {@link Range} representing all keys in the {@code Subspace} strictly starting with
* the specified {@link Tuple}.
*
* @param tuple the {@code Tuple} whose sub-keys we are searching for
* @return the {@link Range} of keyspace corresponding to {@code tuple}
*/
public Range range(Tuple tuple) {
Range p = tuple.range();
return new Range(join(rawPrefix, p.begin), join(rawPrefix, p.end));
}
/**
* Tests whether the specified key starts with this {@code Subspace}'s prefix, indicating that
* the {@code Subspace} logically contains key.
*
* @param key the key to be tested
* @return {@code true} if {@code key} starts with {@code Subspace.key()}
*/
public boolean contains(byte[] key) {
return ByteArrayUtil.startsWith(key, rawPrefix);
}
/**
* Tests whether the specified key starts with this {@code Subspace}'s prefix, indicating that
* the {@code Subspace} logically contains key.
*
* @param key the key to be tested
* @return {@code true} if {@code key} starts with {@code Subspace.key()}
*/
public boolean contains(byte[] key) {
return ByteArrayUtil.startsWith(key, rawPrefix);
}
/**
* Gets a new subspace which is equivalent to this subspace with its prefix {@link Tuple} extended by
* the specified {@link Tuple}.
*
* @param tuple the {@link Tuple} used to form the new {@code Subspace}
* @return a new subspace formed by joining this {@code Subspace}'s prefix to {@code tuple}
*/
public Subspace subspace(Tuple tuple) {
return new Subspace(tuple, rawPrefix);
}
/**
* Gets a new subspace which is equivalent to this subspace with its prefix {@link Tuple} extended by
* the specified {@link Tuple}.
*
* @param tuple the {@link Tuple} used to form the new {@code Subspace}
* @return a new subspace formed by joining this {@code Subspace}'s prefix to {@code tuple}
*/
public Subspace subspace(Tuple tuple) {
return new Subspace(tuple, rawPrefix);
}
}

View File

@ -26,7 +26,7 @@
* from the result. As a best practice, API clients should use at least one
* subspace for application data.<br>
* <br>
* See <a href="/developer-guide.html#developer-guide-sub-keyspaces">general
* See <a href="/foundationdb/developer-guide.html#developer-guide-sub-keyspaces">general
* subspace documentation</a> for information about how subspaces work and
* interact with other parts of the built-in keyspace management features.
*/

View File

@ -63,45 +63,45 @@ import java.util.Iterator;
* </ul>
*/
public class IterableComparator implements Comparator<Iterable<?>> {
/**
* Creates a new {@code IterableComparator}. This {@link Comparator} has
* no internal state.
*/
public IterableComparator() {}
/**
* Creates a new {@code IterableComparator}. This {@link Comparator} has
* no internal state.
*/
public IterableComparator() {}
/**
* Compare two {@link Iterable}s in a way consistent with their
* byte representation. This is done element-wise and is consistent
* with a number of other ways of sorting {@link Tuple}s. This will
* raise an {@link IllegalArgumentException} if any of the items
* of either {@link Iterable} cannot be serialized by a {@link Tuple}.
*
* @param iterable1 the first {@link Iterable} of items
* @param iterable2 the second {@link Iterable} of items
* @return a negative number if the first iterable would sort before the second
* when serialized, a positive number if the opposite is true, and zero
* if the two are equal
*/
@Override
public int compare(Iterable<?> iterable1, Iterable<?> iterable2) {
Iterator<?> i1 = iterable1.iterator();
Iterator<?> i2 = iterable2.iterator();
/**
* Compare two {@link Iterable}s in a way consistent with their
* byte representation. This is done element-wise and is consistent
* with a number of other ways of sorting {@link Tuple}s. This will
* raise an {@link IllegalArgumentException} if any of the items
* of either {@link Iterable} cannot be serialized by a {@link Tuple}.
*
* @param iterable1 the first {@link Iterable} of items
* @param iterable2 the second {@link Iterable} of items
* @return a negative number if the first iterable would sort before the second
* when serialized, a positive number if the opposite is true, and zero
* if the two are equal
*/
@Override
public int compare(Iterable<?> iterable1, Iterable<?> iterable2) {
Iterator<?> i1 = iterable1.iterator();
Iterator<?> i2 = iterable2.iterator();
while(i1.hasNext() && i2.hasNext()) {
int itemComp = TupleUtil.compareItems(i1.next(), i2.next());
if(itemComp != 0) {
return itemComp;
}
}
while(i1.hasNext() && i2.hasNext()) {
int itemComp = TupleUtil.compareItems(i1.next(), i2.next());
if(itemComp != 0) {
return itemComp;
}
}
if(i1.hasNext()) {
// iterable2 is a prefix of iterable1.
return 1;
}
if(i2.hasNext()) {
// iterable1 is a prefix of iterable2.
return -1;
}
return 0;
}
if(i1.hasNext()) {
// iterable2 is a prefix of iterable1.
return 1;
}
if(i2.hasNext()) {
// iterable1 is a prefix of iterable2.
return -1;
}
return 0;
}
}

View File

@ -22,7 +22,7 @@
* Provides a set of utilities for serializing and deserializing typed data
* for use in FoundationDB. When packed together into a {@link com.apple.foundationdb.tuple.Tuple}
* this data is suitable for use as an index or organizational structure within FoundationDB
* keyspace. See <a href="/data-modeling.html#data-modeling-tuples">general Tuple
* keyspace. See <a href="/foundationdb/data-modeling.html#data-modeling-tuples">general Tuple
* documentation</a> for information about how Tuples sort and can be used to efficiently
* model data.
*/

View File

@ -5,22 +5,10 @@ This documents the client API for using FoundationDB from Java.<br>
<h3>Installation</h3>
FoundationDB's Java bindings rely on native libraries that are installed as part of the
FoundationDB client binaries installation (see
<a href="/api-general.html#installing-client-binaries" target="_blank">
Installing FoundationDB client binaries</a>). The FoundationDB Java bindings are available
through Artifactory. To use them in your Maven-enabled project, add a dependency to your
pom.xml like: <br>
<pre>
{@code
<dependency>
<groupId>com.apple.cie.foundationdb</groupId>
<artifactId>fdb-java</artifactId>
<version>VERSION</version>
</dependency>
}
</pre>
Alternatively, simply download the JAR from
<a href="https://www.foundationdb.org/downloads/fdb-java/">Artifactory</a>
and add it to your classpath.<br>
<a href="/foundationdb/api-general.html#installing-client-binaries" target="_blank">
Installing FoundationDB client binaries</a>). The JAR can be downloaded from
<a href="https://www.foundationdb.org/download/">our website</a>
and then added to your classpath.<br>
<br>
<h3>Getting started</h3>
To start using FoundationDB from Java, create an instance of the
@ -30,7 +18,7 @@ With this API object you can then open {@link com.apple.foundationdb.Cluster Clu
{@link com.apple.foundationdb.Database Database}s and start using
{@link com.apple.foundationdb.Transaction Transaction}s.
Here we give an example. The example relies on a cluster file at the
<a href="/administration.html#default-cluster-file">default location</a>
<a href="/foundationdb/administration.html#default-cluster-file">default location</a>
for your platform and a running server.<br>
<br>
<pre>
@ -69,7 +57,7 @@ cross-language support for storing and retrieving typed data from the
binary data that FoundationDB supports. And, just as importantly, data packed into
{@code Tuple}s and used as keys sort in predictable and useful ways. See the
{@link com.apple.foundationdb.tuple Tuple class documentation} for information about use in Java
and <a href="/data-modeling.html#data-modeling-tuples">general Tuple documentation</a>
and <a href="/foundationdb/data-modeling.html#data-modeling-tuples">general Tuple documentation</a>
for information about how Tuples sort and can be used to efficiently model data.
<br>
<h3>FoundationDB {@link com.apple.foundationdb.directory Directory API}</h3>

View File

@ -27,89 +27,89 @@ import com.apple.foundationdb.Database;
import com.apple.foundationdb.FDB;
public abstract class AbstractTester {
public static final int API_VERSION = 520;
protected static final int NUM_RUNS = 25;
protected static final Charset ASCII = Charset.forName("ASCII");
public static final int API_VERSION = 520;
protected static final int NUM_RUNS = 25;
protected static final Charset ASCII = Charset.forName("ASCII");
protected TesterArgs args;
protected Random random;
protected TestResult result;
protected FDB fdb;
protected TesterArgs args;
protected Random random;
protected TestResult result;
protected FDB fdb;
public AbstractTester() {
args = null;
random = new Random();
result = new TestResult(random);
}
public AbstractTester() {
args = null;
random = new Random();
result = new TestResult(random);
}
public void runTest() {
try(Database db = fdb.open()) {
try {
testPerformance(db);
}
catch (Exception e) {
result.addError(wrapAndPrintError(e, "Failed to complete all tests"));
}
}
catch (Exception e) {
result.addError(wrapAndPrintError(e, "fdb.open failed"));
return;
}
}
public void runTest() {
try(Database db = fdb.open()) {
try {
testPerformance(db);
}
catch (Exception e) {
result.addError(wrapAndPrintError(e, "Failed to complete all tests"));
}
}
catch (Exception e) {
result.addError(wrapAndPrintError(e, "fdb.open failed"));
return;
}
}
public abstract void testPerformance(Database db);
public abstract void testPerformance(Database db);
public String multiVersionDescription() {
if (args == null) return "";
public String multiVersionDescription() {
if (args == null) return "";
if (!args.useMultiversionApi()) {
return "multi-version API disabled";
} else if (args.useExternalClient()) {
if (args.putCallbacksOnExternalThread()) {
return "external client on external thread";
} else {
return "external client on main thread";
}
} else {
return "local client";
}
}
if (!args.useMultiversionApi()) {
return "multi-version API disabled";
} else if (args.useExternalClient()) {
if (args.putCallbacksOnExternalThread()) {
return "external client on external thread";
} else {
return "external client on main thread";
}
} else {
return "local client";
}
}
public void run(String[] argStrings) {
args = TesterArgs.parseArgs(argStrings);
if (args == null) return;
public void run(String[] argStrings) {
args = TesterArgs.parseArgs(argStrings);
if (args == null) return;
fdb = FDB.selectAPIVersion(API_VERSION);
fdb = FDB.selectAPIVersion(API_VERSION);
// Validate argument combinations and set options.
if (!args.useMultiversionApi()) {
if (args.putCallbacksOnExternalThread() || args.useExternalClient()) {
throw new IllegalArgumentException("Invalid multi-version API argument combination");
}
fdb.options().setDisableMultiVersionClientApi();
}
if (args.putCallbacksOnExternalThread()) {
if (!args.useExternalClient()) {
throw new IllegalArgumentException("Cannot enable callbacks on external thread without using external client");
}
fdb.options().setCallbacksOnExternalThreads();
}
if (args.useExternalClient()) {
fdb.options().setDisableLocalClient();
}
// Validate argument combinations and set options.
if (!args.useMultiversionApi()) {
if (args.putCallbacksOnExternalThread() || args.useExternalClient()) {
throw new IllegalArgumentException("Invalid multi-version API argument combination");
}
fdb.options().setDisableMultiVersionClientApi();
}
if (args.putCallbacksOnExternalThread()) {
if (!args.useExternalClient()) {
throw new IllegalArgumentException("Cannot enable callbacks on external thread without using external client");
}
fdb.options().setCallbacksOnExternalThreads();
}
if (args.useExternalClient()) {
fdb.options().setDisableLocalClient();
}
try {
runTest();
} catch (Exception e) {
result.addError(e);
}
try {
runTest();
} catch (Exception e) {
result.addError(e);
}
result.save(args.getOutputDirectory());
}
result.save(args.getOutputDirectory());
}
public RuntimeException wrapAndPrintError(Throwable t, String message) {
String errorMessage = message + ": " + t.getClass() + ": " + t.getMessage() + "\n";
t.printStackTrace();
return new RuntimeException(errorMessage, t);
}
public RuntimeException wrapAndPrintError(Throwable t, String message) {
String errorMessage = message + ": " + t.getClass() + ": " + t.getMessage() + "\n";
t.printStackTrace();
return new RuntimeException(errorMessage, t);
}
}

View File

@ -477,7 +477,6 @@ public class AsyncStackTester {
tr.options().setCausalReadRisky();
tr.options().setCausalWriteRisky();
tr.options().setReadYourWritesDisable();
tr.options().setReadAheadDisable();
tr.options().setReadSystemKeys();
tr.options().setAccessSystemKeys();
tr.options().setDurabilityDevNullIsWebScale();

View File

@ -24,7 +24,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.apple.foundationdb.Cluster;
import com.apple.foundationdb.Database;
import com.apple.foundationdb.FDB;
import com.apple.foundationdb.TransactionContext;

View File

@ -22,7 +22,6 @@ package com.apple.foundationdb.test;
import java.util.concurrent.atomic.AtomicInteger;
import com.apple.foundationdb.Cluster;
import com.apple.foundationdb.Database;
import com.apple.foundationdb.FDB;
import com.apple.foundationdb.KeyValue;

View File

@ -53,15 +53,14 @@ public class ParallelRandomScan {
}
private static void runTest(Database database,
int parallelism, int rows, int duration) throws InterruptedException
{
int parallelism, int rows, int duration) throws InterruptedException {
final Random r = new Random();
final AtomicInteger readsCompleted = new AtomicInteger(0);
final AtomicInteger errors = new AtomicInteger(0);
final Semaphore coordinator = new Semaphore(parallelism);
final ContinuousSample<Long> latencies = new ContinuousSample<>(1000);
try(final Transaction tr = database.createTransaction()) {
try(Transaction tr = database.createTransaction()) {
tr.options().setReadYourWritesDisable();
// Clearing the whole database before starting means all reads are local

View File

@ -41,370 +41,370 @@ import com.apple.foundationdb.async.AsyncUtil;
import com.apple.foundationdb.tuple.ByteArrayUtil;
public class PerformanceTester extends AbstractTester {
private final int keyCount;
private final int keySize;
private final int valueSize;
private final String keyFormat;
private final byte[] valueBytes;
public static final int DEFAULT_KEY_COUNT = 10_000;
public static final int DEFAULT_KEY_SIZE = 16;
public static final int DEFAULT_VALUE_SIZE = 100;
private enum Tests {
FUTURE_LATENCY("Java Completable API future throughput"),
SET("Java Completable API set throughput"),
CLEAR("Java Completable API clear throughput"),
CLEAR_RANGE("Java Completable API clear_range throughput"),
PARALLEL_GET("Java Completable API parallel get throughput"),
SERIAL_GET("Java Completable API serial get throughput"),
GET_RANGE("Java Completable API get_range throughput"),
GET_KEY("Java Completable API get_key throughput"),
GET_SINGLE_KEY_RANGE("Java Completable API get_single_key_range throughput"),
ALTERNATING_GET_SET("Java Completable API alternating get and set throughput"),
WRITE_TRANSACTION("Java Completable API single-key transaction throughput");
private String kpi;
private Function<? super Database, ? extends Double> function;
Tests(String kpi) {
this.kpi = kpi;
}
public void setFunction(Function<?super Database, ? extends Double> function) {
this.function = function;
}
public Function<? super Database, ? extends Double> getFunction() {
return function;
}
public String getKpi() {
return kpi;
}
}
public PerformanceTester() {
this(DEFAULT_KEY_COUNT, DEFAULT_KEY_SIZE, DEFAULT_VALUE_SIZE);
}
public PerformanceTester(int keyCount, int keySize, int valueSize) {
super();
this.keyCount = keyCount;
this.keySize = keySize;
this.valueSize = valueSize;
keyFormat = "%0" + keySize + "d";
valueBytes = new byte[valueSize];
Arrays.fill(valueBytes, (byte)'x');
// Initialize tests.
Tests.FUTURE_LATENCY.setFunction(db -> futureLatency(db, 100_000));
Tests.SET.setFunction(db -> set(db, 100_000));
Tests.CLEAR.setFunction(db -> clear(db, 100_000));
Tests.CLEAR_RANGE.setFunction(db -> clearRange(db, 100_000));
Tests.PARALLEL_GET.setFunction(db -> parallelGet(db, 10_000));
Tests.SERIAL_GET.setFunction(db -> serialGet(db, 2_000));
Tests.GET_RANGE.setFunction(db -> getRange(db, 1_000));
Tests.GET_KEY.setFunction(db -> getKey(db, 2_000));
Tests.GET_SINGLE_KEY_RANGE.setFunction(db -> getSingleKeyRange(db, 2_000));
Tests.ALTERNATING_GET_SET.setFunction(db -> alternatingGetSet(db, 2_000));
Tests.WRITE_TRANSACTION.setFunction(db -> writeTransaction(db, 1_000));
}
@Override
public void testPerformance(Database db) {
insertData(db);
List<String> testsToRun;
if (args.getTestsToRun().isEmpty()) {
testsToRun = Arrays.stream(Tests.values()).map(Tests::name).map(String::toLowerCase).sorted().collect(Collectors.toList());
} else {
testsToRun = args.getTestsToRun();
}
for (String test : testsToRun) {
Tests testObj;
try {
testObj = Tests.valueOf(test.toUpperCase());
} catch (IllegalArgumentException e) {
result.addError(new IllegalArgumentException("Test " + test + " not implemented"));
continue;
}
Function<? super Database, ? extends Double> function = testObj.getFunction();
try {
Thread.sleep(5_000);
} catch (InterruptedException e) {
result.addError(wrapAndPrintError(e, "Interrupted while sleeping"));
}
System.out.println("Running test " + test);
List<Double> results = new ArrayList<>(NUM_RUNS);
for (int i = 0; i < NUM_RUNS; i++) {
try {
results.add(function.apply(db));
} catch (Exception e) {
result.addError(wrapAndPrintError(e, "Performance test failed: " + test));
break;
}
}
if (results.size() == NUM_RUNS) {
Collections.sort(results);
result.addKpi(String.format("%s (%s)", testObj.getKpi(), multiVersionDescription()), results.get(results.size()/2).intValue(), "keys/s");
}
}
}
public void insertData(Database db) {
System.out.println("Loading database");
db.run(tr -> {
byte[] subspacePrefix = args.getSubspace().pack();
if (subspacePrefix.length == 0) {
// Clear user space.
tr.clear(new byte[0], new byte[]{(byte)0xff});
} else {
tr.clear(args.getSubspace().range());
}
return null;
});
int keysPerActor = 100_000 / (keySize + valueSize);
int numActors = (int)Math.ceil(keyCount*1.0/keysPerActor);
List<CompletableFuture<Void>> futures = IntStream.range(0, numActors).mapToObj(i -> {
int startKey = keysPerActor * i;
int endKey = (i + 1 == numActors) ? (keyCount) : (keysPerActor * (i+1));
return db.runAsync(tr -> {
IntStream.range(startKey, endKey).forEach(keyIndex -> tr.set(key(keyIndex), value(keyIndex)));
return CompletableFuture.completedFuture((Void)null);
});
}).collect(Collectors.toList());
try {
AsyncUtil.whenAll(futures).get();
} catch (InterruptedException | ExecutionException e) {
result.addError(wrapAndPrintError(e, "Data insertion failed"));
}
// Give the database time to re-balance
try {
Thread.sleep(15_000);
} catch (InterruptedException e) {
result.addError(wrapAndPrintError(e, "Interrupted while waiting for quiescence"));
}
}
public Double futureLatency(Database db, int count) {
return db.run(tr -> {
tr.options().setRetryLimit(5);
tr.getReadVersion().join();
long start = System.nanoTime();
for (int i = 0; i < count; i++) {
tr.getReadVersion().join();
}
long end = System.nanoTime();
return count*1_000_000_000.0/(end - start);
});
}
public Double clear(Database db, int count) {
try(Transaction tr = db.createTransaction()) {
long start = System.nanoTime();
for(int i = 0; i < count; i++) {
tr.clear(randomKey());
}
long end = System.nanoTime();
tr.cancel();
return count * 1_000_000_000.0 / (end - start);
}
}
public Double clearRange(Database db, int count) {
try(Transaction tr = db.createTransaction()) {
long start = System.nanoTime();
for(int i = 0; i < count; i++) {
int keyIndex = randomKeyIndex();
tr.clear(key(keyIndex), key(keyIndex + 1));
}
long end = System.nanoTime();
tr.cancel();
return count * 1_000_000_000.0 / (end - start);
}
}
public Double set(Database db, int count) {
try(Transaction tr = db.createTransaction()) {
long start = System.nanoTime();
for(int i = 0; i < count; i++) {
int keyIndex = randomKeyIndex();
tr.set(key(keyIndex), value(keyIndex));
}
long end = System.nanoTime();
tr.cancel();
return count * 1_000_000_000.0 / (end - start);
}
}
public Double parallelGet(TransactionContext tcx, int count) {
return tcx.run(tr -> {
tr.options().setRetryLimit(5);
long start = System.nanoTime();
List<CompletableFuture<byte[]>> futures = IntStream.range(0, count)
.mapToObj(ignore -> tr.get(randomKey()))
.collect(Collectors.toList());
AsyncUtil.whenAll(futures).join();
long end = System.nanoTime();
return count*1_000_000_000.0/(end - start);
});
}
public Double alternatingGetSet(TransactionContext tcx, int count) {
return tcx.run(tr -> {
tr.options().setRetryLimit(5);
long start = System.nanoTime();
List<CompletableFuture<byte[]>> futures = IntStream.range(0, count)
.mapToObj(ignore -> {
int keyIndex = randomKeyIndex();
byte[] keyBytes = key(keyIndex);
byte[] valBytes = value(keyIndex);
tr.set(keyBytes, valBytes);
return tr.get(keyBytes);
}).collect(Collectors.toList());
AsyncUtil.whenAll(futures).join();
long end = System.nanoTime();
return count*1_000_000_000.0/(end - start);
});
}
public Double serialGet(TransactionContext tcx, int count) {
return tcx.run(tr -> {
tr.options().setRetryLimit(5);
List<byte[]> keys;
if (count > keyCount/2) {
keys = Stream.generate(this::randomKey).limit(count).collect(Collectors.toList());
} else {
Set<Integer> keySet = new HashSet<>();
while (keySet.size() < count) {
keySet.add(randomKeyIndex());
}
keys = keySet.stream().map(this::key).collect(Collectors.toList());
}
long start = System.nanoTime();
for (byte[] key : keys) {
tr.get(key).join();
}
long end = System.nanoTime();
return count*1_000_000_000.0/(end - start);
});
}
public Double getRange(TransactionContext tcx, int count) {
return tcx.run(tr -> {
tr.options().setRetryLimit(5);
int startIndex = random.nextInt(keyCount - count);
long start = System.nanoTime();
tr.getRange(key(startIndex), key(startIndex+count)).asList().join();
long end = System.nanoTime();
return count*1_000_000_000.0/(end - start);
});
}
public Double getKey(TransactionContext tcx, int count) {
return tcx.run(tr -> {
tr.options().setRetryLimit(5);
long start = System.nanoTime();
for (int i = 0; i < count; i++) {
tr.getKey(new KeySelector(randomKey(), true, random.nextInt(20) - 10)).join();
}
long end = System.nanoTime();
return count*1_000_000_000.0/(end - start);
});
}
public Double getSingleKeyRange(TransactionContext tcx, int count) {
return tcx.run(tr -> {
tr.options().setRetryLimit(5);
long start = System.nanoTime();
for (int i = 0; i < count; i++) {
int keyIndex = randomKeyIndex();
tr.getRange(key(keyIndex), key(keyIndex + 1), 2).asList().join();
}
long end = System.nanoTime();
return count*1_000_000_000.0/(end - start);
});
}
public Double writeTransaction(TransactionContext tcx, int count) {
long start = System.nanoTime();
for (int i = 0; i < count; i++) {
tcx.run(tr -> {
int keyIndex = randomKeyIndex();
tr.set(key(keyIndex), value(keyIndex));
return null;
});
}
long end = System.nanoTime();
return count*1_000_000_000.0/(end - start);
}
public byte[] key(int i) {
return ByteArrayUtil.join(args.getSubspace().pack(), String.format(keyFormat, i).getBytes(ASCII));
}
public int randomKeyIndex() {
return random.nextInt(keyCount);
}
public byte[] randomKey() {
return key(randomKeyIndex());
}
public byte[] value(int key) {
return valueBytes;
}
public static void main(String[] args) {
System.out.println("Running Java performance test on Java version " + System.getProperty("java.version"));
try {
new PerformanceTester().run(args);
} catch (IllegalArgumentException e) {
System.out.println("Could not run test due to malformed arguments.");
System.out.println(e.getMessage());
System.exit(1);
} catch (Exception e) {
System.out.println("Fatal error encountered during run: " + e);
e.printStackTrace();
System.exit(2);
}
}
private final int keyCount;
private final int keySize;
private final int valueSize;
private final String keyFormat;
private final byte[] valueBytes;
public static final int DEFAULT_KEY_COUNT = 10_000;
public static final int DEFAULT_KEY_SIZE = 16;
public static final int DEFAULT_VALUE_SIZE = 100;
private enum Tests {
FUTURE_LATENCY("Java Completable API future throughput"),
SET("Java Completable API set throughput"),
CLEAR("Java Completable API clear throughput"),
CLEAR_RANGE("Java Completable API clear_range throughput"),
PARALLEL_GET("Java Completable API parallel get throughput"),
SERIAL_GET("Java Completable API serial get throughput"),
GET_RANGE("Java Completable API get_range throughput"),
GET_KEY("Java Completable API get_key throughput"),
GET_SINGLE_KEY_RANGE("Java Completable API get_single_key_range throughput"),
ALTERNATING_GET_SET("Java Completable API alternating get and set throughput"),
WRITE_TRANSACTION("Java Completable API single-key transaction throughput");
private String kpi;
private Function<? super Database, ? extends Double> function;
Tests(String kpi) {
this.kpi = kpi;
}
public void setFunction(Function<?super Database, ? extends Double> function) {
this.function = function;
}
public Function<? super Database, ? extends Double> getFunction() {
return function;
}
public String getKpi() {
return kpi;
}
}
public PerformanceTester() {
this(DEFAULT_KEY_COUNT, DEFAULT_KEY_SIZE, DEFAULT_VALUE_SIZE);
}
public PerformanceTester(int keyCount, int keySize, int valueSize) {
super();
this.keyCount = keyCount;
this.keySize = keySize;
this.valueSize = valueSize;
keyFormat = "%0" + keySize + "d";
valueBytes = new byte[valueSize];
Arrays.fill(valueBytes, (byte)'x');
// Initialize tests.
Tests.FUTURE_LATENCY.setFunction(db -> futureLatency(db, 100_000));
Tests.SET.setFunction(db -> set(db, 100_000));
Tests.CLEAR.setFunction(db -> clear(db, 100_000));
Tests.CLEAR_RANGE.setFunction(db -> clearRange(db, 100_000));
Tests.PARALLEL_GET.setFunction(db -> parallelGet(db, 10_000));
Tests.SERIAL_GET.setFunction(db -> serialGet(db, 2_000));
Tests.GET_RANGE.setFunction(db -> getRange(db, 1_000));
Tests.GET_KEY.setFunction(db -> getKey(db, 2_000));
Tests.GET_SINGLE_KEY_RANGE.setFunction(db -> getSingleKeyRange(db, 2_000));
Tests.ALTERNATING_GET_SET.setFunction(db -> alternatingGetSet(db, 2_000));
Tests.WRITE_TRANSACTION.setFunction(db -> writeTransaction(db, 1_000));
}
@Override
public void testPerformance(Database db) {
insertData(db);
List<String> testsToRun;
if (args.getTestsToRun().isEmpty()) {
testsToRun = Arrays.stream(Tests.values()).map(Tests::name).map(String::toLowerCase).sorted().collect(Collectors.toList());
} else {
testsToRun = args.getTestsToRun();
}
for (String test : testsToRun) {
Tests testObj;
try {
testObj = Tests.valueOf(test.toUpperCase());
} catch (IllegalArgumentException e) {
result.addError(new IllegalArgumentException("Test " + test + " not implemented"));
continue;
}
Function<? super Database, ? extends Double> function = testObj.getFunction();
try {
Thread.sleep(5_000);
} catch (InterruptedException e) {
result.addError(wrapAndPrintError(e, "Interrupted while sleeping"));
}
System.out.println("Running test " + test);
List<Double> results = new ArrayList<>(NUM_RUNS);
for (int i = 0; i < NUM_RUNS; i++) {
try {
results.add(function.apply(db));
} catch (Exception e) {
result.addError(wrapAndPrintError(e, "Performance test failed: " + test));
break;
}
}
if (results.size() == NUM_RUNS) {
Collections.sort(results);
result.addKpi(String.format("%s (%s)", testObj.getKpi(), multiVersionDescription()), results.get(results.size()/2).intValue(), "keys/s");
}
}
}
public void insertData(Database db) {
System.out.println("Loading database");
db.run(tr -> {
byte[] subspacePrefix = args.getSubspace().pack();
if (subspacePrefix.length == 0) {
// Clear user space.
tr.clear(new byte[0], new byte[]{(byte)0xff});
} else {
tr.clear(args.getSubspace().range());
}
return null;
});
int keysPerActor = 100_000 / (keySize + valueSize);
int numActors = (int)Math.ceil(keyCount*1.0/keysPerActor);
List<CompletableFuture<Void>> futures = IntStream.range(0, numActors).mapToObj(i -> {
int startKey = keysPerActor * i;
int endKey = (i + 1 == numActors) ? (keyCount) : (keysPerActor * (i+1));
return db.runAsync(tr -> {
IntStream.range(startKey, endKey).forEach(keyIndex -> tr.set(key(keyIndex), value(keyIndex)));
return CompletableFuture.completedFuture((Void)null);
});
}).collect(Collectors.toList());
try {
AsyncUtil.whenAll(futures).get();
} catch (InterruptedException | ExecutionException e) {
result.addError(wrapAndPrintError(e, "Data insertion failed"));
}
// Give the database time to re-balance
try {
Thread.sleep(15_000);
} catch (InterruptedException e) {
result.addError(wrapAndPrintError(e, "Interrupted while waiting for quiescence"));
}
}
public Double futureLatency(Database db, int count) {
return db.run(tr -> {
tr.options().setRetryLimit(5);
tr.getReadVersion().join();
long start = System.nanoTime();
for (int i = 0; i < count; i++) {
tr.getReadVersion().join();
}
long end = System.nanoTime();
return count*1_000_000_000.0/(end - start);
});
}
public Double clear(Database db, int count) {
try(Transaction tr = db.createTransaction()) {
long start = System.nanoTime();
for(int i = 0; i < count; i++) {
tr.clear(randomKey());
}
long end = System.nanoTime();
tr.cancel();
return count * 1_000_000_000.0 / (end - start);
}
}
public Double clearRange(Database db, int count) {
try(Transaction tr = db.createTransaction()) {
long start = System.nanoTime();
for(int i = 0; i < count; i++) {
int keyIndex = randomKeyIndex();
tr.clear(key(keyIndex), key(keyIndex + 1));
}
long end = System.nanoTime();
tr.cancel();
return count * 1_000_000_000.0 / (end - start);
}
}
public Double set(Database db, int count) {
try(Transaction tr = db.createTransaction()) {
long start = System.nanoTime();
for(int i = 0; i < count; i++) {
int keyIndex = randomKeyIndex();
tr.set(key(keyIndex), value(keyIndex));
}
long end = System.nanoTime();
tr.cancel();
return count * 1_000_000_000.0 / (end - start);
}
}
public Double parallelGet(TransactionContext tcx, int count) {
return tcx.run(tr -> {
tr.options().setRetryLimit(5);
long start = System.nanoTime();
List<CompletableFuture<byte[]>> futures = IntStream.range(0, count)
.mapToObj(ignore -> tr.get(randomKey()))
.collect(Collectors.toList());
AsyncUtil.whenAll(futures).join();
long end = System.nanoTime();
return count*1_000_000_000.0/(end - start);
});
}
public Double alternatingGetSet(TransactionContext tcx, int count) {
return tcx.run(tr -> {
tr.options().setRetryLimit(5);
long start = System.nanoTime();
List<CompletableFuture<byte[]>> futures = IntStream.range(0, count)
.mapToObj(ignore -> {
int keyIndex = randomKeyIndex();
byte[] keyBytes = key(keyIndex);
byte[] valBytes = value(keyIndex);
tr.set(keyBytes, valBytes);
return tr.get(keyBytes);
}).collect(Collectors.toList());
AsyncUtil.whenAll(futures).join();
long end = System.nanoTime();
return count*1_000_000_000.0/(end - start);
});
}
public Double serialGet(TransactionContext tcx, int count) {
return tcx.run(tr -> {
tr.options().setRetryLimit(5);
List<byte[]> keys;
if (count > keyCount/2) {
keys = Stream.generate(this::randomKey).limit(count).collect(Collectors.toList());
} else {
Set<Integer> keySet = new HashSet<>();
while (keySet.size() < count) {
keySet.add(randomKeyIndex());
}
keys = keySet.stream().map(this::key).collect(Collectors.toList());
}
long start = System.nanoTime();
for (byte[] key : keys) {
tr.get(key).join();
}
long end = System.nanoTime();
return count*1_000_000_000.0/(end - start);
});
}
public Double getRange(TransactionContext tcx, int count) {
return tcx.run(tr -> {
tr.options().setRetryLimit(5);
int startIndex = random.nextInt(keyCount - count);
long start = System.nanoTime();
tr.getRange(key(startIndex), key(startIndex+count)).asList().join();
long end = System.nanoTime();
return count*1_000_000_000.0/(end - start);
});
}
public Double getKey(TransactionContext tcx, int count) {
return tcx.run(tr -> {
tr.options().setRetryLimit(5);
long start = System.nanoTime();
for (int i = 0; i < count; i++) {
tr.getKey(new KeySelector(randomKey(), true, random.nextInt(20) - 10)).join();
}
long end = System.nanoTime();
return count*1_000_000_000.0/(end - start);
});
}
public Double getSingleKeyRange(TransactionContext tcx, int count) {
return tcx.run(tr -> {
tr.options().setRetryLimit(5);
long start = System.nanoTime();
for (int i = 0; i < count; i++) {
int keyIndex = randomKeyIndex();
tr.getRange(key(keyIndex), key(keyIndex + 1), 2).asList().join();
}
long end = System.nanoTime();
return count*1_000_000_000.0/(end - start);
});
}
public Double writeTransaction(TransactionContext tcx, int count) {
long start = System.nanoTime();
for (int i = 0; i < count; i++) {
tcx.run(tr -> {
int keyIndex = randomKeyIndex();
tr.set(key(keyIndex), value(keyIndex));
return null;
});
}
long end = System.nanoTime();
return count*1_000_000_000.0/(end - start);
}
public byte[] key(int i) {
return ByteArrayUtil.join(args.getSubspace().pack(), String.format(keyFormat, i).getBytes(ASCII));
}
public int randomKeyIndex() {
return random.nextInt(keyCount);
}
public byte[] randomKey() {
return key(randomKeyIndex());
}
public byte[] value(int key) {
return valueBytes;
}
public static void main(String[] args) {
System.out.println("Running Java performance test on Java version " + System.getProperty("java.version"));
try {
new PerformanceTester().run(args);
} catch (IllegalArgumentException e) {
System.out.println("Could not run test due to malformed arguments.");
System.out.println(e.getMessage());
System.exit(1);
} catch (Exception e) {
System.out.println("Fatal error encountered during run: " + e);
e.printStackTrace();
System.exit(2);
}
}
}

View File

@ -32,62 +32,62 @@ import com.apple.foundationdb.Transaction;
import com.apple.foundationdb.tuple.ByteArrayUtil;
public class RYWBenchmark extends AbstractTester {
private int keyCount;
private int keyCount;
public static final int DEFAULT_KEY_COUNT = 10_000;
public static final int DEFAULT_KEY_SIZE = 16;
public static final int DEFAULT_KEY_COUNT = 10_000;
public static final int DEFAULT_KEY_SIZE = 16;
private final String keyFormat;
private final String keyFormat;
private enum Tests {
GET_SINGLE("RYW Java Completable: get single cached value throughput"),
GET_MANY_SEQUENTIAL("RYW Java Completable: get sequential cached value throughput"),
GET_RANGE_BASIC("RYW Java Completable: get range cached values throughput"),
SINGLE_CLEAR_GET_RANGE("RYW Java Completable: get range cached values with clears throughput"),
CLEAR_RANGE_GET_RANGE("RYW Java Completable: get range cached values with clear ranges throughput"),
INTERLEAVED_SETS_GETS("RYW Java Completable: interleaved sets and gets on a single key throughput");
private enum Tests {
GET_SINGLE("RYW Java Completable: get single cached value throughput"),
GET_MANY_SEQUENTIAL("RYW Java Completable: get sequential cached value throughput"),
GET_RANGE_BASIC("RYW Java Completable: get range cached values throughput"),
SINGLE_CLEAR_GET_RANGE("RYW Java Completable: get range cached values with clears throughput"),
CLEAR_RANGE_GET_RANGE("RYW Java Completable: get range cached values with clear ranges throughput"),
INTERLEAVED_SETS_GETS("RYW Java Completable: interleaved sets and gets on a single key throughput");
private String kpi;
private Function<? super Transaction, ? extends Double> function;
private String kpi;
private Function<? super Transaction, ? extends Double> function;
Tests(String kpi) {
this.kpi = kpi;
}
Tests(String kpi) {
this.kpi = kpi;
}
public void setFunction(Function<?super Transaction, ? extends Double> function) {
this.function = function;
}
public void setFunction(Function<?super Transaction, ? extends Double> function) {
this.function = function;
}
public Function<? super Transaction, ? extends Double> getFunction() {
return function;
}
public Function<? super Transaction, ? extends Double> getFunction() {
return function;
}
public String getKpi() {
return kpi;
}
}
public String getKpi() {
return kpi;
}
}
public RYWBenchmark() {
this(DEFAULT_KEY_COUNT, DEFAULT_KEY_SIZE);
}
public RYWBenchmark() {
this(DEFAULT_KEY_COUNT, DEFAULT_KEY_SIZE);
}
public RYWBenchmark(int keyCount, int keySize) {
super();
this.keyCount = keyCount;
public RYWBenchmark(int keyCount, int keySize) {
super();
this.keyCount = keyCount;
keyFormat = "%0" + keySize + "d";
keyFormat = "%0" + keySize + "d";
Tests.GET_SINGLE.setFunction(tr -> getSingle(tr, 10_000));
Tests.GET_MANY_SEQUENTIAL.setFunction(tr -> getManySequential(tr, 10_000));
Tests.GET_RANGE_BASIC.setFunction(tr -> getRangeBasic(tr, 1_000));
Tests.SINGLE_CLEAR_GET_RANGE.setFunction(tr -> singleClearGetRange(tr, 1_000));
Tests.CLEAR_RANGE_GET_RANGE.setFunction(tr -> clearRangeGetRange(tr, 1_000));
Tests.INTERLEAVED_SETS_GETS.setFunction(tr -> interleavedSetsGets(tr, 10_000));
}
Tests.GET_SINGLE.setFunction(tr -> getSingle(tr, 10_000));
Tests.GET_MANY_SEQUENTIAL.setFunction(tr -> getManySequential(tr, 10_000));
Tests.GET_RANGE_BASIC.setFunction(tr -> getRangeBasic(tr, 1_000));
Tests.SINGLE_CLEAR_GET_RANGE.setFunction(tr -> singleClearGetRange(tr, 1_000));
Tests.CLEAR_RANGE_GET_RANGE.setFunction(tr -> clearRangeGetRange(tr, 1_000));
Tests.INTERLEAVED_SETS_GETS.setFunction(tr -> interleavedSetsGets(tr, 10_000));
}
@Override
public void testPerformance(Database db) {
try(Transaction tr = db.createTransaction()) {
@Override
public void testPerformance(Database db) {
try(Transaction tr = db.createTransaction()) {
insertData(tr);
List<String> testsToRun;
@ -139,103 +139,103 @@ public class RYWBenchmark extends AbstractTester {
tr.cancel();
}
}
}
public Double getSingle(Transaction tr, int count) {
long start = System.nanoTime();
for (int i = 0; i < count; i++) {
tr.get(key(5001)).join();
}
long end = System.nanoTime();
public Double getSingle(Transaction tr, int count) {
long start = System.nanoTime();
for (int i = 0; i < count; i++) {
tr.get(key(5001)).join();
}
long end = System.nanoTime();
return count*1_000_000_000.0/(end - start);
}
return count*1_000_000_000.0/(end - start);
}
public Double getManySequential(Transaction tr, int count) {
long start = System.nanoTime();
for (int i = 0; i < count; i++) {
tr.get(key(i)).join();
}
long end = System.nanoTime();
public Double getManySequential(Transaction tr, int count) {
long start = System.nanoTime();
for (int i = 0; i < count; i++) {
tr.get(key(i)).join();
}
long end = System.nanoTime();
return count*1_000_000_000.0/(end - start);
}
return count*1_000_000_000.0/(end - start);
}
public Double getRangeBasic(Transaction tr, int count) {
long start = System.nanoTime();
for (int i = 0; i < count; i++) {
tr.getRange(key(0), key(keyCount)).asList().join();
}
long end = System.nanoTime();
public Double getRangeBasic(Transaction tr, int count) {
long start = System.nanoTime();
for (int i = 0; i < count; i++) {
tr.getRange(key(0), key(keyCount)).asList().join();
}
long end = System.nanoTime();
return count * 1_000_000_000.0 * keyCount/(end - start);
}
return count * 1_000_000_000.0 * keyCount/(end - start);
}
public Double singleClearGetRange(Transaction tr, int count) {
for (int i = 0; i < keyCount; i += 2) {
tr.clear(("" + i).getBytes(ASCII));
}
long start = System.nanoTime();
for (int i = 0; i < count; i++) {
tr.getRange(key(0), key(keyCount)).asList().join();
}
long end = System.nanoTime();
public Double singleClearGetRange(Transaction tr, int count) {
for (int i = 0; i < keyCount; i += 2) {
tr.clear(("" + i).getBytes(ASCII));
}
long start = System.nanoTime();
for (int i = 0; i < count; i++) {
tr.getRange(key(0), key(keyCount)).asList().join();
}
long end = System.nanoTime();
Double kpi = count * 1_000_000_000.0 * keyCount / 2 / (end - start);
insertData(tr);
return kpi;
}
Double kpi = count * 1_000_000_000.0 * keyCount / 2 / (end - start);
insertData(tr);
return kpi;
}
public Double clearRangeGetRange(Transaction tr, int count) {
for (int i = 0; i < keyCount; i += 4) {
tr.clear(key(i), key(i+1));
}
long start = System.nanoTime();
for (int i = 0; i < count; i++) {
tr.getRange(key(0), key(keyCount)).asList().join();
}
long end = System.nanoTime();
public Double clearRangeGetRange(Transaction tr, int count) {
for (int i = 0; i < keyCount; i += 4) {
tr.clear(key(i), key(i+1));
}
long start = System.nanoTime();
for (int i = 0; i < count; i++) {
tr.getRange(key(0), key(keyCount)).asList().join();
}
long end = System.nanoTime();
Double kpi = count * 1_000_000_000.0 * keyCount * 3 / 4 / (end - start);
insertData(tr);
return kpi;
}
Double kpi = count * 1_000_000_000.0 * keyCount * 3 / 4 / (end - start);
insertData(tr);
return kpi;
}
public Double interleavedSetsGets(Transaction tr, int count) {
long start = System.nanoTime();
byte[] keyBytes = "foo".getBytes(ASCII);
tr.set(keyBytes, "1".getBytes(ASCII));
for (int i = 0; i < count; i++) {
int old = Integer.parseInt(new String(tr.get(keyBytes).join(), ASCII));
tr.set(keyBytes, ("" + (old + 1)).getBytes(ASCII));
}
long end = System.nanoTime();
public Double interleavedSetsGets(Transaction tr, int count) {
long start = System.nanoTime();
byte[] keyBytes = "foo".getBytes(ASCII);
tr.set(keyBytes, "1".getBytes(ASCII));
for (int i = 0; i < count; i++) {
int old = Integer.parseInt(new String(tr.get(keyBytes).join(), ASCII));
tr.set(keyBytes, ("" + (old + 1)).getBytes(ASCII));
}
long end = System.nanoTime();
return count * 1_000_000_000.0/(end - start);
}
return count * 1_000_000_000.0/(end - start);
}
public void insertData(Transaction tr) {
tr.clear(new byte[0], new byte[]{(byte)0xff}); // Clear user space.
for (int i = 0; i < keyCount; i++) {
tr.set(key(i), "foo".getBytes(ASCII));
}
}
public void insertData(Transaction tr) {
tr.clear(new byte[0], new byte[]{(byte)0xff}); // Clear user space.
for (int i = 0; i < keyCount; i++) {
tr.set(key(i), "foo".getBytes(ASCII));
}
}
public byte[] key(int i) {
return ByteArrayUtil.join(args.getSubspace().pack(), String.format(keyFormat, i).getBytes(ASCII));
}
public byte[] key(int i) {
return ByteArrayUtil.join(args.getSubspace().pack(), String.format(keyFormat, i).getBytes(ASCII));
}
public static void main(String[] args) {
System.out.println("Running Java RYW benchmark on Java version " + System.getProperty("java.version"));
try {
new RYWBenchmark().run(args);
} catch (IllegalArgumentException e) {
System.out.println("Could not run test due to malformed arguments.");
System.exit(1);
} catch (Exception e) {
System.out.println("Fatal error encountered during run: " + e);
e.printStackTrace();
System.exit(2);
}
}
public static void main(String[] args) {
System.out.println("Running Java RYW benchmark on Java version " + System.getProperty("java.version"));
try {
new RYWBenchmark().run(args);
} catch (IllegalArgumentException e) {
System.out.println("Could not run test due to malformed arguments.");
System.exit(1);
} catch (Exception e) {
System.out.println("Fatal error encountered during run: " + e);
e.printStackTrace();
System.exit(2);
}
}
}

View File

@ -22,7 +22,6 @@ package com.apple.foundationdb.test;
import java.util.concurrent.atomic.AtomicInteger;
import com.apple.foundationdb.Cluster;
import com.apple.foundationdb.Database;
import com.apple.foundationdb.FDB;
import com.apple.foundationdb.TransactionContext;

View File

@ -427,7 +427,6 @@ public class StackTester {
tr.options().setCausalReadRisky();
tr.options().setCausalWriteRisky();
tr.options().setReadYourWritesDisable();
tr.options().setReadAheadDisable();
tr.options().setReadSystemKeys();
tr.options().setAccessSystemKeys();
tr.options().setDurabilityDevNullIsWebScale();

View File

@ -62,7 +62,7 @@ public class StackUtils {
throw e;
}
item = getErrorBytes(ex);
item = getErrorBytes(ex);
}
return item;
}

View File

@ -30,119 +30,119 @@ import java.util.Random;
import java.util.TreeMap;
public class TestResult {
private long id;
private Map<String,Map<String,Object>> kpis;
private List<Throwable> errors;
private long id;
private Map<String,Map<String,Object>> kpis;
private List<Throwable> errors;
public TestResult(Random r) {
id = Math.abs(r.nextLong());
kpis = new TreeMap<String,Map<String,Object>>(); // Tree map because we will have to print this out.
errors = new ArrayList<Throwable>();
}
public TestResult(Random r) {
id = Math.abs(r.nextLong());
kpis = new TreeMap<String,Map<String,Object>>(); // Tree map because we will have to print this out.
errors = new ArrayList<Throwable>();
}
public void addKpi(String name, Number value, String units) {
TreeMap<String,Object> kpi = new TreeMap<String,Object>();
kpi.put("value", value);
kpi.put("units", units);
kpis.put(name, kpi);
}
public void addKpi(String name, Number value, String units) {
TreeMap<String,Object> kpi = new TreeMap<String,Object>();
kpi.put("value", value);
kpi.put("units", units);
kpis.put(name, kpi);
}
public void addError(Throwable t) {
errors.add(t);
}
public void addError(Throwable t) {
errors.add(t);
}
public void save(String directory) {
String file = "javaresult-" + id + ".json";
if(directory.length() > 0) {
file = directory + "/" + file;
}
public void save(String directory) {
String file = "javaresult-" + id + ".json";
if(directory.length() > 0) {
file = directory + "/" + file;
}
// TODO: Should we use a really JSON library?
// TODO: Should we use a really JSON library?
StringBuilder outputBuilder = new StringBuilder();
outputBuilder.append('{');
StringBuilder outputBuilder = new StringBuilder();
outputBuilder.append('{');
// Add KPIs:
outputBuilder.append("\"kpis\": {");
boolean firstKpi = true;
for (Map.Entry<String,Map<String,Object>> kpi : kpis.entrySet()) {
if (firstKpi) {
firstKpi = false;
} else {
outputBuilder.append(", ");
}
// Add KPIs:
outputBuilder.append("\"kpis\": {");
boolean firstKpi = true;
for (Map.Entry<String,Map<String,Object>> kpi : kpis.entrySet()) {
if (firstKpi) {
firstKpi = false;
} else {
outputBuilder.append(", ");
}
outputBuilder.append("\"");
outputBuilder.append(kpi.getKey());
outputBuilder.append("\": {");
outputBuilder.append("\"");
outputBuilder.append(kpi.getKey());
outputBuilder.append("\": {");
boolean firstEntry = true;
boolean firstEntry = true;
for (Map.Entry<String,Object> entry : kpi.getValue().entrySet()) {
if (firstEntry) {
firstEntry = false;
} else {
outputBuilder.append(", ");
}
for (Map.Entry<String,Object> entry : kpi.getValue().entrySet()) {
if (firstEntry) {
firstEntry = false;
} else {
outputBuilder.append(", ");
}
outputBuilder.append("\"");
outputBuilder.append(entry.getKey());
outputBuilder.append("\": ");
outputBuilder.append("\"");
outputBuilder.append(entry.getKey());
outputBuilder.append("\": ");
Object value = entry.getValue();
if (value instanceof String) {
outputBuilder.append("\"");
outputBuilder.append((String)value);
outputBuilder.append("\"");
} else {
outputBuilder.append(value.toString());
}
}
Object value = entry.getValue();
if (value instanceof String) {
outputBuilder.append("\"");
outputBuilder.append((String)value);
outputBuilder.append("\"");
} else {
outputBuilder.append(value.toString());
}
}
outputBuilder.append("}");
}
outputBuilder.append("}, ");
outputBuilder.append("}");
}
outputBuilder.append("}, ");
// Add errors:
outputBuilder.append("\"errors\":[");
boolean firstError = true;
for (Throwable t : errors) {
if (firstError) {
firstError = false;
} else {
outputBuilder.append(", ");
}
// Add errors:
outputBuilder.append("\"errors\":[");
boolean firstError = true;
for (Throwable t : errors) {
if (firstError) {
firstError = false;
} else {
outputBuilder.append(", ");
}
StringBuilder msgBuilder = new StringBuilder();
msgBuilder.append(t.getClass().toString());
msgBuilder.append(": ");
msgBuilder.append(t.getMessage()); // Escaping quotes. Yeah, this won't work in the general case....
StackTraceElement[] stackTraceElements = t.getStackTrace();
for (StackTraceElement element : stackTraceElements) {
msgBuilder.append("\n ");
msgBuilder.append(element.toString());
}
outputBuilder.append('"');
outputBuilder.append(msgBuilder.toString()
.replace("\\", "\\\\")
.replace("\"", "\\\"")
.replace("\t", "\\t")
.replace("\r", "\\r")
.replace("\n", "\\n")
.replace("\f", "\\f")
.replace("\b", "\\b")
);
outputBuilder.append('"');
}
outputBuilder.append("]");
StringBuilder msgBuilder = new StringBuilder();
msgBuilder.append(t.getClass().toString());
msgBuilder.append(": ");
msgBuilder.append(t.getMessage()); // Escaping quotes. Yeah, this won't work in the general case....
StackTraceElement[] stackTraceElements = t.getStackTrace();
for (StackTraceElement element : stackTraceElements) {
msgBuilder.append("\n ");
msgBuilder.append(element.toString());
}
outputBuilder.append('"');
outputBuilder.append(msgBuilder.toString()
.replace("\\", "\\\\")
.replace("\"", "\\\"")
.replace("\t", "\\t")
.replace("\r", "\\r")
.replace("\n", "\\n")
.replace("\f", "\\f")
.replace("\b", "\\b")
);
outputBuilder.append('"');
}
outputBuilder.append("]");
outputBuilder.append('}');
outputBuilder.append('}');
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
writer.write(outputBuilder.toString());
} catch (IOException e) {
System.out.println("Could not write results to file " + file);
throw new RuntimeException("Could not save results: " + e.getMessage(), e);
}
}
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
writer.write(outputBuilder.toString());
} catch (IOException e) {
System.out.println("Could not write results to file " + file);
throw new RuntimeException("Could not save results: " + e.getMessage(), e);
}
}
}

View File

@ -27,126 +27,126 @@ import com.apple.foundationdb.subspace.Subspace;
import com.apple.foundationdb.tuple.Tuple;
public class TesterArgs {
private String outputDirectory;
private boolean multiversionApi;
private boolean callbacksOnExternalThread;
private boolean externalClient;
private Subspace subspace;
private List<String> testsToRun;
private String outputDirectory;
private boolean multiversionApi;
private boolean callbacksOnExternalThread;
private boolean externalClient;
private Subspace subspace;
private List<String> testsToRun;
private TesterArgs(String outputDirectory, boolean multiversionApi, boolean callbacksOnExternalThread, boolean externalClient, Subspace subspace, List<String> testsToRun) {
this.outputDirectory = outputDirectory;
this.multiversionApi = multiversionApi;
this.callbacksOnExternalThread = callbacksOnExternalThread;
this.externalClient = externalClient;
this.subspace = subspace;
this.testsToRun = testsToRun;
}
private TesterArgs(String outputDirectory, boolean multiversionApi, boolean callbacksOnExternalThread, boolean externalClient, Subspace subspace, List<String> testsToRun) {
this.outputDirectory = outputDirectory;
this.multiversionApi = multiversionApi;
this.callbacksOnExternalThread = callbacksOnExternalThread;
this.externalClient = externalClient;
this.subspace = subspace;
this.testsToRun = testsToRun;
}
public static void printUsage() {
String usage = "Arguments: [-o/--output-directory DIR] [--disable-multiversion-api] [--enable-callbacks-on-external-threads] [--use-external-client] [--tests-to-run TEST [TEST ...]] [-h/--help]\n" +
"\n" +
"Arguments:\n" +
" -o/--output-directory DIR Directory to store JSON output. If not set, the current directory is used.\n" +
" --disable-multiversion-api Disables the multi-version client API\n" +
" --enable-callbacks-on-external-threads Allows callbacks to be called on threads created by the client library.\n" +
" --use-external-client Connect to the server using an external client.\n" +
" --tests-to-run TEST [TEST ...] List of test names to run.\n" +
" -h/--help Print this help message and then quit.\n";
public static void printUsage() {
String usage = "Arguments: [-o/--output-directory DIR] [--disable-multiversion-api] [--enable-callbacks-on-external-threads] [--use-external-client] [--tests-to-run TEST [TEST ...]] [-h/--help]\n" +
"\n" +
"Arguments:\n" +
" -o/--output-directory DIR Directory to store JSON output. If not set, the current directory is used.\n" +
" --disable-multiversion-api Disables the multi-version client API\n" +
" --enable-callbacks-on-external-threads Allows callbacks to be called on threads created by the client library.\n" +
" --use-external-client Connect to the server using an external client.\n" +
" --tests-to-run TEST [TEST ...] List of test names to run.\n" +
" -h/--help Print this help message and then quit.\n";
System.out.print(usage);
}
System.out.print(usage);
}
/**
* Parses the argument strings into a <code>TesterArgs</code> instance.
* This will return <code>null</code> if the args include an argument telling
* it to print the help message and it will throw an {@link IllegalArgumentException}
* if it can't parse the arguments.
*
* @param args command-line args
* @return built instance or <code>null</code>
* @throws IllegalArgumentException if the arguments can't be parsed
*/
public static TesterArgs parseArgs(String[] args) {
String outputDirectory = "";
boolean multiversionApi = true;
boolean callbacksOnExternalThread = false;
boolean externalClient = false;
Subspace subspace = new Subspace();
List<String> testsToRun = new ArrayList<String>();
/**
* Parses the argument strings into a <code>TesterArgs</code> instance.
* This will return <code>null</code> if the args include an argument telling
* it to print the help message and it will throw an {@link IllegalArgumentException}
* if it can't parse the arguments.
*
* @param args command-line args
* @return built instance or <code>null</code>
* @throws IllegalArgumentException if the arguments can't be parsed
*/
public static TesterArgs parseArgs(String[] args) {
String outputDirectory = "";
boolean multiversionApi = true;
boolean callbacksOnExternalThread = false;
boolean externalClient = false;
Subspace subspace = new Subspace();
List<String> testsToRun = new ArrayList<String>();
for (int i = 0; i < args.length; i++) {
String arg = args[i];
if (arg.equals("-o") || arg.equals("--output-directory")) {
if (i + 1 < args.length) {
outputDirectory = args[++i];
} else {
System.out.println("No output directory specified for argument " + arg + "\n");
printUsage();
throw new IllegalArgumentException("No output directory specified for argument " + arg);
}
} else if (arg.equals("--subspace")) {
if (i + 1 < args.length) {
subspace = new Subspace(Tuple.from(args[++i]));
} else {
System.out.println("No subspace specified for argument " + arg + "\n");
printUsage();
throw new IllegalArgumentException("Not subspace specified for argument " + arg);
}
} else if (arg.equals("--disable-multiversion-api")) {
multiversionApi = false;
} else if (arg.equals("--enable-callbacks-on-external-threads")) {
callbacksOnExternalThread = true;
} else if (arg.equals("--use-external-client")) {
externalClient = true;
} else if (arg.equals("--tests-to-run")) {
if (i + 1 < args.length && args[i + 1].charAt(0) != '-') {
int j;
for (j = i + 1; j < args.length && args[j].charAt(0) != '-'; j++) {
testsToRun.add(args[j]);
}
i = j - 1;
} else {
System.out.println("No tests specified with argument " + arg + "\n");
printUsage();
throw new IllegalArgumentException("No tests specified with argument " + arg);
}
} else if (arg.equals("-h") || arg.equals("--help")) {
printUsage();
return null;
} else {
System.out.println("Unknown argument " + arg + "\n");
printUsage();
throw new IllegalArgumentException("Unknown argument " + arg);
}
}
for (int i = 0; i < args.length; i++) {
String arg = args[i];
if (arg.equals("-o") || arg.equals("--output-directory")) {
if (i + 1 < args.length) {
outputDirectory = args[++i];
} else {
System.out.println("No output directory specified for argument " + arg + "\n");
printUsage();
throw new IllegalArgumentException("No output directory specified for argument " + arg);
}
} else if (arg.equals("--subspace")) {
if (i + 1 < args.length) {
subspace = new Subspace(Tuple.from(args[++i]));
} else {
System.out.println("No subspace specified for argument " + arg + "\n");
printUsage();
throw new IllegalArgumentException("Not subspace specified for argument " + arg);
}
} else if (arg.equals("--disable-multiversion-api")) {
multiversionApi = false;
} else if (arg.equals("--enable-callbacks-on-external-threads")) {
callbacksOnExternalThread = true;
} else if (arg.equals("--use-external-client")) {
externalClient = true;
} else if (arg.equals("--tests-to-run")) {
if (i + 1 < args.length && args[i + 1].charAt(0) != '-') {
int j;
for (j = i + 1; j < args.length && args[j].charAt(0) != '-'; j++) {
testsToRun.add(args[j]);
}
i = j - 1;
} else {
System.out.println("No tests specified with argument " + arg + "\n");
printUsage();
throw new IllegalArgumentException("No tests specified with argument " + arg);
}
} else if (arg.equals("-h") || arg.equals("--help")) {
printUsage();
return null;
} else {
System.out.println("Unknown argument " + arg + "\n");
printUsage();
throw new IllegalArgumentException("Unknown argument " + arg);
}
}
return new TesterArgs(outputDirectory, multiversionApi, callbacksOnExternalThread, externalClient, subspace, testsToRun);
}
return new TesterArgs(outputDirectory, multiversionApi, callbacksOnExternalThread, externalClient, subspace, testsToRun);
}
// Accessors.
// Accessors.
public String getOutputDirectory() {
return outputDirectory;
}
public String getOutputDirectory() {
return outputDirectory;
}
public boolean useMultiversionApi() {
return multiversionApi;
}
public boolean useMultiversionApi() {
return multiversionApi;
}
public boolean putCallbacksOnExternalThread() {
return callbacksOnExternalThread;
}
public boolean putCallbacksOnExternalThread() {
return callbacksOnExternalThread;
}
public boolean useExternalClient() {
return externalClient;
}
public boolean useExternalClient() {
return externalClient;
}
public Subspace getSubspace() {
return subspace;
}
public Subspace getSubspace() {
return subspace;
}
public List<String> getTestsToRun() {
return testsToRun;
}
public List<String> getTestsToRun() {
return testsToRun;
}
}

View File

@ -20,7 +20,6 @@
package com.apple.foundationdb.test;
import com.apple.foundationdb.Cluster;
import com.apple.foundationdb.Database;
import com.apple.foundationdb.FDB;
import com.apple.foundationdb.TransactionContext;

View File

@ -31,9 +31,9 @@ import com.apple.foundationdb.tuple.Tuple;
import com.apple.foundationdb.tuple.Versionstamp;
public class VersionstampSmokeTest {
public static void main(String[] args) {
FDB fdb = FDB.selectAPIVersion(520);
try(Database db = fdb.open()) {
public static void main(String[] args) {
FDB fdb = FDB.selectAPIVersion(520);
try(Database db = fdb.open()) {
db.run(tr -> {
tr.clear(Tuple.from("prefix").range());
return null;
@ -59,7 +59,7 @@ public class VersionstampSmokeTest {
System.out.println(Versionstamp.complete(trVersion));
assert v.equals(Versionstamp.complete(trVersion));
}
}
}
private VersionstampSmokeTest() {}
private VersionstampSmokeTest() {}
}

View File

@ -26,13 +26,13 @@ import java.util.concurrent.atomic.AtomicInteger;
import com.apple.foundationdb.async.AsyncUtil;
public class WhileTrueTest {
public static void main(String[] args) {
// This should cause memory issues using the old implementation but not the new one.
// Pro tip: Run with options -Xms16m -Xmx16m -XX:+HeadDumpOnOutOfMemoryError
AtomicInteger count = new AtomicInteger(1000000);
AsyncUtil.whileTrue(() -> CompletableFuture.completedFuture(count.decrementAndGet()).thenApplyAsync(c -> c > 0)).join();
System.out.println("Final value: " + count.get());
}
public static void main(String[] args) {
// This should cause memory issues using the old implementation but not the new one.
// Pro tip: Run with options -Xms16m -Xmx16m -XX:+HeadDumpOnOutOfMemoryError
AtomicInteger count = new AtomicInteger(1000000);
AsyncUtil.whileTrue(() -> CompletableFuture.completedFuture(count.decrementAndGet()).thenApplyAsync(c -> c > 0)).join();
System.out.println("Final value: " + count.get());
}
private WhileTrueTest() {}
private WhileTrueTest() {}
}

View File

@ -1,3 +0,0 @@
Complete documentation of the FoundationDB Node.js API can be found at [https://www.foundationdb.org/documentation/api-node.html](https://www.foundationdb.org/documentation/api-node.html).
These bindings require the FoundationDB client. The client can be obtained from [https://www.foundationdb.org/downloads/fdb-c/](https://www.foundationdb.org/downloads/fdb-c/).

View File

@ -1,25 +0,0 @@
{
'targets': [
{
'target_name': 'fdblib',
'sources': [ 'src/FdbV8Wrapper.cpp', 'src/Database.cpp', 'src/Transaction.cpp', 'src/Cluster.cpp', 'src/FdbError.cpp', 'src/FdbOptions.cpp', 'src/FdbOptions.g.cpp', 'src/FdbUtil.cpp' ],
'include_dirs': ['../c'],
'conditions': [
['OS=="linux"', {
'link_settings': { 'libraries': ['-lfdb_c', '-L../../../lib'] },
}],
['OS=="mac"', {
'xcode_settings': {
'MACOSX_DEPLOYMENT_TARGET': '10.7', # -mmacosx-version-min=10.7
'OTHER_CFLAGS': ['-std=c++0x']
},
'link_settings': { 'libraries': ['-lfdb_c', '-L../../../lib'] },
}],
['OS=="win"', {
'link_settings': { 'libraries': ['../../../bin/Release/fdb_c.lib'] },
}],
],
'cflags': ['-std=c++0x'],
}
]
}

View File

@ -1,23 +0,0 @@
{
'targets': [
{
'target_name': 'fdblib',
'sources': [ 'src/FdbV8Wrapper.cpp', 'src/Database.cpp', 'src/Transaction.cpp', 'src/Cluster.cpp', 'src/FdbError.cpp', 'src/FdbOptions.cpp', 'src/FdbOptions.g.cpp', 'src/FdbUtil.cpp' ],
'conditions': [
['OS=="linux"', {
'link_settings': { 'libraries': ['-lfdb_c'] },
}],
['OS=="mac"', {
'xcode_settings': { 'OTHER_CFLAGS': ['-std=c++0x'] },
'include_dirs': ['/usr/local/include'],
'link_settings': { 'libraries': ['-lfdb_c', '-L/usr/local/lib'] },
}],
['OS=="win"', {
'link_settings': { 'libraries': ['<!(echo %FOUNDATIONDB_INSTALL_PATH%)\\lib\\foundationdb\\fdb_c.lib'] },
'include_dirs': ['<!(echo %FOUNDATIONDB_INSTALL_PATH%)\\include'],
}],
],
'cflags': ['-std=c++0x'],
}
]
}

View File

@ -1,28 +0,0 @@
/*
* FoundationDB Node.js API
* Copyright (c) 2012 FoundationDB, LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
"use strict";
var fdb = require('bindings')('fdblib.node');
module.exports = fdb;

View File

@ -1,157 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(SolutionDir)versions.target" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{9463CB25-DCA0-9D45-C46E-0A8E68EE7FAE}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>fdblib</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings" />
<ImportGroup Label="PropertySheets">
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IgnoreImportLibrary>true</IgnoreImportLibrary>
<IntDir>$(SystemDrive)\temp\msvcfdb\$(Platform)$(Configuration)\$(MSBuildProjectName)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<TargetName>$(ProjectName)</TargetName>
<TargetPath>$(OutDir)$(ProjectName).node</TargetPath>
<TargetExt>.node</TargetExt>
</PropertyGroup>
<ItemDefinitionGroup>
<PreBuildEvent>
<Command>"$(ProgramW6432)\nodejs\node_modules\npm\bin\node-gyp-bin\node-gyp.cmd" install --ensure -v --target=$(NodeVersion)</Command>
</PreBuildEvent>
<PreBuildEvent>
<Message>Download and install node-gyp header and lib files</Message>
</PreBuildEvent>
<PostBuildEvent>
<Command>
mkdir modules
mkdir "modules\$(NodeVersionDir)"
copy "$(TargetPath)" "modules\$(NodeVersionDir)\fdblib.node"
</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<AdditionalIncludeDirectories>$(USERPROFILE)\.node-gyp\$(NodeVersion)\src;$(USERPROFILE)\.node-gyp\$(NodeVersion)\deps\uv\include;$(USERPROFILE)\.node-gyp\$(NodeVersion)\deps\v8\include;..\c;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<BufferSecurityCheck>true</BufferSecurityCheck>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4251;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ExceptionHandling>Sync</ExceptionHandling>
<MinimalRebuild>false</MinimalRebuild>
<OmitFramePointers>false</OmitFramePointers>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;BUILDING_V8_SHARED=1;BUILDING_UV_SHARED=1;DEBUG;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<StringPooling>true</StringPooling>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TreatWarningAsError>false</TreatWarningAsError>
<WarningLevel>Level3</WarningLevel>
</ClCompile>
<Link>
<AdditionalDependencies>$(USERPROFILE)\.node-gyp\$(NodeVersion)\$(Platform)\node.lib;..\..\bin\$(Configuration)\fdb_c.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AllowIsolation>true</AllowIsolation>
<DataExecutionPrevention>true</DataExecutionPrevention>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OutputFile>$(OutDir)$(ProjectName).node</OutputFile>
<RandomizedBaseAddress>true</RandomizedBaseAddress>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TargetMachine>MachineX64</TargetMachine>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>$(USERPROFILE)\.node-gyp\$(NodeVersion)\src;$(USERPROFILE)\.node-gyp\$(NodeVersion)\deps\uv\include;$(USERPROFILE)\.node-gyp\$(NodeVersion)\deps\v8\include;..\..\c;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;BUILDING_V8_SHARED=1;BUILDING_UV_SHARED=1;DEBUG;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<AdditionalIncludeDirectories>$(USERPROFILE)\.node-gyp\$(NodeVersion)\src;$(USERPROFILE)\.node-gyp\$(NodeVersion)\deps\uv\include;$(USERPROFILE)\.node-gyp\$(NodeVersion)\deps\v8\include;..\c;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/MP %(AdditionalOptions)</AdditionalOptions>
<BufferSecurityCheck>true</BufferSecurityCheck>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4251;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ExceptionHandling>false</ExceptionHandling>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<FunctionLevelLinking>true</FunctionLevelLinking>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<OmitFramePointers>true</OmitFramePointers>
<Optimization>Full</Optimization>
<PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;BUILDING_V8_SHARED=1;BUILDING_UV_SHARED=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<StringPooling>true</StringPooling>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TreatWarningAsError>false</TreatWarningAsError>
<WarningLevel>Level3</WarningLevel>
<WholeProgramOptimization>true</WholeProgramOptimization>
</ClCompile>
<Lib>
<AdditionalOptions>/LTCG %(AdditionalOptions)</AdditionalOptions>
</Lib>
<Link>
<AdditionalDependencies>$(USERPROFILE)\.node-gyp\$(NodeVersion)\$(Platform)\node.lib;..\..\bin\$(Configuration)\fdb_c.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AllowIsolation>true</AllowIsolation>
<DataExecutionPrevention>true</DataExecutionPrevention>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<GenerateDebugInformation>true</GenerateDebugInformation>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
<OptimizeReferences>true</OptimizeReferences>
<OutputFile>$(OutDir)$(ProjectName).node</OutputFile>
<RandomizedBaseAddress>true</RandomizedBaseAddress>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TargetMachine>MachineX64</TargetMachine>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>$(USERPROFILE)\.node-gyp\$(NodeVersion)\src;$(USERPROFILE)\.node-gyp\$(NodeVersion)\deps\uv\include;$(USERPROFILE)\.node-gyp\$(NodeVersion)\deps\v8\include;..\..\c;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;BUILDING_V8_SHARED=1;BUILDING_UV_SHARED=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\FdbOptions.g.cpp" />
<ClCompile Include="src\Database.cpp" />
<ClCompile Include="src\Transaction.cpp" />
<ClCompile Include="src\FdbError.cpp" />
<ClCompile Include="src\Cluster.cpp" />
<ClCompile Include="src\FdbV8Wrapper.cpp" />
<ClCompile Include="src\FdbOptions.cpp" />
<ClCompile Include="src\FdbUtil.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\Cluster.h" />
<ClInclude Include="src\Database.h" />
<ClInclude Include="src\FdbError.h" />
<ClInclude Include="src\FdbOptions.h" />
<ClInclude Include="src\FdbUtil.h" />
<ClInclude Include="src\NodeCallback.h" />
<ClInclude Include="src\Transaction.h" />
<ClInclude Include="src\Version.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
<Target Name="AfterClean">
<Message Text="Cleaning $(NodeVersionDir)\fdblib module" Importance="high" />
<Delete Files="modules\$(NodeVersionDir)\fdblib.node" />
</Target>
</Project>

View File

@ -1,64 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Load version information from the central versions file, creating -PRERELEASE if needed -->
<Import Project="$(SolutionDir)versions.target" />
<PropertyGroup Condition="'$(Release)' != 'true' ">
<PreReleaseDecoration>-PRERELEASE</PreReleaseDecoration>
</PropertyGroup>
<PropertyGroup Condition="'$(Release)' == 'true' ">
<PreReleaseDecoration>
</PreReleaseDecoration>
</PropertyGroup>
<!-- Set up VS minimal configuation -->
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{9463CB25-DCA0-9D45-C46E-0A8E68EE7FAE}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration">
<PlatformToolset>v140_xp</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup>
<IntDir>$(SystemDrive)\temp\msvcfdb\$(Platform)$(Configuration)\$(MSBuildProjectName)\</IntDir>
</PropertyGroup>
<!-- Meat of the work to create proper node output. -->
<ItemDefinitionGroup>
<!-- Clean up before a build -->
<PreBuildEvent>
<Command>del "$(SolutionDir)bin\$(Configuration)\fdb-node*.tar.gz"</Command>
</PreBuildEvent>
<PostBuildEvent>
<!-- After build, create package.json from input -->
<Command>
c:\python27\python -c "print open(\"package.json.in\").read().replace(\"VERSION\",\"$(Version)$(PreReleaseDecoration)\")" &gt; package.json
copy ..\..\LICENSE
c:\python27\python "$(SolutionDir)build/tarball.py" -r nodejs "$(SolutionDir)bin\$(Configuration)\fdb-node-$(Version)$(PreReleaseDecoration)-windows-$(Platform).tar.gz" lib modules package.json README.md LICENSE
del LICENSE</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Target Name="AfterClean">
<!-- Add output of which VS was not aware to "clean" step -->
<ItemGroup>
<FilesToDelete Include="$(ProjectDir)package.json">
<Visible>false</Visible>
</FilesToDelete>
<FilesToDelete Include="$(SolutionDir)bin\$(Configuration)\fdb-node-$(Version)$(PreReleaseDecoration)-windows-$(Platform).tar.gz">
<Visible>false</Visible>
</FilesToDelete>
</ItemGroup>
<Message Text="Cleaning package.json and tar.gz file" Importance="high" />
<Delete Files="@(FilesToDelete)" />
</Target>
</Project>

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>{E22D4EF8-E75D-4281-93F9-A9F73936DE54}</ProjectGuid>
</PropertyGroup>
<PropertyGroup Label="Configuration">
<PlatformToolset>v140_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup>
<NodeVersion>0.10.0</NodeVersion>
<NodeVersionDir>0.10</NodeVersionDir>
</PropertyGroup>
<Import Project="fdb_node.target" />
</Project>

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>{E936E200-689E-49FD-8463-32FE763F1860}</ProjectGuid>
</PropertyGroup>
<PropertyGroup Label="Configuration">
<PlatformToolset>v140_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup>
<NodeVersion>0.8.22</NodeVersion>
<NodeVersionDir>0.8</NodeVersionDir>
</PropertyGroup>
<Import Project="fdb_node.target" />
</Project>

View File

@ -1,99 +0,0 @@
#
# include.mk
#
# This source file is part of the FoundationDB open source project
#
# Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# -*- mode: makefile-gmake; -*-
TARGETS += fdb_node fdb_node_npm
CLEAN_TARGETS += fdb_node_clean fdb_node_npm_clean
NODE_VERSIONS := 0.8.22 0.10.0
NODE_DIST_URL ?= https://nodejs.org/dist
NODE_REGISTRY_URL ?= https://registry.npmjs.org/
ifeq ($(RELEASE),true)
NPMVER = $(VERSION)
else
NPMVER = $(VERSION)-PRERELEASE
endif
packages: fdb_node_npm
packages_clean: fdb_node_npm_clean
fdb_node: fdb_c bindings/nodejs/fdb_node.stamp
bindings/nodejs/fdb_node.stamp: bindings/nodejs/src/FdbOptions.g.cpp bindings/nodejs/src/*.cpp bindings/nodejs/src/*.h bindings/nodejs/binding.gyp lib/libfdb_c.$(DLEXT) bindings/nodejs/package.json
@echo "Building $@"
@rm -f $@
@cd bindings/nodejs && \
mkdir -p modules && \
rm -rf modules/* && \
for ver in $(NODE_VERSIONS); do \
MMVER=`echo $$ver | sed -e 's,\., ,g' | awk '{print $$1 "." $$2}'` && \
mkdir modules/$$MMVER && \
node-gyp configure --dist-url=$(NODE_DIST_URL) --target=$$ver && \
node-gyp -v build && \
cp build/Release/fdblib.node modules/$${MMVER} ; \
done
@touch $@
bindings/nodejs/src/FdbOptions.g.cpp: bin/vexillographer.exe fdbclient/vexillographer/fdb.options
@echo "Building $@"
@$(MONO) bin/vexillographer.exe fdbclient/vexillographer/fdb.options nodejs $@
fdb_node_clean:
@echo "Cleaning fdb_node"
@rm -f bindings/nodejs/src/FdbOptions.g.cpp
@rm -rf bindings/nodejs/modules
@(cd bindings/nodejs && node-gyp clean)
@rm -f bindings/nodejs/fdb_node.stamp
bindings/nodejs/package.json: bindings/nodejs/package.json.in $(ALL_MAKEFILES) versions.target
@m4 -DVERSION=$(NPMVER) $< > $@
@echo "Updating Node dependencies"
@cd bindings/nodejs && \
npm config set registry "$(NODE_REGISTRY_URL)" && \
npm update
fdb_node_npm: fdb_node versions.target bindings/nodejs/README.md bindings/nodejs/lib/*.js bindings/nodejs/src/* bindings/nodejs/binding.gyp LICENSE
@echo "Packaging NPM"
@mkdir -p packages
@rm -f packages/fdb-node-*
@rm -rf packages/nodejs.tmp
@mkdir -p packages/nodejs.tmp/nodejs
@cp LICENSE packages/nodejs.tmp/nodejs/LICENSE
@tar -C bindings -czf packages/fdb-node-$(NPMVER)-$(PLATFORM)-$(ARCH).tar.gz nodejs/lib nodejs/modules nodejs/package.json nodejs/README.md -C ../packages/nodejs.tmp nodejs/LICENSE
@rm -rf packages/nodejs.tmp
ifeq ($(PLATFORM),linux)
@echo "Packaging NPM (unbuilt)"
@rm -rf packages/nodejs.tmp
@mkdir -p packages/nodejs.tmp/npmsrc/nodejs
@cat bindings/nodejs/package.json | grep -v private | grep -v engineStrict | awk '/"semver"/ {print " \"bindings\": \"*\""; next} {print}' > packages/nodejs.tmp/npmsrc/nodejs/package.json
@cp -r bindings/nodejs/lib bindings/nodejs/src bindings/nodejs/README.md LICENSE packages/nodejs.tmp/npmsrc/nodejs
@cp bindings/nodejs/binding.gyp.npmsrc packages/nodejs.tmp/npmsrc/nodejs/binding.gyp
@cp bindings/nodejs/fdbModule.js.npmsrc packages/nodejs.tmp/npmsrc/nodejs/lib/fdbModule.js
@tar -C packages/nodejs.tmp/npmsrc -czf packages/fdb-node-$(NPMVER).tar.gz nodejs
@rm -rf packages/nodejs.tmp
endif
fdb_node_npm_clean:
@echo "Cleaning NPM"
@rm -f packages/fdb-node-* bindings/nodejs/package.json

View File

@ -1,26 +0,0 @@
/*
* apiVersion.js
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
var apiVersion;
module.exports = { value: apiVersion };

View File

@ -1,86 +0,0 @@
/*
* bufferConversion.js
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
var toBuffer = function(obj) {
if(Buffer.isBuffer(obj))
return obj;
if(obj instanceof ArrayBuffer)
obj = new Uint8Array(obj);
if(obj instanceof Uint8Array) {
var buf = new Buffer(obj.length);
for(var i = 0; i < obj.length; ++i)
buf[i] = obj[i];
return buf;
}
if(typeof obj === 'string')
return new Buffer(obj, 'utf8');
throw new TypeError('toBuffer function expects a string, buffer, ArrayBuffer, or Uint8Array');
};
toBuffer.fromByteLiteral = function(str) {
if(typeof str === 'string') {
var buf = new Buffer(str.length);
for(var i = 0; i < str.length; ++i) {
if(str[i] > 255)
throw new RangeError('fromByteLiteral string argument cannot have codepoints larger than 1 byte');
buf[i] = str.charCodeAt(i);
}
return buf;
}
else
throw new TypeError('fromByteLiteral function expects a string');
};
toBuffer.toByteLiteral = function(buf) {
if(Buffer.isBuffer(buf))
return String.fromCharCode.apply(null, buf);
else
throw new TypeError('toByteLiteral function expects a buffer');
};
toBuffer.printable = function(buf) {
buf = toBuffer(buf);
var out = '';
for(var i = 0; i < buf.length; ++i) {
if(buf[i] >= 32 && buf[i] < 127 && buf[i] !== 92)
out += String.fromCharCode(buf[i]);
else if(buf[i] === 92)
out += '\\\\';
else {
var str = buf[i].toString(16);
out += '\\x';
if(str.length == 1)
out += '0';
out += str;
}
}
return out;
};
module.exports = toBuffer;

View File

@ -1,38 +0,0 @@
/*
* cluster.js
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
var future = require('./future');
var Database = require('./database');
var Cluster = function(_cluster) {
this._cluster = _cluster;
this.options = _cluster.options;
};
Cluster.prototype.openDatabase = function() {
return new Database(this._cluster.openDatabase());
};
module.exports = Cluster;

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