Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Catch database assertion when item path cannot be calculated #1217

Merged
merged 3 commits into from
Jan 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/itemdb.d
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,9 @@ final class ItemDatabase
}
} else {
// broken tree
log.vdebug("The following generated a broken tree query:");
log.vdebug("Drive ID: ", driveId);
log.vdebug("Item ID: ", id);
assert(0);
}
}
Expand Down
47 changes: 37 additions & 10 deletions src/sync.d
Original file line number Diff line number Diff line change
Expand Up @@ -1760,7 +1760,8 @@ final class SyncEngine
// What is the original local path for this ID in the database? Does it match 'syncFolderChildPath'
if (itemdb.idInLocalDatabase(driveId, item["id"].str)){
// item is in the database
string originalLocalPath = itemdb.computePath(driveId, item["id"].str);
string originalLocalPath = computeItemPath(driveId, item["id"].str);

if (canFind(originalLocalPath, syncFolderChildPath)){
JSONValue oneDriveMovedNotDeleted;
try {
Expand Down Expand Up @@ -1957,7 +1958,8 @@ final class SyncEngine
log.vdebug("skip_dir path to check (simple): ", simplePathToCheck);
// complex path
if (itemdb.idInLocalDatabase(parentDriveId, parentItem)){
complexPathToCheck = itemdb.computePath(parentDriveId, parentItem) ~ "/" ~ driveItem["name"].str;
// build up complexPathToCheck
complexPathToCheck = computeItemPath(parentDriveId, parentItem) ~ "/" ~ driveItem["name"].str;
complexPathToCheck = buildNormalizedPath(complexPathToCheck);
} else {
log.vdebug("Parent details not in database - unable to compute complex path to check");
Expand Down Expand Up @@ -2016,8 +2018,8 @@ final class SyncEngine

// is the parent id in the database?
if (itemdb.idInLocalDatabase(item.driveId, item.parentId)){
// need to compute the full path for this file
path = itemdb.computePath(item.driveId, item.parentId) ~ "/" ~ item.name;
// Compute this item path & need the full path for this file
path = computeItemPath(item.driveId, item.parentId) ~ "/" ~ item.name;

// The path that needs to be checked needs to include the '/'
// This due to if the user has specified in skip_file an exclusive path: '/path/file' - that is what must be matched
Expand Down Expand Up @@ -2050,7 +2052,8 @@ final class SyncEngine
} else {
// Why was this unwanted?
if (path.empty) {
path = itemdb.computePath(item.driveId, item.parentId) ~ "/" ~ item.name;
// Compute this item path & need the full path for this file
path = computeItemPath(item.driveId, item.parentId) ~ "/" ~ item.name;
}
// Microsoft OneNote container objects present as neither folder or file but has file size
if ((!isItemFile(driveItem)) && (!isItemFolder(driveItem)) && (hasFileSize(driveItem))) {
Expand All @@ -2069,8 +2072,8 @@ final class SyncEngine
if (!unwanted) {
// Is the item parent in the local database?
if (itemdb.idInLocalDatabase(item.driveId, item.parentId)){
// compute the item path to see if the path is excluded
path = itemdb.computePath(item.driveId, item.parentId) ~ "/" ~ item.name;
// compute the item path to see if the path is excluded & need the full path for this file
path = computeItemPath(item.driveId, item.parentId) ~ "/" ~ item.name;
path = buildNormalizedPath(path);
if (selectiveSync.isPathExcludedViaSyncList(path)) {
// selective sync advised to skip, however is this a file and are we configured to upload / download files in the root?
Expand Down Expand Up @@ -2165,7 +2168,8 @@ final class SyncEngine
// Is the item in the local database
if (itemdb.idInLocalDatabase(item.driveId, item.id)){
log.vdebug("OneDrive item ID is present in local database");
oldPath = itemdb.computePath(item.driveId, item.id);
// Compute this item path
oldPath = computeItemPath(item.driveId, item.id);
// Query DB for existing local item in specified path
string itemSource = "database";
if (!isItemSynced(oldItem, oldPath, itemSource)) {
Expand Down Expand Up @@ -2781,8 +2785,11 @@ final class SyncEngine
{
foreach_reverse (i; idsToDelete) {
Item item;
string path;
if (!itemdb.selectById(i[0], i[1], item)) continue; // check if the item is in the db
const(string) path = itemdb.computePath(i[0], i[1]);
// Compute this item path
path = computeItemPath(i[0], i[1]);
// Try to delete item object
log.log("Trying to delete item ", path);
if (!dryRun) {
// Actually process the database entry removal
Expand Down Expand Up @@ -3100,7 +3107,9 @@ final class SyncEngine
string path;

// Compute this item path early as we we use this path often
path = itemdb.computePath(item.driveId, item.id);
path = computeItemPath(item.driveId, item.id);

// item.id was in the database associated with the item.driveId specified
log.vlog("Processing ", buildNormalizedPath(path));

// What type of DB item are we processing
Expand Down Expand Up @@ -6199,4 +6208,22 @@ final class SyncEngine
log.error("ERROR: onedrive.getSharedWithMe call returned an invalid JSON Object");
}
}

// Query itemdb.computePath() and catch potential assert when DB consistency issue occurs
string computeItemPath(string thisDriveId, string thisItemId)
{
string calculatedPath;
log.vdebug("Attempting to calculate local filesystem path for ", thisDriveId, " and ", thisItemId);
try {
calculatedPath = itemdb.computePath(thisDriveId, thisItemId);
} catch (core.exception.AssertError) {
// broken tree in the database, we cant compute the path for this item id, exit
log.error("ERROR: A database consistency issue has been caught. A --resync is needed to rebuild the database.");
// Must exit here to preserve data
exit(-1);
}

// return calculated path as string
return calculatedPath;
}
}