Wiki source code of Filesystem Store Layout

Last modified by Eleni Cojocariu on 2026/10/23 14:40

Show last authors
1 This page gives every path the filesystem store writes and what each file in them is called. [[The Attachment Store>>doc:documentation.xs.admin.store.attachment-store.WebHome]] explains the store itself, and [[Locate an Attachment's File on Disk>>doc:documentation.xs.admin.store.locate-file.WebHome]] computes a path for a given attachment rather than deriving it by hand.
2
3 Every path below is relative to ##store/file## in the [[permanent directory>>doc:documentation.xs.admin.configuration.directories.permanent-directory.WebHome]]. They are blob paths, not file paths: on an S3 [[blob store>>doc:documentation.xs.admin.store.blob.WebHome]] the same relative paths are the object keys.
4
5 == How a path is derived ==
6
7 {{plantuml}}
8 @startuml
9 !theme bluegray
10 skinparam nodesep 25
11 skinparam ranksep 35
12
13 rectangle "Page reference\nSandbox.WebHome" as R
14 rectangle "locale stripped,\nserialized by local/uid\n7:Sandbox7:WebHome" as S
15 rectangle "MD5, hex\n83927acf911df7547cf26345b2c3e89c" as M
16 folder "8 / 3 / 927acf911df7547cf26345b2c3e89c" as D
17
18 R --> S
19 S --> M
20 M --> D : split 1 / 1 / 30
21 @enduml
22 {{/plantuml}}
23
24 The ##local/uid## serializer writes each name of the reference as its length, a colon, then the name, and leaves the wiki out. ##Sandbox.WebHome## becomes ##7:Sandbox7:WebHome##. The length is a character count, so a name miscounted by one produces a completely different path.
25
26 The hash is then split across three directory levels so that no single directory holds too many entries.
27
28 == The directory levels ==
29
30 |=Level|=Built from|=Present
31 |##<wiki>##|the wiki identifier, ##xwiki## on a single wiki|always
32 |##<a>/<b>/<rest>##|the MD5 of the serialized Page reference, split after the first and second characters|always
33 |##locales/<locale>##|the locale|only for a **deleted translation**; nothing else writes it
34 |##attachments/<a>/<b>/<rest>##|the MD5 of the attachment name, split the same way|for an attachment that is still there
35 |##deleted-attachments/<a>/<b>/<rest>/<index>##|the same hash, then the index of the deleted attachment|for a deleted attachment
36 |##deleted-documents/<index>##|the recycle bin index of the deleted Page|for a deleted Page
37
38 The attachment hash is taken from the **plain attachment name**, not from a serialized reference.
39
40 == The files in a directory ==
41
42 |=File|=What it is
43 |##f<extension>##|The current content. The name is always ##f##, followed by whatever came after the last ##.## of the attachment name, and by nothing when the name has no dot.
44 |##fv<version><extension>##|One stored version, for instance ##fv1.2.txt##.
45 |##<name>.lnk##|A one-line link holding the path, relative to its own directory, of the blob it stands for. XWiki writes one instead of a second copy whenever the current content is identical to a stored version, which is the usual case, and rewrites it on every new version.
46 |##~METADATA.xml##|The list of stored versions of the attachment: file name, size, author, version, comment and date for each.
47 |##~DELETED_ATTACH_METADATA.xml##|The same, for a deleted attachment, written beside ##~METADATA.xml##.
48 |##content.xml##|A deleted Page, serialized whole.
49 |##<name>~bak##, ##<name>~tmp##|The backup and temporary files of the two-stage commit. Seeing them on a quiet instance means a write did not finish.
50
51 == An attachment ==
52
53 ##XWikiLogo.png##, attached to ##Sandbox.WebHome##, ships with the standard flavor and can be checked on any instance:
54
55 {{code language="none"}}
56 xwiki/8/3/927acf911df7547cf26345b2c3e89c/ Sandbox.WebHome
57 attachments/
58 9/2/0bc685fa0da28168319c0126def81b/ XWikiLogo.png
59 fv1.1.png version 1.1
60 f.png.lnk the current content, holding "fv1.1.png"
61 ~METADATA.xml the list of stored versions
62 {{/code}}
63
64 == A deleted attachment ==
65
66 Deleting it moves the whole set one level deeper, under ##deleted-attachments##, keeping the versions and gaining the index the attachment recycle bin gave it. [[Deleted Attachments and the Recycle Bin>>doc:documentation.xs.admin.attachments.deleted-attachments.WebHome]] covers what becomes of it from there.
67
68 {{code language="none"}}
69 xwiki/8/3/927acf911df7547cf26345b2c3e89c/
70 deleted-attachments/
71 9/2/0bc685fa0da28168319c0126def81b/ the same hash of the attachment name
72 1/ the index of the deleted attachment
73 fv1.1.png
74 f.png.lnk
75 ~METADATA.xml
76 ~DELETED_ATTACH_METADATA.xml
77 {{/code}}
78
79 == A deleted Page ==
80
81 A deleted Page is a single file, not a directory of files: ##content.xml## is the Page serialized whole, its attachments included, so the ##attachments## directory disappears as the Page is deleted.
82
83 {{code language="none"}}
84 xwiki/1/b/017ac37905fda8aca6f74a719cfae4/
85 deleted-documents/
86 18/ the recycle bin index of the Page
87 content.xml the Page and its attachments
88 {{/code}}
89
90 Deleting one **translation** rather than the whole Page is the only thing that writes a ##locales## level, and it leaves the Page's attachments where they are:
91
92 {{code language="none"}}
93 xwiki/5/3/d3fccc5c1af9cf5ca0170d2e2a2aab/
94 attachments/... untouched
95 locales/
96 fr/
97 deleted-documents/
98 19/
99 content.xml
100 {{/code}}

Get Connected