From 20d01cd3c706b9d8a47dabfa31f44b62c029ac2f Mon Sep 17 00:00:00 2001 From: Pavel Karpy Date: Wed, 31 Jan 2024 19:47:28 +0300 Subject: [PATCH] arch: Adapt object split information according to https://github.com/nspcc-dev/neofs-api/pull/283 Keep both versions of the split objects and mark them as v1 and v2. Signed-off-by: Pavel Karpy --- 01-arch/03-objects.md | 2 +- 01-arch/04-object_split.md | 34 +++++++++++++++--- ..._all.drawio => object_split_all_v1.drawio} | 0 ..._split_all.pdf => object_split_all_v1.pdf} | Bin ..._split_all.svg => object_split_all_v1.svg} | 0 01-arch/pic/object_split_all_v2.drawio | 1 + 01-arch/pic/object_split_all_v2.pdf | Bin 0 -> 15375 bytes 01-arch/pic/object_split_all_v2.svg | 4 +++ 8 files changed, 35 insertions(+), 6 deletions(-) rename 01-arch/pic/{object_split_all.drawio => object_split_all_v1.drawio} (100%) rename 01-arch/pic/{object_split_all.pdf => object_split_all_v1.pdf} (100%) rename 01-arch/pic/{object_split_all.svg => object_split_all_v1.svg} (100%) create mode 100644 01-arch/pic/object_split_all_v2.drawio create mode 100644 01-arch/pic/object_split_all_v2.pdf create mode 100644 01-arch/pic/object_split_all_v2.svg diff --git a/01-arch/03-objects.md b/01-arch/03-objects.md index f49a402..8eed4d4 100644 --- a/01-arch/03-objects.md +++ b/01-arch/03-objects.md @@ -4,6 +4,6 @@ NeoFS stores all data in the form of objects, thus providing an object-based sto ObjectID is a hash that equals Headers hashes plus Payload hashes. Any object includes a system header, extended headers, and a payload. A system header is an obligatory field, while extended headers may be omitted. However, any extended header should follow a particular structure (e.g. IntegrityHeader is a must). A user can add any extended header in the form of a key-value pair, though keeping in mind that it cannot be duplicated with several values. One attribute -- one value. Please note that any object initially has FileName, so that you cannot create an extended header with it as a key. -The maximum size for an object is fixed and can be changed only for the whole network in the main contract. It means that if a file is too heavy, it will be automatically divided into smaller objects. This smaller parts are put in a container and placed to a Storage Node. Later, they can be assembled to the initial object. Such assembling is performed in the storage nodes upon a corresponding request for a linking object. Once your file is converted into an object (or several objects), this object cannot be changed. +The maximum size for an object is fixed and can be changed only for the whole network in the main contract. It means that if a file is too heavy, it will be automatically divided into smaller objects. This smaller parts are put in a container and placed to a Storage Node. Later, they can be assembled to the original object. Such assembling is performed in the storage nodes upon a corresponding request for a linking object. Once your file is converted into an object (or several objects), this object cannot be changed. One can define the format of the object in an API Specification. For more information, see [API Specification](https://github.com/nspcc-dev/neofs-api/tree/master/proto-docs). diff --git a/01-arch/04-object_split.md b/01-arch/04-object_split.md index da4e1f3..0920007 100644 --- a/01-arch/04-object_split.md +++ b/01-arch/04-object_split.md @@ -4,9 +4,11 @@ NeoFS has a limit on the maximal physically stored single object size. If there For each part of the original object's payload, a separate object with own `ObjectID` will be created. The large object will not be physically present in the system, but it will be reconstructed from the object parts when requested. -![Large object split](pic/object_split_all) +There are two active versions of the split objects, both are supported, but the second one is more flexible and support attributes-based ACL rules. The first one is for the backward compatibility only. All objects participating in the split have the `Split` headers set. Depending on the place in the split hierarchy it has different field combinations. -All objects participating in the split have the `Split` headers set. Depending on the place in the split hierarchy it has different field combinations. There are four possible cases: +### Object Split V1 + +![Large object split V1](pic/object_split_all_v1) * First part \ First part object only has the `split_id` field set, as there is no more information known at this point @@ -15,13 +17,35 @@ All objects participating in the split have the `Split` headers set. Depending o Middle parts have information about the previous part in `previous` field in addition to the `split_id` * Last part \ - At this point all the information about the object under split is known. Hence the last part contains not only the `split_id` and `previous` fields, but also the `ObjectID` of the original large object in its `parent` field, signed `ObjectID` in `parent_signature` and original object's `Header` in `parent_header`. + At this point, all the information about the object under split is known. Hence, the last part contains not only the `split_id` and `previous` fields, but also the `ObjectID` of the original large object in its `parent` field, signed `ObjectID` in `parent_signature` and original object's `Header` in `parent_header`. * Link object \ There are special "Link objects" that have the same common `split_id`, do not have any payload, but contain original object's `ObjectID` in `parent` field, it's signature in `parent_signature`, original object's `Header` in `parent_header` and the list of all object parts with payload in repeated `children` field. Link objects help to speed up the large object reconstruction and `HEAD` requests processing. If Link object is lost, the original large object still will be reconstructed from its parts, but it will require more actions from NeoFS nodes. -All of the split hierarchy objects may be physically stored on different nodes. During reconstruction, at first the link object or the last part object will be found. If it's a HEAD request, the link object or the last part object will have all the information required to return the original large object's HEAD response. For a GET request, the payload will be taken from part objects listed in the `split.children` header. As they are ordered, it will be possible to begin streaming the payload as soon as the first part object becomes available. If Link object is lost, some additional time will be spent on reconstructing the list from `split.previous` header fields. +### Object Split V2 +\pagebreak + +![Large object split V2](pic/object_split_all_v2) + +* Initial object \ + Initial object that expresses a desire to put a large object in the NeoFS network. It has `split_id` and `parent_header` fields set. The parent header is not finished: since there is no information about payload, it cannot be measured, hashed and signed (also, no object ID can be assigned). However, it has all user information attached to the object (e.g. attributes), and plays the role of representative of the original object until all the parts are uploaded to the NeoFS. + +* First part \ + First part object only has the `split_id` and `init` fields set + +* Middle parts \ + Middle parts have information about the previous part in `previous` field in addition to the `split_id` and `init` pair + +* Last part \ + At this point, all the information about the object under split is known. Hence, the last part contains not only the `split_id`, `init` and `previous` fields, but also the `ObjectID` of the original large object in its `parent` field, signed `ObjectID` in `parent_signature` and original object's `Header` in `parent_header`. + +* Link object \ + There are special "Link objects" that have the same common `split_id`, but also contain original object's `ObjectID` in `parent` field, its signature in `parent_signature`, original object's `Header` in `parent_header` and the list of all object part IDs paired with their sizes encoded in the payload. Link objects help to speed up the large object reconstruction and `HEAD` requests processing. If a Link object is lost, the original large object still will be reconstructed from its parts, but it will require more actions from NeoFS nodes. + +All of the split hierarchy objects may be physically stored on different nodes. During reconstruction, at first the link object or the last part object will be found. If it's a HEAD request, the link object or the last part object will have all the information required to return the original large object's HEAD response. For a GET request, the payload will be taken from part objects listed in the Link object's payload. As they are ordered, it will be possible to begin streaming the payload as soon as the first part object becomes available. If a Link object is lost, some additional time will be spent on reconstructing the list from `split.previous` header fields. + +If the whole payload is available, a large object may be split on the client side using local tools like `neofs-cli`. In this case, the resulting object set will be signed with user's key. Such a split type can be called a "Static split". -If the whole payload is available, a large object may be split on the client side using local tools like `neofs-cli`. In this case the resulting object set will be signed with user's key. Such a split type can be called a "Static split". +There are attribute-based ACL rules in the NeoFS. Before the last part and the link object are created, the original object's parts should be validated according to the initial object's information about the original object. When the large object's payload is not fully available right away, or it is too big to be split locally, the object upload can be started in a Session with another NeoFS node and be streamed in a PUT operation, part by part. Object parts will be automatically created as soon as the payload hits the MaxObjectSize limit. In this case, the resulting object set will be signed with a session key signed by user's key. This split type can be called a "Dynamic split". diff --git a/01-arch/pic/object_split_all.drawio b/01-arch/pic/object_split_all_v1.drawio similarity index 100% rename from 01-arch/pic/object_split_all.drawio rename to 01-arch/pic/object_split_all_v1.drawio diff --git a/01-arch/pic/object_split_all.pdf b/01-arch/pic/object_split_all_v1.pdf similarity index 100% rename from 01-arch/pic/object_split_all.pdf rename to 01-arch/pic/object_split_all_v1.pdf diff --git a/01-arch/pic/object_split_all.svg b/01-arch/pic/object_split_all_v1.svg similarity index 100% rename from 01-arch/pic/object_split_all.svg rename to 01-arch/pic/object_split_all_v1.svg diff --git a/01-arch/pic/object_split_all_v2.drawio b/01-arch/pic/object_split_all_v2.drawio new file mode 100644 index 0000000..3ae332c --- /dev/null +++ b/01-arch/pic/object_split_all_v2.drawio @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/01-arch/pic/object_split_all_v2.pdf b/01-arch/pic/object_split_all_v2.pdf new file mode 100644 index 0000000000000000000000000000000000000000..bb0e02825e797c2e05b97fae426f20e7e6b907a4 GIT binary patch literal 15375 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 + + +Link Objectobject_id: ID5payload: [ID1,N1][ID2,N2][ID3,N3]header.split.split_id: f00dcaf3...header.split.parent: ID4header.split.parent_signature: ...header.split.parent_header: ...Part 1 Objectobject_id: ID1payload: 0xAABB...header.payload_length: N1header.split.split_id: f00dcaf3...header.split.init: ID6Part 2 Objectobject_id: ID2payload: 0xCCDD...header.payload_length: N2header.split.split_id: f00dcaf3...header.split.init: ID6header.split.previous: ID1Part 3 Objectobject_id: ID3payload: 0xEEFF...header.payload_length: N3header.split.split_id: f00dcaf3...header.split.init: ID6header.split.previous: ID2header.split.parent: ID4header.split.parent_signature: ...header.split.parent_header: ...Large Objectobject_id: ObjectID4signature: ...header: ...payload: 0xAA...CC...EE...Init Objectobject_id: ID6payload: nilheader.split.split_id: f00dcaf3...header.split.parent_header: *NO ID* \ No newline at end of file