From e6ecce741f04d44b1078df27588ad387f5467339 Mon Sep 17 00:00:00 2001 From: Pavel Karpy Date: Wed, 31 Jan 2024 19:48:57 +0300 Subject: [PATCH 1/3] Dockerfile: Drop maintainer that cannot maintain it At least, there is no ability to use the provided contact and more contributions are not expected. Signed-off-by: Pavel Karpy --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 0cfe000..5d802a4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ FROM ubuntu:20.04 -MAINTAINER Stanislav Bogatyrev +MAINTAINER NeoSPCC ENV DEBIAN_FRONTEND noninteractive From 6d756c0a69da2c746a35aaa66a6e26b484926424 Mon Sep 17 00:00:00 2001 From: Pavel Karpy Date: Wed, 31 Jan 2024 19:49:55 +0300 Subject: [PATCH 2/3] Add CODEOWNERS file Signed-off-by: Pavel Karpy --- .github/workflows/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/workflows/CODEOWNERS diff --git a/.github/workflows/CODEOWNERS b/.github/workflows/CODEOWNERS new file mode 100644 index 0000000..18f85a8 --- /dev/null +++ b/.github/workflows/CODEOWNERS @@ -0,0 +1 @@ +* @carpawell @cthulhu-rider @roman-khimov From 6c234c5e40305307c4d5fb9a11f0ff93eb32eb7e Mon Sep 17 00:00:00 2001 From: Pavel Karpy Date: Wed, 31 Jan 2024 19:47:28 +0300 Subject: [PATCH 3/3] 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 | 31 +++++++++++++++--- ..._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 | 2 ++ 01-arch/pic/object_split_all_v2.pdf | Bin 0 -> 21162 bytes 01-arch/pic/object_split_all_v2.svg | 4 +++ 8 files changed, 33 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..d188038 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 kept for 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,32 @@ 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) + +* First part \ + First part object only has `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. + +* Middle parts \ + Middle parts have information about the previous part in `previous` field and the first one in the `first` field + +* Last part \ + At this point, all the information about the object under split is known. Hence, the last part contains not only the `first` 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 `first` field, but also contain original object's `ObjectID` in `parent` field, its signature in `parent_signature`, original object's `Header` in `parent_header` and a list of all the object parts' 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 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..8fc3b91 --- /dev/null +++ b/01-arch/pic/object_split_all_v2.drawio @@ -0,0 +1,2 @@ + +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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..6e24503bd9f75c97ee790b48e46b142ffced1ff2 GIT binary patch literal 21162 zcmc$`Wl&sQ(>97*a1z`iSa5d>7JP7r5Zv88BoKnT!vuGCm*CC}u7f+l9nO&F&hy^i zskgp5{|?fXCH6+m2)k(G%XjVb{8hla+=Mae>G_t_FnKmd(d&cxQt z*_@S=`jB3$%0AkvUdS~-*e^rRPX2+mZ-YXJnP!M&7U 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

8)p%`nGnWidvI8|)rMd6IpDGe{$_hYoo zGuOw&pQVBi#s&<&{qgk2*TD$}FwD1MATEf^gcz1+zPy1SY|-^#N40zh5wKaF6XQ!g z4+Z_mb@Fr@`#VyO1;tg6@r==0>$sZPwRBs)hwHVq))R2QfF zVAd**aK*r6y*e@q(1Eqkzp12!H5v8WBYDPcao#I%8bjE((o#l>EeD%UpNn8O6koBY z(lo<5lw@ztA4j$o8s}7BZJ$IXS69Zv247cHaDMxUfSm~JmwHttgn@f!SYkXde;j<2X#Sg3l8)=3=>UDt6e84kkTI~IuK za`c}E-3X|$;|xzH4tOzwvC||*?GHS@C0ziN%u=sh6`9Iqv(0V^-VD_cU+L>d`I&s# zzfs*&^Sr!TU)Y2#&rG4Nv0J7rutvpYyy+!(^XZt~m^jd;od4nAXPi1jX*Qx=Y(^)~ z?wb8!@bYNA;@pk)1G-M0!{a`S9Kx)2VLUp?)YZyH8OU490D5|()Jvl} zv|O4dZ?OmRwvRdtTfF7e2k|hkuvjKU$H=AX&U@Kj|MI|W$?FkRUVhc`p`iqjfK$rt zQS@F+Sw_MIc7?q45(v-`l%q!1{Hysl{lEQKC#qLdpmHt>4JmHF@!>0174UWUrkpa? zDkh5|`HAkfM57SaRGsac2dWyN_z)F`{8@~>ZIDVVPu=F1p(!kAo{n1sNn=4A`{YP;h@x4`UT2<=Ra$=}b(4O3MUVU-d ze%0!EE+KZ~ScDt=x_|HF{m;R@7R?tND=l zZXuHSDxaqXd;)C2=<0n+Mpl)90}MT7XO2v1l!mIBD0^nl$8c%eZ96^xLAO5&CQgs5 zH?qfDX;#Fd=A57dqaQvjC+UEveH7)Jy(U5GfcgM9g&M{VV!1b=@ytrE) zUgMc5=Z@HW*S9Z^>nFKDQ^kFuo8p%;17meRgLHK%R>?(69c}xC^+oz*KbPk0w8Q&) zoTeVsy1>zRt%8&KRQN?WPRMaAk<=-m_Bvo~sdPX49t+z}-m{&nx(P1M!=`ZuNw((upT6G`Envj8NR8*n=&Vs&pYx!^$Cf2&xCq`MX)E!1~4 zWpxlBDO~D_I;sw9?e$Nx>jQ3H^0YJmd~6k)==J+zu*{JBm8_c3jibqB1F+Qbi+su8 zX{zQ#z_~L|0bd`7lCRs!R7gV&ZJV~Az%%Pn1(p`;>&Zd0 zaqA7PJAJnYjFTSS&0W}!@UisQe^*Uwl~?FnUOK%}Hd3T?d*MUES{?t^)cgiNo)l*I zDRV2&ECUDx(W=7)+I?8-o}4%kzhjh#=*36kiI@4i;weqaAIq%?LZQ5tp~8McW!(wm zA|cw>|MoMCfo|)n~^)ooi=rUy|^cs z^Rvlpr!B}JK4#_)__TfLaAwC>{*3-Fn@=Vef5UX+TIC^X(B>c)=JtgHvUBJMz2eua z+2`cl9HG2v4gLWl^D#7f?HQce?;Kah9t3R_#i=c3+j+LwmJc3OYviojEjgH?OV*PQ zzI!CVO0NjCr<9x`#ZJAvsoi)|-*csdwuYV4;EIG_nRqGwbp!LBtQj&laAEIO?|QVz zn_f|7;m!AH&rVIIn#zWxG-;4qcnZT_agjiei00LZEIqd)z-T#-1HKYxO)#BYz7U(0 zlw$2>Ij)AajSwl2M6!CbQmHQR`fhKbuLyIGz7l;2F)Kl{vFwO->7is1-}C;O1c>2y zUA781%Iqlj{3Wqr+EuEkKsHcM{s7Tt(DOdkEGbKM^Dgj!nK@W2VpCeEOHX>y0b{^AFhP3{f}K-{X!?#4R-D05sB1 z+r!Ob*)jnSMc0kMfem^Rz$?(7!jPKZDge*68KnfZ7>!rEq z?EJ4z7&%VeZuvJVh5v&}|GKqQ*_2TjOr*r09Tc0gMVLQELiMls|8VVPl%N0K#Hy*z zrtB=?CIR~e0+;ak69nxS`>UWL0ayK%|I^=5_8pNU=>m{(6mzZA%8+@4RgyK~qA+q1 zDvr|$#N!Cf!TFt?5xC#=6WRsOOu`~S-lIkwE literal 0 HcmV?d00001 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..0ee29dd --- /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.first: ID1header.split.parent: ID4header.split.parent_signature: ...header.split.parent_header: ...Part 1 Objectobject_id: ID1payload: 0xAABB...header.payload_length: N1header.split.parent_header: *NO HASHES*Part 2 Objectobject_id: ID2payload: 0xCCDD...header.payload_length: N2header.split.previous: ID1header.split.first: ID1Part 3 Objectobject_id: ID3payload: 0xEEFF...header.payload_length: N3header.split.previous: ID2header.split.first: ID1header.split.parent: ID4header.split.parent_signature: ...header.split.parent_header: ...Large Objectobject_id: ObjectID4signature: ...header: ...payload: 0xAA...CC...EE... \ No newline at end of file