Add new epoch event handler to GC that finds all expired non-tombstone
objects and marks them to be removed.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Implement `DB.IterateExpired` method that iterates over the objects in
metabase that are expired at particular epoch.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Group handlers of the particular event to a WaitGroup and wait for it before
the next event handling. This will ensure that all handlers complete and
prevent potential conflicts between past and present jobs.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
`Shard.Init` method creates a new GC instance from shard configuration and
starts GC's workers through `init` call. In initial implementation GC
routines are indefinite and can be killed only with by application shutdown.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Shard's GC component consists of:
* asynchronous remover that periodically wake up and removes all garbage
objects from the shard, and goes to sleep for particular time interval;
* external event listener that distributes jobs between workers;
* group of workers that can handle a single job related to particular
external event.
Remover and event listener represents go-routines which are started by
`init` method (calls from `Shard.Init`). In initial version all event
handlers are interrupted: this means that next event of the same type will
interrupt previous handling and start the new one.
GC is fully encapsulated in Shard. All GC configurations are reflected in
Shard's configuration.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Implement `DB.IterateOverGraveyard` method that iterates over all graves and
passes passes their descriptors (new type `Grave`) to handler (new type
`GraveHandler`). `Grave` currently have buried object address and garbage
flag.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Replace single target address in `InhumePrm` with the list of addresses.
Change corresponding parameter in `WithTarget` and `MarkAsGarbage` methods
to variadic.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Replace single target address in `InhumePrm` with the list of addresses.
Rename `WithAddress` method to `WithAddresses` and change parameter to
variadic.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Make `StorageEngine.Delete` to execute `Inhume` operation with
`MarkAsGarbage` parameter on the `Shard` that holds the object. Searching of
the particular shard is performed through iterating over HRW-sorted shards.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Implement `InhumePrm.MarkAsGarbage` method that leads to marking object as
garbage in metabase. Update `InhumePrm.WithTarget` doc indicating a conflict
with the new method.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Implement `InhumePrm.WithGCMark` method that marks the object as garbage in
graveyard. Update `InhumePrm.WithTombstoneAddress` doc indicating a conflict
with the new method. Update `Inhume` function doc about tombstone address
parameter.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Delete operation of Metabase is performed on group of objects. The set being
removed can contain descendants of a common parent. In the case when all
descendants of a parent object are deleted, it must also be deleted from
the metabase. In the previous implementation, this was not done due to the
chosen approach to counting references to the parent.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
The lifetime of an object can be limited by specifying a correspondin
well-known attribute. Node should refuse to save expired objects.
Checking objects in FormatValidator is extended with an expiration attribute
parsing step.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
In previous implementation StorageEngine.Inhume operation forced Shard
.Inhume call on all internal shards. There is a need to inhume object in a
single shard. To achieve this, Inhume operation is performed in next steps:
1. iterate over sorted shards, check object presence through Exists call;
2. if object exists at any shard in step 1 => inhume it and return on
success;
3. if no shards contain the object => iterate over sorted shards again and
try to inhume the object at first possible shard;
4. if all Inhume calls are failed => return an error.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
All node info attribute transformations can't guarantee
the order of attributes. However it should be consistent
otherwise smart-contract won't be able to collect signatures
and approve transaction.
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
Node info validator may change node attributes, e.g. update
it with human-readable location attributes based on LOCODE.
So inner ring node should provide new node info binary to
smart contract.
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
Scanning subdivision csv-table entries one-by-one takes significant time and
system resources. To speed up random access to table records, on the first
call, the table is pumped into memory (map). On subsequent calls, I/O
operations are not performed.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Scanning csv-table entries one-by-one takes significant time and system
resources. To speed up random access to table records, on the first call,
the table is pumped into memory (map). On subsequent calls, I/O operations
are not performed.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Inner ring Server does not modify LOCODE database (Put method), thus it is
better to open it in RO mode.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Add ReadOnly function that returns Option that enables read-only mode in DB.
RO mode can be used by processes that won't modify the DB in order to not
acquire write flock.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Set timeout option of BoltDB Open operation to 3s in order to prevent
indefinite waiting for file lock.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Implement DB interface required by LOCODE validator on new wrapper over the
LOCODE Bolt DB (Record on new wrapper over LOCODE Bolt DB entries).
Construct LOCODE validator and pass it to Netmap processor's constructor as
NodeValidator parameter.
Thus, candidates for a network map must set LOCODE attribute for which there
is an entry in the NeoFS location database.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Keep list of functions which are called first when the server starts (method
Server.Start). If any of the starters returns an error, the server will not
start. Such starters will mainly be used for resources that need to be
initialized after a successful server construction, but before its main work
(e.g. local files).
Keep list of functions which are called when the server stops (Server.Stop
method). Such closers will mainly be used for resources that need to be
released after server shutdown (e.g. initialized by starters).
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Define a structure for dealing with the geographic location of nodes.
Implement VerifyAndUpdate (with the same purpose as NodeValidator interface)
that checks LOCODE attribute and fills other attributes of the location.
Technically the entity is a wrapper over the NeoFS location database: it
maps the node LOCODE to the database record from which the new attributes
are generated.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Define NodeValidator interface of the entity that checks and finalizes
NodeInfo structure. Add NodeValidator to Netmap processor. Pass NodeInfo
structures of network map candidates to NodeValidator in order to verify it
and prepare to final state required by network.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Define NeoFS location database based on BoltDB. Implement methods to save
the record by key (Put) and to read the record by key (Get).
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Define database of Earth's polygons in GeoJSON format. Implement resolving
of geo point to continent in which it is located through point-in-polygon
calculation.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Implement airport database based on csv OpenFlights table. Implement
UN/LOCODE entry matcher. Implement country namespace.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Define structure of keys and records of the location database. Define the
interfaces of all components necessary for the formation of the database.
Implement the function of filling the database.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Define the data types needed to work with LOCODE's in NeoFS (country code,
location code, coordinates). Implement string parsers for new types.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Check if `new(big.Int)` will be efficient later and replace
all `big.NewInt()` in code or leave it as it is.
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
TxTable used twice in context to transfer assets to
and from banking account. There is no need to store
instance of table persistently.
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
Some transfers from container owners into bank account may
fail due to lack of assets, so we have to deal with remaining
amount of assets in banking account.
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
Add SignWithRFC6979 option to signature verification function since eACL
table are signed by users with this option.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Since the contract started returning the table signature, it became
necessary to check its correctness.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Basic settlement context is a main structure that
implement logic of basic settlement phases: collecting
assets from container owners and then distributing them
to storage nodes.
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
Implement route Builder interface on wrapper over the container placement
builder, Component implies exactly one transfer to each of the most weight
nodes of the container (according to some weighing algorithm).
Implementation is planned for use when transferring local estimates of
storage nodes.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Implement a component for transmitting the value of the used container space
along a route defined in the system. Implement WriterProvider interface on
it. By implementation, it is the link between the route planner and the
point-to-point transmitter, and abstracts from the implementation of both of
them. In the future, this implementation will be used as a transmitter of
local estimates of storage nodes among themselves.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Implement API methods of the Container contracts client corresponding
to the calls of the contract for storing the used space of the container
("putContainerSize", "getContainerSize", "listContainerSizes"). Extend
the wrapper over the client with methods abstracted from sidechen calls.
In particular, the method of storing the value will be used to record
the estimates of the used space of containers calculated by the network
participants.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Implement functions to wrap Writer or Iterator. The resulting wrapper
provides WriterProvider or IteratorProvider interface respectively.
Such a wrapper can be used as a single storage instance provider
regardless of context.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Implement a component that stores the values of the used space of
containers. The storage allows you to write several values for a fixed
container and epoch number, and read the averaged estimates of all
accumulated values. All values are stored in memory. This component is
planned to be used as an accumulator of opinions from various network
participants about the fullness of the container.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Implement a component that connects the value stores of the used space of
containers. Implement the Start/Stop operations on it, which will later
become the application handlers of the corresponding events from the
sidechain. The main task of the controller is to temporarily synchronize the
stages of calculating the global estimate of the used space in the
container. The details of the score calculation (the way of collecting /
transmitting local scores, the final score formula and writing to the
contract) are encapsulated in the dependency components, the controller is
abstracted from them.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
There are two notifications:
- start estimation notification produced at the beginning of the
epoch,
- stop estimation notifications should be produced before
basic audit settlement starts.
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
This small refactoring adds `blocktimer.go` file with
all timer related function and constructors. This way
we can create all timers in one place (at the end of
innerring.Server constructor).
To do that we had to move timer reset into global
server state so it can be accessed by netmap
processor.
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
There is no point of making separate `Fee` and `NoFee`
wrappers because all reading operations are free disregarding
of fee value in static client. However we can use these same
wrappers so send transaction.
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
Pass handler of audit settlement event to netmap event processor. Generate
AuditEvent in during new epoch processing.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Define a processor of events related to monetary transactions. Define
audit-related event. Provide an interface for processing the audit payout
event.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Use client with extraFee instead of readOnlyFee. Rename
NewNoFeeBalanceClient to NewBalanceClient since no-fee client is no longer
used.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Do not pass zero transfers from the calculation table to Exchanger. Revert
transfers with negative amount since Exchanger interface requires positive
amounts of funds.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Move control of the minimum cost of payment for the audit from the
implementation of the Exchanger to the place where the amount is calculated.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Calculate payments to storage nodes for the passed audit when changing the
epoch. The calculation results are wrapped in a call to the Balance contract
(one transaction per user-to-user transfer).
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Implement component that analyzes audit results and generates transactions
for payment of awards for successfully passed audit. When calculating the
total fee, the declared price of the node (attribute) and the total volume
of storage groups, which were successfully audited by the container, are
taken into account. In one call the calculator processes all audit results
for the previous epoch (relative to the calculated parameter).
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
In previous implementation handler was not called more the one time after
Reset. It was caused by tick counter not being reset inside Reset method.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Container listing already supported in the metabase for `engine.List`
operation. To get container statistics engine should provide both the
option to get container volume estimation and list of all containers.
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
Objects of one container can be split among shards, so engine
should iterate over all available shards to sum all size
estimations.
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
Storage nodes keep container size estimation so they
can announce this info and hope for some basic income
settlements. This is also useful for monitoring.
Container size does not include non regular or inhumed
object sizes.
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
Listen to new blocks from mainnet until the required fix in neo-go lib is
released (https://github.com/nspcc-dev/neo-go/pull/1687).
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Replace WSClient.Init call from the body of BlockNotifications method to
constructor New since Init should be called before working with client
according to neo-go docs.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Write error returned by BlockNotifications() call ins listenLoop method body
to error channel only if it is procided. Otherwise, write debug log message.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Replace block channel's initialization from BlockNotifications method body
to Subscriber's constructor in order to prevent potential writing to nil
channel.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Call handler of the fractional block interval once between base interval
ticks by default. Add option to call handler of fractional block interval
multiple times (N times if fractional interval == BASE_INTERVAL / N).
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Extend Listener with RegisterBlockHandler method. All block handlers are
called on each block read from Subscriber.BlockNotifications channel.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Call SubscribeForNewBlocks in Subscriber's constructor. Provide
BlockNotifications interface method that returns block channel. Write new
blocks to the channel on notification events with BlockEventID type.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Classifier looks at list of inner ring nodes and container
nodes from current and previous epoch to classify request.
Sometimes these checks might return error.
Consider there is a request from unknown key and container's
placement policy valid for current epoch and invalid for past
epoch. Classifier tries to find if key belongs to container
node from current epoch -- it is not. Then it tries to find if
key belongs to container node from past epoch and it throws
error, because placement policy is invalid for past epoch.
This is a legit case and classifier should ignore such errors
to provide best effort in matching. The only error classifier
should return is an error when request does not contain
public key to classify it.
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
Pivot used to shuffle nodes in the CRUSH tree. This is
required argument. We use container ID value to select
container nodes, so `nil` value produces incorrect placements.
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
Replace static NodeInfo structure with NodeState interface that provides
method to read node information in runtime.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
There is a codecov issue because objects are not placed
in the engine the same way every unit test. Therefore
sometimes there are more coverage, sometimes there are
less. Seeded RNG should solve this issue for engine tests.
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
Netmap snapshot table caches bootstrap `AddPeer` txs so inner ring
node does not produce redundant approval txs for bootstrapped nodes.
However if node updates states to `Offline`, then such node should
be flagged in snapshot table, so re-bootstrap will actually produce
approval tx.
`ev.PublicKey.String()` returns uncompressed representation of the
node's public key, while snapshot contains compressed values.
Therefore the node was not flagged and re-bootstrap tx was not
approved by inner ring nodes.
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
Add HealthStatus method to HealthChecker interface that should return
current health status of the node application.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Implement methods required for signatures. Receive network map from netmap
storage, convert it to Control service message and return in response.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Add NetmapSnapshot rpc to ControlService protobuf definition. Recompile
proto files. Add required method to server structure.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
Support processing of NetmapEpoch and NetmapLookupDepth X-headers when
processing object read operations. Placement for operations
Get/Head/GetRange/GetRangeHash/Search is built for the epoch specified in
NetmapEpoch X-header (by default latest). Also the specified operations are
processed until success is achieved for network maps from the past up to
NetmapLookupDepth value. Behavior for default values (zero or missing) left
unchanged.
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>