Skip to content

Commit fe366fd

Browse files
committed
Update PR
* Update PR
1 parent 69016f0 commit fe366fd

3 files changed

Lines changed: 52 additions & 16 deletions

File tree

src/main.d

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,8 +1359,8 @@ int main(string[] cliArgs) {
13591359
}
13601360

13611361
// Handle any local filesystem events that occurred while the sync was running.
1362-
// Remote -> local generated events are drained inside the standard sync path
1363-
// immediately after online reconciliation, and inside oneDriveOnlineCallback().
1362+
// Remote-generated and genuine concurrent local events are both processed at
1363+
// each reconciliation boundary; database/hash checks suppress harmless echoes.
13641364
processInotifyEvents(true);
13651365

13661366
// Detail the outcome of the sync process
@@ -1680,8 +1680,12 @@ void oneDriveOnlineCallback() {
16801680
}
16811681
}
16821682
if (appConfig.getValueBool("monitor")) {
1683-
// Drain inotify events generated by online -> local reconciliation.
1684-
processInotifyEvents(false, true);
1683+
// Process every queued inotify event after online -> local reconciliation.
1684+
// The database and local filesystem have already been updated by the remote
1685+
// reconciliation, so self-generated events are naturally filtered by the
1686+
// existing database/hash checks. Genuine concurrent local events must not be
1687+
// consumed and discarded here.
1688+
processInotifyEvents(true);
16851689
}
16861690
}
16871691

@@ -1735,8 +1739,10 @@ void performStandardSyncProcess(string localPath, Monitor filesystemMonitor = nu
17351739
// Download data from OneDrive last
17361740
syncEngineInstance.syncOneDriveAccountToLocalDisk();
17371741
if (appConfig.getValueBool("monitor")) {
1738-
// Cancel out any inotify events from downloading data
1739-
processInotifyEvents(false, true);
1742+
// Process all queued inotify events. Events caused by the completed remote
1743+
// reconciliation are filtered by current database/hash state; concurrent
1744+
// local activity must remain actionable.
1745+
processInotifyEvents(true);
17401746
}
17411747

17421748
// At this point, we have done a sync from:
@@ -1754,8 +1760,10 @@ void performStandardSyncProcess(string localPath, Monitor filesystemMonitor = nu
17541760
// Download data from OneDrive first
17551761
syncEngineInstance.syncOneDriveAccountToLocalDisk();
17561762
if (appConfig.getValueBool("monitor")) {
1757-
// Cancel out any inotify events from downloading data
1758-
processInotifyEvents(false, true);
1763+
// Process all queued inotify events. Events caused by the completed remote
1764+
// reconciliation are filtered by current database/hash state; concurrent
1765+
// local activity must remain actionable.
1766+
processInotifyEvents(true);
17591767
}
17601768

17611769
// Perform the local database consistency check, picking up locally modified data and uploading this to OneDrive
@@ -1788,8 +1796,10 @@ void performStandardSyncProcess(string localPath, Monitor filesystemMonitor = nu
17881796
// If 'appConfig.fullScanTrueUpRequired' is true, we do not use the 'deltaLink' if we are in --monitor mode, thus forcing a full scan true up
17891797
syncEngineInstance.syncOneDriveAccountToLocalDisk();
17901798
if (appConfig.getValueBool("monitor")) {
1791-
// Cancel out any inotify events from downloading data
1792-
processInotifyEvents(false, true);
1799+
// Process all queued inotify events after the final online true-up.
1800+
// Never consume concurrent local changes merely because remote work
1801+
// also generated filesystem notifications.
1802+
processInotifyEvents(true);
17931803
}
17941804
} else {
17951805
// exitHandlerTriggered triggered

src/monitor.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import clientSideFiltering;
3030

3131
// Relevant inotify events
3232
version(FreeBSD) {
33-
private immutable uint32_t mask = IN_CLOSE_WRITE | IN_CREATE | IN_DELETE | IN_MOVE;
33+
private immutable uint32_t mask = IN_CLOSE_WRITE | IN_CREATE | IN_DELETE | IN_MOVE | IN_IGNORED | IN_Q_OVERFLOW;
3434
} else {
3535
private immutable uint32_t mask = IN_CLOSE_WRITE | IN_CREATE | IN_DELETE | IN_MOVE | IN_IGNORED | IN_Q_OVERFLOW;
3636
}

src/sync.d

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,6 +1227,8 @@ class SyncEngine {
12271227
JSONValue deltaChanges;
12281228
long responseBundleCount;
12291229
long jsonItemsReceived = 0;
1230+
bool preserveEstablishedDeltaLink = false;
1231+
string establishedDeltaLinkBeforeFullScan = null;
12301232

12311233
// Reset jsonItemsToProcess & processedCount
12321234
jsonItemsToProcess = [];
@@ -1321,8 +1323,25 @@ class SyncEngine {
13211323

13221324
// Do we need to perform a Full Scan True Up? Is 'appConfig.fullScanTrueUpRequired' set to 'true'?
13231325
if (appConfig.fullScanTrueUpRequired) {
1326+
// A tokenless /delta response is a snapshot of the current live state. It does not
1327+
// contain the deletion history represented by an established incremental deltaLink.
1328+
// Preserve that checkpoint so the next incremental pass still receives every change
1329+
// that occurred before or during this full-scan true-up.
1330+
establishedDeltaLinkBeforeFullScan = getDeltaLinkFromCache(deltaLinkInfo, driveIdToQuery);
1331+
if (establishedDeltaLinkBeforeFullScan.empty) {
1332+
establishedDeltaLinkBeforeFullScan = itemDB.getDeltaLink(driveIdToQuery, itemIdToQuery);
1333+
}
1334+
preserveEstablishedDeltaLink = !establishedDeltaLinkBeforeFullScan.empty;
1335+
13241336
addLogEntry("Performing a full scan of online data to ensure consistent local state");
1325-
if (debugLogging) {addLogEntry("Setting currentDeltaLink = null", ["debug"]);}
1337+
if (debugLogging) {
1338+
if (preserveEstablishedDeltaLink) {
1339+
addLogEntry("Preserving the established incremental deltaLink across this tokenless full scan", ["debug"]);
1340+
} else {
1341+
addLogEntry("No established incremental deltaLink exists; the tokenless full-scan checkpoint may be used to initialise delta tracking", ["debug"]);
1342+
}
1343+
addLogEntry("Setting currentDeltaLink = null", ["debug"]);
1344+
}
13261345
currentDeltaLink = null;
13271346
} else {
13281347
// Try and get the current Delta Link from the internal cache, this saves a DB I/O call
@@ -1460,10 +1479,17 @@ class SyncEngine {
14601479
}
14611480
}
14621481

1463-
// Update deltaLinkCache
1464-
deltaLinkCache.driveId = driveIdToQuery;
1465-
deltaLinkCache.itemId = itemIdToQuery;
1466-
deltaLinkCache.latestDeltaLink = currentDeltaLink;
1482+
// A scheduled tokenless full scan must not replace an established incremental
1483+
// checkpoint. The snapshot omits historical deletion tombstones, so advancing to
1484+
// its checkpoint can permanently skip changes that occurred around the scan.
1485+
if (preserveEstablishedDeltaLink) {
1486+
if (debugLogging) {addLogEntry("Not staging the tokenless full-scan deltaLink; the established incremental checkpoint remains authoritative", ["debug"]);}
1487+
} else {
1488+
// Update deltaLinkCache
1489+
deltaLinkCache.driveId = driveIdToQuery;
1490+
deltaLinkCache.itemId = itemIdToQuery;
1491+
deltaLinkCache.latestDeltaLink = currentDeltaLink;
1492+
}
14671493
}
14681494

14691495
// We have a valid deltaChanges JSON array. This means we have at least 200+ JSON items to process.

0 commit comments

Comments
 (0)