-
Notifications
You must be signed in to change notification settings - Fork 4
NRS
It stands for Nu@ge Repository Storage.
NRS is the file format of the image of volumes and snapshots. A volume is divided into blocks of equal size. For a given offset in the volume, the NRS file contains the hash of a block while the block is stored in the IBS. See VVR for more details.
The header of the file describes the contents of the file and how it was created: the block size, the size of the hash, the size of the volume, ...
Each file has a UUID and a parent UUID. The tree of NRS files gives the history of the volumes and of the snapshots of a VVR.
Some files are not associated with a snapshot or a volume. For example, when a volume is resized, a new NRS file is created, but there is no new snapshot.
The NRS file header is a read-only information: once created, the header of a file is never written.
Field | Unit | Format | Size (bits) | Value |
---|---|---|---|---|
magic/version | constant+version | 3 char ASCII + 1 char ASCII | 32 | NRS1 |
parent ID | UUID | 128 | ID of the parent NRS file | |
device ID | UUID | 128 | ID of the device/volume which created the NRS file | |
node ID | UUID | 128 | root: current node; ID of the originating node, the node where the element was created and written |
|
ID | UUID | 128 | ID of this file | |
device size | bytes | uint64 | 64 | Size of the device |
block size | bytes | uint32 | 32 | 4096 by default |
cluster size | bytes | uint32 | 32 | 4096 by default |
value size | bytes | uint32 | 32 | hash size or block size (see work in progress) |
L1 offset | uint32 | 32 | Offset of L1 table | |
timestamp | milliseconds | uint64 | 64 | Creation date and time |
flags | uint32 | 32 | 0x00000001/ROOT: root snapshot 0x00000002/PARTIAL: partial item 0x00000004/BLOCK: file associated with a NRS block file (see work in progress) |
The fields are written in the 'big endian' format.
The header is 104 bytes long. The root file contains only the header and it is the only file where the device size is 0.
In NRS files (except the root file), the header is followed by the L1 table. This table contains the address of the L2 tables.
A L2 table contains the values for a segment of the volume. L2 tables are allocated when necessary; the size of a L2 table is the size of a cluster.
The number of values in the L2 table depends on the value size and on the cluster size. If the cluster size is 4096 bytes and the value size is 20 bytes (a SHA-1 digest), a L2 table contains 204 values. The size of the L1 table depends on the device size, the block size and the number of values in L2 tables. If the device size is 1 Gi, the block size 4096 bytes and the number of values 204, there are 262144 blocks, so we need 1285 L2 tables. A L2 table address takes 8 bytes, so the L1 table takes 10288 bytes (3 clusters).
Example of a NRS file
The L1 table is written in the first cluster after the header. The first L2 table is written in the first cluster after the L1 table. The first block written was the block index 140: the L2 table containing the value for that block was allocated after the L1 table and the address of the L2 table in the file is written in the L1 table. The last block written was the block index 12: the last L2 table allocated contains the value for that block.
This way of writing files is optimized for sparse files, but causes some overhead if the volume is completely written.
The TRIM operation, similar to the TRIM of SSD, is supported. The value associated to the block is marked as unreferenced. This leads to a better management of available storage by removing blocks from the IBS.
If the NRS is configured with remote peers, every modification of a file is sent to the peers in asynchronous mode. When the file is closed, the close operation waits for the flush of the pending messages. So, if the associated device is activated on another node, the NRS file parent of the new NRS file of the device will be up-to-date on this other node.
The remote update of the file is based on the version of the file: when the version is not the same, the digest of each cluster is send to another node (reference node). The clusters with different digest are copied from the reference to the destination file. This operation works even if the source file is opened in write mode.
-
NrsFileJanitor: This class is the public entry point to access to NRS files. It handles the creation, the deletion, the opening and the closing of NRS files. It makes sure that there only one instance in memory per file.
-
NrsFile: once opened with the NrsFileJanitor, a NRS file can be read and written as needed. The file is set read-only when the snapshot is taken to prevent from unexpected writes.
-
NrsMsgPostOffice: this class sends update messages to remote peers and handles the phases of the remote update operation.
Some blocks written in a device have very short life and are re-written. This is taken into account with the replace() method of the IBS. Still, some blocks are re-written and stay unreferenced in the IBS.
To avoid this situation, a new kind of NRS file have been created: the NrsFileBlock. Instead of containing hashes, it contains the blocks. Once the NRS file is set read-only or if the file system containing the NRS file gets full, the blocks are copied to the IBS and the NrsFileBlock file is removed.
For now, the NrsFileBlock exists, but is not yet associated to a NrsFile.