Compare commits

...

252 Commits

Author SHA1 Message Date
Nik Bougalis
9cc8eec773 Set version to 0.27.2 2015-03-01 14:56:44 -08:00
Nik Bougalis
0b45535061 Calculate deep offer quality 2015-02-28 13:28:54 -08:00
Vinnie Falco
95973ba3e8 Set version to 0.27.1 2015-02-24 13:31:13 -08:00
Vinnie Falco
ac64731d55 Set version to 0.27.1-rc3 2015-02-12 12:59:48 -08:00
Vinnie Falco
5dc064e971 Revert "Disable Overlay socket handoffs"
This reverts commit 8eb05d0950.
2015-02-12 12:59:48 -08:00
Vinnie Falco
c24732ed4e Fix streambuf bug:
The buffers_type::iterator could hold a pointer to a buffers_type that
was destroyed. This changes buffers_type::iterator to point to the
original streambuf instead, which always outlives the iterator.
2015-02-12 12:59:35 -08:00
Vinnie Falco
ba710bee86 Reject invalid requests on peer port sooner. 2015-02-12 12:43:42 -08:00
Vinnie Falco
c20392ca80 Set version to 0.27.1-rc2 2015-02-11 20:53:27 -08:00
Vinnie Falco
8eb05d0950 Disable Overlay socket handoffs 2015-02-11 20:53:27 -08:00
Vinnie Falco
0f94e2c0c3 Set version to 0.27.1-rc1 2015-02-10 16:22:14 -08:00
Vinnie Falco
a25508b98d Add RocksDB to nudb import tool (RIPD-781,785):
This custom tool is specifically designed for very fast import of
RocksDB nodestore databases into NuDB.
2015-02-10 16:22:14 -08:00
Vinnie Falco
e825433a38 NuDB: Use nodeobject codec in Backend (RIPD-793):
This adds codecs for snappy and lz4, and a new nodeobject codec. The
nodeobject codec provides a highly efficient custom compression scheme
for inner nodes, which make up the majority of nodestore databases.
Non inner node objects are compressed using lz4.

The NuDB backend is modified to use the nodeobject codec. This change
is not backward compatible - older NuDB databases cannot be opened or
imported.
2015-02-10 16:22:13 -08:00
Vinnie Falco
d1c08889fe Remove obsolete NodeObject fields:
Legacy fields of NodeObject are removed, as they are no longer
used and there is a space savings from omitting them:

* Remove LedgerIndex
2015-02-10 16:22:13 -08:00
Vinnie Falco
0b82b5a0d6 NuDB: Performance improvements (RIPD-793,796):
This introduces changes in nudb to improve speed, reduce database size,
and enhance correctness. The most significant change is to store hashes
rather than entire keys in the key file. The output of the hash function
is reduced to 48 bits, and stored directly in buckets.

The API is also modified to introduce a Codec parameter allowing for
compression and decompression to be supported in the implementation
itself rather than callers.

THe data file no longer contains a salt, as the salt is applicable
only to the key and log files. This allows a data file to have multiple
key files with different salt values. To distinguish physical files
belonging to the same logical database, a new field UID is introduced.
The UID is a 64-bit random value generated once on creation and stored
in all three files.

Buckets are zero filled to the end of each block, this is a security
measure to prevent unintended contents of memory getting stored to
disk. NuDB offers the varint integer type, this is identical to
the varint described by Google.

* Add varint
* Add Codec template argument
* Add "api" convenience traits
* Store hash in buckets
* istream can throw short read errors
* Support std::uint8_t format in streams
* Make file classes part of the public interface
* Remove buffers pessimization, replace with buffer
* Consolidate creation utility functions to the same header
* Zero fill unused areas of buckets on disk
* More coverage and improvements to the recover test
* Fix file read/write to loop until all bytes processed
* Add verify_fast, faster verify for large databases

The database version number is incremented to 2; older databases can
no longer be opened and should be deleted.
2015-02-10 16:22:13 -08:00
Vinnie Falco
a33d0d4fb6 Add general delimiter split() to rfc2616 2015-02-08 19:43:37 -08:00
Vinnie Falco
ba42334d36 Add lz4
Conflicts:
	Builds/VisualStudio2013/RippleD.vcxproj
	Builds/VisualStudio2013/RippleD.vcxproj.filters
2015-02-08 19:43:26 -08:00
Vinnie Falco
2e62641aa4 Merge commit 'dad460dcfc8466a8e1c59529d490829fcfaeee73' as 'src/lz4' 2015-02-08 19:43:04 -08:00
Vinnie Falco
dad460dcfc Squashed 'src/lz4/' content from commit e25b51d
git-subtree-dir: src/lz4
git-subtree-split: e25b51de7b51101e04ceea194dd557fcc23c03ca
2015-02-08 19:43:04 -08:00
Vinnie Falco
3ae23b6a54 Remove spurious call to fetch in NuDBBackend 2015-02-08 19:42:07 -08:00
Vinnie Falco
97126f18b1 Add /crawl cgi request feature to peer protocol (RIPD-729):
This adds support for a cgi /crawl request, issued over HTTPS to the configured
peer protocol port. The response to the request is a JSON object containing
the node public key, type, and IP address of each directly connected neighbor.
The IP address is suppressed unless the neighbor has requested its address
to be revealed by adding "Crawl: public" to its HTTP headers. This field is
currently set by the peer_private option in the rippled.cfg file.
2015-02-08 19:42:01 -08:00
Vinnie Falco
3838d222c2 NuDB: limit size of mempool (RIPD-787):
Insert now blocks when the size of the memory pool exceeds a predefined
threshold. This solves the problem where sustained insertions cause the
memory pool to grow without bound.
2015-02-08 19:41:54 -08:00
Vinnie Falco
96c3292210 Add missing include 2015-02-08 19:41:48 -08:00
Vinnie Falco
b0fd92cb3f Fix unsafe iterator dereference in PeerFinder 2015-02-08 19:41:43 -08:00
Vinnie Falco
6276c55cc9 Set version to 0.27.0-sp1 2015-02-03 14:58:02 -08:00
Vinnie Falco
afa6ff7c4b Revert RocksDB backend settings:
This reverts the change that makes RocksDBQuick the default settings for
node_db "type=rocksdb". The quick settings can be obtained by setting
"type=rocksdbquick".

RocksDBQuick settings are implicated in memory over-utilization problems
seen recently.
2015-02-03 14:57:54 -08:00
Vinnie Falco
c6c8e5d70c Set version to 0.27.0 2015-01-26 10:56:11 -08:00
Nik Bougalis
fa354ec8d9 Set version to 0.27.0-b11 2015-01-23 17:37:18 -08:00
Nik Bougalis
d0375f697d Invoke correct deleter 2015-01-23 17:34:30 -08:00
Vinnie Falco
33c8257d25 Set version to 0.27.0-b10 2015-01-21 15:25:11 -08:00
Scott Determan
f389bc33c3 VSProject: Handle tuples in CPPDEFINES:
The VSProject generator now handles tuples in addition to strings and
dicts when converting environment variables such as CPPDEFINES.
2015-01-21 15:20:06 -08:00
Vinnie Falco
4d5dca71ce Squelch Peerfinder fixed connection attempts 2015-01-21 14:59:47 -08:00
Vinnie Falco
a9c44a1b9c Set version to 0.27.0-b9 2015-01-21 14:23:50 -08:00
Vinnie Falco
4144f800a1 Fix PeerImp concurrent access of socket:
The PeerImp::run launch function is now dispatched on the strand to prevent
undefined behavior resulting from concurrent access to the ssl::stream object.
2015-01-21 14:21:43 -08:00
Vinnie Falco
6ef9a81017 Set version to 0.27.0-b8 2015-01-21 14:21:43 -08:00
Vinnie Falco
8c6722f3c5 Remove use of date and time from rocksdb unity build 2015-01-21 14:21:43 -08:00
Vinnie Falco
40e138627b Fixes to Overlay:
* Make ~Peer virtual
* Call close in ConnectAttempt::stop
* Handle nullptr return in new_outbound_slot
* Check gracefulClose_ in read loop
2015-01-21 10:48:32 -08:00
Vinnie Falco
a470dda4e6 Fix Journal::Stream::active to return the correct value 2015-01-21 10:48:32 -08:00
Edward Hennis
b725410623 Option to specify rippled path on command line.
* --rippled=<absolute or relative path>
* Works for "npm test" and "mocha"
* Remove "rippled_path" from config.js to require CLI path.
2015-01-21 10:48:31 -08:00
Miguel Portilla
a9dfb33126 Log abnormal close time offsets (RIPD-572) 2015-01-21 10:48:31 -08:00
Miguel Portilla
8b848770dc Add config "ledger_history_index" functionality (RIPD-559) 2015-01-21 10:48:31 -08:00
Vinnie Falco
94629edb9b Add NuDB backend:
The NuDB database backend is a high performance key/value store presented
as an alternative to RocksDB on Mac and Linux deployments, and the preferred
backend option for Windows deployments. The LevelDB backend is deprecated for
all platforms.

This includes these changes:

* Add Backend::verify API for doing consistency checks
* Add Database::close so caller can catch exceptions
* Improved Timing test for NodeStore creates a simulated workload
2015-01-21 10:48:30 -08:00
Vinnie Falco
2a3f2ca28d Add NuDB: A Key/Value Store For Decentralized Systems
NuDB is a high performance key/value database optimized for insert-only
workloads, with these features:

* Low memory footprint
* Values are immutable
* Value sizes from 1 2^48 bytes (281TB)
* All keys are the same size
* Performance independent of growth
* Optimized for concurrent fetch
* Key file can be rebuilt if needed
* Inserts are atomic and consistent
* Data file may be iterated, index rebuilt.
* Key and data files may be on different volumes
* Hardened against algorithmic complexity attacks
* Header-only, nothing to build or link
2015-01-21 10:48:30 -08:00
Edward Hennis
8ab1e7d432 Integration test to subscribe to offer books. 2015-01-20 16:45:04 -08:00
Miguel Portilla
b2ba6a0c85 Fix RPC subscribe with multiple books 2015-01-20 16:45:04 -08:00
Tom Ritchford
cca5421aed Fix Subscribe RPC to correctly distinguish bids and asks. 2015-01-20 16:45:04 -08:00
Nik Bougalis
799d9a73e6 Ensure that hash_append will never throw
Conflicts:
	src/beast/beast/net/IPAddress.h
2015-01-20 16:45:03 -08:00
Scott Determan
b0781622b2 Handle nullptr return values to InboundLedgers::findCreate
In normal operation, InboundLedgers::findCreate never returns null, but
during system shutdown, it will return null.

Since this only happens in system shutdown, when findCreate returns null
the calling function stops what it was doing and returns.

During testing, an issue where destroying the application object
and creating a new one caused problems with a static PathTable. This table
is now cleared when re-initialized.
2015-01-20 16:45:03 -08:00
Tom Ritchford
0d0eec6345 Clean up test documentation and a log message. 2015-01-20 16:45:03 -08:00
Nik Bougalis
1af79f7960 Properly validate the configured online delete interval 2015-01-20 16:45:03 -08:00
Vinnie Falco
15b570bbdd Add profile targets for gcc and clang 2015-01-20 16:45:02 -08:00
Tom Ritchford
7aa5599cc2 Remove unused parameter in two lambdas. 2015-01-20 16:45:02 -08:00
JoelKatz
676293ec42 Ensure account_tx queries over and returns correct range 2015-01-20 16:45:02 -08:00
Nik Bougalis
abc4fb81b1 Improve RippleLineCache hashing 2015-01-20 16:45:01 -08:00
Vinnie Falco
53a16f354f Add hardened_hash to basics/:
xxhasher is the default hash function for hardened_hash.
2015-01-20 16:45:01 -08:00
Vinnie Falco
6ab1ecd836 Tidy up container hash functions:
* Add xxhasher
* Move fnv1a, siphash, spookyto hash/
* Move hash_append, uhash to hash/
* Move hash_speed_test to hash/
* Move hash classes to individual header files
* Remove hardened_hash
2015-01-20 16:45:01 -08:00
Vinnie Falco
e7b16e7b47 Add rngfill 2015-01-20 16:45:01 -08:00
Vinnie Falco
14804f81a8 Optimize calls to unit_test::suite::expect:
This changes expect and unexpected to receive the reason text as a
template argument, allowing the std::string conversion of char const*
parameters to take place only if the condition evaluates to false. This
cuts all calls to malloc and free on tests that pass.
2015-01-20 16:45:00 -08:00
Vinnie Falco
9a61b8d77d Declare base_uints with using statements 2015-01-20 16:45:00 -08:00
Vinnie Falco
f42c2763d5 Improve streambuf unit test 2015-01-20 16:45:00 -08:00
Vinnie Falco
98d4e0e1b5 Fix ZeroCopyOutputStream:
Added a destructor that commits the last block of data
if there was no final call to BackUp.
2015-01-20 16:45:00 -08:00
Tom Ritchford
9156633baf Set version to 0.27.0-b7 2015-01-20 17:59:55 -05:00
Tom Ritchford
bcf4f836b4 Use websocketpp_02 namespace. 2015-01-20 17:08:15 -05:00
Vinnie Falco
dbc1d70f99 Set version to 0.27.0-b6 2015-01-20 09:41:27 -08:00
Vinnie Falco
78bc190a85 Merge commit '02855d7fed46d3c1aa1f2cefbcf4a42720575c3f' as 'src/websocketpp' 2015-01-20 09:35:00 -08:00
Vinnie Falco
02855d7fed Squashed 'src/websocketpp/' content from commit 875d420
git-subtree-dir: src/websocketpp
git-subtree-split: 875d420952
2015-01-20 09:35:00 -08:00
Vinnie Falco
6fdd5d32be Rename websocket/ to websocketpp_02 2015-01-20 09:34:54 -08:00
Vinnie Falco
d7f32b105b Set version to 0.27.0-b5 2015-01-13 11:50:58 -08:00
Vinnie Falco
0ac480a0bd Fix extra increment in GenerateRootDeterministicKey 2015-01-13 11:49:59 -08:00
Tom Ritchford
417996de02 Set version to 0.27.0-b4 2015-01-13 11:30:23 -05:00
Tom Ritchford
6c2d60cec2 Prevent RPC handlers from returning non-objects. 2015-01-13 11:30:23 -05:00
Tom Ritchford
743bd6c917 Fix RPC command logrotate to return a Json object. 2015-01-13 11:30:14 -05:00
Edward Hennis
ab61aa41d9 Set version to 0.27.0-b3 2015-01-12 18:00:55 -05:00
Edward Hennis
36396ae29e rippled.cfg [db_node] options for RocksDB
* open_files and compression.
2015-01-12 18:00:54 -05:00
Vinnie Falco
749e083e6e NodeStore improvements:
* Add Backend::verify API for doing consistency checks
* Add Database::close so caller can catch exceptions
* Improved Timing test for NodeStore creates a simulated workload
2015-01-12 18:00:52 -05:00
Vinnie Falco
67b9cf9e82 Improved support for exceptions in threads spawned by unit tests:
Unit tests that wish to spawn threads for testing concurrency may now do so
by using unit_test::thread as a replacement for std::thread. These threads
propagate unhandled exceptions to the unit test, and work with the abort on
failure feature.
2015-01-12 17:17:09 -05:00
Vinnie Falco
27fb20f3ab Add xor_shift_engine 2015-01-12 17:17:07 -05:00
Josh Juran
1c71b274f0 SConstruct: Add ed25519.c
Conflicts:
	Builds/VisualStudio2013/RippleD.vcxproj
	Builds/VisualStudio2013/RippleD.vcxproj.filters
	SConstruct
2015-01-12 12:16:26 -08:00
Vinnie Falco
fcd20b63fe Merge commit '8ec344ac1b6c66d936fa0f7005490e126a434a70' as 'src/ed25519-donna' 2015-01-12 11:27:15 -08:00
Vinnie Falco
8ec344ac1b Squashed 'src/ed25519-donna/' content from commit 04223b0
git-subtree-dir: src/ed25519-donna
git-subtree-split: 04223b04e22f5eff32c6c27e25194d4d984c6f41
2015-01-12 11:27:15 -08:00
Vinnie Falco
df966a9ac6 Set version to 0.27.0-b2 2015-01-05 18:49:18 -08:00
Vinnie Falco
f634666dc6 Make rocksdbquick settings default:
This removes the old default configuration for the "rocksdb" backend and
replaces it with the configuration that was formerly available using
the experimental backend "rocksdbquick".

The new configuration setting improves the performance of the key/value
database by changing the compaction style and tuning the size parameters for
the typical rippled workload. Testing shows a decrease in I/O spikes for both
reading and writing.
2015-01-05 18:49:17 -08:00
Tom Ritchford
e2f9f5d7e5 Fix compilation warnings. 2015-01-05 18:49:17 -08:00
Tom Ritchford
d078b0d143 Extract the git ID into a separate compilation unit. 2015-01-05 18:49:15 -08:00
Nik Bougalis
0ccdea3cd8 Disable Ticket transactions and tests 2015-01-05 14:18:27 -08:00
Vinnie Falco
df54b47cd0 Tidy up includes and add modules to the classic build:
An alternative to the unity build, the classic build compiles each
translation unit individually. This adds more modules to the classic build:

* Remove unity header app.h
* Add missing includes as needed
* Remove obsolete NodeStore backend code
* Add app/, core/, crypto/, json/, net/, overlay/, peerfinder/ to classic build
2015-01-05 13:35:57 -08:00
Vinnie Falco
2e595830b3 Levelize SHAMap:
The SHAMap class is refactored into a separate module where each translation
unit compiles separate without errors. Dependencies on higher level business
logic are removed. SHAMap now depends only on basics, crypto, nodestore,
and protocol:

* Inject NodeStore::Database& to SHAMap
* Move sync filter instances to app/ledger/
* Move shamap to its own module
* Move FullBelowCache to shamap/
* Move private code to shamap/impl/
* Refactor SHAMap treatment of missing node handler
* Inject and use Journal for logging in SHAMap
2015-01-05 11:46:11 -08:00
Vinnie Falco
96fbcc9a5a Refactor NodeStore:
Manager is changed to be a Meyer's singleton, with factories automatically
registering upon construction.
2015-01-05 11:46:11 -08:00
Vinnie Falco
6283801981 Add non-unity build targets:
The SConstruct is modified to provide a new family of targets, ending with
the suffix ".nounity", which compile individual translation units instead of
some of the unity translation units ("classic" builds). Two modules updated
for this treatment are ripple/basics/ and ripple/protocol/, with plans to
update more in the future. A consequence is longer build times in some cases.
A benefit of classic builds is that missing includes can be identified
through compiler errors.
2015-01-05 11:46:11 -08:00
Vinnie Falco
9a3214d46e Normalize files containing unit test code:
Source files are split to place all unit test code into translation
units ending in .test.cpp with no other business logic in the same file,
and in directories named "test".

A new target is added to the SConstruct, invoked by:
    scons count
This prints the total number of source code lines occupied by unit tests,
in rippled specific code and excluding library subtrees.
2015-01-05 11:46:07 -08:00
Vinnie Falco
9eb7c8344f Don't leak track StringPairArray 2015-01-05 11:44:15 -08:00
Vinnie Falco
4140bbb1f7 Set version to 0.27.0-b1 2015-01-05 11:37:01 -08:00
Vinnie Falco
ea44497136 Fix msvc ICE on initializer-list 2015-01-05 11:37:00 -08:00
Nik Bougalis
07737c6e5b Add 'delivered_amount' to Transaction JSON (RIPD-643):
The synthetic field 'delivered_amount' can be used to determine the exact
amount delivered by a Payment without having to check the DeliveredAmount
field, if present, or the Amount field otherwise.

The field is only returned when metadata is available and the data is not
returned in binary format.
2014-12-31 01:55:10 -08:00
JoelKatz
98d5eefc86 Pathfinding bugfixes (RIPD-735):
* Fix specifying paths and search level for ripple_path_find
* Don't modify the pathfinder, it has issuer-neutral paths.
* Handle previous paths correctly
* Compare paths correctly
2014-12-31 01:55:10 -08:00
JoelKatz
4f2d93bb65 Avoid processing transactions if we need a network ledger
Not processing tranasctions without a network ledger makes
initial network synchronization faster.
2014-12-31 01:55:10 -08:00
Edward Hennis
a5df3f1747 Support a "no_server" flag in test config.
* Will use a running instance of rippled (possibly in a debugger).
* Modify all tests to respect the server_default value.
* Fail test if new account already exists and has a balance.
* README.md with instructions for advanced test debugging, particularly using no_server.
2014-12-31 01:55:10 -08:00
Howard Hinnant
7f5f73887d Fix undefined behavior 2014-12-31 01:55:10 -08:00
Nik Bougalis
91ce7807b9 Remove legacy LoadTypes (RIPD-365) 2014-12-31 01:55:10 -08:00
Nik Bougalis
d26fae9875 Reduce Beast dependencies by leveraging C++11 features:
* Remove beast::Atomic (RIPD-728):
  * Use std-provided alternatives
  * Eliminate atomic variables where possible

* Cleanup beast::Thread interface:
  * Use std::string instead of beast::String
  * Remove unused functions and parameters

* Remove unused code:
  * beast::ThreadLocalValue
  * beast::ServiceQueue
2014-12-31 01:55:10 -08:00
Nik Bougalis
60bdc79ec4 Remove unused sitefiles module 2014-12-30 12:33:41 -08:00
Tom Ritchford
253ddf2998 Split off CheckLibraryVersions.test.cpp. 2014-12-30 12:33:41 -08:00
Nik Bougalis
9fa15b390a Always initialize LedgerHandler options field 2014-12-29 11:21:19 -08:00
Josh Juran
e7d6fe6c8b Cull duplicate/unused code in RippleAddress:
Deduplicate a call to GeneratePublicDeterministicKey().
Remove unused member functions.
2014-12-29 11:21:19 -08:00
Tom Ritchford
9650b1aa70 New ripple::TestSuite with method expectEquals(). 2014-12-29 11:21:19 -08:00
Howard Hinnant
eafa6f960f API for improved Unit Testing (RIPD-432):
* Added new test APIs allowing easy ways to create ledgers, apply
  transactions to them, close and advance them.

* Moved Ledger tests from Ledger.cpp to Ledger.test.cpp.

* Changed several TransactionEngine log priorities from lsINFO to lsDEBUG to
  reduce unnecessary verbosity in the log messages while running these tests.

* Moved LedgerConsensus:applyTransactions from a private member function to a
  free function so that it could be accessed externally, and without having to
  reference a LedgerConsensus object.  This was done to facilitate the new
  testing API.
2014-12-29 11:21:19 -08:00
Yana
c62ccf4870 Update README.md (RIPD-601) 2014-12-29 11:21:19 -08:00
Vinnie Falco
ef34439a79 Set version to 0.26.5-rc1 2014-12-22 15:20:03 -08:00
Nik Bougalis
b328ec2462 Prevent passing of non-POD types to POD-only interfaces:
This tidies up the code that produces random numbers to conform
to programming best practices and reduce dependencies.

* Use std::random_device instead of platform-specific code
* Remove RandomNumbers class and use free functions instead
2014-12-22 15:19:48 -08:00
Vinnie Falco
60f27178b8 Levelization, improve structure of source files:
Source files are moved between modules, includes changed and added,
and some code rewritten, with the goal of reducing cross-module dependencies
and eliminating cycles in the dependency graph of classes.

* Remove RippleAddress dependency in CKey_test
* ByteOrder.h, Blob.h, and strHex.h are moved to basics/. This makes
  the basics/ module fully independent of other ripple sources.
* types/ is merged into protocol/. The protocol module now contains
  all primitive types specific to the Ripple protocol.
* Move ErrorCodes to protocol/
* Move base_uint to basics/
* Move Base58 to crypto/
* Remove dependence on Serializer in GenerateDeterministicKey
* Eliminate unity header json.h
* Remove obsolete unity headers
* Remove unnecessary includes
2014-12-22 10:23:49 -08:00
Vinnie Falco
e3fbb83ad0 Tidy up usage of std::begin, std::end 2014-12-19 11:55:43 -08:00
Nik Bougalis
28b70a7b9a Remove 'Proof of Work' code 2014-12-19 11:00:29 -08:00
Nicholas Dudfield
dcdc341d0f Add appveyor 2014-12-19 11:00:29 -08:00
Tom Ritchford
fce77c9372 Configuration for yielding RPC server. 2014-12-19 11:00:28 -08:00
Tom Ritchford
a360c481c2 Refactor out a version of lookupLedger returning Status. 2014-12-19 11:00:28 -08:00
Tom Ritchford
c72db5fa5f Refactor away RPCHandler::doRpcCommand 2014-12-19 11:00:28 -08:00
Tom Ritchford
fc9a23d6d4 Send output incrementally in ServerHandlerImp. 2014-12-19 11:00:27 -08:00
Tom Ritchford
167f4666e2 New generic Ledger RPC handler. 2014-12-19 11:00:27 -08:00
Tom Ritchford
1cbcc7be21 Allow the Ledger to generically output to both Json models. 2014-12-19 11:00:27 -08:00
Tom Ritchford
8053598069 Better interoperation between Json::Value and JsonObject.
* Generic functions to add entries to both object models.
* Add Json::Value into JsonObjects.
* Write Json::Value to string incrementally.
* Get rid of ripple::RPC::New namespace
2014-12-19 11:00:26 -08:00
Tom Ritchford
7cfac1a91a Wrap Output in a coroutine that periodically yields. 2014-12-19 11:00:26 -08:00
Tom Ritchford
192cdd028e Change Output to be a generic std::function. 2014-12-19 11:00:26 -08:00
Tom Ritchford
029c143922 Add a comment to ledger/Ledger.h. 2014-12-19 11:00:26 -08:00
Tom Ritchford
00298cc68c Simplify LedgerData.cpp. 2014-12-19 11:00:25 -08:00
Tom Ritchford
d9c7db51af Make three ErrorCode functions generic. 2014-12-19 11:00:25 -08:00
Vinnie Falco
f12b15d22b Fix logic in HTTP/S server:
These bugs do not affect production code since callers do not invoke
`write` multiple times, but these would become a problem in the future.

* Access to Peer::write_queue_ is synchronized correctly.
* Remove unsafe access to deleted container element.
2014-12-19 11:00:25 -08:00
Vinnie Falco
409b8bac00 Remove unused and obsolete Ripple identifiers and tidy up:
These identifiers were part of a failed set of classes to replace
the functionality combined into RippleAddress. They are not used
and therefore can be removed.

* Remove RippleAccountPrivateKey
* Remove RippleAccountPublicKey
* Remove RippleAccountID
* Remove RipplePrivateKey
* Remove RipplePublicKeyHash
* Remove RippleLedgerHash
* Remove unused withCheck argument
* Remove CryptoIdentifier
* Remove IdentifierStorage
* Remove IdentifierType
* Remove SimpleIdentifier
* Add missing include
2014-12-19 11:00:24 -08:00
Vinnie Falco
28b09bde4b Simplify RipplePublicKey:
This implements the bare minimum necessary to store a 33 byte public
key and use it in ordered containers. It is an efficient and well
defined alternative to RippleAddress when the caller only needs
a node public key.
2014-12-19 11:00:24 -08:00
Vinnie Falco
2f6af906f4 Validators work (RIPD-703):
This replaces the experimental validators module with foundational
code to implement a new system for tracking validators, validations and
the UNL. The code is turned off by default, in BeastConfig.h

* Remove obsolete public Manager interfaces
* Remove obsolete database methods
* Remove obsolete ChosenList concept
* Remove obsolete code
* Add missing includes
* Tidy up STValidation.h
* Move factory function to Validators::make_Manager
* Add Connection object for tracking STValidations
2014-12-19 11:00:23 -08:00
Vinnie Falco
628e3ac1eb Add waitable_executor 2014-12-18 10:26:55 -08:00
Josh Juran
fbf5785e35 Combine STTx::checkSign overloads:
Callers don't need to specify the signing key -- they're just retrieving
the key from the SerializedTransaction and then passing it back.

This simplifies Ed25519 implementation.
2014-12-12 20:14:02 -08:00
Nicholas Dudfield
eeea2b1ff8 Use ppa:afrank/boost 1.57 for Travis 2014-12-12 20:14:02 -08:00
Vinnie Falco
32062e439f Split peer connect logic to another class (RIPD-711):
All of the logic for establishing an outbound peer connection including
the initial HTTP handshake exchange is moved into a separate class. This
allows PeerImp to have a strong invariant: All PeerImp objects that exist
represent active peer connections that have already gone through the
handshake process.
2014-12-12 20:14:02 -08:00
Vinnie Falco
930a0beaf1 Add ZeroCopyOutputStream and tidy up 2014-12-12 20:14:02 -08:00
Nik Bougalis
4a49fefdd9 Various cleanups:
* Replace SYSTEM_NAME and other macros with C++ constructs
* Remove RIPPLE_ARRAYSIZE and use std::extent or ranged for loops
* Remove old-style, unused offer crossing unit test
* Make STAmount::saFromRate free and remove default argument
2014-12-12 20:14:02 -08:00
Nik Bougalis
8e792855e0 Do not use path if path expansion fails 2014-12-10 16:55:06 -08:00
Tom Ritchford
69f5c6987a Whitespace: clean WebSockets to 80 columns. 2014-12-10 16:55:06 -08:00
Nik Bougalis
85fc9e4ecf Revert e4c9822d78 "Enable processor-specific optimizations when available:" 2014-12-08 14:54:03 -08:00
Mark Travis
d5c3f0c9cf Stability bugfixes for online delete SHAMapStore:
The correct ledger age is necessary for checking health
status, and the previous behavior caused the online deletion process to
abort if the process took too long.

The tuning parameter added and the parameter whose default was modified both
minimize impact of SQL DELETE operations by decreasing the default batch size
for deletes and for increasing the backoff period between deletion batches.
These parameters decrease contention for the SQLite and I/O with the trade-off
of longer processing time for online delete. Online-delete is not a
time-critical function, so a little slowness in wall-clock time is not harmful.
2014-12-08 14:54:03 -08:00
JoelKatz
a48120e675 Fix incorrect source issuer for XRP source 2014-12-08 14:54:03 -08:00
Nik Bougalis
36f8e4f2ad Improve hex conversion & parsing routines 2014-12-08 14:54:03 -08:00
David Schwartz
1084a39a45 Improve the humanAccountID cache (RIPD-693)
Profiling indicated some performance issues coming from the
cache of 160-bit account IDs to base58 format. This replaces
the single cache with two caches and rotates out old
entries.
2014-12-08 14:54:03 -08:00
Tom Ritchford
86df482842 Make sure that handlers always return Json::objectValue. 2014-12-01 17:16:24 -05:00
Tom Ritchford
b0d47ebcc6 Use better base64 handling in ServerHandlerImp. 2014-12-01 17:15:23 -05:00
Tom Ritchford
fffdf1dfba Make beast::detail::chunk_encoded_buffers::to_hex() static 2014-12-01 11:12:59 -05:00
Tom Ritchford
3273ed2616 Remove unused BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES. 2014-12-01 10:56:03 -05:00
Vinnie Falco
aa7b0a31b0 Refactor protocol message parsing:
This replaces the stateful class parser with a stateless free function.
The protocol buffer message is parsed using a ZeroCopyInputStream.

* Invoke method is now a free function.
* Protocol handler doesn't need to derive from an abstract interface
* Only up to one message is processed at a time by the invoker.
* Remove error_code return from the handler's message processing functions.
* Add ZeroCopyInputStream implementation that wraps a BufferSequence.
* Free function parses up to one protocol message and calls the handler.
* Message type and size can be calculated from an iterator
  range or a buffer sequence.
2014-11-26 12:23:21 -08:00
Vinnie Falco
fb0d44d403 Use cluster state in Slot instead of PeerImp 2014-11-26 12:23:10 -08:00
Vinnie Falco
cd8ec89cbb Use injections from OverlayImpl in PeerImp 2014-11-26 12:23:02 -08:00
Vinnie Falco
252f271dc5 Fixes to beast::asio::streambuf:
* Fix to_string conversion
* Fix assert on debug invariant checks
* Fix the treatment of the output position when the entire output is committed.
* Add unit test
2014-11-26 12:22:55 -08:00
Vinnie Falco
62d400c3a9 Move the call to cancel_timer to the right place 2014-11-26 12:22:46 -08:00
Scott Schurr
f9aa3e0da5 Add more unit tests to rpc/impl/TransactionSign (RIPD-480):
By adding a mock it is possible to test the transactionSign
function without interacting with the ledger.  This is the
smallest change I could come up with that allows transactionSign
to be unit tested.

The unit tests are white boxed.  Each test case is a result
of examining the code and identifying behavior associated with
different JSON fields.  That means the tests are not based on
requirements, they are based on observed behavior.
2014-11-26 12:07:44 -08:00
Vinnie Falco
685fe5b0fb Don't call std::exit on clean exit 2014-11-25 19:19:56 -08:00
Vinnie Falco
5180e71a0d Remove unused chrono::time_point stream conversions 2014-11-25 19:19:56 -08:00
Vinnie Falco
55637f7508 Template abstract_clock on Clock:
The abstract_clock is now templated on a type meeting the requirements of
the Clock concept. It inherits the nested types of the Clock on which it
is based. This resolves a problem with the original design which broke the
type-safety of time_point from different abstract clocks.
2014-11-25 19:19:56 -08:00
Nicholas Dudfield
7d72dfe0be Updated freeze tests:
* Always run freeze tests (and  enforcement tests)
* book_offers filtering tests are broken
2014-11-25 11:46:34 -08:00
Mark Travis
02529a0fc2 SHAMapStore Online Delete (RIPD-415):
Makes rippled configurable to support deletion of all data in its key-value
store (nodestore) and ledger and transaction SQLite databases based on
validated ledger sequence numbers. All records from a specified ledger
and forward shall remain available in the key-value store and SQLite, and
all data prior to that specific ledger may be deleted.

Additionally, the administrator may require that an RPC command be
executed to enable deletion. This is to align data deletion with local
policy.
2014-11-25 11:44:02 -08:00
JoelKatz
b44974677e Cleanup some stray formatting left in logs 2014-11-21 17:13:13 -08:00
Vinnie Falco
d4fd5e4fce HTTP Handshaking for Peers on Universal Port (RIPD-446):
This introduces a considerable change in the way that peers handshake. Instead
of sending the TMHello protocol message, the peer making the connection (client
role) sends an HTTP Upgrade request along with some special headers. The peer
acting in the server role sends an HTTP response completing the upgrade and
transition to RTXP (Ripple Transaction Protocol, a.k.a. peer protocol). If the
server has no available slots, then it sends a 503 Service Unavailable HTTP
response with a JSON content-body containing IP addresses of other servers to
try. The information that was previously contained in the TMHello message is
now communicated in the HTTP request and HTTP response including the secure
cookie to prevent man in the middle attacks. This information is documented
in the overlay README.md file.

To prevent disruption on the network, the handshake feature is rolled out in
two parts. This is part 1, where new servents acting in the client role will
send the old style TMHello handshake, and new servents acting in the server
role can automatically detect and accept both the old style TMHello handshake,
or the HTTP request accordingly. This detection happens in the Server module,
which supports the universal port. An experimental .cfg setting allows clients
to instead send HTTP handshakes when establishing peer connections. When this
code has reached a significant fraction of the network, these clients will be
able to establish a connection to the Ripple network using HTTP handshakes.

These changes clean up the handling of the socket for peers. It fixes a long
standing bug in the graceful close sequence, where remaining data such as the
IP addresses of other servers to try, did not get sent. Redundant state
variables for the peer are removed and the treatment of completion handlers is
streamlined. The treatment of SSL short reads and secure shutdown is also fixed.

Logging for the peers in the overlay module are divided into two partitions:
"Peer" and "Protocol". The Peer partition records activity taking place on the
socket while the Protocol partition informs about RTXP specific actions such as
transaction relay, fetch packs, and consensus rounds. The severity on the log
partitions may be adjusted independently to diagnose problems. Every log
message for peers is prefixed with a small, unique integer id in brackets,
to accurately associate log messages with peers.

HTTP handshaking is the first step in implementing the Hub and Spoke feature,
which transforms the network from a homogeneous network where all peers are
the same, into a structured network where peers with above average capabilities
in their ability to process ledgers and transactions self-assemble to form a
backbone of high powered machines which in turn serve a much larger number of
'leaves' with lower capacities with a goal to improve the number of
transactions that may be retired over time.
2014-11-21 16:47:12 -08:00
Vinnie Falco
30123eaa4a Add WrappedSink:
This class puts a configured string prefix in front of
each line of Journal output.
2014-11-21 16:46:57 -08:00
Nik Bougalis
454ec97d51 Replace custom exceptions with std::runtime_error 2014-11-21 13:15:41 -08:00
Vinnie Falco
c2ac331e78 Fix unit_test suite matching with full names 2014-11-21 12:59:32 -08:00
Nik Bougalis
be4a35af11 Clarify SetAccount logic and clean up existing code 2014-11-21 12:59:32 -08:00
Tom Ritchford
445b29ad0d Fix RPC handlers to use the results of lookupLedger. 2014-11-21 12:59:32 -08:00
Vinnie Falco
64d0f7fffd Fix DecayingSample treatment of the window 2014-11-21 12:59:32 -08:00
Nik Bougalis
baf0d09455 Simplify the Beast fatal error reporting framework:
* Reduce interface to a single function which reports error details
* Remove unused functions
2014-11-21 12:59:32 -08:00
Vinnie Falco
08a81a0ab9 Tidy up the structure of sources in protocol/:
Split out and rename STValidation
Split out and rename STBlob
Split out and rename STAccount
Split out STPathSet
Split STVector256 and move UintTypes to protocol/
Rename to STBase
Rename to STLedgerEntry
Rename to SOTemplate
Rename to STTx
Remove obsolete AgedHistory
Remove types.h and add missing includes
Remove unnecessary includes in app.h
Remove unnecessary includes in app.h
Remove include app.h from app1.cpp
2014-11-20 20:15:29 -08:00
Nik Bougalis
31110c7fd9 Cleanup ripple::Ledger:
* Convert static member functions to free functions
* Adopt consistent naming convention
* De-inline code
2014-11-20 20:15:29 -08:00
Vinnie Falco
0e1dd92d9b Fix case where slot==nullptr in Overlay:
This changes the Overlay to correctly handle the case when nullptr is
returned by PeerFinder new_inbound_slot on a detected self-connection.
2014-11-20 20:15:29 -08:00
Vinnie Falco
a3204a4df7 Add http::chunk_encode:
This transforms a ConstBufferSequence into a new ConstBufferSequence whose
data is encoded according to the Content transfer encoding rules of RFC2616.
The implementation does not copy any memory.
2014-11-20 20:15:29 -08:00
Donovan Hide
2288ab48b9 Use asio signal handling in Application (RIPD-140):
* Use signal_set as cross platform way of handling SIGINT
* Remove polling on main thread for shutdown.
* Add extra logging for received signal.
* Clean up exit handling on error in setup routines.
* Reuse isStopped() from Stoppable for status (could be isStopping() instead).
* Ctrl-C should now work for standalone mode as well on Windows.

Also small fixes to Resolver:
* Add Resolver prefix to logging.
* Fix AsyncObject::removeReference() logic.
* Fix work remaining logic.
2014-11-20 20:15:29 -08:00
mDuo13
670401884c Improve the human-readable description of the tesSUCCESS code:
Transactions that return tesSUCCESS have only been accepted and
propagated on the Ripple network and should not be considered
final until they have been included in a validated ledger.
2014-11-20 20:14:04 -08:00
Yana
37181c341e Changed doc/rippled-example.cfg to specify default for ssl_verify 2014-11-14 11:19:42 -08:00
wltsmrz
be7e677448 Update integration tests for changes to ripple-lib account request API:
Account requests expect an object as first argument
2014-11-14 11:10:12 -08:00
Josh Juran
b2eeb49a45 Clean up CKey and RippleAddress (RIPD-672)
* Remove CKey dependency on RippleAddress
* Create RAII ec_key wrapper that hides EC_KEY and other OpenSSL details
* Move CKey member logic into free functions
* Delete CKey class
* Rename units that are no longer CKey-related
* Delete code that was unused
2014-11-14 11:10:12 -08:00
Vinnie Falco
9aa040d917 Accept generic arguments in ci_equal 2014-11-14 11:10:11 -08:00
Vinnie Falco
c2043a223b Tidy up split_commas function and use it in Server
Conflicts:
	src/ripple/server/impl/ServerHandlerImp.cpp
2014-11-14 11:10:11 -08:00
Vinnie Falco
f24e859f17 Construct Server after Overlay and WSDoors:
When the ServerHandler is constructed before the Overlay, an incoming
connection received after the server's listening ports have been opened
but before the Overlay object has been created causes a crash.
2014-11-14 11:10:11 -08:00
Vinnie Falco
737b33f9d1 Merge branch 'release' into develop 2014-11-14 10:56:45 -08:00
David Schwartz
00791d2151 Set version to 0.26.4-sp3 2014-11-11 16:33:52 -08:00
David Schwartz
b141598f9b Fix bugs in pathfinding with XRP as the source currency 2014-11-11 16:27:39 -08:00
Tom Ritchford
d1618d79b0 Fix pathfinding with multiple issuers for one currency (RIPD-618).
* Allow pathfinding requests where the starting currency may have
  multiple issuers.

* Cache paths over all issuers to avoid repeating work.

* Clear the ledger checkpoint in one retry case.

* Add an additional node at the front of paths when the starting issuer
  is not the source account.
2014-11-11 16:27:03 -08:00
Tom Ritchford
00c84dfe5c Clean up Pathfinder.
* Restrict to 80-columns and other style cleanups.
* Make pathfinding a free function and hide the class Pathfinder.
* Split off unrelated utility functions into separate files.
2014-11-11 16:26:38 -08:00
Tom Ritchford
0829ee9234 Add missing header needed for boost 1.57 compatibility. 2014-11-10 23:23:53 -05:00
Nik Bougalis
b22e33444b Make Stoppable unit tests manual 2014-11-10 23:23:53 -05:00
David Schwartz
d115a12cbe Remove dead TxQueue code 2014-11-10 23:23:53 -05:00
Nik Bougalis
b7b744de94 Remove sole use of beast::MurmurHash 2014-11-10 15:00:20 -08:00
Nik Bougalis
68e46e406a Remove MurmurHash from Beast 2014-11-10 14:00:54 -08:00
Tom Ritchford
329a969761 Remove unused RPCServer. 2014-11-10 12:53:21 -08:00
Vinnie Falco
30170bc394 Add short_read manual unit test:
This manual unit test explores the outcomes of shutting down
SSL stream connections at various point during a session.
2014-11-10 12:52:57 -08:00
Vinnie Falco
f193302e15 Add WrappedSink 2014-11-10 12:52:57 -08:00
Vinnie Falco
7c4870d641 Add operator<< for basic_streambuf 2014-11-10 12:52:43 -08:00
Vinnie Falco
8b84a76d5d Make ci_equal a function 2014-11-10 12:52:42 -08:00
Vinnie Falco
a4cd761372 Add rfc2616::parse_csv 2014-11-10 12:52:42 -08:00
Miguel Portilla
63d2cfd6ba Fix account_lines, account_offers and book_offers result (RIPD-682):
The RPC account_lines and account_offers commands respond with the correct
ledger info. account_offers, account_lines and book_offers allow admins
unlimited size on the limit param. Specifying a negative value on limit clamps
to the minimum value allowed. Incorrect types for limit are correctly reported
in the result.
2014-11-10 12:46:36 -08:00
Vinnie Falco
fbffe2367e Fix weak_fn unit test. 2014-11-09 20:27:05 -08:00
Vinnie Falco
e442a2846d Overlay improvements and bug fixes:
PeerImp::detach had a default argument graceful=true which did not
correctly close the socket and cause the Overlay to often hang on exit.
The logging for Overlay and Peers has been reworked. All the socket activity
is logged to Peers while protocol activity goes to Protocol. Every log line
is prefixed by a small integer ID unique to the connection.
* Removed graceful PeerImp::detach option
* Peer and Protocol log message handle respective types of logging
* Log messages prefixed with peer unique integer
* Prevent call to timer ancel from throwing an exception
2014-11-08 14:39:46 -08:00
Vinnie Falco
f6985586ea Better logging when opening Server ports. 2014-11-08 14:36:45 -08:00
Vinnie Falco
2bae5b0959 Throw if rippled.cfg is missing a [server] section 2014-11-08 14:36:45 -08:00
Vinnie Falco
1e58809fcc Remove obsolete get_pointer 2014-11-08 14:36:44 -08:00
Vinnie Falco
6b1d213cc2 Add weak_fn 2014-11-08 14:36:44 -08:00
David Schwartz
42bec13a83 Add missing include needed for std::bad_cast in LexicalCast.h 2014-11-07 15:23:43 -08:00
Vinnie Falco
4415a179b3 Update freeze test for moved TxFlags.h 2014-11-07 14:12:43 -08:00
Vinnie Falco
5d42604efd Refactor the structure of source files:
* New src/ripple/crypto and src/ripple/protocol directories
* Merged src/ripple/common into src/ripple/basics
* Move resource/api files up a level
* Add headers for "include what you use"
* Normalized include guards
* Renamed to JsonFields.h
* Remove obsolete files
* Remove net.h unity header
* Remove resource.h unity header
* Removed some deprecated unity includes
2014-11-07 13:40:43 -08:00
Vinnie Falco
b134b7d3f6 Add missing includes. 2014-11-07 12:24:02 -08:00
Vinnie Falco
788219fe05 Adjust SSL context generation for Server:
The creation of self-signed certificates slows down the command
line client when launched repeatedly during unit test.
* Contexts are no longer generated for the command line client
* A port with no secure protocols generates an empty context
2014-11-07 06:13:56 -08:00
Tom Ritchford
9a7f66cfe9 Fix compilation errors in RPC/RipplePathFind.cpp 2014-11-06 21:58:13 -05:00
Tom Ritchford
daa4d16e61 Remove unused isXRP(Issue) function. 2014-11-06 20:17:13 -05:00
Tom Ritchford
cf05f87795 Fix pathfinding with multiple issuers for one currency (RIPD-618).
* Allow pathfinding requests where the starting currency may have
  multiple issuers.

* Cache paths over all issuers to avoid repeating work.

* Clear the ledger checkpoint in one retry case.

* Add an additional node at the front of paths when the starting issuer
  is not the source account.
2014-11-06 20:14:01 -05:00
Tom Ritchford
c2f2f83b7c Clean up Pathfinder.
* Restrict to 80-columns and other style cleanups.
* Make pathfinding a free function and hide the class Pathfinder.
* Split off unrelated utility functions into separate files.

Conflicts:
	src/ripple/rpc/handlers/RipplePathFind.cpp
2014-11-06 16:58:10 -08:00
Tom Ritchford
b30b2a523f Fix public member names of RPC::Context.
Conflicts:
	src/ripple/rpc/handlers/AccountTx.cpp
	src/ripple/rpc/handlers/AccountTxOld.cpp
	src/ripple/rpc/handlers/Ledger.cpp
	src/ripple/rpc/handlers/LedgerData.cpp
	src/ripple/rpc/handlers/RipplePathFind.cpp
	src/ripple/rpc/handlers/ServerInfo.cpp
	src/ripple/rpc/handlers/ServerState.cpp
	src/ripple/rpc/handlers/Submit.cpp
	src/ripple/rpc/handlers/Subscribe.cpp
	src/ripple/rpc/handlers/TxHistory.cpp
	src/ripple/rpc/handlers/Unsubscribe.cpp
	src/ripple/rpc/impl/Context.h
2014-11-06 16:55:20 -08:00
Nicholas Dudfield
150a3810a8 Update npm test rippled.cfg to use [server]:
The test now generates a configuration file with the new
configuration sections define by the Universal Port feature.
2014-11-06 16:10:00 -08:00
Vinnie Falco
ac0eaa912b Universal Port (RIPD-160):
This changes the behavior and configuration specification of the listening
ports that rippled uses to accept incoming connections for the supported
protocols: peer (Peer Protocol), http (JSON-RPC over HTTP), https (JSON-RPC)
over HTTPS, ws (Websockets Clients), and wss (Secure Websockets Clients).
Each listening port is now capable of handshaking in multiple protocols
specified in the configuration file (subject to some restrictions). Each
port can be configured to provide its own SSL certificate, or to use a
self-signed certificate. Ports can be configured to share settings, this
allows multiple ports to use the same certificate or values. The list of
ports is dynamic, administrators can open as few or as many ports as they
like. Authentication settings such as user/password or admin user/admin
password (for administrative commands on RPC or Websockets interfaces) can
also be specified per-port.

As the configuration file has changed significantly, administrators will
need to update their ripple.cfg files and carefully review the documentation
and new settings.

Changes:

* rippled-example.cfg updated with documentation and new example settings:
  All obsolete websocket, rpc, and peer configuration sections have been
  removed, the documentation updated, and a new documented set of example
  settings added.

* HTTP::Writer abstraction for sending HTTP server requests and responses
* HTTP::Handler handler improvements to support Universal Port
* HTTP::Handler handler supports legacy Peer protocol handshakes
* HTTP::Port uses shared_ptr<boost::asio::ssl::context>
* HTTP::PeerImp and Overlay use ssl_bundle to support Universal Port
* New JsonWriter to stream message and body through HTTP server
* ServerHandler refactored to support Universal Port and legacy peers
* ServerHandler Setup struct updated for Universal Port
* Refactor some PeerFinder members
* WSDoor and Websocket code stores and uses the HTTP::Port configuration
* Websocket autotls class receives the current secure/plain SSL setting
* Remove PeerDoor and obsolete Overlay peer accept code
* Remove obsolete RPCDoor and synchronous RPC handling code
* Remove other obsolete classes, types, and files
* Command line tool uses ServerHandler Setup for port and authorization info
* Fix handling of admin_user, admin_password in administrative commands
* Fix adminRole to check credentials for Universal Port
* Updated Overlay README.md

* Overlay sends IP:port redirects on HTTP Upgrade peer connection requests:
  Incoming peers who handshake using the HTTP Upgrade mechanism don't get
  a slot, and always get HTTP Status 503 redirect containing a JSON
  content-body with a set of alternate IP and port addresses to try, learned
  from PeerFinder. A future commit related to the Hub and Spoke feature will
  change the response to grant the peer a slot when there are peer slots
  available.

* HTTP responses to outgoing Peer connect requests parse redirect IP:ports:
  When the [overlay] configuration section (which is experimental) has
  http_handshake = 1, HTTP redirect responses will have the JSON content-body
  parsed to obtain the redirect IP:port addresses.

* Use a single io_service for HTTP::Server and Overlay:
  This is necessary to allow HTTP::Server to pass sockets to and from Overlay
  and eventually Websockets. Unfortunately Websockets is not so easily changed
  to use an externally provided io_service. This will be addressed in a future
  commit, and is one step necessary ease the restriction on ports configured
  to offer Websocket protocols in the .cfg file.
2014-11-06 16:10:00 -08:00
Vinnie Falco
e37d4043f6 Add missing includes to make headers compile separately 2014-11-03 16:40:57 -08:00
Vinnie Falco
d073425b44 Improved beast::http::message:
* Add headers::erase
* Set http::message version with std::pair
* Use std::pair for headers::value_type
2014-11-03 16:40:57 -08:00
Nicholas Dudfield
825b18cf71 Add bin/stop-test.js shutdown testing script:
This script launches rippled repeatedly and then issues a stop command
after a variable amount of time. This is to test the shutdown of the
application and catch errors.
2014-11-03 16:31:21 -08:00
Vinnie Falco
549ad3204f Fix race conditions closing HTTP I/O objects:
This fixes a case where stop can sometimes skip calling close on some
I/O objects or crash in a rare circumstance where a connection is in the
process of being torn down at the exact time the server is stopped. When
the acceptor receives errors, it logs the error and continues listening
instead of stopping.
2014-11-03 14:11:06 -08:00
Vinnie Falco
35f9499b67 Fix Overlay stop on exit:
The stop sequence for Overlay had a race condition where autoconnect could
be called after close_all, resulting in a hang on exit. This resolves the
problem by putting the close and timer operations on a strand:
* Rename some Overlay members
* Put close on strand and tidy up members
* Use completion handler instead of coroutine for timer
* Use App io_service in PeerFinder
2014-11-03 14:11:05 -08:00
Vinnie Falco
db82c35c17 Remove spurious assert in ResolverAsioImpl 2014-11-03 14:11:05 -08:00
Vinnie Falco
73c74f753c Change to the Application io_service:
* Simplified the implementation and removed class IoServicePool
* The io_service outlives the components of the Application
2014-11-03 14:11:05 -08:00
JoelKatz
a38fb2a5dc Clear the acquiring ledger when shutting down NetworkOPs:
This solves a circular destruction problem on exit.
2014-11-03 14:11:04 -08:00
Donovan Hide
38e99e01f9 Improve nodestore benchmarking:
* Use more succinct while loops on NodeFactory.
* Better formatting of multiple test results.
* Updated benchmarks.
* Use simpler and faster RNG to generate test data.
2014-11-02 07:16:08 -08:00
Donovan Hide
a1f46e84b8 Add new RocksDBQuickFactory for benchmarking:
This new factory is intended for benchmarking against the existing RocksDBFactory and has the following differences.
* Does not use BatchWriter
* Disables WAL for writes to memtable
* Uses a hash index in blocks
* Uses RocksDB OptimizeFor… functions
See Benchmarks.md for further discussion of some of the issues raised by investigation of RocksDB performance.
2014-11-01 07:12:09 -07:00
Donovan Hide
6540804571 Add repeatable NodeStore timing benchmark:
The timing test is changed to overcome possible file buffer cache effects by creating different read access patterns. The unittest-arg command line arguments allow running the benchmarks against any of the available backends and altering the parameters passed in the same format as rippled.cfg. The num_objects parameter permits variation of the number of key/values inserted. The data is random but matches reasonably well the values that rippled might generate.
2014-11-01 07:12:08 -07:00
Howard Hinnant
ffe6707595 Refactor Stoppable:
The Stoppable interface aids in the enforcement of invariants needed to
successful start and stop a multi-threaded application composed of classes
that depend on each other in complex ways.
* Test written to confirm the current behavior.
* Comments updated to reflect the current behavior.
* Public API reduced to what is currently in use.
* Protected data members made private.
* volatile bool members changed to std::atomic<bool>.
* std::atomic<int> members changed to std::atomic<bool>.
* Name storage uses std::string
2014-10-31 21:29:16 -07:00
Tom Ritchford
9b21740c9f Delete temporary directories at the end of tests (RIPD-460). 2014-10-31 21:21:54 -07:00
Tom Ritchford
bd12e2ab95 New class TempDirectory in UnitTestUtilities. 2014-10-31 21:21:54 -07:00
Donovan Hide
bffb5ef8b4 Avoid zero initialization of Blob:
This seemed to improve the performance of the copy, although there did seem to be some byte by byte copying still present. Further investigation recommended.
2014-10-31 20:12:39 -07:00
Donovan Hide
e4c9822d78 Enable processor-specific optimizations when available:
The SConstruct is modified to enable processor specific optimizations on clang and gcc toolchains. This improves the performance of RocksDB's CRC function. It might also enable other used libraries that are in the codebase now or in the future to apply cpu-specific optimisations. The mtune option ensures that a binary compiled on one machine will function on another,
2014-10-31 20:12:39 -07:00
Vinnie Falco
73187d8832 Remove obsolete multitls and proxy websocket features 2014-10-31 15:15:40 -07:00
Vinnie Falco
8101154d5e Remove obsolete websocket PROXY port 2014-10-31 15:15:40 -07:00
Vinnie Falco
c02937fd6f Remove obsolete sections from rippled-example.cfg:
* peer_port_proxy is obsolete since the MultiSocket was removed.
* peer_ssl_cipher_list has no effect, SSL ciphers are hard coded for security.
2014-10-31 15:15:40 -07:00
Vinnie Falco
3430be4075 Add PeerFinder onRedirects function 2014-10-31 13:27:55 -07:00
Vinnie Falco
3f2b6f771f Add streambuf to_string function 2014-10-31 13:27:38 -07:00
Vinnie Falco
6e39b49cc2 Add Json::stream to write Value to a Streambuf 2014-10-31 13:27:33 -07:00
Vinnie Falco
71c34ed4e0 Remove unused ErrorReply function 2014-10-31 13:25:54 -07:00
Vinnie Falco
477178675c Fix parseIniFile for duplicate sections 2014-10-31 13:25:30 -07:00
Vinnie Falco
dbdf68b248 Refactor HTTP::Server to support Universal Port:
These changes are necessary to support the Universal port feature. Synopsis:

* Persist HTTP peer io_service::work lifetime:
This simplification eliminates any potential for bugs caused by incorrect
lifetime management of the io_service::work object.

* Restructure Door to prevent data races, and handle clean exit:
The Server, Door, Door::detector, and Peer objects work together to
correctly implement graceful stop and destructors that block until
all child objects have been destroyed.

Cleanups:
* De-pimpl HTTP::Server
* Rename ServerImpl data members
* Tidy up HTTP::Port interface
2014-10-30 16:02:19 -07:00
Vinnie Falco
2fd139b307 Refactor Overlay and add [overlay] config section (experimental):
These changes prepare Overlay for the Universal Port and Hub and Spoke
features.

* Add [overlay configuration section:
The [overlay] section uses the new BasicConfig interface that
supports key-value pairs in the section. Some exposition is added to the
example cfg file. The new settings for overlay are related to the Hub and
Spoke feature which is currently in development. Production servers should
not set these configuration options, they are clearly marked experimental
in the example cfg file.

Other changes:
* Use _MSC_VER to detect Visual Studio
* Use ssl_bundle in Overlay::Peer
* Use shared_ptr to SSL context in Overlay:
* Removed undocumented PEER_SSL_CIPHER_LIST configuration setting
* Add Section::name: The Section object now stores its name for better diagnostic messages.
2014-10-30 13:55:01 -07:00
Vinnie Falco
a6c2657062 Add shared_ptr<boost::asio::ssl::context> to ssl_bundle:
This gives the ssl_bundle shared ownership of the underlying ssl context
so that ownership of the bundle may be transferred to other classes without
introduce lifetime issues.
2014-10-30 13:55:00 -07:00
Vinnie Falco
78a0bc0e2c Make streambuf buffers_type iterators default constructible 2014-10-30 13:55:00 -07:00
Edward Hennis
d7116d6867 Enable std::array overloads for boost::asio on clang:
* Remove Boost config option from beast config.
* Define from compiler, or let Boost figure out itself.
2014-10-30 13:55:00 -07:00
Josh Juran
edc15b9fa2 Use a self-signed certificate for peers (RIPD-108):
Generate a new RSA key pair and a self-signed X.509v3 certificate to use
with SSL connections to rippled peers.  New credentials are created each
startup.
2014-10-30 13:54:49 -07:00
Josh Juran
93d4b73b2f RippleSSLContext: Add openssl wrappers 2014-10-30 10:52:37 -07:00
Vinnie Falco
8e3849e591 Create Ripple SSL contexts using std::make_shared. 2014-10-30 10:52:36 -07:00
Vinnie Falco
acaa1098f7 Separate beast::http::body from beast::http::message (RIPD-660):
This changes the http::message object to no longer contain a body. It modifies
the parser to store the body in a separate object, or to pass the body data
to a functor. This allows the body to be stored in more flexible ways. For
example, in HTTP responses the body can be generated procedurally instead
of being required to exist entirely in memory at once.
2014-10-29 19:23:53 -07:00
Vinnie Falco
c1a5e88752 Use beast::asio::streambuf in Overlay 2014-10-29 19:23:53 -07:00
Vinnie Falco
74b99014d2 Add beast::asio::basic_streambuf (RIPD-661):
This is class whose interface is identical to the boost::asio::basic_streambuf,
and uses an implementation that stores the data in multiple discontiguous
linear buffers, expanding and shrinking as needed.
2014-10-29 19:23:53 -07:00
Tom Ritchford
9cba944d21 Add Json::to_string:
This allows the declaration for FastWriter to be hidden and makes
conversion of Json::Value objects to strings a little less clunky.
2014-10-29 19:23:52 -07:00
Tom Ritchford
8c1c2f5d05 Eliminate a copy of the string returned by FastWriter 2014-10-29 19:22:44 -07:00
Tom Ritchford
bf0fa8c562 Add 'sample' npm test:
test/sample-test.js is the smallest possible npm test.
2014-10-28 10:59:59 -07:00
Donovan Hide
3e1fc9ba6c Update unit testing command line parser parameters:
A string passed by the '--unittest-arg' command line parameter is passed to
suites when unit tests run and can be used to customize test behavior.
* Add '--unittest-arg' command line argument
* Remove obsolete '--unittest-format' command line argument
2014-10-28 10:55:44 -07:00
Vinnie Falco
4ceba603e4 Improvements to beast::unit_test framework:
* Some runner member functions are now thread-safe.
* De-inline and tidy up declarations and definitions.
* arg() interface allows command lines to be passed to suites.
2014-10-28 10:41:10 -07:00
1456 changed files with 111127 additions and 34151 deletions

View File

@@ -6,20 +6,10 @@ before_install:
- sudo apt-get update -qq
- sudo apt-get install -qq python-software-properties
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
- sudo add-apt-repository -y ppa:boost-latest/ppa
- sudo add-apt-repository -y ppa:afrank/boost
- sudo apt-get update -qq
- sudo apt-get install -qq g++-4.8
- sudo apt-get install -qq libboost1.55-all-dev
# We want debug symbols for boost as we install gdb later
- sudo apt-get install -qq libboost1.55-dbg
- | # Setup the BOOST_ROOT
export BOOST_ROOT=$HOME/boost_root
mkdir -p $BOOST_ROOT/stage
ln -s /usr/lib/x86_64-linux-gnu $BOOST_ROOT/stage/lib
ln -s /usr/include/boost $BOOST_ROOT/boost
- | # Try to patch boost
sudo patch /usr/include/boost/bimap/detail/debug/static_error.hpp Builds/travis/static_error.boost.patch
sudo patch /usr/include/boost/config/compiler/clang.hpp Builds/travis/clang.boost.patch
- sudo apt-get install -qq libboost1.57-all-dev
- sudo apt-get install -qq mlocate
- sudo updatedb
- sudo locate libboost | grep /lib | grep -e ".a$"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Express 2013 for Windows Desktop
VisualStudioVersion = 12.0.30110.0
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RippleD", "RippleD.vcxproj", "{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}"
EndProject
@@ -14,9 +14,11 @@ Global
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}.Debug|Win32.ActiveCfg = debug|x64
{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}.Debug|Win32.Build.0 = debug|x64
{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}.Debug|x64.ActiveCfg = debug|x64
{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}.Debug|x64.Build.0 = debug|x64
{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}.Release|Win32.ActiveCfg = release|x64
{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}.Release|Win32.Build.0 = release|x64
{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}.Release|x64.ActiveCfg = release|x64
{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}.Release|x64.Build.0 = release|x64
EndGlobalSection

View File

@@ -1,5 +1,5 @@
Name: rippled
Version: 0.26.4-sp2
Version: 0.27.2
Release: 1%{?dist}
Summary: Ripple peer-to-peer network daemon
@@ -50,4 +50,3 @@ rm -rf %{buildroot}
/usr/bin/rippled
/usr/share/rippled/LICENSE
/etc/rippled/rippled-example.cfg

View File

@@ -1,3 +1,77 @@
![Ripple](/images/ripple.png)
#The Worlds Fastest and Most Secure Payment System
**What is Ripple?**
Ripple is the open-source, distributed payment protocol that enables instant
payments with low fees, no chargebacks, and currency flexibility (for example
dollars, yen, euros, bitcoins, or even loyalty points). Businesses of any size
can easily build payment solutions such as banking or remittance apps, and
accelerate the movement of money. Ripple enables the world to move value the
way it moves information on the Internet.
![Ripple Network](images/network.png)
**What is a Gateway?**
Ripple works with gateways: independent businesses which hold customer
deposits in various currencies such as U.S. dollars (USD) or Euros (EUR),
in exchange for providing cryptographically-signed issuances that users can
send and trade with one another in seconds on the Ripple network. Within the
protocol, exchanges between multiple currencies can occur atomically without
any central authority to monitor them. Later, customers can withdraw their
Ripple balances from the gateways that created those issuances.
**How do Ripple payments work?**
A sender specifies the amount and currency the recipient should receive and
Ripple automatically converts the senders available currencies using the
distributed order books integrated into the Ripple protocol. Independent third
parties acting as market makers provide liquidity in these order books.
Ripple uses a pathfinding algorithm that considers currency pairs when
converting from the source to the destination currency. This algorithm searches
for a series of currency swaps that gives the user the lowest cost. Since
anyone can participate as a market maker, market forces drive fees to the
lowest practical level.
**What can you do with Ripple?**
The protocol is entirely open-source and the networks shared ledger is public
information, so no central authority prevents anyone from participating.Anyone
can become a market maker, create a wallet or a gateway, or monitor network
behavior. Competition drives down spreads and fees, making the network useful
to everyone.
###Key Protocol Features
1. XRP is Ripples native [cryptocurrency]
(http://en.wikipedia.org/wiki/Cryptocurrency) with a fixed supply that
decreases slowly over time, with no mining. XRP acts as a bridge currency, and
pays for transaction fees that protect the network against spam
![XRP as a bridge currency](/images/vehicle_currency.png)
2. Pathfinding discovers cheap and efficient payment paths through multiple
[order books](https://www.ripplecharts.com) allowing anyone to [trade](https://www.rippletrade.com) anything. When two accounts arent linked by relationships of trust, the Ripple pathfinding engine considers intermediate links and order books to produce a set of possible paths the transaction can take. When the payment is processed, the liquidity along these paths is iteratively consumed in best-first order.
![Pathfinding from Euro to Japanese Yen](/images/pathfinding.png)
3. [Consensus](https://www.youtube.com/watch?v=pj1QVb1vlC0) confirms
transactions in an atomic fashion, without mining, ensuring efficient use of
resources.
[transact]: https://ripple.com/files/ripple-FIs.pdf
[build]: https://ripple.com/build/
[transact.png]: /images/transact.png
[build.png]: /images/build.png
[contribute.png]: /images/contribute.png
###Join The Ripple Community
|![Transact][transact.png]|![Build][build.png]|![Contribute][contribute.png]|
|:-----------------------:|:-----------------:|:---------------------------:|
|[Transact on the fastest payment infrastructure][transact]|[Build Imaginative Apps][build]|Contribute to the Ripple Protocol Implementation|
#rippled - Ripple P2P server
##[![Build Status](https://travis-ci.org/ripple/rippled.png?branch=develop)](https://travis-ci.org/ripple/rippled)
@@ -37,5 +111,9 @@ Ripple is open source and permissively licensed under the ISC license. See the
LICENSE file for more details.
###For more information:
* https://ripple.com
* https://ripple.com/wiki
* Ripple Wiki - https://ripple.com/wiki/
* Ripple Primer - https://ripple.com/ripple_primer.pdf
* Ripple Primer (Market Making) - https://ripple.com/ripple-mm.pdf
* Ripple Gateway Primer - https://ripple.com/ripple-gateways.pdf
* Consensus - https://wiki.ripple.com/Consensus

View File

@@ -11,14 +11,17 @@
all All available variants
debug All available debug variants
release All available release variants
profile All available profile variants
clang All clang variants
clang.debug clang debug variant
clang.release clang release variant
clang.profile clang profile variant
gcc All gcc variants
gcc.debug gcc debug variant
gcc.release gcc release variant
gcc.profile gcc profile variant
msvc All msvc variants
msvc.debug MSVC debug variant
@@ -26,6 +29,13 @@
vcxproj Generate Visual Studio 2013 project file
count Show line count metrics
Any individual target can also have ".nounity" appended for a classic,
non unity build. Example:
scons gcc.debug.nounity
If the clang toolchain is detected, then the default target will use it, else
the gcc toolchain will be used. On Windows environments, the MSVC toolchain is
also detected.
@@ -199,7 +209,10 @@ def config_base(env):
)
check_openssl()
env.Append(CPPDEFINES=['OPENSSL_NO_SSL2'])
env.Append(CPPDEFINES=[
'OPENSSL_NO_SSL2'
,'DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER'
])
try:
BOOST_ROOT = os.path.normpath(os.environ['BOOST_ROOT'])
@@ -245,7 +258,7 @@ def config_env(toolchain, variant, env):
if variant == 'debug':
env.Append(CPPDEFINES=['DEBUG', '_DEBUG'])
elif variant == 'release':
elif variant == 'release' or variant == 'profile':
env.Append(CPPDEFINES=['NDEBUG'])
if toolchain in Split('clang gcc'):
@@ -263,14 +276,32 @@ def config_env(toolchain, variant, env):
'-g' # generate debug symbols
])
env.Append(LINKFLAGS=[
'-rdynamic',
'-g',
])
if variant == 'profile':
env.Append(CCFLAGS=[
'-p',
'-pg',
])
env.Append(LINKFLAGS=[
'-p',
'-pg',
])
if toolchain == 'clang':
env.Append(CCFLAGS=['-Wno-redeclared-class-member'])
env.Append(CPPDEFINES=['BOOST_ASIO_HAS_STD_ARRAY'])
env.Append(CXXFLAGS=[
'-frtti',
'-std=c++11',
'-Wno-invalid-offsetof'])
env.Append(CPPDEFINES=['_FILE_OFFSET_BITS=64'])
if Beast.system.osx:
env.Append(CPPDEFINES={
'BEAST_COMPILE_OBJECTIVE_CPP': 1,
@@ -298,11 +329,10 @@ def config_env(toolchain, variant, env):
'boost_program_options',
'boost_regex',
'boost_system',
'boost_thread'
]
# We prefer static libraries for boost
if env.get('BOOST_ROOT'):
# Need to add boost_thread. Not needed when dynamic linking is used.
boost_libs += ['boost_thread']
static_libs = ['%s/stage/lib/lib%s.a' % (env['BOOST_ROOT'], l) for
l in boost_libs]
if all(os.path.exists(f) for f in static_libs):
@@ -324,22 +354,12 @@ def config_env(toolchain, variant, env):
else:
env.Append(LIBS=['rt'])
env.Append(LINKFLAGS=[
'-rdynamic'
])
if variant == 'release':
env.Append(CCFLAGS=[
'-O3',
'-fno-strict-aliasing'
])
if toolchain != 'msvc':
git = Beast.Git(env)
if git.exists:
id = '%s+%s.%s' % (git.tags, git.user, git.branch)
env.Append(CPPDEFINES={'GIT_COMMIT_ID' : '\'"%s"\'' % id })
if toolchain == 'clang':
if Beast.system.osx:
env.Replace(CC='clang', CXX='clang++', LINK='clang++')
@@ -480,7 +500,7 @@ base.Append(CPPPATH=[
])
# Configure the toolchains, variants, default toolchain, and default target
variants = ['debug', 'release']
variants = ['debug', 'release', 'profile']
all_toolchains = ['clang', 'gcc', 'msvc']
if Beast.system.osx:
toolchains = ['clang']
@@ -501,6 +521,8 @@ else:
default_toolchain = 'clang'
else:
raise ValueError("Don't understand toolchains in " + str(toolchains))
default_tu_style = 'unity'
default_variant = 'release'
default_target = None
@@ -527,144 +549,216 @@ class ObjectBuilder(object):
if kwds:
env = env.Clone()
env.Prepend(**kwds)
path = UNITY_BUILD_DIRECTORY + filename
o = env.Object(Beast.variantFile(path, self.variant_dirs))
o = env.Object(Beast.variantFile(filename, self.variant_dirs))
self.objects.append(o)
def list_sources(base, suffixes):
def _iter(base):
for parent, dirs, files in os.walk(base):
files = [f for f in files if not f[0] == '.']
dirs[:] = [d for d in dirs if not d[0] == '.']
for path in files:
path = os.path.join(parent, path)
r = os.path.splitext(path)
if r[1] and r[1] in suffixes:
yield os.path.normpath(path)
return list(_iter(base))
# Declare the targets
aliases = collections.defaultdict(list)
msvc_configs = []
for toolchain in all_toolchains:
for variant in variants:
# Configure this variant's construction environment
env = base.Clone()
config_env(toolchain, variant, env)
variant_name = '%s.%s' % (toolchain, variant)
variant_dir = os.path.join(build_dir, variant_name)
variant_dirs = {
os.path.join(variant_dir, 'src') :
'src',
os.path.join(variant_dir, 'proto') :
os.path.join (build_dir, 'proto'),
}
for dest, source in variant_dirs.iteritems():
env.VariantDir(dest, source, duplicate=0)
object_builder = ObjectBuilder(env, variant_dirs)
object_builder.add_source_files(
'app.cpp',
'app1.cpp',
'app2.cpp',
'app3.cpp',
'app4.cpp',
'app5.cpp',
'app6.cpp',
'app7.cpp',
'app8.cpp',
'app9.cpp',
'basics.cpp',
'beast.cpp',
'common.cpp',
'core.cpp',
'data.cpp',
'http.cpp',
'json.cpp',
'net.cpp',
'overlay.cpp',
'peerfinder.cpp',
'protobuf.cpp',
'ripple.proto.cpp',
'resource.cpp',
'rpcx.cpp',
'sitefiles.cpp',
'sslutil.cpp',
'types.cpp',
'validators.cpp',
'websocket.cpp',
)
for tu_style in ['classic', 'unity']:
for toolchain in all_toolchains:
for variant in variants:
if variant == 'profile' and toolchain == 'msvc':
continue
# Configure this variant's construction environment
env = base.Clone()
config_env(toolchain, variant, env)
variant_name = '%s.%s' % (toolchain, variant)
if tu_style == 'classic':
variant_name += '.nounity'
variant_dir = os.path.join(build_dir, variant_name)
variant_dirs = {
os.path.join(variant_dir, 'src') :
'src',
os.path.join(variant_dir, 'proto') :
os.path.join (build_dir, 'proto'),
}
for dest, source in variant_dirs.iteritems():
env.VariantDir(dest, source, duplicate=0)
object_builder.add_source_files(
'beastc.c',
CCFLAGS=['-Wno-array-bounds'])
object_builder = ObjectBuilder(env, variant_dirs)
object_builder.add_source_files(
'nodestore.cpp',
CPPPATH=[
'src/leveldb/include',
#'src/hyperleveldb/include', # hyper
'src/rocksdb2/include',
]
)
if tu_style == 'classic':
object_builder.add_source_files(
*list_sources('src/ripple/app', '.cpp'))
object_builder.add_source_files(
*list_sources('src/ripple/basics', '.cpp'))
object_builder.add_source_files(
*list_sources('src/ripple/core', '.cpp'))
object_builder.add_source_files(
*list_sources('src/ripple/crypto', '.cpp'))
object_builder.add_source_files(
*list_sources('src/ripple/json', '.cpp'))
object_builder.add_source_files(
*list_sources('src/ripple/net', '.cpp'))
object_builder.add_source_files(
*list_sources('src/ripple/overlay', '.cpp'))
object_builder.add_source_files(
*list_sources('src/ripple/peerfinder', '.cpp'))
object_builder.add_source_files(
*list_sources('src/ripple/protocol', '.cpp'))
object_builder.add_source_files(
*list_sources('src/ripple/shamap', '.cpp'))
object_builder.add_source_files(
*list_sources('src/ripple/nodestore', '.cpp'),
CPPPATH=[
'src/leveldb/include',
'src/rocksdb2/include',
'src/snappy/snappy',
'src/snappy/config',
])
else:
object_builder.add_source_files(
'src/ripple/unity/app.cpp',
'src/ripple/unity/app1.cpp',
'src/ripple/unity/app2.cpp',
'src/ripple/unity/app3.cpp',
'src/ripple/unity/app4.cpp',
'src/ripple/unity/app5.cpp',
'src/ripple/unity/app6.cpp',
'src/ripple/unity/app7.cpp',
'src/ripple/unity/app8.cpp',
'src/ripple/unity/app9.cpp',
'src/ripple/unity/core.cpp',
'src/ripple/unity/basics.cpp',
'src/ripple/unity/crypto.cpp',
'src/ripple/unity/net.cpp',
'src/ripple/unity/overlay.cpp',
'src/ripple/unity/peerfinder.cpp',
'src/ripple/unity/json.cpp',
'src/ripple/unity/protocol.cpp',
'src/ripple/unity/shamap.cpp',
)
if 'gcc' in toolchain:
no_uninitialized_warning = {'CCFLAGS': ['-Wno-maybe-uninitialized']}
else:
no_uninitialized_warning = {}
object_builder.add_source_files(
'src/ripple/unity/nodestore.cpp',
CPPPATH=[
'src/leveldb/include',
'src/rocksdb2/include',
'src/snappy/snappy',
'src/snappy/config',
])
object_builder.add_source_files(
'leveldb.cpp',
CPPPATH=[
'src/leveldb/',
'src/leveldb/include',
'src/snappy/snappy',
'src/snappy/config',
],
**no_uninitialized_warning
)
git_commit_tag = {}
if toolchain != 'msvc':
git = Beast.Git(env)
if git.exists:
id = '%s+%s.%s' % (git.tags, git.user, git.branch)
git_commit_tag = {'CPPDEFINES':
{'GIT_COMMIT_ID' : '\'"%s"\'' % id }}
object_builder.add_source_files(
'hyperleveldb.cpp',
CPPPATH=[
'src/hyperleveldb',
'src/snappy/snappy',
'src/snappy/config',
],
**no_uninitialized_warning
)
object_builder.add_source_files(
'src/ripple/unity/git_id.cpp',
**git_commit_tag)
object_builder.add_source_files(
'rocksdb.cpp',
CPPPATH=[
'src/rocksdb2',
'src/rocksdb2/include',
'src/snappy/snappy',
'src/snappy/config',
],
**no_uninitialized_warning
)
object_builder.add_source_files(
'snappy.cpp',
CCFLAGS=['-Wno-unused-function'],
CPPPATH=[
'src/snappy/snappy',
'src/snappy/config',
]
)
if toolchain == "clang" and Beast.system.osx:
object_builder.add_source_files('beastobjc.mm')
target = env.Program(
target=os.path.join(variant_dir, 'rippled'),
source=object_builder.objects
object_builder.add_source_files(
'src/beast/beast/unity/hash_unity.cpp',
'src/ripple/unity/beast.cpp',
'src/ripple/unity/lz4.c',
'src/ripple/unity/protobuf.cpp',
'src/ripple/unity/ripple.proto.cpp',
'src/ripple/unity/resource.cpp',
'src/ripple/unity/rpcx.cpp',
'src/ripple/unity/server.cpp',
'src/ripple/unity/validators.cpp',
'src/ripple/unity/websocket.cpp'
)
if toolchain == default_toolchain and variant == default_variant:
default_target = target
install_target = env.Install (build_dir, source=default_target)
env.Alias ('install', install_target)
env.Default (install_target)
aliases['all'].extend(install_target)
if toolchain == 'msvc':
config = env.VSProjectConfig(variant, 'x64', target, env)
msvc_configs.append(config)
if toolchain in toolchains:
aliases['all'].extend(target)
aliases[variant].extend(target)
aliases[toolchain].extend(target)
env.Alias(variant_name, target)
object_builder.add_source_files(
'src/ripple/unity/beastc.c',
CCFLAGS = ([] if toolchain == 'msvc' else ['-Wno-array-bounds']))
if 'gcc' in toolchain:
no_uninitialized_warning = {'CCFLAGS': ['-Wno-maybe-uninitialized']}
else:
no_uninitialized_warning = {}
object_builder.add_source_files(
'src/ripple/unity/ed25519.c',
CPPPATH=[
'src/ed25519-donna',
]
)
object_builder.add_source_files(
'src/ripple/unity/leveldb.cpp',
CPPPATH=[
'src/leveldb/',
'src/leveldb/include',
'src/snappy/snappy',
'src/snappy/config',
],
**no_uninitialized_warning
)
object_builder.add_source_files(
'src/ripple/unity/hyperleveldb.cpp',
CPPPATH=[
'src/hyperleveldb',
'src/snappy/snappy',
'src/snappy/config',
],
**no_uninitialized_warning
)
object_builder.add_source_files(
'src/ripple/unity/rocksdb.cpp',
CPPPATH=[
'src/rocksdb2',
'src/rocksdb2/include',
'src/snappy/snappy',
'src/snappy/config',
],
**no_uninitialized_warning
)
object_builder.add_source_files(
'src/ripple/unity/snappy.cpp',
CCFLAGS=([] if toolchain == 'msvc' else ['-Wno-unused-function']),
CPPPATH=[
'src/snappy/snappy',
'src/snappy/config',
]
)
if toolchain == "clang" and Beast.system.osx:
object_builder.add_source_files('src/ripple/unity/beastobjc.mm')
target = env.Program(
target=os.path.join(variant_dir, 'rippled'),
source=object_builder.objects
)
if tu_style == default_tu_style:
if toolchain == default_toolchain and (
variant == default_variant):
default_target = target
install_target = env.Install (build_dir, source=default_target)
env.Alias ('install', install_target)
env.Default (install_target)
aliases['all'].extend(install_target)
if toolchain == 'msvc':
config = env.VSProjectConfig(variant, 'x64', target, env)
msvc_configs.append(config)
if toolchain in toolchains:
aliases['all'].extend(target)
aliases[toolchain].extend(target)
if toolchain in toolchains:
aliases[variant].extend(target)
env.Alias(variant_name, target)
for key, value in aliases.iteritems():
env.Alias(key, value)
@@ -675,3 +769,32 @@ vcxproj = base.VSProject(
VSPROJECT_ROOT_DIRS = ['src/beast', 'src', '.'],
VSPROJECT_CONFIGS = msvc_configs)
base.Alias('vcxproj', vcxproj)
#-------------------------------------------------------------------------------
# Adds a phony target to the environment that always builds
# See: http://www.scons.org/wiki/PhonyTargets
def PhonyTargets(env = None, **kw):
if not env: env = DefaultEnvironment()
for target, action in kw.items():
env.AlwaysBuild(env.Alias(target, [], action))
# Build the list of rippled source files that hold unit tests
def do_count(target, source, env):
def list_testfiles(base, suffixes):
def _iter(base):
for parent, _, files in os.walk(base):
for path in files:
path = os.path.join(parent, path)
r = os.path.splitext(path)
if r[1] in suffixes:
if r[0].endswith('.test'):
yield os.path.normpath(path)
return list(_iter(base))
testfiles = list_testfiles(os.path.join('src', 'ripple'), env.get('CPPSUFFIXES'))
lines = 0
for f in testfiles:
lines = lines + sum(1 for line in open(f))
print "Total unit test lines: %d" % lines
PhonyTargets(env, count = do_count)

77
appveyor.yml Normal file
View File

@@ -0,0 +1,77 @@
# Set environment variables.
environment:
PYTHON: C:/Python27-x64
# We bundle up protoc.exe and only the parts of boost and openssl we need so
# that it's a small download. We also use appveyor's free cache, avoiding fees
# downloading from S3 each time.
# TODO: script to create this package.
RIPPLED_DEPS_URL: https://s3-ap-northeast-1.amazonaws.com/history-replay/rippled_deps.zip
# Other dependencies we just download each time.
PIP_URL: https://bootstrap.pypa.io/get-pip.py
PYWIN32_URL: https://downloads.sourceforge.net/project/pywin32/pywin32/Build%20219/pywin32-219.win-amd64-py2.7.exe
# Scons honours these environment variables, setting the include/lib paths.
BOOST_ROOT: C:/rippled_deps/boost
OPENSSL_ROOT: C:/rippled_deps/openssl
# At the end of each successful build we cache this directory. It must be less
# than 100MB total compressed.
cache:
- 'C:\\rippled_deps'
# This means we'll download a zip of the branch we want, rather than the full
# history.
shallow_clone: true
install:
# We want easy_install, python and protoc.exe on PATH.
- SET PATH=%PYTHON%;%PYTHON%/Scripts;C:/rippled_deps;%PATH%
# `ps` prefix means the command is executed by powershell.
- ps: Start-FileDownload $env:PIP_URL
- ps: Start-FileDownload $env:PYWIN32_URL
# Installing pip will install setuptools/easy_install.
- python get-pip.py
# Pip has some problems installing scons on windows so we use easy install.
- easy_install scons
# Scons has problems with parallel builds on windows without pywin32.
- easy_install pywin32-219.win-amd64-py2.7.exe
# (easy_install can do headless installs of .exe wizards)
# Download dependencies if appveyor didn't restore them from the cache.
# Use 7zip to unzip.
- ps: |
if (-not(Test-Path 'C:/rippled_deps')) {
Start-FileDownload "$env:RIPPLED_DEPS_URL"
7z x rippled_deps.zip -oC:\ -y > $null
}
# TODO: This is giving me grief
# artifacts:
# # Save rippled.exe in the cloud after each build.
# - path: "build\\rippled.exe"
build_script:
# We set the environment variables needed to put compilers on the PATH.
- '"%VS120COMNTOOLS%../../VC/vcvarsall.bat" x86_amd64'
# Show which version of the compiler we are using.
- cl
- scons msvc.debug -j%NUMBER_OF_PROCESSORS%
after_build:
# Put our executable in a place where npm test can find it.
- ps: cp build/msvc.debug/rippled.exe build
- ps: ls build
test_script:
# Run the unit tests
- build\\rippled --unittest
# Run the integration tests
- npm install
- npm test

133
bin/stop-test.js Normal file
View File

@@ -0,0 +1,133 @@
/* -------------------------------- REQUIRES -------------------------------- */
var child = require("child_process");
var assert = require("assert");
/* --------------------------------- CONFIG --------------------------------- */
if (process.argv[2] == null) {
[
'Usage: ',
'',
' `node bin/stop-test.js i,j [rippled_path] [rippled_conf]`',
'',
' Launch rippled and stop it after n seconds for all n in [i, j}',
' For all even values of n launch rippled with `--fg`',
' For values of n where n % 3 == 0 launch rippled with `--fg`\n',
'Examples: ',
'',
' $ node bin/stop-test.js 5,10',
(' $ node bin/stop-test.js 1,4 ' +
'build/clang.debug/rippled $HOME/.confs/rippled.cfg')
]
.forEach(function(l){console.log(l)});
process.exit();
} else {
var testRange = process.argv[2].split(',').map(Number);
var rippledPath = process.argv[3] || 'build/rippled'
var rippledConf = process.argv[4] || 'rippled.cfg'
}
var options = {
env: process.env,
stdio: 'ignore' // we could dump the child io when it fails abnormally
};
// default args
var conf_args = ['--conf='+rippledConf];
var start_args = conf_args.concat([/*'--net'*/])
var stop_args = conf_args.concat(['stop']);
/* --------------------------------- HELPERS -------------------------------- */
function start(args) {
return child.spawn(rippledPath, args, options);
}
function stop(rippled) { child.execFile(rippledPath, stop_args, options)}
function secs_l8r(ms, f) {setTimeout(f, ms * 1000); }
function show_results_and_exit(results) {
console.log(JSON.stringify(results, undefined, 2));
process.exit();
}
var timeTakes = function (range) {
function sumRange(n) {return (n+1) * n /2}
var ret = sumRange(range[1]);
if (range[0] > 1) {
ret = ret - sumRange(range[0] - 1)
}
var stopping = (range[1] - range[0]) * 0.5;
return ret + stopping;
}
/* ---------------------------------- TEST ---------------------------------- */
console.log("Test will take ~%s seconds", timeTakes(testRange));
(function oneTest(n /* seconds */, results) {
if (n >= testRange[1]) {
// show_results_and_exit(results);
console.log(JSON.stringify(results, undefined, 2));
oneTest(testRange[0], []);
return;
}
var args = start_args;
if (n % 2 == 0) {args = args.concat(['--fg'])}
if (n % 3 == 0) {args = args.concat(['--net'])}
var result = {args: args, alive_for: n};
results.push(result);
console.log("\nLaunching `%s` with `%s` for %d seconds",
rippledPath, JSON.stringify(args), n);
rippled = start(args);
console.log("Rippled pid: %d", rippled.pid);
// defaults
var b4StopSent = false;
var stopSent = false;
var stop_took = null;
rippled.once('exit', function(){
if (!stopSent && !b4StopSent) {
console.warn('\nRippled exited itself b4 stop issued');
process.exit();
};
// The io handles close AFTER exit, may have implications for
// `stdio:'inherit'` option to `child.spawn`.
rippled.once('close', function() {
result.stop_took = (+new Date() - stop_took) / 1000; // seconds
console.log("Stopping after %d seconds took %s seconds",
n, result.stop_took);
oneTest(n+1, results);
});
});
secs_l8r(n, function(){
console.log("Stopping rippled after %d seconds", n);
// possible race here ?
// seems highly unlikely, but I was having issues at one point
b4StopSent=true;
stop_took = (+new Date());
// when does `exit` actually get sent?
stop();
stopSent=true;
// Sometimes we want to attach with a debugger.
if (process.env.ABORT_TESTS_ON_STALL != null) {
// We wait 30 seconds, and if it hasn't stopped, we abort the process
secs_l8r(30, function() {
if (result.stop_took == null) {
console.log("rippled has stalled");
process.exit();
};
});
}
})
}(testRange[0], []));

View File

@@ -6,23 +6,23 @@
#
# Contents
#
# 1. Peer Networking
# 1. Server
#
# 2. Websocket Networking
# 2. Peer Protocol
#
# 3. RPC Networking
# 3. SMS Gateway
#
# 4. SMS Gateway
# 4. Ripple Protocol
#
# 5. Ripple Protcol
# 5. HTTPS Client
#
# 6. HTTPS Client
# 6. Database
#
# 7. Database
# 7. Diagnostics
#
# 8. Diagnostics
# 8. Voting
#
# 9. Voting
# 9. Example Settings
#
#-------------------------------------------------------------------------------
#
@@ -44,19 +44,235 @@
# or Mac style end of lines. Blank lines and lines beginning with '#' are
# ignored. Undefined sections are reserved. No escapes are currently defined.
#
# Notation
#
# In this document a simple BNF notation is used. Angle brackets denote
# required elements, square brackets denote optional elements, and single
# quotes indicate string literals. A vertical bar separating 1 or more
# elements is a logical "or"; Any one of the elements may be chosen.
# Parenthesis are notational only, and used to group elements, they are not
# part of the syntax unless they appear in quotes. White space may always
# appear between elements, it has no effect on values.
#
# <key> A required identifier
# '=' The equals sign character
# | Logical "or"
# ( ) Used for grouping
#
#
# An identifier is a string of upper or lower case letters, digits, or
# underscores subject to the requirement that the first character of an
# identifier must be a letter. Identifiers are not case sensitive (but
# values may be).
#
# Some configuration sections contain key/value pairs. A line containing
# a key/value pair has this syntax:
#
# <identifier> '=' <value>
#
# Depending on the section and key, different value types are possible:
#
# <integer> A signed integer
# <unsigned> An unsigned integer
# <flag> A boolean. 1 = true/yes/on, 0 = false/no/off.
#
# Consult the documentation on the key in question to determine the possible
# value types.
#
#
#
#-------------------------------------------------------------------------------
#
# 1. Peer Networking
# 1. Server
#
#-------------------
#----------
#
#
#
# rippled offers various server protocols to clients making inbound
# connections. The listening ports rippled uses are "universal" ports
# which may be configured to handshake in one or more of the available
# supported protocols. These universal ports simplify administration:
# A single open port can be used for multiple protocols.
#
# NOTE At least one server port must be defined in order
# to accept incoming network connections.
#
#
# [server]
#
# A list of port names and key/value pairs. A port name must start with a
# letter and contain only letters and numbers. The name is not case-sensitive.
# For each name in this list, rippled will look for a configuration file
# section with the same name and use it to create a listening port. The
# name is informational only; the choice of name does not affect the function
# of the listening port.
#
# Key/value pairs specified in this section are optional, and apply to all
# listening ports unless the port overrides the value in its section. They
# may be considered default values.
#
# Suggestion:
#
# To avoid a conflict with port names and future configuration sections,
# we recommend prepending "port_" to the port name. This prefix is not
# required, but suggested.
#
# This example defines two ports with different port numbers and settings:
#
# [server]
# port_public
# port_private
# port = 80
#
# [port_public]
# ip=0.0.0.0
# port = 443
# protocol=peer,https
#
# [port_private]
# ip=127.0.0.1
# protocol=http
#
# When rippled is used as a command line client (for example, issuing a
# server stop command), the first port advertising the http or https
# protocol will be used to make the connection.
#
#
#
# [<name>]
#
# A series of key/value pairs that define the settings for the port with
# the corresponding name. These keys are possible:
#
# ip = <IP-address>
#
# Required. Determines the IP address of the network interface to bind
# to. To bind to all available interfaces, uses 0.0.0.0
#
# port = <number>
#
# Required. Sets the port number to use for this port.
#
# protocol = [ http, https, peer ]
#
# Required. A comma-separated list of protocols to support:
#
# http JSON-RPC over HTTP
# https JSON-RPC over HTTPS
# ws Websockets
# wss Secure Websockets
# peer Peer Protocol
#
# Restrictions:
#
# Only one port may be configured to support the peer protocol.
# A port cannot have websocket and non websocket protocols at the
# same time. It is possible have both Websockets and Secure Websockets
# together in one port.
#
# NOTE If no ports support the peer protocol, rippled cannot
# receive incoming peer connections or become a superpeer.
#
# user = <text>
# password = <text>
#
# When set, these credentials will be required on HTTP/S requests.
# The credentials must be provided using HTTP's Basic Authentication
# headers. If either or both fields are empty, then no credentials are
# required. IP address restrictions, if any, will be checked in addition
# to the credentials specified here.
#
# When acting in the client role, rippled will supply these credentials
# using HTTP's Basic Authentication headers when making outbound HTTP/S
# requests.
#
# admin = no | allow
#
# Controls whether or not administrative commands are allowed. These
# commands may be issued over http, https, ws, or wss if configured
# on the port. If unspecified, the default is to not allow
# administrative commands.
#
# admin_user = <text>
# admin_password = <text>
#
# When set, clients must provide these credentials in the submitted
# JSON for any administrative command requests submitted to the HTTP/S,
# WS, or WSS protocol interfaces. If administrative commands are
# disabled for a port, these credentials have no effect.
#
# When acting in the client role, rippled will supply these credentials
# in the submitted JSON for any administrative command requests when
# invoking JSON-RPC commands on remote servers.
#
# ssl_key = <filename>
# ssl_cert = <filename>
# ssl_chain = <filename>
#
# Use the specified files when configuring SSL on the port.
#
# NOTE If no files are specified and secure protocols are selected,
# rippled will generate an internal self-signed certificate.
#
# The files have these meanings:
#
# ssl_key
#
# Specifies the filename holding the SSL key in PEM format.
#
# ssl_cert
#
# Specifies the path to the SSL certificate file in PEM format.
# This is not needed if the chain includes it.
#
# ssl_chain
#
# If you need a certificate chain, specify the path to the
# certificate chain here. The chain may include the end certificate.
#
#
#
# [rpc_admin_allow]
#
# Specify a list of IP addresses allowed to have admin access. One per line.
# If you want to test the output of non-admin commands add this section and
# just put an ip address not under your control.
# Defaults to 127.0.0.1.
#
#
#
# [rpc_startup]
#
# Specify a list of RPC commands to run at startup.
#
# Examples:
# { "command" : "server_info" }
# { "command" : "log_level", "partition" : "ripplecalc", "severity" : "trace" }
#
#
#
# [websocket_ping_frequency]
#
# <number>
#
# The amount of time to wait in seconds, before sending a websocket 'ping'
# message. Ping messages are used to determine if the remote end of the
# connection is no longer available.
#
#
#
#-------------------------------------------------------------------------------
#
# 2. Peer Protocol
#
#-----------------
#
# These settings control security and access attributes of the Peer to Peer
# server section of the rippled process. Peer Networking implements the
# server section of the rippled process. Peer Protocol implements the
# Ripple Payment protocol. It is over peer connections that transactions
# and validations are passed from to machine to machine, to make up the
# components of closed ledgers.
# and validations are passed from to machine to machine, to determine the
# contents of validated ledgers.
#
#
#
@@ -95,40 +311,6 @@
#
#
#
# [peer_ip]
#
# IP address or domain to bind to allow external connections from peers.
# Defaults to not binding, which disallows external connections from peers.
#
# Examples: 0.0.0.0 - Bind on all interfaces.
#
#
#
# [peer_port]
#
# If peer_ip is supplied, corresponding port to bind to for peer connections.
#
#
#
# [peer_port_proxy]
#
# An optional, additional listening port number for peers. Incoming
# connections on this port will be required to provide a PROXY Protocol
# handshake, described in this document (external link):
#
# http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt
#
# The PROXY Protocol is a popular method used by elastic load balancing
# service providers such as Amazon, to identify the true IP address and
# port number of external incoming connections.
#
# In addition to enabling this setting, it will also be required to
# use your provider-specific control panel or administrative web page
# to configure your server instance to receive PROXY Protocol handshakes,
# and also to restrict access to your instance to the Elastic Load Balancer.
#
#
#
# [peer_private]
#
# 0 or 1.
@@ -147,19 +329,6 @@
#
#
#
# [peer_ssl_cipher_list]
#
# A colon delimited string with the allowed SSL cipher modes for peer. The
# choices for for ciphers are defined by the OpenSSL API function
# SSL_CTX_set_cipher_list, documented here (external link):
#
# http://pic.dhe.ibm.com/infocenter/tpfhelp/current/index.jsp?topic=%2Fcom.ibm.ztpf-ztpfdf.doc_put.cur%2Fgtpc2%2Fcpp_ssl_ctx_set_cipher_list.html
#
# The default setting is "ALL:!LOW:!EXP:!MD5:@STRENGTH", which allows
# non-authenticated peer connections (they are, however, secure).
#
#
#
# [node_seed]
#
# This is used for clustering. To force a particular node seed or key, the
@@ -193,245 +362,49 @@
#
#
#
#-------------------------------------------------------------------------------
# [overlay] EXPERIMENTAL
#
# 2. Websocket Networking
# This section is EXPERIMENTAL, and should not be
# present for production configuration settings.
#
#------------------------
# A set of key/value pair parameters to configure the overlay.
#
# These settings control security and access attributes of the Websocket
# server section of the rippled process, primarily used to service
# client requests and backend applications.
# auto_connect = 0 | 1
#
# When set, activates the autoconnect feature. This maintains outgoing
# connections using PeerFinder's "Outgoing Connection Strategy."
#
# http_handshake = 0 | 1
#
# [websocket_public_ip]
# When set, outgoing peer connections will handshaking using a HTTP
# request instead of the legacy TMHello protocol buffers message.
# Incoming peer connections have their handshakes detected automatically.
#
# IP address or domain to bind to allow untrusted connections from clients.
# In the future, this option will go away and the peer_ip will accept
# websocket client connections.
# become_superpeer = 'never' | 'always' | 'auto'
#
# Examples: 0.0.0.0 - Bind on all interfaces.
# 127.0.0.1 - Bind on localhost interface. Only local programs may connect.
# Controls the selection of peer roles:
#
# 'never' Always handshake in the leaf role.
# 'always' Always handshake in the superpeer role.
# 'auto' Start as a leaf, promote to superpeer after
# passing capability check (default).
#
# In the leaf role, a peer does not advertise its IP and port for
# the purpose of receiving incoming connections. The peer also does
# not forward transactions and validations received from other peers.
#
# [websocket_public_port]
#
# Port to bind to allow untrusted connections from clients. In the future,
# this option will go away and the peer_ip will accept websocket client
# connections.
#
#
#
# [websocket_public_secure]
#
# 0, 1 or 2.
# 0: Provide ws service for websocket_public_ip/websocket_public_port.
# 1: Provide both ws and wss service for websocket_public_ip/websocket_public_port. [default]
# 2: Provide wss service only for websocket_public_ip/websocket_public_port.
#
# Browser pages like the Ripple client will not be able to connect to a secure
# websocket connection if a self-signed certificate is used. As the Ripple
# reference client currently shares secrets with its server, this should be
# enabled.
#
#
#
# [websocket_ping_frequency]
#
# <number>
#
# The amount of time to wait in seconds, before sending a websocket 'ping'
# message. Ping messages are used to determine if the remote end of the
# connection is no longer available.
#
#
#
# [websocket_ip]
#
# IP address or domain to bind to allow trusted ADMIN connections from backend
# applications.
#
# Examples: 0.0.0.0 - Bind on all interfaces.
# 127.0.0.1 - Bind on localhost interface. Only local programs may connect.
#
#
#
# [websocket_port]
#
# Port to bind to allow trusted ADMIN connections from backend applications.
#
#
#
# [websocket_secure]
#
# 0, 1, or 2.
# 0: Provide ws service only for websocket_ip/websocket_port. [default]
# 1: Provide ws and wss service for websocket_ip/websocket_port
# 2: Provide wss service for websocket_ip/websocket_port.
#
#
#
# [websocket_ssl_cert]
#
# Specify the path to the SSL certificate file in PEM format.
# This is not needed if the chain includes it.
#
#
#
# [websocket_ssl_chain]
#
# If you need a certificate chain, specify the path to the certificate chain
# here. The chain may include the end certificate.
#
#
#
# [websocket_ssl_key]
#
# Specify the filename holding the SSL key in PEM format.
# In the superpeer role, a peer advertises its IP and port for
# receiving incoming connections after passing an incoming connection
# test. Superpeers forward transactions and protocol messages to all
# other peers. Superpeers do not forward validations to other superpeers.
# Instead, a validation received by a superpeer from a leaf is forwarded
# only to other leaf connections.
#
#
#
#-------------------------------------------------------------------------------
#
# 3. RPC Networking
#
#------------------
#
# This group of settings configures security and access attributes of the
# RPC server section of the rippled process, used to service both local
# and optional remote clients.
#
#
#
# [rpc_allow_remote]
#
# 0 or 1.
#
# 0: Allow RPC connections only from 127.0.0.1. [default]
# 1: Allow RPC connections from any IP.
#
#
#
# [rpc_admin_allow]
#
# Specify a list of IP addresses allowed to have admin access. One per line.
# If you want to test the output of non-admin commands add this section and
# just put an ip address not under your control.
# Defaults to 127.0.0.1.
#
#
#
# [rpc_admin_user]
#
# As a server, require this as the admin user to be specified. Also, require
# rpc_admin_user and rpc_admin_password to be checked for RPC admin functions.
# The request must specify these as the admin_user and admin_password in the
# request object.
#
# As a client, supply this to the server in the request object.
#
#
#
# [rpc_admin_password]
#
# As a server, require this as the admin password to be specified. Also,
# require rpc_admin_user and rpc_admin_password to be checked for RPC admin
# functions. The request must specify these as the admin_user and
# admin_password in the request object.
#
# As a client, supply this to the server in the request object.
#
#
#
# [rpc_ip]
#
# IP address or domain to bind to allow insecure RPC connections.
# Defaults to not binding, which disallows RPC connections.
#
#
#
# [rpc_port]
#
# If rpc_ip is supplied, corresponding port to bind to for peer connections.
#
#
#
# [rpc_user]
#
# As a server, require this user to be specified and require rpc_password to
# be checked for RPC access via the rpc_ip and rpc_port. The user and password
# must be specified via HTTP's basic authentication method.
# As a client, supply this to the server via HTTP's basic authentication
# method.
#
#
#
# [rpc_password]
#
# As a server, require this password to be specified and require rpc_user to
# be checked for RPC access via the rpc_ip and rpc_port. The user and password
# must be specified via HTTP's basic authentication method.
# As a client, supply this to the server via HTTP's basic authentication
# method.
#
#
#
# [rpc_startup]
#
# Specify a list of RPC commands to run at startup.
#
# Examples:
# { "command" : "server_info" }
# { "command" : "log_level", "partition" : "ripplecalc", "severity" : "trace" }
#
#
#
# [rpc_secure]
#
# 0 or 1.
#
# 0: Server certificates are not provided for RPC clients using SSL [default]
# 1: Client RPC connections wil be provided with SSL certificates.
#
# Note that if rpc_secure is enabled, it will also be necessary to configure
# the certificate file settings located in rpc_ssl_cert, rpc_ssl_chain, and
# rpc_ssl_key
#
#
#
# [rpc_ssl_cert]
#
# <pathname>
#
# A file system path leading to the SSL certificate file to use for secure
# RPC. The file is in PEM format. The file is not needed if the chain
# includes it.
#
#
#
# [rpc_ssl_chain]
#
# <pathname>
#
# A file system path leading to the file with the certificate chain.
# The chain may include the end certificate.
#
#
#
# [rpc_ssl_key]
#
# <pathname>
#
# A file system path leading to the file with the SSL key.
# The file is in PEM format.
#
#
#
#-------------------------------------------------------------------------------
#
# 4. SMS Gateway
# 3. SMS Gateway
#
#---------------
#
@@ -467,9 +440,9 @@
#
#-------------------------------------------------------------------------------
#
# 5. Ripple Protocol
# 4. Ripple Protocol
#
#------------------
#-------------------
#
# These settings affect the behavior of the server instance with respect
# to Ripple payment protocol level activities such as validating and
@@ -508,6 +481,13 @@
#
#
#
# [ledger_history_index]
#
# If set to greater than 0, the index number of the earliest ledger to
# acquire.
#
#
#
# [fetch_depth]
#
# The number of past ledgers to serve to other peers that request historical
@@ -611,7 +591,7 @@
#
#-------------------------------------------------------------------------------
#
# 6. HTTPS Client
# 5. HTTPS Client
#
#----------------
#
@@ -625,7 +605,9 @@
# 0 or 1.
#
# 0. HTTPS client connections will not verify certificates.
# 1. Certificates will be checked for HTTPS client connections .
# 1. Certificates will be checked for HTTPS client connections.
#
# If not specified, this parameter defaults to 1.
#
#
#
@@ -651,7 +633,7 @@
#
#-------------------------------------------------------------------------------
#
# 7. Database
# 6. Database
#
#------------
#
@@ -690,16 +672,24 @@
#
# Choices for 'type' (not case-sensitive)
# RocksDB Use Facebook's RocksDB database (preferred)
# HyperLevelDB Use an improved version of LevelDB
# SQLite Use SQLite
# LevelDB Use Google's LevelDB database (deprecated)
# none Use no backend
# NuDB Use Ripple Labs' NuDB (Windows preferred)
# HyperLevelDB (Deprecated)
# SQLite (Deprecated)
# LevelDB (Deprecated)
# none (No backend)
#
# Required keys:
# path Location to store the database (all types)
#
# Optional keys:
# compression 0 for none, 1 for Snappy compression
# online_delete Minimum value of 256. Enable automatic purging
# of older ledger information. Maintain at least this
# number of ledger records online. Must be greater
# than or equal to ledger_history.
# advisory_delete 0 for disabled, 1 for enabled. If set, then
# require administrative RPC call "can_delete"
# to enable online deletion of ledger records.
#
# Notes:
# The 'node_db' entry configures the primary, persistent storage.
@@ -724,7 +714,7 @@
#
#-------------------------------------------------------------------------------
#
# 8. Diagnostics
# 7. Diagnostics
#
#---------------
#
@@ -780,7 +770,7 @@
#
#-------------------------------------------------------------------------------
#
# 9. Voting
# 8. Voting
#
#----------
#
@@ -830,41 +820,84 @@
# owner_reserve = 5000000 # 5 XRP
#
#-------------------------------------------------------------------------------
# Allow other peers to connect to this server.
#
[peer_ip]
0.0.0.0
[peer_port]
51235
# Allow untrusted clients to connect to this server.
# 9. Example Settings
#
[websocket_public_ip]
0.0.0.0
[websocket_public_port]
5006
# Provide trusted websocket ADMIN access to the localhost.
#--------------------
#
[websocket_ip]
127.0.0.1
[websocket_port]
6006
# Provide trusted json-rpc ADMIN access to the localhost.
# Administrators can use these values as a starting poing for configuring
# their instance of rippled, but each value should be checked to make sure
# it meets the business requirements for the organization.
#
[rpc_ip]
127.0.0.1
# Server
#
# These example configuration settings create these ports:
#
# "peer"
#
# Peer protocol open to everyone. This is required to accept
# incoming rippled connections. This does not affect automatic
# or manual outgoing Peer protocol connections.
#
# "rpc"
#
# Administrative RPC commands over HTTPS, when originating from
# the same machine (via the loopback adapter at 127.0.0.1).
#
# "wss_admin"
#
# Admin level API commands over Secure Websockets, when originating
# from the same machine (via the loopback adapter at 127.0.0.1).
#
# This port is commented out but can be enabled by removing
# the '#' from each corresponding line including the entry under [server]
#
# "wss_public"
#
# Guest level API commands over Secure Websockets, open to everyone.
#
# For HTTPS and Secure Websockets ports, if no certificate and key file
# are specified then a self-signed certificate will be generated on startup.
# If you have a certificate and key file, uncomment the corresponding lines
# and ensure the paths to the files are correct.
#
# NOTE
#
# To accept connections on well known ports such as 80 (HTTP) or
# 443 (HTTPS), most operating systems will require rippled to
# run with administrator privileges, or else rippled will not start.
[rpc_port]
5005
[server]
port_rpc
port_peer
port_wss_admin
#port_ws_public
#ssl_key = /etc/ssl/private/server.key
#ssl_cert = /etc/ssl/certs/server.crt
[rpc_allow_remote]
0
[port_rpc]
port = 5005
ip = 127.0.0.1
admin = allow
protocol = https
[port_peer]
port = 51235
ip = 0.0.0.0
protocol = peer
[port_wss_admin]
port = 6006
ip = 127.0.0.1
admin = allow
protocol = wss
#[port_ws_public]
#port = 5005
#ip = 127.0.0.1
#protocol = wss
#-------------------------------------------------------------------------------
[node_size]
medium
@@ -872,6 +905,8 @@ medium
# This is primary persistent datastore for rippled. This includes transaction
# metadata, account states, and ledger headers. Helpful information can be
# found here: https://ripple.com/wiki/NodeBackEnd
# delete old ledgers while maintaining at least 2000. Do not require an
# external administrative command to initiate deletion.
[node_db]
type=RocksDB
path=/var/lib/rippled/db/rocksdb
@@ -880,6 +915,8 @@ filter_bits=12
cache_mb=256
file_size_mb=8
file_size_mult=2
online_delete=2000
advisory_delete=0
[database_path]
/var/lib/rippled/db
@@ -919,22 +956,7 @@ n9LdgEtkmGB9E2h3K4Vp7iGUaKuq23Zr32ehxiU8FWY7xoxbWTSA RL5
[rpc_startup]
{ "command": "log_level", "severity": "warning" }
# Configure SSL for WebSockets. Not enabled by default because not everybody
# has an SSL cert on their server, but if you uncomment the following lines and
# set the path to the SSL certificate and private key the WebSockets protocol
# will be protected by SSL/TLS.
#[websocket_secure]
#1
#[websocket_ssl_cert]
#/etc/ssl/certs/server.crt
#[websocket_ssl_key]
#/etc/ssl/private/server.key
# Defaults to 0 ("no") so that you can use self-signed SSL certificates for
# development, or internally.
# Defaults to 1 ("yes") so that certificates will be validated. To allow the use
# of self-signed certificates for development or internal use, set to 0 ("no").
#[ssl_verify]
#0

BIN
images/build.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
images/contribute.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
images/network.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
images/pathfinding.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

BIN
images/ripple.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
images/transact.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
images/vehicle_currency.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -66,17 +66,6 @@
//#define BEAST_CHECK_MEMORY_LEAKS 0
#endif
/** Config: BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES
Setting this option makes Socket-derived classes generate compile errors
if they forget any of the virtual overrides As some Socket-derived classes
intentionally omit member functions that are not applicable, this macro
should only be enabled temporarily when writing your own Socket-derived
class, to make sure that the function signatures match as expected.
*/
#ifndef BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES
//#define BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES 1
#endif
//------------------------------------------------------------------------------
//
// Libraries
@@ -208,17 +197,18 @@
#define RIPPLE_SINGLE_IO_SERVICE_THREAD 0
#endif
/** Config: RIPPLE_STRUCTURED_OVERLAY_CLIENT
RIPPLE_STRUCTURED_OVERLAY_SERVER
Enables Structured Overlay support for the client or server roles.
This feature is currently in development:
https://ripplelabs.atlassian.net/browse/RIPD-157
/** Config: RIPPLE_HOOK_VALIDATORS
Activates code for handling validations and validators (work in progress).
*/
#ifndef RIPPLE_STRUCTURED_OVERLAY_CLIENT
#define RIPPLE_STRUCTURED_OVERLAY_CLIENT 0
#ifndef RIPPLE_HOOK_VALIDATORS
#define RIPPLE_HOOK_VALIDATORS 0
#endif
#ifndef RIPPLE_STRUCTURED_OVERLAY_SERVER
#define RIPPLE_STRUCTURED_OVERLAY_SERVER 1
/** Config: RIPPLE_ENABLE_TICKETS
Enables processing of ticket transactions
*/
#ifndef RIPPLE_ENABLE_TICKETS
#define RIPPLE_ENABLE_TICKETS 0
#endif
#endif

View File

@@ -64,17 +64,6 @@
//#define BEAST_CHECK_MEMORY_LEAKS 0
#endif
/** Config: BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES
Setting this option makes Socket-derived classes generate compile errors
if they forget any of the virtual overrides As some Socket-derived classes
intentionally omit member functions that are not applicable, this macro
should only be enabled temporarily when writing your own Socket-derived
class, to make sure that the function signatures match as expected.
*/
#ifndef BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES
//#define BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES 1
#endif
//------------------------------------------------------------------------------
//
// Libraries

View File

@@ -1,429 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Portions of this file are from JUCE.
Copyright (c) 2013 - Raw Material Software Ltd.
Please visit http://www.juce.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_ATOMIC_H_INCLUDED
#define BEAST_ATOMIC_H_INCLUDED
#include <beast/Config.h>
#include <beast/utility/noexcept.h>
#include <cstdint>
namespace beast {
//==============================================================================
/**
Simple class to hold a primitive value and perform atomic operations on it.
The type used must be a 32 or 64 bit primitive, like an int, pointer, etc.
There are methods to perform most of the basic atomic operations.
*/
template <typename Type>
class Atomic
{
// This class can only be used for types which are 32 or 64 bits in size.
static_assert (sizeof (Type) == 4 || sizeof (Type) == 8,
"Atomic arguments must be 32- or 64-bit long primitive types.");
public:
/** Creates a new value, initialised to zero. */
inline Atomic() noexcept
: value (0)
{
}
/** Creates a new value, with a given initial value. */
inline Atomic (const Type initialValue) noexcept
: value (initialValue)
{
}
/** Copies another value (atomically). */
inline Atomic (const Atomic& other) noexcept
: value (other.get())
{
}
/** Destructor. */
inline ~Atomic() noexcept
{
}
/** Atomically reads and returns the current value. */
Type get() const noexcept;
/** Copies another value onto this one (atomically). */
Atomic& operator= (const Atomic& other) noexcept
{ exchange (other.get()); return *this; }
/** Copies another value onto this one (atomically). */
Atomic& operator= (const Type newValue) noexcept
{ exchange (newValue); return *this; }
/** Atomically sets the current value. */
void set (Type newValue) noexcept
{ exchange (newValue); }
/** Atomically sets the current value, returning the value that was replaced. */
Type exchange (Type value) noexcept;
/** Atomically adds a number to this value, returning the new value. */
Type operator+= (Type amountToAdd) noexcept;
/** Atomically subtracts a number from this value, returning the new value. */
Type operator-= (Type amountToSubtract) noexcept;
/** Atomically increments this value, returning the new value. */
Type operator++() noexcept;
/** Atomically decrements this value, returning the new value. */
Type operator--() noexcept;
/** Atomically compares this value with a target value, and if it is equal, sets
this to be equal to a new value.
This operation is the atomic equivalent of doing this:
@code
bool compareAndSetBool (Type newValue, Type valueToCompare)
{
if (get() == valueToCompare)
{
set (newValue);
return true;
}
return false;
}
@endcode
@returns true if the comparison was true and the value was replaced; false if
the comparison failed and the value was left unchanged.
@see compareAndSetValue
*/
bool compareAndSetBool (Type newValue, Type valueToCompare) noexcept;
/** Atomically compares this value with a target value, and if it is equal, sets
this to be equal to a new value.
This operation is the atomic equivalent of doing this:
@code
Type compareAndSetValue (Type newValue, Type valueToCompare)
{
Type oldValue = get();
if (oldValue == valueToCompare)
set (newValue);
return oldValue;
}
@endcode
@returns the old value before it was changed.
@see compareAndSetBool
*/
Type compareAndSetValue (Type newValue, Type valueToCompare) noexcept;
//==============================================================================
#if BEAST_64BIT
BEAST_ALIGN (8)
#else
BEAST_ALIGN (4)
#endif
/** The raw value that this class operates on.
This is exposed publically in case you need to manipulate it directly
for performance reasons.
*/
volatile Type value;
private:
template <typename Dest, typename Source>
static inline Dest castTo (Source value) noexcept { union { Dest d; Source s; } u; u.s = value; return u.d; }
static inline Type castFrom32Bit (std::int32_t value) noexcept { return castTo <Type, std::int32_t> (value); }
static inline Type castFrom64Bit (std::int64_t value) noexcept { return castTo <Type, std::int64_t> (value); }
static inline std::int32_t castTo32Bit (Type value) noexcept { return castTo <std::int32_t, Type> (value); }
static inline std::int64_t castTo64Bit (Type value) noexcept { return castTo <std::int64_t, Type> (value); }
Type operator++ (int); // better to just use pre-increment with atomics..
Type operator-- (int);
/** This templated negate function will negate pointers as well as integers */
template <typename ValueType>
inline ValueType negateValue (ValueType n) noexcept
{
return sizeof (ValueType) == 1 ? (ValueType) -(signed char) n
: (sizeof (ValueType) == 2 ? (ValueType) -(short) n
: (sizeof (ValueType) == 4 ? (ValueType) -(int) n
: ((ValueType) -(std::int64_t) n)));
}
/** This templated negate function will negate pointers as well as integers */
template <typename PointerType>
inline PointerType* negateValue (PointerType* n) noexcept
{
return reinterpret_cast <PointerType*> (-reinterpret_cast <std::intptr_t> (n));
}
};
//==============================================================================
/*
The following code is in the header so that the atomics can be inlined where possible...
*/
#if BEAST_IOS || (BEAST_MAC && (BEAST_PPC || BEAST_CLANG || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2)))
#define BEAST_ATOMICS_MAC 1 // Older OSX builds using gcc4.1 or earlier
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
#define BEAST_MAC_ATOMICS_VOLATILE
#else
#define BEAST_MAC_ATOMICS_VOLATILE volatile
#endif
#if BEAST_PPC || BEAST_IOS
// None of these atomics are available for PPC or for iOS 3.1 or earlier!!
template <typename Type> static Type OSAtomicAdd64Barrier (Type b, BEAST_MAC_ATOMICS_VOLATILE Type* a) noexcept { bassertfalse; return *a += b; }
template <typename Type> static Type OSAtomicIncrement64Barrier (BEAST_MAC_ATOMICS_VOLATILE Type* a) noexcept { bassertfalse; return ++*a; }
template <typename Type> static Type OSAtomicDecrement64Barrier (BEAST_MAC_ATOMICS_VOLATILE Type* a) noexcept { bassertfalse; return --*a; }
template <typename Type> static bool OSAtomicCompareAndSwap64Barrier (Type old, Type newValue, BEAST_MAC_ATOMICS_VOLATILE Type* value) noexcept
{ bassertfalse; if (old == *value) { *value = newValue; return true; } return false; }
#define BEAST_64BIT_ATOMICS_UNAVAILABLE 1
#endif
#elif BEAST_CLANG && BEAST_LINUX
#define BEAST_ATOMICS_GCC 1
//==============================================================================
#elif BEAST_GCC
#define BEAST_ATOMICS_GCC 1 // GCC with intrinsics
#if BEAST_IOS || BEAST_ANDROID // (64-bit ops will compile but not link on these mobile OSes)
#define BEAST_64BIT_ATOMICS_UNAVAILABLE 1
#endif
//==============================================================================
#else
#define BEAST_ATOMICS_WINDOWS 1 // Windows with intrinsics
#if BEAST_USE_INTRINSICS
#ifndef __INTEL_COMPILER
#pragma intrinsic (_InterlockedExchange, _InterlockedIncrement, _InterlockedDecrement, _InterlockedCompareExchange, \
_InterlockedCompareExchange64, _InterlockedExchangeAdd, _ReadWriteBarrier)
#endif
#define beast_InterlockedExchange(a, b) _InterlockedExchange(a, b)
#define beast_InterlockedIncrement(a) _InterlockedIncrement(a)
#define beast_InterlockedDecrement(a) _InterlockedDecrement(a)
#define beast_InterlockedExchangeAdd(a, b) _InterlockedExchangeAdd(a, b)
#define beast_InterlockedCompareExchange(a, b, c) _InterlockedCompareExchange(a, b, c)
#define beast_InterlockedCompareExchange64(a, b, c) _InterlockedCompareExchange64(a, b, c)
#define beast_MemoryBarrier _ReadWriteBarrier
#else
long beast_InterlockedExchange (volatile long* a, long b) noexcept;
long beast_InterlockedIncrement (volatile long* a) noexcept;
long beast_InterlockedDecrement (volatile long* a) noexcept;
long beast_InterlockedExchangeAdd (volatile long* a, long b) noexcept;
long beast_InterlockedCompareExchange (volatile long* a, long b, long c) noexcept;
__int64 beast_InterlockedCompareExchange64 (volatile __int64* a, __int64 b, __int64 c) noexcept;
inline void beast_MemoryBarrier() noexcept { long x = 0; beast_InterlockedIncrement (&x); }
#endif
#if BEAST_64BIT
#ifndef __INTEL_COMPILER
#pragma intrinsic (_InterlockedExchangeAdd64, _InterlockedExchange64, _InterlockedIncrement64, _InterlockedDecrement64)
#endif
#define beast_InterlockedExchangeAdd64(a, b) _InterlockedExchangeAdd64(a, b)
#define beast_InterlockedExchange64(a, b) _InterlockedExchange64(a, b)
#define beast_InterlockedIncrement64(a) _InterlockedIncrement64(a)
#define beast_InterlockedDecrement64(a) _InterlockedDecrement64(a)
#else
// None of these atomics are available in a 32-bit Windows build!!
template <typename Type> static Type beast_InterlockedExchangeAdd64 (volatile Type* a, Type b) noexcept { bassertfalse; Type old = *a; *a += b; return old; }
template <typename Type> static Type beast_InterlockedExchange64 (volatile Type* a, Type b) noexcept { bassertfalse; Type old = *a; *a = b; return old; }
template <typename Type> static Type beast_InterlockedIncrement64 (volatile Type* a) noexcept { bassertfalse; return ++*a; }
template <typename Type> static Type beast_InterlockedDecrement64 (volatile Type* a) noexcept { bassertfalse; return --*a; }
#define BEAST_64BIT_ATOMICS_UNAVAILABLE 1
#endif
#endif
#if BEAST_MSVC
#pragma warning (push)
#pragma warning (disable: 4311) // (truncation warning)
#endif
//==============================================================================
template <typename Type>
inline Type Atomic<Type>::get() const noexcept
{
#if BEAST_ATOMICS_MAC
return sizeof (Type) == 4 ? castFrom32Bit ((std::int32_t) OSAtomicAdd32Barrier ((int32_t) 0, (BEAST_MAC_ATOMICS_VOLATILE int32_t*) &value))
: castFrom64Bit ((std::int64_t) OSAtomicAdd64Barrier ((int64_t) 0, (BEAST_MAC_ATOMICS_VOLATILE int64_t*) &value));
#elif BEAST_ATOMICS_WINDOWS
return sizeof (Type) == 4 ? castFrom32Bit ((std::int32_t) beast_InterlockedExchangeAdd ((volatile long*) &value, (long) 0))
: castFrom64Bit ((std::int64_t) beast_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) 0));
#elif BEAST_ATOMICS_GCC
return sizeof (Type) == 4 ? castFrom32Bit ((std::int32_t) __sync_add_and_fetch ((volatile std::int32_t*) &value, 0))
: castFrom64Bit ((std::int64_t) __sync_add_and_fetch ((volatile std::int64_t*) &value, 0));
#endif
}
template <typename Type>
inline Type Atomic<Type>::exchange (const Type newValue) noexcept
{
#if BEAST_ATOMICS_MAC || BEAST_ATOMICS_GCC
Type currentVal = value;
while (! compareAndSetBool (newValue, currentVal)) { currentVal = value; }
return currentVal;
#elif BEAST_ATOMICS_WINDOWS
return sizeof (Type) == 4 ? castFrom32Bit ((std::int32_t) beast_InterlockedExchange ((volatile long*) &value, (long) castTo32Bit (newValue)))
: castFrom64Bit ((std::int64_t) beast_InterlockedExchange64 ((volatile __int64*) &value, (__int64) castTo64Bit (newValue)));
#endif
}
template <typename Type>
inline Type Atomic<Type>::operator+= (const Type amountToAdd) noexcept
{
#if BEAST_ATOMICS_MAC
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"
# pragma clang diagnostic ignored "-Wint-to-pointer-cast"
# endif
return sizeof (Type) == 4 ? (Type) OSAtomicAdd32Barrier ((int32_t) castTo32Bit (amountToAdd), (BEAST_MAC_ATOMICS_VOLATILE int32_t*) &value)
: (Type) OSAtomicAdd64Barrier ((int64_t) amountToAdd, (BEAST_MAC_ATOMICS_VOLATILE int64_t*) &value);
# ifdef __clang__
# pragma clang diagnostic pop
# endif
#elif BEAST_ATOMICS_WINDOWS
return sizeof (Type) == 4 ? (Type) (beast_InterlockedExchangeAdd ((volatile long*) &value, (long) amountToAdd) + (long) amountToAdd)
: (Type) (beast_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) amountToAdd) + (__int64) amountToAdd);
#elif BEAST_ATOMICS_GCC
return (Type) __sync_add_and_fetch (&value, amountToAdd);
#endif
}
template <typename Type>
inline Type Atomic<Type>::operator-= (const Type amountToSubtract) noexcept
{
return operator+= (negateValue (amountToSubtract));
}
template <typename Type>
inline Type Atomic<Type>::operator++() noexcept
{
#if BEAST_ATOMICS_MAC
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"
# pragma clang diagnostic ignored "-Wint-to-pointer-cast"
# endif
return sizeof (Type) == 4 ? (Type) OSAtomicIncrement32Barrier ((BEAST_MAC_ATOMICS_VOLATILE int32_t*) &value)
: (Type) OSAtomicIncrement64Barrier ((BEAST_MAC_ATOMICS_VOLATILE int64_t*) &value);
# ifdef __clang__
# pragma clang diagnostic pop
# endif
#elif BEAST_ATOMICS_WINDOWS
return sizeof (Type) == 4 ? (Type) beast_InterlockedIncrement ((volatile long*) &value)
: (Type) beast_InterlockedIncrement64 ((volatile __int64*) &value);
#elif BEAST_ATOMICS_GCC
return (Type) __sync_add_and_fetch (&value, (Type) 1);
#endif
}
template <typename Type>
inline Type Atomic<Type>::operator--() noexcept
{
#if BEAST_ATOMICS_MAC
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"
# pragma clang diagnostic ignored "-Wint-to-pointer-cast"
# endif
return sizeof (Type) == 4 ? (Type) OSAtomicDecrement32Barrier ((BEAST_MAC_ATOMICS_VOLATILE int32_t*) &value)
: (Type) OSAtomicDecrement64Barrier ((BEAST_MAC_ATOMICS_VOLATILE int64_t*) &value);
# ifdef __clang__
# pragma clang diagnostic pop
# endif
#elif BEAST_ATOMICS_WINDOWS
return sizeof (Type) == 4 ? (Type) beast_InterlockedDecrement ((volatile long*) &value)
: (Type) beast_InterlockedDecrement64 ((volatile __int64*) &value);
#elif BEAST_ATOMICS_GCC
return (Type) __sync_add_and_fetch (&value, (Type) -1);
#endif
}
template <typename Type>
inline bool Atomic<Type>::compareAndSetBool (const Type newValue, const Type valueToCompare) noexcept
{
#if BEAST_ATOMICS_MAC
return sizeof (Type) == 4 ? OSAtomicCompareAndSwap32Barrier ((int32_t) castTo32Bit (valueToCompare), (int32_t) castTo32Bit (newValue), (BEAST_MAC_ATOMICS_VOLATILE int32_t*) &value)
: OSAtomicCompareAndSwap64Barrier ((int64_t) castTo64Bit (valueToCompare), (int64_t) castTo64Bit (newValue), (BEAST_MAC_ATOMICS_VOLATILE int64_t*) &value);
#elif BEAST_ATOMICS_WINDOWS
return compareAndSetValue (newValue, valueToCompare) == valueToCompare;
#elif BEAST_ATOMICS_GCC
return sizeof (Type) == 4 ? __sync_bool_compare_and_swap ((volatile std::int32_t*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue))
: __sync_bool_compare_and_swap ((volatile std::int64_t*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue));
#endif
}
template <typename Type>
inline Type Atomic<Type>::compareAndSetValue (const Type newValue, const Type valueToCompare) noexcept
{
#if BEAST_ATOMICS_MAC
for (;;) // Annoying workaround for only having a bool CAS operation..
{
if (compareAndSetBool (newValue, valueToCompare))
return valueToCompare;
const Type result = value;
if (result != valueToCompare)
return result;
}
#elif BEAST_ATOMICS_WINDOWS
return sizeof (Type) == 4 ? castFrom32Bit ((std::int32_t) beast_InterlockedCompareExchange ((volatile long*) &value, (long) castTo32Bit (newValue), (long) castTo32Bit (valueToCompare)))
: castFrom64Bit ((std::int64_t) beast_InterlockedCompareExchange64 ((volatile __int64*) &value, (__int64) castTo64Bit (newValue), (__int64) castTo64Bit (valueToCompare)));
#elif BEAST_ATOMICS_GCC
return sizeof (Type) == 4 ? castFrom32Bit ((std::int32_t) __sync_val_compare_and_swap ((volatile std::int32_t*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue)))
: castFrom64Bit ((std::int64_t) __sync_val_compare_and_swap ((volatile std::int64_t*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue)));
#endif
}
inline void memoryBarrier() noexcept
{
#if BEAST_ATOMICS_MAC
OSMemoryBarrier();
#elif BEAST_ATOMICS_GCC
__sync_synchronize();
#elif BEAST_ATOMICS_WINDOWS
beast_MemoryBarrier();
#endif
}
#if BEAST_MSVC
#pragma warning (pop)
#endif
}
#endif

View File

@@ -26,9 +26,6 @@
// VFALCO NOTE this is analogous to <boost/config.hpp>
// Assert to boost that we always have std::array support
#define BOOST_ASIO_HAS_STD_ARRAY 1
#if !defined(BEAST_COMPILER_CONFIG) && !defined(BEAST_NO_COMPILER_CONFIG) && !defined(BEAST_NO_CONFIG)
#include <beast/config/SelectCompilerConfig.h>
#endif

View File

@@ -20,7 +20,6 @@
#ifndef BEAST_CRYPTO_H_INCLUDED
#define BEAST_CRYPTO_H_INCLUDED
#include <beast/crypto/MurmurHash.h>
#include <beast/crypto/Sha256.h>
#endif

View File

@@ -25,11 +25,9 @@
#include <beast/threads/SharedLockGuard.h>
#include <beast/threads/SharedMutexAdapter.h>
#include <beast/threads/SharedData.h>
#include <beast/threads/ServiceQueue.h>
#include <beast/threads/SpinLock.h>
#include <beast/threads/Stoppable.h>
#include <beast/threads/Thread.h>
#include <beast/threads/ThreadLocalValue.h>
#include <beast/threads/WaitableEvent.h>
#include <beast/threads/ScopedWrapperContext.h>

View File

@@ -23,4 +23,5 @@
#include <beast/asio/impl/IPAddressConversion.cpp>
#include <beast/asio/tests/bind_handler.test.cpp>
#include <beast/asio/tests/streambuf.test.cpp>

View File

@@ -21,7 +21,9 @@
#define BEAST_ASIO_SSL_BUNDLE_H_INCLUDED
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ssl/context.hpp>
#include <boost/asio/ssl/stream.hpp>
#include <memory>
#include <utility>
namespace beast {
@@ -33,21 +35,33 @@ namespace asio {
*/
struct ssl_bundle
{
typedef boost::asio::ip::tcp::socket socket_type;
typedef boost::asio::ssl::stream <socket_type&> stream_type;
using socket_type = boost::asio::ip::tcp::socket;
using stream_type = boost::asio::ssl::stream <socket_type&>;
using shared_context = std::shared_ptr<boost::asio::ssl::context>;
template <class... Args>
ssl_bundle (boost::asio::ssl::context& context, Args&&... args);
ssl_bundle (shared_context const& context_, Args&&... args);
// DEPRECATED
template <class... Args>
ssl_bundle (boost::asio::ssl::context& context_, Args&&... args);
shared_context context;
socket_type socket;
stream_type stream;
};
template <class... Args>
ssl_bundle::ssl_bundle (boost::asio::ssl::context& context,
Args&&... args)
ssl_bundle::ssl_bundle (shared_context const& context_, Args&&... args)
: socket(std::forward<Args>(args)...)
, stream (socket, context)
, stream (socket, *context_)
{
}
template <class... Args>
ssl_bundle::ssl_bundle (boost::asio::ssl::context& context_, Args&&... args)
: socket(std::forward<Args>(args)...)
, stream (socket, context_)
{
}

View File

@@ -0,0 +1,679 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_ASIO_STREAMBUF_H_INCLUDED
#define BEAST_ASIO_STREAMBUF_H_INCLUDED
#include <beast/utility/empty_base_optimization.h>
#include <boost/asio/buffer.hpp>
#include <boost/intrusive/list.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <algorithm>
#include <cassert>
#include <memory>
#include <exception>
#include <beast/cxx14/type_traits.h> // <type_traits>
#include <string>
#include <utility>
namespace beast {
namespace asio {
/** Implements asio::streambuf interface using multiple buffers. */
template <class Allocator>
class basic_streambuf
: private empty_base_optimization<Allocator>
{
public:
using size_type = typename std::allocator_traits<Allocator>::size_type;
using const_buffer = boost::asio::const_buffer;
using mutable_buffer = boost::asio::mutable_buffer;
private:
class element;
using alloc_traits = std::allocator_traits<Allocator>;
using list_type = typename boost::intrusive::make_list <element,
boost::intrusive::constant_time_size <true>>::type;
using iterator = typename list_type::iterator;
using const_iterator = typename list_type::const_iterator;
/* These diagrams illustrate the layout and state variables.
Input and output contained entirely in one element:
0 out_
|<-------------+------------------------------------------->|
in_pos_ out_pos_ out_end_
Output contained in first and second elements:
out_
|<------+----------+------->| |<----------+-------------->|
in_pos_ out_pos_ out_end_
Output contained in the second element:
out_
|<------------+------------>| |<----+-------------------->|
in_pos_ out_pos_ out_end_
Output contained in second and third elements:
out_
|<-----+-------->| |<-------+------>| |<--------------->|
in_pos_ out_pos_ out_end_
Input sequence is empty:
out_
|<------+------------------>| |<-----------+------------->|
out_pos_ out_end_
in_pos_
Output sequence is empty:
out_
|<------+------------------>| |<------+------------------>|
in_pos_ out_pos_
out_end_
The end of output can point to the end of an element.
But out_pos_ should never point to the end:
out_
|<------+------------------>| |<------+------------------>|
in_pos_ out_pos_ out_end_
When the input sequence entirely fills the last element and
the output sequence is empty, out_ will point to the end of
the list of buffers, and out_pos_ and out_end_ will be 0:
|<------+------------------>| out_ == list_.end()
in_pos_ out_pos_ == 0
out_end_ == 0
*/
list_type list_;
size_type block_size_;
size_type block_size_next_;
size_type in_size_ = 0; // size of the input sequence
iterator out_; // element that contains out_pos_
size_type in_pos_ = 0; // input offset in list_.front()
size_type out_pos_ = 0; // output offset in *out_
size_type out_end_ = 0; // output end offset in list_.back()
public:
class const_buffers_type;
class mutable_buffers_type;
basic_streambuf (basic_streambuf const& other) = delete;
basic_streambuf& operator= (basic_streambuf const& other) = delete;
basic_streambuf& operator= (basic_streambuf&& other) = delete;
~basic_streambuf();
explicit
basic_streambuf(std::size_t block_size = 16*1024,
Allocator const& alloc = Allocator{});
basic_streambuf (basic_streambuf&& other);
/** Get the maximum size of the basic_streambuf. */
size_type
max_size() const
{
return std::numeric_limits<std::size_t>::max();
}
/** Get the size of the input sequence. */
size_type
size() const
{
return in_size_;
}
/** Get a list of buffers that represents the output sequence, with the given size. */
mutable_buffers_type
prepare (size_type n);
/** Move bytes from the output sequence to the input sequence. */
void
commit (size_type n);
/** Get a list of buffers that represents the input sequence. */
const_buffers_type
data() const;
/** Remove bytes from the input sequence. */
void
consume (size_type n);
private:
void
debug_check() const;
};
//------------------------------------------------------------------------------
template <class Allocator>
class basic_streambuf<Allocator>::element
: public boost::intrusive::list_base_hook <
boost::intrusive::link_mode <boost::intrusive::normal_link>>
{
private:
size_type const size_; // size of the allocation minus sizeof(element)
public:
element (element const&) = delete;
element& operator= (element const&) = delete;
explicit
element (size_type block_size)
: size_(block_size)
{ }
size_type
size() const
{
return size_;
}
size_type
alloc_size() const
{
return size_ + sizeof(*this);
}
char*
data() const
{
return const_cast<char*>(
reinterpret_cast<char const*>(this+1));
}
};
//------------------------------------------------------------------------------
template <class Allocator>
class basic_streambuf<Allocator>::const_buffers_type
{
public:
using value_type = const_buffer;
private:
struct transform
{
using argument_type = element;
using result_type = value_type;
basic_streambuf const* streambuf_ = nullptr;
transform() = default;
explicit
transform (basic_streambuf const& streambuf)
: streambuf_ (&streambuf)
{
}
value_type const
operator() (element const& e) const;
};
basic_streambuf const* streambuf_ = nullptr;
public:
using const_iterator = boost::transform_iterator<
transform, typename list_type::const_iterator,
value_type, value_type>;
const_buffers_type() = default;
const_buffers_type (const_buffers_type const&) = default;
const_buffers_type& operator= (const_buffers_type const&) = default;
const_iterator
begin() const
{
return const_iterator (streambuf_->list_.begin(),
transform(*streambuf_));
}
const_iterator
end() const
{
return const_iterator (streambuf_->out_ ==
streambuf_->list_.end() ? streambuf_->list_.end() :
std::next(streambuf_->out_), transform(*streambuf_));
}
private:
friend class basic_streambuf;
explicit
const_buffers_type (basic_streambuf const& streambuf);
};
template <class Allocator>
basic_streambuf<Allocator>::const_buffers_type::const_buffers_type (
basic_streambuf const& streambuf)
: streambuf_ (&streambuf)
{
}
template <class Allocator>
auto
basic_streambuf<Allocator>::const_buffers_type::
transform::operator() (element const& e) const ->
value_type const
{
return value_type (e.data(),
(streambuf_->out_ == streambuf_->list_.end() ||
&e != &*streambuf_->out_) ? e.size() : streambuf_->out_pos_) +
(&e == &*streambuf_->list_.begin() ?
streambuf_->in_pos_ : 0);
}
//------------------------------------------------------------------------------
template <class Allocator>
class basic_streambuf<Allocator>::mutable_buffers_type
{
public:
using value_type = mutable_buffer;
private:
struct transform
{
using argument_type = element;
using result_type = value_type;
basic_streambuf const* streambuf_ = nullptr;
transform() = default;
explicit
transform (basic_streambuf const& streambuf)
: streambuf_ (&streambuf)
{
}
value_type const
operator() (element const& e) const;
};
basic_streambuf const* streambuf_;
public:
using const_iterator = boost::transform_iterator<
transform, typename list_type::const_iterator,
value_type, value_type>;
mutable_buffers_type() = default;
mutable_buffers_type (mutable_buffers_type const&) = default;
mutable_buffers_type& operator= (mutable_buffers_type const&) = default;
const_iterator
begin() const
{
return const_iterator (streambuf_->out_,
transform(*streambuf_));
}
const_iterator
end() const
{
return const_iterator (streambuf_->list_.end(),
transform(*streambuf_));
}
private:
friend class basic_streambuf;
mutable_buffers_type (basic_streambuf const& streambuf);
};
template <class Allocator>
basic_streambuf<Allocator>::mutable_buffers_type::mutable_buffers_type (
basic_streambuf const& streambuf)
: streambuf_ (&streambuf)
{
}
template <class Allocator>
auto
basic_streambuf<Allocator>::mutable_buffers_type::
transform::operator() (element const& e) const ->
value_type const
{
return value_type (e.data(), &e == &*std::prev(streambuf_->list_.end()) ?
streambuf_->out_end_ : e.size()) + (&e == &*streambuf_->out_ ?
streambuf_->out_pos_ : 0);
}
//------------------------------------------------------------------------------
template <class Allocator>
basic_streambuf<Allocator>::~basic_streambuf()
{
for(auto iter = list_.begin(); iter != list_.end();)
{
auto& e = *iter++;
size_type const n = e.alloc_size();
alloc_traits::destroy(this->member(), &e);
alloc_traits::deallocate(this->member(),
reinterpret_cast<char*>(&e), n);
}
}
template <class Allocator>
basic_streambuf<Allocator>::basic_streambuf(std::size_t block_size,
Allocator const& alloc)
: empty_base_optimization<Allocator>(alloc)
, block_size_ (block_size)
, block_size_next_ (block_size)
, out_ (list_.end())
{
if (! (block_size > 0))
throw std::invalid_argument(
"basic_streambuf: invalid block_size");
}
template <class Allocator>
basic_streambuf<Allocator>::basic_streambuf (basic_streambuf&& other)
: empty_base_optimization<Allocator>(other.member())
, list_ (std::move(other.list_))
, block_size_ (other.block_size_)
, block_size_next_ (other.block_size_next_)
, in_size_ (other.in_size_)
, out_ (other.out_)
, in_pos_ (other.in_pos_)
, out_pos_ (other.out_pos_)
, out_end_ (other.out_end_)
{
other.in_size_ = 0;
other.out_ = other.list_.end();
other.in_pos_ = 0;
other.out_pos_ = 0;
other.out_end_ = 0;
}
template <class Allocator>
auto
basic_streambuf<Allocator>::prepare (size_type n) ->
mutable_buffers_type
{
iterator pos = out_;
if (pos != list_.end())
{
auto const avail = pos->size() - out_pos_;
if (n > avail)
{
n -= avail;
while (++pos != list_.end())
{
if (n < pos->size())
{
out_end_ = n;
n = 0;
++pos;
break;
}
n -= pos->size();
}
}
else
{
++pos;
out_end_ = out_pos_ + n;
n = 0;
}
debug_check();
}
if (n > 0)
{
assert(pos == list_.end());
for(;;)
{
auto const avail = block_size_next_;
auto& e = *reinterpret_cast<element*>(alloc_traits::allocate(
this->member(), avail + sizeof(element)));
alloc_traits::construct(this->member(), &e, avail);
list_.push_back(e);
if (out_ == list_.end())
{
out_ = list_.iterator_to(e);
debug_check();
}
if (n <= avail)
{
out_end_ = n;
debug_check();
break;
}
n -= avail;
}
}
else
{
while (pos != list_.end())
{
auto& e = *pos++;
list_.erase(list_.iterator_to(e));
auto const len = e.alloc_size();
alloc_traits::destroy(this->member(), &e);
alloc_traits::deallocate(this->member(),
reinterpret_cast<char*>(&e), len);
}
debug_check();
}
return mutable_buffers_type (*this);
}
template <class Allocator>
void
basic_streambuf<Allocator>::commit (size_type n)
{
if (list_.empty())
return;
if (out_ == list_.end())
return;
auto const last = std::prev(list_.end());
while (out_ != last)
{
auto const avail =
out_->size() - out_pos_;
if (n < avail)
{
out_pos_ += n;
in_size_ += n;
debug_check();
return;
}
++out_;
n -= avail;
out_pos_ = 0;
in_size_ += avail;
debug_check();
}
n = std::min (n, out_end_ - out_pos_);
out_pos_ += n;
in_size_ += n;
if (out_pos_ == out_->size())
{
++out_;
out_pos_ = 0;
out_end_ = 0;
}
debug_check();
}
template <class Allocator>
auto
basic_streambuf<Allocator>::data() const ->
const_buffers_type
{
return const_buffers_type(*this);
}
template <class Allocator>
void
basic_streambuf<Allocator>::consume (size_type n)
{
if (list_.empty())
return;
auto pos = list_.begin();
for(;;)
{
if (pos != out_)
{
auto const avail = pos->size() - in_pos_;
if (n < avail)
{
in_size_ -= n;
in_pos_ += n;
debug_check();
break;
}
n -= avail;
in_size_ -= avail;
in_pos_ = 0;
debug_check();
element& e = *pos++;
list_.erase(list_.iterator_to(e));
size_type const len = e.alloc_size();
alloc_traits::destroy(this->member(), &e);
alloc_traits::deallocate(this->member(),
reinterpret_cast<char*>(&e), len);
}
else
{
auto const avail = out_pos_ - in_pos_;
if (n < avail)
{
in_size_ -= n;
in_pos_ += n;
}
else
{
in_size_ -= avail;
if (out_pos_ != out_end_||
out_ != list_.iterator_to(list_.back()))
{
in_pos_ = out_pos_;
}
else
{
// Use the whole buffer now.
// Alternatively we could deallocate it.
in_pos_ = 0;
out_pos_ = 0;
out_end_ = 0;
}
}
debug_check();
break;
}
}
}
template <class Allocator>
void
basic_streambuf<Allocator>::debug_check() const
{
#ifndef NDEBUG
if (list_.empty())
{
assert(in_pos_ == 0);
assert(in_size_ == 0);
assert(out_pos_ == 0);
assert(out_end_ == 0);
assert(out_ == list_.end());
return;
}
auto const& front = list_.front();
assert(in_pos_ < front.size());
if (out_ == list_.end())
{
assert(out_pos_ == 0);
assert(out_end_ == 0);
}
else
{
auto const& out = *out_;
auto const& back = list_.back();
assert(out_end_ <= back.size());
assert(out_pos_ < out.size());
assert(&out != &front || out_pos_ >= in_pos_);
assert(&out != &front || out_pos_ - in_pos_ == in_size_);
assert(&out != &back || out_pos_ <= out_end_);
}
#endif
}
template <class Alloc, class T>
basic_streambuf<Alloc>&
operator<< (basic_streambuf<Alloc>& buf, T const& t)
{
std::stringstream ss;
ss << t;
auto const& s = ss.str();
buf.commit(boost::asio::buffer_copy(
buf.prepare(s.size()), boost::asio::buffer(s)));
return buf;
}
//------------------------------------------------------------------------------
using streambuf = basic_streambuf<std::allocator<char>>;
/** Convert the entire basic_streambuf to a string.
@note It is more efficient to deal directly in the streambuf instead.
*/
template <class Allocator>
std::string
to_string (basic_streambuf<Allocator> const& buf)
{
std::string s;
s.resize(buf.size());
boost::asio::buffer_copy(boost::asio::buffer(
&s[0], s.size()), buf.data());
return s;
}
}
}
#endif

View File

@@ -0,0 +1,158 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <beast/asio/streambuf.h>
#include <beast/unit_test/suite.h>
namespace beast {
namespace asio {
class streambuf_test : public unit_test::suite
{
public:
// Convert a buffer sequence to a string
template <class Buffers>
static
std::string
to_str (Buffers const& b)
{
std::string s;
auto const n = boost::asio::buffer_size(b);
s.resize(n);
boost::asio::buffer_copy(
boost::asio::buffer(&s[0], n), b);
return s;
}
// Fill a buffer sequence with predictable data
template <class Buffers>
static
void
fill (Buffers const& b)
{
char c = 0;
auto first = boost::asio::buffers_begin(b);
auto last = boost::asio::buffers_end(b);
while (first != last)
*first++ = c++;
}
// Check that a buffer sequence has predictable data
template <class Buffers>
void
check (Buffers const& b, char c = 0)
{
auto first = boost::asio::buffers_begin(b);
auto last = boost::asio::buffers_end(b);
while (first != last)
expect (*first++ == c++);
}
void
test_prepare()
{
testcase << "prepare";
beast::asio::streambuf b(11);
for (std::size_t n = 0; n < 97; ++n)
{
fill(b.prepare(n));
b.commit(n);
check(b.data());
b.consume(n);
}
}
void
test_commit()
{
testcase << "commit";
beast::asio::streambuf b(11);
for (std::size_t n = 0; n < 97; ++n)
{
fill(b.prepare(n));
char c = 0;
for (int i = 1;; ++i)
{
b.commit(i);
check(b.data(), c);
b.consume(i);
if (b.size() < 1)
break;
c += i;
}
}
}
void
test_consume()
{
testcase << "consume";
beast::asio::streambuf b(11);
for (std::size_t n = 0; n < 97; ++n)
{
fill(b.prepare(n));
b.commit(n);
char c = 0;
for (int i = 1; b.size() > 0; ++i)
{
check(b.data(), c);
b.consume(i);
c += i;
}
}
}
void run()
{
{
beast::asio::streambuf b(10);
std::string const s = "1234567890";
b << s;
expect (to_str(b.data()) == s);
b.prepare(5);
}
{
beast::asio::streambuf b(10);
b.prepare(10);
b.commit(10);
b.consume(10);
}
{
beast::asio::streambuf b(5);
boost::asio::buffer_copy(b.prepare(14),
boost::asio::buffer(std::string("1234567890ABCD")));
b.commit(4);
expect(to_str(b.data()) == "1234");
b.consume(4);
b.commit(10);
expect(to_str(b.data()) == "567890ABCD");
}
test_prepare();
test_commit();
test_consume();
}
};
BEAST_DEFINE_TESTSUITE(streambuf,asio,beast);
}
}

View File

@@ -0,0 +1,315 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_ASIO_WAITABLE_EXECUTOR_H_INCLUDED
#define BEAST_ASIO_WAITABLE_EXECUTOR_H_INCLUDED
#include <boost/asio/handler_alloc_hook.hpp>
#include <boost/asio/handler_continuation_hook.hpp>
#include <boost/asio/handler_invoke_hook.hpp>
#include <condition_variable>
#include <functional>
#include <memory>
#include <mutex>
#include <beast/cxx14/type_traits.h> // <type_traits>
#include <utility>
#include <vector>
namespace beast {
namespace asio {
namespace detail {
template <class Owner, class Handler>
class waitable_executor_wrapped_handler
{
private:
static_assert (std::is_same <std::decay_t <Owner>, Owner>::value,
"Owner cannot be a const or reference type");
Handler handler_;
std::reference_wrapper <Owner> owner_;
bool cont_;
public:
waitable_executor_wrapped_handler (Owner& owner,
Handler&& handler, bool continuation = false)
: handler_ (std::move(handler))
, owner_ (owner)
{
using boost::asio::asio_handler_is_continuation;
cont_ = continuation ? true :
asio_handler_is_continuation(
std::addressof(handler_));
owner_.get().increment();
}
waitable_executor_wrapped_handler (Owner& owner,
Handler const& handler, bool continuation = false)
: handler_ (handler)
, owner_ (owner)
{
using boost::asio::asio_handler_is_continuation;
cont_ = continuation ? true :
asio_handler_is_continuation(
std::addressof(handler_));
owner_.get().increment();
}
~waitable_executor_wrapped_handler()
{
owner_.get().decrement();
}
waitable_executor_wrapped_handler (
waitable_executor_wrapped_handler const& other)
: handler_ (other.handler_)
, owner_ (other.owner_)
, cont_ (other.cont_)
{
owner_.get().increment();
}
waitable_executor_wrapped_handler (
waitable_executor_wrapped_handler&& other)
: handler_ (std::move(other.handler_))
, owner_ (other.owner_)
, cont_ (other.cont_)
{
owner_.get().increment();
}
waitable_executor_wrapped_handler& operator=(
waitable_executor_wrapped_handler const&) = delete;
template <class... Args>
void
operator()(Args&&... args)
{
handler_(std::forward<Args>(args)...);
}
template <class... Args>
void
operator()(Args&&... args) const
{
handler_(std::forward<Args>(args)...);
}
template <class Function>
friend
void
asio_handler_invoke (Function& f,
waitable_executor_wrapped_handler* h)
{
using boost::asio::asio_handler_invoke;
asio_handler_invoke(f,
std::addressof(h->handler_));
}
template <class Function>
friend
void
asio_handler_invoke (Function const& f,
waitable_executor_wrapped_handler* h)
{
using boost::asio::asio_handler_invoke;
asio_handler_invoke(f,
std::addressof(h->handler_));
}
friend
void*
asio_handler_allocate (std::size_t size,
waitable_executor_wrapped_handler* h)
{
using boost::asio::asio_handler_allocate;
return asio_handler_allocate(
size, std::addressof(h->handler_));
}
friend
void
asio_handler_deallocate (void* p, std::size_t size,
waitable_executor_wrapped_handler* h)
{
using boost::asio::asio_handler_deallocate;
asio_handler_deallocate(
p, size, std::addressof(h->handler_));
}
friend
bool
asio_handler_is_continuation (
waitable_executor_wrapped_handler* h)
{
return h->cont_;
}
};
} // detail
//------------------------------------------------------------------------------
/** Executor which provides blocking until all handlers are called. */
class waitable_executor
{
private:
template <class, class>
friend class detail::waitable_executor_wrapped_handler;
std::mutex mutex_;
std::condition_variable cond_;
std::size_t count_ = 0;
std::vector<std::function<void(void)>> notify_;
public:
/** Block until all handlers are called. */
template <class = void>
void
wait();
/** Blocks until all handlers are called or time elapses.
@return `true` if all handlers are done or `false` if the time elapses.
*/
template <class Rep, class Period>
bool
wait_for (std::chrono::duration<
Rep, Period> const& elapsed_time);
/** Blocks until all handlers are called or a time is reached.
@return `true` if all handlers are done or `false` on timeout.
*/
template <class Clock, class Duration>
bool
wait_until (std::chrono::time_point<
Clock, Duration> const& timeout_time);
/** Call a function asynchronously after all handlers are called.
The function may be called on the callers thread.
*/
template <class = void>
void
async_wait(std::function<void(void)> f);
/** Create a new handler that dispatches the wrapped handler on the Context. */
template <class Handler>
detail::waitable_executor_wrapped_handler<waitable_executor,
std::remove_reference_t<Handler>>
wrap (Handler&& handler);
private:
template <class = void>
void
increment();
template <class = void>
void
decrement();
};
template <class>
void
waitable_executor::wait()
{
std::unique_lock<std::mutex> lock(mutex_);
cond_.wait(lock,
[this]() { return count_ == 0; });
}
template <class Rep, class Period>
bool
waitable_executor::wait_for (std::chrono::duration<
Rep, Period> const& elapsed_time)
{
std::unique_lock<std::mutex> lock(mutex_);
return cond_.wait_for(lock, elapsed_time,
[this]() { return count_ == 0; }) ==
std::cv_status::no_timeout;
}
template <class Clock, class Duration>
bool
waitable_executor::wait_until (std::chrono::time_point<
Clock, Duration> const& timeout_time)
{
std::unique_lock<std::mutex> lock(mutex_);
return cond_.wait_until(lock, timeout_time,
[this]() { return count_ == 0; }) ==
std::cv_status::no_timeout;
return true;
}
template <class>
void
waitable_executor::async_wait(std::function<void(void)> f)
{
bool busy;
{
std::lock_guard<std::mutex> _(mutex_);
busy = count_ > 0;
if (busy)
notify_.emplace_back(std::move(f));
}
if (! busy)
f();
}
template <class Handler>
detail::waitable_executor_wrapped_handler<waitable_executor,
std::remove_reference_t<Handler>>
waitable_executor::wrap (Handler&& handler)
{
return detail::waitable_executor_wrapped_handler<
waitable_executor, std::remove_reference_t<Handler>>(
*this, std::forward<Handler>(handler));
}
template <class>
void
waitable_executor::increment()
{
std::lock_guard<std::mutex> _(mutex_);
++count_;
}
template <class>
void
waitable_executor::decrement()
{
bool notify;
std::vector<std::function<void(void)>> list;
{
std::lock_guard<std::mutex> _(mutex_);
notify = --count_ == 0;
if (notify)
std::swap(list, notify_);
}
if (notify)
{
cond_.notify_all();
for(auto& _ : list)
_();
}
}
} // asio
} // beast
#endif

View File

@@ -27,12 +27,12 @@ namespace beast {
/** Abstract interface to a clock.
The abstract clock interface allows a dependency injection to take
place so that the choice of implementation can be made at run-time
instead of compile time. The trade-off is that the Duration used to
represent the clock must be chosen at compile time and cannot be
changed. This includes both the choice of representation (integers
for example) and the period in ticks corresponding to one second.
This makes now() a member function instead of a static member, so
an instance of the class can be dependency injected, facilitating
unit tests where time may be controlled.
An abstract_clock inherits all the nested types of the Clock
template parameter.
Example:
@@ -40,56 +40,37 @@ namespace beast {
struct Implementation
{
abstract_clock <std::chrono::seconds>& m_clock;
// Dependency injection
//
explicit Implementation (
abstract_clock <std::chrono::seconds>& clock)
: m_clock (clock)
using clock_type = abstract_clock <std::chrono::steady_clock>;
clock_type& clock_;
explicit Implementation (clock_type& clock)
: clock_(clock)
{
}
};
@endcode
@tparam The length of time, in seconds, corresponding to one tick.
@tparam Clock A type meeting these requirements:
http://en.cppreference.com/w/cpp/concept/Clock
*/
template <class Duration>
template <class Clock>
class abstract_clock
{
public:
typedef typename Duration::rep rep;
typedef typename Duration::period period;
typedef Duration duration;
typedef std::chrono::time_point <
abstract_clock, duration> time_point;
using rep = typename Clock::rep;
using period = typename Clock::period;
using duration = typename Clock::duration;
using time_point = typename Clock::time_point;
virtual ~abstract_clock () { }
static bool const is_steady = Clock::is_steady;
/** Returns `true` if this is a steady clock. */
virtual bool is_steady () const = 0;
virtual ~abstract_clock() = default;
/** Returns the current time. */
virtual time_point now () const = 0;
#if 0
/** Convert the specified time point to a string. */
/** @{ */
//virtual std::string to_string (time_point const& tp) const = 0;
template <class Duration2>
std::string to_string (
std::chrono::time_point <abstract_clock, Duration2> const& tp) const
{
return to_string (
std::chrono::time_point_cast <Duration> (tp));
}
/** @} */
#endif
virtual time_point now() const = 0;
/** Returning elapsed ticks since the epoch. */
rep elapsed () const
rep elapsed()
{
return now().time_since_epoch().count();
}
@@ -99,68 +80,34 @@ public:
namespace detail {
template <class TrivialClock, class Duration>
struct basic_abstract_clock_wrapper : public abstract_clock <Duration>
{
using typename abstract_clock <Duration>::duration;
using typename abstract_clock <Duration>::time_point;
bool is_steady () const
{
return TrivialClock::is_steady;
}
time_point now () const
{
return time_point (duration (
std::chrono::duration_cast <duration> (
TrivialClock::now().time_since_epoch ()).count ()));
}
};
template <class TrivialClock, class Duration>
template <class Facade, class Clock>
struct abstract_clock_wrapper
: public basic_abstract_clock_wrapper <TrivialClock, Duration>
: public abstract_clock<Facade>
{
// generic conversion displays the duration
/*
std::string to_string (typename basic_abstract_clock_wrapper <
TrivialClock, Duration>::time_point const& tp) const
{
std::stringstream ss;
ss << tp.time_since_epoch();
return ss.str ();
}
*/
};
using typename abstract_clock<Facade>::duration;
using typename abstract_clock<Facade>::time_point;
/*
template <class Duration>
struct abstract_clock_wrapper <std::chrono::system_clock, Duration>
: public basic_abstract_clock_wrapper <std::chrono::system_clock, Duration>
{
typedef std::chrono::system_clock clock_type;
std::string to_string (time_point const& tp)
time_point
now() const override
{
std::stringstream ss;
ss << clock_type::time_point (tp.time_since_epoch ());
return ss.str ();
return Clock::now();
}
};
*/
}
//------------------------------------------------------------------------------
/** Retrieve a discrete clock for a type implementing the Clock concept.
The interface is created as an object with static storage duration.
/** Returns a global instance of an abstract clock.
@tparam Facade A type meeting these requirements:
http://en.cppreference.com/w/cpp/concept/Clock
@tparam Clock The actual concrete clock to use.
*/
template <class TrivialClock, class Duration>
abstract_clock <Duration>& get_abstract_clock ()
template<class Facade, class Clock = Facade>
abstract_clock<Facade>&
get_abstract_clock()
{
static detail::abstract_clock_wrapper <
TrivialClock, Duration> clock;
static detail::abstract_clock_wrapper<Facade, Clock> clock;
return clock;
}

View File

@@ -45,25 +45,25 @@ public:
class seconds_clock_thread
{
public:
typedef std::mutex mutex;
typedef std::condition_variable cond_var;
typedef std::lock_guard <mutex> lock_guard;
typedef std::unique_lock <mutex> unique_lock;
typedef std::chrono::steady_clock clock_type;
typedef std::chrono::seconds seconds;
typedef std::thread thread;
typedef std::vector <seconds_clock_worker*> workers;
using mutex = std::mutex;
using cond_var = std::condition_variable;
using lock_guard = std::lock_guard <mutex>;
using unique_lock = std::unique_lock <mutex>;
using clock_type = std::chrono::steady_clock;
using seconds = std::chrono::seconds;
using thread = std::thread;
using workers = std::vector <seconds_clock_worker*>;
bool m_stop;
mutex m_mutex;
cond_var m_cond;
workers m_workers;
thread m_thread;
bool stop_;
mutex mutex_;
cond_var cond_;
workers workers_;
thread thread_;
seconds_clock_thread ()
: m_stop (false)
: stop_ (false)
{
m_thread = thread (std::bind(
thread_ = thread (std::bind(
&seconds_clock_thread::run, this));
}
@@ -74,37 +74,37 @@ public:
void add (seconds_clock_worker& w)
{
lock_guard lock (m_mutex);
m_workers.push_back (&w);
lock_guard lock (mutex_);
workers_.push_back (&w);
}
void remove (seconds_clock_worker& w)
{
lock_guard lock (m_mutex);
m_workers.erase (std::find (
m_workers.begin (), m_workers.end(), &w));
lock_guard lock (mutex_);
workers_.erase (std::find (
workers_.begin (), workers_.end(), &w));
}
void stop()
{
if (m_thread.joinable())
if (thread_.joinable())
{
{
lock_guard lock (m_mutex);
m_stop = true;
lock_guard lock (mutex_);
stop_ = true;
}
m_cond.notify_all();
m_thread.join();
cond_.notify_all();
thread_.join();
}
}
void run()
{
unique_lock lock (m_mutex);;
unique_lock lock (mutex_);;
for (;;)
{
for (auto iter : m_workers)
for (auto iter : workers_)
iter->sample();
clock_type::time_point const when (
@@ -112,7 +112,7 @@ public:
clock_type::now().time_since_epoch()) +
seconds (1));
if (m_cond.wait_until (lock, when, [this]{ return m_stop; }))
if (cond_.wait_until (lock, when, [this]{ return stop_; }))
return;
}
}
@@ -143,24 +143,26 @@ basic_seconds_clock_main_hook()
}
/** A clock whose minimum resolution is one second.
The purpose of this class is to optimize the performance of the now()
member function call. It uses a dedicated thread that wakes up at least
once per second to sample the requested trivial clock.
@tparam TrivialClock The clock to sample.
@tparam Clock A type meeting these requirements:
http://en.cppreference.com/w/cpp/concept/Clock
*/
template <class TrivialClock>
template <class Clock>
class basic_seconds_clock
{
public:
typedef std::chrono::seconds resolution;
typedef typename resolution::rep rep;
typedef typename resolution::period period;
typedef std::chrono::duration <rep, period> duration;
typedef std::chrono::time_point <basic_seconds_clock> time_point;
using rep = typename Clock::rep;
using period = typename Clock::period;
using duration = typename Clock::duration;
using time_point = typename Clock::time_point;
static bool const is_steady = TrivialClock::is_steady;
static bool const is_steady = Clock::is_steady;
static time_point now ()
static time_point now()
{
// Make sure the thread is constructed before the
// worker otherwise we will crash during destruction
@@ -176,45 +178,36 @@ public:
struct worker : detail::seconds_clock_worker
{
typedef std::mutex mutex;
typedef std::lock_guard <mutex> lock_guard;
time_point m_now;
mutex m_mutex;
std::mutex mutex_;
static time_point get_now ()
worker()
: m_now(Clock::now())
{
return time_point (floor <resolution> (
TrivialClock::now().time_since_epoch()));
detail::seconds_clock_thread::instance().add(*this);
}
worker ()
: m_now (get_now ())
~worker()
{
detail::seconds_clock_thread::instance().add (*this);
}
~worker ()
{
detail::seconds_clock_thread::instance().remove (*this);
detail::seconds_clock_thread::instance().remove(*this);
}
time_point now()
{
lock_guard lock (m_mutex);
std::lock_guard<std::mutex> lock (mutex_);
return m_now;
}
void sample ()
void sample()
{
lock_guard lock (m_mutex);
m_now = get_now ();
std::lock_guard<std::mutex> lock (mutex_);
m_now = Clock::now();
}
};
static worker w;
return w.now ();
return w.now();
}
};

View File

@@ -32,8 +32,6 @@
#include <beast/utility/noexcept.h>
#include <ctime>
#include <locale>
#define BEAST_CHRONO_NO_TIMEPOINT_IO 1
/*
@@ -798,292 +796,8 @@ time_fmt(timezone f)
return __time_man(f);
}
#if ! BEAST_CHRONO_NO_TIMEPOINT_IO
} // chrono
template <class _CharT, class _Traits, class _Duration>
basic_istream<_CharT, _Traits>&
operator>>(basic_istream<_CharT, _Traits>& __is,
time_point<steady_clock, _Duration>& __tp)
{
_Duration __d;
__is >> __d;
if (__is.good())
{
const _CharT __u[] = {' ', 's', 'i', 'n', 'c', 'e', ' ', 'b', 'o', 'o', 't'};
const basic_string<_CharT> __units(__u, __u + sizeof(__u)/sizeof(__u[0]));
ios_base::iostate __err = ios_base::goodbit;
typedef istreambuf_iterator<_CharT, _Traits> _I;
_I __i(__is);
_I __e;
ptrdiff_t __k = __scan_keyword(__i, __e,
&__units, &__units + 1,
use_facet<ctype<_CharT> >(__is.getloc()),
__err) - &__units;
if (__k == 1)
{
// failed to read epoch string
__is.setstate(__err);
return __is;
}
__tp = time_point<steady_clock, _Duration>(__d);
}
else
__is.setstate(__is.failbit);
return __is;
}
template <class _CharT, class _Traits, class _Duration>
basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os,
const time_point<system_clock, _Duration>& __tp)
{
typename basic_ostream<_CharT, _Traits>::sentry ok(__os);
if (ok)
{
bool failed = false;
try
{
const _CharT* pb = nullptr;
const _CharT* pe = pb;
timezone tz = utc;
typedef timepunct<_CharT> F;
locale loc = __os.getloc();
if (has_facet<F>(loc))
{
const F& f = use_facet<F>(loc);
pb = f.fmt().data();
pe = pb + f.fmt().size();
tz = f.get_timezone();
}
time_t __t = system_clock::to_time_t(__tp);
tm __tm;
if (tz == local)
{
if (localtime_r(&__t, &__tm) == 0)
failed = true;
}
else
{
if (gmtime_r(&__t, &__tm) == 0)
failed = true;
}
if (!failed)
{
const time_put<_CharT>& tp = use_facet<time_put<_CharT> >(loc);
if (pb == pe)
{
_CharT pattern[] = {'%', 'F', 'T', '%', 'H', ':', '%', 'M', ':'};
pb = pattern;
pe = pb + sizeof(pattern) / sizeof(_CharT);
failed = tp.put(__os, __os, __os.fill(), &__tm, pb, pe).failed();
if (!failed)
{
duration<double> __d = __tp - system_clock::from_time_t(__t) +
seconds(__tm.tm_sec);
if (__d.count() < 10)
__os << _CharT('0');
ios::fmtflags __flgs = __os.flags();
__os.setf(ios::fixed, ios::floatfield);
__os << __d.count();
__os.flags(__flgs);
if (tz == local)
{
_CharT sub_pattern[] = {' ', '%', 'z'};
pb = sub_pattern;
pe = pb + + sizeof(sub_pattern) / sizeof(_CharT);
failed = tp.put(__os, __os, __os.fill(), &__tm, pb, pe).failed();
}
else
{
_CharT sub_pattern[] = {' ', '+', '0', '0', '0', '0', 0};
__os << sub_pattern;
}
}
}
else
failed = tp.put(__os, __os, __os.fill(), &__tm, pb, pe).failed();
}
}
catch (...)
{
failed = true;
}
if (failed)
__os.setstate(ios_base::failbit | ios_base::badbit);
}
return __os;
}
template <class _CharT, class _InputIterator>
minutes
__extract_z(_InputIterator& __b, _InputIterator __e,
ios_base::iostate& __err, const ctype<_CharT>& __ct)
{
int __minn = 0;
if (__b != __e)
{
char __cn = __ct.narrow(*__b, 0);
if (__cn != '+' && __cn != '-')
{
__err |= ios_base::failbit;
return minutes(0);
}
int __sn = __cn == '-' ? -1 : 1;
int __hr = 0;
for (int i = 0; i < 2; ++i)
{
if (++__b == __e)
{
__err |= ios_base::eofbit | ios_base::failbit;
return minutes(0);
}
__cn = __ct.narrow(*__b, 0);
if (!('0' <= __cn && __cn <= '9'))
{
__err |= ios_base::failbit;
return minutes(0);
}
__hr = __hr * 10 + __cn - '0';
}
for (int i = 0; i < 2; ++i)
{
if (++__b == __e)
{
__err |= ios_base::eofbit | ios_base::failbit;
return minutes(0);
}
__cn = __ct.narrow(*__b, 0);
if (!('0' <= __cn && __cn <= '9'))
{
__err |= ios_base::failbit;
return minutes(0);
}
__minn = __minn * 10 + __cn - '0';
}
if (++__b == __e)
__err |= ios_base::eofbit;
__minn += __hr * 60;
__minn *= __sn;
}
else
__err |= ios_base::eofbit | ios_base::failbit;
return minutes(__minn);
}
template <class _CharT, class _Traits, class _Duration>
basic_istream<_CharT, _Traits>&
operator>>(basic_istream<_CharT, _Traits>& __is,
time_point<system_clock, _Duration>& __tp)
{
typename basic_istream<_CharT,_Traits>::sentry ok(__is);
if (ok)
{
ios_base::iostate err = ios_base::goodbit;
try
{
const _CharT* pb = nullptr;
const _CharT* pe = pb;
typedef timepunct<_CharT> F;
locale loc = __is.getloc();
timezone tz = utc;
if (has_facet<F>(loc))
{
const F& f = use_facet<F>(loc);
pb = f.fmt().data();
pe = pb + f.fmt().size();
tz = f.get_timezone();
}
const time_get<_CharT>& tg = use_facet<time_get<_CharT> >(loc);
const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(loc);
tm __tm = {0};
typedef istreambuf_iterator<_CharT, _Traits> _I;
if (pb == pe)
{
_CharT pattern[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd',
'T', '%', 'H', ':', '%', 'M', ':'};
pb = pattern;
pe = pb + sizeof(pattern) / sizeof(_CharT);
tg.get(__is, 0, __is, err, &__tm, pb, pe);
if (err & ios_base::failbit)
goto __exit;
double __sec;
_CharT __c = _CharT();
__is >> __sec;
if (__is.fail())
{
err |= ios_base::failbit;
goto __exit;
}
_I __i(__is);
_I __eof;
__c = *__i;
if (++__i == __eof || __c != ' ')
{
err |= ios_base::failbit;
goto __exit;
}
minutes __minn = __extract_z(__i, __eof, err, __ct);
if (err & ios_base::failbit)
goto __exit;
time_t __t;
__t = timegm(&__tm);
__tp = system_clock::from_time_t(__t) - __minn
+ round<microseconds>(duration<double>(__sec));
}
else
{
const _CharT __z[2] = {'%', 'z'};
const _CharT* __fz = std::search(pb, pe, __z, __z+2);
tg.get(__is, 0, __is, err, &__tm, pb, __fz);
minutes __minn(0);
if (__fz != pe)
{
if (err != ios_base::goodbit)
{
err |= ios_base::failbit;
goto __exit;
}
_I __i(__is);
_I __eof;
__minn = __extract_z(__i, __eof, err, __ct);
if (err & ios_base::failbit)
goto __exit;
if (__fz+2 != pe)
{
if (err != ios_base::goodbit)
{
err |= ios_base::failbit;
goto __exit;
}
tg.get(__is, 0, __is, err, &__tm, __fz+2, pe);
if (err & ios_base::failbit)
goto __exit;
}
}
__tm.tm_isdst = -1;
time_t __t;
if (tz == utc || __fz != pe)
__t = timegm(&__tm);
else
__t = mktime(&__tm);
__tp = system_clock::from_time_t(__t) - __minn;
}
}
catch (...)
{
err |= ios_base::badbit | ios_base::failbit;
}
__exit:
__is.setstate(err);
}
return __is;
}
#endif
} // chrono
//_LIBCPP_END_NAMESPACE_STD
}
#endif

View File

@@ -25,68 +25,73 @@
namespace beast {
/** Manual clock implementation.
This concrete class implements the @ref abstract_clock interface and
allows the time to be advanced manually, mainly for the purpose of
providing a clock in unit tests.
@tparam The length of time, in seconds, corresponding to one tick.
@tparam Clock A type meeting these requirements:
http://en.cppreference.com/w/cpp/concept/Clock
*/
template <class Duration, bool IsSteady = true>
class manual_clock : public abstract_clock <Duration>
template <class Clock>
class manual_clock
: public abstract_clock<Clock>
{
public:
using typename abstract_clock <Duration>::rep;
using typename abstract_clock <Duration>::duration;
using typename abstract_clock <Duration>::time_point;
explicit manual_clock (time_point const& t = time_point (Duration (0)))
: m_now (t)
{
}
bool is_steady () const
{
return IsSteady;
}
time_point now () const
{
return m_now;
}
#if 0
std::string to_string (time_point const& tp) const
{
std::stringstream ss;
ss << tp.time_since_epoch() << " from start";
return ss.str ();
}
#endif
/** Set the current time of the manual clock.
Precondition:
! IsSteady || t > now()
*/
void set (time_point const& t)
{
//if (IsSteady)
m_now = t;
}
/** Convenience for setting the time using a duration in @ref rep units. */
void set (rep v)
{
set (time_point (duration (v)));
}
/** Convenience for advancing the clock by one. */
manual_clock& operator++ ()
{
m_now += duration (1);
return *this;
}
using typename abstract_clock<Clock>::rep;
using typename abstract_clock<Clock>::duration;
using typename abstract_clock<Clock>::time_point;
private:
time_point m_now;
time_point now_;
public:
explicit
manual_clock (time_point const& now = time_point(duration(0)))
: now_(now)
{
}
time_point
now() const override
{
return now_;
}
/** Set the current time of the manual clock. */
void
set (time_point const& when)
{
assert(! Clock::is_steady || when >= now_);
now_ = when;
}
/** Convenience for setting the time in seconds from epoch. */
template <class Integer>
void
set(Integer seconds_from_epoch)
{
set(time_point(duration(
std::chrono::seconds(seconds_from_epoch))));
}
/** Advance the clock by a duration. */
template <class Rep, class Period>
void
advance(std::chrono::duration<Rep, Period> const& elapsed)
{
assert(! Clock::is_steady ||
(now_ + elapsed) >= now_);
now_ += elapsed;
}
/** Convenience for advancing the clock by one second. */
manual_clock&
operator++ ()
{
advance(std::chrono::seconds(1));
return *this;
}
};
}

View File

@@ -20,11 +20,8 @@
// MODULES: ../impl/chrono_io.cpp
#include <beast/chrono/abstract_clock.h>
#include <beast/chrono/abstract_clock_io.h>
#include <beast/chrono/manual_clock.h>
#include <beast/unit_test/suite.h>
#include <sstream>
#include <string>
#include <thread>
@@ -34,7 +31,8 @@ namespace beast {
class abstract_clock_test : public unit_test::suite
{
public:
void test (abstract_clock <std::chrono::seconds>& c)
template <class Clock>
void test (abstract_clock<Clock>& c)
{
{
auto const t1 (c.now ());
@@ -53,18 +51,18 @@ public:
void test_manual ()
{
typedef manual_clock <std::chrono::seconds> clock_type;
using clock_type = manual_clock<std::chrono::steady_clock>;
clock_type c;
std::stringstream ss;
ss << "now() = " << c.now () << std::endl;
ss << "now() = " << c.now().time_since_epoch() << std::endl;
c.set (clock_type::time_point (std::chrono::seconds (1)));
ss << "now() = " << c.now () << std::endl;
c.set (clock_type::time_point (std::chrono::seconds(1)));
ss << "now() = " << c.now().time_since_epoch() << std::endl;
c.set (clock_type::time_point (std::chrono::seconds (2)));
ss << "now() = " << c.now () << std::endl;
c.set (clock_type::time_point (std::chrono::seconds(2)));
ss << "now() = " << c.now().time_since_epoch() << std::endl;
log << ss.str();
}
@@ -72,16 +70,16 @@ public:
void run ()
{
log << "steady_clock";
test (get_abstract_clock <std::chrono::steady_clock,
std::chrono::seconds> ());
test (get_abstract_clock<
std::chrono::steady_clock>());
log << "system_clock";
test (get_abstract_clock <std::chrono::system_clock,
std::chrono::seconds> ());
test (get_abstract_clock<
std::chrono::system_clock>());
log << "high_resolution_clock";
test (get_abstract_clock <std::chrono::high_resolution_clock,
std::chrono::seconds> ());
test (get_abstract_clock<
std::chrono::high_resolution_clock>());
log << "manual_clock";
test_manual ();

View File

@@ -44,10 +44,6 @@
#define BEAST_DISABLE_CONTRACT_CHECKS 0
#endif
#ifndef BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES
#define BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES 0
#endif
//------------------------------------------------------------------------------
#ifndef BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES

View File

@@ -21,10 +21,5 @@
#include <BeastConfig.h>
#endif
#include <beast/container/impl/spookyv2.cpp>
#include <beast/container/impl/siphash.cpp>
#include <beast/container/tests/aged_associative_container.test.cpp>
#include <beast/container/tests/buffer_view.test.cpp>
#include <beast/container/tests/hardened_hash.test.cpp>
#include <beast/container/tests/hash_append.test.cpp>

View File

@@ -31,12 +31,12 @@ namespace beast {
template <
class Key,
class T,
class Duration = std::chrono::seconds,
class Clock = std::chrono::steady_clock,
class Compare = std::less <Key>,
class Allocator = std::allocator <std::pair <Key const, T>>
>
using aged_map = detail::aged_ordered_container <
false, true, Key, T, Duration, Compare, Allocator>;
false, true, Key, T, Clock, Compare, Allocator>;
}

View File

@@ -31,12 +31,12 @@ namespace beast {
template <
class Key,
class T,
class Duration = std::chrono::seconds,
class Clock = std::chrono::steady_clock,
class Compare = std::less <Key>,
class Allocator = std::allocator <std::pair <Key const, T>>
>
using aged_multimap = detail::aged_ordered_container <
true, true, Key, T, Duration, Compare, Allocator>;
true, true, Key, T, Clock, Compare, Allocator>;
}

View File

@@ -30,12 +30,12 @@ namespace beast {
template <
class Key,
class Duration = std::chrono::seconds,
class Clock = std::chrono::steady_clock,
class Compare = std::less <Key>,
class Allocator = std::allocator <Key>
>
using aged_multiset = detail::aged_ordered_container <
true, false, Key, void, Duration, Compare, Allocator>;
true, false, Key, void, Clock, Compare, Allocator>;
}

View File

@@ -30,12 +30,12 @@ namespace beast {
template <
class Key,
class Duration = std::chrono::seconds,
class Clock = std::chrono::steady_clock,
class Compare = std::less <Key>,
class Allocator = std::allocator <Key>
>
using aged_set = detail::aged_ordered_container <
false, false, Key, void, Duration, Compare, Allocator>;
false, false, Key, void, Clock, Compare, Allocator>;
}

View File

@@ -31,13 +31,13 @@ namespace beast {
template <
class Key,
class T,
class Duration = std::chrono::seconds,
class Clock = std::chrono::steady_clock,
class Hash = std::hash <Key>,
class KeyEqual = std::equal_to <Key>,
class Allocator = std::allocator <std::pair <Key const, T>>
>
using aged_unordered_map = detail::aged_unordered_container <
false, true, Key, T, Duration, Hash, KeyEqual, Allocator>;
false, true, Key, T, Clock, Hash, KeyEqual, Allocator>;
}

View File

@@ -31,13 +31,13 @@ namespace beast {
template <
class Key,
class T,
class Duration = std::chrono::seconds,
class Clock = std::chrono::steady_clock,
class Hash = std::hash <Key>,
class KeyEqual = std::equal_to <Key>,
class Allocator = std::allocator <std::pair <Key const, T>>
>
using aged_unordered_multimap = detail::aged_unordered_container <
true, true, Key, T, Duration, Hash, KeyEqual, Allocator>;
true, true, Key, T, Clock, Hash, KeyEqual, Allocator>;
}

View File

@@ -30,13 +30,13 @@ namespace beast {
template <
class Key,
class Duration = std::chrono::seconds,
class Clock = std::chrono::steady_clock,
class Hash = std::hash <Key>,
class KeyEqual = std::equal_to <Key>,
class Allocator = std::allocator <Key>
>
using aged_unordered_multiset = detail::aged_unordered_container <
true, false, Key, void, Duration, Hash, KeyEqual, Allocator>;
true, false, Key, void, Clock, Hash, KeyEqual, Allocator>;
}

View File

@@ -30,13 +30,13 @@ namespace beast {
template <
class Key,
class Duration = std::chrono::seconds,
class Clock = std::chrono::steady_clock,
class Hash = std::hash <Key>,
class KeyEqual = std::equal_to <Key>,
class Allocator = std::allocator <Key>
>
using aged_unordered_set = detail::aged_unordered_container <
false, false, Key, void, Duration, Hash, KeyEqual, Allocator>;
false, false, Key, void, Clock, Hash, KeyEqual, Allocator>;
}

View File

@@ -22,15 +22,11 @@
#include <beast/container/detail/aged_container_iterator.h>
#include <beast/container/detail/aged_associative_container.h>
#include <beast/container/aged_container.h>
#include <beast/chrono/abstract_clock.h>
#include <beast/utility/empty_base_optimization.h>
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/set.hpp>
#include <beast/cxx14/algorithm.h> // <algorithm>
#include <functional>
#include <initializer_list>
@@ -75,7 +71,7 @@ template <
bool IsMap,
class Key,
class T,
class Duration = std::chrono::seconds,
class Clock = std::chrono::steady_clock,
class Compare = std::less <Key>,
class Allocator = std::allocator <
typename std::conditional <IsMap,
@@ -85,25 +81,20 @@ template <
class aged_ordered_container
{
public:
typedef abstract_clock <Duration> clock_type;
typedef typename clock_type::time_point time_point;
typedef typename clock_type::duration duration;
typedef Key key_type;
typedef T mapped_type;
typedef typename std::conditional <
IsMap,
std::pair <Key const, T>,
Key>::type value_type;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
using clock_type = abstract_clock<Clock>;
using time_point = typename clock_type::time_point;
using duration = typename clock_type::duration;
using key_type = Key;
using mapped_type = T;
using value_type = typename std::conditional <
IsMap, std::pair <Key const, T>, Key>::type;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
// Introspection (for unit tests)
typedef std::false_type is_unordered;
typedef std::integral_constant <bool, IsMulti> is_multi;
typedef std::integral_constant <bool, IsMap> is_map;
// VFALCO TODO How can we reorder the declarations to keep
// all the public things together contiguously?
using is_unordered = std::false_type;
using is_multi = std::integral_constant <bool, IsMulti>;
using is_map = std::integral_constant <bool, IsMap>;
private:
static Key const& extract (value_type const& value)
@@ -1237,8 +1228,8 @@ private:
//------------------------------------------------------------------------------
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
class Clock, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
aged_ordered_container (
clock_type& clock)
: m_config (clock)
@@ -1246,8 +1237,8 @@ aged_ordered_container (
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
class Clock, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
aged_ordered_container (
clock_type& clock,
Compare const& comp)
@@ -1256,8 +1247,8 @@ aged_ordered_container (
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
class Clock, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
aged_ordered_container (
clock_type& clock,
Allocator const& alloc)
@@ -1266,8 +1257,8 @@ aged_ordered_container (
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
class Clock, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
aged_ordered_container (
clock_type& clock,
Compare const& comp,
@@ -1277,9 +1268,9 @@ aged_ordered_container (
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <class InputIt>
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
aged_ordered_container (InputIt first, InputIt last,
clock_type& clock)
: m_config (clock)
@@ -1288,9 +1279,9 @@ aged_ordered_container (InputIt first, InputIt last,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <class InputIt>
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
aged_ordered_container (InputIt first, InputIt last,
clock_type& clock,
Compare const& comp)
@@ -1300,9 +1291,9 @@ aged_ordered_container (InputIt first, InputIt last,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <class InputIt>
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
aged_ordered_container (InputIt first, InputIt last,
clock_type& clock,
Allocator const& alloc)
@@ -1312,9 +1303,9 @@ aged_ordered_container (InputIt first, InputIt last,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <class InputIt>
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
aged_ordered_container (InputIt first, InputIt last,
clock_type& clock,
Compare const& comp,
@@ -1325,8 +1316,8 @@ aged_ordered_container (InputIt first, InputIt last,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
class Clock, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
aged_ordered_container (aged_ordered_container const& other)
: m_config (other.m_config)
{
@@ -1334,8 +1325,8 @@ aged_ordered_container (aged_ordered_container const& other)
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
class Clock, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
aged_ordered_container (aged_ordered_container const& other,
Allocator const& alloc)
: m_config (other.m_config, alloc)
@@ -1344,8 +1335,8 @@ aged_ordered_container (aged_ordered_container const& other,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
class Clock, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
aged_ordered_container (aged_ordered_container&& other)
: m_config (std::move (other.m_config))
, m_cont (std::move (other.m_cont))
@@ -1354,8 +1345,8 @@ aged_ordered_container (aged_ordered_container&& other)
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
class Clock, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
aged_ordered_container (aged_ordered_container&& other,
Allocator const& alloc)
: m_config (std::move (other.m_config), alloc)
@@ -1365,8 +1356,8 @@ aged_ordered_container (aged_ordered_container&& other,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
class Clock, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
aged_ordered_container (std::initializer_list <value_type> init,
clock_type& clock)
: m_config (clock)
@@ -1375,8 +1366,8 @@ aged_ordered_container (std::initializer_list <value_type> init,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
class Clock, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
aged_ordered_container (std::initializer_list <value_type> init,
clock_type& clock,
Compare const& comp)
@@ -1386,8 +1377,8 @@ aged_ordered_container (std::initializer_list <value_type> init,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
class Clock, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
aged_ordered_container (std::initializer_list <value_type> init,
clock_type& clock,
Allocator const& alloc)
@@ -1397,8 +1388,8 @@ aged_ordered_container (std::initializer_list <value_type> init,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
class Clock, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
aged_ordered_container (std::initializer_list <value_type> init,
clock_type& clock,
Compare const& comp,
@@ -1409,17 +1400,17 @@ aged_ordered_container (std::initializer_list <value_type> init,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
class Clock, class Compare, class Allocator>
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
~aged_ordered_container()
{
clear();
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
auto
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
operator= (aged_ordered_container const& other) ->
aged_ordered_container&
{
@@ -1433,9 +1424,9 @@ operator= (aged_ordered_container const& other) ->
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
auto
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
operator= (aged_ordered_container&& other) ->
aged_ordered_container&
{
@@ -1447,9 +1438,9 @@ operator= (aged_ordered_container&& other) ->
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
auto
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
operator= (std::initializer_list <value_type> init) ->
aged_ordered_container&
{
@@ -1461,10 +1452,10 @@ operator= (std::initializer_list <value_type> init) ->
//------------------------------------------------------------------------------
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <class K, bool maybe_multi, bool maybe_map, class>
typename std::conditional <IsMap, T, void*>::type&
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
at (K const& k)
{
auto const iter (m_cont.find (k,
@@ -1475,10 +1466,10 @@ at (K const& k)
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <class K, bool maybe_multi, bool maybe_map, class>
typename std::conditional <IsMap, T, void*>::type const&
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
at (K const& k) const
{
auto const iter (m_cont.find (k,
@@ -1489,10 +1480,10 @@ at (K const& k) const
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <bool maybe_multi, bool maybe_map, class>
typename std::conditional <IsMap, T, void*>::type&
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
operator[] (Key const& key)
{
typename cont_type::insert_commit_data d;
@@ -1511,10 +1502,10 @@ operator[] (Key const& key)
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <bool maybe_multi, bool maybe_map, class>
typename std::conditional <IsMap, T, void*>::type&
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
operator[] (Key&& key)
{
typename cont_type::insert_commit_data d;
@@ -1536,9 +1527,9 @@ operator[] (Key&& key)
//------------------------------------------------------------------------------
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
void
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
clear()
{
for (auto iter (chronological.list.begin());
@@ -1550,10 +1541,10 @@ clear()
// map, set
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <bool maybe_multi>
auto
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
insert (value_type const& value) ->
typename std::enable_if <! maybe_multi,
std::pair <iterator, bool>>::type
@@ -1573,10 +1564,10 @@ insert (value_type const& value) ->
// multimap, multiset
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <bool maybe_multi>
auto
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
insert (value_type const& value) ->
typename std::enable_if <maybe_multi,
iterator>::type
@@ -1591,10 +1582,10 @@ insert (value_type const& value) ->
// set
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <bool maybe_multi, bool maybe_map>
auto
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
insert (value_type&& value) ->
typename std::enable_if <! maybe_multi && ! maybe_map,
std::pair <iterator, bool>>::type
@@ -1614,10 +1605,10 @@ insert (value_type&& value) ->
// multiset
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <bool maybe_multi, bool maybe_map>
auto
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
insert (value_type&& value) ->
typename std::enable_if <maybe_multi && ! maybe_map,
iterator>::type
@@ -1634,10 +1625,10 @@ insert (value_type&& value) ->
// map, set
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <bool maybe_multi>
auto
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
insert (const_iterator hint, value_type const& value) ->
typename std::enable_if <! maybe_multi,
iterator>::type
@@ -1657,10 +1648,10 @@ insert (const_iterator hint, value_type const& value) ->
// map, set
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <bool maybe_multi>
auto
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
insert (const_iterator hint, value_type&& value) ->
typename std::enable_if <! maybe_multi,
iterator>::type
@@ -1680,10 +1671,10 @@ insert (const_iterator hint, value_type&& value) ->
// map, set
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <bool maybe_multi, class... Args>
auto
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
emplace (Args&&... args) ->
typename std::enable_if <! maybe_multi,
std::pair <iterator, bool>>::type
@@ -1707,10 +1698,10 @@ emplace (Args&&... args) ->
// multiset, multimap
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <bool maybe_multi, class... Args>
auto
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
emplace (Args&&... args) ->
typename std::enable_if <maybe_multi,
iterator>::type
@@ -1726,10 +1717,10 @@ emplace (Args&&... args) ->
// map, set
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <bool maybe_multi, class... Args>
auto
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
emplace_hint (const_iterator hint, Args&&... args) ->
typename std::enable_if <! maybe_multi,
std::pair <iterator, bool>>::type
@@ -1752,10 +1743,10 @@ emplace_hint (const_iterator hint, Args&&... args) ->
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <bool is_const, class Iterator, class Base, class>
detail::aged_container_iterator <false, Iterator, Base>
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
erase (detail::aged_container_iterator <is_const, Iterator, Base> pos)
{
unlink_and_delete_element(&*((pos++).iterator()));
@@ -1764,10 +1755,10 @@ erase (detail::aged_container_iterator <is_const, Iterator, Base> pos)
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <bool is_const, class Iterator, class Base, class>
detail::aged_container_iterator <false, Iterator, Base>
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
erase (detail::aged_container_iterator <is_const, Iterator, Base> first,
detail::aged_container_iterator <is_const, Iterator, Base> last)
{
@@ -1779,10 +1770,10 @@ erase (detail::aged_container_iterator <is_const, Iterator, Base> first,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <class K>
auto
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
erase (K const& k) ->
size_type
{
@@ -1805,9 +1796,9 @@ erase (K const& k) ->
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
void
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
swap (aged_ordered_container& other) noexcept
{
swap_data (other);
@@ -1818,10 +1809,10 @@ swap (aged_ordered_container& other) noexcept
//------------------------------------------------------------------------------
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <class K>
auto
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
touch (K const& k) ->
size_type
{
@@ -1839,11 +1830,11 @@ touch (K const& k) ->
//------------------------------------------------------------------------------
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <bool OtherIsMulti, bool OtherIsMap,
class OtherT, class OtherDuration, class OtherAllocator>
bool
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
operator== (
aged_ordered_container <OtherIsMulti, OtherIsMap,
Key, OtherT, OtherDuration, Compare,
@@ -1866,10 +1857,10 @@ operator== (
//------------------------------------------------------------------------------
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <bool is_const, class Iterator, class Base, class>
void
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
touch (detail::aged_container_iterator <
is_const, Iterator, Base> pos,
typename clock_type::time_point const& now)
@@ -1881,10 +1872,10 @@ touch (detail::aged_container_iterator <
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <bool maybe_propagate>
typename std::enable_if <maybe_propagate>::type
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
swap_data (aged_ordered_container& other) noexcept
{
std::swap (m_config.key_compare(), other.m_config.key_compare());
@@ -1893,10 +1884,10 @@ swap_data (aged_ordered_container& other) noexcept
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
template <bool maybe_propagate>
typename std::enable_if <! maybe_propagate>::type
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
swap_data (aged_ordered_container& other) noexcept
{
std::swap (m_config.key_compare(), other.m_config.key_compare());
@@ -1908,9 +1899,9 @@ swap_data (aged_ordered_container& other) noexcept
//------------------------------------------------------------------------------
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
struct is_aged_container <detail::aged_ordered_container <
IsMulti, IsMap, Key, T, Duration, Compare, Allocator>>
IsMulti, IsMap, Key, T, Clock, Compare, Allocator>>
: std::true_type
{
};
@@ -1918,22 +1909,22 @@ struct is_aged_container <detail::aged_ordered_container <
// Free functions
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator>
class Clock, class Compare, class Allocator>
void swap (
detail::aged_ordered_container <IsMulti, IsMap,
Key, T, Duration, Compare, Allocator>& lhs,
Key, T, Clock, Compare, Allocator>& lhs,
detail::aged_ordered_container <IsMulti, IsMap,
Key, T, Duration, Compare, Allocator>& rhs) noexcept
Key, T, Clock, Compare, Allocator>& rhs) noexcept
{
lhs.swap (rhs);
}
/** Expire aged container items past the specified age. */
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Compare, class Allocator,
class Clock, class Compare, class Allocator,
class Rep, class Period>
std::size_t expire (detail::aged_ordered_container <
IsMulti, IsMap, Key, T, Duration, Compare, Allocator>& c,
IsMulti, IsMap, Key, T, Clock, Compare, Allocator>& c,
std::chrono::duration <Rep, Period> const& age)
{
std::size_t n (0);

View File

@@ -22,15 +22,11 @@
#include <beast/container/detail/aged_container_iterator.h>
#include <beast/container/detail/aged_associative_container.h>
#include <beast/container/aged_container.h>
#include <beast/chrono/abstract_clock.h>
#include <beast/utility/empty_base_optimization.h>
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/unordered_set.hpp>
#include <beast/cxx14/algorithm.h> // <algorithm>
#include <functional>
#include <initializer_list>
@@ -80,7 +76,7 @@ template <
bool IsMap,
class Key,
class T,
class Duration = std::chrono::seconds,
class Clock = std::chrono::steady_clock,
class Hash = std::hash <Key>,
class KeyEqual = std::equal_to <Key>,
class Allocator = std::allocator <
@@ -91,24 +87,20 @@ template <
class aged_unordered_container
{
public:
typedef abstract_clock <Duration> clock_type;
typedef typename clock_type::time_point time_point;
typedef typename clock_type::duration duration;
typedef Key key_type;
typedef T mapped_type;
typedef typename std::conditional <IsMap,
std::pair <Key const, T>,
Key>::type value_type;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
using clock_type = abstract_clock<Clock>;
using time_point = typename clock_type::time_point;
using duration = typename clock_type::duration;
using key_type = Key;
using mapped_type = T;
using value_type = typename std::conditional <IsMap,
std::pair <Key const, T>, Key>::type;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
// Introspection (for unit tests)
typedef std::true_type is_unordered;
typedef std::integral_constant <bool, IsMulti> is_multi;
typedef std::integral_constant <bool, IsMap> is_map;
// VFALCO TODO How can we reorder the declarations to keep
// all the public things together contiguously?
using is_unordered = std::true_type;
using is_multi = std::integral_constant <bool, IsMulti>;
using is_map = std::integral_constant <bool, IsMap>;
private:
static Key const& extract (value_type const& value)
@@ -1504,8 +1496,8 @@ private:
//------------------------------------------------------------------------------
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
class Clock, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (
clock_type& clock)
@@ -1517,8 +1509,8 @@ aged_unordered_container (
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
class Clock, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (
clock_type& clock,
@@ -1531,8 +1523,8 @@ aged_unordered_container (
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
class Clock, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (
clock_type& clock,
@@ -1545,8 +1537,8 @@ aged_unordered_container (
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
class Clock, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (
clock_type& clock,
@@ -1560,8 +1552,8 @@ aged_unordered_container (
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
class Clock, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (
clock_type& clock,
@@ -1575,8 +1567,8 @@ aged_unordered_container (
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
class Clock, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (
clock_type& clock,
@@ -1591,8 +1583,8 @@ aged_unordered_container (
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
class Clock, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (
clock_type& clock,
@@ -1607,8 +1599,8 @@ aged_unordered_container (
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
class Clock, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (
clock_type& clock,
@@ -1624,9 +1616,9 @@ aged_unordered_container (
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <class InputIt>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (InputIt first, InputIt last,
clock_type& clock)
@@ -1639,9 +1631,9 @@ aged_unordered_container (InputIt first, InputIt last,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <class InputIt>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (InputIt first, InputIt last,
clock_type& clock,
@@ -1655,9 +1647,9 @@ aged_unordered_container (InputIt first, InputIt last,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <class InputIt>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (InputIt first, InputIt last,
clock_type& clock,
@@ -1671,9 +1663,9 @@ aged_unordered_container (InputIt first, InputIt last,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <class InputIt>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (InputIt first, InputIt last,
clock_type& clock,
@@ -1688,9 +1680,9 @@ aged_unordered_container (InputIt first, InputIt last,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <class InputIt>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (InputIt first, InputIt last,
clock_type& clock,
@@ -1705,9 +1697,9 @@ aged_unordered_container (InputIt first, InputIt last,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <class InputIt>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (InputIt first, InputIt last,
clock_type& clock,
@@ -1723,9 +1715,9 @@ aged_unordered_container (InputIt first, InputIt last,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <class InputIt>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (InputIt first, InputIt last,
clock_type& clock,
@@ -1741,9 +1733,9 @@ aged_unordered_container (InputIt first, InputIt last,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <class InputIt>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (InputIt first, InputIt last,
clock_type& clock,
@@ -1760,8 +1752,8 @@ aged_unordered_container (InputIt first, InputIt last,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
class Clock, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (aged_unordered_container const& other)
: m_config (other.m_config)
@@ -1774,8 +1766,8 @@ aged_unordered_container (aged_unordered_container const& other)
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
class Clock, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (aged_unordered_container const& other,
Allocator const& alloc)
@@ -1789,8 +1781,8 @@ aged_unordered_container (aged_unordered_container const& other,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
class Clock, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (aged_unordered_container&& other)
: m_config (std::move (other.m_config))
@@ -1801,8 +1793,8 @@ aged_unordered_container (aged_unordered_container&& other)
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
class Clock, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (aged_unordered_container&& other,
Allocator const& alloc)
@@ -1817,8 +1809,8 @@ aged_unordered_container (aged_unordered_container&& other,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
class Clock, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (std::initializer_list <value_type> init,
clock_type& clock)
@@ -1831,8 +1823,8 @@ aged_unordered_container (std::initializer_list <value_type> init,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
class Clock, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (std::initializer_list <value_type> init,
clock_type& clock,
@@ -1846,8 +1838,8 @@ aged_unordered_container (std::initializer_list <value_type> init,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
class Clock, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (std::initializer_list <value_type> init,
clock_type& clock,
@@ -1861,8 +1853,8 @@ aged_unordered_container (std::initializer_list <value_type> init,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
class Clock, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (std::initializer_list <value_type> init,
clock_type& clock,
@@ -1877,8 +1869,8 @@ aged_unordered_container (std::initializer_list <value_type> init,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
class Clock, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (std::initializer_list <value_type> init,
clock_type& clock,
@@ -1893,8 +1885,8 @@ aged_unordered_container (std::initializer_list <value_type> init,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
class Clock, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (std::initializer_list <value_type> init,
clock_type& clock,
@@ -1910,8 +1902,8 @@ aged_unordered_container (std::initializer_list <value_type> init,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
class Clock, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (std::initializer_list <value_type> init,
clock_type& clock,
@@ -1927,8 +1919,8 @@ aged_unordered_container (std::initializer_list <value_type> init,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
class Clock, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
aged_unordered_container (std::initializer_list <value_type> init,
clock_type& clock,
@@ -1945,8 +1937,8 @@ aged_unordered_container (std::initializer_list <value_type> init,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
class Clock, class Hash, class KeyEqual, class Allocator>
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
~aged_unordered_container()
{
@@ -1954,9 +1946,9 @@ aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
auto
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
operator= (aged_unordered_container const& other)
-> aged_unordered_container&
@@ -1974,9 +1966,9 @@ operator= (aged_unordered_container const& other)
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
auto
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
operator= (aged_unordered_container&& other) ->
aged_unordered_container&
@@ -1992,9 +1984,9 @@ operator= (aged_unordered_container&& other) ->
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
auto
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
operator= (std::initializer_list <value_type> init) ->
aged_unordered_container&
@@ -2007,10 +1999,10 @@ operator= (std::initializer_list <value_type> init) ->
//------------------------------------------------------------------------------
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <class K, bool maybe_multi, bool maybe_map, class>
typename std::conditional <IsMap, T, void*>::type&
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
at (K const& k)
{
@@ -2023,10 +2015,10 @@ at (K const& k)
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <class K, bool maybe_multi, bool maybe_map, class>
typename std::conditional <IsMap, T, void*>::type const&
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
at (K const& k) const
{
@@ -2039,10 +2031,10 @@ at (K const& k) const
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <bool maybe_multi, bool maybe_map, class>
typename std::conditional <IsMap, T, void*>::type&
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
operator[] (Key const& key)
{
@@ -2065,10 +2057,10 @@ operator[] (Key const& key)
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <bool maybe_multi, bool maybe_map, class>
typename std::conditional <IsMap, T, void*>::type&
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
operator[] (Key&& key)
{
@@ -2093,9 +2085,9 @@ operator[] (Key&& key)
//------------------------------------------------------------------------------
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
void
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
clear()
{
@@ -2109,10 +2101,10 @@ clear()
// map, set
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <bool maybe_multi>
auto
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
insert (value_type const& value) ->
typename std::enable_if <! maybe_multi,
@@ -2135,10 +2127,10 @@ insert (value_type const& value) ->
// multimap, multiset
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <bool maybe_multi>
auto
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
insert (value_type const& value) ->
typename std::enable_if <maybe_multi,
@@ -2153,10 +2145,10 @@ insert (value_type const& value) ->
// map, set
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <bool maybe_multi, bool maybe_map>
auto
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
insert (value_type&& value) ->
typename std::enable_if <! maybe_multi && ! maybe_map,
@@ -2179,10 +2171,10 @@ insert (value_type&& value) ->
// multimap, multiset
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <bool maybe_multi, bool maybe_map>
auto
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
insert (value_type&& value) ->
typename std::enable_if <maybe_multi && ! maybe_map,
@@ -2198,10 +2190,10 @@ insert (value_type&& value) ->
#if 1 // Use insert() instead of insert_check() insert_commit()
// set, map
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <bool maybe_multi, class... Args>
auto
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
emplace (Args&&... args) ->
typename std::enable_if <! maybe_multi,
@@ -2223,10 +2215,10 @@ emplace (Args&&... args) ->
#else // As original, use insert_check() / insert_commit () pair.
// set, map
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <bool maybe_multi, class... Args>
auto
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
emplace (Args&&... args) ->
typename std::enable_if <! maybe_multi,
@@ -2254,10 +2246,10 @@ emplace (Args&&... args) ->
// multiset, multimap
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <bool maybe_multi, class... Args>
auto
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
emplace (Args&&... args) ->
typename std::enable_if <maybe_multi,
@@ -2273,10 +2265,10 @@ emplace (Args&&... args) ->
// set, map
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <bool maybe_multi, class... Args>
auto
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
emplace_hint (const_iterator /*hint*/, Args&&... args) ->
typename std::enable_if <! maybe_multi,
@@ -2302,10 +2294,10 @@ emplace_hint (const_iterator /*hint*/, Args&&... args) ->
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <bool is_const, class Iterator, class Base>
detail::aged_container_iterator <false, Iterator, Base>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
erase (detail::aged_container_iterator <
is_const, Iterator, Base> pos)
@@ -2316,10 +2308,10 @@ erase (detail::aged_container_iterator <
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <bool is_const, class Iterator, class Base>
detail::aged_container_iterator <false, Iterator, Base>
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
erase (detail::aged_container_iterator <
is_const, Iterator, Base> first,
@@ -2334,10 +2326,10 @@ erase (detail::aged_container_iterator <
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <class K>
auto
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
erase (K const& k) ->
size_type
@@ -2361,9 +2353,9 @@ erase (K const& k) ->
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
void
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
swap (aged_unordered_container& other) noexcept
{
@@ -2373,10 +2365,10 @@ swap (aged_unordered_container& other) noexcept
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <class K>
auto
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
touch (K const& k) ->
size_type
@@ -2393,7 +2385,7 @@ touch (K const& k) ->
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <
bool OtherIsMap,
class OtherKey,
@@ -2405,7 +2397,7 @@ template <
>
typename std::enable_if <! maybe_multi, bool>::type
aged_unordered_container <
IsMulti, IsMap, Key, T, Duration, Hash, KeyEqual, Allocator>::
IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
operator== (
aged_unordered_container <false, OtherIsMap,
OtherKey, OtherT, OtherDuration, OtherHash, KeyEqual,
@@ -2424,7 +2416,7 @@ operator== (
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <
bool OtherIsMap,
class OtherKey,
@@ -2436,7 +2428,7 @@ template <
>
typename std::enable_if <maybe_multi, bool>::type
aged_unordered_container <
IsMulti, IsMap, Key, T, Duration, Hash, KeyEqual, Allocator>::
IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
operator== (
aged_unordered_container <true, OtherIsMap,
OtherKey, OtherT, OtherDuration, OtherHash, KeyEqual,
@@ -2469,10 +2461,10 @@ operator== (
// map, set
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <bool maybe_multi>
auto
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
insert_unchecked (value_type const& value) ->
typename std::enable_if <! maybe_multi,
@@ -2494,10 +2486,10 @@ insert_unchecked (value_type const& value) ->
// multimap, multiset
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
template <bool maybe_multi>
auto
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
insert_unchecked (value_type const& value) ->
typename std::enable_if <maybe_multi,
@@ -2516,32 +2508,32 @@ insert_unchecked (value_type const& value) ->
//------------------------------------------------------------------------------
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator>
class Clock, class Hash, class KeyEqual, class Allocator>
struct is_aged_container <detail::aged_unordered_container <
IsMulti, IsMap, Key, T, Duration, Hash, KeyEqual, Allocator>>
IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>>
: std::true_type
{
};
// Free functions
template <bool IsMulti, bool IsMap, class Key, class T, class Duration,
template <bool IsMulti, bool IsMap, class Key, class T, class Clock,
class Hash, class KeyEqual, class Allocator>
void swap (
detail::aged_unordered_container <IsMulti, IsMap,
Key, T, Duration, Hash, KeyEqual, Allocator>& lhs,
Key, T, Clock, Hash, KeyEqual, Allocator>& lhs,
detail::aged_unordered_container <IsMulti, IsMap,
Key, T, Duration, Hash, KeyEqual, Allocator>& rhs) noexcept
Key, T, Clock, Hash, KeyEqual, Allocator>& rhs) noexcept
{
lhs.swap (rhs);
}
/** Expire aged container items past the specified age. */
template <bool IsMulti, bool IsMap, class Key, class T,
class Duration, class Hash, class KeyEqual, class Allocator,
class Clock, class Hash, class KeyEqual, class Allocator,
class Rep, class Period>
std::size_t expire (detail::aged_unordered_container <
IsMulti, IsMap, Key, T, Duration, Hash, KeyEqual, Allocator>& c,
IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>& c,
std::chrono::duration <Rep, Period> const& age) noexcept
{
std::size_t n (0);

View File

@@ -302,7 +302,7 @@ public:
>
using Cont = detail::aged_ordered_container <
Base::is_multi::value, Base::is_map::value, typename Base::Key,
typename Base::T, typename Base::Dur, Compare, Allocator>;
typename Base::T, typename Base::Clock, Compare, Allocator>;
};
// unordered
@@ -318,7 +318,7 @@ public:
>
using Cont = detail::aged_unordered_container <
Base::is_multi::value, Base::is_map::value,
typename Base::Key, typename Base::T, typename Base::Dur,
typename Base::Key, typename Base::T, typename Base::Clock,
Hash, KeyEqual, Allocator>;
};
@@ -327,8 +327,8 @@ public:
struct TestTraitsBase
{
typedef std::string Key;
typedef std::chrono::seconds Dur;
typedef manual_clock <Dur> Clock;
typedef std::chrono::steady_clock Clock;
typedef manual_clock<Clock> ManualClock;
};
template <bool IsUnordered, bool IsMulti, bool IsMap>
@@ -744,12 +744,12 @@ testConstructEmpty ()
typedef typename Traits::Value Value;
typedef typename Traits::Key Key;
typedef typename Traits::T T;
typedef typename Traits::Dur Dur;
typedef typename Traits::Clock Clock;
typedef typename Traits::Comp Comp;
typedef typename Traits::Alloc Alloc;
typedef typename Traits::MyComp MyComp;
typedef typename Traits::MyAlloc MyAlloc;
typename Traits::Clock clock;
typename Traits::ManualClock clock;
//testcase (Traits::name() + " empty");
testcase ("empty");
@@ -789,14 +789,14 @@ testConstructEmpty ()
typedef typename Traits::Value Value;
typedef typename Traits::Key Key;
typedef typename Traits::T T;
typedef typename Traits::Dur Dur;
typedef typename Traits::Clock Clock;
typedef typename Traits::Hash Hash;
typedef typename Traits::Equal Equal;
typedef typename Traits::Alloc Alloc;
typedef typename Traits::MyHash MyHash;
typedef typename Traits::MyEqual MyEqual;
typedef typename Traits::MyAlloc MyAlloc;
typename Traits::Clock clock;
typename Traits::ManualClock clock;
//testcase (Traits::name() + " empty");
testcase ("empty");
@@ -859,12 +859,12 @@ testConstructRange ()
typedef typename Traits::Value Value;
typedef typename Traits::Key Key;
typedef typename Traits::T T;
typedef typename Traits::Dur Dur;
typedef typename Traits::Clock Clock;
typedef typename Traits::Comp Comp;
typedef typename Traits::Alloc Alloc;
typedef typename Traits::MyComp MyComp;
typedef typename Traits::MyAlloc MyAlloc;
typename Traits::Clock clock;
typename Traits::ManualClock clock;
auto const v (Traits::values());
//testcase (Traits::name() + " range");
@@ -922,14 +922,14 @@ testConstructRange ()
typedef typename Traits::Value Value;
typedef typename Traits::Key Key;
typedef typename Traits::T T;
typedef typename Traits::Dur Dur;
typedef typename Traits::Clock Clock;
typedef typename Traits::Hash Hash;
typedef typename Traits::Equal Equal;
typedef typename Traits::Alloc Alloc;
typedef typename Traits::MyHash MyHash;
typedef typename Traits::MyEqual MyEqual;
typedef typename Traits::MyAlloc MyAlloc;
typename Traits::Clock clock;
typename Traits::ManualClock clock;
auto const v (Traits::values());
//testcase (Traits::name() + " range");
@@ -1002,12 +1002,12 @@ testConstructInitList ()
typedef typename Traits::Value Value;
typedef typename Traits::Key Key;
typedef typename Traits::T T;
typedef typename Traits::Dur Dur;
typedef typename Traits::Clock Clock;
typedef typename Traits::Comp Comp;
typedef typename Traits::Alloc Alloc;
typedef typename Traits::MyComp MyComp;
typedef typename Traits::MyAlloc MyAlloc;
typename Traits::Clock clock;
typename Traits::ManualClock clock;
//testcase (Traits::name() + " init-list");
testcase ("init-list");
@@ -1027,14 +1027,14 @@ testConstructInitList ()
typedef typename Traits::Value Value;
typedef typename Traits::Key Key;
typedef typename Traits::T T;
typedef typename Traits::Dur Dur;
typedef typename Traits::Clock Clock;
typedef typename Traits::Hash Hash;
typedef typename Traits::Equal Equal;
typedef typename Traits::Alloc Alloc;
typedef typename Traits::MyHash MyHash;
typedef typename Traits::MyEqual MyEqual;
typedef typename Traits::MyAlloc MyAlloc;
typename Traits::Clock clock;
typename Traits::ManualClock clock;
//testcase (Traits::name() + " init-list");
testcase ("init-list");
@@ -1057,7 +1057,7 @@ testCopyMove ()
typedef TestTraits <IsUnordered, IsMulti, IsMap> Traits;
typedef typename Traits::Value Value;
typedef typename Traits::Alloc Alloc;
typename Traits::Clock clock;
typename Traits::ManualClock clock;
auto const v (Traits::values());
//testcase (Traits::name() + " copy/move");
@@ -1139,7 +1139,7 @@ testIterator()
typedef TestTraits <IsUnordered, IsMulti, IsMap> Traits;
typedef typename Traits::Value Value;
typedef typename Traits::Alloc Alloc;
typename Traits::Clock clock;
typename Traits::ManualClock clock;
auto const v (Traits::values());
//testcase (Traits::name() + " iterators");
@@ -1202,7 +1202,7 @@ testReverseIterator()
typedef TestTraits <IsUnordered, IsMulti, IsMap> Traits;
typedef typename Traits::Value Value;
typedef typename Traits::Alloc Alloc;
typename Traits::Clock clock;
typename Traits::ManualClock clock;
auto const v (Traits::values());
//testcase (Traits::name() + " reverse_iterators");
@@ -1357,7 +1357,7 @@ aged_associative_container_test_base::
testModifiers()
{
typedef TestTraits <IsUnordered, IsMulti, IsMap> Traits;
typename Traits::Clock clock;
typename Traits::ManualClock clock;
auto const v (Traits::values());
auto const l (make_list (v));
@@ -1418,7 +1418,7 @@ testChronological ()
{
typedef TestTraits <IsUnordered, IsMulti, IsMap> Traits;
typedef typename Traits::Value Value;
typename Traits::Clock clock;
typename Traits::ManualClock clock;
auto const v (Traits::values());
//testcase (Traits::name() + " chronological");
@@ -1484,7 +1484,7 @@ aged_associative_container_test_base::
testArrayCreate()
{
typedef TestTraits <IsUnordered, IsMulti, IsMap> Traits;
typename Traits::Clock clock;
typename Traits::ManualClock clock;
auto v (Traits::values());
//testcase (Traits::name() + " array create");
@@ -1522,8 +1522,9 @@ reverseFillAgedContainer (Container& c, Values const& values)
c.clear();
// c.clock() returns an abstract_clock, so dynamic_cast to manual_clock.
typedef TestTraitsBase::Clock Clock;
Clock& clk (dynamic_cast <Clock&> (c.clock ()));
// VFALCO NOTE This is sketchy
typedef TestTraitsBase::ManualClock ManualClock;
ManualClock& clk (dynamic_cast <ManualClock&> (c.clock()));
clk.set (0);
Values rev (values);
@@ -1626,8 +1627,8 @@ testElementErase ()
testcase ("element erase");
// Make and fill the container
typename Traits::Clock ck;
typename Traits::template Cont <> c {ck};
typename Traits::ManualClock clock;
typename Traits::template Cont <> c {clock};
reverseFillAgedContainer (c, Traits::values());
{
@@ -1756,8 +1757,8 @@ testRangeErase ()
testcase ("range erase");
// Make and fill the container
typename Traits::Clock ck;
typename Traits::template Cont <> c {ck};
typename Traits::ManualClock clock;
typename Traits::template Cont <> c {clock};
reverseFillAgedContainer (c, Traits::values());
// Not bothering to test range erase with reverse iterators.
@@ -1785,7 +1786,7 @@ testCompare ()
{
typedef TestTraits <IsUnordered, IsMulti, IsMap> Traits;
typedef typename Traits::Value Value;
typename Traits::Clock clock;
typename Traits::ManualClock clock;
auto const v (Traits::values());
//testcase (Traits::name() + " array create");
@@ -1819,7 +1820,7 @@ aged_associative_container_test_base::
testObservers()
{
typedef TestTraits <IsUnordered, IsMulti, IsMap> Traits;
typename Traits::Clock clock;
typename Traits::ManualClock clock;
//testcase (Traits::name() + " observers");
testcase ("observers");
@@ -1838,7 +1839,7 @@ aged_associative_container_test_base::
testObservers()
{
typedef TestTraits <IsUnordered, IsMulti, IsMap> Traits;
typename Traits::Clock clock;
typename Traits::ManualClock clock;
//testcase (Traits::name() + " observers");
testcase ("observers");

View File

@@ -21,7 +21,6 @@
#include <BeastConfig.h>
#endif
#include <beast/crypto/impl/MurmurHash.cpp>
#include <beast/crypto/impl/Sha256.cpp>
#include <beast/crypto/tests/base64.test.cpp>

View File

@@ -1,84 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_CRYPTO_MURMURHASH_H_INCLUDED
#define BEAST_CRYPTO_MURMURHASH_H_INCLUDED
#include <cstdint>
#include <stdexcept>
// Original source code links in .cpp file
namespace beast {
namespace Murmur {
extern void MurmurHash3_x86_32 (const void* key, int len, std::uint32_t seed, void* out);
extern void MurmurHash3_x86_128 (const void* key, int len, std::uint32_t seed, void* out);
extern void MurmurHash3_x64_128 (const void* key, int len, std::uint32_t seed, void* out);
// Uses Beast to choose an appropriate routine
// This handy template deduces which size hash is desired
template <typename HashType>
inline void Hash (const void* key, int len, std::uint32_t seed, HashType* out)
{
switch (8 * sizeof (HashType))
{
case 32:
MurmurHash3_x86_32 (key, len, seed, out);
break;
#if BEAST_64BIT
case 64:
{
HashType tmp[2];
MurmurHash3_x64_128 (key, len, seed, &tmp[0]);
*out = tmp[0];
}
break;
case 128:
MurmurHash3_x64_128 (key, len, seed, out);
break;
#else
case 64:
{
HashType tmp[2];
MurmurHash3_x86_128 (key, len, seed, &tmp[0]);
*out = tmp[0];
}
break;
case 128:
MurmurHash3_x86_128 (key, len, seed, out);
break;
#endif
default:
throw std::runtime_error ("invalid key size in MurmurHash");
break;
};
}
}
}
#endif

View File

@@ -1,492 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
// http://code.google.com/p/smhasher/
#include <beast/crypto/MurmurHash.h>
#include <cstdint>
namespace beast {
namespace Murmur {
//-----------------------------------------------------------------------------
// Platform-specific functions and macros
// Microsoft Visual Studio
#if BEAST_MSVC
#define ROTL32(x,y) _rotl(x,y)
#define ROTL64(x,y) _rotl64(x,y)
#define BIG_CONSTANT(x) (x)
// Other compilers
#else
static inline std::uint32_t rotl32 ( std::uint32_t x, int8_t r )
{
return (x << r) | (x >> (32 - r));
}
static inline std::uint64_t rotl64 ( std::uint64_t x, int8_t r )
{
return (x << r) | (x >> (64 - r));
}
#define ROTL32(x,y) rotl32(x,y)
#define ROTL64(x,y) rotl64(x,y)
#define BIG_CONSTANT(x) (x##LLU)
#endif
//-----------------------------------------------------------------------------
// Block read - if your platform needs to do endian-swapping or can only
// handle aligned reads, do the conversion here
static inline std::uint32_t getblock ( const std::uint32_t* p, int i )
{
return p[i];
}
static inline std::uint64_t getblock ( const std::uint64_t* p, int i )
{
return p[i];
}
//-----------------------------------------------------------------------------
// Finalization mix - force all bits of a hash block to avalanche
static inline std::uint32_t fmix ( std::uint32_t h )
{
h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
h *= 0xc2b2ae35;
h ^= h >> 16;
return h;
}
//----------
static inline std::uint64_t fmix ( std::uint64_t k )
{
k ^= k >> 33;
k *= BIG_CONSTANT (0xff51afd7ed558ccd);
k ^= k >> 33;
k *= BIG_CONSTANT (0xc4ceb9fe1a85ec53);
k ^= k >> 33;
return k;
}
//-----------------------------------------------------------------------------
void MurmurHash3_x86_32 ( const void* key, int len,
std::uint32_t seed, void* out )
{
const uint8_t* data = (const uint8_t*)key;
const int nblocks = len / 4;
std::uint32_t h1 = seed;
std::uint32_t c1 = 0xcc9e2d51;
std::uint32_t c2 = 0x1b873593;
//----------
// body
const std::uint32_t* blocks = (const std::uint32_t*) (data + nblocks * 4);
for (int i = -nblocks; i; i++)
{
std::uint32_t k1 = getblock (blocks, i);
k1 *= c1;
k1 = ROTL32 (k1, 15);
k1 *= c2;
h1 ^= k1;
h1 = ROTL32 (h1, 13);
h1 = h1 * 5 + 0xe6546b64;
}
//----------
// tail
const uint8_t* tail = (const uint8_t*) (data + nblocks * 4);
std::uint32_t k1 = 0;
switch (len & 3)
{
case 3:
k1 ^= tail[2] << 16;
case 2:
k1 ^= tail[1] << 8;
case 1:
k1 ^= tail[0];
k1 *= c1;
k1 = ROTL32 (k1, 15);
k1 *= c2;
h1 ^= k1;
};
//----------
// finalization
h1 ^= len;
h1 = fmix (h1);
* (std::uint32_t*)out = h1;
}
//-----------------------------------------------------------------------------
void MurmurHash3_x86_128 ( const void* key, const int len,
std::uint32_t seed, void* out )
{
const uint8_t* data = (const uint8_t*)key;
const int nblocks = len / 16;
std::uint32_t h1 = seed;
std::uint32_t h2 = seed;
std::uint32_t h3 = seed;
std::uint32_t h4 = seed;
std::uint32_t c1 = 0x239b961b;
std::uint32_t c2 = 0xab0e9789;
std::uint32_t c3 = 0x38b34ae5;
std::uint32_t c4 = 0xa1e38b93;
//----------
// body
const std::uint32_t* blocks = (const std::uint32_t*) (data + nblocks * 16);
for (int i = -nblocks; i; i++)
{
std::uint32_t k1 = getblock (blocks, i * 4 + 0);
std::uint32_t k2 = getblock (blocks, i * 4 + 1);
std::uint32_t k3 = getblock (blocks, i * 4 + 2);
std::uint32_t k4 = getblock (blocks, i * 4 + 3);
k1 *= c1;
k1 = ROTL32 (k1, 15);
k1 *= c2;
h1 ^= k1;
h1 = ROTL32 (h1, 19);
h1 += h2;
h1 = h1 * 5 + 0x561ccd1b;
k2 *= c2;
k2 = ROTL32 (k2, 16);
k2 *= c3;
h2 ^= k2;
h2 = ROTL32 (h2, 17);
h2 += h3;
h2 = h2 * 5 + 0x0bcaa747;
k3 *= c3;
k3 = ROTL32 (k3, 17);
k3 *= c4;
h3 ^= k3;
h3 = ROTL32 (h3, 15);
h3 += h4;
h3 = h3 * 5 + 0x96cd1c35;
k4 *= c4;
k4 = ROTL32 (k4, 18);
k4 *= c1;
h4 ^= k4;
h4 = ROTL32 (h4, 13);
h4 += h1;
h4 = h4 * 5 + 0x32ac3b17;
}
//----------
// tail
const uint8_t* tail = (const uint8_t*) (data + nblocks * 16);
std::uint32_t k1 = 0;
std::uint32_t k2 = 0;
std::uint32_t k3 = 0;
std::uint32_t k4 = 0;
switch (len & 15)
{
case 15:
k4 ^= tail[14] << 16;
case 14:
k4 ^= tail[13] << 8;
case 13:
k4 ^= tail[12] << 0;
k4 *= c4;
k4 = ROTL32 (k4, 18);
k4 *= c1;
h4 ^= k4;
case 12:
k3 ^= tail[11] << 24;
case 11:
k3 ^= tail[10] << 16;
case 10:
k3 ^= tail[ 9] << 8;
case 9:
k3 ^= tail[ 8] << 0;
k3 *= c3;
k3 = ROTL32 (k3, 17);
k3 *= c4;
h3 ^= k3;
case 8:
k2 ^= tail[ 7] << 24;
case 7:
k2 ^= tail[ 6] << 16;
case 6:
k2 ^= tail[ 5] << 8;
case 5:
k2 ^= tail[ 4] << 0;
k2 *= c2;
k2 = ROTL32 (k2, 16);
k2 *= c3;
h2 ^= k2;
case 4:
k1 ^= tail[ 3] << 24;
case 3:
k1 ^= tail[ 2] << 16;
case 2:
k1 ^= tail[ 1] << 8;
case 1:
k1 ^= tail[ 0] << 0;
k1 *= c1;
k1 = ROTL32 (k1, 15);
k1 *= c2;
h1 ^= k1;
};
//----------
// finalization
h1 ^= len;
h2 ^= len;
h3 ^= len;
h4 ^= len;
h1 += h2;
h1 += h3;
h1 += h4;
h2 += h1;
h3 += h1;
h4 += h1;
h1 = fmix (h1);
h2 = fmix (h2);
h3 = fmix (h3);
h4 = fmix (h4);
h1 += h2;
h1 += h3;
h1 += h4;
h2 += h1;
h3 += h1;
h4 += h1;
((std::uint32_t*)out)[0] = h1;
((std::uint32_t*)out)[1] = h2;
((std::uint32_t*)out)[2] = h3;
((std::uint32_t*)out)[3] = h4;
}
//-----------------------------------------------------------------------------
void MurmurHash3_x64_128 ( const void* key, const int len,
const std::uint32_t seed, void* out )
{
const uint8_t* data = (const uint8_t*)key;
const int nblocks = len / 16;
std::uint64_t h1 = seed;
std::uint64_t h2 = seed;
std::uint64_t c1 = BIG_CONSTANT (0x87c37b91114253d5);
std::uint64_t c2 = BIG_CONSTANT (0x4cf5ad432745937f);
//----------
// body
const std::uint64_t* blocks = (const std::uint64_t*) (data);
for (int i = 0; i < nblocks; i++)
{
std::uint64_t k1 = getblock (blocks, i * 2 + 0);
std::uint64_t k2 = getblock (blocks, i * 2 + 1);
k1 *= c1;
k1 = ROTL64 (k1, 31);
k1 *= c2;
h1 ^= k1;
h1 = ROTL64 (h1, 27);
h1 += h2;
h1 = h1 * 5 + 0x52dce729;
k2 *= c2;
k2 = ROTL64 (k2, 33);
k2 *= c1;
h2 ^= k2;
h2 = ROTL64 (h2, 31);
h2 += h1;
h2 = h2 * 5 + 0x38495ab5;
}
//----------
// tail
const uint8_t* tail = (const uint8_t*) (data + nblocks * 16);
std::uint64_t k1 = 0;
std::uint64_t k2 = 0;
switch (len & 15)
{
case 15:
k2 ^= std::uint64_t (tail[14]) << 48;
case 14:
k2 ^= std::uint64_t (tail[13]) << 40;
case 13:
k2 ^= std::uint64_t (tail[12]) << 32;
case 12:
k2 ^= std::uint64_t (tail[11]) << 24;
case 11:
k2 ^= std::uint64_t (tail[10]) << 16;
case 10:
k2 ^= std::uint64_t (tail[ 9]) << 8;
case 9:
k2 ^= std::uint64_t (tail[ 8]) << 0;
k2 *= c2;
k2 = ROTL64 (k2, 33);
k2 *= c1;
h2 ^= k2;
case 8:
k1 ^= std::uint64_t (tail[ 7]) << 56;
case 7:
k1 ^= std::uint64_t (tail[ 6]) << 48;
case 6:
k1 ^= std::uint64_t (tail[ 5]) << 40;
case 5:
k1 ^= std::uint64_t (tail[ 4]) << 32;
case 4:
k1 ^= std::uint64_t (tail[ 3]) << 24;
case 3:
k1 ^= std::uint64_t (tail[ 2]) << 16;
case 2:
k1 ^= std::uint64_t (tail[ 1]) << 8;
case 1:
k1 ^= std::uint64_t (tail[ 0]) << 0;
k1 *= c1;
k1 = ROTL64 (k1, 31);
k1 *= c2;
h1 ^= k1;
};
//----------
// finalization
h1 ^= len;
h2 ^= len;
h1 += h2;
h2 += h1;
h1 = fmix (h1);
h2 = fmix (h2);
h1 += h2;
h2 += h1;
((std::uint64_t*)out)[0] = h1;
((std::uint64_t*)out)[1] = h2;
}
}
}

View File

@@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2014, Howard Hinnant <howard.hinnant@gmail.com>,
Vinnie Falco <vinnie.falco@gmail.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_HASH_FNV1A_H_INCLUDED
#define BEAST_HASH_FNV1A_H_INCLUDED
#include <beast/utility/noexcept.h>
#include <cstddef>
#include <cstdint>
#include <beast/cxx14/type_traits.h> // <type_traits>
namespace beast {
// See http://www.isthe.com/chongo/tech/comp/fnv/
//
class fnv1a
{
private:
std::uint64_t state_ = 14695981039346656037ULL;
public:
using result_type = std::size_t;
fnv1a() = default;
template <class Seed,
std::enable_if_t<
std::is_unsigned<Seed>::value>* = nullptr>
explicit
fnv1a (Seed seed)
{
append (&seed, sizeof(seed));
}
void
append (void const* key, std::size_t len) noexcept
{
unsigned char const* p =
static_cast<unsigned char const*>(key);
unsigned char const* const e = p + len;
for (; p < e; ++p)
state_ = (state_ ^ *p) * 1099511628211ULL;
}
explicit
operator std::size_t() noexcept
{
return static_cast<std::size_t>(state_);
}
};
} // beast
#endif

View File

@@ -18,18 +18,14 @@
*/
//==============================================================================
#ifndef BEAST_CONTAINER_HASH_APPEND_H_INCLUDED
#define BEAST_CONTAINER_HASH_APPEND_H_INCLUDED
#ifndef BEAST_HASH_HASH_APPEND_H_INCLUDED
#define BEAST_HASH_HASH_APPEND_H_INCLUDED
#include <beast/utility/meta.h>
#include <beast/container/impl/spookyv2.h>
#include <beast/utility/noexcept.h>
#if BEAST_USE_BOOST_FEATURES
#include <boost/shared_ptr.hpp>
#endif
#include <beast/utility/noexcept.h>
#include <array>
#include <cstdint>
#include <functional>
@@ -656,96 +652,6 @@ hash_append (Hasher& h, T0 const& t0, T1 const& t1, T const& ...t) noexcept
hash_append (h, t1, t...);
}
// See http://www.isthe.com/chongo/tech/comp/fnv/
class fnv1a
{
std::uint64_t state_ = 14695981039346656037ULL;
public:
using result_type = std::size_t;
void
append (void const* key, std::size_t len) noexcept
{
unsigned char const* p = static_cast<unsigned char const*>(key);
unsigned char const* const e = p + len;
for (; p < e; ++p)
state_ = (state_ ^ *p) * 1099511628211ULL;
}
explicit
operator std::size_t() noexcept
{
return static_cast<std::size_t>(state_);
}
};
// See http://burtleburtle.net/bob/hash/spooky.html
class spooky
{
SpookyHash state_;
public:
using result_type = std::size_t;
spooky (std::size_t seed1 = 1, std::size_t seed2 = 2) noexcept
{
state_.Init (seed1, seed2);
}
void
append (void const* key, std::size_t len) noexcept
{
state_.Update (key, len);
}
explicit
operator std::size_t() noexcept
{
std::uint64_t h1, h2;
state_.Final (&h1, &h2);
return static_cast <std::size_t> (h1);
}
};
// See https://131002.net/siphash/
class siphash
{
std::uint64_t v0_ = 0x736f6d6570736575ULL;
std::uint64_t v1_ = 0x646f72616e646f6dULL;
std::uint64_t v2_ = 0x6c7967656e657261ULL;
std::uint64_t v3_ = 0x7465646279746573ULL;
unsigned char buf_[8];
unsigned bufsize_ = 0;
unsigned total_length_ = 0;
public:
using result_type = std::size_t;
siphash() = default;
explicit siphash(std::uint64_t k0, std::uint64_t k1 = 0) noexcept;
void
append (void const* key, std::size_t len) noexcept;
explicit
operator std::size_t() noexcept;
};
template <class Hasher = spooky>
struct uhash
{
using result_type = typename Hasher::result_type;
template <class T>
result_type
operator()(T const& t) const noexcept
{
Hasher h;
hash_append (h, t);
return static_cast<result_type>(h);
}
};
} // beast
#endif

View File

@@ -0,0 +1,85 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#if BEAST_INCLUDE_BEASTCONFIG
#include <BeastConfig.h>
#endif
#include <beast/container/fnv1a.h>
#include <beast/container/siphash.h>
#include <beast/container/xxhasher.h>
#include <beast/random/rngfill.h>
#include <beast/random/xor_shift_engine.h>
#include <beast/unit_test/suite.h>
#include <array>
#include <chrono>
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <random>
namespace beast {
class hash_speed_test : public beast::unit_test::suite
{
public:
using clock_type =
std::chrono::high_resolution_clock;
template <class Hasher, std::size_t KeySize>
void
test (std::string const& what, std::size_t n)
{
using namespace std;
using namespace std::chrono;
xor_shift_engine g(1);
array<std::uint8_t, KeySize> key;
auto const start = clock_type::now();
while(n--)
{
rngfill (key, g);
Hasher h;
h.append(key.data(), KeySize);
volatile size_t temp =
static_cast<std::size_t>(h);
(void)temp;
}
auto const elapsed = clock_type::now() - start;
log << setw(12) << what << " " <<
duration<double>(elapsed) << "s";
}
void
run()
{
enum
{
N = 100000000
};
#if ! BEAST_NO_XXHASH
test<xxhasher,32> ("xxhash", N);
#endif
test<fnv1a,32> ("fnv1a", N);
test<siphash,32> ("siphash", N);
pass();
}
};
BEAST_DEFINE_TESTSUITE_MANUAL(hash_speed,container,beast);
} // beast

View File

@@ -24,18 +24,15 @@
//
//------------------------------------------------------------------------------
#include <beast/container/hash_append.h>
#include <beast/hash/siphash.h>
#include <algorithm>
#include <cstddef>
#include <cstdint>
// namespace acme is used to demonstrate example code. It is not proposed.
namespace beast
{
namespace
{
namespace beast {
namespace detail {
typedef std::uint64_t u64;
typedef std::uint32_t u32;
@@ -82,7 +79,7 @@ sipround(u64& v0, u64& v1, u64& v2, u64& v3)
v2 = rotl(v2, 32);
}
} // unnamed
} // detail
siphash::siphash(std::uint64_t k0, std::uint64_t k1) noexcept
{
@@ -95,6 +92,7 @@ siphash::siphash(std::uint64_t k0, std::uint64_t k1) noexcept
void
siphash::append (void const* key, std::size_t inlen) noexcept
{
using namespace detail;
u8 const* in = static_cast<const u8*>(key);
total_length_ += inlen;
if (bufsize_ + inlen < 8)
@@ -130,6 +128,7 @@ siphash::append (void const* key, std::size_t inlen) noexcept
siphash::operator std::size_t() noexcept
{
using namespace detail;
std::size_t b = static_cast<u64>(total_length_) << 56;
switch(bufsize_)
{
@@ -163,4 +162,4 @@ siphash::operator std::size_t() noexcept
return b;
}
} // beast
} // beast

View File

@@ -10,7 +10,7 @@
// August 5 2012: SpookyV2: d = should be d += in short hash, and remove extra mix from long hash
#include <memory.h>
#include <beast/container/impl/spookyv2.h>
#include <beast/hash/impl/spookyv2.h>
#ifdef _MSC_VER
#pragma warning (push)

View File

@@ -0,0 +1,934 @@
/*
xxHash - Fast Hash algorithm
Copyright (C) 2012-2014, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You can contact the author at :
- xxHash source repository : http://code.google.com/p/xxhash/
- public discussion board : https://groups.google.com/forum/#!forum/lz4c
*/
#include <beast/hash/impl/xxhash.h>
//**************************************
// Tuning parameters
//**************************************
// Unaligned memory access is automatically enabled for "common" CPU, such as x86.
// For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected.
// If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance.
// You can also enable this parameter if you know your input data will always be aligned (boundaries of 4, for U32).
#if defined(__ARM_FEATURE_UNALIGNED) || defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
# define XXH_USE_UNALIGNED_ACCESS 1
#endif
// XXH_ACCEPT_NULL_INPUT_POINTER :
// If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer.
// When this option is enabled, xxHash output for null input pointers will be the same as a null-length input.
// This option has a very small performance cost (only measurable on small inputs).
// By default, this option is disabled. To enable it, uncomment below define :
// #define XXH_ACCEPT_NULL_INPUT_POINTER 1
// XXH_FORCE_NATIVE_FORMAT :
// By default, xxHash library provides endian-independant Hash values, based on little-endian convention.
// Results are therefore identical for little-endian and big-endian CPU.
// This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
// Should endian-independance be of no importance for your application, you may set the #define below to 1.
// It will improve speed for Big-endian CPU.
// This option has no impact on Little_Endian CPU.
#define XXH_FORCE_NATIVE_FORMAT 0
//**************************************
// Compiler Specific Options
//**************************************
// Disable some Visual warning messages
#ifdef _MSC_VER // Visual Studio
# pragma warning(disable : 4127) // disable: C4127: conditional expression is constant
#endif
#ifdef _MSC_VER // Visual Studio
# define FORCE_INLINE static __forceinline
#else
# ifdef __GNUC__
# define FORCE_INLINE static inline __attribute__((always_inline))
# else
# define FORCE_INLINE static inline
# endif
#endif
//**************************************
// Includes & Memory related functions
//**************************************
//#include "xxhash.h"
// Modify the local functions below should you wish to use some other memory routines
// for malloc(), free()
#include <stdlib.h>
static void* XXH_malloc(size_t s) { return malloc(s); }
static void XXH_free (void* p) { free(p); }
// for memcpy()
#include <string.h>
static void* XXH_memcpy(void* dest, const void* src, size_t size)
{
return memcpy(dest,src,size);
}
//**************************************
// Basic Types
//**************************************
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L // C99
# include <stdint.h>
typedef uint8_t BYTE;
typedef uint16_t U16;
typedef uint32_t U32;
typedef int32_t S32;
typedef uint64_t U64;
#else
typedef unsigned char BYTE;
typedef unsigned short U16;
typedef unsigned int U32;
typedef signed int S32;
typedef unsigned long long U64;
#endif
#if defined(__GNUC__) && !defined(XXH_USE_UNALIGNED_ACCESS)
# define _PACKED __attribute__ ((packed))
#else
# define _PACKED
#endif
#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__)
# ifdef __IBMC__
# pragma pack(1)
# else
# pragma pack(push, 1)
# endif
#endif
namespace beast {
namespace detail {
typedef struct _U32_S
{
U32 v;
} _PACKED U32_S;
typedef struct _U64_S
{
U64 v;
} _PACKED U64_S;
#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__)
# pragma pack(pop)
#endif
#define A32(x) (((U32_S *)(x))->v)
#define A64(x) (((U64_S *)(x))->v)
//***************************************
// Compiler-specific Functions and Macros
//***************************************
#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
// Note : although _rotl exists for minGW (GCC under windows), performance seems poor
#if defined(_MSC_VER)
# define XXH_rotl32(x,r) _rotl(x,r)
# define XXH_rotl64(x,r) _rotl64(x,r)
#else
# define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))
# define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r)))
#endif
#if defined(_MSC_VER) // Visual Studio
# define XXH_swap32 _byteswap_ulong
# define XXH_swap64 _byteswap_uint64
#elif GCC_VERSION >= 403
# define XXH_swap32 __builtin_bswap32
# define XXH_swap64 __builtin_bswap64
#else
static inline U32 XXH_swap32 (U32 x)
{
return ((x << 24) & 0xff000000 ) |
((x << 8) & 0x00ff0000 ) |
((x >> 8) & 0x0000ff00 ) |
((x >> 24) & 0x000000ff );
}
static inline U64 XXH_swap64 (U64 x)
{
return ((x << 56) & 0xff00000000000000ULL) |
((x << 40) & 0x00ff000000000000ULL) |
((x << 24) & 0x0000ff0000000000ULL) |
((x << 8) & 0x000000ff00000000ULL) |
((x >> 8) & 0x00000000ff000000ULL) |
((x >> 24) & 0x0000000000ff0000ULL) |
((x >> 40) & 0x000000000000ff00ULL) |
((x >> 56) & 0x00000000000000ffULL);
}
#endif
//**************************************
// Constants
//**************************************
#define PRIME32_1 2654435761U
#define PRIME32_2 2246822519U
#define PRIME32_3 3266489917U
#define PRIME32_4 668265263U
#define PRIME32_5 374761393U
#define PRIME64_1 11400714785074694791ULL
#define PRIME64_2 14029467366897019727ULL
#define PRIME64_3 1609587929392839161ULL
#define PRIME64_4 9650029242287828579ULL
#define PRIME64_5 2870177450012600261ULL
//**************************************
// Architecture Macros
//**************************************
typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
#ifndef XXH_CPU_LITTLE_ENDIAN // It is possible to define XXH_CPU_LITTLE_ENDIAN externally, for example using a compiler switch
static const int one = 1;
# define XXH_CPU_LITTLE_ENDIAN (*(char*)(&one))
#endif
//**************************************
// Macros
//**************************************
#define XXH_STATIC_ASSERT(c) { enum { XXH_static_assert = 1/(!!(c)) }; } // use only *after* variable declarations
//****************************
// Memory reads
//****************************
typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
FORCE_INLINE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
{
if (align==XXH_unaligned)
return endian==XXH_littleEndian ? A32(ptr) : XXH_swap32(A32(ptr));
else
return endian==XXH_littleEndian ? *(U32*)ptr : XXH_swap32(*(U32*)ptr);
}
FORCE_INLINE U32 XXH_readLE32(const void* ptr, XXH_endianess endian)
{
return XXH_readLE32_align(ptr, endian, XXH_unaligned);
}
FORCE_INLINE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
{
if (align==XXH_unaligned)
return endian==XXH_littleEndian ? A64(ptr) : XXH_swap64(A64(ptr));
else
return endian==XXH_littleEndian ? *(U64*)ptr : XXH_swap64(*(U64*)ptr);
}
FORCE_INLINE U64 XXH_readLE64(const void* ptr, XXH_endianess endian)
{
return XXH_readLE64_align(ptr, endian, XXH_unaligned);
}
//****************************
// Simple Hash Functions
//****************************
FORCE_INLINE U32 XXH32_endian_align(const void* input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align)
{
const BYTE* p = (const BYTE*)input;
const BYTE* bEnd = p + len;
U32 h32;
#define XXH_get32bits(p) XXH_readLE32_align(p, endian, align)
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
if (p==NULL)
{
len=0;
bEnd=p=(const BYTE*)(size_t)16;
}
#endif
if (len>=16)
{
const BYTE* const limit = bEnd - 16;
U32 v1 = seed + PRIME32_1 + PRIME32_2;
U32 v2 = seed + PRIME32_2;
U32 v3 = seed + 0;
U32 v4 = seed - PRIME32_1;
do
{
v1 += XXH_get32bits(p) * PRIME32_2;
v1 = XXH_rotl32(v1, 13);
v1 *= PRIME32_1;
p+=4;
v2 += XXH_get32bits(p) * PRIME32_2;
v2 = XXH_rotl32(v2, 13);
v2 *= PRIME32_1;
p+=4;
v3 += XXH_get32bits(p) * PRIME32_2;
v3 = XXH_rotl32(v3, 13);
v3 *= PRIME32_1;
p+=4;
v4 += XXH_get32bits(p) * PRIME32_2;
v4 = XXH_rotl32(v4, 13);
v4 *= PRIME32_1;
p+=4;
}
while (p<=limit);
h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
}
else
{
h32 = seed + PRIME32_5;
}
h32 += (U32) len;
while (p+4<=bEnd)
{
h32 += XXH_get32bits(p) * PRIME32_3;
h32 = XXH_rotl32(h32, 17) * PRIME32_4 ;
p+=4;
}
while (p<bEnd)
{
h32 += (*p) * PRIME32_5;
h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
p++;
}
h32 ^= h32 >> 15;
h32 *= PRIME32_2;
h32 ^= h32 >> 13;
h32 *= PRIME32_3;
h32 ^= h32 >> 16;
return h32;
}
unsigned int XXH32 (const void* input, size_t len, unsigned seed)
{
#if 0
// Simple version, good for code maintenance, but unfortunately slow for small inputs
XXH32_state_t state;
XXH32_reset(&state, seed);
XXH32_update(&state, input, len);
return XXH32_digest(&state);
#else
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
# if !defined(XXH_USE_UNALIGNED_ACCESS)
if ((((size_t)input) & 3) == 0) // Input is aligned, let's leverage the speed advantage
{
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
else
return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
}
# endif
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
else
return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
#endif
}
FORCE_INLINE U64 XXH64_endian_align(const void* input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align)
{
const BYTE* p = (const BYTE*)input;
const BYTE* bEnd = p + len;
U64 h64;
#define XXH_get64bits(p) XXH_readLE64_align(p, endian, align)
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
if (p==NULL)
{
len=0;
bEnd=p=(const BYTE*)(size_t)32;
}
#endif
if (len>=32)
{
const BYTE* const limit = bEnd - 32;
U64 v1 = seed + PRIME64_1 + PRIME64_2;
U64 v2 = seed + PRIME64_2;
U64 v3 = seed + 0;
U64 v4 = seed - PRIME64_1;
do
{
v1 += XXH_get64bits(p) * PRIME64_2;
p+=8;
v1 = XXH_rotl64(v1, 31);
v1 *= PRIME64_1;
v2 += XXH_get64bits(p) * PRIME64_2;
p+=8;
v2 = XXH_rotl64(v2, 31);
v2 *= PRIME64_1;
v3 += XXH_get64bits(p) * PRIME64_2;
p+=8;
v3 = XXH_rotl64(v3, 31);
v3 *= PRIME64_1;
v4 += XXH_get64bits(p) * PRIME64_2;
p+=8;
v4 = XXH_rotl64(v4, 31);
v4 *= PRIME64_1;
}
while (p<=limit);
h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
v1 *= PRIME64_2;
v1 = XXH_rotl64(v1, 31);
v1 *= PRIME64_1;
h64 ^= v1;
h64 = h64 * PRIME64_1 + PRIME64_4;
v2 *= PRIME64_2;
v2 = XXH_rotl64(v2, 31);
v2 *= PRIME64_1;
h64 ^= v2;
h64 = h64 * PRIME64_1 + PRIME64_4;
v3 *= PRIME64_2;
v3 = XXH_rotl64(v3, 31);
v3 *= PRIME64_1;
h64 ^= v3;
h64 = h64 * PRIME64_1 + PRIME64_4;
v4 *= PRIME64_2;
v4 = XXH_rotl64(v4, 31);
v4 *= PRIME64_1;
h64 ^= v4;
h64 = h64 * PRIME64_1 + PRIME64_4;
}
else
{
h64 = seed + PRIME64_5;
}
h64 += (U64) len;
while (p+8<=bEnd)
{
U64 k1 = XXH_get64bits(p);
k1 *= PRIME64_2;
k1 = XXH_rotl64(k1,31);
k1 *= PRIME64_1;
h64 ^= k1;
h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
p+=8;
}
if (p+4<=bEnd)
{
h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1;
h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
p+=4;
}
while (p<bEnd)
{
h64 ^= (*p) * PRIME64_5;
h64 = XXH_rotl64(h64, 11) * PRIME64_1;
p++;
}
h64 ^= h64 >> 33;
h64 *= PRIME64_2;
h64 ^= h64 >> 29;
h64 *= PRIME64_3;
h64 ^= h64 >> 32;
return h64;
}
unsigned long long XXH64 (const void* input, size_t len, unsigned long long seed)
{
#if 0
// Simple version, good for code maintenance, but unfortunately slow for small inputs
XXH64_state_t state;
XXH64_reset(&state, seed);
XXH64_update(&state, input, len);
return XXH64_digest(&state);
#else
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
# if !defined(XXH_USE_UNALIGNED_ACCESS)
if ((((size_t)input) & 7)==0) // Input is aligned, let's leverage the speed advantage
{
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
else
return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
}
# endif
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
else
return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
#endif
}
/****************************************************
* Advanced Hash Functions
****************************************************/
/*** Allocation ***/
typedef struct
{
U64 total_len;
U32 seed;
U32 v1;
U32 v2;
U32 v3;
U32 v4;
U32 mem32[4]; /* defined as U32 for alignment */
U32 memsize;
} XXH_istate32_t;
typedef struct
{
U64 total_len;
U64 seed;
U64 v1;
U64 v2;
U64 v3;
U64 v4;
U64 mem64[4]; /* defined as U64 for alignment */
U32 memsize;
} XXH_istate64_t;
XXH32_state_t* XXH32_createState(void)
{
static_assert(sizeof(XXH32_state_t) >= sizeof(XXH_istate32_t), ""); // A compilation error here means XXH32_state_t is not large enough
return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t));
}
XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr)
{
XXH_free(statePtr);
return XXH_OK;
};
XXH64_state_t* XXH64_createState(void)
{
static_assert(sizeof(XXH64_state_t) >= sizeof(XXH_istate64_t), ""); // A compilation error here means XXH64_state_t is not large enough
return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t));
}
XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr)
{
XXH_free(statePtr);
return XXH_OK;
};
/*** Hash feed ***/
XXH_errorcode XXH32_reset(XXH32_state_t* state_in, U32 seed)
{
XXH_istate32_t* state = (XXH_istate32_t*) state_in;
state->seed = seed;
state->v1 = seed + PRIME32_1 + PRIME32_2;
state->v2 = seed + PRIME32_2;
state->v3 = seed + 0;
state->v4 = seed - PRIME32_1;
state->total_len = 0;
state->memsize = 0;
return XXH_OK;
}
XXH_errorcode XXH64_reset(XXH64_state_t* state_in, unsigned long long seed)
{
XXH_istate64_t* state = (XXH_istate64_t*) state_in;
state->seed = seed;
state->v1 = seed + PRIME64_1 + PRIME64_2;
state->v2 = seed + PRIME64_2;
state->v3 = seed + 0;
state->v4 = seed - PRIME64_1;
state->total_len = 0;
state->memsize = 0;
return XXH_OK;
}
FORCE_INLINE XXH_errorcode XXH32_update_endian (XXH32_state_t* state_in, const void* input, size_t len, XXH_endianess endian)
{
XXH_istate32_t* state = (XXH_istate32_t *) state_in;
const BYTE* p = (const BYTE*)input;
const BYTE* const bEnd = p + len;
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
if (input==NULL) return XXH_ERROR;
#endif
state->total_len += len;
if (state->memsize + len < 16) // fill in tmp buffer
{
XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len);
state->memsize += (U32)len;
return XXH_OK;
}
if (state->memsize) // some data left from previous update
{
XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, 16-state->memsize);
{
const U32* p32 = state->mem32;
state->v1 += XXH_readLE32(p32, endian) * PRIME32_2;
state->v1 = XXH_rotl32(state->v1, 13);
state->v1 *= PRIME32_1;
p32++;
state->v2 += XXH_readLE32(p32, endian) * PRIME32_2;
state->v2 = XXH_rotl32(state->v2, 13);
state->v2 *= PRIME32_1;
p32++;
state->v3 += XXH_readLE32(p32, endian) * PRIME32_2;
state->v3 = XXH_rotl32(state->v3, 13);
state->v3 *= PRIME32_1;
p32++;
state->v4 += XXH_readLE32(p32, endian) * PRIME32_2;
state->v4 = XXH_rotl32(state->v4, 13);
state->v4 *= PRIME32_1;
p32++;
}
p += 16-state->memsize;
state->memsize = 0;
}
if (p <= bEnd-16)
{
const BYTE* const limit = bEnd - 16;
U32 v1 = state->v1;
U32 v2 = state->v2;
U32 v3 = state->v3;
U32 v4 = state->v4;
do
{
v1 += XXH_readLE32(p, endian) * PRIME32_2;
v1 = XXH_rotl32(v1, 13);
v1 *= PRIME32_1;
p+=4;
v2 += XXH_readLE32(p, endian) * PRIME32_2;
v2 = XXH_rotl32(v2, 13);
v2 *= PRIME32_1;
p+=4;
v3 += XXH_readLE32(p, endian) * PRIME32_2;
v3 = XXH_rotl32(v3, 13);
v3 *= PRIME32_1;
p+=4;
v4 += XXH_readLE32(p, endian) * PRIME32_2;
v4 = XXH_rotl32(v4, 13);
v4 *= PRIME32_1;
p+=4;
}
while (p<=limit);
state->v1 = v1;
state->v2 = v2;
state->v3 = v3;
state->v4 = v4;
}
if (p < bEnd)
{
XXH_memcpy(state->mem32, p, bEnd-p);
state->memsize = (int)(bEnd-p);
}
return XXH_OK;
}
XXH_errorcode XXH32_update (XXH32_state_t* state_in, const void* input, size_t len)
{
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
return XXH32_update_endian(state_in, input, len, XXH_littleEndian);
else
return XXH32_update_endian(state_in, input, len, XXH_bigEndian);
}
FORCE_INLINE U32 XXH32_digest_endian (const XXH32_state_t* state_in, XXH_endianess endian)
{
XXH_istate32_t* state = (XXH_istate32_t*) state_in;
const BYTE * p = (const BYTE*)state->mem32;
BYTE* bEnd = (BYTE*)(state->mem32) + state->memsize;
U32 h32;
if (state->total_len >= 16)
{
h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18);
}
else
{
h32 = state->seed + PRIME32_5;
}
h32 += (U32) state->total_len;
while (p+4<=bEnd)
{
h32 += XXH_readLE32(p, endian) * PRIME32_3;
h32 = XXH_rotl32(h32, 17) * PRIME32_4;
p+=4;
}
while (p<bEnd)
{
h32 += (*p) * PRIME32_5;
h32 = XXH_rotl32(h32, 11) * PRIME32_1;
p++;
}
h32 ^= h32 >> 15;
h32 *= PRIME32_2;
h32 ^= h32 >> 13;
h32 *= PRIME32_3;
h32 ^= h32 >> 16;
return h32;
}
U32 XXH32_digest (const XXH32_state_t* state_in)
{
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
return XXH32_digest_endian(state_in, XXH_littleEndian);
else
return XXH32_digest_endian(state_in, XXH_bigEndian);
}
FORCE_INLINE XXH_errorcode XXH64_update_endian (XXH64_state_t* state_in, const void* input, size_t len, XXH_endianess endian)
{
XXH_istate64_t * state = (XXH_istate64_t *) state_in;
const BYTE* p = (const BYTE*)input;
const BYTE* const bEnd = p + len;
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
if (input==NULL) return XXH_ERROR;
#endif
state->total_len += len;
if (state->memsize + len < 32) // fill in tmp buffer
{
XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len);
state->memsize += (U32)len;
return XXH_OK;
}
if (state->memsize) // some data left from previous update
{
XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, 32-state->memsize);
{
const U64* p64 = state->mem64;
state->v1 += XXH_readLE64(p64, endian) * PRIME64_2;
state->v1 = XXH_rotl64(state->v1, 31);
state->v1 *= PRIME64_1;
p64++;
state->v2 += XXH_readLE64(p64, endian) * PRIME64_2;
state->v2 = XXH_rotl64(state->v2, 31);
state->v2 *= PRIME64_1;
p64++;
state->v3 += XXH_readLE64(p64, endian) * PRIME64_2;
state->v3 = XXH_rotl64(state->v3, 31);
state->v3 *= PRIME64_1;
p64++;
state->v4 += XXH_readLE64(p64, endian) * PRIME64_2;
state->v4 = XXH_rotl64(state->v4, 31);
state->v4 *= PRIME64_1;
p64++;
}
p += 32-state->memsize;
state->memsize = 0;
}
if (p+32 <= bEnd)
{
const BYTE* const limit = bEnd - 32;
U64 v1 = state->v1;
U64 v2 = state->v2;
U64 v3 = state->v3;
U64 v4 = state->v4;
do
{
v1 += XXH_readLE64(p, endian) * PRIME64_2;
v1 = XXH_rotl64(v1, 31);
v1 *= PRIME64_1;
p+=8;
v2 += XXH_readLE64(p, endian) * PRIME64_2;
v2 = XXH_rotl64(v2, 31);
v2 *= PRIME64_1;
p+=8;
v3 += XXH_readLE64(p, endian) * PRIME64_2;
v3 = XXH_rotl64(v3, 31);
v3 *= PRIME64_1;
p+=8;
v4 += XXH_readLE64(p, endian) * PRIME64_2;
v4 = XXH_rotl64(v4, 31);
v4 *= PRIME64_1;
p+=8;
}
while (p<=limit);
state->v1 = v1;
state->v2 = v2;
state->v3 = v3;
state->v4 = v4;
}
if (p < bEnd)
{
XXH_memcpy(state->mem64, p, bEnd-p);
state->memsize = (int)(bEnd-p);
}
return XXH_OK;
}
XXH_errorcode XXH64_update (XXH64_state_t* state_in, const void* input, size_t len)
{
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
return XXH64_update_endian(state_in, input, len, XXH_littleEndian);
else
return XXH64_update_endian(state_in, input, len, XXH_bigEndian);
}
FORCE_INLINE U64 XXH64_digest_endian (const XXH64_state_t* state_in, XXH_endianess endian)
{
XXH_istate64_t * state = (XXH_istate64_t *) state_in;
const BYTE * p = (const BYTE*)state->mem64;
BYTE* bEnd = (BYTE*)state->mem64 + state->memsize;
U64 h64;
if (state->total_len >= 32)
{
U64 v1 = state->v1;
U64 v2 = state->v2;
U64 v3 = state->v3;
U64 v4 = state->v4;
h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
v1 *= PRIME64_2;
v1 = XXH_rotl64(v1, 31);
v1 *= PRIME64_1;
h64 ^= v1;
h64 = h64*PRIME64_1 + PRIME64_4;
v2 *= PRIME64_2;
v2 = XXH_rotl64(v2, 31);
v2 *= PRIME64_1;
h64 ^= v2;
h64 = h64*PRIME64_1 + PRIME64_4;
v3 *= PRIME64_2;
v3 = XXH_rotl64(v3, 31);
v3 *= PRIME64_1;
h64 ^= v3;
h64 = h64*PRIME64_1 + PRIME64_4;
v4 *= PRIME64_2;
v4 = XXH_rotl64(v4, 31);
v4 *= PRIME64_1;
h64 ^= v4;
h64 = h64*PRIME64_1 + PRIME64_4;
}
else
{
h64 = state->seed + PRIME64_5;
}
h64 += (U64) state->total_len;
while (p+8<=bEnd)
{
U64 k1 = XXH_readLE64(p, endian);
k1 *= PRIME64_2;
k1 = XXH_rotl64(k1,31);
k1 *= PRIME64_1;
h64 ^= k1;
h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
p+=8;
}
if (p+4<=bEnd)
{
h64 ^= (U64)(XXH_readLE32(p, endian)) * PRIME64_1;
h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
p+=4;
}
while (p<bEnd)
{
h64 ^= (*p) * PRIME64_5;
h64 = XXH_rotl64(h64, 11) * PRIME64_1;
p++;
}
h64 ^= h64 >> 33;
h64 *= PRIME64_2;
h64 ^= h64 >> 29;
h64 *= PRIME64_3;
h64 ^= h64 >> 32;
return h64;
}
unsigned long long XXH64_digest (const XXH64_state_t* state_in)
{
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
return XXH64_digest_endian(state_in, XXH_littleEndian);
else
return XXH64_digest_endian(state_in, XXH_bigEndian);
}
} // detail
} // beast

View File

@@ -0,0 +1,154 @@
/*
xxHash - Extremely Fast Hash algorithm
Header File
Copyright (C) 2012-2014, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You can contact the author at :
- xxHash source repository : http://code.google.com/p/xxhash/
*/
/* Notice extracted from xxHash homepage :
xxHash is an extremely fast Hash algorithm, running at RAM speed limits.
It also successfully passes all tests from the SMHasher suite.
Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz)
Name Speed Q.Score Author
xxHash 5.4 GB/s 10
CrapWow 3.2 GB/s 2 Andrew
MumurHash 3a 2.7 GB/s 10 Austin Appleby
SpookyHash 2.0 GB/s 10 Bob Jenkins
SBox 1.4 GB/s 9 Bret Mulvey
Lookup3 1.2 GB/s 9 Bob Jenkins
SuperFastHash 1.2 GB/s 1 Paul Hsieh
CityHash64 1.05 GB/s 10 Pike & Alakuijala
FNV 0.55 GB/s 5 Fowler, Noll, Vo
CRC32 0.43 GB/s 9
MD5-32 0.33 GB/s 10 Ronald L. Rivest
SHA1-32 0.28 GB/s 10
Q.Score is a measure of quality of the hash function.
It depends on successfully passing SMHasher test set.
10 is a perfect score.
*/
#ifndef BEAST_CONTAINER_XXHASH_H_INCLUDED
#define BEAST_CONTAINER_XXHASH_H_INCLUDED
/*****************************
Includes
*****************************/
#include <stddef.h> /* size_t */
namespace beast {
namespace detail {
/*****************************
Type
*****************************/
typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
/*****************************
Simple Hash Functions
*****************************/
unsigned int XXH32 (const void* input, size_t length, unsigned seed);
unsigned long long XXH64 (const void* input, size_t length, unsigned long long seed);
/*
XXH32() :
Calculate the 32-bits hash of sequence "length" bytes stored at memory address "input".
The memory between input & input+length must be valid (allocated and read-accessible).
"seed" can be used to alter the result predictably.
This function successfully passes all SMHasher tests.
Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s
XXH64() :
Calculate the 64-bits hash of sequence of length "len" stored at memory address "input".
*/
/*****************************
Advanced Hash Functions
*****************************/
typedef struct { long long ll[ 6]; } XXH32_state_t;
typedef struct { long long ll[11]; } XXH64_state_t;
/*
These structures allow static allocation of XXH states.
States must then be initialized using XXHnn_reset() before first use.
If you prefer dynamic allocation, please refer to functions below.
*/
XXH32_state_t* XXH32_createState(void);
XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr);
XXH64_state_t* XXH64_createState(void);
XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr);
/*
These functions create and release memory for XXH state.
States must then be initialized using XXHnn_reset() before first use.
*/
XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned seed);
XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length);
unsigned int XXH32_digest (const XXH32_state_t* statePtr);
XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, unsigned long long seed);
XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length);
unsigned long long XXH64_digest (const XXH64_state_t* statePtr);
/*
These functions calculate the xxHash of an input provided in multiple smaller packets,
as opposed to an input provided as a single block.
XXH state space must first be allocated, using either static or dynamic method provided above.
Start a new hash by initializing state with a seed, using XXHnn_reset().
Then, feed the hash state by calling XXHnn_update() as many times as necessary.
Obviously, input must be valid, meaning allocated and read accessible.
The function returns an error code, with 0 meaning OK, and any other value meaning there is an error.
Finally, you can produce a hash anytime, by using XXHnn_digest().
This function returns the final nn-bits hash.
You can nonetheless continue feeding the hash state with more input,
and therefore get some new hashes, by calling again XXHnn_digest().
When you are done, don't forget to free XXH state space, using typically XXHnn_freeState().
*/
} // detail
} // beast
#endif

View File

@@ -0,0 +1,59 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2014, Howard Hinnant <howard.hinnant@gmail.com>,
Vinnie Falco <vinnie.falco@gmail.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_HASH_SIPHASH_H_INCLUDED
#define BEAST_HASH_SIPHASH_H_INCLUDED
#include <beast/utility/noexcept.h>
#include <cstddef>
#include <cstdint>
namespace beast {
// See https://131002.net/siphash/
class siphash
{
private:
std::uint64_t v0_ = 0x736f6d6570736575ULL;
std::uint64_t v1_ = 0x646f72616e646f6dULL;
std::uint64_t v2_ = 0x6c7967656e657261ULL;
std::uint64_t v3_ = 0x7465646279746573ULL;
unsigned char buf_[8];
unsigned bufsize_ = 0;
unsigned total_length_ = 0;
public:
using result_type = std::size_t;
siphash() = default;
explicit
siphash (std::uint64_t k0, std::uint64_t k1 = 0) noexcept;
void
append (void const* key, std::size_t len) noexcept;
explicit
operator std::size_t() noexcept;
};
} // beast
#endif

View File

@@ -1,7 +1,8 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2014, Howard Hinnant <howard.hinnant@gmail.com>,
Vinnie Falco <vinnie.falco@gmail.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -17,30 +18,42 @@
*/
//==============================================================================
#ifndef BEAST_BOOST_GET_POINTER_H_INCLUDED
#define BEAST_BOOST_GET_POINTER_H_INCLUDED
#ifndef BEAST_HASH_SPOOKY_H_INCLUDED
#define BEAST_HASH_SPOOKY_H_INCLUDED
#include <boost/get_pointer.hpp>
#include <beast/hash/impl/spookyv2.h>
// Boost 1.55 incorrectly defines BOOST_NO_CXX11_SMART_PTR
// when building with clang 3.4 and earlier. This workaround
// gives beast its own overloads.
#ifdef BOOST_NO_CXX11_SMART_PTR
#include <memory>
namespace beast {
template <class T>
T* get_pointer (std::unique_ptr<T> const& p)
{
return p.get();
}
template <class T>
T* get_pointer (std::shared_ptr<T> const& p)
// See http://burtleburtle.net/bob/hash/spooky.html
class spooky
{
return p.get();
}
}
#endif
private:
SpookyHash state_;
public:
using result_type = std::size_t;
spooky (std::size_t seed1 = 1, std::size_t seed2 = 2) noexcept
{
state_.Init (seed1, seed2);
}
void
append (void const* key, std::size_t len) noexcept
{
state_.Update (key, len);
}
explicit
operator std::size_t() noexcept
{
std::uint64_t h1, h2;
state_.Final (&h1, &h2);
return static_cast <std::size_t> (h1);
}
};
} // beast
#endif

View File

@@ -17,21 +17,15 @@
*/
//==============================================================================
// MODULES: ../impl/spookyv2.cpp
#if BEAST_INCLUDE_BEASTCONFIG
#include <BeastConfig.h>
#endif
#include <beast/container/tests/hash_metrics.h>
#include <beast/container/hash_append.h>
#include <beast/container/impl/spookyv2.h>
#include <beast/hash/tests/hash_metrics.h>
#include <beast/hash/hash_append.h>
#include <beast/chrono/chrono_io.h>
#include <beast/unit_test/suite.h>
#include <beast/utility/type_name.h>
#include <array>
#include <algorithm>
#include <cstring>
@@ -40,8 +34,6 @@
namespace beast {
//------------------------------------------------------------------------------
template <class Block, class Derived>
class block_stream
{

View File

@@ -0,0 +1,86 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#if BEAST_INCLUDE_BEASTCONFIG
#include <BeastConfig.h>
#endif
#include <beast/hash/fnv1a.h>
#include <beast/hash/siphash.h>
#include <beast/hash/xxhasher.h>
#include <beast/chrono/chrono_io.h>
#include <beast/random/rngfill.h>
#include <beast/random/xor_shift_engine.h>
#include <beast/unit_test/suite.h>
#include <array>
#include <chrono>
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <random>
namespace beast {
class hash_speed_test : public beast::unit_test::suite
{
public:
using clock_type =
std::chrono::high_resolution_clock;
template <class Hasher, std::size_t KeySize>
void
test (std::string const& what, std::size_t n)
{
using namespace std;
using namespace std::chrono;
xor_shift_engine g(1);
array<std::uint8_t, KeySize> key;
auto const start = clock_type::now();
while(n--)
{
rngfill (key, g);
Hasher h;
h.append(key.data(), KeySize);
volatile size_t temp =
static_cast<std::size_t>(h);
(void)temp;
}
auto const elapsed = clock_type::now() - start;
log << setw(12) << what << " " <<
duration<double>(elapsed) << "s";
}
void
run()
{
enum
{
N = 100000000
};
#if ! BEAST_NO_XXHASH
test<xxhasher,32> ("xxhash", N);
#endif
test<fnv1a,32> ("fnv1a", N);
test<siphash,32> ("siphash", N);
pass();
}
};
BEAST_DEFINE_TESTSUITE_MANUAL(hash_speed,container,beast);
} // beast

View File

@@ -1,7 +1,8 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Copyright 2014, Howard Hinnant <howard.hinnant@gmail.com>,
Vinnie Falco <vinnie.falco@gmail.com
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -17,21 +18,29 @@
*/
//==============================================================================
#ifndef BEAST_CHRONO_ABSTRACT_CLOCK_IO_H_INCLUDED
#define BEAST_CHRONO_ABSTRACT_CLOCK_IO_H_INCLUDED
#ifndef BEAST_HASH_UHASH_H_INCLUDED
#define BEAST_HASH_UHASH_H_INCLUDED
#include <beast/chrono/chrono_io.h>
#include <beast/hash/spooky.h>
namespace beast {
template <class CharT, class Traits, class Duration, class Resolution>
std::basic_ostream <CharT, Traits>&
operator<< (std::basic_ostream <CharT, Traits>& os,
std::chrono::time_point <abstract_clock <Resolution>, Duration> const& tp)
// Universal hash function
template <class Hasher = spooky>
struct uhash
{
return os << tp.time_since_epoch() << " since epoch";
}
using result_type = typename Hasher::result_type;
}
template <class T>
result_type
operator()(T const& t) const noexcept
{
Hasher h;
hash_append (h, t);
return static_cast<result_type>(h);
}
};
} // beast
#endif

View File

@@ -0,0 +1,86 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2014, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_HASH_XXHASHER_H_INCLUDED
#define BEAST_HASH_XXHASHER_H_INCLUDED
#ifndef BEAST_NO_XXHASH
#define BEAST_NO_XXHASH 0
#endif
#if ! BEAST_NO_XXHASH
#include <beast/hash/impl/xxhash.h>
#include <beast/utility/noexcept.h>
#include <beast/cxx14/type_traits.h> // <type_traits>
#include <cstddef>
namespace beast {
class xxhasher
{
private:
// requires 64-bit std::size_t
static_assert(sizeof(std::size_t)==8, "");
detail::XXH64_state_t state_;
public:
using result_type = std::size_t;
xxhasher() noexcept
{
detail::XXH64_reset (&state_, 1);
}
template <class Seed,
std::enable_if_t<
std::is_unsigned<Seed>::value>* = nullptr>
explicit
xxhasher (Seed seed)
{
detail::XXH64_reset (&state_, seed);
}
template <class Seed,
std::enable_if_t<
std::is_unsigned<Seed>::value>* = nullptr>
xxhasher (Seed seed, Seed)
{
detail::XXH64_reset (&state_, seed);
}
void
append (void const* key, std::size_t len) noexcept
{
detail::XXH64_update (&state_, key, len);
}
explicit
operator std::size_t() noexcept
{
return detail::XXH64_digest(&state_);
}
};
} // beast
#endif
#endif

View File

@@ -27,6 +27,7 @@
#include <beast/http/impl/raw_parser.cpp>
#include <beast/http/impl/URL.cpp>
#include <beast/http/tests/chunked_encoder.test.cpp>
#include <beast/http/tests/parser.test.cpp>
#include <beast/http/tests/rfc2616.test.cpp>
#include <beast/http/tests/URL.test.cpp>

View File

@@ -50,17 +50,16 @@ public:
body (body const&) = delete;
body& operator= (body const&) = delete;
template <class = void>
void
clear();
void
write (void const* data, std::size_t bytes);
template <class ConstBufferSequence>
void
write (ConstBufferSequence const& buffers)
{
for (auto const& buffer : buffers)
write (boost::asio::buffer_cast <void const*> (buffer),
boost::asio::buffer_size (buffer));
}
write (ConstBufferSequence const& buffers);
std::size_t
size() const;
@@ -92,8 +91,9 @@ body::body()
inline
body::body (body&& other)
: buf_ (std::move(other.buf_))
{
buf_ = std::move(other.buf_);
other.clear();
}
inline
@@ -101,9 +101,17 @@ body&
body::operator= (body&& other)
{
buf_ = std::move(other.buf_);
other.clear();
return *this;
}
template <class>
void
body::clear()
{
buf_ = std::make_unique <buffer_type>();
}
inline
void
body::write (void const* data, std::size_t bytes)
@@ -112,6 +120,15 @@ body::write (void const* data, std::size_t bytes)
boost::asio::const_buffers_1 (data, bytes)));
}
template <class ConstBufferSequence>
void
body::write (ConstBufferSequence const& buffers)
{
for (auto const& buffer : buffers)
write (boost::asio::buffer_cast <void const*> (buffer),
boost::asio::buffer_size (buffer));
}
inline
std::size_t
body::size() const

View File

@@ -0,0 +1,285 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_HTTP_CHUNK_ENCODE_H_INCLUDED
#define BEAST_HTTP_CHUNK_ENCODE_H_INCLUDED
#include <boost/asio/buffer.hpp>
#include <algorithm>
#include <array>
#include <cassert>
#include <cstddef>
#include <iterator>
#include <beast/cxx14/type_traits.h> // <type_traits>
namespace beast {
namespace http {
namespace detail {
template <class Buffers>
class chunk_encoded_buffers
{
private:
using const_buffer = boost::asio::const_buffer;
Buffers buffers_;
const_buffer head_;
const_buffer tail_;
// Storage for the longest hex string we might need, plus delimiters.
std::array<char, 2 * sizeof(std::size_t) + 2> data_;
public:
using value_type = boost::asio::const_buffer;
class const_iterator;
chunk_encoded_buffers() = delete;
chunk_encoded_buffers (chunk_encoded_buffers const&) = default;
chunk_encoded_buffers& operator= (chunk_encoded_buffers const&) = default;
chunk_encoded_buffers (Buffers const& buffers, bool final_chunk);
const_iterator
begin() const
{
return const_iterator(*this, false);
}
const_iterator
end() const
{
return const_iterator(*this, true);
}
private:
// Unchecked conversion of unsigned to hex string
template<class OutIter, class Unsigned>
static
std::enable_if_t<std::is_unsigned<Unsigned>::value, OutIter>
to_hex(OutIter const first, OutIter const last, Unsigned n);
};
template <class Buffers>
class chunk_encoded_buffers<Buffers>::const_iterator
: public std::iterator<std::bidirectional_iterator_tag, const_buffer>
{
private:
using iterator = typename Buffers::const_iterator;
enum class Where { head, input, end };
chunk_encoded_buffers const* buffers_;
Where where_;
iterator iter_;
public:
const_iterator();
const_iterator (const_iterator const&) = default;
const_iterator& operator= (const_iterator const&) = default;
bool operator== (const_iterator const& other) const;
bool operator!= (const_iterator const& other) const;
const_iterator& operator++();
const_iterator& operator--();
const_iterator operator++(int) const;
const_iterator operator--(int) const;
const_buffer operator*() const;
private:
friend class chunk_encoded_buffers;
const_iterator(chunk_encoded_buffers const& buffers, bool past_the_end);
};
//------------------------------------------------------------------------------
template <class Buffers>
chunk_encoded_buffers<Buffers>::chunk_encoded_buffers (
Buffers const& buffers, bool final_chunk)
: buffers_(buffers)
{
auto const size = boost::asio::buffer_size(buffers);
data_[data_.size() - 2] = '\r';
data_[data_.size() - 1] = '\n';
auto pos = to_hex(data_.begin(), data_.end() - 2, size);
head_ = const_buffer(&*pos,
std::distance(pos, data_.end()));
if (size > 0 && final_chunk)
tail_ = const_buffer("\r\n0\r\n\r\n", 7);
else
tail_ = const_buffer("\r\n", 2);
}
template <class Buffers>
template <class OutIter, class Unsigned>
std::enable_if_t<std::is_unsigned<Unsigned>::value, OutIter>
chunk_encoded_buffers<Buffers>::to_hex(
OutIter const first, OutIter const last, Unsigned n)
{
assert(first != last);
OutIter iter = last;
if(n == 0)
{
*--iter = '0';
return iter;
}
while(n)
{
assert(iter != first);
*--iter = "0123456789abcdef"[n&0xf];
n>>=4;
}
return iter;
}
template <class Buffers>
chunk_encoded_buffers<Buffers>::const_iterator::const_iterator()
: where_(Where::end)
, buffers_(nullptr)
{
}
template <class Buffers>
bool
chunk_encoded_buffers<Buffers>::const_iterator::operator==(
const_iterator const& other) const
{
return buffers_ == other.buffers_ &&
where_ == other.where_ && iter_ == other.iter_;
}
template <class Buffers>
bool
chunk_encoded_buffers<Buffers>::const_iterator::operator!=(
const_iterator const& other) const
{
return buffers_ != other.buffers_ ||
where_ != other.where_ || iter_ != other.iter_;
}
template <class Buffers>
auto
chunk_encoded_buffers<Buffers>::const_iterator::operator++() ->
const_iterator&
{
assert(buffers_);
assert(where_ != Where::end);
if (where_ == Where::head)
where_ = Where::input;
else if (iter_ != buffers_->buffers_.end())
++iter_;
else
where_ = Where::end;
return *this;
}
template <class Buffers>
auto
chunk_encoded_buffers<Buffers>::const_iterator::operator--() ->
const_iterator&
{
assert(buffers_);
assert(where_ != Where::begin);
if (where_ == Where::end)
where_ = Where::input;
else if (iter_ != buffers_->buffers_.begin())
--iter_;
else
where_ = Where::head;
return *this;
}
template <class Buffers>
auto
chunk_encoded_buffers<Buffers>::const_iterator::operator++(int) const ->
const_iterator
{
auto iter = *this;
++iter;
return iter;
}
template <class Buffers>
auto
chunk_encoded_buffers<Buffers>::const_iterator::operator--(int) const ->
const_iterator
{
auto iter = *this;
--iter;
return iter;
}
template <class Buffers>
auto
chunk_encoded_buffers<Buffers>::const_iterator::operator*() const ->
const_buffer
{
assert(buffers_);
assert(where_ != Where::end);
if (where_ == Where::head)
return buffers_->head_;
if (iter_ != buffers_->buffers_.end())
return *iter_;
return buffers_->tail_;
}
template <class Buffers>
chunk_encoded_buffers<Buffers>::const_iterator::const_iterator(
chunk_encoded_buffers const& buffers, bool past_the_end)
: buffers_(&buffers)
, where_(past_the_end ? Where::end : Where::head)
, iter_(past_the_end ? buffers_->buffers_.end() :
buffers_->buffers_.begin())
{
}
}
/** Returns a chunk-encoded BufferSequence.
See:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1
@tparam Buffers A type meeting the requirements of BufferSequence.
@param buffers The input buffer sequence.
@param final_chunk `true` If this should include a final-chunk.
@return A chunk-encoded ConstBufferSeqeunce representing the input.
*/
/** @{ */
template <class Buffers>
detail::chunk_encoded_buffers<Buffers>
chunk_encode (Buffers const& buffers,
bool final_chunk = false)
{
return detail::chunk_encoded_buffers<
Buffers>(buffers, final_chunk);
}
// Returns a chunked encoding final chunk.
inline
boost::asio::const_buffers_1
chunk_encode_final()
{
return boost::asio::const_buffers_1(
"0\r\n\r\n", 5);
}
/** @} */
} // http
} // beast
#endif

View File

@@ -38,11 +38,7 @@ namespace http {
class headers
{
public:
struct value_type
{
std::string field;
std::string value;
};
using value_type = std::pair<std::string, std::string>;
private:
struct element
@@ -139,6 +135,13 @@ public:
void
clear() noexcept;
/** Remove a field.
@return The number of fields removed.
*/
template <class = void>
std::size_t
erase (std::string const& field);
/** Append a field value.
If a field value already exists the new value will be
extended as per RFC2616 Section 4.2.
@@ -164,8 +167,8 @@ template <class>
headers::element::element (
std::string const& f, std::string const& v)
{
data.field = f;
data.value = v;
data.first = f;
data.second = v;
}
template <class String>
@@ -173,7 +176,7 @@ bool
headers::less::operator() (
String const& lhs, element const& rhs) const
{
return beast::ci_less::operator() (lhs, rhs.data.field);
return beast::ci_less::operator() (lhs, rhs.data.first);
}
template <class String>
@@ -181,7 +184,7 @@ bool
headers::less::operator() (
element const& lhs, String const& rhs) const
{
return beast::ci_less::operator() (lhs.data.field, rhs);
return beast::ci_less::operator() (lhs.data.first, rhs);
}
//------------------------------------------------------------------------------
@@ -210,7 +213,7 @@ inline
headers::headers (headers const& other)
{
for (auto const& e : other.list_)
append (e.data.field, e.data.value);
append (e.data.first, e.data.second);
}
inline
@@ -219,7 +222,7 @@ headers::operator= (headers const& other)
{
clear();
for (auto const& e : other.list_)
append (e.data.field, e.data.value);
append (e.data.first, e.data.second);
return *this;
}
@@ -269,7 +272,7 @@ headers::operator[] (std::string const& field) const
auto const found (find (field));
if (found == end())
return none;
return found->value;
return found->second;
}
template <class>
@@ -280,6 +283,20 @@ headers::clear() noexcept
delete &(*iter++);
}
template <class>
std::size_t
headers::erase (std::string const& field)
{
auto const iter = set_.find(field, less{});
if (iter == set_.end())
return 0;
element& e = *iter;
set_.erase(set_.iterator_to(e));
list_.erase(list_.iterator_to(e));
delete &e;
return 1;
}
template <class>
void
headers::append (std::string const& field,
@@ -296,7 +313,7 @@ headers::append (std::string const& field,
}
// If field already exists, append comma
// separated value as per RFC2616 section 4.2
auto& cur (result.first->data.value);
auto& cur (result.first->data.second);
cur.reserve (cur.size() + 1 + value.size());
cur.append (1, ',');
cur.append (value);
@@ -304,6 +321,36 @@ headers::append (std::string const& field,
//------------------------------------------------------------------------------
template <class Streambuf>
void
write (Streambuf& stream, std::string const& s)
{
stream.commit (boost::asio::buffer_copy (
stream.prepare (s.size()), boost::asio::buffer(s)));
}
template <class Streambuf>
void
write (Streambuf& stream, char const* s)
{
auto const len (::strlen(s));
stream.commit (boost::asio::buffer_copy (
stream.prepare (len), boost::asio::buffer (s, len)));
}
template <class Streambuf>
void
write (Streambuf& stream, headers const& h)
{
for (auto const& _ : h)
{
write (stream, _.first);
write (stream, ": ");
write (stream, _.second);
write (stream, "\r\n");
}
}
template <class>
std::string
to_string (headers const& h)
@@ -311,13 +358,13 @@ to_string (headers const& h)
std::string s;
std::size_t n (0);
for (auto const& e : h)
n += e.field.size() + 2 + e.value.size() + 2;
n += e.first.size() + 2 + e.second.size() + 2;
s.reserve (n);
for (auto const& e : h)
{
s.append (e.field);
s.append (e.first);
s.append (": ");
s.append (e.value);
s.append (e.second);
s.append ("\r\n");
}
return s;
@@ -338,10 +385,10 @@ build_map (headers const& h)
std::map <std::string, std::string> c;
for (auto const& e : h)
{
auto key (e.field);
auto key (e.first);
// TODO Replace with safe C++14 version
std::transform (key.begin(), key.end(), key.begin(), ::tolower);
c [key] = e.value;
c [key] = e.second;
}
return c;
}

View File

@@ -21,7 +21,6 @@
#define BEAST_HTTP_MESSAGE_H_INCLUDED
#include <beast/http/basic_parser.h>
#include <beast/http/body.h>
#include <beast/http/method.h>
#include <beast/http/headers.h>
#include <beast/utility/ci_char_traits.h>
@@ -31,11 +30,26 @@
#include <cctype>
#include <ostream>
#include <string>
#include <sstream>
#include <utility>
namespace beast {
namespace http {
inline
std::pair<int, int>
http_1_0()
{
return std::pair<int, int>(1, 0);
}
inline
std::pair<int, int>
http_1_1()
{
return std::pair<int, int>(1, 1);
}
class message
{
private:
@@ -72,9 +86,8 @@ public:
#endif
// Memberspaces
// Memberspace
beast::http::headers headers;
beast::http::body body;
bool
request() const
@@ -180,6 +193,12 @@ public:
version_ = std::make_pair (major, minor);
}
void
version (std::pair<int, int> p)
{
version_ = p;
}
std::pair<int, int>
version() const
{
@@ -213,7 +232,6 @@ message::message (message&& other)
, keep_alive_ (other.keep_alive_)
, upgrade_ (other.upgrade_)
, headers (std::move(other.headers))
, body (std::move(other.body))
{
}
@@ -230,33 +248,15 @@ message::operator= (message&& other)
keep_alive_ = other.keep_alive_;
upgrade_ = other.upgrade_;
headers = std::move(other.headers);
body = std::move(other.body);
return *this;
}
#endif
//------------------------------------------------------------------------------
template <class AsioStreamBuf>
template <class Streambuf>
void
write (AsioStreamBuf& stream, std::string const& s)
{
stream.commit (boost::asio::buffer_copy (
stream.prepare (s.size()), boost::asio::buffer(s)));
}
template <class AsioStreamBuf>
void
write (AsioStreamBuf& stream, char const* s)
{
auto const len (::strlen(s));
stream.commit (boost::asio::buffer_copy (
stream.prepare (len), boost::asio::buffer (s, len)));
}
template <class AsioStreamBuf>
void
write (AsioStreamBuf& stream, message const& m)
write (Streambuf& stream, message const& m)
{
if (m.request())
{
@@ -280,13 +280,7 @@ write (AsioStreamBuf& stream, message const& m)
write (stream, m.reason());
}
write (stream, "\r\n");
for (auto const& header : m.headers)
{
write (stream, header.field);
write (stream, ": ");
write (stream, header.value);
write (stream, "\r\n");
}
write(stream, m.headers);
write (stream, "\r\n");
}
@@ -311,4 +305,4 @@ to_string (message const& m)
} // http
} // beast
#endif
#endif

View File

@@ -21,6 +21,8 @@
#define BEAST_HTTP_PARSER_H_INCLUDED
#include <beast/http/message.h>
#include <beast/http/body.h>
#include <functional>
#include <string>
#include <utility>
@@ -34,15 +36,33 @@ class parser : public beast::http::basic_parser
{
private:
std::reference_wrapper <message> message_;
std::function<void(void const*, std::size_t)> write_body_;
public:
/** Construct a parser for HTTP request or response.
The result is stored in the passed message.
The headers plus request or status line are stored in message.
The content-body, if any, is passed as a series of calls to
the write_body function. Transfer encodings are applied before
any data is passed to the write_body function.
*/
parser (message& m, bool request)
parser (std::function<void(void const*, std::size_t)> write_body,
message& m, bool request)
: beast::http::basic_parser (request)
, message_(m)
, write_body_(std::move(write_body))
{
message_.get().request(request);
}
parser (message& m, body& b, bool request)
: beast::http::basic_parser (request)
, message_(m)
{
write_body_ = [&b](void const* data, std::size_t size)
{
b.write(data, size);
};
message_.get().request(request);
}
@@ -135,7 +155,7 @@ parser::operator= (parser&& other)
template <class>
void
parser::do_start ()
parser::do_start()
{
}
@@ -176,7 +196,7 @@ template <class>
void
parser::do_body (void const* data, std::size_t bytes)
{
message_.get().body.write (data, bytes);
write_body_(data, bytes);
}
template <class>

View File

@@ -20,12 +20,14 @@
#ifndef BEAST_HTTP_RFC2616_H_INCLUDED
#define BEAST_HTTP_RFC2616_H_INCLUDED
#include <boost/regex.hpp>
#include <algorithm>
#include <string>
#include <iterator>
#include <utility>
#include <vector>
namespace beast {
namespace http {
/** Routines for performing RFC2616 compliance.
RFC2616:
@@ -129,8 +131,8 @@ trim (String const& s)
{
using std::begin;
using std::end;
auto first (begin(s));
auto last (end(s));
auto first = begin(s);
auto last = end(s);
std::tie (first, last) = trim (first, last);
return { first, last };
}
@@ -154,21 +156,25 @@ trim (std::string const& s)
return trim <std::string> (s);
}
/** Call a functor for each comma delimited element.
Quotes and escape sequences will be parsed and converted appropriately.
Excess white space, commas, double quotes, and empty elements are not
passed to func.
/** Parse a character sequence of values separated by commas.
Double quotes and escape sequences will be converted. Excess white
space, commas, double quotes, and empty elements are not copied.
Format:
#(token|quoted-string)
Reference:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2
*/
template <class FwdIter, class Function>
void
for_each_element (FwdIter first, FwdIter last, Function func)
template <class FwdIt,
class Result = std::vector<
std::basic_string<typename FwdIt::value_type>>,
class Char>
Result
split(FwdIt first, FwdIt last, Char delim)
{
FwdIter iter (first);
std::string e;
Result result;
using string = typename Result::value_type;
FwdIt iter = first;
string e;
while (iter != last)
{
if (*iter == '"')
@@ -198,16 +204,16 @@ for_each_element (FwdIter first, FwdIter last, Function func)
}
if (! e.empty())
{
func (e);
result.emplace_back(std::move(e));
e.clear();
}
}
else if (*iter == ',')
else if (*iter == delim)
{
e = trim_right (e);
if (! e.empty())
{
func (e);
result.emplace_back(std::move(e));
e.clear();
}
++iter;
@@ -226,13 +232,29 @@ for_each_element (FwdIter first, FwdIter last, Function func)
{
e = trim_right (e);
if (! e.empty())
func (e);
result.emplace_back(std::move(e));
}
return result;
}
template <class FwdIt,
class Result = std::vector<
std::basic_string<typename FwdIt::value_type>>>
Result
split_commas(FwdIt first, FwdIt last)
{
return split(first, last, ',');
}
template <class Result = std::vector<std::string>>
Result
split_commas(std::string const& s)
{
return split_commas(s.begin(), s.end());
}
} // rfc2616
} // http
} // beast
#endif

View File

@@ -0,0 +1,151 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <beast/asio/streambuf.h>
#include <beast/http/chunk_encode.h>
#include <beast/unit_test/suite.h>
namespace beast {
namespace http {
class chunk_encode_test : public unit_test::suite
{
public:
// Convert CR LF to printables for display
static
std::string
encode (std::string const& s)
{
std::string result;
for(auto const c : s)
{
if (c == '\r')
result += "\\r";
else if (c== '\n')
result += "\\n";
else
result += c;
}
return result;
}
// Print the contents of a ConstBufferSequence to the log
template <class ConstBufferSequence, class Log>
static
void
print (ConstBufferSequence const& buffers, Log log)
{
for(auto const& buf : buffers)
log << encode (std::string(
boost::asio::buffer_cast<char const*>(buf),
boost::asio::buffer_size(buf)));
}
// Convert a ConstBufferSequence to a string
template <class ConstBufferSequence>
static
std::string
buffer_to_string (ConstBufferSequence const& b)
{
std::string s;
auto const n = boost::asio::buffer_size(b);
s.resize(n);
boost::asio::buffer_copy(
boost::asio::buffer(&s[0], n), b);
return s;
}
// Append a ConstBufferSequence to an existing string
template <class ConstBufferSequence>
static
void
buffer_append (std::string& s, ConstBufferSequence const& b)
{
s += buffer_to_string(b);
}
// Convert the input sequence of the stream to a
// chunked-encoded string. The input sequence is consumed.
template <class Streambuf>
static
std::string
streambuf_to_string (Streambuf& sb,
bool final_chunk = false)
{
std::string s;
buffer_append(s, chunk_encode(sb.data(), final_chunk));
return s;
}
// Check an input against the correct chunk encoded version
void
check (std::string const& in, std::string const& answer,
bool final_chunk = true)
{
asio::streambuf sb(3);
sb << in;
auto const out = streambuf_to_string (sb, final_chunk);
if (! expect (out == answer))
log << "expected\n" << encode(answer) <<
"\ngot\n" << encode(out);
}
void testStreambuf()
{
asio::streambuf sb(3);
std::string const s =
"0123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789";
sb << s;
expect(buffer_to_string(sb.data()) == s);
}
void
testEncoder()
{
check("", "0\r\n\r\n");
check("x", "1\r\nx\r\n0\r\n\r\n");
check("abcd", "4\r\nabcd\r\n0\r\n\r\n");
check("x", "1\r\nx\r\n", false);
check(
"0123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789"
,
"d2\r\n"
"0123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789012345678901234567890123456789"
"\r\n"
"0\r\n\r\n");
}
void
run()
{
testStreambuf();
testEncoder();
}
};
BEAST_DEFINE_TESTSUITE(chunk_encode,http,beast);
}
}

View File

@@ -20,6 +20,7 @@
#include <beast/http/message.h>
#include <beast/http/parser.h>
#include <beast/unit_test/suite.h>
#include <utility>
namespace beast {
namespace http {
@@ -31,7 +32,8 @@ public:
request (std::string const& text)
{
message m;
parser p (m, true);
body b;
parser p (m, b, true);
auto result (p.write (boost::asio::buffer(text)));
p.write_eof();
return std::make_pair (std::move(m), result.first);
@@ -56,16 +58,27 @@ public:
log << "|" << result.first.headers["Field"] << "|";
}
void
test_headers()
{
headers h;
h.append("Field", "Value");
expect (h.erase("Field") == 1);
}
void
run()
{
test_headers();
{
std::string const text =
"GET / HTTP/1.1\r\n"
"\r\n"
;
message m;
parser p (m, true);
body b;
parser p (m, b, true);
auto result (p.write (boost::asio::buffer(text)));
expect (! result.first);
auto result2 (p.write_eof());
@@ -80,7 +93,8 @@ public:
"\r\n"
;
message m;
parser p (m, true);
body b;
parser p (m, b, true);
auto result = p.write (boost::asio::buffer(text));
if (expect (result.first))
expect (result.first.message() == "invalid HTTP method");

View File

@@ -27,62 +27,56 @@
#include <vector>
namespace beast {
namespace http {
namespace rfc2616 {
class rfc2616_test : public beast::unit_test::suite
{
public:
void
check (std::string const& value,
check (std::string const& s,
std::vector <std::string> const& expected)
{
std::vector <std::string> parsed;
for_each_element (value.begin(), value.end(),
[&](std::string const& element)
{
parsed.push_back (element);
});
auto const parsed = split_commas(s.begin(), s.end());
expect (parsed == expected);
}
void test_split_commas()
{
testcase("split_commas");
check ("", {});
check (" ", {});
check (" ", {});
check ("\t", {});
check (" \t ", {});
check (",", {});
check (",,", {});
check (" ,", {});
check (" , ,", {});
check ("x", {"x"});
check (" x", {"x"});
check (" \t x", {"x"});
check ("x ", {"x"});
check ("x \t", {"x"});
check (" \t x \t ", {"x"});
check ("\"\"", {});
check (" \"\"", {});
check ("\"\" ", {});
check ("\"x\"", {"x"});
check ("\" \"", {" "});
check ("\" x\"", {" x"});
check ("\"x \"", {"x "});
check ("\" x \"", {" x "});
check ("\"\tx \"", {"\tx "});
check ("x,y", { "x", "y" });
check ("x ,\ty ", { "x", "y" });
check ("x, y, z", {"x","y","z"});
check ("x, \"y\", z", {"x","y","z"});
}
void
run()
{
check ("", {});
check (" ", {});
check (" ", {});
check ("\t", {});
check (" \t ", {});
check (",", {});
check (",,", {});
check (" ,", {});
check (" , ,", {});
check ("x", {"x"});
check (" x", {"x"});
check (" \t x", {"x"});
check ("x ", {"x"});
check ("x \t", {"x"});
check (" \t x \t ", {"x"});
check ("\"\"", {});
check (" \"\"", {});
check ("\"\" ", {});
check ("\"x\"", {"x"});
check ("\" \"", {" "});
check ("\" x\"", {" x"});
check ("\"x \"", {"x "});
check ("\" x \"", {" x "});
check ("\"\tx \"", {"\tx "});
check ("x,y", { "x", "y" });
check ("x ,\ty ", { "x", "y" });
check ("x, y, z", {"x","y","z"});
check ("x, \"y\", z", {"x","y","z"});
test_split_commas();
}
};
@@ -90,4 +84,3 @@ BEAST_DEFINE_TESTSUITE(rfc2616,http,beast);
}
}
}

View File

@@ -18,8 +18,8 @@
//==============================================================================
#include <unordered_map>
#include <beast/cxx14/memory.h>
#include <beast/hash/uhash.h>
#include <beast/cxx14/memory.h> // <memory>
namespace beast {
namespace insight {

View File

@@ -83,8 +83,8 @@ public:
void removeReference ()
{
if (--m_pending)
(static_cast <Derived *> (this))->asyncHandlersComplete ();
if (--m_pending == 0)
(static_cast<Derived*>(this))->asyncHandlersComplete();
}
private:

View File

@@ -24,8 +24,9 @@
#ifndef BEAST_ELEMENTCOMPARATOR_H_INCLUDED
#define BEAST_ELEMENTCOMPARATOR_H_INCLUDED
namespace beast
{
#include <algorithm>
namespace beast {
#ifndef DOXYGEN

View File

@@ -41,7 +41,6 @@
// New header-only library modeled more closely according to boost
#include <beast/SmartPtr.h>
#include <beast/Atomic.h>
#include <beast/Arithmetic.h>
#include <beast/ByteOrder.h>
#include <beast/HeapBlock.h>

View File

@@ -18,111 +18,58 @@
//==============================================================================
#include <beast/module/core/diagnostic/FatalError.h>
#include <beast/unit_test/suite.h>
#include <atomic>
#include <exception>
#include <iostream>
#include <mutex>
namespace beast {
//
// FatalError::Reporter
//
void FatalError::Reporter::onFatalError (
char const* message,
char const* backtrace,
char const* filePath,
int lineNumber)
{
reportMessage (formatMessage (message, backtrace, filePath, lineNumber));
}
void FatalError::Reporter::reportMessage (std::string const& message)
{
std::cerr << message << std::endl;
}
std::string FatalError::Reporter::formatMessage (
char const* message,
char const* backtrace,
char const* filePath,
int lineNumber)
{
std::string output;
output.reserve (16 * 1024);
output.append (message);
if (filePath != nullptr && filePath [0] != 0)
{
output.append (", in ");
output.append (formatFilePath (filePath));
output.append (" line ");
output.append (std::to_string (lineNumber));
}
output.append ("\n");
if (backtrace != nullptr && backtrace[0] != 0)
{
output.append ("Stack:\n");
output.append (backtrace);
}
return output;
}
std::string FatalError::Reporter::formatFilePath (char const* filePath)
{
return filePath;
}
//------------------------------------------------------------------------------
FatalError::Reporter *FatalError::s_reporter;
/** Returns the current fatal error reporter. */
FatalError::Reporter* FatalError::getReporter ()
void
FatalError (char const* message, char const* file, int line)
{
return s_reporter;
}
static std::atomic <int> error_count (0);
static std::recursive_mutex gate;
FatalError::Reporter* FatalError::setReporter (Reporter* reporter)
{
Reporter* const previous (s_reporter);
s_reporter = reporter;
return previous;
}
// We only allow one thread to report a fatal error. Other threads that
// encounter fatal errors while we are reporting get blocked here.
std::lock_guard<std::recursive_mutex> lock(gate);
FatalError::FatalError (char const* message, char const* fileName, int lineNumber)
{
typedef CriticalSection LockType;
// If we encounter a recursive fatal error, then we want to terminate
// unconditionally.
if (error_count++ != 0)
return std::terminate ();
static LockType s_mutex;
std::lock_guard <LockType> lock (s_mutex);
auto const backtrace = SystemStats::getStackBacktrace ();
Reporter* const reporter = s_reporter;
if (reporter != nullptr)
// We protect this entire block of code since writing to cerr might trigger
// exceptions.
try
{
reporter->onFatalError (message, backtrace.c_str (), fileName, lineNumber);
std::cerr << "An error has occurred. The application will terminate.\n";
if (message != nullptr && message [0] != 0)
std::cerr << "Message: " << message << '\n';
if (file != nullptr && file [0] != 0)
std::cerr << " File: " << file << ":" << line << '\n';
auto const backtrace = SystemStats::getStackBacktrace ();
if (!backtrace.empty ())
{
std::cerr << " Stack:" << std::endl;
for (auto const& frame : backtrace)
std::cerr << " " << frame << '\n';
}
}
catch (...)
{
// nothing we can do - just fall through and terminate
}
Process::terminate ();
return std::terminate ();
}
//------------------------------------------------------------------------------
class FatalError_test : public unit_test::suite
{
public:
void run ()
{
int shouldBeZero (1);
check_invariant (shouldBeZero == 0);
}
};
BEAST_DEFINE_TESTSUITE_MANUAL(FatalError,beast_core,beast);
} // beast

View File

@@ -32,128 +32,11 @@ namespace beast
would be to protect data integrity, prevent valuable resources from being
wasted, or to ensure that the user does not experience undefined behavior.
This function will end the process with exit code EXIT_FAILURE. Before
the process is terminated, a listener object gets notified so that the
client application can perform logging or emit further diagnostics.
If multiple threads raise an error, only one will succeed while the others
will be blocked before the process terminates.
*/
class FatalError
{
public:
struct Reporter
{
virtual ~Reporter() = default;
/** Called when a fatal error is raised.
Because the program is likely in an inconsistent state, it is a
good idea to do as little as possible from within this function.
It will be called from the thread that raised the fatal error.
The default implementation of this function first calls
formatMessage to produce the string, then calls reportMessage
to report the results.
You can override this to perform custom formatting.
@note filePath may be a zero length string if identifying
information was stripped from the executable for security.
@note stackBacktrace will be a string with zero characters for
platforms for which which don't support stack crawls, or
when symbolic information is missing from the executable.
@param message The error message.
@param stackBackTrace The stack of the thread that raised the error.
@param filePath A full or partial path to the source file that raised the error.
@param lineNumber The line number in the source file.
*/
virtual void onFatalError (char const* message,
char const* backtrace,
char const* filePath,
int lineNumber);
/** Called to report the message.
The default implementation simply writes this to standard error.
You can override this to perform additional things like logging
to a file or sending the message to another process.
@param formattedMessage The message to report.
*/
virtual void reportMessage (std::string const& formattedMessage);
protected:
/** Called to format the message.
The default implementation calls formatFilePath to produce
a formatted file name, and then creates a suitable string
containing all of the information.
You can override this function to format your own messages.
@param message The message from the report.
@param stackBacktrace The stack backtrace from the report.
@param filePath The file path from the report.
@param lineNumber The line number from the report
*/
virtual std::string formatMessage (
char const* message,
char const* backtrace,
char const* filePath,
int lineNumber);
/** Call to reformat the file path.
Usually the file is a full path, which we really don't care
to see and can also be a security hole.
The default implementation removes most of the useless
directory components from the front.
You can override this to do a custom format on the file path.
*/
virtual std::string formatFilePath (char const* filePath);
};
/** Returns the current fatal error reporter. */
static Reporter* getReporter ();
/** Set the fatal error reporter.
Note that if a fatal error is raised during the construction of
objects with static storage duration, it might not be possible to
set the reporter before the error is raised. The solution is not
to use objects with static storage duration that have non-trivial
constructors, use SharedSingleton instead.
The default behavior when no reporter is set is to invoke
the base class version of Reporter::onFatalError.
If a reporter was previously set, this routine will do nothing.
@return The previous Reporter (Which may be null).
@see SharedSingleton, Reporter
*/
static Reporter* setReporter (Reporter* reporter);
/** Raise a fatal error.
If multiple threads raise an error, only one will succeed. The
other threads will be blocked before the process terminates.
@param message A null terminated string, which should come from a constant.
@param filePath Pass __FILE__ here.
@param lineNumber Pass __LINE__ here.
*/
FatalError (char const* message, char const* filePath, int lineNumber);
FatalError(FatalError const&) = delete;
FatalError& operator= (FatalError const&) = delete;
private:
static Reporter* s_reporter;
};
void
FatalError (char const* message, char const* file = nullptr, int line = 0);
} // beast

View File

@@ -20,6 +20,9 @@
#ifndef BEAST_UNITTESTUTILITIES_H_INCLUDED
#define BEAST_UNITTESTUTILITIES_H_INCLUDED
#include <beast/module/core/files/File.h>
#include <beast/module/core/maths/Random.h>
namespace beast {
namespace UnitTestUtilities {
@@ -99,6 +102,31 @@ public:
HeapBlock <char> data;
};
class TempDirectory
{
public:
explicit TempDirectory (std::string const& root)
: directory (File::createTempFile (root))
{
}
~TempDirectory()
{
directory.deleteRecursively();
}
String const& getFullPathName() const
{
return directory.getFullPathName();
}
TempDirectory(const TempDirectory&) = delete;
TempDirectory& operator=(const TempDirectory&) = delete;
private:
File const directory;
};
} // UnitTestUtilities
} // beast

View File

@@ -24,8 +24,10 @@
#ifndef BEAST_RANDOM_H_INCLUDED
#define BEAST_RANDOM_H_INCLUDED
namespace beast
{
#include <cstddef>
#include <cstdint>
namespace beast {
//==============================================================================
/**

View File

@@ -24,6 +24,8 @@
#include <beast/smart_ptr/SharedPtr.h>
#include <beast/module/core/time/AtExitHook.h>
#include <atomic>
namespace beast
{
@@ -99,7 +101,7 @@ public:
bassert (lifetime == SingletonLifetime::createOnDemand || ! staticData.destructorCalled);
staticData.instance = &staticData.object;
new (staticData.instance) SharedSingleton (lifetime);
memoryBarrier();
std::atomic_thread_fence (std::memory_order_seq_cst);
instance = staticData.instance;
}
}

View File

@@ -21,6 +21,10 @@
*/
//==============================================================================
#include <cstdlib>
#include <iterator>
#include <memory>
// Some basic tests, to keep an eye on things and make sure these types work ok
// on all platforms.
@@ -48,20 +52,22 @@ SystemStats::getBeastVersion()
}
//==============================================================================
std::string
std::vector <std::string>
SystemStats::getStackBacktrace()
{
std::string result;
std::vector <std::string> result;
#if BEAST_ANDROID || BEAST_MINGW || BEAST_BSD
#if BEAST_ANDROID || BEAST_MINGW || BEAST_BSD
bassertfalse; // sorry, not implemented yet!
#elif BEAST_WINDOWS
#elif BEAST_WINDOWS
HANDLE process = GetCurrentProcess();
SymInitialize (process, nullptr, TRUE);
void* stack[128];
int frames = (int) CaptureStackBackTrace (0, numElementsInArray (stack), stack, nullptr);
int frames = (int) CaptureStackBackTrace (0,
std::distance(std::begin(stack), std::end(stack)),
stack, nullptr);
HeapBlock<SYMBOL_INFO> symbol;
symbol.calloc (sizeof (SYMBOL_INFO) + 256, 1);
@@ -74,7 +80,9 @@ SystemStats::getStackBacktrace()
if (SymFromAddr (process, (DWORD64) stack[i], &displacement, symbol))
{
result.append (std::to_string (i) + ": ");
std::string frame;
frame.append (std::to_string (i) + ": ");
IMAGEHLP_MODULE64 moduleInfo;
zerostruct (moduleInfo);
@@ -82,35 +90,33 @@ SystemStats::getStackBacktrace()
if (::SymGetModuleInfo64 (process, symbol->ModBase, &moduleInfo))
{
result.append (moduleInfo.ModuleName);
result.append (": ");
frame.append (moduleInfo.ModuleName);
frame.append (": ");
}
result.append (symbol->Name);
frame.append (symbol->Name);
if (displacement)
{
result.append ("+");
result.append (std::to_string (displacement));
frame.append ("+");
frame.append (std::to_string (displacement));
}
result.append ("\r\n");
result.push_back (frame);
}
}
#else
#else
void* stack[128];
int frames = backtrace (stack, numElementsInArray (stack));
char** frameStrings = backtrace_symbols (stack, frames);
int frames = backtrace (stack,
std::distance(std::begin(stack), std::end(stack)));
std::unique_ptr<char*[], void(*)(void*)> frame (
backtrace_symbols (stack, frames), std::free);
for (int i = 0; i < frames; ++i)
{
result.append (frameStrings[i]);
result.append ("\n");
}
::free (frameStrings);
#endif
result.push_back (frame[i]);
#endif
return result;
}

View File

@@ -48,7 +48,8 @@ namespace SystemStats
The usefulness of the result will depend on the level of debug symbols
that are available in the executable.
*/
std::string getStackBacktrace();
std::vector <std::string>
getStackBacktrace();
/** A void() function type, used by setApplicationCrashHandler(). */
typedef void (*CrashHandlerFunction)();

View File

@@ -21,16 +21,17 @@
#define BEAST_LEXICALCAST_H_INCLUDED
#include <beast/Config.h>
#include <beast/cxx14/type_traits.h> // <type_traits>
#include <algorithm>
#include <cerrno>
#include <cstdlib>
#include <iostream>
#include <iterator>
#include <limits>
#include <string>
#include <beast/cxx14/type_traits.h> // <type_traits>
#include <typeinfo>
#include <utility>
#include <iostream>
namespace beast {
namespace detail {
@@ -169,14 +170,14 @@ struct LexicalCast <Out, std::string>
std::enable_if_t <std::is_unsigned <Integral>::value, bool>
operator () (Integral& out, std::string const& in) const
{
return parseUnsigned (out, std::begin(in), std::end(in));
return parseUnsigned (out, in.begin(), in.end());
}
template <class Integral = Out>
std::enable_if_t <std::is_signed <Integral>::value, bool>
operator () (Integral& out, std::string const& in) const
{
return parseSigned (out, std::begin(in), std::end(in));
return parseSigned (out, in.begin(), in.end());
}
bool

View File

@@ -25,7 +25,6 @@
#define BEAST_STRINGPAIRARRAY_H_INCLUDED
#include <beast/module/core/text/StringArray.h>
#include <beast/utility/LeakChecked.h>
namespace beast {
@@ -35,7 +34,7 @@ namespace beast {
@see StringArray
*/
class StringPairArray : LeakChecked <StringPairArray>
class StringPairArray
{
public:
//==============================================================================

View File

@@ -141,7 +141,7 @@ void Workers::deleteWorkers (LockFreeStack <Worker>& stack)
//------------------------------------------------------------------------------
Workers::Worker::Worker (Workers& workers, String const& threadName)
Workers::Worker::Worker (Workers& workers, std::string const& threadName)
: Thread (threadName)
, m_workers (workers)
{
@@ -232,7 +232,6 @@ void Workers::Worker::run ()
class Workers_test : public unit_test::suite
{
public:
struct TestCallback : Workers::Callback
{
explicit TestCallback (int count_)
@@ -251,13 +250,6 @@ public:
std::atomic <int> count;
};
template <class T1, class T2>
bool
expectEquals (T1 const& t1, T2 const& t2)
{
return expect (t1 == t2);
}
void testThreads (int const threadCount)
{
testcase ("threadCount = " + std::to_string (threadCount));
@@ -276,14 +268,12 @@ public:
// 10 seconds should be enough to finish on any system
//
bool signaled = cb.finished.wait (10 * 1000);
expect (signaled, "timed out");
w.pauseAllThreadsAndWait ();
int const count (cb.count.load ());
expectEquals (count, 0);
// We had better finished all our work!
expect (cb.count.load () == 0, "Did not complete task!");
}
void run ()

View File

@@ -122,7 +122,7 @@ private:
, public Thread
{
public:
Worker (Workers& workers, String const& threadName);
Worker (Workers& workers, std::string const& threadName);
~Worker ();
@@ -138,7 +138,7 @@ private:
private:
Callback& m_callback;
String m_threadNames; // The name to give each thread
std::string m_threadNames; // The name to give each thread
WaitableEvent m_allPaused; // signaled when all threads paused
semaphore m_semaphore; // each pending task is 1 resource
int m_numberOfThreads; // how many we want active now

View File

@@ -247,31 +247,6 @@ std::uint32_t Time::getApproximateMillisecondCounter() noexcept
return TimeHelpers::lastMSCounterValue;
}
void Time::waitForMillisecondCounter (const std::uint32_t targetTime) noexcept
{
for (;;)
{
const std::uint32_t now = getMillisecondCounter();
if (now >= targetTime)
break;
const int toWait = (int) (targetTime - now);
if (toWait > 2)
{
Thread::sleep (std::min (20, toWait >> 1));
}
else
{
// xxx should consider using mutex_pause on the mac as it apparently
// makes it seem less like a spinlock and avoids lowering the thread pri.
for (int i = 10; --i >= 0;)
std::this_thread::yield();
}
}
}
//==============================================================================
double Time::highResolutionTicksToSeconds (const std::int64_t ticks) noexcept
{

View File

@@ -324,12 +324,6 @@ public:
*/
static double getMillisecondCounterHiRes() noexcept;
/** Waits until the getMillisecondCounter() reaches a given value.
This will make the thread sleep as efficiently as it can while it's waiting.
*/
static void waitForMillisecondCounter (std::uint32_t targetTime) noexcept;
/** Less-accurate but faster version of getMillisecondCounter().
This will return the last value that getMillisecondCounter() returned, so doesn't

View File

@@ -22,10 +22,11 @@
#include <beast/net/IPAddressV4.h>
#include <beast/net/IPAddressV6.h>
#include <beast/container/hash_append.h>
#include <beast/hash/hash_append.h>
#include <beast/hash/uhash.h>
#include <beast/utility/noexcept.h>
#include <boost/functional/hash.hpp>
#include <cassert>
#include <cstdint>
#include <ios>
#include <string>
@@ -102,14 +103,14 @@ public:
/** Returns `true` if this address represents an IPv4 address. */
bool
is_v4 () const
is_v4 () const noexcept
{
return m_type == ipv4;
}
/** Returns `true` if this address represents an IPv6 address. */
bool
is_v6() const
is_v6() const noexcept
{
return m_type == ipv6;
}
@@ -121,12 +122,11 @@ public:
AddressV4 const&
to_v4 () const
{
if (m_type != ipv4)
if (!is_v4 ())
throw std::bad_cast();
return m_v4;
}
/** Returns the IPv6 address.
Precondition:
is_v6() == `true`
@@ -134,7 +134,7 @@ public:
AddressV6 const&
to_v6 () const
{
if (m_type != ipv6)
if (!is_v6 ())
throw std::bad_cast();
return m_v6;
}
@@ -142,13 +142,15 @@ public:
template <class Hasher>
friend
void
hash_append(Hasher& h, Address const& addr)
hash_append(Hasher& h, Address const& addr) noexcept
{
using beast::hash_append;
if (addr.is_v4 ())
hash_append(h, addr.to_v4 ());
else
else if (addr.is_v6 ())
hash_append(h, addr.to_v6 ());
else
assert (false);
}
/** Arithmetic comparison. */

View File

@@ -20,7 +20,7 @@
#ifndef BEAST_NET_IPADDRESSV4_H_INCLUDED
#define BEAST_NET_IPADDRESSV4_H_INCLUDED
#include <beast/container/hash_append.h>
#include <beast/hash/hash_append.h>
#include <cstdint>
#include <functional>
@@ -140,7 +140,7 @@ struct AddressV4
Proxy <true> operator[] (std::size_t index) const;
Proxy <false> operator[] (std::size_t index);
/** @{ */
/** @} */
/** The value as a 32 bit unsigned. */
std::uint32_t value;

View File

@@ -21,8 +21,8 @@
#define BEAST_NET_IPENDPOINT_H_INCLUDED
#include <beast/net/IPAddress.h>
#include <beast/container/hash_append.h>
#include <beast/hash/hash_append.h>
#include <beast/hash/uhash.h>
#include <cstdint>
#include <ios>
#include <string>

32
src/beast/beast/nudb.h Normal file
View File

@@ -0,0 +1,32 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2014, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_NUDB_H_INCLUDED
#define BEAST_NUDB_H_INCLUDED
#include <beast/nudb/api.h>
#include <beast/nudb/create.h>
#include <beast/nudb/common.h>
#include <beast/nudb/file.h>
#include <beast/nudb/recover.h>
#include <beast/nudb/store.h>
#include <beast/nudb/verify.h>
#include <beast/nudb/visit.h>
#endif

View File

@@ -0,0 +1,283 @@
# NuDB: A Key/Value Store For Decentralized Systems
The new breed of decentralized systems such as Ripple or Bitcoin
that use embedded key/value databases place different demands on
these database than what is traditional. NuDB provides highly
optimized and concurrent atomic, durable, and isolated fetch and
insert operations to secondary storage, along with these features:
* Low memory footprint
* Values are immutable
* Value sizes from 1 2^48 bytes (281TB)
* All keys are the same size
* Performance independent of growth
* Optimized for concurrent fetch
* Key file can be rebuilt if needed
* Inserts are atomic and consistent
* Data file may be iterated, index rebuilt.
* Key and data files may be on different volumes
* Hardened against algorithmic complexity attacks
* Header-only, nothing to build or link
Three files are used. The data file holds keys and values stored
sequentially and size-prefixed. The key file holds a series of
fixed-size bucket records forming an on-disk hash table. The log file
stores bookkeeping information used to restore consistency when an
external failure occurs. In typical cases a fetch costs one I/O to
consult the key file and if the key is present, one I/O to read the
value.
## Usage
Callers define these parameters when a database is created:
* KeySize: The size of a key in bytes
* BlockSize: The physical size of a key file record
* LoadFactor: The desired fraction of bucket occupancy
The ideal block size matches the sector size or block size of the
underlying physical media that holds the key file. Functions are
provided to return a best estimate of this value for a particular
device, but a default of 4096 should work for typical installations.
The implementation tries to fit as many entries as possible in a key
file record, to maximize the amount of useful work performed per I/O.
The load factor is chosen to make bucket overflows unlikely without
sacrificing bucket occupancy. A value of 0.50 seems to work well with
a good hash function.
Callers also provide these parameters when a database is opened:
* Appnum: An application-defined integer constant
* AllocSize: A significant multiple of the average data size
To improve performance, memory is recycled. NuDB needs a hint about
the average size of the data being inserted. For an average data
size of 1KB (one kilobyte), AllocSize of sixteen megabytes (16MB) is
sufficient. If the AllocSize is too low, the memory recycler will
not make efficient use of allocated blocks.
Two operations are defined, fetch and insert.
### Fetch
The fetch operation retrieves a variable length value given the
key. The caller supplies a factory used to provide a buffer for storing
the value. This interface allows custom memory allocation strategies.
### Insert
Insert adds a key/value pair to the store. Value data must contain at
least one byte. Duplicate keys are disallowed. Insertions are serialized.
## Implementation
All insertions are buffered in memory, with inserted values becoming
immediately discoverable in subsequent or concurrent calls to fetch.
Periodically, buffered data is safely committed to disk files using
a separate dedicated thread associated with the database. This commit
process takes place at least once per second, or more often during
a detected surge in insertion activity. In the commit process the
key/value pairs receive the following treatment:
An insertion is performed by appending a value record to the data file.
The value record has some header information including the size of the
data and a copy of the key; the data file is iteratable without the key
file. The value data follows the header. The data file is append-only
and immutable: once written, bytes are never changed.
Initially the hash table in the key file consists of a single bucket.
After the load factor is exceeded from insertions, the hash table grows
in size by one bucket by doing a "split". The split operation is the
linear hashing algorithm as described by Litwin and Larson:
http://en.wikipedia.org/wiki/Linear_hashing
When a bucket is split, each key is rehashed and either remains in the
original bucket or gets moved to the new bucket appended to the end of
the key file.
An insertion on a full bucket first triggers the "spill" algorithm:
First, a spill record is appended to the data file. The spill record
contains header information followed by the entire bucket record. Then,
the bucket's size is set to zero and the offset of the spill record is
stored in the bucket. At this point the insertion may proceed normally,
since the bucket is empty. Spilled buckets in the data file are always
full.
Because every bucket holds the offset of the next spill record in the
data file, each bucket forms a linked list. In practice, careful
selection of capacity and load factor will keep the percentage of
buckets with one spill record to a minimum, with no bucket requiring
two spill records.
The implementation of fetch is straightforward: first the bucket in the
key file is checked, then each spill record in the linked list of
spill records is checked, until the key is found or there are no more
records. As almost all buckets have no spill records, the average
fetch requires one I/O (not including reading the value).
One complication in the scheme is when a split occurs on a bucket that
has one or more spill records. In this case, both the bucket being split
and the new bucket may overflow. This is handled by performing the
spill algorithm for each overflow that occurs. The new buckets may have
one or more spill records each, depending on the number of keys that
were originally present.
Because the data file is immutable, a bucket's original spill records
are no longer referenced after the bucket is split. These blocks of data
in the data file are unrecoverable wasted space. Correctly configured
databases can have a typical waste factor of 1%, which is acceptable.
These unused bytes can be removed by visiting each value in the value
file using an off-line process and inserting it into a new database,
then delete the old database and use the new one instead.
## Recovery
To provide atomicity and consistency, a log file associated with the
database stores information used to roll back partial commits.
## Iteration
Each record in the data file is prefixed with a header identifying
whether it is a value record or a spill record, along with the size of
the record in bytes and a copy of the key if its a value record.
Therefore, values may be iterated. A key file can be regenerated from
just the data file by iterating the values and performing the key
insertion algorithm.
## Concurrency
Locks are never held during disk reads and writes. Fetches are fully
concurrent, while inserts are serialized. Inserts prevent duplicate
keys. Inserts are atomic, they either succeed immediately or fail.
After an insert, the key is immediately visible to subsequent fetches.
## Formats
All integer values are stored as big endian. The uint48_t format
consists of 6 bytes.
### Key File
The Key File contains the Header followed by one or more
fixed-length Bucket Records.
#### Header (104 bytes)
char[8] Type The characters "nudb.key"
uint16 Version Holds the version number
uint64 UID Unique ID generated on creation
uint64 Appnum Application defined constant
uint16 KeySize Key size in bytes
uint64 Salt A random seed
uint64 Pepper The salt hashed
uint16 BlockSize Size of a file block in bytes
uint16 LoadFactor Target fraction in 65536ths
uint8[56] Reserved Zeroes
uint8[] Reserved Zero-pad to block size
The Type identifies the file as belonging to nudb. The UID is
generated randomly when the database is created, and this value
is stored in the data and log files as well. The UID is used
to determine if files belong to the same database. Salt is
generated when the database is created and helps prevent
complexity attacks; the salt is prepended to the key material
when computing a hash, or used to initialize the state of
the hash function. Appnum is an application defined constant
set when the database is created. It can be used for anything,
for example to distinguish between different data formats.
Pepper is computed by hashing the salt using a hash function
seeded with the salt. This is used to fingerprint the hash
function used. If a database is opened and the fingerprint
does not match the hash calculation performed using the template
argument provided when constructing the store, an exception
is thrown.
The header for the key file contains the File Header followed by
the information above. The Capacity is the number of keys per
bucket, and defines the size of a bucket record. The load factor
is the target fraction of bucket occupancy.
None of the information in the key file header or the data file
header may be changed after the database is created, including
the Appnum.
#### Bucket Record (fixed-length)
uint16 Count Number of keys in this bucket
uint48 Spill Offset of the next spill record or 0
BucketEntry[] Entries The bucket entries
#### Bucket Entry
uint48 Offset Offset in data file of the data
uint48 Size The size of the value in bytes
uint48 Hash The hash of the key
### Data File
The Data File contains the Header followed by zero or more
variable-length Value Records and Spill Records.
#### Header (92 bytes)
char[8] Type The characters "nudb.dat"
uint16 Version Holds the version number
uint64 UID Unique ID generated on creation
uint64 Appnum Application defined constant
uint16 KeySize Key size in bytes
uint8[64] Reserved Zeroes
UID contains the same value as the salt in the corresponding key
file. This is placed in the data file so that key and value files
belonging to the same database can be identified.
#### Data Record (variable-length)
uint48 Size Size of the value in bytes
uint8[KeySize] Key The key.
uint8[Size] Data The value data.
#### Spill Record (fixed-length)
uint48 Zero All zero, identifies a spill record
uint16 Size Bytes in spill bucket (for skipping)
Bucket SpillBucket Bucket Record
### Log File
The Log file contains the Header followed by zero or more fixed size
log records. Each log record contains a snapshot of a bucket. When a
database is not closed cleanly, the recovery process applies the log
records to the key file, overwriting data that may be only partially
updated with known good information. After the log records are applied,
the data and key files are truncated to the last known good size.
#### Header (62 bytes)
char[8] Type The characters "nudb.log"
uint16 Version Holds the version number
uint64 UID Unique ID generated on creation
uint64 Appnum Application defined constant
uint16 KeySize Key size in bytes
uint64 Salt A random seed.
uint64 Pepper The salt hashed
uint16 BlockSize Size of a file block in bytes
uint64 KeyFileSize Size of key file.
uint64 DataFileSize Size of data file.
#### Log Record
uint64_t Index Bucket index (0-based)
Bucket Bucket Compact Bucket record
Compact buckets include only Size entries. These are primarily
used to minimize the volume of writes to the log file.

109
src/beast/beast/nudb/api.h Normal file
View File

@@ -0,0 +1,109 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2014, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_NUDB_API_H_INCLUDED
#define BEAST_NUDB_API_H_INCLUDED
#include <beast/nudb/create.h>
#include <beast/nudb/store.h>
#include <beast/nudb/recover.h>
#include <beast/nudb/verify.h>
#include <beast/nudb/visit.h>
#include <cstdint>
namespace beast {
namespace nudb {
// Convenience for consolidating template arguments
//
template <
class Hasher,
class Codec,
class File = native_file,
std::size_t BufferSize = 16 * 1024 * 1024
>
struct api
{
using hash_type = Hasher;
using codec_type = Codec;
using file_type = File;
using store = nudb::store<Hasher, Codec, File>;
static std::size_t const buffer_size = BufferSize;
template <class... Args>
static
bool
create (
path_type const& dat_path,
path_type const& key_path,
path_type const& log_path,
std::uint64_t appnum,
std::uint64_t salt,
std::size_t key_size,
std::size_t block_size,
float load_factor,
Args&&... args)
{
return nudb::create<Hasher, Codec, File>(
dat_path, key_path, log_path,
appnum, salt, key_size, block_size,
load_factor, args...);
}
template <class... Args>
static
bool
recover (
path_type const& dat_path,
path_type const& key_path,
path_type const& log_path,
Args&&... args)
{
return nudb::recover<Hasher, Codec, File>(
dat_path, key_path, log_path, BufferSize,
args...);
}
static
verify_info
verify (
path_type const& dat_path,
path_type const& key_path)
{
return nudb::verify<Hasher>(
dat_path, key_path, BufferSize);
}
template <class Function>
static
bool
visit(
path_type const& path,
Function&& f)
{
return nudb::visit<Codec>(
path, BufferSize, f);
}
};
} // nudb
} // beast
#endif

View File

@@ -0,0 +1,123 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2014, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_NUDB_COMMON_H_INCLUDED
#define BEAST_NUDB_COMMON_H_INCLUDED
#include <stdexcept>
#include <string>
namespace beast {
namespace nudb {
// Commonly used types
enum class file_mode
{
scan, // read sequential
read, // read random
append, // read random, write append
write // read random, write random
};
using path_type = std::string;
// All exceptions thrown by nudb are derived
// from std::runtime_error except for fail_error
/** Thrown when a codec fails, e.g. corrupt data. */
struct codec_error : std::runtime_error
{
template <class String>
explicit
codec_error (String const& s)
: runtime_error(s)
{
}
};
/** Base class for all errors thrown by file classes. */
struct file_error : std::runtime_error
{
template <class String>
explicit
file_error (String const& s)
: runtime_error(s)
{
}
};
/** Thrown when file bytes read are less than requested. */
struct file_short_read_error : file_error
{
file_short_read_error()
: file_error (
"nudb: short read")
{
}
};
/** Thrown when file bytes written are less than requested. */
struct file_short_write_error : file_error
{
file_short_write_error()
: file_error (
"nudb: short write")
{
}
};
/** Thrown when end of istream reached while reading. */
struct short_read_error : std::runtime_error
{
short_read_error()
: std::runtime_error(
"nudb: short read")
{
}
};
/** Base class for all exceptions thrown by store. */
class store_error : public std::runtime_error
{
public:
template <class String>
explicit
store_error (String const& s)
: runtime_error(s)
{
}
};
/** Thrown when corruption in a file is detected. */
class store_corrupt_error : public store_error
{
public:
template <class String>
explicit
store_corrupt_error (String const& s)
: store_error(s)
{
}
};
} // nudb
} // beast
#endif

View File

@@ -0,0 +1,164 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2014, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_NUDB_CREATE_H_INCLUDED
#define BEAST_NUDB_CREATE_H_INCLUDED
#include <beast/nudb/file.h>
#include <beast/nudb/detail/bucket.h>
#include <beast/nudb/detail/format.h>
#include <algorithm>
#include <cstring>
#include <random>
#include <stdexcept>
#include <utility>
namespace beast {
namespace nudb {
namespace detail {
template <class = void>
std::uint64_t
make_uid()
{
std::random_device rng;
std::mt19937_64 gen {rng()};
std::uniform_int_distribution <std::size_t> dist;
return dist(gen);
}
}
/** Generate a random salt. */
template <class = void>
std::uint64_t
make_salt()
{
std::random_device rng;
std::mt19937_64 gen {rng()};
std::uniform_int_distribution <std::size_t> dist;
return dist(gen);
}
/** Returns the best guess at the volume's block size. */
inline
std::size_t
block_size (path_type const& /*path*/)
{
return 4096;
}
/** Create a new database.
Preconditions:
The files must not exist
Throws:
@param args Arguments passed to File constructors
@return `false` if any file could not be created.
*/
template <
class Hasher,
class Codec,
class File,
class... Args
>
bool
create (
path_type const& dat_path,
path_type const& key_path,
path_type const& log_path,
std::uint64_t appnum,
std::uint64_t salt,
std::size_t key_size,
std::size_t block_size,
float load_factor,
Args&&... args)
{
using namespace detail;
if (key_size < 1)
throw std::domain_error(
"invalid key size");
if (block_size > field<std::uint16_t>::max)
throw std::domain_error(
"nudb: block size too large");
if (load_factor <= 0.f)
throw std::domain_error(
"nudb: load factor too small");
if (load_factor >= 1.f)
throw std::domain_error(
"nudb: load factor too large");
auto const capacity =
bucket_capacity(block_size);
if (capacity < 1)
throw std::domain_error(
"nudb: block size too small");
File df(args...);
File kf(args...);
File lf(args...);
if (df.create(
file_mode::append, dat_path))
{
if (kf.create (
file_mode::append, key_path))
{
if (lf.create(
file_mode::append, log_path))
goto success;
File::erase (dat_path);
}
File::erase (key_path);
}
return false;
success:
dat_file_header dh;
dh.version = currentVersion;
dh.uid = make_uid();
dh.appnum = appnum;
dh.key_size = key_size;
key_file_header kh;
kh.version = currentVersion;
kh.uid = dh.uid;
kh.appnum = appnum;
kh.key_size = key_size;
kh.salt = salt;
kh.pepper = pepper<Hasher>(salt);
kh.block_size = block_size;
// VFALCO Should it be 65536?
// How do we set the min?
kh.load_factor = std::min<std::size_t>(
65536.0 * load_factor, 65535);
write (df, dh);
write (kf, kh);
buffer buf(block_size);
std::memset(buf.get(), 0, block_size);
bucket b (block_size, buf.get(), empty);
b.write (kf, block_size);
// VFALCO Leave log file empty?
df.sync();
kf.sync();
lf.sync();
return true;
}
} // nudb
} // beast
#endif

View File

@@ -0,0 +1,246 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2014, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_NUDB_ARENA_H_INCLUDED
#define BEAST_NUDB_ARENA_H_INCLUDED
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <memory>
namespace beast {
namespace nudb {
namespace detail {
/* Custom memory manager that allocates in large blocks.
No limit is placed on the size of an allocation but
alloc_size should be tuned upon construction to be a
significant multiple of the average allocation size.
When the arena is cleared, allocated memory is placed
on a free list for re-use, avoiding future system calls.
*/
template <class = void>
class arena_t
{
private:
class element;
std::size_t alloc_size_;
element* used_ = nullptr;
element* free_ = nullptr;
public:
arena_t (arena_t const&);
arena_t& operator= (arena_t const&);
~arena_t();
explicit
arena_t (std::size_t alloc_size);
arena_t& operator= (arena_t&& other);
// Makes used blocks free
void
clear();
// deletes free blocks
void
shrink_to_fit();
std::uint8_t*
alloc (std::size_t n);
template <class U>
friend
void
swap (arena_t<U>& lhs, arena_t<U>& rhs);
private:
void
dealloc (element*& list);
};
//------------------------------------------------------------------------------
template <class _>
class arena_t<_>::element
{
private:
std::size_t const capacity_;
std::size_t used_ = 0;
public:
element* next = nullptr;
explicit
element (std::size_t alloc_size)
: capacity_ (
alloc_size - sizeof(*this))
{
}
void
clear()
{
used_ = 0;
}
std::size_t
remain() const
{
return capacity_ - used_;
}
std::size_t
capacity() const
{
return capacity_;
}
std::uint8_t*
alloc (std::size_t n);
};
template <class _>
std::uint8_t*
arena_t<_>::element::alloc (std::size_t n)
{
if (n > capacity_ - used_)
return nullptr;
auto const p = const_cast<std::uint8_t*>(
reinterpret_cast<uint8_t const*>(this + 1)
) + used_;
used_ += n;
return p;
}
//------------------------------------------------------------------------------
template <class _>
arena_t<_>::arena_t (std::size_t alloc_size)
: alloc_size_ (alloc_size)
{
if (alloc_size <= sizeof(element))
throw std::domain_error(
"arena: bad alloc size");
}
template <class _>
arena_t<_>::~arena_t()
{
dealloc (used_);
dealloc (free_);
}
template <class _>
arena_t<_>&
arena_t<_>::operator= (arena_t&& other)
{
dealloc (used_);
dealloc (free_);
alloc_size_ = other.alloc_size_;
used_ = other.used_;
free_ = other.free_;
other.used_ = nullptr;
other.free_ = nullptr;
return *this;
}
template <class _>
void
arena_t<_>::clear()
{
while (used_)
{
auto const e = used_;
used_ = used_->next;
e->clear();
e->next = free_;
free_ = e;
}
}
template <class _>
void
arena_t<_>::shrink_to_fit()
{
dealloc (free_);
}
template <class _>
std::uint8_t*
arena_t<_>::alloc (std::size_t n)
{
// Undefined behavior: Zero byte allocations
assert(n != 0);
n = 8 * ((n + 7) / 8);
if (used_ && used_->remain() >= n)
return used_->alloc(n);
if (free_ && free_->remain() >= n)
{
auto const e = free_;
free_ = free_->next;
e->next = used_;
used_ = e;
return used_->alloc(n);
}
std::size_t const size = std::max(
alloc_size_, sizeof(element) + n);
element* const e = reinterpret_cast<element*>(
new std::uint8_t[size]);
::new(e) element(size);
e->next = used_;
used_ = e;
return used_->alloc(n);
}
template <class _>
void
swap (arena_t<_>& lhs, arena_t<_>& rhs)
{
using std::swap;
swap(lhs.alloc_size_, rhs.alloc_size_);
swap(lhs.used_, rhs.used_);
swap(lhs.free_, rhs.free_);
}
template <class _>
void
arena_t<_>::dealloc (element*& list)
{
while (list)
{
auto const e = list;
list = list->next;
e->~element();
delete[] reinterpret_cast<std::uint8_t*>(e);
}
}
using arena = arena_t<>;
} // detail
} // nudb
} // beast
#endif

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