Catch database assertion when item path cannot be calculated (#1217)

* Catch database assertion when item path cannot be calculated
This commit is contained in:
abraunegg 2021-01-15 14:44:13 +11:00 committed by GitHub
parent bbba32cc49
commit cef00e74b2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 10 deletions

View file

@ -388,6 +388,9 @@ final class ItemDatabase
} }
} else { } else {
// broken tree // broken tree
log.vdebug("The following generated a broken tree query:");
log.vdebug("Drive ID: ", driveId);
log.vdebug("Item ID: ", id);
assert(0); assert(0);
} }
} }

View file

@ -1760,7 +1760,8 @@ final class SyncEngine
// What is the original local path for this ID in the database? Does it match 'syncFolderChildPath' // What is the original local path for this ID in the database? Does it match 'syncFolderChildPath'
if (itemdb.idInLocalDatabase(driveId, item["id"].str)){ if (itemdb.idInLocalDatabase(driveId, item["id"].str)){
// item is in the database // item is in the database
string originalLocalPath = itemdb.computePath(driveId, item["id"].str); string originalLocalPath = computeItemPath(driveId, item["id"].str);
if (canFind(originalLocalPath, syncFolderChildPath)){ if (canFind(originalLocalPath, syncFolderChildPath)){
JSONValue oneDriveMovedNotDeleted; JSONValue oneDriveMovedNotDeleted;
try { try {
@ -1957,7 +1958,8 @@ final class SyncEngine
log.vdebug("skip_dir path to check (simple): ", simplePathToCheck); log.vdebug("skip_dir path to check (simple): ", simplePathToCheck);
// complex path // complex path
if (itemdb.idInLocalDatabase(parentDriveId, parentItem)){ 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); complexPathToCheck = buildNormalizedPath(complexPathToCheck);
} else { } else {
log.vdebug("Parent details not in database - unable to compute complex path to check"); log.vdebug("Parent details not in database - unable to compute complex path to check");
@ -2016,8 +2018,8 @@ final class SyncEngine
// is the parent id in the database? // is the parent id in the database?
if (itemdb.idInLocalDatabase(item.driveId, item.parentId)){ if (itemdb.idInLocalDatabase(item.driveId, item.parentId)){
// need to compute the full path for this file // Compute this item path & need the full path for this file
path = itemdb.computePath(item.driveId, item.parentId) ~ "/" ~ item.name; path = computeItemPath(item.driveId, item.parentId) ~ "/" ~ item.name;
// The path that needs to be checked needs to include the '/' // 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 // This due to if the user has specified in skip_file an exclusive path: '/path/file' - that is what must be matched
@ -2050,7 +2052,8 @@ final class SyncEngine
} else { } else {
// Why was this unwanted? // Why was this unwanted?
if (path.empty) { 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 // Microsoft OneNote container objects present as neither folder or file but has file size
if ((!isItemFile(driveItem)) && (!isItemFolder(driveItem)) && (hasFileSize(driveItem))) { if ((!isItemFile(driveItem)) && (!isItemFolder(driveItem)) && (hasFileSize(driveItem))) {
@ -2069,8 +2072,8 @@ final class SyncEngine
if (!unwanted) { if (!unwanted) {
// Is the item parent in the local database? // Is the item parent in the local database?
if (itemdb.idInLocalDatabase(item.driveId, item.parentId)){ if (itemdb.idInLocalDatabase(item.driveId, item.parentId)){
// compute the item path to see if the path is excluded // compute the item path to see if the path is excluded & need the full path for this file
path = itemdb.computePath(item.driveId, item.parentId) ~ "/" ~ item.name; path = computeItemPath(item.driveId, item.parentId) ~ "/" ~ item.name;
path = buildNormalizedPath(path); path = buildNormalizedPath(path);
if (selectiveSync.isPathExcludedViaSyncList(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? // selective sync advised to skip, however is this a file and are we configured to upload / download files in the root?
@ -2165,7 +2168,8 @@ final class SyncEngine
// Is the item in the local database // Is the item in the local database
if (itemdb.idInLocalDatabase(item.driveId, item.id)){ if (itemdb.idInLocalDatabase(item.driveId, item.id)){
log.vdebug("OneDrive item ID is present in local database"); 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 // Query DB for existing local item in specified path
string itemSource = "database"; string itemSource = "database";
if (!isItemSynced(oldItem, oldPath, itemSource)) { if (!isItemSynced(oldItem, oldPath, itemSource)) {
@ -2781,8 +2785,11 @@ final class SyncEngine
{ {
foreach_reverse (i; idsToDelete) { foreach_reverse (i; idsToDelete) {
Item item; Item item;
string path;
if (!itemdb.selectById(i[0], i[1], item)) continue; // check if the item is in the db 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); log.log("Trying to delete item ", path);
if (!dryRun) { if (!dryRun) {
// Actually process the database entry removal // Actually process the database entry removal
@ -3100,7 +3107,9 @@ final class SyncEngine
string path; string path;
// Compute this item path early as we we use this path often // 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)); log.vlog("Processing ", buildNormalizedPath(path));
// What type of DB item are we processing // What type of DB item are we processing
@ -6199,4 +6208,22 @@ final class SyncEngine
log.error("ERROR: onedrive.getSharedWithMe call returned an invalid JSON Object"); 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;
}
} }