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 0000000..bb0e028 Binary files /dev/null and b/01-arch/pic/object_split_all_v2.pdf differ diff --git a/01-arch/pic/object_split_all_v2.svg b/01-arch/pic/object_split_all_v2.svg new file mode 100644 index 0000000..849938f --- /dev/null +++ b/01-arch/pic/object_split_all_v2.svg @@ -0,0 +1,4 @@ + + + +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