зеркало из https://github.com/microsoft/CCF.git
Re-namespace `::kv` to `ccf::kv` (#6312)
This commit is contained in:
Родитель
da4e643e75
Коммит
45328bf200
|
@ -3,4 +3,4 @@
|
|||
( V ) / . \ | +---=---'
|
||||
/--x-m- /--n-n---xXx--/--yY------>>>----<<<>>]]{{}}---||-/\---..
|
||||
2024__
|
||||
!..!
|
||||
!..!!
|
|
@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||
- `::http` is now `ccf::http`
|
||||
- `::nonstd` is now `ccf::nonstd`
|
||||
- `::crypto` is now `ccf::crypto`
|
||||
- `::kv` is now `ccf::kv`
|
||||
- `::logger` is now `ccf::logger`
|
||||
- The `programmability` sample app now demonstrates how applications can define their own extensions, creating bindings between C++ and JS state, and allowing JS endpoints to call functions implemented in C++.
|
||||
- Introduce `DynamicJSEndpointRegistry::record_action_for_audit_v1` and `DynamicJSEndpointRegistry::check_action_not_replayed_v1` to allow an application making use of the programmability feature to easily implement auditability, and protect users allowed to update the application against replay attacks (#6285).
|
||||
|
|
|
@ -35,21 +35,21 @@ The following table describes the structure of a serialised transaction as it is
|
|||
+ +------------------------------------------+-------------------------------------------------------------------------+
|
||||
| | uint64_t | Length of serialised public domain |
|
||||
+----------+------------------------------------------+-------------------------------------------------------------------------+
|
||||
| | :cpp:type:`kv::EntryType` | Snapshot, or a WriteSet variant |
|
||||
| | :cpp:type:`ccf::kv::EntryType` | Snapshot, or a WriteSet variant |
|
||||
+ +------------------------------------------+-------------------------------------------------------------------------+
|
||||
| | :cpp:type:`kv::Version` | Transaction version |
|
||||
| | :cpp:type:`ccf::kv::Version` | Transaction version |
|
||||
+ +------------------------------------------+-------------------------------------------------------------------------+
|
||||
| | :cpp:type:`ccf::crypto::Sha256Hash` | User-defined claims digest, when entry type is WriteSetWith.*Claims |
|
||||
| | :cpp:type:`ccf::crypto::Sha256Hash` | User-defined claims digest, when entry type is WriteSetWith.*Claims |
|
||||
+ +------------------------------------------+-------------------------------------------------------------------------+
|
||||
| | :cpp:type:`ccf::crypto::Sha256Hash` | Commit evidence digest, when entry type is WriteSetWithCommitEvidence.* |
|
||||
| | :cpp:type:`ccf::crypto::Sha256Hash` | Commit evidence digest, when entry type is WriteSetWithCommitEvidence.* |
|
||||
+ +------------------------------------------+-------------------------------------------------------------------------+
|
||||
| | :cpp:type:`kv::Version` | Unused, reserved for compatibility |
|
||||
| | :cpp:type:`ccf::kv::Version` | Unused, reserved for compatibility |
|
||||
+ +------------------------------------------+-------------------------------------------------------------------------+
|
||||
| | **Repeating [0..n]** | With ``n`` the number of maps in the transaction |
|
||||
+ +-----+------------------------------------+-------------------------------------------------------------------------+
|
||||
| | | std::string | Name of the serialised :cpp:type:`kv::Map` |
|
||||
| | | std::string | Name of the serialised :cpp:type:`ccf::kv::Map` |
|
||||
| +-----+------------------------------------+-------------------------------------------------------------------------+
|
||||
| | | :cpp:type:`kv::Version` | Read version |
|
||||
| | | :cpp:type:`ccf::kv::Version` | Read version |
|
||||
| +-----+------------------------------------+-------------------------------------------------------------------------+
|
||||
| | | uint64_t | Read count |
|
||||
| | +------------------------------------+-------------------------------------------------------------------------+
|
||||
|
|
|
@ -19,7 +19,7 @@ The Logging example application simply has:
|
|||
|
||||
.. note::
|
||||
|
||||
:cpp:type:`kv::Map` tables are the only interface between CCF and the replicated application, and the sole mechanism for it to have distributed state.
|
||||
:cpp:type:`ccf::kv::Map` tables are the only interface between CCF and the replicated application, and the sole mechanism for it to have distributed state.
|
||||
|
||||
The Logging application keeps its state in a pair of tables, one containing private encrypted logs and the other containing public unencrypted logs. Their type is defined as:
|
||||
|
||||
|
@ -54,7 +54,7 @@ The implementation of :cpp:func:`ccfapp::make_user_endpoints()` should return a
|
|||
:lines: 1
|
||||
:dedent:
|
||||
|
||||
The logging app defines :cpp:class:`ccfapp::LoggerHandlers`, which creates and installs handler functions or lambdas for several different HTTP endpoints. Each of these functions takes as input the details of the current request (such as the URI which was called, the query string, the request body), interacts with the KV tables using the given :cpp:class:`kv::Tx` object, and returns a result:
|
||||
The logging app defines :cpp:class:`ccfapp::LoggerHandlers`, which creates and installs handler functions or lambdas for several different HTTP endpoints. Each of these functions takes as input the details of the current request (such as the URI which was called, the query string, the request body), interacts with the KV tables using the given :cpp:class:`ccf::kv::Tx` object, and returns a result:
|
||||
|
||||
.. literalinclude:: ../../samples/apps/logging/logging.cpp
|
||||
:language: cpp
|
||||
|
|
|
@ -3,84 +3,84 @@ Key-Value Store API
|
|||
|
||||
This page presents the API that a CCF application must use to access and mutate the replicated key-value store.
|
||||
|
||||
A CCF application should store its data in one or more :cpp:type:`kv::Map`. The name, type, and serialisation of these maps is under the application's control. Each invocation of an :cpp:class:`ccf::EndpointRegistry::Endpoint` is given a :cpp:class:`kv::Tx` transaction object, through which it can read and write to its :cpp:type:`kv::Map`.
|
||||
A CCF application should store its data in one or more :cpp:type:`ccf::kv::Map`. The name, type, and serialisation of these maps is under the application's control. Each invocation of an :cpp:class:`ccf::EndpointRegistry::Endpoint` is given a :cpp:class:`ccf::kv::Tx` transaction object, through which it can read and write to its :cpp:type:`ccf::kv::Map`.
|
||||
|
||||
Map
|
||||
---
|
||||
|
||||
.. doxygentypedef:: kv::Version
|
||||
.. doxygentypedef:: ccf::kv::Version
|
||||
:project: CCF
|
||||
|
||||
.. doxygenvariable:: kv::NoVersion
|
||||
.. doxygenvariable:: ccf::kv::NoVersion
|
||||
:project: CCF
|
||||
|
||||
.. doxygenclass:: kv::TypedMap
|
||||
.. doxygenclass:: ccf::kv::TypedMap
|
||||
:project: CCF
|
||||
|
||||
.. doxygentypedef:: kv::Map
|
||||
.. doxygentypedef:: ccf::kv::Map
|
||||
:project: CCF
|
||||
|
||||
.. doxygenclass:: kv::TypedValue
|
||||
.. doxygenclass:: ccf::kv::TypedValue
|
||||
:project: CCF
|
||||
|
||||
.. doxygentypedef:: kv::Value
|
||||
.. doxygentypedef:: ccf::kv::Value
|
||||
:project: CCF
|
||||
|
||||
.. doxygenclass:: kv::TypedSet
|
||||
.. doxygenclass:: ccf::kv::TypedSet
|
||||
:project: CCF
|
||||
|
||||
.. doxygentypedef:: kv::Set
|
||||
.. doxygentypedef:: ccf::kv::Set
|
||||
:project: CCF
|
||||
|
||||
Transaction
|
||||
-----------
|
||||
|
||||
.. doxygenclass:: kv::ReadOnlyTx
|
||||
.. doxygenclass:: ccf::kv::ReadOnlyTx
|
||||
:project: CCF
|
||||
:members: ro
|
||||
|
||||
.. doxygenclass:: kv::Tx
|
||||
.. doxygenclass:: ccf::kv::Tx
|
||||
:project: CCF
|
||||
:members: rw, wo
|
||||
|
||||
Handles
|
||||
-------
|
||||
|
||||
.. doxygenclass:: kv::ReadableMapHandle
|
||||
.. doxygenclass:: ccf::kv::ReadableMapHandle
|
||||
:project: CCF
|
||||
:members:
|
||||
|
||||
.. doxygenclass:: kv::WriteableMapHandle
|
||||
.. doxygenclass:: ccf::kv::WriteableMapHandle
|
||||
:project: CCF
|
||||
:members:
|
||||
|
||||
.. doxygenclass:: kv::MapHandle
|
||||
.. doxygenclass:: ccf::kv::MapHandle
|
||||
:project: CCF
|
||||
|
||||
.. doxygenclass:: kv::ReadableValueHandle
|
||||
.. doxygenclass:: ccf::kv::ReadableValueHandle
|
||||
:project: CCF
|
||||
:members:
|
||||
|
||||
.. doxygenclass:: kv::WriteableValueHandle
|
||||
.. doxygenclass:: ccf::kv::WriteableValueHandle
|
||||
:project: CCF
|
||||
:members:
|
||||
|
||||
.. doxygenclass:: kv::ValueHandle
|
||||
.. doxygenclass:: ccf::kv::ValueHandle
|
||||
:project: CCF
|
||||
|
||||
.. doxygenclass:: kv::ReadableSetHandle
|
||||
.. doxygenclass:: ccf::kv::ReadableSetHandle
|
||||
:project: CCF
|
||||
:members:
|
||||
|
||||
.. doxygenclass:: kv::WriteableSetHandle
|
||||
.. doxygenclass:: ccf::kv::WriteableSetHandle
|
||||
:project: CCF
|
||||
:members:
|
||||
|
||||
.. doxygenclass:: kv::SetHandle
|
||||
.. doxygenclass:: ccf::kv::SetHandle
|
||||
:project: CCF
|
||||
|
||||
Serialisation
|
||||
-------------
|
||||
|
||||
.. doxygenenum:: kv::EntryType
|
||||
.. doxygenenum:: ccf::kv::EntryType
|
||||
:project: CCF
|
|
@ -1,70 +1,70 @@
|
|||
Key-Value Store How-To
|
||||
======================
|
||||
|
||||
The `Key-Value Store` (KV) consists of a set of :cpp:type:`kv::Map` objects that are available to the endpoints of an application. Endpoint handlers create handles which allow them to read and write from these :cpp:type:`kv::Map` objects. The framework handles conflicts between concurrent execution of multiple transactions, and produces a consistent order of transactions which is replicated between nodes, allowing the entries to be read from multiple nodes. This page outlines the core concepts and C++ APIs used to interact with the KV.
|
||||
The `Key-Value Store` (KV) consists of a set of :cpp:type:`ccf::kv::Map` objects that are available to the endpoints of an application. Endpoint handlers create handles which allow them to read and write from these :cpp:type:`ccf::kv::Map` objects. The framework handles conflicts between concurrent execution of multiple transactions, and produces a consistent order of transactions which is replicated between nodes, allowing the entries to be read from multiple nodes. This page outlines the core concepts and C++ APIs used to interact with the KV.
|
||||
|
||||
Map Naming
|
||||
----------
|
||||
|
||||
A :cpp:type:`kv::Map` (often referred to as a `Table`) is a collection of key-value pairs of a given type. The :cpp:type:`kv::Map` itself is identified by its name, which is used to lookup the map :cpp:type:`kv::Map` from the local store during a transaction.
|
||||
A :cpp:type:`ccf::kv::Map` (often referred to as a `Table`) is a collection of key-value pairs of a given type. The :cpp:type:`ccf::kv::Map` itself is identified by its name, which is used to lookup the map :cpp:type:`ccf::kv::Map` from the local store during a transaction.
|
||||
|
||||
If a :cpp:type:`kv::Map` with the given name did not previously exist, it will be created in this transaction.
|
||||
If a :cpp:type:`ccf::kv::Map` with the given name did not previously exist, it will be created in this transaction.
|
||||
|
||||
A :cpp:type:`kv::Map` can either be created as private (default) or public. Public map's names begin with a ``public:`` prefix, any any other name indicates a private map. For instance the name ``public:foo`` to a public map, while ``foo`` refers to a private map. Transactions on private maps are written to the ledger in encrypted form and can only be decrypted in the enclave of nodes that have joined the network. Transactions on public maps are written to the ledger as plaintext and can be read from outside the enclave; only their integrity is protected. The security domain of a map (public or private) cannot be changed after its creation, since this is encoded in the map's name. Public and private maps with similar names in different domains are distinct; writes to ``public:foo`` have no impact on ``foo``, and vice versa.
|
||||
A :cpp:type:`ccf::kv::Map` can either be created as private (default) or public. Public map's names begin with a ``public:`` prefix, any any other name indicates a private map. For instance the name ``public:foo`` to a public map, while ``foo`` refers to a private map. Transactions on private maps are written to the ledger in encrypted form and can only be decrypted in the enclave of nodes that have joined the network. Transactions on public maps are written to the ledger as plaintext and can be read from outside the enclave; only their integrity is protected. The security domain of a map (public or private) cannot be changed after its creation, since this is encoded in the map's name. Public and private maps with similar names in different domains are distinct; writes to ``public:foo`` have no impact on ``foo``, and vice versa.
|
||||
|
||||
Some table names are reserved for governance of a CCF service and cannot be modified by application code. For more information, see :doc:`/audit/read_write_restrictions`.
|
||||
|
||||
Transaction Semantics
|
||||
---------------------
|
||||
|
||||
A transaction (:cpp:class:`kv::Tx`) encapsulates an individual endpoint invocation's atomic interaction with the KV. Transactions may read from and write to multiple :cpp:type:`kv::Map`, and each is automatically ordered, applied, serialised, and committed by the framework.
|
||||
A transaction (:cpp:class:`ccf::kv::Tx`) encapsulates an individual endpoint invocation's atomic interaction with the KV. Transactions may read from and write to multiple :cpp:type:`ccf::kv::Map`, and each is automatically ordered, applied, serialised, and committed by the framework.
|
||||
|
||||
A reference to a new :cpp:class:`kv::Tx` is passed to each endpoint handler, and used to interact with the KV.
|
||||
A reference to a new :cpp:class:`ccf::kv::Tx` is passed to each endpoint handler, and used to interact with the KV.
|
||||
|
||||
Each :cpp:class:`kv::Tx` gets a consistent, opaque view of the KV, including the values which have been left by previous writes. Any writes produced by this transaction will be visible to all future transactions.
|
||||
Each :cpp:class:`ccf::kv::Tx` gets a consistent, opaque view of the KV, including the values which have been left by previous writes. Any writes produced by this transaction will be visible to all future transactions.
|
||||
|
||||
When the endpoint handler indicates that its :cpp:class:`kv::Tx` should be applied (see :ref:`this section <build_apps/kv/kv_how_to:Applying and reverting writes>` for details), the executing node attempts to apply the changes to its local KV. If this produces conflicts with concurrently executing transactions, it will be automatically re-executed. Once the transaction is applied successfully, it is automatically replicated to other nodes and will, if the network is healthy, eventually be committed.
|
||||
When the endpoint handler indicates that its :cpp:class:`ccf::kv::Tx` should be applied (see :ref:`this section <build_apps/kv/kv_how_to:Applying and reverting writes>` for details), the executing node attempts to apply the changes to its local KV. If this produces conflicts with concurrently executing transactions, it will be automatically re-executed. Once the transaction is applied successfully, it is automatically replicated to other nodes and will, if the network is healthy, eventually be committed.
|
||||
|
||||
For each :cpp:type:`kv::Map` that a transaction wants to write to or read from, a :cpp:class:`kv::MapHandle` must first be acquired. These are acquired from the :cpp:func:`kv::Tx::rw` (`read-write`) method. These may be acquired either by name (in which case the desired type must be explicitly specified as a template parameter), or by using a :cpp:type:`kv::Map` instance which defines both the map's name and key-value types.
|
||||
For each :cpp:type:`ccf::kv::Map` that a transaction wants to write to or read from, a :cpp:class:`ccf::kv::MapHandle` must first be acquired. These are acquired from the :cpp:func:`ccf::kv::Tx::rw` (`read-write`) method. These may be acquired either by name (in which case the desired type must be explicitly specified as a template parameter), or by using a :cpp:type:`ccf::kv::Map` instance which defines both the map's name and key-value types.
|
||||
|
||||
By name:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
// Handle for map1
|
||||
auto map1_handle = tx.rw<kv::Map<string, string>>("map1");
|
||||
auto map1_handle = tx.rw<ccf::kv::Map<string, string>>("map1");
|
||||
|
||||
// Handles for 2 other maps, one public and one private, with different types
|
||||
auto map2_handle = tx.rw<kv::Map<string, uint64_t>>("public:map2");
|
||||
auto map3_handle = tx.rw<kv::Map<uint64_t, MyCustomClass>>("map3");
|
||||
auto map2_handle = tx.rw<ccf::kv::Map<string, uint64_t>>("public:map2");
|
||||
auto map3_handle = tx.rw<ccf::kv::Map<uint64_t, MyCustomClass>>("map3");
|
||||
|
||||
By :cpp:type:`kv::Map`:
|
||||
By :cpp:type:`ccf::kv::Map`:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
kv::Map<string, string> map_priv("map1");
|
||||
ccf::kv::Map<string, string> map_priv("map1");
|
||||
auto map1_handle = tx.rw(map_priv);
|
||||
|
||||
kv::Map<string, uint64_t> map_pub("public:map2");
|
||||
ccf::kv::Map<string, uint64_t> map_pub("public:map2");
|
||||
auto map2_handle = tx.rw(map_pub);
|
||||
|
||||
kv::Map<uint64_t, MyCustomClass> map_priv_int("map3");
|
||||
ccf::kv::Map<uint64_t, MyCustomClass> map_priv_int("map3");
|
||||
auto map3_handle = tx.rw(map_priv_int);
|
||||
|
||||
The latter approach introduces a named binding between the map's name and the types of its keys and values, reducing the chance for errors where code attempts to read a map with the wrong type.
|
||||
|
||||
.. note:: As mentioned above, there is no need to explicitly declare a :cpp:type:`kv::Map` before it is used. The first write to a :cpp:type:`kv::Map` implicitly creates it in the underlying KV. Within a transaction, a newly created :cpp:type:`kv::Map` behaves exactly the same as an existing :cpp:type:`kv::Map` with no keys - the framework views these as semantically identical, and offers no way for the application logic to tell them apart. Any writes to a newly created :cpp:type:`kv::Map` will be persisted when the transaction commits, and future transactions will be able to access this :cpp:type:`kv::Map` by name to read those writes.
|
||||
.. note:: As mentioned above, there is no need to explicitly declare a :cpp:type:`ccf::kv::Map` before it is used. The first write to a :cpp:type:`ccf::kv::Map` implicitly creates it in the underlying KV. Within a transaction, a newly created :cpp:type:`ccf::kv::Map` behaves exactly the same as an existing :cpp:type:`ccf::kv::Map` with no keys - the framework views these as semantically identical, and offers no way for the application logic to tell them apart. Any writes to a newly created :cpp:type:`ccf::kv::Map` will be persisted when the transaction commits, and future transactions will be able to access this :cpp:type:`ccf::kv::Map` by name to read those writes.
|
||||
|
||||
Accessing Map content via a Handle
|
||||
----------------------------------
|
||||
|
||||
Once a :cpp:class:`kv::MapHandle` on a specific :cpp:type:`kv::Map` has been obtained, it is possible to:
|
||||
Once a :cpp:class:`ccf::kv::MapHandle` on a specific :cpp:type:`ccf::kv::Map` has been obtained, it is possible to:
|
||||
|
||||
- test (:cpp:func:`kv::ReadableMapHandle::has`) whether a key has any associated value;
|
||||
- read (:cpp:func:`kv::ReadableMapHandle::get`) the value associated with a key;
|
||||
- write (:cpp:func:`kv::WriteableMapHandle::put`) a new value for a key;
|
||||
- delete (:cpp:func:`kv::WriteableMapHandle::remove`) a key and its current value;
|
||||
- iterate (:cpp:func:`kv::ReadableMapHandle::foreach`) through all key-value pairs.
|
||||
- test (:cpp:func:`ccf::kv::ReadableMapHandle::has`) whether a key has any associated value;
|
||||
- read (:cpp:func:`ccf::kv::ReadableMapHandle::get`) the value associated with a key;
|
||||
- write (:cpp:func:`ccf::kv::WriteableMapHandle::put`) a new value for a key;
|
||||
- delete (:cpp:func:`ccf::kv::WriteableMapHandle::remove`) a key and its current value;
|
||||
- iterate (:cpp:func:`ccf::kv::ReadableMapHandle::foreach`) through all key-value pairs.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
|
@ -91,7 +91,7 @@ Once a :cpp:class:`kv::MapHandle` on a specific :cpp:type:`kv::Map` has been obt
|
|||
Read/Write safety
|
||||
-----------------
|
||||
|
||||
If you are only reading from or only writing to a given :cpp:type:`kv::Map` you can retrieve a `read-only` or `write-only` handle for it. This will turn unexpected reads/writes (which would introduce unintended dependencies between transactions) into compile-time errors. Instead of calling :cpp:func:`kv::Tx::rw` to get a handle which can both read and write, you can call :cpp:func:`kv::ReadOnlyTx::ro` to acquire a `read-only` handle or :cpp:func:`kv::Tx::wo` to acquire a `write-only` handle.
|
||||
If you are only reading from or only writing to a given :cpp:type:`ccf::kv::Map` you can retrieve a `read-only` or `write-only` handle for it. This will turn unexpected reads/writes (which would introduce unintended dependencies between transactions) into compile-time errors. Instead of calling :cpp:func:`ccf::kv::Tx::rw` to get a handle which can both read and write, you can call :cpp:func:`ccf::kv::ReadOnlyTx::ro` to acquire a `read-only` handle or :cpp:func:`ccf::kv::Tx::wo` to acquire a `write-only` handle.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
|
@ -122,7 +122,7 @@ Note that, as in the sample above, it is possible to acquire different kinds of
|
|||
Removing a key
|
||||
--------------
|
||||
|
||||
If a Key-Value pair was written to a :cpp:type:`kv::Map` by a previous :cpp:class:`kv::Tx`, it is possible to delete this key. Because of the append-only nature of the KV, this Key-Value pair is not actually removed from the :cpp:type:`kv::Map` but instead explicitly marked as deleted in the version that the deleting :cpp:class:`kv::Tx` is applied at.
|
||||
If a Key-Value pair was written to a :cpp:type:`ccf::kv::Map` by a previous :cpp:class:`ccf::kv::Tx`, it is possible to delete this key. Because of the append-only nature of the KV, this Key-Value pair is not actually removed from the :cpp:type:`ccf::kv::Map` but instead explicitly marked as deleted in the version that the deleting :cpp:class:`ccf::kv::Tx` is applied at.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
|
@ -141,7 +141,7 @@ Global commit
|
|||
|
||||
A transaction is automatically (globally) committed once the consensus protocol has established that a majority of nodes in the CCF network have successfully received and acknowledged that transaction. To operate on durable state, an application may want to query the globally committed state rather than the *current* state of the KV.
|
||||
|
||||
The :cpp:func:`kv::MapHandle::get_globally_committed` member function returns the value of a key that we know has been globally committed.
|
||||
The :cpp:func:`ccf::kv::MapHandle::get_globally_committed` member function returns the value of a key that we know has been globally committed.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
|
@ -166,9 +166,9 @@ Miscellaneous
|
|||
``foreach()``
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
Values can only be retrieved directly (:cpp:func:`kv::MapHandle::get`) for a given target key. However, it is sometimes necessary to access unknown keys, or to iterate through all Key-Value pairs.
|
||||
Values can only be retrieved directly (:cpp:func:`ccf::kv::MapHandle::get`) for a given target key. However, it is sometimes necessary to access unknown keys, or to iterate through all Key-Value pairs.
|
||||
|
||||
CCF offers a member function :cpp:func:`kv::MapHandle::foreach` to iterate over all the elements written to that :cpp:type:`kv::Map` so far, and run a lambda function for each Key-Value pair. Note that a :cpp:class:`kv::MapHandle::foreach` loop can be ended early by returning ``false`` from this lambda, while ``true`` should be returned to continue iteration.
|
||||
CCF offers a member function :cpp:func:`ccf::kv::MapHandle::foreach` to iterate over all the elements written to that :cpp:type:`ccf::kv::Map` so far, and run a lambda function for each Key-Value pair. Note that a :cpp:class:`ccf::kv::MapHandle::foreach` loop can be ended early by returning ``false`` from this lambda, while ``true`` should be returned to continue iteration.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
|
@ -192,7 +192,7 @@ CCF offers a member function :cpp:func:`kv::MapHandle::foreach` to iterate over
|
|||
Applying and reverting writes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Changes to the KV are made by atomic transactions. For a given :cpp:class:`kv::Tx`, either all of its writes are applied, or none are. Only applied writes are replicated and may be globally committed. Transactions may be abandoned without applying their writes - their changes will never be seen by other transactions.
|
||||
Changes to the KV are made by atomic transactions. For a given :cpp:class:`ccf::kv::Tx`, either all of its writes are applied, or none are. Only applied writes are replicated and may be globally committed. Transactions may be abandoned without applying their writes - their changes will never be seen by other transactions.
|
||||
|
||||
By default CCF decides which transactions are successful (so should be applied to the persistent store) by looking at the status code contained in the response: all transactions producing ``2xx`` status codes will be applied, while any other status code will be treated as an error and will `not` be applied to the persistent store. If this behaviour is not desired, for instance when an app wants to log incoming requests even though they produce an error, then it can be dynamically overridden by explicitly telling CCF whether it should apply a given transaction:
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
Key-Value Serialisation
|
||||
=======================
|
||||
|
||||
Every transaction executed by the primary on its Key-Value store is serialised before being replicated to all backups of the CCF network and written to the ledger. The serialisation format is defined per :cpp:type:`kv::Map` and distinctly for the key and value types.
|
||||
Every transaction executed by the primary on its Key-Value store is serialised before being replicated to all backups of the CCF network and written to the ledger. The serialisation format is defined per :cpp:type:`ccf::kv::Map` and distinctly for the key and value types.
|
||||
|
||||
.. tip:: Selecting the right serialision format for a KV map depends on the application logic but is generally a trade-off between performance and auditability of the ledger. For example, the default serialisation format for :cpp:type:`kv::Map` is JSON and allows for easy parsing of transactions in the `public` ledger. For more performance sensitive use cases, apps may define or use their own serialisers.
|
||||
.. tip:: Selecting the right serialision format for a KV map depends on the application logic but is generally a trade-off between performance and auditability of the ledger. For example, the default serialisation format for :cpp:type:`ccf::kv::Map` is JSON and allows for easy parsing of transactions in the `public` ledger. For more performance sensitive use cases, apps may define or use their own serialisers.
|
||||
|
||||
Custom key and value types
|
||||
--------------------------
|
||||
|
||||
User-defined types can be used for both the key and value types of a :cpp:type:`kv::Map`. It must be possible to use the key type as the key of an ``std::map`` (so it must be copyable, assignable, and less-comparable), and both types must be serialisable. By default, when using a :cpp:type:`kv::Map`, serialisation converts to JSON. To add support to your custom types, it should usually be possible to use the ``DECLARE_JSON_...`` macros:
|
||||
User-defined types can be used for both the key and value types of a :cpp:type:`ccf::kv::Map`. It must be possible to use the key type as the key of an ``std::map`` (so it must be copyable, assignable, and less-comparable), and both types must be serialisable. By default, when using a :cpp:type:`ccf::kv::Map`, serialisation converts to JSON. To add support to your custom types, it should usually be possible to use the ``DECLARE_JSON_...`` macros:
|
||||
|
||||
.. literalinclude:: ../../../src/kv/test/kv_serialisation.cpp
|
||||
:language: cpp
|
||||
|
@ -22,7 +22,7 @@ Custom serialisers can also be defined. The serialiser itself must be a type imp
|
|||
:start-after: SNIPPET_START: CustomSerialiser definition
|
||||
:end-before: SNIPPET_END: CustomSerialiser definition
|
||||
|
||||
To use these serialised for a specific map declare the map as a :cpp:class:`kv::TypedMap`, adding the appropriate serialiser types for the key and value types:
|
||||
To use these serialised for a specific map declare the map as a :cpp:class:`ccf::kv::TypedMap`, adding the appropriate serialiser types for the key and value types:
|
||||
|
||||
.. literalinclude:: ../../../src/kv/test/kv_serialisation.cpp
|
||||
:language: cpp
|
||||
|
|
|
@ -79,7 +79,7 @@ Glossary
|
|||
`Transport Layer Security <https://en.wikipedia.org/wiki/Transport_Layer_Security>`_ is an IETF cryptographic protocol standard designed to secure communications between a client and a server over a computer network.
|
||||
|
||||
Transaction ID
|
||||
Unique transaction identifier in CCF, composed of a View and a Sequence Number separated by a period. Sequence Numbers start from 1, and are contiguous. Views are monotonic. E.g. The transaction ID ``2.15`` indicates the View is ``2`` and the Sequence Number is ``15``. Sequence Numbers are also referred to as a :cpp:type:`kv::Version` in the context of the Key-Value store.
|
||||
Unique transaction identifier in CCF, composed of a View and a Sequence Number separated by a period. Sequence Numbers start from 1, and are contiguous. Views are monotonic. E.g. The transaction ID ``2.15`` indicates the View is ``2`` and the Sequence Number is ``15``. Sequence Numbers are also referred to as a :cpp:type:`ccf::kv::Version` in the context of the Key-Value store.
|
||||
|
||||
Users
|
||||
Directly interact with the application running in CCF. Their public identity should be voted in by members before they are allowed to issue requests.
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace ccf
|
|||
class RpcFrontend;
|
||||
}
|
||||
|
||||
namespace kv
|
||||
namespace ccf::kv
|
||||
{
|
||||
class Store;
|
||||
}
|
||||
|
|
|
@ -188,7 +188,7 @@ namespace ccf
|
|||
* does not affect the OpenAPI version of the format of the document.
|
||||
*/
|
||||
ApiResult generate_openapi_document_v1(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const std::string& title,
|
||||
const std::string& description,
|
||||
const std::string& document_version,
|
||||
|
@ -197,7 +197,7 @@ namespace ccf
|
|||
/** Get a quote attesting to the hardware this node is running on.
|
||||
*/
|
||||
ApiResult get_quote_for_this_node_v1(
|
||||
kv::ReadOnlyTx& tx, QuoteInfo& quote_info);
|
||||
ccf::kv::ReadOnlyTx& tx, QuoteInfo& quote_info);
|
||||
|
||||
/** Get the id of the currently executing node.
|
||||
*/
|
||||
|
@ -207,7 +207,7 @@ namespace ccf
|
|||
* running on.
|
||||
*/
|
||||
ApiResult get_quotes_for_all_trusted_nodes_v1(
|
||||
kv::ReadOnlyTx& tx, std::map<NodeId, QuoteInfo>& quotes);
|
||||
ccf::kv::ReadOnlyTx& tx, std::map<NodeId, QuoteInfo>& quotes);
|
||||
|
||||
/** Get the view associated with a given seqno, to construct a valid TxID.
|
||||
*/
|
||||
|
@ -216,26 +216,28 @@ namespace ccf
|
|||
/** Get the user data associated with a given user id.
|
||||
*/
|
||||
ApiResult get_user_data_v1(
|
||||
kv::ReadOnlyTx& tx, const UserId& user_id, nlohmann::json& user_data);
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const UserId& user_id,
|
||||
nlohmann::json& user_data);
|
||||
|
||||
/** Get the member data associated with a given member id.
|
||||
*/
|
||||
ApiResult get_member_data_v1(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const MemberId& member_id,
|
||||
nlohmann::json& member_data);
|
||||
|
||||
/** Get the certificate (PEM) of a given user id.
|
||||
*/
|
||||
ApiResult get_user_cert_v1(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const UserId& user_id,
|
||||
ccf::crypto::Pem& user_cert_pem);
|
||||
|
||||
/** Get the certificate (PEM) of a given member id.
|
||||
*/
|
||||
ApiResult get_member_cert_v1(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const MemberId& member_id,
|
||||
ccf::crypto::Pem& member_cert_pem);
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ struct formatter<ccf::crypto::Sha256Hash>
|
|||
};
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
namespace kv::serialisers
|
||||
namespace ccf::kv::serialisers
|
||||
{
|
||||
template <>
|
||||
struct BlitSerialiser<ccf::crypto::Sha256Hash>
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace ccf::endpoints
|
|||
};
|
||||
}
|
||||
|
||||
namespace kv::serialisers
|
||||
namespace ccf::kv::serialisers
|
||||
{
|
||||
template <>
|
||||
struct BlitSerialiser<ccf::endpoints::EndpointKey>
|
||||
|
|
|
@ -53,12 +53,12 @@ namespace ccf::endpoints
|
|||
|
||||
struct EndpointContext : public CommandEndpointContext
|
||||
{
|
||||
EndpointContext(const std::shared_ptr<ccf::RpcContext>& r, kv::Tx& t) :
|
||||
EndpointContext(const std::shared_ptr<ccf::RpcContext>& r, ccf::kv::Tx& t) :
|
||||
CommandEndpointContext(r),
|
||||
tx(t)
|
||||
{}
|
||||
|
||||
kv::Tx& tx;
|
||||
ccf::kv::Tx& tx;
|
||||
};
|
||||
using EndpointFunction = std::function<void(EndpointContext& args)>;
|
||||
|
||||
|
@ -69,12 +69,12 @@ namespace ccf::endpoints
|
|||
struct ReadOnlyEndpointContext : public CommandEndpointContext
|
||||
{
|
||||
ReadOnlyEndpointContext(
|
||||
const std::shared_ptr<ccf::RpcContext>& r, kv::ReadOnlyTx& t) :
|
||||
const std::shared_ptr<ccf::RpcContext>& r, ccf::kv::ReadOnlyTx& t) :
|
||||
CommandEndpointContext(r),
|
||||
tx(t)
|
||||
{}
|
||||
|
||||
kv::ReadOnlyTx& tx;
|
||||
ccf::kv::ReadOnlyTx& tx;
|
||||
};
|
||||
using ReadOnlyEndpointFunction =
|
||||
std::function<void(ReadOnlyEndpointContext& args)>;
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include <regex>
|
||||
#include <set>
|
||||
|
||||
namespace kv
|
||||
namespace ccf::kv
|
||||
{
|
||||
class Consensus;
|
||||
class TxHistory;
|
||||
|
@ -161,8 +161,8 @@ namespace ccf::endpoints
|
|||
std::map<RESTVerb, std::shared_ptr<PathTemplatedEndpoint>>>
|
||||
templated_endpoints;
|
||||
|
||||
kv::Consensus* consensus = nullptr;
|
||||
kv::TxHistory* history = nullptr;
|
||||
ccf::kv::Consensus* consensus = nullptr;
|
||||
ccf::kv::TxHistory* history = nullptr;
|
||||
|
||||
public:
|
||||
EndpointRegistry(const std::string& method_prefix_) :
|
||||
|
@ -254,12 +254,12 @@ namespace ccf::endpoints
|
|||
* internally, so must be able to populate the document
|
||||
* with the supported endpoints however it defines them.
|
||||
*/
|
||||
virtual void build_api(nlohmann::json& document, kv::ReadOnlyTx&);
|
||||
virtual void build_api(nlohmann::json& document, ccf::kv::ReadOnlyTx&);
|
||||
|
||||
virtual void init_handlers();
|
||||
|
||||
virtual EndpointDefinitionPtr find_endpoint(
|
||||
kv::Tx&, ccf::RpcContext& rpc_ctx);
|
||||
ccf::kv::Tx&, ccf::RpcContext& rpc_ctx);
|
||||
|
||||
virtual void execute_endpoint(
|
||||
EndpointDefinitionPtr e, EndpointContext& args);
|
||||
|
@ -268,7 +268,7 @@ namespace ccf::endpoints
|
|||
EndpointDefinitionPtr e, CommandEndpointContext& args, const TxID& tx_id);
|
||||
|
||||
virtual std::set<RESTVerb> get_allowed_verbs(
|
||||
kv::Tx&, const ccf::RpcContext& rpc_ctx);
|
||||
ccf::kv::Tx&, const ccf::RpcContext& rpc_ctx);
|
||||
|
||||
virtual bool request_needs_root(const ccf::RpcContext& rpc_ctx);
|
||||
|
||||
|
@ -278,9 +278,9 @@ namespace ccf::endpoints
|
|||
|
||||
virtual void tick(std::chrono::milliseconds);
|
||||
|
||||
void set_consensus(kv::Consensus* c);
|
||||
void set_consensus(ccf::kv::Consensus* c);
|
||||
|
||||
void set_history(kv::TxHistory* h);
|
||||
void set_history(ccf::kv::TxHistory* h);
|
||||
|
||||
// Override these methods to log or report request metrics.
|
||||
virtual void handle_event_request_completed(
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace ccf
|
|||
const std::vector<std::shared_ptr<AuthnPolicy>>& _policies);
|
||||
|
||||
std::unique_ptr<AuthnIdentity> authenticate(
|
||||
kv::ReadOnlyTx&,
|
||||
ccf::kv::ReadOnlyTx&,
|
||||
const std::shared_ptr<ccf::RpcContext>&,
|
||||
std::string&) override;
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace ccf
|
|||
virtual ~AuthnPolicy() = default;
|
||||
|
||||
virtual std::unique_ptr<AuthnIdentity> authenticate(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const std::shared_ptr<ccf::RpcContext>& ctx,
|
||||
std::string& error_reason) = 0;
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace ccf
|
|||
virtual ~UserCertAuthnPolicy();
|
||||
|
||||
std::unique_ptr<AuthnIdentity> authenticate(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const std::shared_ptr<ccf::RpcContext>& ctx,
|
||||
std::string& error_reason) override;
|
||||
|
||||
|
@ -72,7 +72,7 @@ namespace ccf
|
|||
virtual ~MemberCertAuthnPolicy();
|
||||
|
||||
std::unique_ptr<AuthnIdentity> authenticate(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const std::shared_ptr<ccf::RpcContext>& ctx,
|
||||
std::string& error_reason) override;
|
||||
|
||||
|
@ -99,7 +99,7 @@ namespace ccf
|
|||
static constexpr auto SECURITY_SCHEME_NAME = "node_cert";
|
||||
|
||||
std::unique_ptr<AuthnIdentity> authenticate(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const std::shared_ptr<ccf::RpcContext>& ctx,
|
||||
std::string& error_reason) override;
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ namespace ccf
|
|||
~MemberCOSESign1AuthnPolicy();
|
||||
|
||||
std::unique_ptr<AuthnIdentity> authenticate(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const std::shared_ptr<ccf::RpcContext>& ctx,
|
||||
std::string& error_reason) override;
|
||||
|
||||
|
@ -158,7 +158,7 @@ namespace ccf
|
|||
using MemberCOSESign1AuthnPolicy::MemberCOSESign1AuthnPolicy;
|
||||
|
||||
std::unique_ptr<AuthnIdentity> authenticate(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const std::shared_ptr<ccf::RpcContext>& ctx,
|
||||
std::string& error_reason) override;
|
||||
|
||||
|
@ -182,7 +182,7 @@ namespace ccf
|
|||
static const OpenAPISecuritySchema security_schema;
|
||||
|
||||
virtual std::unique_ptr<UserCOSESign1AuthnIdentity> _authenticate(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const std::shared_ptr<ccf::RpcContext>& ctx,
|
||||
std::string& error_reason);
|
||||
|
||||
|
@ -198,7 +198,7 @@ namespace ccf
|
|||
~UserCOSESign1AuthnPolicy();
|
||||
|
||||
std::unique_ptr<AuthnIdentity> authenticate(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const std::shared_ptr<ccf::RpcContext>& ctx,
|
||||
std::string& error_reason) override;
|
||||
|
||||
|
@ -240,7 +240,7 @@ namespace ccf
|
|||
{}
|
||||
|
||||
std::unique_ptr<AuthnIdentity> authenticate(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const std::shared_ptr<ccf::RpcContext>& ctx,
|
||||
std::string& error_reason) override;
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace ccf
|
|||
static constexpr auto SECURITY_SCHEME_NAME = "no_auth";
|
||||
|
||||
std::unique_ptr<AuthnIdentity> authenticate(
|
||||
kv::ReadOnlyTx&,
|
||||
ccf::kv::ReadOnlyTx&,
|
||||
const std::shared_ptr<ccf::RpcContext>&,
|
||||
std::string&) override;
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace ccf
|
|||
virtual ~JwtAuthnPolicy();
|
||||
|
||||
std::unique_ptr<AuthnIdentity> authenticate(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const std::shared_ptr<ccf::RpcContext>& ctx,
|
||||
std::string& error_reason) override;
|
||||
|
||||
|
|
|
@ -202,7 +202,7 @@ struct formatter<ccf::EntityId<FmtExtender>>
|
|||
};
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
namespace kv::serialisers
|
||||
namespace ccf::kv::serialisers
|
||||
{
|
||||
template <typename FmtExtender>
|
||||
struct BlitSerialiser<ccf::EntityId<FmtExtender>>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "ccf/tx_id.h"
|
||||
#include "ccf/tx_status.h"
|
||||
|
||||
namespace kv
|
||||
namespace ccf::kv
|
||||
{
|
||||
class Consensus;
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ namespace ccf::historical
|
|||
ccf::View view, ccf::SeqNo seqno, std::string& error_reason)>;
|
||||
|
||||
HistoricalTxStatus is_tx_committed_v2(
|
||||
kv::Consensus* consensus,
|
||||
ccf::kv::Consensus* consensus,
|
||||
ccf::View view,
|
||||
ccf::SeqNo seqno,
|
||||
std::string& error_reason);
|
||||
|
|
|
@ -16,14 +16,14 @@ namespace ccf::historical
|
|||
struct State
|
||||
{
|
||||
/// Read-only historical store at transaction_id
|
||||
kv::ReadOnlyStorePtr store = nullptr;
|
||||
ccf::kv::ReadOnlyStorePtr store = nullptr;
|
||||
/// Receipt for ledger entry at transaction_id
|
||||
TxReceiptImplPtr receipt = nullptr;
|
||||
/// View and Sequence Number for the State
|
||||
ccf::TxID transaction_id;
|
||||
|
||||
State(
|
||||
const kv::ReadOnlyStorePtr& store_,
|
||||
const ccf::kv::ReadOnlyStorePtr& store_,
|
||||
const TxReceiptImplPtr& receipt_,
|
||||
const ccf::TxID& transaction_id_) :
|
||||
store(store_),
|
||||
|
@ -93,7 +93,7 @@ namespace ccf::historical
|
|||
* is equivalent to get_store_at(handle, seqno, seqno), but returns nullptr
|
||||
* if the state is currently unavailable.
|
||||
*/
|
||||
virtual kv::ReadOnlyStorePtr get_store_at(
|
||||
virtual ccf::kv::ReadOnlyStorePtr get_store_at(
|
||||
RequestHandle handle,
|
||||
ccf::SeqNo seqno,
|
||||
ExpiryDuration seconds_until_expiry) = 0;
|
||||
|
@ -101,7 +101,7 @@ namespace ccf::historical
|
|||
/** Same as @c get_store_at but uses default expiry value.
|
||||
* @see get_store_at
|
||||
*/
|
||||
virtual kv::ReadOnlyStorePtr get_store_at(
|
||||
virtual ccf::kv::ReadOnlyStorePtr get_store_at(
|
||||
RequestHandle handle, ccf::SeqNo seqno) = 0;
|
||||
|
||||
/** Retrieve a full state at a given seqno, including the Store, the TxID
|
||||
|
@ -135,7 +135,7 @@ namespace ccf::historical
|
|||
* vector will be of length (end_seqno - start_seqno + 1) and will contain
|
||||
* no nullptrs.
|
||||
*/
|
||||
virtual std::vector<kv::ReadOnlyStorePtr> get_store_range(
|
||||
virtual std::vector<ccf::kv::ReadOnlyStorePtr> get_store_range(
|
||||
RequestHandle handle,
|
||||
ccf::SeqNo start_seqno,
|
||||
ccf::SeqNo end_seqno,
|
||||
|
@ -144,7 +144,7 @@ namespace ccf::historical
|
|||
/** Same as @c get_store_range but uses default expiry value.
|
||||
* @see get_store_range
|
||||
*/
|
||||
virtual std::vector<kv::ReadOnlyStorePtr> get_store_range(
|
||||
virtual std::vector<ccf::kv::ReadOnlyStorePtr> get_store_range(
|
||||
RequestHandle handle, ccf::SeqNo start_seqno, ccf::SeqNo end_seqno) = 0;
|
||||
|
||||
/** Retrieve a range of states at the given indices, including the Store,
|
||||
|
@ -165,11 +165,11 @@ namespace ccf::historical
|
|||
|
||||
/** Retrieve stores for a set of given indices.
|
||||
*/
|
||||
virtual std::vector<kv::ReadOnlyStorePtr> get_stores_for(
|
||||
virtual std::vector<ccf::kv::ReadOnlyStorePtr> get_stores_for(
|
||||
RequestHandle handle,
|
||||
const SeqNoCollection& seqnos,
|
||||
ExpiryDuration seconds_until_expiry) = 0;
|
||||
virtual std::vector<kv::ReadOnlyStorePtr> get_stores_for(
|
||||
virtual std::vector<ccf::kv::ReadOnlyStorePtr> get_stores_for(
|
||||
RequestHandle handle, const SeqNoCollection& seqnos) = 0;
|
||||
|
||||
/** Retrieve states for a set of given indices.
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace ccf::historical
|
|||
// additional entries have been requested, in which case the caller should
|
||||
// retry later.
|
||||
bool populate_service_endorsements(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
ccf::historical::StatePtr& state,
|
||||
AbstractStateCache& state_cache,
|
||||
std::shared_ptr<NetworkIdentitySubsystemInterface>
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace ccf::indexing::strategies
|
|||
virtual ~VisitEachEntryInMap() = default;
|
||||
|
||||
void handle_committed_transaction(
|
||||
const ccf::TxID& tx_id, const kv::ReadOnlyStorePtr& store) override;
|
||||
const ccf::TxID& tx_id, const ccf::kv::ReadOnlyStorePtr& store) override;
|
||||
std::optional<ccf::SeqNo> next_requested() override;
|
||||
|
||||
nlohmann::json describe() override;
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace ccf::indexing
|
|||
* transaction.
|
||||
*/
|
||||
virtual void handle_committed_transaction(
|
||||
const ccf::TxID& tx_id, const kv::ReadOnlyStorePtr& store) = 0;
|
||||
const ccf::TxID& tx_id, const ccf::kv::ReadOnlyStorePtr& store) = 0;
|
||||
|
||||
virtual void tick() {}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace ccf::js
|
|||
class WithKVExtension : public Base
|
||||
{
|
||||
public:
|
||||
WithKVExtension(TxAccess acc, kv::Tx* tx) : Base(acc)
|
||||
WithKVExtension(TxAccess acc, ccf::kv::Tx* tx) : Base(acc)
|
||||
{
|
||||
// add ccf.kv.*
|
||||
Base::add_extension(
|
||||
|
|
|
@ -21,9 +21,9 @@ namespace ccf::js::extensions
|
|||
class GovEffectsExtension : public ExtensionInterface
|
||||
{
|
||||
public:
|
||||
kv::Tx* tx;
|
||||
ccf::kv::Tx* tx;
|
||||
|
||||
GovEffectsExtension(kv::Tx* t) : tx(t) {}
|
||||
GovEffectsExtension(ccf::kv::Tx* t) : tx(t) {}
|
||||
|
||||
void install(js::core::Context& ctx) override;
|
||||
};
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#include <memory>
|
||||
|
||||
namespace kv
|
||||
namespace ccf::kv
|
||||
{
|
||||
class Tx;
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ namespace ccf::js::extensions
|
|||
|
||||
ccf::js::NamespaceRestriction namespace_restriction;
|
||||
|
||||
KvExtension(kv::Tx* t, const ccf::js::NamespaceRestriction& nr = {});
|
||||
KvExtension(ccf::kv::Tx* t, const ccf::js::NamespaceRestriction& nr = {});
|
||||
~KvExtension();
|
||||
|
||||
void install(js::core::Context& ctx);
|
||||
|
|
|
@ -84,7 +84,7 @@ namespace ccf::js
|
|||
* later be dispatched to.
|
||||
*/
|
||||
ccf::ApiResult install_custom_endpoints_v1(
|
||||
kv::Tx& tx, const ccf::js::Bundle& bundle);
|
||||
ccf::kv::Tx& tx, const ccf::js::Bundle& bundle);
|
||||
|
||||
/**
|
||||
* Retrieve all endpoint definitions currently in-use. This returns the same
|
||||
|
@ -93,14 +93,14 @@ namespace ccf::js
|
|||
* due to internal normalisation.
|
||||
*/
|
||||
ccf::ApiResult get_custom_endpoints_v1(
|
||||
ccf::js::Bundle& bundle, kv::ReadOnlyTx& tx);
|
||||
ccf::js::Bundle& bundle, ccf::kv::ReadOnlyTx& tx);
|
||||
|
||||
/**
|
||||
* Retrieve property definition for a single JS endpoint.
|
||||
*/
|
||||
ccf::ApiResult get_custom_endpoint_properties_v1(
|
||||
ccf::endpoints::EndpointProperties& properties,
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const ccf::RESTVerb& verb,
|
||||
const ccf::endpoints::URI& uri);
|
||||
|
||||
|
@ -108,7 +108,9 @@ namespace ccf::js
|
|||
* Retrieve content of a single JS module.
|
||||
*/
|
||||
ccf::ApiResult get_custom_endpoint_module_v1(
|
||||
std::string& code, kv::ReadOnlyTx& tx, const std::string& module_name);
|
||||
std::string& code,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const std::string& module_name);
|
||||
|
||||
/**
|
||||
* Pass a function to control which maps can be accessed by JS endpoints.
|
||||
|
@ -121,7 +123,7 @@ namespace ccf::js
|
|||
* bound any values specified here.
|
||||
*/
|
||||
ccf::ApiResult set_js_runtime_options_v1(
|
||||
kv::Tx& tx, const ccf::JSRuntimeOptions& options);
|
||||
ccf::kv::Tx& tx, const ccf::JSRuntimeOptions& options);
|
||||
|
||||
/**
|
||||
* Get the options which currently control JS execution. If no value has
|
||||
|
@ -129,14 +131,14 @@ namespace ccf::js
|
|||
* which will be applied instead.
|
||||
*/
|
||||
ccf::ApiResult get_js_runtime_options_v1(
|
||||
ccf::JSRuntimeOptions& options, kv::ReadOnlyTx& tx);
|
||||
ccf::JSRuntimeOptions& options, ccf::kv::ReadOnlyTx& tx);
|
||||
|
||||
/**
|
||||
* Record action details by storing them in KV maps using a common format,
|
||||
* for the purposes of offline audit using the ledger.
|
||||
*/
|
||||
ccf::ApiResult record_action_for_audit_v1(
|
||||
kv::Tx& tx,
|
||||
ccf::kv::Tx& tx,
|
||||
ccf::ActionFormat format,
|
||||
const std::string& user_id,
|
||||
const std::string& action_name,
|
||||
|
@ -148,7 +150,7 @@ namespace ccf::js
|
|||
* size, an authenticated timestamp (@p created_at) is required.
|
||||
*/
|
||||
ccf::ApiResult check_action_not_replayed_v1(
|
||||
kv::Tx& tx,
|
||||
ccf::kv::Tx& tx,
|
||||
uint64_t created_at,
|
||||
const std::span<const uint8_t> action,
|
||||
ccf::InvalidArgsReason& reason);
|
||||
|
@ -157,7 +159,7 @@ namespace ccf::js
|
|||
/// endpoints before delegating to base implementation.
|
||||
///@{
|
||||
ccf::endpoints::EndpointDefinitionPtr find_endpoint(
|
||||
kv::Tx& tx, ccf::RpcContext& rpc_ctx) override;
|
||||
ccf::kv::Tx& tx, ccf::RpcContext& rpc_ctx) override;
|
||||
|
||||
void execute_endpoint(
|
||||
ccf::endpoints::EndpointDefinitionPtr e,
|
||||
|
@ -168,7 +170,7 @@ namespace ccf::js
|
|||
ccf::endpoints::CommandEndpointContext& endpoint_ctx,
|
||||
const ccf::TxID& tx_id) override;
|
||||
|
||||
void build_api(nlohmann::json& document, kv::ReadOnlyTx& tx) override;
|
||||
void build_api(nlohmann::json& document, ccf::kv::ReadOnlyTx& tx) override;
|
||||
///@}
|
||||
|
||||
virtual ccf::js::extensions::Extensions get_extensions(
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Licensed under the Apache 2.0 License.
|
||||
#pragma once
|
||||
|
||||
namespace kv
|
||||
namespace ccf::kv
|
||||
{
|
||||
class AbstractHandle
|
||||
{
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
namespace kv
|
||||
namespace ccf::kv
|
||||
{
|
||||
struct GetName
|
||||
{
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace kv
|
||||
namespace ccf::kv
|
||||
{
|
||||
class ConfigurableConsensus;
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "ccf/kv/serialisers/json_serialiser.h"
|
||||
#include "ccf/kv/untyped.h"
|
||||
|
||||
namespace kv
|
||||
namespace ccf::kv
|
||||
{
|
||||
/** Defines the schema of a map accessed by a @c ccf::Tx, exposing associated
|
||||
* types. This map is an unordered associative container of key-value pairs.
|
||||
|
@ -31,11 +31,11 @@ namespace kv
|
|||
public:
|
||||
// Expose correct public aliases of types
|
||||
using ReadOnlyHandle =
|
||||
kv::ReadableMapHandle<K, V, KSerialiser, VSerialiser>;
|
||||
ccf::kv::ReadableMapHandle<K, V, KSerialiser, VSerialiser>;
|
||||
using WriteOnlyHandle =
|
||||
kv::WriteableMapHandle<K, V, KSerialiser, VSerialiser>;
|
||||
using Handle = kv::MapHandle<K, V, KSerialiser, VSerialiser>;
|
||||
using Diff = kv::MapDiff<K, V, KSerialiser, VSerialiser>;
|
||||
ccf::kv::WriteableMapHandle<K, V, KSerialiser, VSerialiser>;
|
||||
using Handle = ccf::kv::MapHandle<K, V, KSerialiser, VSerialiser>;
|
||||
using Diff = ccf::kv::MapDiff<K, V, KSerialiser, VSerialiser>;
|
||||
|
||||
using Write = std::map<K, std::optional<V>>;
|
||||
using CommitHook = CommitHook<Write>;
|
||||
|
@ -49,7 +49,7 @@ namespace kv
|
|||
using GetName::GetName;
|
||||
|
||||
private:
|
||||
static Write deserialise_write(const kv::untyped::Write& w)
|
||||
static Write deserialise_write(const ccf::kv::untyped::Write& w)
|
||||
{
|
||||
Write typed_writes;
|
||||
for (const auto& [uk, opt_uv] : w)
|
||||
|
@ -70,16 +70,16 @@ namespace kv
|
|||
}
|
||||
|
||||
public:
|
||||
static kv::untyped::CommitHook wrap_commit_hook(const CommitHook& hook)
|
||||
static ccf::kv::untyped::CommitHook wrap_commit_hook(const CommitHook& hook)
|
||||
{
|
||||
return [hook](Version v, const kv::untyped::Write& w) {
|
||||
return [hook](Version v, const ccf::kv::untyped::Write& w) {
|
||||
hook(v, deserialise_write(w));
|
||||
};
|
||||
}
|
||||
|
||||
static kv::untyped::MapHook wrap_map_hook(const MapHook& hook)
|
||||
static ccf::kv::untyped::MapHook wrap_map_hook(const MapHook& hook)
|
||||
{
|
||||
return [hook](Version v, const kv::untyped::Write& w) {
|
||||
return [hook](Version v, const ccf::kv::untyped::Write& w) {
|
||||
return hook(v, deserialise_write(w));
|
||||
};
|
||||
}
|
||||
|
@ -95,14 +95,14 @@ namespace kv
|
|||
|
||||
template <typename K, typename V>
|
||||
using JsonSerialisedMap =
|
||||
MapSerialisedWith<K, V, kv::serialisers::JsonSerialiser>;
|
||||
MapSerialisedWith<K, V, ccf::kv::serialisers::JsonSerialiser>;
|
||||
|
||||
template <typename K, typename V>
|
||||
using RawCopySerialisedMap = TypedMap<
|
||||
K,
|
||||
V,
|
||||
kv::serialisers::BlitSerialiser<K>,
|
||||
kv::serialisers::BlitSerialiser<V>>;
|
||||
ccf::kv::serialisers::BlitSerialiser<K>,
|
||||
ccf::kv::serialisers::BlitSerialiser<V>>;
|
||||
|
||||
/** Short name for default-serialised maps, using JSON serialisers. Support
|
||||
* for custom types can be added through the DECLARE_JSON... macros.
|
||||
|
|
|
@ -4,21 +4,21 @@
|
|||
|
||||
#include "ccf/kv/untyped_map_diff.h"
|
||||
|
||||
namespace kv
|
||||
namespace ccf::kv
|
||||
{
|
||||
template <typename K, typename V, typename KSerialiser, typename VSerialiser>
|
||||
class MapDiff : public AbstractHandle
|
||||
{
|
||||
protected:
|
||||
kv::untyped::MapDiff map_diff;
|
||||
ccf::kv::untyped::MapDiff map_diff;
|
||||
|
||||
public:
|
||||
using KeyType = K;
|
||||
using ValueType = V;
|
||||
|
||||
MapDiff(kv::untyped::MapDiff map_diff_) : map_diff(map_diff_) {}
|
||||
MapDiff(ccf::kv::untyped::MapDiff map_diff_) : map_diff(map_diff_) {}
|
||||
|
||||
MapDiff(kv::untyped::ChangeSet& changes, const std::string& map_name) :
|
||||
MapDiff(ccf::kv::untyped::ChangeSet& changes, const std::string& map_name) :
|
||||
map_diff(changes, map_name)
|
||||
{}
|
||||
|
||||
|
@ -86,8 +86,8 @@ namespace kv
|
|||
{
|
||||
const auto& g =
|
||||
[&](
|
||||
const kv::serialisers::SerialisedEntry& k_rep,
|
||||
const std::optional<kv::serialisers::SerialisedEntry>& v_rep)
|
||||
const ccf::kv::serialisers::SerialisedEntry& k_rep,
|
||||
const std::optional<ccf::kv::serialisers::SerialisedEntry>& v_rep)
|
||||
-> bool {
|
||||
const auto k = KSerialiser::from_serialised(k_rep);
|
||||
if (v_rep.has_value())
|
||||
|
@ -116,8 +116,8 @@ namespace kv
|
|||
void foreach_key(F&& f)
|
||||
{
|
||||
auto g = [&](
|
||||
const kv::serialisers::SerialisedEntry& k_rep,
|
||||
const kv::serialisers::SerialisedEntry&) {
|
||||
const ccf::kv::serialisers::SerialisedEntry& k_rep,
|
||||
const ccf::kv::serialisers::SerialisedEntry&) {
|
||||
return f(KSerialiser::from_serialised(k_rep));
|
||||
};
|
||||
map_diff.foreach(g);
|
||||
|
@ -133,18 +133,19 @@ namespace kv
|
|||
template <class F>
|
||||
void foreach_value(F&& f)
|
||||
{
|
||||
auto g = [&](
|
||||
const kv::serialisers::SerialisedEntry&,
|
||||
const std::optional<kv::serialisers::SerialisedEntry>& v_rep) {
|
||||
if (v_rep.has_value())
|
||||
{
|
||||
return f(VSerialiser::from_serialised(v_rep));
|
||||
}
|
||||
else
|
||||
{
|
||||
return f(std::nullopt);
|
||||
}
|
||||
};
|
||||
auto g =
|
||||
[&](
|
||||
const ccf::kv::serialisers::SerialisedEntry&,
|
||||
const std::optional<ccf::kv::serialisers::SerialisedEntry>& v_rep) {
|
||||
if (v_rep.has_value())
|
||||
{
|
||||
return f(VSerialiser::from_serialised(v_rep));
|
||||
}
|
||||
else
|
||||
{
|
||||
return f(std::nullopt);
|
||||
}
|
||||
};
|
||||
map_diff.foreach(g);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,21 +4,21 @@
|
|||
|
||||
#include "ccf/kv/untyped_map_handle.h"
|
||||
|
||||
namespace kv
|
||||
namespace ccf::kv
|
||||
{
|
||||
/** Grants read access to a @c kv::Map, as part of a @c kv::Tx.
|
||||
/** Grants read access to a @c ccf::kv::Map, as part of a @c ccf::kv::Tx.
|
||||
*/
|
||||
template <typename K, typename V, typename KSerialiser, typename VSerialiser>
|
||||
class ReadableMapHandle
|
||||
{
|
||||
protected:
|
||||
kv::untyped::MapHandle& read_handle;
|
||||
ccf::kv::untyped::MapHandle& read_handle;
|
||||
|
||||
public:
|
||||
using KeyType = K;
|
||||
using ValueType = V;
|
||||
|
||||
ReadableMapHandle(kv::untyped::MapHandle& uh) : read_handle(uh) {}
|
||||
ReadableMapHandle(ccf::kv::untyped::MapHandle& uh) : read_handle(uh) {}
|
||||
|
||||
/** Get name of this map.
|
||||
*
|
||||
|
@ -146,8 +146,8 @@ namespace kv
|
|||
void foreach(F&& f)
|
||||
{
|
||||
auto g = [&](
|
||||
const kv::serialisers::SerialisedEntry& k_rep,
|
||||
const kv::serialisers::SerialisedEntry& v_rep) {
|
||||
const ccf::kv::serialisers::SerialisedEntry& k_rep,
|
||||
const ccf::kv::serialisers::SerialisedEntry& v_rep) {
|
||||
return f(
|
||||
KSerialiser::from_serialised(k_rep),
|
||||
VSerialiser::from_serialised(v_rep));
|
||||
|
@ -169,8 +169,8 @@ namespace kv
|
|||
void foreach_key(F&& f)
|
||||
{
|
||||
auto g = [&](
|
||||
const kv::serialisers::SerialisedEntry& k_rep,
|
||||
const kv::serialisers::SerialisedEntry&) {
|
||||
const ccf::kv::serialisers::SerialisedEntry& k_rep,
|
||||
const ccf::kv::serialisers::SerialisedEntry&) {
|
||||
return f(KSerialiser::from_serialised(k_rep));
|
||||
};
|
||||
read_handle.foreach(g);
|
||||
|
@ -190,8 +190,8 @@ namespace kv
|
|||
void foreach_value(F&& f)
|
||||
{
|
||||
auto g = [&](
|
||||
const kv::serialisers::SerialisedEntry&,
|
||||
const kv::serialisers::SerialisedEntry& v_rep) {
|
||||
const ccf::kv::serialisers::SerialisedEntry&,
|
||||
const ccf::kv::serialisers::SerialisedEntry& v_rep) {
|
||||
return f(VSerialiser::from_serialised(v_rep));
|
||||
};
|
||||
read_handle.foreach(g);
|
||||
|
@ -211,16 +211,16 @@ namespace kv
|
|||
}
|
||||
};
|
||||
|
||||
/** Grants write access to a @c kv::Map, as part of a @c kv::Tx.
|
||||
/** Grants write access to a @c ccf::kv::Map, as part of a @c ccf::kv::Tx.
|
||||
*/
|
||||
template <typename K, typename V, typename KSerialiser, typename VSerialiser>
|
||||
class WriteableMapHandle
|
||||
{
|
||||
protected:
|
||||
kv::untyped::MapHandle& write_handle;
|
||||
ccf::kv::untyped::MapHandle& write_handle;
|
||||
|
||||
public:
|
||||
WriteableMapHandle(kv::untyped::MapHandle& uh) : write_handle(uh) {}
|
||||
WriteableMapHandle(ccf::kv::untyped::MapHandle& uh) : write_handle(uh) {}
|
||||
|
||||
/** Write value at key.
|
||||
*
|
||||
|
@ -255,10 +255,11 @@ namespace kv
|
|||
}
|
||||
};
|
||||
|
||||
/** Grants read and write access to a @c kv::Map, as part of a @c kv::Tx.
|
||||
/** Grants read and write access to a @c ccf::kv::Map, as part of a @c
|
||||
* ccf::kv::Tx.
|
||||
*
|
||||
* @see kv::ReadableMapHandle
|
||||
* @see kv::WriteableMapHandle
|
||||
* @see ccf::kv::ReadableMapHandle
|
||||
* @see ccf::kv::WriteableMapHandle
|
||||
*/
|
||||
template <typename K, typename V, typename KSerialiser, typename VSerialiser>
|
||||
class MapHandle : public AbstractHandle,
|
||||
|
@ -266,13 +267,14 @@ namespace kv
|
|||
public WriteableMapHandle<K, V, KSerialiser, VSerialiser>
|
||||
{
|
||||
protected:
|
||||
kv::untyped::MapHandle untyped_handle;
|
||||
ccf::kv::untyped::MapHandle untyped_handle;
|
||||
|
||||
using ReadableBase = ReadableMapHandle<K, V, KSerialiser, VSerialiser>;
|
||||
using WriteableBase = WriteableMapHandle<K, V, KSerialiser, VSerialiser>;
|
||||
|
||||
public:
|
||||
MapHandle(kv::untyped::ChangeSet& changes, const std::string& map_name) :
|
||||
MapHandle(
|
||||
ccf::kv::untyped::ChangeSet& changes, const std::string& map_name) :
|
||||
ReadableBase(untyped_handle),
|
||||
WriteableBase(untyped_handle),
|
||||
untyped_handle(changes, map_name)
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#include <memory>
|
||||
|
||||
namespace kv
|
||||
namespace ccf::kv
|
||||
{
|
||||
class ReadOnlyStore
|
||||
{
|
||||
|
@ -15,9 +15,9 @@ namespace kv
|
|||
virtual ~ReadOnlyStore() = default;
|
||||
|
||||
virtual ccf::TxID get_txid() = 0;
|
||||
virtual kv::ReadOnlyTx create_read_only_tx() = 0;
|
||||
virtual std::unique_ptr<kv::ReadOnlyTx> create_read_only_tx_ptr() = 0;
|
||||
virtual kv::TxDiff create_tx_diff() = 0;
|
||||
virtual ccf::kv::ReadOnlyTx create_read_only_tx() = 0;
|
||||
virtual std::unique_ptr<ccf::kv::ReadOnlyTx> create_read_only_tx_ptr() = 0;
|
||||
virtual ccf::kv::TxDiff create_tx_diff() = 0;
|
||||
};
|
||||
|
||||
using ReadOnlyStorePtr = std::shared_ptr<ReadOnlyStore>;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "ccf/ds/nonstd.h"
|
||||
#include "ccf/kv/serialisers/serialised_entry.h"
|
||||
|
||||
namespace kv::serialisers
|
||||
namespace ccf::kv::serialisers
|
||||
{
|
||||
// Converts values to their raw, in-memory representation. To add support for
|
||||
// custom types, add a specialization of BlitSerialiser for them.
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace kv::serialisers
|
||||
namespace ccf::kv::serialisers
|
||||
{
|
||||
// Converts values to and from JSON, using nlohmann JSON. To add support for
|
||||
// custom types, make them convertible to nlohmann::json. You may do this
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#pragma once
|
||||
#include "ccf/byte_vector.h"
|
||||
|
||||
namespace kv::serialisers
|
||||
namespace ccf::kv::serialisers
|
||||
{
|
||||
using SerialisedEntry = ccf::ByteVector;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "ccf/kv/set_handle.h"
|
||||
#include "ccf/kv/untyped.h"
|
||||
|
||||
namespace kv
|
||||
namespace ccf::kv
|
||||
{
|
||||
/** Defines the schema of a set type accessed by a @c ccf::Tx. This set is an
|
||||
* unordered container of unique keys. Each key is either present or missing
|
||||
|
@ -21,24 +21,26 @@ namespace kv
|
|||
* evaluated on the serialised form; if unequal Ks produce the same
|
||||
* serialisation, they will coincide within this set.
|
||||
*
|
||||
* This is implemented as a @c kv::Map from K to Unit, and the serialisation
|
||||
* of the unit values is overridable with the Unit template parameter.
|
||||
* This is implemented as a @c ccf::kv::Map from K to Unit, and the
|
||||
* serialisation of the unit values is overridable with the Unit template
|
||||
* parameter.
|
||||
*/
|
||||
template <
|
||||
typename K,
|
||||
typename KSerialiser,
|
||||
typename Unit = kv::serialisers::ZeroBlitUnitCreator>
|
||||
typename Unit = ccf::kv::serialisers::ZeroBlitUnitCreator>
|
||||
class TypedSet : public GetName
|
||||
{
|
||||
public:
|
||||
using ReadOnlyHandle = kv::ReadableSetHandle<K, KSerialiser>;
|
||||
using WriteOnlyHandle = kv::WriteableSetHandle<K, KSerialiser, Unit>;
|
||||
using Handle = kv::SetHandle<K, KSerialiser, Unit>;
|
||||
using ReadOnlyHandle = ccf::kv::ReadableSetHandle<K, KSerialiser>;
|
||||
using WriteOnlyHandle = ccf::kv::WriteableSetHandle<K, KSerialiser, Unit>;
|
||||
using Handle = ccf::kv::SetHandle<K, KSerialiser, Unit>;
|
||||
|
||||
// Note: The type V of the value `std::optional<V>` does not matter here.
|
||||
// The optional type is required to differentiate additions from deletions,
|
||||
// and to provide a consistent interface with the more generic `TypedMap`.
|
||||
using Write = std::map<K, std::optional<kv::serialisers::SerialisedEntry>>;
|
||||
using Write =
|
||||
std::map<K, std::optional<ccf::kv::serialisers::SerialisedEntry>>;
|
||||
using MapHook = MapHook<Write>;
|
||||
using CommitHook = CommitHook<Write>;
|
||||
|
||||
|
@ -48,7 +50,7 @@ namespace kv
|
|||
using GetName::GetName;
|
||||
|
||||
private:
|
||||
static Write deserialise_write(const kv::untyped::Write& w)
|
||||
static Write deserialise_write(const ccf::kv::untyped::Write& w)
|
||||
{
|
||||
Write typed_writes;
|
||||
for (const auto& [uk, opt_uv] : w)
|
||||
|
@ -68,16 +70,16 @@ namespace kv
|
|||
}
|
||||
|
||||
public:
|
||||
static kv::untyped::CommitHook wrap_commit_hook(const CommitHook& hook)
|
||||
static ccf::kv::untyped::CommitHook wrap_commit_hook(const CommitHook& hook)
|
||||
{
|
||||
return [hook](Version v, const kv::untyped::Write& w) {
|
||||
return [hook](Version v, const ccf::kv::untyped::Write& w) {
|
||||
hook(v, deserialise_write(w));
|
||||
};
|
||||
}
|
||||
|
||||
static kv::untyped::MapHook wrap_map_hook(const MapHook& hook)
|
||||
static ccf::kv::untyped::MapHook wrap_map_hook(const MapHook& hook)
|
||||
{
|
||||
return [hook](Version v, const kv::untyped::Write& w) {
|
||||
return [hook](Version v, const ccf::kv::untyped::Write& w) {
|
||||
return hook(v, deserialise_write(w));
|
||||
};
|
||||
}
|
||||
|
@ -87,15 +89,16 @@ namespace kv
|
|||
typename K,
|
||||
template <typename>
|
||||
typename KSerialiser,
|
||||
typename Unit = kv::serialisers::ZeroBlitUnitCreator>
|
||||
typename Unit = ccf::kv::serialisers::ZeroBlitUnitCreator>
|
||||
using SetSerialisedWith = TypedSet<K, KSerialiser<K>, Unit>;
|
||||
|
||||
template <typename K>
|
||||
using JsonSerialisedSet =
|
||||
SetSerialisedWith<K, kv::serialisers::JsonSerialiser>;
|
||||
SetSerialisedWith<K, ccf::kv::serialisers::JsonSerialiser>;
|
||||
|
||||
template <typename K>
|
||||
using RawCopySerialisedSet = TypedSet<K, kv::serialisers::BlitSerialiser<K>>;
|
||||
using RawCopySerialisedSet =
|
||||
TypedSet<K, ccf::kv::serialisers::BlitSerialiser<K>>;
|
||||
|
||||
/** Short name for default-serialised sets, using JSON serialisers. Support
|
||||
* for custom types can be added through the DECLARE_JSON... macros.
|
||||
|
|
|
@ -5,20 +5,20 @@
|
|||
#include "ccf/kv/unit.h"
|
||||
#include "ccf/kv/untyped_map_handle.h"
|
||||
|
||||
namespace kv
|
||||
namespace ccf::kv
|
||||
{
|
||||
/** Grants read access to a @c kv::Set, as part of a @c kv::Tx.
|
||||
/** Grants read access to a @c ccf::kv::Set, as part of a @c ccf::kv::Tx.
|
||||
*/
|
||||
template <typename K, typename KSerialiser>
|
||||
class ReadableSetHandle
|
||||
{
|
||||
protected:
|
||||
kv::untyped::MapHandle& read_handle;
|
||||
ccf::kv::untyped::MapHandle& read_handle;
|
||||
|
||||
public:
|
||||
using KeyType = K;
|
||||
|
||||
ReadableSetHandle(kv::untyped::MapHandle& uh) : read_handle(uh) {}
|
||||
ReadableSetHandle(ccf::kv::untyped::MapHandle& uh) : read_handle(uh) {}
|
||||
|
||||
/** Test whether a key is present in the set.
|
||||
*
|
||||
|
@ -37,7 +37,7 @@ namespace kv
|
|||
/** Test whether a key's presence is globally committed, meaning it has been
|
||||
* replciated and acknowledged by consensus protocol.
|
||||
*
|
||||
* @see kv::ReadableMapHandle::get_globally_committed
|
||||
* @see ccf::kv::ReadableMapHandle::get_globally_committed
|
||||
*
|
||||
* @param key Key to test
|
||||
*
|
||||
|
@ -53,7 +53,7 @@ namespace kv
|
|||
*
|
||||
* Returns nullopt if the key is not present.
|
||||
*
|
||||
* @see kv::ReadableMapHandle::get_version_of_previous_write
|
||||
* @see ccf::kv::ReadableMapHandle::get_version_of_previous_write
|
||||
*
|
||||
* @param key Key to read
|
||||
*
|
||||
|
@ -68,7 +68,7 @@ namespace kv
|
|||
|
||||
/** Iterate over all entries in this set.
|
||||
*
|
||||
* @see kv::ReadableMapHandle::foreach
|
||||
* @see ccf::kv::ReadableMapHandle::foreach
|
||||
*
|
||||
* @tparam F Functor type. Should usually be derived implicitly from f
|
||||
* @param f Functor instance, taking (const K& k) and returning a
|
||||
|
@ -79,8 +79,8 @@ namespace kv
|
|||
void foreach(F&& f)
|
||||
{
|
||||
auto g = [&](
|
||||
const kv::serialisers::SerialisedEntry& k_rep,
|
||||
const kv::serialisers::SerialisedEntry&) {
|
||||
const ccf::kv::serialisers::SerialisedEntry& k_rep,
|
||||
const ccf::kv::serialisers::SerialisedEntry&) {
|
||||
return f(KSerialiser::from_serialised(k_rep));
|
||||
};
|
||||
read_handle.foreach(g);
|
||||
|
@ -100,16 +100,16 @@ namespace kv
|
|||
}
|
||||
};
|
||||
|
||||
/** Grants write access to a @c kv::Set, as part of a @c kv::Tx.
|
||||
/** Grants write access to a @c ccf::kv::Set, as part of a @c ccf::kv::Tx.
|
||||
*/
|
||||
template <typename K, typename KSerialiser, typename Unit>
|
||||
class WriteableSetHandle
|
||||
{
|
||||
protected:
|
||||
kv::untyped::MapHandle& write_handle;
|
||||
ccf::kv::untyped::MapHandle& write_handle;
|
||||
|
||||
public:
|
||||
WriteableSetHandle(kv::untyped::MapHandle& uh) : write_handle(uh) {}
|
||||
WriteableSetHandle(ccf::kv::untyped::MapHandle& uh) : write_handle(uh) {}
|
||||
|
||||
/** Insert an element into this set.
|
||||
*
|
||||
|
@ -143,24 +143,26 @@ namespace kv
|
|||
}
|
||||
};
|
||||
|
||||
/** Grants read and write access to a @c kv::Set, as part of a @c kv::Tx.
|
||||
/** Grants read and write access to a @c ccf::kv::Set, as part of a @c
|
||||
* ccf::kv::Tx.
|
||||
*
|
||||
* @see kv::ReadableSetHandle
|
||||
* @see kv::WriteableSetHandle
|
||||
* @see ccf::kv::ReadableSetHandle
|
||||
* @see ccf::kv::WriteableSetHandle
|
||||
*/
|
||||
template <typename K, typename KSerialiser, typename Unit>
|
||||
class SetHandle : public kv::AbstractHandle,
|
||||
class SetHandle : public ccf::kv::AbstractHandle,
|
||||
public ReadableSetHandle<K, KSerialiser>,
|
||||
public WriteableSetHandle<K, KSerialiser, Unit>
|
||||
{
|
||||
protected:
|
||||
kv::untyped::MapHandle untyped_handle;
|
||||
ccf::kv::untyped::MapHandle untyped_handle;
|
||||
|
||||
using ReadableBase = ReadableSetHandle<K, KSerialiser>;
|
||||
using WriteableBase = WriteableSetHandle<K, KSerialiser, Unit>;
|
||||
|
||||
public:
|
||||
SetHandle(kv::untyped::ChangeSet& changes, const std::string& map_name) :
|
||||
SetHandle(
|
||||
ccf::kv::untyped::ChangeSet& changes, const std::string& map_name) :
|
||||
ReadableBase(untyped_handle),
|
||||
WriteableBase(untyped_handle),
|
||||
untyped_handle(changes, map_name)
|
||||
|
|
|
@ -4,23 +4,23 @@
|
|||
|
||||
#include "ccf/kv/serialisers/serialised_entry.h"
|
||||
|
||||
namespace kv::serialisers
|
||||
namespace ccf::kv::serialisers
|
||||
{
|
||||
// Unit serialisations are used as a utility type to convert kv::Maps to
|
||||
// kv::Maps and kv::Sets. Specifically, these are implemented as wrappers so
|
||||
// that kv::Value<T> is essentially kv::Map<Unit, T>, and kv::Set<T> is
|
||||
// kv::Map<T, Unit>.
|
||||
// This is used as a template parameter allowing the caller to specify what
|
||||
// value is inserted into the ledger.
|
||||
// Unit serialisations are used as a utility type to convert ccf::kv::Maps to
|
||||
// ccf::kv::Maps and ccf::kv::Sets. Specifically, these are implemented as
|
||||
// wrappers so that ccf::kv::Value<T> is essentially ccf::kv::Map<Unit, T>,
|
||||
// and ccf::kv::Set<T> is ccf::kv::Map<T, Unit>. This is used as a template
|
||||
// parameter allowing the caller to specify what value is inserted into the
|
||||
// ledger.
|
||||
|
||||
// This is the default UnitCreator, returning 8 null bytes for compatibility
|
||||
// with old ledgers (where Values were previously Maps with a single entry
|
||||
// at key 0, serialised as a uint64_t)
|
||||
struct ZeroBlitUnitCreator
|
||||
{
|
||||
static kv::serialisers::SerialisedEntry get()
|
||||
static ccf::kv::serialisers::SerialisedEntry get()
|
||||
{
|
||||
kv::serialisers::SerialisedEntry e;
|
||||
ccf::kv::serialisers::SerialisedEntry e;
|
||||
e.assign(sizeof(uint64_t), 0u);
|
||||
return e;
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ namespace kv::serialisers
|
|||
|
||||
struct EmptyUnitCreator
|
||||
{
|
||||
static kv::serialisers::SerialisedEntry get()
|
||||
static ccf::kv::serialisers::SerialisedEntry get()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -8,13 +8,13 @@
|
|||
#include <map>
|
||||
#include <optional>
|
||||
|
||||
namespace kv::untyped
|
||||
namespace ccf::kv::untyped
|
||||
{
|
||||
// nullopt values represent deletions
|
||||
using Write = std::map<
|
||||
kv::serialisers::SerialisedEntry,
|
||||
std::optional<kv::serialisers::SerialisedEntry>>;
|
||||
ccf::kv::serialisers::SerialisedEntry,
|
||||
std::optional<ccf::kv::serialisers::SerialisedEntry>>;
|
||||
|
||||
using CommitHook = kv::CommitHook<Write>;
|
||||
using MapHook = kv::MapHook<Write>;
|
||||
using CommitHook = ccf::kv::CommitHook<Write>;
|
||||
using MapHook = ccf::kv::MapHook<Write>;
|
||||
}
|
|
@ -11,15 +11,15 @@
|
|||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace kv::untyped
|
||||
namespace ccf::kv::untyped
|
||||
{
|
||||
struct ChangeSet;
|
||||
|
||||
class MapDiff : public kv::AbstractHandle
|
||||
class MapDiff : public ccf::kv::AbstractHandle
|
||||
{
|
||||
public:
|
||||
using KeyType = kv::serialisers::SerialisedEntry;
|
||||
using ValueType = kv::serialisers::SerialisedEntry;
|
||||
using KeyType = ccf::kv::serialisers::SerialisedEntry;
|
||||
using ValueType = ccf::kv::serialisers::SerialisedEntry;
|
||||
|
||||
using ElementVisitor =
|
||||
std::function<void(const KeyType& k, const std::optional<ValueType>& V)>;
|
||||
|
@ -28,13 +28,13 @@ namespace kv::untyped
|
|||
std::function<bool(const KeyType& k, const std::optional<ValueType>& V)>;
|
||||
|
||||
protected:
|
||||
kv::untyped::Write& writes;
|
||||
ccf::kv::untyped::Write& writes;
|
||||
std::string map_name;
|
||||
|
||||
void foreach_(const ElementVisitorWithEarlyOut& fn);
|
||||
|
||||
public:
|
||||
MapDiff(kv::untyped::ChangeSet& cs, const std::string& map_name);
|
||||
MapDiff(ccf::kv::untyped::ChangeSet& cs, const std::string& map_name);
|
||||
|
||||
std::optional<std::optional<ValueType>> get(const KeyType& key);
|
||||
|
||||
|
|
|
@ -10,17 +10,17 @@
|
|||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace kv::untyped
|
||||
namespace ccf::kv::untyped
|
||||
{
|
||||
struct ChangeSet;
|
||||
|
||||
class MapHandle : public kv::AbstractHandle
|
||||
class MapHandle : public ccf::kv::AbstractHandle
|
||||
{
|
||||
public:
|
||||
// Expose these types so that other code can use them as MyTx::KeyType or
|
||||
// MyMap::MapHandle::KeyType, templated on the MapHandle or Map type
|
||||
using KeyType = kv::serialisers::SerialisedEntry;
|
||||
using ValueType = kv::serialisers::SerialisedEntry;
|
||||
using KeyType = ccf::kv::serialisers::SerialisedEntry;
|
||||
using ValueType = ccf::kv::serialisers::SerialisedEntry;
|
||||
|
||||
using ElementVisitor =
|
||||
std::function<void(const KeyType& k, const ValueType& V)>;
|
||||
|
@ -29,7 +29,7 @@ namespace kv::untyped
|
|||
std::function<bool(const KeyType& k, const ValueType& V)>;
|
||||
|
||||
protected:
|
||||
kv::untyped::ChangeSet& tx_changes;
|
||||
ccf::kv::untyped::ChangeSet& tx_changes;
|
||||
std::string map_name;
|
||||
|
||||
/** Get pointer to current value if this key exists, else nullptr if it does
|
||||
|
@ -45,7 +45,7 @@ namespace kv::untyped
|
|||
const ElementVisitorWithEarlyOut& fn, bool always_consider_writes);
|
||||
|
||||
public:
|
||||
MapHandle(kv::untyped::ChangeSet& cs, const std::string& map_name);
|
||||
MapHandle(ccf::kv::untyped::ChangeSet& cs, const std::string& map_name);
|
||||
|
||||
std::string get_name_of_map() const;
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "ccf/kv/untyped.h"
|
||||
#include "ccf/kv/value_handle.h"
|
||||
|
||||
namespace kv
|
||||
namespace ccf::kv
|
||||
{
|
||||
/** Defines the schema of a single-valued type accessed by a @c ccf::Tx. This
|
||||
* value type is a container for an optional single element of type V. This
|
||||
|
@ -20,19 +20,20 @@ namespace kv
|
|||
* this V is serialised and deserialised, so it may be written to the ledger
|
||||
* and replicated by the consensus algorithm.
|
||||
*
|
||||
* This is implemented as a @c kv::Map from Unit to V, and the serialisation
|
||||
* of the unit key is overridable with the Unit template parameter.
|
||||
* This is implemented as a @c ccf::kv::Map from Unit to V, and the
|
||||
* serialisation of the unit key is overridable with the Unit template
|
||||
* parameter.
|
||||
*/
|
||||
template <
|
||||
typename V,
|
||||
typename VSerialiser,
|
||||
typename Unit = kv::serialisers::ZeroBlitUnitCreator>
|
||||
typename Unit = ccf::kv::serialisers::ZeroBlitUnitCreator>
|
||||
class TypedValue : public GetName
|
||||
{
|
||||
public:
|
||||
using ReadOnlyHandle = kv::ReadableValueHandle<V, VSerialiser, Unit>;
|
||||
using WriteOnlyHandle = kv::WriteableValueHandle<V, VSerialiser, Unit>;
|
||||
using Handle = kv::ValueHandle<V, VSerialiser, Unit>;
|
||||
using ReadOnlyHandle = ccf::kv::ReadableValueHandle<V, VSerialiser, Unit>;
|
||||
using WriteOnlyHandle = ccf::kv::WriteableValueHandle<V, VSerialiser, Unit>;
|
||||
using Handle = ccf::kv::ValueHandle<V, VSerialiser, Unit>;
|
||||
|
||||
using Write = std::optional<V>;
|
||||
using MapHook = MapHook<Write>;
|
||||
|
@ -43,13 +44,13 @@ namespace kv
|
|||
|
||||
using GetName::GetName;
|
||||
|
||||
static kv::serialisers::SerialisedEntry create_unit()
|
||||
static ccf::kv::serialisers::SerialisedEntry create_unit()
|
||||
{
|
||||
return Unit::get();
|
||||
}
|
||||
|
||||
private:
|
||||
static Write deserialise_write(const kv::untyped::Write& w)
|
||||
static Write deserialise_write(const ccf::kv::untyped::Write& w)
|
||||
{
|
||||
assert(w.size() == 1); // Value contains only one element
|
||||
const auto& value = w.begin()->second;
|
||||
|
@ -61,16 +62,16 @@ namespace kv
|
|||
}
|
||||
|
||||
public:
|
||||
static kv::untyped::CommitHook wrap_commit_hook(const CommitHook& hook)
|
||||
static ccf::kv::untyped::CommitHook wrap_commit_hook(const CommitHook& hook)
|
||||
{
|
||||
return [hook](Version v, const kv::untyped::Write& w) {
|
||||
return [hook](Version v, const ccf::kv::untyped::Write& w) {
|
||||
hook(v, deserialise_write(w));
|
||||
};
|
||||
}
|
||||
|
||||
static kv::untyped::MapHook wrap_map_hook(const MapHook& hook)
|
||||
static ccf::kv::untyped::MapHook wrap_map_hook(const MapHook& hook)
|
||||
{
|
||||
return [hook](Version v, const kv::untyped::Write& w) {
|
||||
return [hook](Version v, const ccf::kv::untyped::Write& w) {
|
||||
return hook(v, deserialise_write(w));
|
||||
};
|
||||
}
|
||||
|
@ -80,16 +81,16 @@ namespace kv
|
|||
typename V,
|
||||
template <typename>
|
||||
typename VSerialiser,
|
||||
typename Unit = kv::serialisers::ZeroBlitUnitCreator>
|
||||
typename Unit = ccf::kv::serialisers::ZeroBlitUnitCreator>
|
||||
using ValueSerialisedWith = TypedValue<V, VSerialiser<V>, Unit>;
|
||||
|
||||
template <typename V>
|
||||
using JsonSerialisedValue =
|
||||
ValueSerialisedWith<V, kv::serialisers::JsonSerialiser>;
|
||||
ValueSerialisedWith<V, ccf::kv::serialisers::JsonSerialiser>;
|
||||
|
||||
template <typename V>
|
||||
using RawCopySerialisedValue =
|
||||
TypedValue<V, kv::serialisers::BlitSerialiser<V>>;
|
||||
TypedValue<V, ccf::kv::serialisers::BlitSerialiser<V>>;
|
||||
|
||||
/** Short name for default-serialised values, using JSON serialisers. Support
|
||||
* for custom types can be added through the DECLARE_JSON... macros.
|
||||
|
|
|
@ -5,20 +5,20 @@
|
|||
#include "ccf/kv/unit.h"
|
||||
#include "ccf/kv/untyped_map_handle.h"
|
||||
|
||||
namespace kv
|
||||
namespace ccf::kv
|
||||
{
|
||||
/** Grants read access to a @c kv::Value, as part of a @c kv::Tx.
|
||||
/** Grants read access to a @c ccf::kv::Value, as part of a @c ccf::kv::Tx.
|
||||
*/
|
||||
template <typename V, typename VSerialiser, typename Unit>
|
||||
class ReadableValueHandle
|
||||
{
|
||||
protected:
|
||||
kv::untyped::MapHandle& read_handle;
|
||||
ccf::kv::untyped::MapHandle& read_handle;
|
||||
|
||||
public:
|
||||
using ValueType = V;
|
||||
|
||||
ReadableValueHandle(kv::untyped::MapHandle& uh) : read_handle(uh) {}
|
||||
ReadableValueHandle(ccf::kv::untyped::MapHandle& uh) : read_handle(uh) {}
|
||||
|
||||
/** Get the stored value.
|
||||
*
|
||||
|
@ -73,7 +73,7 @@ namespace kv
|
|||
/** Get version when this value was last written to, by a previous
|
||||
* transaction.
|
||||
*
|
||||
* @see kv::ReadableMapHandle::get_version_of_previous_write
|
||||
* @see ccf::kv::ReadableMapHandle::get_version_of_previous_write
|
||||
*
|
||||
* @return Optional containing version of applied transaction which last
|
||||
* wrote to this value, or nullopt if such a version does not exist
|
||||
|
@ -84,16 +84,16 @@ namespace kv
|
|||
}
|
||||
};
|
||||
|
||||
/** Grants write access to a @c kv::Value, as part of a @c kv::Tx.
|
||||
/** Grants write access to a @c ccf::kv::Value, as part of a @c ccf::kv::Tx.
|
||||
*/
|
||||
template <typename V, typename VSerialiser, typename Unit>
|
||||
class WriteableValueHandle
|
||||
{
|
||||
protected:
|
||||
kv::untyped::MapHandle& write_handle;
|
||||
ccf::kv::untyped::MapHandle& write_handle;
|
||||
|
||||
public:
|
||||
WriteableValueHandle(kv::untyped::MapHandle& uh) : write_handle(uh) {}
|
||||
WriteableValueHandle(ccf::kv::untyped::MapHandle& uh) : write_handle(uh) {}
|
||||
|
||||
/** Modify this value.
|
||||
*
|
||||
|
@ -116,10 +116,11 @@ namespace kv
|
|||
}
|
||||
};
|
||||
|
||||
/** Grants read and write access to a @c kv::Value, as part of a @c kv::Tx.
|
||||
/** Grants read and write access to a @c ccf::kv::Value, as part of a @c
|
||||
* ccf::kv::Tx.
|
||||
*
|
||||
* @see kv::ReadableValueHandle
|
||||
* @see kv::WriteableValueHandle
|
||||
* @see ccf::kv::ReadableValueHandle
|
||||
* @see ccf::kv::WriteableValueHandle
|
||||
*/
|
||||
template <typename V, typename VSerialiser, typename Unit>
|
||||
class ValueHandle : public AbstractHandle,
|
||||
|
@ -127,13 +128,14 @@ namespace kv
|
|||
public WriteableValueHandle<V, VSerialiser, Unit>
|
||||
{
|
||||
protected:
|
||||
kv::untyped::MapHandle untyped_handle;
|
||||
ccf::kv::untyped::MapHandle untyped_handle;
|
||||
|
||||
using ReadableBase = ReadableValueHandle<V, VSerialiser, Unit>;
|
||||
using WriteableBase = WriteableValueHandle<V, VSerialiser, Unit>;
|
||||
|
||||
public:
|
||||
ValueHandle(kv::untyped::ChangeSet& changes, const std::string& map_name) :
|
||||
ValueHandle(
|
||||
ccf::kv::untyped::ChangeSet& changes, const std::string& map_name) :
|
||||
ReadableBase(untyped_handle),
|
||||
WriteableBase(untyped_handle),
|
||||
untyped_handle(changes, map_name)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Licensed under the Apache 2.0 License.
|
||||
#pragma once
|
||||
|
||||
namespace kv
|
||||
namespace ccf::kv
|
||||
{
|
||||
// Version indexes modifications to the local kv store.
|
||||
using Version = uint64_t;
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace ccf
|
|||
static std::optional<HostData> get_host_data(const QuoteInfo& quote_info);
|
||||
|
||||
static QuoteVerificationResult verify_quote_against_store(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const QuoteInfo& quote_info,
|
||||
const std::vector<uint8_t>& expected_node_public_key_der,
|
||||
pal::PlatformAttestationMeasurement& measurement);
|
||||
|
|
|
@ -143,7 +143,7 @@ namespace ccf::pal
|
|||
DECLARE_JSON_REQUIRED_FIELDS(PlatformAttestationMeasurement, data);
|
||||
}
|
||||
|
||||
namespace kv::serialisers
|
||||
namespace ccf::kv::serialisers
|
||||
{
|
||||
template <size_t N>
|
||||
struct BlitSerialiser<ccf::pal::AttestationMeasurement<N>>
|
||||
|
|
|
@ -13,5 +13,5 @@ namespace ccfapp
|
|||
* @return an optional claims digest
|
||||
*/
|
||||
std::optional<ccf::ClaimsDigest::Digest> get_create_tx_claims_digest(
|
||||
kv::ReadOnlyTx& tx)
|
||||
ccf::kv::ReadOnlyTx& tx)
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ namespace ccf
|
|||
struct Essentials
|
||||
{
|
||||
ringbuffer::WriterPtr writer;
|
||||
std::shared_ptr<kv::ReadOnlyTx> tx;
|
||||
std::shared_ptr<ccf::kv::ReadOnlyTx> tx;
|
||||
std::shared_ptr<ccf::endpoints::ReadOnlyEndpointContext> ctx;
|
||||
};
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "ccf/crypto/pem.h"
|
||||
#include "ccf/kv/serialisers/blit_serialiser.h"
|
||||
|
||||
namespace kv::serialisers
|
||||
namespace ccf::kv::serialisers
|
||||
{
|
||||
template <>
|
||||
struct BlitSerialiser<ccf::crypto::Pem>
|
||||
|
|
|
@ -12,24 +12,24 @@ namespace ccf
|
|||
// - The raw key is trivially and cheaply deserialisable.
|
||||
// - The JSON value can conveniently be audited offline.
|
||||
// Note: Maps which include large values (e.g. certificate or serialised
|
||||
// Merkle tree) can use the `kv::RawCopySerialisedMap` type to maximise
|
||||
// Merkle tree) can use the `ccf::kv::RawCopySerialisedMap` type to maximise
|
||||
// performance.
|
||||
template <typename K, typename V>
|
||||
using ServiceMap = kv::MapSerialisedWith<
|
||||
using ServiceMap = ccf::kv::MapSerialisedWith<
|
||||
K,
|
||||
V,
|
||||
kv::serialisers::BlitSerialiser,
|
||||
kv::serialisers::JsonSerialiser>;
|
||||
ccf::kv::serialisers::BlitSerialiser,
|
||||
ccf::kv::serialisers::JsonSerialiser>;
|
||||
|
||||
template <typename V>
|
||||
using ServiceValue = kv::ValueSerialisedWith<
|
||||
using ServiceValue = ccf::kv::ValueSerialisedWith<
|
||||
V,
|
||||
kv::serialisers::JsonSerialiser,
|
||||
kv::serialisers::ZeroBlitUnitCreator>;
|
||||
ccf::kv::serialisers::JsonSerialiser,
|
||||
ccf::kv::serialisers::ZeroBlitUnitCreator>;
|
||||
|
||||
template <typename K>
|
||||
using ServiceSet = kv::SetSerialisedWith<
|
||||
using ServiceSet = ccf::kv::SetSerialisedWith<
|
||||
K,
|
||||
kv::serialisers::BlitSerialiser,
|
||||
kv::serialisers::ZeroBlitUnitCreator>;
|
||||
ccf::kv::serialisers::BlitSerialiser,
|
||||
ccf::kv::serialisers::ZeroBlitUnitCreator>;
|
||||
}
|
|
@ -37,7 +37,7 @@ namespace ccf
|
|||
|
||||
/** Set to the seqno of the latest ledger secret at the time the node is
|
||||
trusted */
|
||||
std::optional<kv::Version> ledger_secret_seqno = std::nullopt;
|
||||
std::optional<ccf::kv::Version> ledger_secret_seqno = std::nullopt;
|
||||
|
||||
/// Code identity for the node
|
||||
std::optional<std::string> code_digest = std::nullopt;
|
||||
|
|
|
@ -80,7 +80,7 @@ namespace ccf
|
|||
ProposalInfoSummary, votes, vote_failures, failure);
|
||||
|
||||
using ProposalMap =
|
||||
kv::RawCopySerialisedMap<ccf::ProposalId, std::vector<uint8_t>>;
|
||||
ccf::kv::RawCopySerialisedMap<ccf::ProposalId, std::vector<uint8_t>>;
|
||||
using ProposalInfoMap = ServiceMap<ccf::ProposalId, ProposalInfo>;
|
||||
|
||||
namespace Tables
|
||||
|
|
|
@ -86,9 +86,10 @@ namespace ccf
|
|||
static constexpr auto JWT_PUBLIC_SIGNING_KEY_ISSUER =
|
||||
"public:ccf.gov.jwt.public_signing_key_issuer";
|
||||
|
||||
using JwtPublicSigningKeys = kv::RawCopySerialisedMap<JwtKeyId, Cert>;
|
||||
using JwtPublicSigningKeys =
|
||||
ccf::kv::RawCopySerialisedMap<JwtKeyId, Cert>;
|
||||
using JwtPublicSigningKeyIssuer =
|
||||
kv::RawCopySerialisedMap<JwtKeyId, JwtIssuer>;
|
||||
ccf::kv::RawCopySerialisedMap<JwtKeyId, JwtIssuer>;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -76,9 +76,9 @@ namespace ccf
|
|||
|
||||
using MemberInfo = ServiceMap<MemberId, MemberDetails>;
|
||||
|
||||
using MemberCerts = kv::RawCopySerialisedMap<MemberId, ccf::crypto::Pem>;
|
||||
using MemberCerts = ccf::kv::RawCopySerialisedMap<MemberId, ccf::crypto::Pem>;
|
||||
using MemberPublicEncryptionKeys =
|
||||
kv::RawCopySerialisedMap<MemberId, ccf::crypto::Pem>;
|
||||
ccf::kv::RawCopySerialisedMap<MemberId, ccf::crypto::Pem>;
|
||||
|
||||
namespace Tables
|
||||
{
|
||||
|
|
|
@ -12,10 +12,10 @@
|
|||
namespace ccf
|
||||
{
|
||||
using Module = std::string;
|
||||
using Modules = kv::RawCopySerialisedMap<std::string, Module>;
|
||||
using Modules = ccf::kv::RawCopySerialisedMap<std::string, Module>;
|
||||
using ModulesQuickJsBytecode =
|
||||
kv::RawCopySerialisedMap<std::string, std::vector<uint8_t>>;
|
||||
using ModulesQuickJsVersion = kv::RawCopySerialisedValue<std::string>;
|
||||
ccf::kv::RawCopySerialisedMap<std::string, std::vector<uint8_t>>;
|
||||
using ModulesQuickJsVersion = ccf::kv::RawCopySerialisedValue<std::string>;
|
||||
using InterpreterFlush = ServiceValue<bool>;
|
||||
|
||||
namespace Tables
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace ccf
|
|||
{
|
||||
using Nodes = ServiceMap<NodeId, NodeInfo>;
|
||||
using NodeEndorsedCertificates =
|
||||
kv::RawCopySerialisedMap<NodeId, ccf::crypto::Pem>;
|
||||
ccf::kv::RawCopySerialisedMap<NodeId, ccf::crypto::Pem>;
|
||||
|
||||
namespace Tables
|
||||
{
|
||||
|
|
|
@ -31,7 +31,8 @@ namespace ccf
|
|||
/// Status of the service
|
||||
ServiceStatus status = ServiceStatus::OPENING;
|
||||
/// Version (seqno) of previous service identity (before the last recovery)
|
||||
std::optional<kv::Version> previous_service_identity_version = std::nullopt;
|
||||
std::optional<ccf::kv::Version> previous_service_identity_version =
|
||||
std::nullopt;
|
||||
/// Number of disaster recoveries performed on this service
|
||||
std::optional<size_t> recovery_count = std::nullopt;
|
||||
/// Free-form user data, can be used by members to store additional
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace ccf
|
|||
DECLARE_JSON_TYPE(UserDetails)
|
||||
DECLARE_JSON_REQUIRED_FIELDS(UserDetails, user_data)
|
||||
|
||||
using UserCerts = kv::RawCopySerialisedMap<UserId, ccf::crypto::Pem>;
|
||||
using UserCerts = ccf::kv::RawCopySerialisedMap<UserId, ccf::crypto::Pem>;
|
||||
using UserInfo = ServiceMap<UserId, UserDetails>;
|
||||
|
||||
namespace Tables
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace kv
|
||||
namespace ccf::kv
|
||||
{
|
||||
class AbstractHandle;
|
||||
class AbstractMap;
|
||||
|
@ -196,7 +196,7 @@ namespace kv
|
|||
* type-safety, prefer restricted handles returned by @c ro or @c wo where
|
||||
* possible, rather than the general @c rw.
|
||||
*
|
||||
* @see kv::ReadOnlyTx
|
||||
* @see ccf::kv::ReadOnlyTx
|
||||
*/
|
||||
class Tx : public ReadOnlyTx
|
||||
{
|
||||
|
|
|
@ -18,7 +18,7 @@ using namespace nlohmann;
|
|||
|
||||
namespace basicapp
|
||||
{
|
||||
using RecordsMap = kv::Map<string, std::vector<uint8_t>>;
|
||||
using RecordsMap = ccf::kv::Map<string, std::vector<uint8_t>>;
|
||||
static constexpr auto PRIVATE_RECORDS = "records";
|
||||
|
||||
class BasicHandlers : public ccf::UserEndpointRegistry
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
namespace ccfapp
|
||||
{
|
||||
std::optional<ccf::ClaimsDigest::Digest> get_create_tx_claims_digest(
|
||||
kv::ReadOnlyTx& tx)
|
||||
ccf::kv::ReadOnlyTx& tx)
|
||||
{
|
||||
auto constitution =
|
||||
tx.ro<ccf::Constitution>(ccf::Tables::CONSTITUTION)->get();
|
||||
|
|
|
@ -28,7 +28,7 @@ using namespace nlohmann;
|
|||
namespace loggingapp
|
||||
{
|
||||
// SNIPPET: table_definition
|
||||
using RecordsMap = kv::Map<size_t, string>;
|
||||
using RecordsMap = ccf::kv::Map<size_t, string>;
|
||||
static constexpr auto PUBLIC_RECORDS = "public:records";
|
||||
static constexpr auto PRIVATE_RECORDS = "records";
|
||||
|
||||
|
@ -71,7 +71,7 @@ namespace loggingapp
|
|||
{
|
||||
public:
|
||||
std::unique_ptr<ccf::AuthnIdentity> authenticate(
|
||||
kv::ReadOnlyTx&,
|
||||
ccf::kv::ReadOnlyTx&,
|
||||
const std::shared_ptr<ccf::RpcContext>& ctx,
|
||||
std::string& error_reason) override
|
||||
{
|
||||
|
@ -169,7 +169,7 @@ namespace loggingapp
|
|||
{}
|
||||
|
||||
void handle_committed_transaction(
|
||||
const ccf::TxID& tx_id, const kv::ReadOnlyStorePtr& store)
|
||||
const ccf::TxID& tx_id, const ccf::kv::ReadOnlyStorePtr& store)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(txid_lock);
|
||||
auto tx_diff = store->create_tx_diff();
|
||||
|
@ -1571,7 +1571,7 @@ namespace loggingapp
|
|||
// Fetch the requested range
|
||||
auto& historical_cache = context.get_historical_state();
|
||||
|
||||
std::vector<kv::ReadOnlyStorePtr> stores;
|
||||
std::vector<ccf::kv::ReadOnlyStorePtr> stores;
|
||||
if (!interesting_seqnos->empty())
|
||||
{
|
||||
stores =
|
||||
|
|
|
@ -19,7 +19,7 @@ using namespace nlohmann;
|
|||
|
||||
namespace programmabilityapp
|
||||
{
|
||||
using RecordsMap = kv::Map<std::string, std::vector<uint8_t>>;
|
||||
using RecordsMap = ccf::kv::Map<std::string, std::vector<uint8_t>>;
|
||||
static constexpr auto PRIVATE_RECORDS = "programmability.records";
|
||||
static constexpr auto CUSTOM_ENDPOINTS_NAMESPACE = "public:custom_endpoints";
|
||||
|
||||
|
@ -43,9 +43,11 @@ namespace programmabilityapp
|
|||
// This is a pure helper function which can be called from either C++ or JS,
|
||||
// to implement common functionality in a single place
|
||||
static inline bool has_role_permitting_action(
|
||||
kv::ReadOnlyTx& tx, const std::string& user_id, const std::string& action)
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const std::string& user_id,
|
||||
const std::string& action)
|
||||
{
|
||||
using RoleSet = kv::Set<std::string>;
|
||||
using RoleSet = ccf::kv::Set<std::string>;
|
||||
|
||||
auto users_handle = tx.ro<ccf::UserInfo>(ccf::Tables::USER_INFO);
|
||||
const auto user_info = users_handle->get(user_id);
|
||||
|
@ -77,9 +79,9 @@ namespace programmabilityapp
|
|||
// this extension object.
|
||||
// In this case, since the extension adds a function that wants to read from
|
||||
// the KV, it needs the current request's Tx.
|
||||
kv::ReadOnlyTx* tx;
|
||||
ccf::kv::ReadOnlyTx* tx;
|
||||
|
||||
MyExtension(kv::ReadOnlyTx* t) : tx(t) {}
|
||||
MyExtension(ccf::kv::ReadOnlyTx* t) : tx(t) {}
|
||||
|
||||
void install(ccf::js::core::Context& ctx) override;
|
||||
};
|
||||
|
@ -113,7 +115,7 @@ namespace programmabilityapp
|
|||
return JS_ThrowInternalError(ctx, "No transaction available");
|
||||
}
|
||||
|
||||
kv::ReadOnlyTx& tx = *tx_ptr;
|
||||
ccf::kv::ReadOnlyTx& tx = *tx_ptr;
|
||||
|
||||
// Process the arguments passed to the JS function, confirming they're both
|
||||
// strings
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
namespace ccfapp
|
||||
{
|
||||
using namespace std;
|
||||
using namespace kv;
|
||||
using namespace ccf::kv;
|
||||
using namespace ccf;
|
||||
|
||||
class JSHandlers : public UserEndpointRegistry
|
||||
|
@ -592,7 +592,7 @@ namespace ccfapp
|
|||
}
|
||||
|
||||
ccf::endpoints::EndpointDefinitionPtr find_endpoint(
|
||||
kv::Tx& tx, ccf::RpcContext& rpc_ctx) override
|
||||
ccf::kv::Tx& tx, ccf::RpcContext& rpc_ctx) override
|
||||
{
|
||||
const auto method = rpc_ctx.get_method();
|
||||
const auto verb = rpc_ctx.get_request_verb();
|
||||
|
@ -685,7 +685,7 @@ namespace ccfapp
|
|||
}
|
||||
|
||||
std::set<RESTVerb> get_allowed_verbs(
|
||||
kv::Tx& tx, const ccf::RpcContext& rpc_ctx) override
|
||||
ccf::kv::Tx& tx, const ccf::RpcContext& rpc_ctx) override
|
||||
{
|
||||
const auto method = rpc_ctx.get_method();
|
||||
|
||||
|
@ -751,7 +751,7 @@ namespace ccfapp
|
|||
|
||||
// Since we do our own dispatch within the default handler, report the
|
||||
// supported methods here
|
||||
void build_api(nlohmann::json& document, kv::ReadOnlyTx& tx) override
|
||||
void build_api(nlohmann::json& document, ccf::kv::ReadOnlyTx& tx) override
|
||||
{
|
||||
UserEndpointRegistry::build_api(document, tx);
|
||||
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
namespace tpcc
|
||||
{
|
||||
template <typename T>
|
||||
kv::serialisers::SerialisedEntry tpcc_serialise(const T& t);
|
||||
ccf::kv::serialisers::SerialisedEntry tpcc_serialise(const T& t);
|
||||
|
||||
template <typename T>
|
||||
T tpcc_deserialise(const kv::serialisers::SerialisedEntry& rep);
|
||||
T tpcc_deserialise(const ccf::kv::serialisers::SerialisedEntry& rep);
|
||||
|
||||
template <typename T>
|
||||
constexpr size_t serialised_size()
|
||||
|
@ -106,9 +106,9 @@ namespace tpcc
|
|||
_Pragma("clang diagnostic push"); \
|
||||
_Pragma("clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\""); \
|
||||
template <> \
|
||||
kv::serialisers::SerialisedEntry tpcc_serialise(const TYPE& t) \
|
||||
ccf::kv::serialisers::SerialisedEntry tpcc_serialise(const TYPE& t) \
|
||||
{ \
|
||||
kv::serialisers::SerialisedEntry rep; \
|
||||
ccf::kv::serialisers::SerialisedEntry rep; \
|
||||
constexpr size_t required_size = 0 _FOR_JSON_COUNT_NN(__VA_ARGS__)(POP1)( \
|
||||
ADD_SERIALIZED_SIZE, TYPE, ##__VA_ARGS__); \
|
||||
rep.resize(required_size); \
|
||||
|
@ -118,7 +118,7 @@ namespace tpcc
|
|||
return rep; \
|
||||
} \
|
||||
template <> \
|
||||
TYPE tpcc_deserialise(const kv::serialisers::SerialisedEntry& rep) \
|
||||
TYPE tpcc_deserialise(const ccf::kv::serialisers::SerialisedEntry& rep) \
|
||||
{ \
|
||||
auto data = rep.data(); \
|
||||
auto size = rep.size(); \
|
||||
|
@ -132,12 +132,12 @@ namespace tpcc
|
|||
template <typename T>
|
||||
struct TpccSerialiser
|
||||
{
|
||||
static kv::serialisers::SerialisedEntry to_serialised(const T& t)
|
||||
static ccf::kv::serialisers::SerialisedEntry to_serialised(const T& t)
|
||||
{
|
||||
return tpcc_serialise(t);
|
||||
}
|
||||
|
||||
static T from_serialised(const kv::serialisers::SerialisedEntry& rep)
|
||||
static T from_serialised(const ccf::kv::serialisers::SerialisedEntry& rep)
|
||||
{
|
||||
return tpcc_deserialise<T>(rep);
|
||||
}
|
||||
|
@ -539,7 +539,7 @@ namespace tpcc
|
|||
History, c_id, c_d_id, c_w_id, d_id, w_id, amount, date, data);
|
||||
|
||||
template <typename K, typename V>
|
||||
using TpccMap = kv::MapSerialisedWith<K, V, TpccSerialiser>;
|
||||
using TpccMap = ccf::kv::MapSerialisedWith<K, V, TpccSerialiser>;
|
||||
|
||||
struct TpccTables
|
||||
{
|
||||
|
|
|
@ -19,12 +19,12 @@ namespace aft
|
|||
class ViewHistory
|
||||
{
|
||||
// Entry i stores the first version in view i+1
|
||||
std::vector<kv::Version> views;
|
||||
std::vector<ccf::kv::Version> views;
|
||||
|
||||
public:
|
||||
static constexpr ccf::View InvalidView = ccf::VIEW_UNKNOWN;
|
||||
|
||||
void initialise(const std::vector<kv::Version>& terms_)
|
||||
void initialise(const std::vector<ccf::kv::Version>& terms_)
|
||||
{
|
||||
views.clear();
|
||||
for (size_t i = 0; i < terms_.size(); ++i)
|
||||
|
@ -34,7 +34,7 @@ namespace aft
|
|||
LOG_DEBUG_FMT("Initialised views: {}", fmt::join(views, ", "));
|
||||
}
|
||||
|
||||
void update(kv::Version idx, ccf::View view)
|
||||
void update(ccf::kv::Version idx, ccf::View view)
|
||||
{
|
||||
LOG_DEBUG_FMT("Updating view to: {} at version: {}", view, idx);
|
||||
if (!views.empty())
|
||||
|
@ -56,7 +56,7 @@ namespace aft
|
|||
LOG_DEBUG_FMT("Resulting views: {}", fmt::join(views, ", "));
|
||||
}
|
||||
|
||||
ccf::View view_at(kv::Version idx)
|
||||
ccf::View view_at(ccf::kv::Version idx)
|
||||
{
|
||||
auto it = upper_bound(views.begin(), views.end(), idx);
|
||||
|
||||
|
@ -69,11 +69,11 @@ namespace aft
|
|||
return (it - views.begin());
|
||||
}
|
||||
|
||||
kv::Version start_of_view(ccf::View view)
|
||||
ccf::kv::Version start_of_view(ccf::View view)
|
||||
{
|
||||
if (view > views.size() || view == InvalidView)
|
||||
{
|
||||
return kv::NoVersion;
|
||||
return ccf::kv::NoVersion;
|
||||
}
|
||||
|
||||
// NB: If views == {5, 10, 10}, then view 2 doesn't start at 10. View 2
|
||||
|
@ -81,23 +81,23 @@ namespace aft
|
|||
const auto tentative = views[view - 1];
|
||||
if (view + 1 <= views.size() && views[view] == tentative)
|
||||
{
|
||||
return kv::NoVersion;
|
||||
return ccf::kv::NoVersion;
|
||||
}
|
||||
return tentative;
|
||||
}
|
||||
|
||||
kv::Version end_of_view(ccf::View view)
|
||||
ccf::kv::Version end_of_view(ccf::View view)
|
||||
{
|
||||
// If this view has no start (potentially because it contains no
|
||||
// transactions), then it can't have an end
|
||||
if (start_of_view(view) == kv::NoVersion)
|
||||
if (start_of_view(view) == ccf::kv::NoVersion)
|
||||
{
|
||||
return kv::NoVersion;
|
||||
return ccf::kv::NoVersion;
|
||||
}
|
||||
|
||||
if (view >= views.size() || view == InvalidView)
|
||||
{
|
||||
return kv::NoVersion;
|
||||
return ccf::kv::NoVersion;
|
||||
}
|
||||
|
||||
// Otherwise the end of this view is the transaction before (- 1) the
|
||||
|
@ -105,14 +105,14 @@ namespace aft
|
|||
return views[view] - 1;
|
||||
}
|
||||
|
||||
std::vector<kv::Version> get_history_until(
|
||||
kv::Version idx = std::numeric_limits<kv::Version>::max())
|
||||
std::vector<ccf::kv::Version> get_history_until(
|
||||
ccf::kv::Version idx = std::numeric_limits<ccf::kv::Version>::max())
|
||||
{
|
||||
return {views.begin(), std::upper_bound(views.begin(), views.end(), idx)};
|
||||
}
|
||||
|
||||
// view should be non-zero as views start at one in here
|
||||
std::vector<kv::Version> get_history_since(uint64_t view)
|
||||
std::vector<ccf::kv::Version> get_history_since(uint64_t view)
|
||||
{
|
||||
if (view > views.size())
|
||||
{
|
||||
|
@ -121,7 +121,7 @@ namespace aft
|
|||
return {views.begin() + view - 1, views.end()};
|
||||
}
|
||||
|
||||
void rollback(kv::Version idx)
|
||||
void rollback(ccf::kv::Version idx)
|
||||
{
|
||||
auto it = upper_bound(views.begin(), views.end(), idx);
|
||||
views.erase(it, views.end());
|
||||
|
@ -157,8 +157,8 @@ namespace aft
|
|||
|
||||
ccf::NodeId node_id;
|
||||
ccf::View current_view = 0;
|
||||
kv::Version last_idx = 0;
|
||||
kv::Version commit_idx = 0;
|
||||
ccf::kv::Version last_idx = 0;
|
||||
ccf::kv::Version commit_idx = 0;
|
||||
ViewHistory view_history;
|
||||
|
||||
// Indices that are eligible for global commit, from a Node's perspective
|
||||
|
@ -176,10 +176,11 @@ namespace aft
|
|||
// the node
|
||||
// Leader -> Follower, when receiving entries for a newer term
|
||||
// Candidate -> Follower, when receiving entries for a newer term
|
||||
kv::LeadershipState leadership_state = kv::LeadershipState::None;
|
||||
kv::MembershipState membership_state = kv::MembershipState::Active;
|
||||
ccf::kv::LeadershipState leadership_state = ccf::kv::LeadershipState::None;
|
||||
ccf::kv::MembershipState membership_state =
|
||||
ccf::kv::MembershipState::Active;
|
||||
|
||||
std::optional<kv::RetirementPhase> retirement_phase = std::nullopt;
|
||||
std::optional<ccf::kv::RetirementPhase> retirement_phase = std::nullopt;
|
||||
// Index at which this node observes its retirement
|
||||
std::optional<ccf::SeqNo> retirement_idx = std::nullopt;
|
||||
// Earliest index at which this node's retirement can be committed
|
||||
|
|
|
@ -89,10 +89,10 @@ static inline void add_committable_indices_start_and_end(
|
|||
|
||||
namespace aft
|
||||
{
|
||||
using Configuration = kv::Configuration;
|
||||
using Configuration = ccf::kv::Configuration;
|
||||
|
||||
template <class LedgerProxy>
|
||||
class Aft : public kv::Consensus
|
||||
class Aft : public ccf::kv::Consensus
|
||||
{
|
||||
private:
|
||||
struct NodeState
|
||||
|
@ -216,8 +216,8 @@ namespace aft
|
|||
std::shared_ptr<aft::State> state_,
|
||||
std::shared_ptr<ccf::NodeClient> rpc_request_context_,
|
||||
bool public_only_ = false,
|
||||
kv::MembershipState initial_membership_state_ =
|
||||
kv::MembershipState::Active,
|
||||
ccf::kv::MembershipState initial_membership_state_ =
|
||||
ccf::kv::MembershipState::Active,
|
||||
ReconfigurationType reconfiguration_type_ =
|
||||
ReconfigurationType::ONE_TRANSACTION) :
|
||||
store(std::move(store_)),
|
||||
|
@ -258,12 +258,12 @@ namespace aft
|
|||
|
||||
bool is_primary() override
|
||||
{
|
||||
return state->leadership_state == kv::LeadershipState::Leader;
|
||||
return state->leadership_state == ccf::kv::LeadershipState::Leader;
|
||||
}
|
||||
|
||||
bool is_candidate() override
|
||||
{
|
||||
return state->leadership_state == kv::LeadershipState::Candidate;
|
||||
return state->leadership_state == ccf::kv::LeadershipState::Candidate;
|
||||
}
|
||||
|
||||
bool can_replicate() override
|
||||
|
@ -284,7 +284,7 @@ namespace aft
|
|||
return false;
|
||||
}
|
||||
std::unique_lock<ccf::pal::Mutex> guard(state->lock);
|
||||
return state->leadership_state == kv::LeadershipState::Leader &&
|
||||
return state->leadership_state == ccf::kv::LeadershipState::Leader &&
|
||||
(state->last_idx - state->commit_idx >= max_uncommitted_tx_count);
|
||||
}
|
||||
|
||||
|
@ -310,46 +310,46 @@ namespace aft
|
|||
|
||||
bool is_backup() override
|
||||
{
|
||||
return state->leadership_state == kv::LeadershipState::Follower;
|
||||
return state->leadership_state == ccf::kv::LeadershipState::Follower;
|
||||
}
|
||||
|
||||
bool is_active() const
|
||||
{
|
||||
return state->membership_state == kv::MembershipState::Active;
|
||||
return state->membership_state == ccf::kv::MembershipState::Active;
|
||||
}
|
||||
|
||||
bool is_retired() const
|
||||
{
|
||||
return state->membership_state == kv::MembershipState::Retired;
|
||||
return state->membership_state == ccf::kv::MembershipState::Retired;
|
||||
}
|
||||
|
||||
bool is_retired_committed() const
|
||||
{
|
||||
return state->membership_state == kv::MembershipState::Retired &&
|
||||
state->retirement_phase == kv::RetirementPhase::RetiredCommitted;
|
||||
return state->membership_state == ccf::kv::MembershipState::Retired &&
|
||||
state->retirement_phase == ccf::kv::RetirementPhase::RetiredCommitted;
|
||||
}
|
||||
|
||||
bool is_retired_completed() const
|
||||
{
|
||||
return state->membership_state == kv::MembershipState::Retired &&
|
||||
state->retirement_phase == kv::RetirementPhase::Completed;
|
||||
return state->membership_state == ccf::kv::MembershipState::Retired &&
|
||||
state->retirement_phase == ccf::kv::RetirementPhase::Completed;
|
||||
}
|
||||
|
||||
void set_retired_committed(
|
||||
ccf::SeqNo seqno, const std::vector<kv::NodeId>& node_ids) override
|
||||
ccf::SeqNo seqno, const std::vector<ccf::kv::NodeId>& node_ids) override
|
||||
{
|
||||
for (auto& node_id : node_ids)
|
||||
{
|
||||
if (id() == node_id)
|
||||
{
|
||||
CCF_ASSERT(
|
||||
state->membership_state == kv::MembershipState::Retired,
|
||||
state->membership_state == ccf::kv::MembershipState::Retired,
|
||||
"Node is not retired, cannot become retired committed");
|
||||
CCF_ASSERT(
|
||||
state->retirement_phase == kv::RetirementPhase::Completed,
|
||||
state->retirement_phase == ccf::kv::RetirementPhase::Completed,
|
||||
"Node is not retired, cannot become retired committed");
|
||||
state->retired_committed_idx = seqno;
|
||||
become_retired(seqno, kv::RetirementPhase::RetiredCommitted);
|
||||
become_retired(seqno, ccf::kv::RetirementPhase::RetiredCommitted);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -531,7 +531,7 @@ namespace aft
|
|||
public:
|
||||
void add_configuration(
|
||||
Index idx,
|
||||
const kv::Configuration::Nodes& conf,
|
||||
const ccf::kv::Configuration::Nodes& conf,
|
||||
const std::unordered_set<ccf::NodeId>& new_learner_nodes = {},
|
||||
const std::unordered_set<ccf::NodeId>& new_retired_nodes = {}) override
|
||||
{
|
||||
|
@ -561,7 +561,7 @@ namespace aft
|
|||
configurations.back().nodes.end() &&
|
||||
conf.find(state->node_id) == conf.end())
|
||||
{
|
||||
become_retired(idx, kv::RetirementPhase::Ordered);
|
||||
become_retired(idx, ccf::kv::RetirementPhase::Ordered);
|
||||
}
|
||||
|
||||
if (conf != configurations.back().nodes)
|
||||
|
@ -606,9 +606,9 @@ namespace aft
|
|||
return get_latest_configuration_unsafe();
|
||||
}
|
||||
|
||||
kv::ConsensusDetails get_details() override
|
||||
ccf::kv::ConsensusDetails get_details() override
|
||||
{
|
||||
kv::ConsensusDetails details;
|
||||
ccf::kv::ConsensusDetails details;
|
||||
std::lock_guard<ccf::pal::Mutex> guard(state->lock);
|
||||
details.primary_id = leader_id;
|
||||
details.current_view = state->current_view;
|
||||
|
@ -632,11 +632,11 @@ namespace aft
|
|||
return details;
|
||||
}
|
||||
|
||||
bool replicate(const kv::BatchVector& entries, Term term) override
|
||||
bool replicate(const ccf::kv::BatchVector& entries, Term term) override
|
||||
{
|
||||
std::lock_guard<ccf::pal::Mutex> guard(state->lock);
|
||||
|
||||
if (state->leadership_state != kv::LeadershipState::Leader)
|
||||
if (state->leadership_state != ccf::kv::LeadershipState::Leader)
|
||||
{
|
||||
RAFT_DEBUG_FMT(
|
||||
"Failed to replicate {} items: not leader", entries.size());
|
||||
|
@ -702,10 +702,10 @@ namespace aft
|
|||
state->membership_state,
|
||||
state->leadership_state);
|
||||
if (
|
||||
state->membership_state == kv::MembershipState::Retired &&
|
||||
state->retirement_phase == kv::RetirementPhase::Ordered)
|
||||
state->membership_state == ccf::kv::MembershipState::Retired &&
|
||||
state->retirement_phase == ccf::kv::RetirementPhase::Ordered)
|
||||
{
|
||||
become_retired(index, kv::RetirementPhase::Signed);
|
||||
become_retired(index, ccf::kv::RetirementPhase::Signed);
|
||||
}
|
||||
state->committable_indices.push_back(index);
|
||||
start_ticking_if_necessary();
|
||||
|
@ -825,7 +825,7 @@ namespace aft
|
|||
std::unique_lock<ccf::pal::Mutex> guard(state->lock);
|
||||
timeout_elapsed += elapsed;
|
||||
|
||||
if (state->leadership_state == kv::LeadershipState::Leader)
|
||||
if (state->leadership_state == ccf::kv::LeadershipState::Leader)
|
||||
{
|
||||
if (timeout_elapsed >= request_timeout)
|
||||
{
|
||||
|
@ -962,13 +962,13 @@ namespace aft
|
|||
|
||||
bool can_replicate_unsafe()
|
||||
{
|
||||
return state->leadership_state == kv::LeadershipState::Leader &&
|
||||
return state->leadership_state == ccf::kv::LeadershipState::Leader &&
|
||||
!is_retired_committed();
|
||||
}
|
||||
|
||||
bool can_sign_unsafe()
|
||||
{
|
||||
return state->leadership_state == kv::LeadershipState::Leader &&
|
||||
return state->leadership_state == ccf::kv::LeadershipState::Leader &&
|
||||
!is_retired_committed();
|
||||
}
|
||||
|
||||
|
@ -998,7 +998,7 @@ namespace aft
|
|||
const auto term_of_ae = state->view_history.view_at(start);
|
||||
const auto index_at_end_of_term =
|
||||
state->view_history.end_of_view(term_of_ae);
|
||||
if (index_at_end_of_term != kv::NoVersion)
|
||||
if (index_at_end_of_term != ccf::kv::NoVersion)
|
||||
{
|
||||
max_idx = index_at_end_of_term;
|
||||
}
|
||||
|
@ -1116,7 +1116,7 @@ namespace aft
|
|||
// follower if necessary
|
||||
if (
|
||||
state->current_view == r.term &&
|
||||
state->leadership_state == kv::LeadershipState::Candidate)
|
||||
state->leadership_state == ccf::kv::LeadershipState::Candidate)
|
||||
{
|
||||
become_aware_of_new_term(r.term);
|
||||
}
|
||||
|
@ -1216,8 +1216,9 @@ namespace aft
|
|||
r.idx,
|
||||
r.prev_idx);
|
||||
|
||||
std::vector<
|
||||
std::tuple<std::unique_ptr<kv::AbstractExecutionWrapper>, kv::Version>>
|
||||
std::vector<std::tuple<
|
||||
std::unique_ptr<ccf::kv::AbstractExecutionWrapper>,
|
||||
ccf::kv::Version>>
|
||||
append_entries;
|
||||
// Finally, deserialise each entry in the batch
|
||||
for (Index i = r.prev_idx + 1; i <= r.idx; i++)
|
||||
|
@ -1299,7 +1300,7 @@ namespace aft
|
|||
return;
|
||||
}
|
||||
|
||||
kv::TxID expected{r.term_of_idx, i};
|
||||
ccf::kv::TxID expected{r.term_of_idx, i};
|
||||
auto ds = store->deserialize(entry, public_only, expected);
|
||||
if (ds == nullptr)
|
||||
{
|
||||
|
@ -1321,8 +1322,8 @@ namespace aft
|
|||
|
||||
void execute_append_entries_sync(
|
||||
std::vector<std::tuple<
|
||||
std::unique_ptr<kv::AbstractExecutionWrapper>,
|
||||
kv::Version>>&& append_entries,
|
||||
std::unique_ptr<ccf::kv::AbstractExecutionWrapper>,
|
||||
ccf::kv::Version>>&& append_entries,
|
||||
const ccf::NodeId& from,
|
||||
AppendEntries&& r)
|
||||
{
|
||||
|
@ -1341,9 +1342,9 @@ namespace aft
|
|||
#endif
|
||||
|
||||
bool track_deletes_on_missing_keys = false;
|
||||
kv::ApplyResult apply_success =
|
||||
ccf::kv::ApplyResult apply_success =
|
||||
ds->apply(track_deletes_on_missing_keys);
|
||||
if (apply_success == kv::ApplyResult::FAIL)
|
||||
if (apply_success == ccf::kv::ApplyResult::FAIL)
|
||||
{
|
||||
ledger->truncate(i - 1);
|
||||
send_append_entries_response_nack(from);
|
||||
|
@ -1357,7 +1358,7 @@ namespace aft
|
|||
}
|
||||
|
||||
bool globally_committable =
|
||||
(apply_success == kv::ApplyResult::PASS_SIGNATURE);
|
||||
(apply_success == ccf::kv::ApplyResult::PASS_SIGNATURE);
|
||||
if (globally_committable)
|
||||
{
|
||||
start_ticking_if_necessary();
|
||||
|
@ -1370,7 +1371,7 @@ namespace aft
|
|||
|
||||
switch (apply_success)
|
||||
{
|
||||
case kv::ApplyResult::FAIL:
|
||||
case ccf::kv::ApplyResult::FAIL:
|
||||
{
|
||||
RAFT_FAIL_FMT("Follower failed to apply log entry: {}", i);
|
||||
state->last_idx--;
|
||||
|
@ -1379,14 +1380,14 @@ namespace aft
|
|||
break;
|
||||
}
|
||||
|
||||
case kv::ApplyResult::PASS_SIGNATURE:
|
||||
case ccf::kv::ApplyResult::PASS_SIGNATURE:
|
||||
{
|
||||
RAFT_DEBUG_FMT("Deserialising signature at {}", i);
|
||||
if (
|
||||
state->membership_state == kv::MembershipState::Retired &&
|
||||
state->retirement_phase == kv::RetirementPhase::Ordered)
|
||||
state->membership_state == ccf::kv::MembershipState::Retired &&
|
||||
state->retirement_phase == ccf::kv::RetirementPhase::Ordered)
|
||||
{
|
||||
become_retired(i, kv::RetirementPhase::Signed);
|
||||
become_retired(i, ccf::kv::RetirementPhase::Signed);
|
||||
}
|
||||
state->committable_indices.push_back(i);
|
||||
|
||||
|
@ -1416,12 +1417,12 @@ namespace aft
|
|||
break;
|
||||
}
|
||||
|
||||
case kv::ApplyResult::PASS:
|
||||
case ccf::kv::ApplyResult::PASS:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case kv::ApplyResult::PASS_ENCRYPTED_PAST_LEDGER_SECRET:
|
||||
case ccf::kv::ApplyResult::PASS_ENCRYPTED_PAST_LEDGER_SECRET:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -1560,7 +1561,7 @@ namespace aft
|
|||
#endif
|
||||
|
||||
// Ignore if we're not the leader.
|
||||
if (state->leadership_state != kv::LeadershipState::Leader)
|
||||
if (state->leadership_state != ccf::kv::LeadershipState::Leader)
|
||||
{
|
||||
RAFT_FAIL_FMT(
|
||||
"Recv append entries response to {} from {}: no longer leader",
|
||||
|
@ -1811,7 +1812,7 @@ namespace aft
|
|||
RAFT_TRACE_JSON_OUT(j);
|
||||
#endif
|
||||
|
||||
if (state->leadership_state != kv::LeadershipState::Candidate)
|
||||
if (state->leadership_state != ccf::kv::LeadershipState::Candidate)
|
||||
{
|
||||
RAFT_INFO_FMT(
|
||||
"Recv request vote response to {} from: {}: we aren't a candidate",
|
||||
|
@ -1929,7 +1930,7 @@ namespace aft
|
|||
return;
|
||||
}
|
||||
|
||||
state->leadership_state = kv::LeadershipState::Candidate;
|
||||
state->leadership_state = ccf::kv::LeadershipState::Candidate;
|
||||
leader_id.reset();
|
||||
|
||||
voted_for = state->node_id;
|
||||
|
@ -1986,7 +1987,7 @@ namespace aft
|
|||
store->initialise_term(state->current_view);
|
||||
}
|
||||
|
||||
state->leadership_state = kv::LeadershipState::Leader;
|
||||
state->leadership_state = ccf::kv::LeadershipState::Leader;
|
||||
leader_id = state->node_id;
|
||||
should_sign = true;
|
||||
|
||||
|
@ -2045,7 +2046,7 @@ namespace aft
|
|||
// receiving a conflicting AppendEntries
|
||||
rollback(last_committable_index());
|
||||
|
||||
state->leadership_state = kv::LeadershipState::Follower;
|
||||
state->leadership_state = ccf::kv::LeadershipState::Follower;
|
||||
RAFT_INFO_FMT(
|
||||
"Becoming follower {}: {}.{}",
|
||||
state->node_id,
|
||||
|
@ -2077,7 +2078,7 @@ namespace aft
|
|||
}
|
||||
|
||||
private:
|
||||
void become_retired(Index idx, kv::RetirementPhase phase)
|
||||
void become_retired(Index idx, ccf::kv::RetirementPhase phase)
|
||||
{
|
||||
RAFT_INFO_FMT(
|
||||
"Becoming retired, phase {} (leadership {}): {}: {} at {}",
|
||||
|
@ -2087,7 +2088,7 @@ namespace aft
|
|||
state->current_view,
|
||||
idx);
|
||||
|
||||
if (phase == kv::RetirementPhase::Ordered)
|
||||
if (phase == ccf::kv::RetirementPhase::Ordered)
|
||||
{
|
||||
CCF_ASSERT_FMT(
|
||||
!state->retirement_idx.has_value(),
|
||||
|
@ -2096,7 +2097,7 @@ namespace aft
|
|||
state->retirement_idx = idx;
|
||||
RAFT_INFO_FMT("Node retiring at {}", idx);
|
||||
}
|
||||
else if (phase == kv::RetirementPhase::Signed)
|
||||
else if (phase == ccf::kv::RetirementPhase::Signed)
|
||||
{
|
||||
assert(state->retirement_idx.has_value());
|
||||
CCF_ASSERT_FMT(
|
||||
|
@ -2107,15 +2108,15 @@ namespace aft
|
|||
state->retirement_committable_idx = idx;
|
||||
RAFT_INFO_FMT("Node retirement committable at {}", idx);
|
||||
}
|
||||
else if (phase == kv::RetirementPhase::RetiredCommitted)
|
||||
else if (phase == ccf::kv::RetirementPhase::RetiredCommitted)
|
||||
{
|
||||
if (state->leadership_state == kv::LeadershipState::Leader)
|
||||
if (state->leadership_state == ccf::kv::LeadershipState::Leader)
|
||||
{
|
||||
ProposeRequestVote prv{.term = state->current_view};
|
||||
|
||||
std::optional<ccf::NodeId> successor = std::nullopt;
|
||||
Index max_match_idx = 0;
|
||||
kv::ReconfigurationId reconf_id_of_max_match = 0;
|
||||
ccf::kv::ReconfigurationId reconf_id_of_max_match = 0;
|
||||
|
||||
// Pick the node that has the highest match_idx, and break
|
||||
// ties by looking at the highest reconfiguration id they are
|
||||
|
@ -2131,7 +2132,7 @@ namespace aft
|
|||
{
|
||||
if (node_state.match_idx >= max_match_idx)
|
||||
{
|
||||
kv::ReconfigurationId latest_reconf_id = 0;
|
||||
ccf::kv::ReconfigurationId latest_reconf_id = 0;
|
||||
auto conf = configurations.rbegin();
|
||||
while (conf != configurations.rend())
|
||||
{
|
||||
|
@ -2160,10 +2161,10 @@ namespace aft
|
|||
}
|
||||
|
||||
leader_id.reset();
|
||||
state->leadership_state = kv::LeadershipState::None;
|
||||
state->leadership_state = ccf::kv::LeadershipState::None;
|
||||
}
|
||||
|
||||
state->membership_state = kv::MembershipState::Retired;
|
||||
state->membership_state = ccf::kv::MembershipState::Retired;
|
||||
state->retirement_phase = phase;
|
||||
}
|
||||
|
||||
|
@ -2221,7 +2222,7 @@ namespace aft
|
|||
// idx.
|
||||
void update_commit()
|
||||
{
|
||||
if (state->leadership_state != kv::LeadershipState::Leader)
|
||||
if (state->leadership_state != ccf::kv::LeadershipState::Leader)
|
||||
{
|
||||
throw std::logic_error(
|
||||
"update_commit() must only be called while this node is leader");
|
||||
|
@ -2357,11 +2358,11 @@ namespace aft
|
|||
state->commit_idx = idx;
|
||||
if (
|
||||
is_retired() &&
|
||||
state->retirement_phase == kv::RetirementPhase::Signed &&
|
||||
state->retirement_phase == ccf::kv::RetirementPhase::Signed &&
|
||||
state->retirement_committable_idx.has_value() &&
|
||||
idx >= state->retirement_committable_idx.value())
|
||||
{
|
||||
become_retired(idx, kv::RetirementPhase::Completed);
|
||||
become_retired(idx, ccf::kv::RetirementPhase::Completed);
|
||||
}
|
||||
|
||||
RAFT_DEBUG_FMT("Compacting...");
|
||||
|
@ -2457,27 +2458,27 @@ namespace aft
|
|||
}
|
||||
|
||||
if (
|
||||
state->membership_state == kv::MembershipState::Retired &&
|
||||
state->retirement_phase == kv::RetirementPhase::Signed)
|
||||
state->membership_state == ccf::kv::MembershipState::Retired &&
|
||||
state->retirement_phase == ccf::kv::RetirementPhase::Signed)
|
||||
{
|
||||
assert(state->retirement_committable_idx.has_value());
|
||||
if (state->retirement_committable_idx.value() > idx)
|
||||
{
|
||||
state->retirement_committable_idx = std::nullopt;
|
||||
state->retirement_phase = kv::RetirementPhase::Ordered;
|
||||
state->retirement_phase = ccf::kv::RetirementPhase::Ordered;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
state->membership_state == kv::MembershipState::Retired &&
|
||||
state->retirement_phase == kv::RetirementPhase::Ordered)
|
||||
state->membership_state == ccf::kv::MembershipState::Retired &&
|
||||
state->retirement_phase == ccf::kv::RetirementPhase::Ordered)
|
||||
{
|
||||
assert(state->retirement_idx.has_value());
|
||||
if (state->retirement_idx.value() > idx)
|
||||
{
|
||||
state->retirement_idx = std::nullopt;
|
||||
state->retirement_phase = std::nullopt;
|
||||
state->membership_state = kv::MembershipState::Active;
|
||||
state->membership_state = ccf::kv::MembershipState::Active;
|
||||
RAFT_DEBUG_FMT("Becoming Active after rollback");
|
||||
}
|
||||
}
|
||||
|
@ -2558,7 +2559,7 @@ namespace aft
|
|||
all_other_nodes.try_emplace(
|
||||
node_info.first, node_info.second, index, 0);
|
||||
|
||||
if (state->leadership_state == kv::LeadershipState::Leader)
|
||||
if (state->leadership_state == ccf::kv::LeadershipState::Leader)
|
||||
{
|
||||
send_append_entries(node_info.first, index);
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace aft
|
|||
|
||||
using ReplyCallback = std::function<bool(
|
||||
void* owner,
|
||||
kv::TxHistory::RequestID caller_rid,
|
||||
ccf::kv::TxHistory::RequestID caller_rid,
|
||||
int status,
|
||||
std::vector<uint8_t>&& data)>;
|
||||
|
||||
|
@ -34,12 +34,13 @@ namespace aft
|
|||
public:
|
||||
virtual ~Store() {}
|
||||
virtual void compact(Index v) = 0;
|
||||
virtual void rollback(const kv::TxID& tx_id, Term term_of_next_version) = 0;
|
||||
virtual void rollback(
|
||||
const ccf::kv::TxID& tx_id, Term term_of_next_version) = 0;
|
||||
virtual void initialise_term(Term t) = 0;
|
||||
virtual std::unique_ptr<kv::AbstractExecutionWrapper> deserialize(
|
||||
virtual std::unique_ptr<ccf::kv::AbstractExecutionWrapper> deserialize(
|
||||
const std::vector<uint8_t> data,
|
||||
bool public_only = false,
|
||||
const std::optional<kv::TxID>& expected_txid = std::nullopt) = 0;
|
||||
const std::optional<ccf::kv::TxID>& expected_txid = std::nullopt) = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
@ -60,7 +61,8 @@ namespace aft
|
|||
}
|
||||
}
|
||||
|
||||
void rollback(const kv::TxID& tx_id, Term term_of_next_version) override
|
||||
void rollback(
|
||||
const ccf::kv::TxID& tx_id, Term term_of_next_version) override
|
||||
{
|
||||
auto p = x.lock();
|
||||
if (p)
|
||||
|
@ -78,10 +80,10 @@ namespace aft
|
|||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<kv::AbstractExecutionWrapper> deserialize(
|
||||
std::unique_ptr<ccf::kv::AbstractExecutionWrapper> deserialize(
|
||||
const std::vector<uint8_t> data,
|
||||
bool public_only = false,
|
||||
const std::optional<kv::TxID>& expected_txid = std::nullopt) override
|
||||
const std::optional<ccf::kv::TxID>& expected_txid = std::nullopt) override
|
||||
{
|
||||
auto p = x.lock();
|
||||
if (p)
|
||||
|
|
|
@ -205,7 +205,7 @@ DOCTEST_TEST_CASE("Retention of dead leader's commit")
|
|||
DOCTEST_INFO("Entry at 1.1 is received by all nodes");
|
||||
{
|
||||
auto entry = make_ledger_entry(1, 1);
|
||||
rA.replicate(kv::BatchVector{{1, entry, true, hooks}}, 1);
|
||||
rA.replicate(ccf::kv::BatchVector{{1, entry, true, hooks}}, 1);
|
||||
DOCTEST_REQUIRE(rA.get_last_idx() == 1);
|
||||
DOCTEST_REQUIRE(rA.get_committed_seqno() == 0);
|
||||
// Size limit was reached, so periodic is not needed
|
||||
|
@ -235,21 +235,21 @@ DOCTEST_TEST_CASE("Retention of dead leader's commit")
|
|||
"committed");
|
||||
{
|
||||
auto entry = make_ledger_entry(1, 2);
|
||||
rA.replicate(kv::BatchVector{{2, entry, true, hooks}}, 1);
|
||||
rA.replicate(ccf::kv::BatchVector{{2, entry, true, hooks}}, 1);
|
||||
DOCTEST_REQUIRE(rA.get_last_idx() == 2);
|
||||
DOCTEST_REQUIRE(rA.get_committed_seqno() == 1);
|
||||
// Size limit was reached, so periodic is not needed
|
||||
// rA.periodic(request_timeout);
|
||||
|
||||
entry = make_ledger_entry(1, 3);
|
||||
rA.replicate(kv::BatchVector{{3, entry, true, hooks}}, 1);
|
||||
rA.replicate(ccf::kv::BatchVector{{3, entry, true, hooks}}, 1);
|
||||
DOCTEST_REQUIRE(rA.get_last_idx() == 3);
|
||||
DOCTEST_REQUIRE(rA.get_committed_seqno() == 1);
|
||||
// Size limit was reached, so periodic is not needed
|
||||
// rA.periodic(request_timeout);
|
||||
|
||||
entry = make_ledger_entry(1, 4);
|
||||
rA.replicate(kv::BatchVector{{4, entry, true, hooks}}, 1);
|
||||
rA.replicate(ccf::kv::BatchVector{{4, entry, true, hooks}}, 1);
|
||||
DOCTEST_REQUIRE(rA.get_last_idx() == 4);
|
||||
DOCTEST_REQUIRE(rA.get_committed_seqno() == 1);
|
||||
// Size limit was reached, so periodic is not needed
|
||||
|
@ -283,7 +283,7 @@ DOCTEST_TEST_CASE("Retention of dead leader's commit")
|
|||
"committed");
|
||||
{
|
||||
auto entry = make_ledger_entry(1, 5);
|
||||
rA.replicate(kv::BatchVector{{5, entry, true, hooks}}, 1);
|
||||
rA.replicate(ccf::kv::BatchVector{{5, entry, true, hooks}}, 1);
|
||||
DOCTEST_REQUIRE(rA.get_last_idx() == 5);
|
||||
// Size limit was reached, so periodic is not needed
|
||||
// rB.periodic(request_timeout);
|
||||
|
@ -350,11 +350,11 @@ DOCTEST_TEST_CASE("Retention of dead leader's commit")
|
|||
DOCTEST_INFO("Node B writes some entries, though they are lost");
|
||||
{
|
||||
auto entry = make_ledger_entry(2, 6);
|
||||
rB.replicate(kv::BatchVector{{6, entry, true, hooks}}, 2);
|
||||
rB.replicate(ccf::kv::BatchVector{{6, entry, true, hooks}}, 2);
|
||||
DOCTEST_REQUIRE(rB.get_last_idx() == 6);
|
||||
|
||||
entry = make_ledger_entry(2, 7);
|
||||
rB.replicate(kv::BatchVector{{7, entry, true, hooks}}, 2);
|
||||
rB.replicate(ccf::kv::BatchVector{{7, entry, true, hooks}}, 2);
|
||||
DOCTEST_REQUIRE(rB.get_last_idx() == 7);
|
||||
|
||||
// Size limit was reached, so periodic is not needed
|
||||
|
@ -401,15 +401,15 @@ DOCTEST_TEST_CASE("Retention of dead leader's commit")
|
|||
DOCTEST_REQUIRE("Node C produces 3.5, 3.6, and 3.7");
|
||||
{
|
||||
auto entry = make_ledger_entry(3, 5);
|
||||
rC.replicate(kv::BatchVector{{5, entry, true, hooks}}, 3);
|
||||
rC.replicate(ccf::kv::BatchVector{{5, entry, true, hooks}}, 3);
|
||||
DOCTEST_REQUIRE(rC.get_last_idx() == 5);
|
||||
|
||||
entry = make_ledger_entry(3, 6);
|
||||
rC.replicate(kv::BatchVector{{6, entry, true, hooks}}, 3);
|
||||
rC.replicate(ccf::kv::BatchVector{{6, entry, true, hooks}}, 3);
|
||||
DOCTEST_REQUIRE(rC.get_last_idx() == 6);
|
||||
|
||||
entry = make_ledger_entry(3, 7);
|
||||
rC.replicate(kv::BatchVector{{7, entry, true, hooks}}, 3);
|
||||
rC.replicate(ccf::kv::BatchVector{{7, entry, true, hooks}}, 3);
|
||||
DOCTEST_REQUIRE(rC.get_last_idx() == 7);
|
||||
|
||||
// The early AppendEntries that describe this are lost
|
||||
|
@ -598,7 +598,7 @@ DOCTEST_TEST_CASE_TEMPLATE("Multi-term divergence", T, WorstCase, RandomCase)
|
|||
{
|
||||
auto entry = make_ledger_entry(primary.get_view(), idx);
|
||||
primary.replicate(
|
||||
kv::BatchVector{{idx, entry, true, hooks}}, primary.get_view());
|
||||
ccf::kv::BatchVector{{idx, entry, true, hooks}}, primary.get_view());
|
||||
}
|
||||
|
||||
// All related AppendEntries are lost
|
||||
|
@ -627,9 +627,9 @@ DOCTEST_TEST_CASE_TEMPLATE("Multi-term divergence", T, WorstCase, RandomCase)
|
|||
// be committed
|
||||
|
||||
auto entry = make_ledger_entry(1, 1);
|
||||
rA.replicate(kv::BatchVector{{1, entry, true, hooks}}, 1);
|
||||
rA.replicate(ccf::kv::BatchVector{{1, entry, true, hooks}}, 1);
|
||||
entry = make_ledger_entry(1, 2);
|
||||
rA.replicate(kv::BatchVector{{2, entry, true, hooks}}, 1);
|
||||
rA.replicate(ccf::kv::BatchVector{{2, entry, true, hooks}}, 1);
|
||||
DOCTEST_REQUIRE(rA.get_last_idx() == 2);
|
||||
DOCTEST_REQUIRE(rA.get_committed_seqno() == 0);
|
||||
// Size limit was reached, so periodic is not needed
|
||||
|
@ -662,18 +662,18 @@ DOCTEST_TEST_CASE_TEMPLATE("Multi-term divergence", T, WorstCase, RandomCase)
|
|||
// Node A produces 2 additional entries that A and B have, and 2 additional
|
||||
// entries that are only present on A
|
||||
entry = make_ledger_entry(1, 3);
|
||||
rA.replicate(kv::BatchVector{{3, entry, true, hooks}}, 1);
|
||||
rA.replicate(ccf::kv::BatchVector{{3, entry, true, hooks}}, 1);
|
||||
|
||||
entry = make_ledger_entry(1, 4);
|
||||
rA.replicate(kv::BatchVector{{4, entry, true, hooks}}, 1);
|
||||
rA.replicate(ccf::kv::BatchVector{{4, entry, true, hooks}}, 1);
|
||||
keep_messages_for(node_idB, channelsA->messages);
|
||||
DOCTEST_REQUIRE(2 == dispatch_all(nodes, node_idA));
|
||||
|
||||
entry = make_ledger_entry(1, 5);
|
||||
rA.replicate(kv::BatchVector{{5, entry, true, hooks}}, 1);
|
||||
rA.replicate(ccf::kv::BatchVector{{5, entry, true, hooks}}, 1);
|
||||
|
||||
entry = make_ledger_entry(1, 6);
|
||||
rA.replicate(kv::BatchVector{{6, entry, true, hooks}}, 1);
|
||||
rA.replicate(ccf::kv::BatchVector{{6, entry, true, hooks}}, 1);
|
||||
channelsA->messages.clear();
|
||||
channelsB->messages.clear();
|
||||
|
||||
|
@ -936,7 +936,7 @@ DOCTEST_TEST_CASE_TEMPLATE("Multi-term divergence", T, WorstCase, RandomCase)
|
|||
const auto seqno = rPrimary.get_last_idx() + 1;
|
||||
auto final_entry = make_ledger_entry(view, seqno);
|
||||
rPrimary.replicate(
|
||||
kv::BatchVector{{seqno, final_entry, true, hooks}}, view);
|
||||
ccf::kv::BatchVector{{seqno, final_entry, true, hooks}}, view);
|
||||
|
||||
rPrimary.periodic(request_timeout);
|
||||
keep_earliest_append_entries_for_each_target(channelsPrimary->messages);
|
||||
|
|
|
@ -48,8 +48,8 @@ struct LedgerStubProxy_Mermaid : public aft::LedgerStubProxy
|
|||
void put_entry(
|
||||
const std::vector<uint8_t>& data,
|
||||
bool globally_committable,
|
||||
kv::Term term,
|
||||
kv::Version index) override
|
||||
ccf::kv::Term term,
|
||||
ccf::kv::Version index) override
|
||||
{
|
||||
RAFT_DRIVER_PRINT(
|
||||
"{}->>{}: [ledger] appending: {}.{}={}",
|
||||
|
@ -78,7 +78,7 @@ struct LoggingStubStore_Mermaid : public aft::LoggingStubStoreConfig
|
|||
aft::LoggingStubStoreConfig::compact(idx);
|
||||
}
|
||||
|
||||
void rollback(const kv::TxID& tx_id, aft::Term t) override
|
||||
void rollback(const ccf::kv::TxID& tx_id, aft::Term t) override
|
||||
{
|
||||
RAFT_DRIVER_PRINT(
|
||||
"{}->>{}: [KV] rolling back to {}.{}, in term {}",
|
||||
|
@ -124,8 +124,9 @@ private:
|
|||
std::vector<uint8_t> data,
|
||||
const size_t lineno,
|
||||
bool committable = false,
|
||||
const std::optional<kv::Configuration::Nodes>& configuration = std::nullopt,
|
||||
const std::optional<kv::Configuration::Nodes>& retired_committed =
|
||||
const std::optional<ccf::kv::Configuration::Nodes>& configuration =
|
||||
std::nullopt,
|
||||
const std::optional<ccf::kv::Configuration::Nodes>& retired_committed =
|
||||
std::nullopt)
|
||||
{
|
||||
const auto opt = find_primary_in_term(term_s, lineno);
|
||||
|
@ -150,7 +151,7 @@ private:
|
|||
configuration.has_value() ? "reconfiguration" : "raw");
|
||||
|
||||
aft::ReplicatedDataType type = aft::ReplicatedDataType::raw;
|
||||
auto hooks = std::make_shared<kv::ConsensusHookPtrs>();
|
||||
auto hooks = std::make_shared<ccf::kv::ConsensusHookPtrs>();
|
||||
if (configuration.has_value() && retired_committed.has_value())
|
||||
{
|
||||
throw std::logic_error(
|
||||
|
@ -184,7 +185,7 @@ private:
|
|||
|
||||
auto s = nlohmann::json(aft::ReplicatedData{type, data}).dump();
|
||||
auto d = std::make_shared<std::vector<uint8_t>>(s.begin(), s.end());
|
||||
raft->replicate(kv::BatchVector{{idx, d, committable, hooks}}, term);
|
||||
raft->replicate(ccf::kv::BatchVector{{idx, d, committable, hooks}}, term);
|
||||
}
|
||||
|
||||
void add_node(ccf::NodeId node_id)
|
||||
|
@ -199,7 +200,7 @@ private:
|
|||
std::make_shared<aft::State>(node_id),
|
||||
nullptr);
|
||||
kv->set_set_retired_committed_hook(
|
||||
[raft](aft::Index idx, const std::vector<kv::NodeId>& node_ids) {
|
||||
[raft](aft::Index idx, const std::vector<ccf::kv::NodeId>& node_ids) {
|
||||
raft->set_retired_committed(idx, node_ids);
|
||||
});
|
||||
raft->start_ticking();
|
||||
|
@ -220,7 +221,7 @@ public:
|
|||
{
|
||||
// Unrealistic way to create network. Initial configuration is automatically
|
||||
// added to all nodes.
|
||||
kv::Configuration::Nodes configuration;
|
||||
ccf::kv::Configuration::Nodes configuration;
|
||||
for (auto const& n : node_ids)
|
||||
{
|
||||
add_node(n);
|
||||
|
@ -248,7 +249,7 @@ public:
|
|||
{
|
||||
throw std::logic_error("Start node already exists");
|
||||
}
|
||||
kv::Configuration::Nodes configuration;
|
||||
ccf::kv::Configuration::Nodes configuration;
|
||||
add_node(start_node_id);
|
||||
configuration.try_emplace(start_node_id);
|
||||
_nodes[start_node_id].raft->force_become_primary();
|
||||
|
@ -264,7 +265,7 @@ public:
|
|||
const std::vector<std::string>& node_ids,
|
||||
const size_t lineno)
|
||||
{
|
||||
kv::Configuration::Nodes retired_committed;
|
||||
ccf::kv::Configuration::Nodes retired_committed;
|
||||
for (const auto& id : node_ids)
|
||||
{
|
||||
if (_nodes.find(id) == _nodes.end())
|
||||
|
@ -288,7 +289,7 @@ public:
|
|||
RAFT_DRIVER_PRINT(
|
||||
"Note over {}: Node {} trusted", ccf::NodeId(node_id), node_id);
|
||||
}
|
||||
kv::Configuration::Nodes configuration;
|
||||
ccf::kv::Configuration::Nodes configuration;
|
||||
for (const auto& [id, node] : _nodes)
|
||||
{
|
||||
configuration.try_emplace(id);
|
||||
|
@ -325,7 +326,7 @@ public:
|
|||
}
|
||||
std::set<std::string> out(nodes_out.begin(), nodes_out.end());
|
||||
|
||||
kv::Configuration::Nodes configuration;
|
||||
ccf::kv::Configuration::Nodes configuration;
|
||||
for (const auto& [id, node] : _nodes)
|
||||
{
|
||||
if (out.find(id) == out.end())
|
||||
|
@ -352,7 +353,7 @@ public:
|
|||
std::vector<std::string> node_ids,
|
||||
const size_t lineno)
|
||||
{
|
||||
kv::Configuration::Nodes configuration;
|
||||
ccf::kv::Configuration::Nodes configuration;
|
||||
for (const auto& node_id_s : node_ids)
|
||||
{
|
||||
ccf::NodeId node_id(node_id_s);
|
||||
|
|
|
@ -73,9 +73,9 @@ TEST_CASE("Enclave record")
|
|||
|
||||
bool globally_committable = false;
|
||||
const std::vector<uint8_t> entry = {'a', 'b', 'c'};
|
||||
kv::SerialisedEntryHeader entry_header;
|
||||
ccf::kv::SerialisedEntryHeader entry_header;
|
||||
|
||||
std::vector<uint8_t> tx(kv::serialised_entry_header_size + entry.size());
|
||||
std::vector<uint8_t> tx(ccf::kv::serialised_entry_header_size + entry.size());
|
||||
auto tx_ = tx.data();
|
||||
auto size_ = tx.size();
|
||||
serialized::write(tx_, size_, entry_header);
|
||||
|
|
|
@ -30,8 +30,8 @@ namespace aft
|
|||
virtual void put_entry(
|
||||
const std::vector<uint8_t>& original,
|
||||
bool globally_committable,
|
||||
kv::Term term,
|
||||
kv::Version index)
|
||||
ccf::kv::Term term,
|
||||
ccf::kv::Version index)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(ledger_access);
|
||||
|
||||
|
@ -98,8 +98,8 @@ namespace aft
|
|||
// Remove the View and Index that were written during put_entry
|
||||
data->erase(
|
||||
data->begin(),
|
||||
data->begin() + sizeof(size_t) + sizeof(kv::Term) +
|
||||
sizeof(kv::Version));
|
||||
data->begin() + sizeof(size_t) + sizeof(ccf::kv::Term) +
|
||||
sizeof(ccf::kv::Version));
|
||||
}
|
||||
|
||||
return data;
|
||||
|
@ -286,20 +286,21 @@ namespace aft
|
|||
DECLARE_JSON_TYPE(ReplicatedData);
|
||||
DECLARE_JSON_REQUIRED_FIELDS(ReplicatedData, type, data);
|
||||
|
||||
class ConfigurationChangeHook : public kv::ConsensusHook
|
||||
class ConfigurationChangeHook : public ccf::kv::ConsensusHook
|
||||
{
|
||||
kv::Configuration::Nodes
|
||||
ccf::kv::Configuration::Nodes
|
||||
new_configuration; // Absence of node means that node has been retired
|
||||
kv::Version version;
|
||||
ccf::kv::Version version;
|
||||
|
||||
public:
|
||||
ConfigurationChangeHook(
|
||||
kv::Configuration::Nodes new_configuration_, kv::Version version_) :
|
||||
ccf::kv::Configuration::Nodes new_configuration_,
|
||||
ccf::kv::Version version_) :
|
||||
new_configuration(new_configuration_),
|
||||
version(version_)
|
||||
{}
|
||||
|
||||
void call(kv::ConfigurableConsensus* consensus) override
|
||||
void call(ccf::kv::ConfigurableConsensus* consensus) override
|
||||
{
|
||||
auto configuration = consensus->get_latest_configuration_unsafe();
|
||||
std::unordered_set<ccf::NodeId> retired_nodes;
|
||||
|
@ -329,7 +330,8 @@ namespace aft
|
|||
}
|
||||
};
|
||||
|
||||
using RCHook = std::function<void(Index, const std::vector<kv::NodeId>&)>;
|
||||
using RCHook =
|
||||
std::function<void(Index, const std::vector<ccf::kv::NodeId>&)>;
|
||||
|
||||
class LoggingStubStore
|
||||
{
|
||||
|
@ -348,32 +350,32 @@ namespace aft
|
|||
|
||||
virtual void compact(Index i) {}
|
||||
|
||||
virtual void rollback(const kv::TxID& tx_id, Term t) {}
|
||||
virtual void rollback(const ccf::kv::TxID& tx_id, Term t) {}
|
||||
|
||||
virtual void initialise_term(Term t) {}
|
||||
|
||||
kv::Version current_version()
|
||||
ccf::kv::Version current_version()
|
||||
{
|
||||
return kv::NoVersion;
|
||||
return ccf::kv::NoVersion;
|
||||
}
|
||||
|
||||
class ExecutionWrapper : public kv::AbstractExecutionWrapper
|
||||
class ExecutionWrapper : public ccf::kv::AbstractExecutionWrapper
|
||||
{
|
||||
private:
|
||||
kv::ConsensusHookPtrs hooks;
|
||||
ccf::kv::ConsensusHookPtrs hooks;
|
||||
aft::Term term;
|
||||
kv::Version index;
|
||||
ccf::kv::Version index;
|
||||
std::vector<uint8_t> entry;
|
||||
ccf::ClaimsDigest claims_digest;
|
||||
std::optional<ccf::crypto::Sha256Hash> commit_evidence_digest =
|
||||
std::nullopt;
|
||||
kv::ApplyResult result;
|
||||
ccf::kv::ApplyResult result;
|
||||
|
||||
public:
|
||||
ExecutionWrapper(
|
||||
const std::vector<uint8_t>& data_,
|
||||
const std::optional<kv::TxID>& expected_txid,
|
||||
kv::ConsensusHookPtrs&& hooks_) :
|
||||
const std::optional<ccf::kv::TxID>& expected_txid,
|
||||
ccf::kv::ConsensusHookPtrs&& hooks_) :
|
||||
hooks(std::move(hooks_))
|
||||
{
|
||||
const uint8_t* data = data_.data();
|
||||
|
@ -381,17 +383,17 @@ namespace aft
|
|||
|
||||
const auto committable = serialized::read<bool>(data, size);
|
||||
term = serialized::read<aft::Term>(data, size);
|
||||
index = serialized::read<kv::Version>(data, size);
|
||||
index = serialized::read<ccf::kv::Version>(data, size);
|
||||
entry = serialized::read(data, size, size);
|
||||
|
||||
result =
|
||||
committable ? kv::ApplyResult::PASS_SIGNATURE : kv::ApplyResult::PASS;
|
||||
result = committable ? ccf::kv::ApplyResult::PASS_SIGNATURE :
|
||||
ccf::kv::ApplyResult::PASS;
|
||||
|
||||
if (expected_txid.has_value())
|
||||
{
|
||||
if (term != expected_txid->term || index != expected_txid->version)
|
||||
{
|
||||
result = kv::ApplyResult::FAIL;
|
||||
result = ccf::kv::ApplyResult::FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -407,12 +409,12 @@ namespace aft
|
|||
return std::move(commit_evidence_digest);
|
||||
}
|
||||
|
||||
kv::ApplyResult apply(bool track_deletes_on_missing_keys) override
|
||||
ccf::kv::ApplyResult apply(bool track_deletes_on_missing_keys) override
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
kv::ConsensusHookPtrs& get_hooks() override
|
||||
ccf::kv::ConsensusHookPtrs& get_hooks() override
|
||||
{
|
||||
return hooks;
|
||||
}
|
||||
|
@ -427,7 +429,7 @@ namespace aft
|
|||
return term;
|
||||
}
|
||||
|
||||
kv::Version get_index() override
|
||||
ccf::kv::Version get_index() override
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
@ -448,22 +450,22 @@ namespace aft
|
|||
}
|
||||
};
|
||||
|
||||
virtual std::unique_ptr<kv::AbstractExecutionWrapper> deserialize(
|
||||
virtual std::unique_ptr<ccf::kv::AbstractExecutionWrapper> deserialize(
|
||||
const std::vector<uint8_t>& data,
|
||||
bool public_only = false,
|
||||
const std::optional<kv::TxID>& expected_txid = std::nullopt)
|
||||
const std::optional<ccf::kv::TxID>& expected_txid = std::nullopt)
|
||||
{
|
||||
kv::ConsensusHookPtrs hooks = {};
|
||||
ccf::kv::ConsensusHookPtrs hooks = {};
|
||||
return std::make_unique<ExecutionWrapper>(
|
||||
data, expected_txid, std::move(hooks));
|
||||
}
|
||||
|
||||
bool flag_enabled(kv::AbstractStore::Flag)
|
||||
bool flag_enabled(ccf::kv::AbstractStore::Flag)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void unset_flag(kv::AbstractStore::Flag) {}
|
||||
void unset_flag(ccf::kv::AbstractStore::Flag) {}
|
||||
};
|
||||
|
||||
class LoggingStubStoreConfig : public LoggingStubStore
|
||||
|
@ -483,7 +485,7 @@ namespace aft
|
|||
{
|
||||
if (version <= i)
|
||||
{
|
||||
std::vector<kv::NodeId> retired_committed_node_ids;
|
||||
std::vector<ccf::kv::NodeId> retired_committed_node_ids;
|
||||
for (auto& [node_id, _] : configuration.items())
|
||||
{
|
||||
retired_committed_node_ids.push_back(node_id);
|
||||
|
@ -503,7 +505,7 @@ namespace aft
|
|||
retired_committed_entries.end());
|
||||
}
|
||||
|
||||
virtual void rollback(const kv::TxID& tx_id, Term t) override
|
||||
virtual void rollback(const ccf::kv::TxID& tx_id, Term t) override
|
||||
{
|
||||
retired_committed_entries.erase(
|
||||
std::remove_if(
|
||||
|
@ -513,10 +515,10 @@ namespace aft
|
|||
retired_committed_entries.end());
|
||||
}
|
||||
|
||||
virtual std::unique_ptr<kv::AbstractExecutionWrapper> deserialize(
|
||||
virtual std::unique_ptr<ccf::kv::AbstractExecutionWrapper> deserialize(
|
||||
const std::vector<uint8_t>& data,
|
||||
bool public_only = false,
|
||||
const std::optional<kv::TxID>& expected_txid = std::nullopt) override
|
||||
const std::optional<ccf::kv::TxID>& expected_txid = std::nullopt) override
|
||||
{
|
||||
// Set reconfiguration hook if there are any new nodes
|
||||
// Read wrapping term and version
|
||||
|
@ -524,19 +526,21 @@ namespace aft
|
|||
auto size = data.size();
|
||||
const auto committable = serialized::read<bool>(data_, size);
|
||||
serialized::read<aft::Term>(data_, size);
|
||||
auto version = serialized::read<kv::Version>(data_, size);
|
||||
auto version = serialized::read<ccf::kv::Version>(data_, size);
|
||||
ReplicatedData r = nlohmann::json::parse(std::span{data_, size});
|
||||
kv::ConsensusHookPtrs hooks = {};
|
||||
ccf::kv::ConsensusHookPtrs hooks = {};
|
||||
if (r.type == ReplicatedDataType::reconfiguration)
|
||||
{
|
||||
kv::Configuration::Nodes configuration = nlohmann::json::parse(r.data);
|
||||
ccf::kv::Configuration::Nodes configuration =
|
||||
nlohmann::json::parse(r.data);
|
||||
auto hook = std::make_unique<aft::ConfigurationChangeHook>(
|
||||
configuration, version);
|
||||
hooks.push_back(std::move(hook));
|
||||
}
|
||||
if (r.type == ReplicatedDataType::retired_committed)
|
||||
{
|
||||
kv::Configuration::Nodes configuration = nlohmann::json::parse(r.data);
|
||||
ccf::kv::Configuration::Nodes configuration =
|
||||
nlohmann::json::parse(r.data);
|
||||
retired_committed_entries.emplace_back(version, configuration);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ using ms = std::chrono::milliseconds;
|
|||
|
||||
DOCTEST_TEST_CASE("Single node startup" * doctest::test_suite("single"))
|
||||
{
|
||||
ccf::NodeId node_id = kv::test::PrimaryNodeId;
|
||||
ccf::NodeId node_id = ccf::kv::test::PrimaryNodeId;
|
||||
auto kv_store = std::make_shared<Store>(node_id);
|
||||
|
||||
TRaft r0(
|
||||
|
@ -26,7 +26,7 @@ DOCTEST_TEST_CASE("Single node startup" * doctest::test_suite("single"))
|
|||
nullptr);
|
||||
r0.start_ticking();
|
||||
|
||||
kv::Configuration::Nodes config;
|
||||
ccf::kv::Configuration::Nodes config;
|
||||
config.try_emplace(node_id);
|
||||
r0.add_configuration(0, config);
|
||||
|
||||
|
@ -50,7 +50,7 @@ DOCTEST_TEST_CASE("Single node startup" * doctest::test_suite("single"))
|
|||
|
||||
DOCTEST_TEST_CASE("Single node commit" * doctest::test_suite("single"))
|
||||
{
|
||||
ccf::NodeId node_id = kv::test::PrimaryNodeId;
|
||||
ccf::NodeId node_id = ccf::kv::test::PrimaryNodeId;
|
||||
auto kv_store = std::make_shared<Store>(node_id);
|
||||
|
||||
TRaft r0(
|
||||
|
@ -80,9 +80,9 @@ DOCTEST_TEST_CASE("Single node commit" * doctest::test_suite("single"))
|
|||
entry->push_back(2);
|
||||
entry->push_back(3);
|
||||
|
||||
auto hooks = std::make_shared<kv::ConsensusHookPtrs>();
|
||||
auto hooks = std::make_shared<ccf::kv::ConsensusHookPtrs>();
|
||||
|
||||
r0.replicate(kv::BatchVector{{i, entry, true, hooks}}, 1);
|
||||
r0.replicate(ccf::kv::BatchVector{{i, entry, true, hooks}}, 1);
|
||||
DOCTEST_REQUIRE(r0.get_last_idx() == i);
|
||||
DOCTEST_REQUIRE(r0.get_committed_seqno() == i);
|
||||
}
|
||||
|
@ -91,10 +91,10 @@ DOCTEST_TEST_CASE("Single node commit" * doctest::test_suite("single"))
|
|||
DOCTEST_TEST_CASE(
|
||||
"Multiple nodes startup and election" * doctest::test_suite("multiple"))
|
||||
{
|
||||
ccf::NodeId node_id0 = kv::test::PrimaryNodeId;
|
||||
ccf::NodeId node_id1 = kv::test::FirstBackupNodeId;
|
||||
ccf::NodeId node_id2 = kv::test::SecondBackupNodeId;
|
||||
ccf::NodeId node_id3 = kv::test::ThirdBackupNodeId;
|
||||
ccf::NodeId node_id0 = ccf::kv::test::PrimaryNodeId;
|
||||
ccf::NodeId node_id1 = ccf::kv::test::FirstBackupNodeId;
|
||||
ccf::NodeId node_id2 = ccf::kv::test::SecondBackupNodeId;
|
||||
ccf::NodeId node_id3 = ccf::kv::test::ThirdBackupNodeId;
|
||||
|
||||
auto kv_store0 = std::make_shared<Store>(node_id0);
|
||||
auto kv_store1 = std::make_shared<Store>(node_id1);
|
||||
|
@ -275,9 +275,9 @@ DOCTEST_TEST_CASE(
|
|||
DOCTEST_TEST_CASE(
|
||||
"Multiple nodes append entries" * doctest::test_suite("multiple"))
|
||||
{
|
||||
ccf::NodeId node_id0 = kv::test::PrimaryNodeId;
|
||||
ccf::NodeId node_id1 = kv::test::FirstBackupNodeId;
|
||||
ccf::NodeId node_id2 = kv::test::SecondBackupNodeId;
|
||||
ccf::NodeId node_id0 = ccf::kv::test::PrimaryNodeId;
|
||||
ccf::NodeId node_id1 = ccf::kv::test::FirstBackupNodeId;
|
||||
ccf::NodeId node_id2 = ccf::kv::test::SecondBackupNodeId;
|
||||
|
||||
auto kv_store0 = std::make_shared<Store>(node_id0);
|
||||
auto kv_store1 = std::make_shared<Store>(node_id1);
|
||||
|
@ -359,12 +359,13 @@ DOCTEST_TEST_CASE(
|
|||
DOCTEST_INFO("Try to replicate on a follower, and fail");
|
||||
std::vector<uint8_t> entry = {1, 2, 3};
|
||||
auto data = std::make_shared<std::vector<uint8_t>>(entry);
|
||||
auto hooks = std::make_shared<kv::ConsensusHookPtrs>();
|
||||
auto hooks = std::make_shared<ccf::kv::ConsensusHookPtrs>();
|
||||
DOCTEST_REQUIRE_FALSE(
|
||||
r1.replicate(kv::BatchVector{{1, data, true, hooks}}, 1));
|
||||
r1.replicate(ccf::kv::BatchVector{{1, data, true, hooks}}, 1));
|
||||
|
||||
DOCTEST_INFO("Tell the leader to replicate a message");
|
||||
DOCTEST_REQUIRE(r0.replicate(kv::BatchVector{{1, data, true, hooks}}, 1));
|
||||
DOCTEST_REQUIRE(
|
||||
r0.replicate(ccf::kv::BatchVector{{1, data, true, hooks}}, 1));
|
||||
DOCTEST_REQUIRE(r0.ledger->ledger.size() == 1);
|
||||
|
||||
// The test ledger adds its own header. Confirm that the expected data is
|
||||
|
@ -411,9 +412,9 @@ DOCTEST_TEST_CASE(
|
|||
|
||||
DOCTEST_TEST_CASE("Multiple nodes late join" * doctest::test_suite("multiple"))
|
||||
{
|
||||
ccf::NodeId node_id0 = kv::test::PrimaryNodeId;
|
||||
ccf::NodeId node_id1 = kv::test::FirstBackupNodeId;
|
||||
ccf::NodeId node_id2 = kv::test::SecondBackupNodeId;
|
||||
ccf::NodeId node_id0 = ccf::kv::test::PrimaryNodeId;
|
||||
ccf::NodeId node_id1 = ccf::kv::test::FirstBackupNodeId;
|
||||
ccf::NodeId node_id2 = ccf::kv::test::SecondBackupNodeId;
|
||||
|
||||
auto kv_store0 = std::make_shared<Store>(node_id0);
|
||||
auto kv_store1 = std::make_shared<Store>(node_id1);
|
||||
|
@ -475,8 +476,9 @@ DOCTEST_TEST_CASE("Multiple nodes late join" * doctest::test_suite("multiple"))
|
|||
|
||||
std::vector<uint8_t> first_entry = {1, 2, 3};
|
||||
auto data = std::make_shared<std::vector<uint8_t>>(first_entry);
|
||||
auto hooks = std::make_shared<kv::ConsensusHookPtrs>();
|
||||
DOCTEST_REQUIRE(r0.replicate(kv::BatchVector{{1, data, true, hooks}}, 1));
|
||||
auto hooks = std::make_shared<ccf::kv::ConsensusHookPtrs>();
|
||||
DOCTEST_REQUIRE(
|
||||
r0.replicate(ccf::kv::BatchVector{{1, data, true, hooks}}, 1));
|
||||
r0.periodic(request_timeout);
|
||||
|
||||
DOCTEST_REQUIRE(
|
||||
|
@ -528,8 +530,8 @@ DOCTEST_TEST_CASE("Multiple nodes late join" * doctest::test_suite("multiple"))
|
|||
|
||||
DOCTEST_TEST_CASE("Recv append entries logic" * doctest::test_suite("multiple"))
|
||||
{
|
||||
ccf::NodeId node_id0 = kv::test::PrimaryNodeId;
|
||||
ccf::NodeId node_id1 = kv::test::FirstBackupNodeId;
|
||||
ccf::NodeId node_id0 = ccf::kv::test::PrimaryNodeId;
|
||||
ccf::NodeId node_id1 = ccf::kv::test::FirstBackupNodeId;
|
||||
|
||||
auto kv_store0 = std::make_shared<Store>(node_id0);
|
||||
auto kv_store1 = std::make_shared<Store>(node_id1);
|
||||
|
@ -548,7 +550,7 @@ DOCTEST_TEST_CASE("Recv append entries logic" * doctest::test_suite("multiple"))
|
|||
std::make_shared<aft::ChannelStubProxy>(),
|
||||
std::make_shared<aft::State>(node_id1),
|
||||
nullptr);
|
||||
auto hooks = std::make_shared<kv::ConsensusHookPtrs>();
|
||||
auto hooks = std::make_shared<ccf::kv::ConsensusHookPtrs>();
|
||||
|
||||
aft::Configuration::Nodes config0;
|
||||
config0[node_id0] = {};
|
||||
|
@ -586,8 +588,10 @@ DOCTEST_TEST_CASE("Recv append entries logic" * doctest::test_suite("multiple"))
|
|||
std::vector<uint8_t> second_entry = {2, 2, 2};
|
||||
auto data_2 = std::make_shared<std::vector<uint8_t>>(second_entry);
|
||||
|
||||
DOCTEST_REQUIRE(r0.replicate(kv::BatchVector{{1, data_1, true, hooks}}, 1));
|
||||
DOCTEST_REQUIRE(r0.replicate(kv::BatchVector{{2, data_2, true, hooks}}, 1));
|
||||
DOCTEST_REQUIRE(
|
||||
r0.replicate(ccf::kv::BatchVector{{1, data_1, true, hooks}}, 1));
|
||||
DOCTEST_REQUIRE(
|
||||
r0.replicate(ccf::kv::BatchVector{{2, data_2, true, hooks}}, 1));
|
||||
DOCTEST_REQUIRE(r0.ledger->ledger.size() == 2);
|
||||
r0.periodic(request_timeout);
|
||||
DOCTEST_REQUIRE(r0c->messages.size() == 1);
|
||||
|
@ -608,7 +612,8 @@ DOCTEST_TEST_CASE("Recv append entries logic" * doctest::test_suite("multiple"))
|
|||
{
|
||||
std::vector<uint8_t> third_entry = {3, 3, 3};
|
||||
auto data = std::make_shared<std::vector<uint8_t>>(third_entry);
|
||||
DOCTEST_REQUIRE(r0.replicate(kv::BatchVector{{3, data, true, hooks}}, 1));
|
||||
DOCTEST_REQUIRE(
|
||||
r0.replicate(ccf::kv::BatchVector{{3, data, true, hooks}}, 1));
|
||||
DOCTEST_REQUIRE(r0.ledger->ledger.size() == 3);
|
||||
|
||||
// Simulate that the append entries was not deserialised successfully
|
||||
|
@ -640,7 +645,8 @@ DOCTEST_TEST_CASE("Recv append entries logic" * doctest::test_suite("multiple"))
|
|||
{
|
||||
std::vector<uint8_t> fourth_entry = {4, 4, 4};
|
||||
auto data = std::make_shared<std::vector<uint8_t>>(fourth_entry);
|
||||
DOCTEST_REQUIRE(r0.replicate(kv::BatchVector{{4, data, true, hooks}}, 1));
|
||||
DOCTEST_REQUIRE(
|
||||
r0.replicate(ccf::kv::BatchVector{{4, data, true, hooks}}, 1));
|
||||
DOCTEST_REQUIRE(r0.ledger->ledger.size() == 4);
|
||||
r0.periodic(request_timeout);
|
||||
DOCTEST_REQUIRE(r0c->messages.size() == 1);
|
||||
|
@ -653,7 +659,8 @@ DOCTEST_TEST_CASE("Recv append entries logic" * doctest::test_suite("multiple"))
|
|||
{
|
||||
std::vector<uint8_t> fifth_entry = {5, 5, 5};
|
||||
auto data = std::make_shared<std::vector<uint8_t>>(fifth_entry);
|
||||
DOCTEST_REQUIRE(r0.replicate(kv::BatchVector{{5, data, true, hooks}}, 1));
|
||||
DOCTEST_REQUIRE(
|
||||
r0.replicate(ccf::kv::BatchVector{{5, data, true, hooks}}, 1));
|
||||
DOCTEST_REQUIRE(r0.ledger->ledger.size() == 5);
|
||||
r0.periodic(request_timeout);
|
||||
DOCTEST_REQUIRE(r0c->messages.size() == 1);
|
||||
|
@ -682,7 +689,8 @@ DOCTEST_TEST_CASE("Recv append entries logic" * doctest::test_suite("multiple"))
|
|||
{
|
||||
std::vector<uint8_t> entry_6 = {6, 6, 6};
|
||||
auto data = std::make_shared<std::vector<uint8_t>>(entry_6);
|
||||
DOCTEST_REQUIRE(r0.replicate(kv::BatchVector{{6, data, true, hooks}}, 1));
|
||||
DOCTEST_REQUIRE(
|
||||
r0.replicate(ccf::kv::BatchVector{{6, data, true, hooks}}, 1));
|
||||
DOCTEST_REQUIRE(r0.ledger->ledger.size() == 6);
|
||||
}
|
||||
const auto last_correct_version = r0.ledger->ledger.size();
|
||||
|
@ -691,7 +699,8 @@ DOCTEST_TEST_CASE("Recv append entries logic" * doctest::test_suite("multiple"))
|
|||
{
|
||||
std::vector<uint8_t> entry_7 = {7, 7, 7};
|
||||
auto data = std::make_shared<std::vector<uint8_t>>(entry_7);
|
||||
DOCTEST_REQUIRE(r0.replicate(kv::BatchVector{{7, data, true, hooks}}, 1));
|
||||
DOCTEST_REQUIRE(
|
||||
r0.replicate(ccf::kv::BatchVector{{7, data, true, hooks}}, 1));
|
||||
DOCTEST_REQUIRE(r0.ledger->ledger.size() == 7);
|
||||
dead_branch = r0.ledger->ledger.back();
|
||||
}
|
||||
|
@ -712,7 +721,8 @@ DOCTEST_TEST_CASE("Recv append entries logic" * doctest::test_suite("multiple"))
|
|||
{
|
||||
std::vector<uint8_t> entry_7b = {7, 7, 'b'};
|
||||
auto data = std::make_shared<std::vector<uint8_t>>(entry_7b);
|
||||
DOCTEST_REQUIRE(r0.replicate(kv::BatchVector{{7, data, true, hooks}}, 4));
|
||||
DOCTEST_REQUIRE(
|
||||
r0.replicate(ccf::kv::BatchVector{{7, data, true, hooks}}, 4));
|
||||
DOCTEST_REQUIRE(r0.ledger->ledger.size() == 7);
|
||||
live_branch = r0.ledger->ledger.back();
|
||||
}
|
||||
|
@ -720,7 +730,8 @@ DOCTEST_TEST_CASE("Recv append entries logic" * doctest::test_suite("multiple"))
|
|||
{
|
||||
std::vector<uint8_t> entry_8 = {8, 8, 8};
|
||||
auto data = std::make_shared<std::vector<uint8_t>>(entry_8);
|
||||
DOCTEST_REQUIRE(r0.replicate(kv::BatchVector{{8, data, true, hooks}}, 4));
|
||||
DOCTEST_REQUIRE(
|
||||
r0.replicate(ccf::kv::BatchVector{{8, data, true, hooks}}, 4));
|
||||
DOCTEST_REQUIRE(r0.ledger->ledger.size() == 8);
|
||||
DOCTEST_REQUIRE(r0.ledger->ledger.size() > last_correct_version);
|
||||
}
|
||||
|
@ -771,9 +782,9 @@ DOCTEST_TEST_CASE("Exceed append entries limit")
|
|||
{
|
||||
ccf::logger::config::level() = LoggerLevel::INFO;
|
||||
|
||||
ccf::NodeId node_id0 = kv::test::PrimaryNodeId;
|
||||
ccf::NodeId node_id1 = kv::test::FirstBackupNodeId;
|
||||
ccf::NodeId node_id2 = kv::test::SecondBackupNodeId;
|
||||
ccf::NodeId node_id0 = ccf::kv::test::PrimaryNodeId;
|
||||
ccf::NodeId node_id1 = ccf::kv::test::FirstBackupNodeId;
|
||||
ccf::NodeId node_id2 = ccf::kv::test::SecondBackupNodeId;
|
||||
|
||||
auto kv_store0 = std::make_shared<Store>(node_id0);
|
||||
auto kv_store1 = std::make_shared<Store>(node_id1);
|
||||
|
@ -847,8 +858,9 @@ DOCTEST_TEST_CASE("Exceed append entries limit")
|
|||
|
||||
for (size_t i = 1; i <= num_big_entries; ++i)
|
||||
{
|
||||
auto hooks = std::make_shared<kv::ConsensusHookPtrs>();
|
||||
DOCTEST_REQUIRE(r0.replicate(kv::BatchVector{{i, data, true, hooks}}, 1));
|
||||
auto hooks = std::make_shared<ccf::kv::ConsensusHookPtrs>();
|
||||
DOCTEST_REQUIRE(
|
||||
r0.replicate(ccf::kv::BatchVector{{i, data, true, hooks}}, 1));
|
||||
const auto received_ae =
|
||||
dispatch_all_and_DOCTEST_CHECK<aft::AppendEntries>(
|
||||
nodes, node_id0, r0c->messages, [&i](const auto& msg) {
|
||||
|
@ -864,9 +876,9 @@ DOCTEST_TEST_CASE("Exceed append entries limit")
|
|||
|
||||
for (size_t i = num_big_entries + 1; i <= individual_entries; ++i)
|
||||
{
|
||||
auto hooks = std::make_shared<kv::ConsensusHookPtrs>();
|
||||
auto hooks = std::make_shared<ccf::kv::ConsensusHookPtrs>();
|
||||
DOCTEST_REQUIRE(
|
||||
r0.replicate(kv::BatchVector{{i, smaller_data, true, hooks}}, 1));
|
||||
r0.replicate(ccf::kv::BatchVector{{i, smaller_data, true, hooks}}, 1));
|
||||
dispatch_all(nodes, node_id0, r0c->messages);
|
||||
}
|
||||
|
||||
|
@ -925,8 +937,8 @@ DOCTEST_TEST_CASE(
|
|||
"Nodes only run for election when they should" *
|
||||
doctest::test_suite("multiple"))
|
||||
{
|
||||
ccf::NodeId node_id0 = kv::test::PrimaryNodeId;
|
||||
ccf::NodeId node_id1 = kv::test::FirstBackupNodeId;
|
||||
ccf::NodeId node_id0 = ccf::kv::test::PrimaryNodeId;
|
||||
ccf::NodeId node_id1 = ccf::kv::test::FirstBackupNodeId;
|
||||
|
||||
auto kv_store0 = std::make_shared<Store>(node_id0);
|
||||
auto kv_store1 = std::make_shared<Store>(node_id1);
|
||||
|
|
|
@ -24,7 +24,7 @@ static const std::chrono::milliseconds election_timeout = election_timeout_;
|
|||
static const ccf::consensus::Configuration raft_settings{
|
||||
request_timeout_, election_timeout_, max_uncommitted_tx_count_};
|
||||
|
||||
static auto hooks = std::make_shared<kv::ConsensusHookPtrs>();
|
||||
static auto hooks = std::make_shared<ccf::kv::ConsensusHookPtrs>();
|
||||
|
||||
static aft::ChannelStubProxy* channel_stub_proxy(const TRaft& r)
|
||||
{
|
||||
|
|
|
@ -19,8 +19,8 @@ TEST_CASE("Advancing view history" * doctest::test_suite("viewhistory"))
|
|||
CHECK(history.view_at(3) == ViewHistory::InvalidView);
|
||||
CHECK(history.view_at(4) == ViewHistory::InvalidView);
|
||||
|
||||
CHECK(history.start_of_view(1) == kv::NoVersion);
|
||||
CHECK(history.end_of_view(1) == kv::NoVersion);
|
||||
CHECK(history.start_of_view(1) == ccf::kv::NoVersion);
|
||||
CHECK(history.end_of_view(1) == ccf::kv::NoVersion);
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -64,9 +64,9 @@ TEST_CASE("Advancing view history" * doctest::test_suite("viewhistory"))
|
|||
CHECK(history.start_of_view(2) == 3);
|
||||
CHECK(history.end_of_view(2) == 3);
|
||||
CHECK(history.start_of_view(3) == 4);
|
||||
CHECK(history.end_of_view(3) == kv::NoVersion);
|
||||
CHECK(history.start_of_view(4) == kv::NoVersion);
|
||||
CHECK(history.end_of_view(4) == kv::NoVersion);
|
||||
CHECK(history.end_of_view(3) == ccf::kv::NoVersion);
|
||||
CHECK(history.start_of_view(4) == ccf::kv::NoVersion);
|
||||
CHECK(history.end_of_view(4) == ccf::kv::NoVersion);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,14 +143,14 @@ TEST_CASE("Edge case view histories" * doctest::test_suite("viewhistory"))
|
|||
CHECK(history.view_at(4) == 4);
|
||||
|
||||
CHECK(history.start_of_view(4) == 2);
|
||||
CHECK(history.end_of_view(4) == kv::NoVersion);
|
||||
CHECK(history.end_of_view(4) == ccf::kv::NoVersion);
|
||||
|
||||
CHECK(history.start_of_view(1) == kv::NoVersion);
|
||||
CHECK(history.end_of_view(1) == kv::NoVersion);
|
||||
CHECK(history.start_of_view(2) == kv::NoVersion);
|
||||
CHECK(history.end_of_view(2) == kv::NoVersion);
|
||||
CHECK(history.start_of_view(3) == kv::NoVersion);
|
||||
CHECK(history.end_of_view(3) == kv::NoVersion);
|
||||
CHECK(history.start_of_view(1) == ccf::kv::NoVersion);
|
||||
CHECK(history.end_of_view(1) == ccf::kv::NoVersion);
|
||||
CHECK(history.start_of_view(2) == ccf::kv::NoVersion);
|
||||
CHECK(history.end_of_view(2) == ccf::kv::NoVersion);
|
||||
CHECK(history.start_of_view(3) == ccf::kv::NoVersion);
|
||||
CHECK(history.end_of_view(3) == ccf::kv::NoVersion);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,12 +168,12 @@ TEST_CASE("Initialised view histories" * doctest::test_suite("viewhistory"))
|
|||
|
||||
CHECK(history.start_of_view(1) == 2);
|
||||
CHECK(history.end_of_view(1) == 3);
|
||||
CHECK(history.start_of_view(2) == kv::NoVersion);
|
||||
CHECK(history.end_of_view(2) == kv::NoVersion);
|
||||
CHECK(history.start_of_view(2) == ccf::kv::NoVersion);
|
||||
CHECK(history.end_of_view(2) == ccf::kv::NoVersion);
|
||||
CHECK(history.start_of_view(3) == 4);
|
||||
CHECK(history.end_of_view(3) == 9);
|
||||
CHECK(history.start_of_view(4) == 10);
|
||||
CHECK(history.end_of_view(4) == kv::NoVersion);
|
||||
CHECK(history.end_of_view(4) == ccf::kv::NoVersion);
|
||||
|
||||
CHECK_THROWS(history.initialise({2, 1}));
|
||||
CHECK_THROWS(history.initialise({1, 2, 1}));
|
||||
|
@ -203,8 +203,8 @@ TEST_CASE("Initialised view histories" * doctest::test_suite("viewhistory"))
|
|||
CHECK(history.view_at(19) == 6);
|
||||
CHECK(history.view_at(20) == 6);
|
||||
|
||||
CHECK(history.start_of_view(1) == kv::NoVersion);
|
||||
CHECK(history.end_of_view(1) == kv::NoVersion);
|
||||
CHECK(history.start_of_view(1) == ccf::kv::NoVersion);
|
||||
CHECK(history.end_of_view(1) == ccf::kv::NoVersion);
|
||||
CHECK(history.start_of_view(3) == 3);
|
||||
CHECK(history.end_of_view(3) == 4);
|
||||
CHECK(history.start_of_view(4) == 5);
|
||||
|
@ -212,7 +212,7 @@ TEST_CASE("Initialised view histories" * doctest::test_suite("viewhistory"))
|
|||
CHECK(history.start_of_view(5) == 6);
|
||||
CHECK(history.end_of_view(5) == 11);
|
||||
CHECK(history.start_of_view(6) == 12);
|
||||
CHECK(history.end_of_view(6) == kv::NoVersion);
|
||||
CHECK(history.end_of_view(6) == ccf::kv::NoVersion);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,23 +234,28 @@ TEST_CASE(
|
|||
{
|
||||
INFO("Test that view history is correct");
|
||||
|
||||
REQUIRE(history.get_history_until(kv::NoVersion).size() == 0);
|
||||
REQUIRE(history.get_history_until(1) == std::vector<kv::Version>({1}));
|
||||
REQUIRE(history.get_history_until(2) == std::vector<kv::Version>({1, 2}));
|
||||
REQUIRE(history.get_history_until(3) == std::vector<kv::Version>({1, 2}));
|
||||
REQUIRE(history.get_history_until(4) == std::vector<kv::Version>({1, 2}));
|
||||
REQUIRE(history.get_history_until(ccf::kv::NoVersion).size() == 0);
|
||||
REQUIRE(history.get_history_until(1) == std::vector<ccf::kv::Version>({1}));
|
||||
REQUIRE(
|
||||
history.get_history_until(5) == std::vector<kv::Version>({1, 2, 5, 5}));
|
||||
history.get_history_until(2) == std::vector<ccf::kv::Version>({1, 2}));
|
||||
REQUIRE(
|
||||
history.get_history_until(9) == std::vector<kv::Version>({1, 2, 5, 5}));
|
||||
history.get_history_until(3) == std::vector<ccf::kv::Version>({1, 2}));
|
||||
REQUIRE(
|
||||
history.get_history_until(4) == std::vector<ccf::kv::Version>({1, 2}));
|
||||
REQUIRE(
|
||||
history.get_history_until(5) ==
|
||||
std::vector<ccf::kv::Version>({1, 2, 5, 5}));
|
||||
REQUIRE(
|
||||
history.get_history_until(9) ==
|
||||
std::vector<ccf::kv::Version>({1, 2, 5, 5}));
|
||||
REQUIRE(
|
||||
history.get_history_until(10) ==
|
||||
std::vector<kv::Version>({1, 2, 5, 5, 10}));
|
||||
std::vector<ccf::kv::Version>({1, 2, 5, 5, 10}));
|
||||
REQUIRE(
|
||||
history.get_history_until(11) ==
|
||||
std::vector<kv::Version>({1, 2, 5, 5, 10}));
|
||||
std::vector<ccf::kv::Version>({1, 2, 5, 5, 10}));
|
||||
REQUIRE(
|
||||
history.get_history_until() ==
|
||||
std::vector<kv::Version>({1, 2, 5, 5, 10}));
|
||||
std::vector<ccf::kv::Version>({1, 2, 5, 5, 10}));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,8 +25,9 @@ namespace consensus
|
|||
*/
|
||||
static std::vector<uint8_t> get_entry(const uint8_t*& data, size_t& size)
|
||||
{
|
||||
auto header = serialized::peek<kv::SerialisedEntryHeader>(data, size);
|
||||
size_t entry_size = kv::serialised_entry_header_size + header.size;
|
||||
auto header =
|
||||
serialized::peek<ccf::kv::SerialisedEntryHeader>(data, size);
|
||||
size_t entry_size = ccf::kv::serialised_entry_header_size + header.size;
|
||||
std::vector<uint8_t> entry(data, data + entry_size);
|
||||
serialized::skip(data, size, entry_size);
|
||||
return entry;
|
||||
|
@ -51,8 +52,8 @@ namespace consensus
|
|||
void put_entry(
|
||||
const std::vector<uint8_t>& entry,
|
||||
bool globally_committable,
|
||||
kv::Term term,
|
||||
kv::Version index)
|
||||
ccf::kv::Term term,
|
||||
ccf::kv::Version index)
|
||||
{
|
||||
put_entry(entry.data(), entry.size(), globally_committable, term, index);
|
||||
}
|
||||
|
@ -72,8 +73,8 @@ namespace consensus
|
|||
const uint8_t* data,
|
||||
size_t size,
|
||||
bool globally_committable,
|
||||
kv::Term term,
|
||||
kv::Version index)
|
||||
ccf::kv::Term term,
|
||||
ccf::kv::Version index)
|
||||
{
|
||||
serializer::ByteRange byte_range = {data, size};
|
||||
RINGBUFFER_WRITE_MESSAGE(
|
||||
|
@ -90,7 +91,8 @@ namespace consensus
|
|||
*/
|
||||
static void skip_entry(const uint8_t*& data, size_t& size)
|
||||
{
|
||||
auto header = serialized::read<kv::SerialisedEntryHeader>(data, size);
|
||||
auto header =
|
||||
serialized::read<ccf::kv::SerialisedEntryHeader>(data, size);
|
||||
serialized::skip(data, size, header.size);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@ struct CollisionHash
|
|||
}
|
||||
};
|
||||
|
||||
using K = kv::serialisers::SerialisedEntry;
|
||||
using V = kv::serialisers::SerialisedEntry;
|
||||
using K = ccf::kv::serialisers::SerialisedEntry;
|
||||
using V = ccf::kv::serialisers::SerialisedEntry;
|
||||
constexpr static size_t max_key_value_size = 128;
|
||||
|
||||
namespace map
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
namespace kv
|
||||
namespace ccf::kv
|
||||
{
|
||||
class CommittableTx;
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ namespace ccf
|
|||
}
|
||||
|
||||
std::unique_ptr<AuthnIdentity> AllOfAuthnPolicy::authenticate(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const std::shared_ptr<ccf::RpcContext>& ctx,
|
||||
std::string& error_reason)
|
||||
{
|
||||
|
|
|
@ -104,7 +104,7 @@ namespace ccf
|
|||
UserCertAuthnPolicy::~UserCertAuthnPolicy() = default;
|
||||
|
||||
std::unique_ptr<AuthnIdentity> UserCertAuthnPolicy::authenticate(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const std::shared_ptr<ccf::RpcContext>& ctx,
|
||||
std::string& error_reason)
|
||||
{
|
||||
|
@ -141,7 +141,7 @@ namespace ccf
|
|||
MemberCertAuthnPolicy::~MemberCertAuthnPolicy() = default;
|
||||
|
||||
std::unique_ptr<AuthnIdentity> MemberCertAuthnPolicy::authenticate(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const std::shared_ptr<ccf::RpcContext>& ctx,
|
||||
std::string& error_reason)
|
||||
{
|
||||
|
@ -167,7 +167,7 @@ namespace ccf
|
|||
}
|
||||
|
||||
std::unique_ptr<AuthnIdentity> NodeCertAuthnPolicy::authenticate(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const std::shared_ptr<ccf::RpcContext>& ctx,
|
||||
std::string& error_reason)
|
||||
{
|
||||
|
|
|
@ -300,7 +300,7 @@ namespace ccf
|
|||
MemberCOSESign1AuthnPolicy::~MemberCOSESign1AuthnPolicy() = default;
|
||||
|
||||
std::unique_ptr<AuthnIdentity> MemberCOSESign1AuthnPolicy::authenticate(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const std::shared_ptr<ccf::RpcContext>& ctx,
|
||||
std::string& error_reason)
|
||||
{
|
||||
|
@ -406,7 +406,7 @@ namespace ccf
|
|||
"Signer must be a member identity registered with this service."}});
|
||||
|
||||
std::unique_ptr<AuthnIdentity> ActiveMemberCOSESign1AuthnPolicy::authenticate(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const std::shared_ptr<ccf::RpcContext>& ctx,
|
||||
std::string& error_reason)
|
||||
{
|
||||
|
@ -441,7 +441,7 @@ namespace ccf
|
|||
|
||||
std::unique_ptr<UserCOSESign1AuthnIdentity> UserCOSESign1AuthnPolicy::
|
||||
_authenticate(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const std::shared_ptr<ccf::RpcContext>& ctx,
|
||||
std::string& error_reason)
|
||||
{
|
||||
|
@ -502,7 +502,7 @@ namespace ccf
|
|||
}
|
||||
|
||||
std::unique_ptr<AuthnIdentity> UserCOSESign1AuthnPolicy::authenticate(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const std::shared_ptr<ccf::RpcContext>& ctx,
|
||||
std::string& error_reason)
|
||||
{
|
||||
|
@ -533,7 +533,7 @@ namespace ccf
|
|||
"Signer must be a user identity registered with this service."}});
|
||||
|
||||
std::unique_ptr<AuthnIdentity> TypedUserCOSESign1AuthnPolicy::authenticate(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const std::shared_ptr<ccf::RpcContext>& ctx,
|
||||
std::string& error_reason)
|
||||
{
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
namespace ccf
|
||||
{
|
||||
std::unique_ptr<AuthnIdentity> EmptyAuthnPolicy::authenticate(
|
||||
kv::ReadOnlyTx&, const std::shared_ptr<ccf::RpcContext>&, std::string&)
|
||||
ccf::kv::ReadOnlyTx&, const std::shared_ptr<ccf::RpcContext>&, std::string&)
|
||||
{
|
||||
return std::make_unique<EmptyAuthnIdentity>();
|
||||
}
|
||||
|
|
|
@ -115,7 +115,7 @@ namespace ccf
|
|||
JwtAuthnPolicy::~JwtAuthnPolicy() = default;
|
||||
|
||||
std::unique_ptr<AuthnIdentity> JwtAuthnPolicy::authenticate(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const std::shared_ptr<ccf::RpcContext>& ctx,
|
||||
std::string& error_reason)
|
||||
{
|
||||
|
|
|
@ -115,7 +115,7 @@ namespace ccf
|
|||
}
|
||||
|
||||
ApiResult BaseEndpointRegistry::generate_openapi_document_v1(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const std::string& title,
|
||||
const std::string& description,
|
||||
const std::string& document_version,
|
||||
|
@ -136,7 +136,7 @@ namespace ccf
|
|||
}
|
||||
|
||||
ApiResult BaseEndpointRegistry::get_quote_for_this_node_v1(
|
||||
kv::ReadOnlyTx& tx, QuoteInfo& quote_info)
|
||||
ccf::kv::ReadOnlyTx& tx, QuoteInfo& quote_info)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -175,7 +175,7 @@ namespace ccf
|
|||
}
|
||||
|
||||
ApiResult BaseEndpointRegistry::get_quotes_for_all_trusted_nodes_v1(
|
||||
kv::ReadOnlyTx& tx, std::map<NodeId, QuoteInfo>& quotes)
|
||||
ccf::kv::ReadOnlyTx& tx, std::map<NodeId, QuoteInfo>& quotes)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -230,7 +230,7 @@ namespace ccf
|
|||
}
|
||||
|
||||
ApiResult BaseEndpointRegistry::get_user_data_v1(
|
||||
kv::ReadOnlyTx& tx, const UserId& user_id, nlohmann::json& user_data)
|
||||
ccf::kv::ReadOnlyTx& tx, const UserId& user_id, nlohmann::json& user_data)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -252,7 +252,9 @@ namespace ccf
|
|||
}
|
||||
|
||||
ApiResult BaseEndpointRegistry::get_member_data_v1(
|
||||
kv::ReadOnlyTx& tx, const MemberId& member_id, nlohmann::json& member_data)
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const MemberId& member_id,
|
||||
nlohmann::json& member_data)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -274,7 +276,9 @@ namespace ccf
|
|||
}
|
||||
|
||||
ApiResult BaseEndpointRegistry::get_user_cert_v1(
|
||||
kv::ReadOnlyTx& tx, const UserId& user_id, ccf::crypto::Pem& user_cert_pem)
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const UserId& user_id,
|
||||
ccf::crypto::Pem& user_cert_pem)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -296,7 +300,7 @@ namespace ccf
|
|||
}
|
||||
|
||||
ApiResult BaseEndpointRegistry::get_member_cert_v1(
|
||||
kv::ReadOnlyTx& tx,
|
||||
ccf::kv::ReadOnlyTx& tx,
|
||||
const MemberId& member_id,
|
||||
ccf::crypto::Pem& member_cert_pem)
|
||||
{
|
||||
|
|
|
@ -304,7 +304,8 @@ namespace ccf::endpoints
|
|||
default_endpoint = std::move(tmp);
|
||||
}
|
||||
|
||||
void EndpointRegistry::build_api(nlohmann::json& document, kv::ReadOnlyTx&)
|
||||
void EndpointRegistry::build_api(
|
||||
nlohmann::json& document, ccf::kv::ReadOnlyTx&)
|
||||
{
|
||||
// Add common components:
|
||||
// - Descriptions of each kind of forwarding
|
||||
|
@ -389,7 +390,7 @@ namespace ccf::endpoints
|
|||
void EndpointRegistry::init_handlers() {}
|
||||
|
||||
EndpointDefinitionPtr EndpointRegistry::find_endpoint(
|
||||
kv::Tx&, ccf::RpcContext& rpc_ctx)
|
||||
ccf::kv::Tx&, ccf::RpcContext& rpc_ctx)
|
||||
{
|
||||
auto method = rpc_ctx.get_method();
|
||||
auto endpoints_for_exact_method = fully_qualified_endpoints.find(method);
|
||||
|
@ -497,7 +498,7 @@ namespace ccf::endpoints
|
|||
}
|
||||
|
||||
std::set<RESTVerb> EndpointRegistry::get_allowed_verbs(
|
||||
kv::Tx& tx, const ccf::RpcContext& rpc_ctx)
|
||||
ccf::kv::Tx& tx, const ccf::RpcContext& rpc_ctx)
|
||||
{
|
||||
auto method = rpc_ctx.get_method();
|
||||
|
||||
|
@ -555,12 +556,12 @@ namespace ccf::endpoints
|
|||
// Default implementation does nothing
|
||||
void EndpointRegistry::tick(std::chrono::milliseconds) {}
|
||||
|
||||
void EndpointRegistry::set_consensus(kv::Consensus* c)
|
||||
void EndpointRegistry::set_consensus(ccf::kv::Consensus* c)
|
||||
{
|
||||
consensus = c;
|
||||
}
|
||||
|
||||
void EndpointRegistry::set_history(kv::TxHistory* h)
|
||||
void EndpointRegistry::set_history(ccf::kv::TxHistory* h)
|
||||
{
|
||||
history = h;
|
||||
}
|
||||
|
|
|
@ -187,8 +187,8 @@ namespace ccf
|
|||
};
|
||||
}
|
||||
|
||||
// Note: For now, only command endpoints (i.e. with no kv::Tx) support gRPC
|
||||
// server streaming.
|
||||
// Note: For now, only command endpoints (i.e. with no ccf::kv::Tx) support
|
||||
// gRPC server streaming.
|
||||
template <typename In, typename Out>
|
||||
endpoints::CommandEndpointFunction grpc_command_unary_stream_adapter(
|
||||
const GrpcCommandUnaryStreamEndpoint<In, Out>& f)
|
||||
|
|
|
@ -288,12 +288,13 @@ namespace asynchost
|
|||
total_len = sizeof(positions_offset_header_t);
|
||||
auto len = total_file_size - total_len;
|
||||
|
||||
kv::SerialisedEntryHeader entry_header = {};
|
||||
ccf::kv::SerialisedEntryHeader entry_header = {};
|
||||
size_t current_idx = start_idx;
|
||||
while (len >= kv::serialised_entry_header_size)
|
||||
while (len >= ccf::kv::serialised_entry_header_size)
|
||||
{
|
||||
if (
|
||||
fread(&entry_header, kv::serialised_entry_header_size, 1, file) !=
|
||||
fread(
|
||||
&entry_header, ccf::kv::serialised_entry_header_size, 1, file) !=
|
||||
1)
|
||||
{
|
||||
LOG_FAIL_FMT(
|
||||
|
@ -303,7 +304,7 @@ namespace asynchost
|
|||
return;
|
||||
}
|
||||
|
||||
len -= kv::serialised_entry_header_size;
|
||||
len -= ccf::kv::serialised_entry_header_size;
|
||||
|
||||
const auto& entry_size = entry_header.size;
|
||||
if (len < entry_size)
|
||||
|
@ -330,7 +331,7 @@ namespace asynchost
|
|||
|
||||
current_idx++;
|
||||
positions.push_back(total_len);
|
||||
total_len += (kv::serialised_entry_header_size + entry_size);
|
||||
total_len += (ccf::kv::serialised_entry_header_size + entry_size);
|
||||
}
|
||||
completed = false;
|
||||
}
|
||||
|
@ -1297,9 +1298,10 @@ namespace asynchost
|
|||
TimeBoundLogger log_if_slow(fmt::format(
|
||||
"Writing ledger entry - {} bytes, committable={}", size, committable));
|
||||
|
||||
auto header = serialized::peek<kv::SerialisedEntryHeader>(data, size);
|
||||
auto header =
|
||||
serialized::peek<ccf::kv::SerialisedEntryHeader>(data, size);
|
||||
|
||||
if (header.flags & kv::EntryFlags::FORCE_LEDGER_CHUNK_BEFORE)
|
||||
if (header.flags & ccf::kv::EntryFlags::FORCE_LEDGER_CHUNK_BEFORE)
|
||||
{
|
||||
LOG_TRACE_FMT(
|
||||
"Forcing ledger chunk before entry as required by the entry header "
|
||||
|
@ -1314,7 +1316,7 @@ namespace asynchost
|
|||
}
|
||||
|
||||
bool force_chunk_after =
|
||||
header.flags & kv::EntryFlags::FORCE_LEDGER_CHUNK_AFTER;
|
||||
header.flags & ccf::kv::EntryFlags::FORCE_LEDGER_CHUNK_AFTER;
|
||||
if (force_chunk_after)
|
||||
{
|
||||
if (!committable)
|
||||
|
|
|
@ -149,12 +149,12 @@ void verify_framed_entries_range(
|
|||
const uint8_t* data = &framed_entries[pos];
|
||||
size_t size = framed_entries.size() - pos;
|
||||
|
||||
auto header = serialized::read<kv::SerialisedEntryHeader>(data, size);
|
||||
auto header = serialized::read<ccf::kv::SerialisedEntryHeader>(data, size);
|
||||
auto header_size = header.size;
|
||||
REQUIRE(header_size == sizeof(TestLedgerEntry));
|
||||
|
||||
REQUIRE(TestLedgerEntry(data, size).value() == idx);
|
||||
pos += kv::serialised_entry_header_size + sizeof(TestLedgerEntry);
|
||||
pos += ccf::kv::serialised_entry_header_size + sizeof(TestLedgerEntry);
|
||||
idx++;
|
||||
}
|
||||
|
||||
|
@ -169,7 +169,7 @@ void read_entry_from_ledger(Ledger& ledger, size_t idx)
|
|||
auto& entry = framed_entry->data;
|
||||
const uint8_t* data = entry.data();
|
||||
auto size = entry.size();
|
||||
auto header = serialized::read<kv::SerialisedEntryHeader>(data, size);
|
||||
auto header = serialized::read<ccf::kv::SerialisedEntryHeader>(data, size);
|
||||
auto header_size = header.size;
|
||||
REQUIRE(header_size == sizeof(TestLedgerEntry));
|
||||
|
||||
|
@ -212,11 +212,11 @@ std::vector<uint8_t> make_ledger_entry(size_t idx, uint8_t header_flags = 0)
|
|||
{
|
||||
auto e = TestLedgerEntry(idx);
|
||||
std::vector<uint8_t> framed_entry(
|
||||
kv::serialised_entry_header_size + sizeof(TestLedgerEntry));
|
||||
ccf::kv::serialised_entry_header_size + sizeof(TestLedgerEntry));
|
||||
auto data = framed_entry.data();
|
||||
auto size = framed_entry.size();
|
||||
|
||||
kv::SerialisedEntryHeader header;
|
||||
ccf::kv::SerialisedEntryHeader header;
|
||||
header.set_size(sizeof(TestLedgerEntry));
|
||||
header.flags = header_flags;
|
||||
|
||||
|
@ -283,7 +283,7 @@ size_t get_entries_per_chunk(size_t chunk_threshold)
|
|||
// size of each entry
|
||||
return ceil(
|
||||
(static_cast<float>(chunk_threshold - sizeof(size_t))) /
|
||||
(kv::serialised_entry_header_size + sizeof(TestLedgerEntry)));
|
||||
(ccf::kv::serialised_entry_header_size + sizeof(TestLedgerEntry)));
|
||||
}
|
||||
|
||||
// Assumes that no entries have been written yet
|
||||
|
@ -385,7 +385,7 @@ TEST_CASE("Regular chunking")
|
|||
|
||||
// Write a new committable entry that forces a new ledger chunk
|
||||
is_committable = true;
|
||||
entry_submitter.write(is_committable, kv::FORCE_LEDGER_CHUNK_AFTER);
|
||||
entry_submitter.write(is_committable, ccf::kv::FORCE_LEDGER_CHUNK_AFTER);
|
||||
REQUIRE(number_of_files_in_ledger_dir() == number_of_files_after);
|
||||
|
||||
// Because of forcing a new chunk, the next entry will create a new chunk
|
||||
|
@ -396,7 +396,7 @@ TEST_CASE("Regular chunking")
|
|||
REQUIRE(number_of_files_in_ledger_dir() == number_of_files_after + 1);
|
||||
|
||||
is_committable = true;
|
||||
entry_submitter.write(is_committable, kv::FORCE_LEDGER_CHUNK_BEFORE);
|
||||
entry_submitter.write(is_committable, ccf::kv::FORCE_LEDGER_CHUNK_BEFORE);
|
||||
// A new chunk is created before, as the entry is committable and forced
|
||||
REQUIRE(number_of_files_in_ledger_dir() == number_of_files_after + 2);
|
||||
}
|
||||
|
@ -1078,7 +1078,7 @@ void corrupt_ledger_file(
|
|||
else if (corrupt_first_hdr)
|
||||
{
|
||||
REQUIRE(fread(&table_offset, sizeof(table_offset), 1, file) == 1);
|
||||
kv::SerialisedEntryHeader entry_header = {.size = 0xffffffff};
|
||||
ccf::kv::SerialisedEntryHeader entry_header = {.size = 0xffffffff};
|
||||
fwrite(&entry_header, sizeof(entry_header), 1, file);
|
||||
}
|
||||
else if (corrupt_last_entry)
|
||||
|
@ -1087,7 +1087,7 @@ void corrupt_ledger_file(
|
|||
std::vector<uint8_t> last_entry = {};
|
||||
while (true)
|
||||
{
|
||||
kv::SerialisedEntryHeader entry_header = {};
|
||||
ccf::kv::SerialisedEntryHeader entry_header = {};
|
||||
if (fread(&entry_header, sizeof(entry_header), 1, file) != 1)
|
||||
{
|
||||
break;
|
||||
|
@ -1396,7 +1396,7 @@ TEST_CASE("Chunking according to entry header flag")
|
|||
INFO("Write an entry with the ledger chunking after header flag enabled");
|
||||
{
|
||||
entry_submitter.write(
|
||||
is_committable, kv::EntryFlags::FORCE_LEDGER_CHUNK_AFTER);
|
||||
is_committable, ccf::kv::EntryFlags::FORCE_LEDGER_CHUNK_AFTER);
|
||||
|
||||
REQUIRE(number_of_files_in_ledger_dir() == 1);
|
||||
|
||||
|
@ -1419,7 +1419,7 @@ TEST_CASE("Chunking according to entry header flag")
|
|||
{
|
||||
auto ledger_files_count = number_of_files_in_ledger_dir();
|
||||
entry_submitter.write(
|
||||
is_committable, kv::EntryFlags::FORCE_LEDGER_CHUNK_BEFORE);
|
||||
is_committable, ccf::kv::EntryFlags::FORCE_LEDGER_CHUNK_BEFORE);
|
||||
|
||||
// Forcing a new chunk before creating a new chunk to store this entry
|
||||
REQUIRE(number_of_files_in_ledger_dir() == ledger_files_count + 1);
|
||||
|
|
|
@ -19,15 +19,15 @@ namespace ccf::indexing
|
|||
historical_cache(sc)
|
||||
{}
|
||||
|
||||
kv::ReadOnlyStorePtr deserialise_transaction(
|
||||
ccf::kv::ReadOnlyStorePtr deserialise_transaction(
|
||||
ccf::SeqNo seqno, const uint8_t* data, size_t size) override
|
||||
{
|
||||
kv::ApplyResult result;
|
||||
ccf::kv::ApplyResult result;
|
||||
ccf::ClaimsDigest claims_digest;
|
||||
bool has_commit_evidence;
|
||||
auto store = historical_cache->deserialise_ledger_entry(
|
||||
seqno, data, size, result, claims_digest, has_commit_evidence);
|
||||
if (store != nullptr && result != kv::ApplyResult::FAIL)
|
||||
if (store != nullptr && result != ccf::kv::ApplyResult::FAIL)
|
||||
{
|
||||
return store;
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ namespace ccf::indexing
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<kv::ReadOnlyStorePtr> fetch_transactions(
|
||||
std::vector<ccf::kv::ReadOnlyStorePtr> fetch_transactions(
|
||||
const SeqNoCollection& seqnos) override
|
||||
{
|
||||
const ccf::historical::CompoundHandle handle{
|
||||
|
|
|
@ -436,7 +436,9 @@ namespace ccf::indexing::strategies
|
|||
size_t max_buckets_) :
|
||||
VisitEachEntryInMap(map_name_, "SeqnosByKey")
|
||||
{
|
||||
if (kv::get_security_domain(map_name_) != kv::SecurityDomain::PUBLIC)
|
||||
if (
|
||||
ccf::kv::get_security_domain(map_name_) !=
|
||||
ccf::kv::SecurityDomain::PUBLIC)
|
||||
{
|
||||
throw std::logic_error(fmt::format(
|
||||
"This Strategy ({}) is currently only implemented for public tables, "
|
||||
|
|
|
@ -14,12 +14,12 @@ namespace ccf::indexing::strategies
|
|||
{}
|
||||
|
||||
void VisitEachEntryInMap::handle_committed_transaction(
|
||||
const ccf::TxID& tx_id, const kv::ReadOnlyStorePtr& store)
|
||||
const ccf::TxID& tx_id, const ccf::kv::ReadOnlyStorePtr& store)
|
||||
{
|
||||
// NB: Get an untyped view over the map with the same name. This saves
|
||||
// deserialisation here, where we hand on the raw key and value.
|
||||
auto tx = store->create_read_only_tx();
|
||||
auto handle = tx.ro<kv::untyped::Map>(map_name);
|
||||
auto handle = tx.ro<ccf::kv::untyped::Map>(map_name);
|
||||
|
||||
handle->foreach([this, &tx_id](const auto& k, const auto& v) {
|
||||
visit_entry(tx_id, k, v);
|
||||
|
|
|
@ -8,16 +8,16 @@
|
|||
// Needed by TestTransactionFetcher
|
||||
#include "kv/test/null_encryptor.h"
|
||||
|
||||
using MapA = kv::Map<std::string, std::string>;
|
||||
using MapA = ccf::kv::Map<std::string, std::string>;
|
||||
static MapA map_a("public:map_a");
|
||||
|
||||
using MapB = kv::Map<size_t, size_t>;
|
||||
using MapB = ccf::kv::Map<size_t, size_t>;
|
||||
static MapB map_b("public:map_b");
|
||||
|
||||
using ValueA = kv::Value<std::string>;
|
||||
using ValueA = ccf::kv::Value<std::string>;
|
||||
static ValueA value_a("public:value_a");
|
||||
|
||||
using SetA = kv::Set<std::string>;
|
||||
using SetA = ccf::kv::Set<std::string>;
|
||||
static SetA set_a("public:set_a");
|
||||
|
||||
static const std::chrono::milliseconds step_time(10);
|
||||
|
@ -25,16 +25,16 @@ static const std::chrono::milliseconds step_time(10);
|
|||
class TestTransactionFetcher : public ccf::indexing::TransactionFetcher
|
||||
{
|
||||
public:
|
||||
std::shared_ptr<kv::NullTxEncryptor> encryptor =
|
||||
std::make_shared<kv::NullTxEncryptor>();
|
||||
std::shared_ptr<ccf::kv::NullTxEncryptor> encryptor =
|
||||
std::make_shared<ccf::kv::NullTxEncryptor>();
|
||||
|
||||
ccf::SeqNoCollection requested;
|
||||
std::unordered_map<ccf::SeqNo, kv::ReadOnlyStorePtr> fetched_stores;
|
||||
std::unordered_map<ccf::SeqNo, ccf::kv::ReadOnlyStorePtr> fetched_stores;
|
||||
|
||||
kv::ReadOnlyStorePtr deserialise_transaction(
|
||||
ccf::kv::ReadOnlyStorePtr deserialise_transaction(
|
||||
ccf::SeqNo seqno, const uint8_t* data, size_t size)
|
||||
{
|
||||
auto store = std::make_shared<kv::Store>(
|
||||
auto store = std::make_shared<ccf::kv::Store>(
|
||||
false /* Do not start from very first seqno */,
|
||||
true /* Make use of historical secrets */);
|
||||
|
||||
|
@ -48,7 +48,7 @@ public:
|
|||
}
|
||||
|
||||
auto result = exec->apply();
|
||||
if (result == kv::ApplyResult::FAIL)
|
||||
if (result == ccf::kv::ApplyResult::FAIL)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -56,10 +56,10 @@ public:
|
|||
return store;
|
||||
}
|
||||
|
||||
std::vector<kv::ReadOnlyStorePtr> fetch_transactions(
|
||||
std::vector<ccf::kv::ReadOnlyStorePtr> fetch_transactions(
|
||||
const ccf::SeqNoCollection& seqnos)
|
||||
{
|
||||
std::vector<kv::ReadOnlyStorePtr> stores;
|
||||
std::vector<ccf::kv::ReadOnlyStorePtr> stores;
|
||||
|
||||
for (auto seqno : seqnos)
|
||||
{
|
||||
|
@ -87,11 +87,11 @@ class AllCommittableWrapper : public TConsensus
|
|||
public:
|
||||
using TConsensus::TConsensus;
|
||||
|
||||
bool replicate(const kv::BatchVector& entries_, ccf::View view) override
|
||||
bool replicate(const ccf::kv::BatchVector& entries_, ccf::View view) override
|
||||
{
|
||||
// Rather than building a history that produces real signatures, we just
|
||||
// overwrite the entries here to say that everything is committable
|
||||
kv::BatchVector entries(entries_);
|
||||
ccf::kv::BatchVector entries(entries_);
|
||||
for (auto& [seqno, data, committable, hooks] : entries)
|
||||
{
|
||||
committable = true;
|
||||
|
@ -101,7 +101,8 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
using AllCommittableConsensus = AllCommittableWrapper<kv::test::StubConsensus>;
|
||||
using AllCommittableConsensus =
|
||||
AllCommittableWrapper<ccf::kv::test::StubConsensus>;
|
||||
|
||||
using ExpectedSeqNos = std::set<ccf::SeqNo>;
|
||||
|
||||
|
@ -161,7 +162,7 @@ static inline bool check_seqnos(
|
|||
return true;
|
||||
}
|
||||
|
||||
using Action = std::function<bool(size_t, kv::Tx&)>;
|
||||
using Action = std::function<bool(size_t, ccf::kv::Tx&)>;
|
||||
struct ActionDesc
|
||||
{
|
||||
ExpectedSeqNos& expected;
|
||||
|
@ -169,7 +170,7 @@ struct ActionDesc
|
|||
};
|
||||
|
||||
static inline bool create_transactions(
|
||||
kv::Store& kv_store,
|
||||
ccf::kv::Store& kv_store,
|
||||
const std::vector<ActionDesc>& actions,
|
||||
size_t count = ccf::indexing::Indexer::MAX_REQUESTABLE * 3)
|
||||
{
|
||||
|
@ -185,7 +186,7 @@ static inline bool create_transactions(
|
|||
}
|
||||
}
|
||||
|
||||
if (tx.commit() != kv::CommitResult::SUCCESS)
|
||||
if (tx.commit() != ccf::kv::CommitResult::SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -41,11 +41,11 @@ static std::vector<ActionDesc> create_actions(
|
|||
ExpectedSeqNos& seqnos_2)
|
||||
{
|
||||
std::vector<ActionDesc> actions;
|
||||
actions.push_back({seqnos_hello, [](size_t i, kv::Tx& tx) {
|
||||
actions.push_back({seqnos_hello, [](size_t i, ccf::kv::Tx& tx) {
|
||||
tx.wo(map_a)->put("hello", "value doesn't matter");
|
||||
return true;
|
||||
}});
|
||||
actions.push_back({seqnos_saluton, [](size_t i, kv::Tx& tx) {
|
||||
actions.push_back({seqnos_saluton, [](size_t i, ccf::kv::Tx& tx) {
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
tx.wo(map_a)->put("saluton", "value doesn't matter");
|
||||
|
@ -53,7 +53,7 @@ static std::vector<ActionDesc> create_actions(
|
|||
}
|
||||
return false;
|
||||
}});
|
||||
actions.push_back({seqnos_1, [](size_t i, kv::Tx& tx) {
|
||||
actions.push_back({seqnos_1, [](size_t i, ccf::kv::Tx& tx) {
|
||||
if (i % 3 == 0)
|
||||
{
|
||||
tx.wo(map_b)->put(1, 42);
|
||||
|
@ -61,7 +61,7 @@ static std::vector<ActionDesc> create_actions(
|
|||
}
|
||||
return false;
|
||||
}});
|
||||
actions.push_back({seqnos_2, [](size_t i, kv::Tx& tx) {
|
||||
actions.push_back({seqnos_2, [](size_t i, ccf::kv::Tx& tx) {
|
||||
if (i % 4 == 0)
|
||||
{
|
||||
tx.wo(map_b)->put(2, 42);
|
||||
|
@ -75,7 +75,7 @@ static std::vector<ActionDesc> create_actions(
|
|||
template <typename AA>
|
||||
void run_tests(
|
||||
const std::function<void()>& tick_until_caught_up,
|
||||
kv::Store& kv_store,
|
||||
ccf::kv::Store& kv_store,
|
||||
ccf::indexing::Indexer& indexer,
|
||||
ExpectedSeqNos& seqnos_hello,
|
||||
ExpectedSeqNos& seqnos_saluton,
|
||||
|
@ -172,7 +172,7 @@ void run_tests(
|
|||
// Uses stub classes to test just indexing logic in isolation
|
||||
TEST_CASE("basic indexing" * doctest::test_suite("indexing"))
|
||||
{
|
||||
kv::Store kv_store;
|
||||
ccf::kv::Store kv_store;
|
||||
|
||||
auto consensus = std::make_shared<AllCommittableConsensus>();
|
||||
kv_store.set_consensus(consensus);
|
||||
|
@ -180,7 +180,7 @@ TEST_CASE("basic indexing" * doctest::test_suite("indexing"))
|
|||
auto fetcher = std::make_shared<TestTransactionFetcher>();
|
||||
ccf::indexing::Indexer indexer(fetcher);
|
||||
|
||||
auto encryptor = std::make_shared<kv::NullTxEncryptor>();
|
||||
auto encryptor = std::make_shared<ccf::kv::NullTxEncryptor>();
|
||||
kv_store.set_encryptor(encryptor);
|
||||
|
||||
REQUIRE_THROWS(indexer.install_strategy(nullptr));
|
||||
|
@ -253,8 +253,8 @@ TEST_CASE("basic indexing" * doctest::test_suite("indexing"))
|
|||
index_b);
|
||||
}
|
||||
|
||||
kv::Version rekey(
|
||||
kv::Store& kv_store,
|
||||
ccf::kv::Version rekey(
|
||||
ccf::kv::Store& kv_store,
|
||||
const std::shared_ptr<ccf::LedgerSecrets>& ledger_secrets)
|
||||
{
|
||||
ccf::ShareManager share_manager(ledger_secrets);
|
||||
|
@ -262,7 +262,7 @@ kv::Version rekey(
|
|||
auto tx = kv_store.create_tx();
|
||||
auto new_ledger_secret = ccf::make_ledger_secret();
|
||||
share_manager.issue_recovery_shares(tx, new_ledger_secret);
|
||||
REQUIRE(tx.commit() == kv::CommitResult::SUCCESS);
|
||||
REQUIRE(tx.commit() == ccf::kv::CommitResult::SUCCESS);
|
||||
|
||||
auto tx_version = tx.commit_version();
|
||||
|
||||
|
@ -275,7 +275,7 @@ kv::Version rekey(
|
|||
}
|
||||
|
||||
aft::LedgerStubProxy* add_raft_consensus(
|
||||
std::shared_ptr<kv::Store> kv_store,
|
||||
std::shared_ptr<ccf::kv::Store> kv_store,
|
||||
std::shared_ptr<ccf::indexing::Indexer> indexer)
|
||||
{
|
||||
using TRaft = aft::Aft<aft::LedgerStubProxy>;
|
||||
|
@ -285,7 +285,7 @@ aft::LedgerStubProxy* add_raft_consensus(
|
|||
const ccf::consensus::Configuration settings{{"20ms"}, {"100ms"}};
|
||||
auto consensus = std::make_shared<AllCommittableRaftConsensus>(
|
||||
settings,
|
||||
std::make_unique<aft::Adaptor<kv::Store>>(kv_store),
|
||||
std::make_unique<aft::Adaptor<ccf::kv::Store>>(kv_store),
|
||||
std::make_unique<aft::LedgerStubProxy>(node_id),
|
||||
std::make_shared<aft::ChannelStubProxy>(),
|
||||
std::make_shared<aft::State>(node_id),
|
||||
|
@ -309,7 +309,7 @@ TEST_CASE_TEMPLATE(
|
|||
IndexA,
|
||||
LazyIndexA)
|
||||
{
|
||||
auto kv_store_p = std::make_shared<kv::Store>();
|
||||
auto kv_store_p = std::make_shared<ccf::kv::Store>();
|
||||
auto& kv_store = *kv_store_p;
|
||||
|
||||
auto ledger_secrets = std::make_shared<ccf::LedgerSecrets>();
|
||||
|
@ -350,7 +350,7 @@ TEST_CASE_TEMPLATE(
|
|||
member_info->put(member_id, {ccf::MemberStatus::ACTIVE});
|
||||
member_public_encryption_keys->put(
|
||||
member_id, ccf::crypto::make_rsa_key_pair()->public_key_pem());
|
||||
REQUIRE(tx.commit() == kv::CommitResult::SUCCESS);
|
||||
REQUIRE(tx.commit() == ccf::kv::CommitResult::SUCCESS);
|
||||
}
|
||||
|
||||
ExpectedSeqNos seqnos_hello, seqnos_saluton, seqnos_1, seqnos_2;
|
||||
|
@ -457,7 +457,7 @@ const auto max_multithread_run_time = 100s;
|
|||
TEST_CASE(
|
||||
"multi-threaded indexing - in memory" * doctest::test_suite("indexing"))
|
||||
{
|
||||
auto kv_store_p = std::make_shared<kv::Store>();
|
||||
auto kv_store_p = std::make_shared<ccf::kv::Store>();
|
||||
auto& kv_store = *kv_store_p;
|
||||
|
||||
auto ledger_secrets = std::make_shared<ccf::LedgerSecrets>();
|
||||
|
@ -501,7 +501,7 @@ TEST_CASE(
|
|||
member_info->put(member_id, {ccf::MemberStatus::ACTIVE});
|
||||
member_public_encryption_keys->put(
|
||||
member_id, ccf::crypto::make_rsa_key_pair()->public_key_pem());
|
||||
REQUIRE(tx.commit() == kv::CommitResult::SUCCESS);
|
||||
REQUIRE(tx.commit() == ccf::kv::CommitResult::SUCCESS);
|
||||
}
|
||||
|
||||
std::atomic<bool> finished = false;
|
||||
|
@ -528,7 +528,7 @@ TEST_CASE(
|
|||
tx.wo(map_b)->put(42, i);
|
||||
}
|
||||
|
||||
REQUIRE(tx.commit() == kv::CommitResult::SUCCESS);
|
||||
REQUIRE(tx.commit() == ccf::kv::CommitResult::SUCCESS);
|
||||
++i;
|
||||
std::this_thread::yield();
|
||||
}
|
||||
|
@ -661,19 +661,20 @@ TEST_CASE(
|
|||
|
||||
class MockTransactionFetcher : public ccf::indexing::TransactionFetcher
|
||||
{
|
||||
std::shared_ptr<kv::AbstractTxEncryptor> encryptor;
|
||||
std::shared_ptr<ccf::kv::AbstractTxEncryptor> encryptor;
|
||||
|
||||
public:
|
||||
aft::LedgerStubProxy* ledger;
|
||||
|
||||
MockTransactionFetcher(const std::shared_ptr<kv::AbstractTxEncryptor>& e) :
|
||||
MockTransactionFetcher(
|
||||
const std::shared_ptr<ccf::kv::AbstractTxEncryptor>& e) :
|
||||
encryptor(e)
|
||||
{}
|
||||
|
||||
kv::ReadOnlyStorePtr deserialise_transaction(
|
||||
ccf::kv::ReadOnlyStorePtr deserialise_transaction(
|
||||
ccf::SeqNo seqno, const uint8_t* data, size_t size) override
|
||||
{
|
||||
auto store = std::make_shared<kv::Store>(
|
||||
auto store = std::make_shared<ccf::kv::Store>(
|
||||
false /* Do not start from very first seqno */,
|
||||
true /* Make use of historical secrets */);
|
||||
|
||||
|
@ -687,7 +688,7 @@ public:
|
|||
}
|
||||
|
||||
auto result = exec->apply();
|
||||
if (result == kv::ApplyResult::FAIL)
|
||||
if (result == ccf::kv::ApplyResult::FAIL)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -695,10 +696,10 @@ public:
|
|||
return store;
|
||||
}
|
||||
|
||||
std::vector<kv::ReadOnlyStorePtr> fetch_transactions(
|
||||
std::vector<ccf::kv::ReadOnlyStorePtr> fetch_transactions(
|
||||
const ccf::SeqNoCollection& seqnos) override
|
||||
{
|
||||
std::vector<kv::ReadOnlyStorePtr> ret;
|
||||
std::vector<ccf::kv::ReadOnlyStorePtr> ret;
|
||||
|
||||
for (const auto& seqno : seqnos)
|
||||
{
|
||||
|
@ -723,7 +724,7 @@ TEST_CASE(
|
|||
INFO("Using seed: ", seed);
|
||||
srand(seed);
|
||||
|
||||
auto kv_store_p = std::make_shared<kv::Store>();
|
||||
auto kv_store_p = std::make_shared<ccf::kv::Store>();
|
||||
auto& kv_store = *kv_store_p;
|
||||
|
||||
auto ledger_secrets = std::make_shared<ccf::LedgerSecrets>();
|
||||
|
@ -790,7 +791,7 @@ TEST_CASE(
|
|||
member_info->put(member_id, {ccf::MemberStatus::ACTIVE});
|
||||
member_public_encryption_keys->put(
|
||||
member_id, ccf::crypto::make_rsa_key_pair()->public_key_pem());
|
||||
REQUIRE(tx.commit() == kv::CommitResult::SUCCESS);
|
||||
REQUIRE(tx.commit() == ccf::kv::CommitResult::SUCCESS);
|
||||
}
|
||||
|
||||
std::atomic<bool> all_submitted = false;
|
||||
|
@ -824,7 +825,7 @@ TEST_CASE(
|
|||
tx.wo(map_b)->put(42, i);
|
||||
}
|
||||
|
||||
REQUIRE(tx.commit() == kv::CommitResult::SUCCESS);
|
||||
REQUIRE(tx.commit() == ccf::kv::CommitResult::SUCCESS);
|
||||
++i;
|
||||
std::this_thread::yield();
|
||||
}
|
||||
|
|
|
@ -42,11 +42,11 @@ static std::vector<ActionDesc> create_actions(
|
|||
ExpectedSeqNos& seqnos_value)
|
||||
{
|
||||
std::vector<ActionDesc> actions;
|
||||
actions.push_back({seqnos_hello, [](size_t i, kv::Tx& tx) {
|
||||
actions.push_back({seqnos_hello, [](size_t i, ccf::kv::Tx& tx) {
|
||||
tx.wo(map_a)->put("hello", "value doesn't matter");
|
||||
return true;
|
||||
}});
|
||||
actions.push_back({seqnos_saluton, [](size_t i, kv::Tx& tx) {
|
||||
actions.push_back({seqnos_saluton, [](size_t i, ccf::kv::Tx& tx) {
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
tx.wo(map_a)->put("saluton", "value doesn't matter");
|
||||
|
@ -54,7 +54,7 @@ static std::vector<ActionDesc> create_actions(
|
|||
}
|
||||
return false;
|
||||
}});
|
||||
actions.push_back({seqnos_1, [](size_t i, kv::Tx& tx) {
|
||||
actions.push_back({seqnos_1, [](size_t i, ccf::kv::Tx& tx) {
|
||||
if (i % 3 == 0)
|
||||
{
|
||||
tx.wo(map_b)->put(1, 42);
|
||||
|
@ -62,7 +62,7 @@ static std::vector<ActionDesc> create_actions(
|
|||
}
|
||||
return false;
|
||||
}});
|
||||
actions.push_back({seqnos_2, [](size_t i, kv::Tx& tx) {
|
||||
actions.push_back({seqnos_2, [](size_t i, ccf::kv::Tx& tx) {
|
||||
if (i % 4 == 0)
|
||||
{
|
||||
tx.wo(map_b)->put(2, 42);
|
||||
|
@ -70,7 +70,7 @@ static std::vector<ActionDesc> create_actions(
|
|||
}
|
||||
return false;
|
||||
}});
|
||||
actions.push_back({seqnos_set, [](size_t i, kv::Tx& tx) {
|
||||
actions.push_back({seqnos_set, [](size_t i, ccf::kv::Tx& tx) {
|
||||
if (i % 5 == 0)
|
||||
{
|
||||
tx.wo(set_a)->insert("set key");
|
||||
|
@ -78,7 +78,7 @@ static std::vector<ActionDesc> create_actions(
|
|||
}
|
||||
return false;
|
||||
}});
|
||||
actions.push_back({seqnos_value, [](size_t i, kv::Tx& tx) {
|
||||
actions.push_back({seqnos_value, [](size_t i, ccf::kv::Tx& tx) {
|
||||
if (i % 6 == 0)
|
||||
{
|
||||
tx.wo(value_a)->put("value doesn't matter");
|
||||
|
@ -181,7 +181,7 @@ TEST_CASE("Basic cache" * doctest::test_suite("lfs"))
|
|||
|
||||
TEST_CASE("Integrated cache" * doctest::test_suite("lfs"))
|
||||
{
|
||||
kv::Store kv_store;
|
||||
ccf::kv::Store kv_store;
|
||||
|
||||
auto consensus = std::make_shared<AllCommittableConsensus>();
|
||||
kv_store.set_consensus(consensus);
|
||||
|
@ -189,7 +189,7 @@ TEST_CASE("Integrated cache" * doctest::test_suite("lfs"))
|
|||
auto fetcher = std::make_shared<TestTransactionFetcher>();
|
||||
ccf::indexing::Indexer indexer(fetcher);
|
||||
|
||||
auto encryptor = std::make_shared<kv::NullTxEncryptor>();
|
||||
auto encryptor = std::make_shared<ccf::kv::NullTxEncryptor>();
|
||||
kv_store.set_encryptor(encryptor);
|
||||
|
||||
messaging::BufferProcessor host_bp("lfs_host");
|
||||
|
@ -394,7 +394,7 @@ TEST_CASE("Integrated cache" * doctest::test_suite("lfs"))
|
|||
auto index_b = std::make_shared<StratB>(map_b, node_context, 100, 4);
|
||||
REQUIRE(indexer.install_strategy(index_b));
|
||||
|
||||
kv::TxID current_ = kv_store.current_txid();
|
||||
ccf::kv::TxID current_ = kv_store.current_txid();
|
||||
ccf::TxID current{current_.term, current_.version};
|
||||
REQUIRE(index_a->get_indexed_watermark() == current);
|
||||
REQUIRE(index_b->get_indexed_watermark() == ccf::TxID());
|
||||
|
@ -505,7 +505,7 @@ TEST_CASE("Integrated cache" * doctest::test_suite("lfs"))
|
|||
|
||||
void run_sparse_index_test(size_t bucket_size, size_t num_buckets)
|
||||
{
|
||||
kv::Store kv_store;
|
||||
ccf::kv::Store kv_store;
|
||||
|
||||
auto consensus = std::make_shared<AllCommittableConsensus>();
|
||||
kv_store.set_consensus(consensus);
|
||||
|
@ -513,7 +513,7 @@ void run_sparse_index_test(size_t bucket_size, size_t num_buckets)
|
|||
auto fetcher = std::make_shared<TestTransactionFetcher>();
|
||||
ccf::indexing::Indexer indexer(fetcher);
|
||||
|
||||
auto encryptor = std::make_shared<kv::NullTxEncryptor>();
|
||||
auto encryptor = std::make_shared<ccf::kv::NullTxEncryptor>();
|
||||
kv_store.set_encryptor(encryptor);
|
||||
|
||||
messaging::BufferProcessor host_bp("lfs_host");
|
||||
|
@ -565,7 +565,7 @@ void run_sparse_index_test(size_t bucket_size, size_t num_buckets)
|
|||
{
|
||||
handle_b->put(k, k);
|
||||
}
|
||||
REQUIRE(tx.commit() == kv::CommitResult::SUCCESS);
|
||||
REQUIRE(tx.commit() == ccf::kv::CommitResult::SUCCESS);
|
||||
const auto seqno = tx.get_txid()->version;
|
||||
for (const auto& k : keys)
|
||||
{
|
||||
|
@ -580,7 +580,7 @@ void run_sparse_index_test(size_t bucket_size, size_t num_buckets)
|
|||
auto tx = kv_store.create_tx();
|
||||
auto handle_a = tx.wo(map_a);
|
||||
handle_a->put("ignore", "ignore");
|
||||
REQUIRE(tx.commit() == kv::CommitResult::SUCCESS);
|
||||
REQUIRE(tx.commit() == ccf::kv::CommitResult::SUCCESS);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -12,10 +12,10 @@ namespace ccf::indexing
|
|||
public:
|
||||
virtual ~TransactionFetcher() = default;
|
||||
|
||||
virtual kv::ReadOnlyStorePtr deserialise_transaction(
|
||||
virtual ccf::kv::ReadOnlyStorePtr deserialise_transaction(
|
||||
ccf::SeqNo seqno, const uint8_t* data, size_t size) = 0;
|
||||
|
||||
virtual std::vector<kv::ReadOnlyStorePtr> fetch_transactions(
|
||||
virtual std::vector<ccf::kv::ReadOnlyStorePtr> fetch_transactions(
|
||||
const SeqNoCollection& seqnos) = 0;
|
||||
};
|
||||
}
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче