From ac882f86e2fd7aa9426e8ed71e18262999f27b16 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 12 Mar 2015 09:13:53 -0700 Subject: [PATCH] backup code is now aware of possible file extension differences --- libraries/entities/src/EntityTree.cpp | 26 ++++++-- libraries/octree/src/Octree.cpp | 66 ++++++++++---------- libraries/octree/src/Octree.h | 9 +++ libraries/octree/src/OctreePersistThread.cpp | 12 +++- 4 files changed, 74 insertions(+), 39 deletions(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index b2823f54ee..486cd0792d 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1040,8 +1040,21 @@ bool EntityTree::sendEntitiesOperation(OctreeElement* element, void* extraData) class ToMapOperator : public RecurseOctreeOperator { public: - ToMapOperator(QVariantMap& map) : RecurseOctreeOperator(), _map(map) {}; - bool preRecursion(OctreeElement* element) {return true;} + ToMapOperator(QVariantMap& map, OctreeElement *top) : RecurseOctreeOperator(), _map(map), _top(top) { + // if some element "top" was given, only save information for that element and it's children. + if (_top) { + _withinTop = false; + } else { + // top was NULL, export entire tree. + _withinTop = true; + } + }; + bool preRecursion(OctreeElement* element) { + if (element == _top) { + _withinTop = true; + } + return true; + } bool postRecursion(OctreeElement* element) { qDebug() << " in ToMapOperator::preRecursion"; EntityTreeElement* entityTreeElement = static_cast(element); @@ -1052,19 +1065,22 @@ public: entitiesQList << entityItem->writeToMap(); } _map["Entities"] = entitiesQList; + if (element == _top) { + _withinTop = false; + } return true; } private: QVariantMap& _map; + OctreeElement *_top; + bool _withinTop; }; bool EntityTree::writeToMap(QVariantMap& entityDescription, OctreeElement* element) { - - // XXX how can I make the RecurseOctreeOperator start with element? entityDescription["Entities"] = QVariantList(); - ToMapOperator theOperator(entityDescription); + ToMapOperator theOperator(entityDescription, element); recurseTreeWithOperator(&theOperator); return true; } diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 1adc374c70..68b1a3bc3c 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -46,6 +46,9 @@ #include "Octree.h" #include "ViewFrustum.h" + +QVector persistExtensions = {"svo", "json"}; + float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale) { return voxelSizeScale / powf(2, renderLevel); } @@ -1846,44 +1849,18 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element, } -QString withoutFileExtension(const QString& fileName) { - return fileName.left(fileName.lastIndexOf(".")); -} - - bool Octree::readFromFile(const char* fileName) { bool fileOk = false; - // try to ease migration from svo to json or back - QString svoFileName = withoutFileExtension(QString(fileName)) + ".svo"; - QFileInfo svoFileInfo(svoFileName); - QString jsonFileName = withoutFileExtension(QString(fileName)) + ".json"; - QFileInfo jsonFileInfo(jsonFileName); - QString qFileName; - QFileInfo fileInfo; - - if (jsonFileInfo.exists() && svoFileInfo.exists()) { - if (jsonFileInfo.lastModified() >= svoFileInfo.lastModified()) { - qFileName = jsonFileName; - fileInfo = jsonFileInfo; - } else { - qFileName = svoFileName; - fileInfo = svoFileInfo; - } - } else if (jsonFileInfo.exists()) { - qFileName = jsonFileName; - fileInfo = jsonFileInfo; - } else if (svoFileInfo.exists()) { - qFileName = svoFileName; - fileInfo = svoFileInfo; - } else { - qDebug() << "failed to read Octree from nonexistant file:" << fileName; - return false; - } + QString qFileName = findMostRecentPersist(fileName); + // QByteArray byteArray = qFileName.toUtf8(); + // const char* cFileName = byteArray.constData(); QFile file(qFileName); fileOk = file.open(QIODevice::ReadOnly); + QFileInfo fileInfo(qFileName); + if(fileOk) { QDataStream fileInputStream(&file); unsigned long fileLength = fileInfo.size(); @@ -2102,7 +2079,7 @@ void Octree::writeToFile(const char* fileName, OctreeElement* element, bool pers if (persistAsJson) { // make the sure file extension is correct. This isn't great, but it allows a user with // an existing .svo save to migrate. - QString qFileName = withoutFileExtension(QString(fileName)) + ".json"; + QString qFileName = fileNameWithoutExtension(QString(fileName), persistExtensions) + ".json"; QByteArray byteArray = qFileName.toUtf8(); const char* cFileName = byteArray.constData(); writeToJSONFile(cFileName, element); @@ -2231,3 +2208,28 @@ void Octree::cancelImport() { _stopImport = true; } +QString fileNameWithoutExtension(const QString& fileName, const QVector possibleExtensions) { + foreach (const QString possibleExtension, possibleExtensions) { + if (fileName.endsWith(possibleExtension) || + fileName.endsWith(possibleExtension.toUpper()) || + fileName.endsWith(possibleExtension.toLower())) { + return fileName.left(fileName.count() - possibleExtension.count() - 1); + } + } + return fileName; +} + +QString findMostRecentPersist(const QString& originalFileName) { + QString sansExt = fileNameWithoutExtension(originalFileName, persistExtensions); + QString newestFileName = originalFileName; + QDateTime newestTime = QDateTime::fromMSecsSinceEpoch(0); + foreach (QString possibleExtension, persistExtensions) { + QString fileName = sansExt + "." + possibleExtension; + QFileInfo fileInfo(fileName); + if (fileInfo.exists() && fileInfo.lastModified() > newestTime) { + newestFileName = fileName; + newestTime = fileInfo.lastModified(); + } + } + return newestFileName; +} diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 8ad59e8592..3a39ccfb42 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -35,6 +35,9 @@ class Shape; #include #include + +extern QVector persistExtensions; + /// derive from this class to use the Octree::recurseTreeWithOperator() method class RecurseOctreeOperator { public: @@ -410,4 +413,10 @@ protected: float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale); + +QString fileNameWithoutExtension(const QString& fileName, const QVector possibleExtensions); + +// XXX rename this +QString findMostRecentPersist(const QString& originalFileName); + #endif // hifi_Octree_h diff --git a/libraries/octree/src/OctreePersistThread.cpp b/libraries/octree/src/OctreePersistThread.cpp index dfe6e26b92..ee6ada7050 100644 --- a/libraries/octree/src/OctreePersistThread.cpp +++ b/libraries/octree/src/OctreePersistThread.cpp @@ -44,6 +44,14 @@ OctreePersistThread::OctreePersistThread(Octree* tree, const QString& filename, _persistAsJson(persistAsJson) { parseSettings(settings); + + QString sansExt = fileNameWithoutExtension(_filename, persistExtensions); + if (_persistAsJson) { + _filename = sansExt + "." + "json"; + } else { + _filename = sansExt + "." + "svo"; + } + } void OctreePersistThread::parseSettings(const QJsonObject& settings) { @@ -347,8 +355,8 @@ void OctreePersistThread::rollOldBackupVersions(const BackupRule& rule) { QString backupExtensionNplusOne = rule.extensionFormat; backupExtensionN.replace(QString("%N"), QString::number(n)); backupExtensionNplusOne.replace(QString("%N"), QString::number(n+1)); - - QString backupFilenameN = _filename + backupExtensionN; + + QString backupFilenameN = findMostRecentPersist(_filename) + backupExtensionN; QString backupFilenameNplusOne = _filename + backupExtensionNplusOne; QFile backupFileN(backupFilenameN);