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:
commit
af61d3596d
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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)
|
|
@ -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.
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
global:
|
||||
get_plugin;
|
||||
local:
|
||||
*;
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
_get_plugin
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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
|
|
@ -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 */
|
|
@ -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)
|
|
@ -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);
|
||||
}
|
|
@ -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'
|
|
@ -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-----
|
|
@ -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-----
|
|
@ -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-----
|
|
@ -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-----
|
|
@ -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-----
|
|
@ -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-----
|
|
@ -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-----
|
|
@ -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-----
|
|
@ -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-----
|
|
@ -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-----
|
|
@ -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);
|
||||
}
|
12
Makefile
12
Makefile
|
@ -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
|
||||
|
|
51
README.md
51
README.md
|
@ -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.
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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=()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 <item>
|
||||
|
||||
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
|
|
@ -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.
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
//
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
)
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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])
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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()
|
||||
);
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -62,7 +62,7 @@ public class StackUtils {
|
|||
throw e;
|
||||
}
|
||||
|
||||
item = getErrorBytes(ex);
|
||||
item = getErrorBytes(ex);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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() {}
|
||||
}
|
||||
|
|
|
@ -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() {}
|
||||
}
|
||||
|
|
|
@ -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/).
|
|
@ -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'],
|
||||
}
|
||||
]
|
||||
}
|
|
@ -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'],
|
||||
}
|
||||
]
|
||||
}
|
|
@ -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;
|
|
@ -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>
|
|
@ -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)\")" > 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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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
|
|
@ -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 };
|
||||
|
|
@ -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;
|
|
@ -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
Loading…
Reference in New Issue