diff --git a/src/IOCoordinator.cpp b/src/IOCoordinator.cpp index 425751d15..b5782a046 100755 --- a/src/IOCoordinator.cpp +++ b/src/IOCoordinator.cpp @@ -476,21 +476,27 @@ void IOCoordinator::deleteMetaFile(const bf::path &file) tell cache they were deleted tell synchronizer to delete them in cloud storage */ + Synchronizer *synchronizer = Synchronizer::get(); ScopedWriteLock lock(this, file.string()); - MetadataFile meta(file.stem().string().c_str()); + MetadataFile meta(file); replicator->remove(file); lock.unlock(); vector objects = meta.metadataRead(0, meta.getLength()); vector deletedObjects; - bf::path journal; + bf::path journal, obj; + size_t size; for (auto &object : objects) { - size_t size = bf::file_size(object.key); - replicator->remove(cachePath/object.key); - cache->deletedObject(object.key, size); + obj = cachePath/object.key; + if (bf::exists(obj)) + { + size = bf::file_size(obj); + replicator->remove(obj); + cache->deletedObject(object.key, size); + } journal = journalPath/(object.key + ".journal"); if (bf::exists(journal)) { @@ -505,24 +511,33 @@ void IOCoordinator::deleteMetaFile(const bf::path &file) void IOCoordinator::remove(const bf::path &p) { + // recurse on dirs if (bf::is_directory(p)) { bf::directory_iterator dend; bf::directory_iterator entry(p); while (entry != dend) { - remove(p/(*entry)); + remove(*entry); ++entry; } bf::remove(p); return; } - bf::path possibleMetaFile = p.string() + ".meta"; - if (bf::is_regular_file(possibleMetaFile)) - deleteMetaFile(possibleMetaFile); + // if p is a metadata file call deleteMetaFile + if (p.extension() == ".meta" && bf::is_regular_file(p)) + deleteMetaFile(p); else - bf::remove(p); + { + // if we were passed a 'logical' file, it needs to have the meta extension added + bf::path possibleMetaFile = p.string() + ".meta"; + if (bf::is_regular_file(possibleMetaFile)) + deleteMetaFile(possibleMetaFile); + else + bf::remove(p); // if p.meta doesn't exist, and it's not a dir, then just throw it out + } + } /* Need to rename this one. The corresponding fcn in IDBFileSystem specifies that it @@ -548,6 +563,7 @@ int IOCoordinator::unlink(const char *path) } catch (bf::filesystem_error &e) { + cout << "IOC::unlink caught an error: " << e.what() << endl; errno = e.code().value(); return -1; } diff --git a/src/MetadataFile.cpp b/src/MetadataFile.cpp index 3b3f8344b..cbf794578 100755 --- a/src/MetadataFile.cpp +++ b/src/MetadataFile.cpp @@ -155,6 +155,39 @@ MetadataFile::MetadataFile(const char* filename, no_create_t) } } +MetadataFile::MetadataFile(const boost::filesystem::path &path) +{ + mpConfig = MetadataConfig::get(); + mpLogger = SMLogging::get(); + + mFilename = path.string(); + if (boost::filesystem::exists(path)) + { + _exists = true; + boost::property_tree::ptree jsontree; + boost::property_tree::read_json(mFilename, jsontree); + metadataObject newObject; + //try catch + mVersion = jsontree.get("version"); + mRevision = jsontree.get("revision"); + + BOOST_FOREACH(const boost::property_tree::ptree::value_type &v, jsontree.get_child("objects")) + { + metadataObject newObject; + newObject.offset = v.second.get("offset"); + newObject.length = v.second.get("length"); + newObject.key = v.second.get("key"); + mObjects.insert(newObject); + } + } + else + { + mVersion = 1; + mRevision = 1; + _exists = false; + } +} + MetadataFile::~MetadataFile() { } diff --git a/src/MetadataFile.h b/src/MetadataFile.h index 839656b95..3e376f457 100755 --- a/src/MetadataFile.h +++ b/src/MetadataFile.h @@ -13,6 +13,7 @@ #include #include #include +#include namespace storagemanager { @@ -33,6 +34,11 @@ class MetadataFile MetadataFile(); MetadataFile(const char* filename); MetadataFile(const char* filename, no_create_t); // this one won't create it if it doesn't exist + + // this ctor is 'special'. It will take an absolute path, and it will assume it points to a metafile + // meaning, that it doesn't need the metadata prefix prepended, or the .meta extension appended. + // aside from that, it will behave like the no_create ctor variant above + MetadataFile(const boost::filesystem::path &path); ~MetadataFile(); bool exists() const; diff --git a/src/unit_tests.cpp b/src/unit_tests.cpp index 6e0ab30ab..158caddb2 100755 --- a/src/unit_tests.cpp +++ b/src/unit_tests.cpp @@ -1228,12 +1228,68 @@ void IOCReadTest1() void IOCUnlink() { - cout << "IOCUnlink not implmemented yet" << endl; + IOCoordinator *ioc = IOCoordinator::get(); + CloudStorage *cs = CloudStorage::get(); + Cache *cache = Cache::get(); + Synchronizer *sync = Synchronizer::get(); + + cache->reset(); + + /* + Make a metadata file with a complex path + make the test object and test journal + delete it at the parent dir level + make sure the parent dir was deleted + make sure the object and journal were deleted + */ + + bf::path metaPath = ioc->getMetadataPath(); + bf::path cachePath = ioc->getCachePath(); + bf::path journalPath = ioc->getJournalPath(); + bf::path cachedObjPath = cachePath/testObjKey; + bf::path cachedJournalPath = journalPath/(string(testObjKey) + ".journal"); + bf::path basedir = "unlinktest"; + bf::path metadataFile = metaPath/basedir/(string(testFile) + ".meta"); + bf::create_directories(metaPath/basedir); + makeTestMetadata(metadataFile.string().c_str()); + makeTestObject(cachedObjPath.string().c_str()); + makeTestJournal(cachedJournalPath.string().c_str()); + + cache->newObject(cachedObjPath.filename().string(), bf::file_size(cachedObjPath)); + cache->newJournalEntry(bf::file_size(cachedJournalPath)); + vector keys; + keys.push_back(cachedObjPath.filename().string()); + sync->newObjects(keys); + //sync->newJournalEntry(keys[0]); don't want to end up renaming it + sleep(1); + + // ok, they should be fully 'in the system' now. + // verify that they are + assert(bf::exists(metaPath/basedir)); + assert(bf::exists(cachedObjPath)); + assert(bf::exists(cachedJournalPath)); + bool exists; + cs->exists(cachedObjPath.filename().string(), &exists); + assert(exists); + + int err = ioc->unlink(basedir.string().c_str()); + assert(err == 0); + + assert(!bf::exists(metaPath/basedir)); + assert(!bf::exists(cachedObjPath)); + assert(!bf::exists(cachedJournalPath)); + sleep(1); // stall for sync + cs->exists(cachedObjPath.filename().string(), &exists); + assert(!exists); + assert(cache->getCurrentCacheSize() == 0); + + cout << "IOC unlink test OK" << endl; } int main() { + std::size_t sizeKB = 1024; cout << "connecting" << endl; makeConnection();