The ChunkProcessor synchronizes specific chunks between source and destination MCA files by directly manipulating the Region File Format.
See src/region/chunk_processor.cc.
For each chunk coordinate
- Deletion: If a chunk exists in the destination but is missing in the source, the processor zeroes out the corresponding 4 bytes entry. This unlinks the chunk, marking its sectors as available.
- Addition: If a chunk is new, the processor reads the source data, finds a suitable gap in the destination using the Sector Map, and appends or inserts the data.
- In-place Overwrite: Used if the new data fits within the currently allocated sectors.
- Relocation: If the data grows, the old sectors are freed, and the chunk is moved to a new offset to prevent overwriting adjacent data.
- Condition: Exists in Destination, but missing in Source.
- Action: The processor zeroes out the 4-byte entry in the destination's location table. This effectively "unlinks" the chunk from the world, making the sectors available for future overwrites.
- Condition: Missing in Destination, but exists in Source.
- Action:
- Reads the chunk data from the source file.
- Scans the destination file for a gap (free sectors) using a sector map.
- If no suitable hole is found, it appends the data to the end of the file.
- Updates the destination's location table and sets the current timestamp.
- Condition: Exists in both Source and Destination.
- Action:
- In-place Overwrite: If the new chunk data fits within existing allocated sectors, the data is written directly to the same offset.
- Relocation: If the new data is larger than the allocated space, the processor:
- Marks the old sectors as free.
- Finds a new offset that can accommodate the larger size.
- Writes the data and updates the location table to point to the new offset.
| Component | Description |
|---|---|
| Location Table | A 4 KiB header where each 4-byte entry contains a 3-byte offset and a 1-byte sector count. |
| Sector Map | A bitset-like structure used to track which 4KiB sectors in the destination file are currently occupied. |
| Relocation | A mechanism to prevent file corruption when a chunk grows, ensuring it doesn't overwrite adjacent chunk data. |
- Sector Size: All operations are aligned to
kSectorSize(4 KiB). - Chunk Indexing: Calculated as ($(cx \ & \ 31) + ((cz \ & \ 31) \ll 5)$).
- Timestamp: The second 4 KiB page of the MCA file is updated with the current Unix timestamp whenever a chunk is modified.
- I/O Backend: All file access uses fast
MappedFile.
The FullRegionProcessor handles high-efficiency rollbacks when an entire region (32x32 chunks) needs to be restored. Instead of parsing internal MCA structures, it operates at the file-system level.
See src/region/full_region_processor.cc.
- Direct File Replacement: If a region is fully contained within the rollback boundaries, the processor replaces the destination
.mcafile with the source file. - Atomic Write:
- Opens the source MCA via
MappedFile(mmap). - Creates a
.tmpfile in the destination directory, sized to match the source. - Maps the
.tmpfile and copies data viamemcpywithmadvise(MADV_SEQUENTIAL)for prefetch optimization. - Calls
msync(MS_SYNC)to flush pages to disk before rename. - Renames the
.tmpfile to the final destination filename (atomic on same filesystem).- This ensures that a crash during the copy process doesn't leave the destination world with a corrupted or half-written region file.
- Opens the source MCA via
The RollbackExecutor is the multi-threaded orchestration engine. It determines the most efficient processing strategy (Full vs. Partial) based on the requested coordinates and manages the worker lifecycle.
See src/region/rollback_executor.cc.
The executor divides the world into "tasks" based on region boundaries (RollbackMode:
| Mode | Trigger Condition | Execution Strategy |
|---|---|---|
| FullCopy | The requested range completely covers the |
Uses FullRegionProcessor for instant file-level restoration. |
| Partial | The requested range only partially overlaps a region. | Uses ChunkProcessor to surgically update specific chunks within the file. |
- Worker Pool: Spawns a configurable number of worker threads (up to
std::hardware_concurrency). - Thread Safety: Uses a synchronized
std::queueprotected by astd::mutexandstd::condition_variableto distribute tasks. - Atomic Progress Tracking: Uses
std::atomic<u64>to track processed chunk counts across all threads without performance bottlenecks.
- Init: Loads configuration (paths, thread count, coordinates).
- Start: - Calculates the required regions.
- Pushes
RollbackTaskobjects into the queue. - Wakes up worker threads.
- Pushes
- Execution: Workers pull tasks and route them to either
FullRegionProcessororChunkProcessor. - Flush/Cleanup: Signals threads to stop and joins them, ensuring all I/O operations are completed before the application exits.
- User defines a 3D box
$(\min x, \min z)$ to$(\max X, \max Z)$ . - RollbackExecutor identifies all affected
.mcafiles forregion,entities, andpoi. - Region is fully contained within the box
$\implies$ pass to FullRegionProcessor (Fast). - Region is not fully contained within the box
$\implies$ pass to ChunkProcessor (Precise). - Workers perform the binary patching or file replacement in parallel.