Internally, all key-value mappings are stored in files in the DecSync directory.
Each collection is stored in the subdirectory syncType/collectionId, or just syncType if there is just one collection for the sync type.
Every application stores its own files in the subdirectory "v2"/appId.
So, every application only writes files inside syncType/collectionId/"v2"/appId.
Inside these directories there are two types of files: entry files of the form 00 to ff or info, and a sequences file.
In addition to the "v2"/appId directories, there are also the "local"/appId ones.
These directories store information only relevant to the application itself.
Its place inside the DecSync directory is just the (current) default location, but this is not required.
It could be placed anywhere, even outside the DecSync directory.
DecSync
├── calendars
│ └── colID12345
│ ├── local
│ │ ├── appId1
│ │ │ ├── info
│ │ │ └── sequences
│ │ └── appId2
│ │ ├── info
│ │ └── sequences
│ └── v2
│ ├── appId1
│ │ ├── 2f
│ │ ├── a7
│ │ ├── info
│ │ └── sequences
│ └── appId2
│ ├── 2f
│ ├── a7
│ ├── info
│ └── sequences
└── rss
├── local
│ ├── appId1
│ │ ├── info
│ │ └── sequences
│ └── appId2
│ ├── info
│ └── sequences
└── v2
├── appId1
│ ├── 0b
│ ├── b9
│ └── sequences
└── appId2
├── 0b
├── b9
└── sequences
With for example DecSync/rss/v2/appId1/b9:
[["feeds", "subscriptions"], "2020-07-17T12:34:56", "https://foo.example.com/rss", true]
[["feeds", "subscriptions"], "2020-07-17T12:35:56", "https://bar.example.com/rss", false]
[["feeds", "subscriptions"], "2020-07-17T12:36:56", "https://baz.example.com/rss", true]
DecSync/rss/v2/appId1/sequences:
{"0b": 1, "b9": 4}
DecSync/rss/local/appId2/info:
{"version": 2, "last-active": "2020-07-17"}
DecSync/rss/local/appId2/sequences:
{"appId1": {"0b": 1, "b9": 2}}
The entry files contain a list of entries separated by newlines.
Every entry is expressed by the JSON value [path, datetime, key, value], with path an array of strings, datetime a string and key and value arbitrary JSON values.
The name of the file is equal to the hash of path, whose definition is specified below.
The sequences file contains a JSON object mapping the hashes to their sequence numbers.
Inside the local directory the file sequences is stored.
This file contains a JSON object, mapping all other appIds to their last read sequence numbers.
Furthermore, there is a info file stored inside this directory, which is used for general operation of the DecSync directory unrelated to the current version.
The hash function hashes a path to an integer in [0, 256) expressed as two lowercase hexadecimal digits.
It is the polynomial hash modulo 256 of its hashed parts evaluated at 199.
That is, [s1, s2, ..., sn] is hashed to 199^(n-1)*h_s(s1) + 199^(n-2)*h_s(s2) + ... + 1*h_s(sn).
Here, h_s is the hash for the strings.
This is also a polynomial hash modulo 256, but over the UTF-8 bytestring and evaluated at 19.
That is, [b1, b2, ..., bn] is hashed to 19^(n-1)*b1 + 19^(n-2)*b2 + ... + 1*bn.
There is one exception to this: the hash of ["info"] is equal to info.
Here, the implementations of the most important methods are given, see also api.md.
- Remove any entry with the same
pathandkeyin the filehash(path). - Append the entry
[path, datetime-now, key, value]to the filehash(path), withdatetime-nowthe current datetime. - Increase the corresponding sequence number in
sequencesby 1, with a non-existing one treated as 0.
- Read the
sequencesfile in our local directory. - List all the files with updates by reading all other
sequencesfiles. - Read all the entries in the updates files.
- Filter out already up-to-date entries.
- Execute all the new entries.
- Add the new entries to our own entry files.
- Update the
sequencesfile in our local directory. - Do not update our own
sequencesfile, as the entries do not originate from us.
- Read the file
hash(path). - Filter out the entry corresponding to
pathandkey. - Execute the entry, if it exists.
- Read all the
infofiles in all directories. - Combine the results to get all most up-to-date entries.