------------------------------------------------------------ revno: 3157 committer: poy <p...@123gen.com> branch nick: trunk timestamp: Mon 2012-12-17 18:07:08 +0100 message: rename case-insensitive duplicated directories modified: dcpp/ShareManager.cpp dcpp/ShareManager.h
-- lp:dcplusplus https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk Your team Dcplusplus-team is subscribed to branch lp:dcplusplus. To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'dcpp/ShareManager.cpp' --- dcpp/ShareManager.cpp 2012-12-14 17:07:25 +0000 +++ dcpp/ShareManager.cpp 2012-12-17 17:07:08 +0000 @@ -85,6 +85,10 @@ { } +const string& ShareManager::Directory::getRealName() const noexcept { + return realName ? realName.get() : name; +} + string ShareManager::Directory::getADCPath() const noexcept { if(!getParent()) return '/' + name + '/'; @@ -107,9 +111,9 @@ string ShareManager::Directory::getRealPath(const std::string& path) const { if(getParent()) { - return getParent()->getRealPath(getName() + PATH_SEPARATOR_STR + path); + return getParent()->getRealPath(getRealName() + PATH_SEPARATOR_STR + path); } else { - return ShareManager::getInstance()->findRealRoot(getName(), path); + return ShareManager::getInstance()->findRealRoot(getRealName(), path); } } @@ -288,12 +292,12 @@ throw ShareException(UserConnection::FILE_NOT_AVAILABLE); } - auto dmi = getByVirtual( virtualPath.substr(1, i - 1)); + auto dmi = directories.find(virtualPath.substr(1, i - 1)); if(dmi == directories.end()) { throw ShareException(UserConnection::FILE_NOT_AVAILABLE); } - auto d = *dmi; + auto d = dmi->second; auto j = i + 1; while((i = virtualPath.find('/', j)) != string::npos) { @@ -336,7 +340,7 @@ bool ShareManager::hasVirtual(const string& virtualName) const noexcept { Lock l(cs); - return getByVirtual(virtualName) != directories.end(); + return directories.find(virtualName) != directories.end(); } void ShareManager::load(SimpleXML& aXml) { @@ -358,8 +362,8 @@ const string& virtualName = aXml.getChildAttrib("Virtual"); string vName = validateVirtual(virtualName.empty() ? Util::getLastDir(realPath) : virtualName); shares[move(realPath)] = vName; - if(getByVirtual(vName) == directories.end()) { - directories.push_back(Directory::create(vName)); + if(directories.find(vName) == directories.end()) { + directories[vName] = Directory::create(vName); } } aXml.stepOut(); @@ -373,17 +377,15 @@ static const string STTH = "TTH"; struct ShareLoader : public SimpleXMLReader::CallBack { - ShareLoader(ShareManager::DirList& aDirs) : dirs(aDirs), cur(0), depth(0) { } + ShareLoader(decltype(ShareManager::directories)& aDirs) : dirs(aDirs), cur(0), depth(0) { } void startTag(const string& name, StringPairList& attribs, bool simple) { if(name == SDIRECTORY) { const string& name = getAttrib(attribs, SNAME, 0); if(!name.empty()) { if(depth == 0) { - for(auto& i: dirs) { - if(Util::stricmp(i->getName(), name) == 0) { - cur = i; - break; - } + auto i = dirs.find(name); + if(i != dirs.end()) { + cur = i->second; } } else if(cur) { cur = ShareManager::Directory::create(name, cur); @@ -419,7 +421,7 @@ } private: - ShareManager::DirList& dirs; + decltype(ShareManager::directories)& dirs; ShareManager::Directory::Ptr cur; size_t depth; @@ -435,8 +437,8 @@ xml.parse(f); - for(const auto& d: directories) { - updateIndices(*d); + for(const auto& i: directories) { + updateIndices(*i.second); } return true; @@ -487,7 +489,7 @@ HashManager::HashPauser pauser; - Directory::Ptr dp = buildTree(realPath, Directory::Ptr()); + auto dp = buildTree(realPath); string vName = validateVirtual(virtualName); dp->setName(vName); @@ -503,17 +505,16 @@ } ShareManager::Directory::Ptr ShareManager::merge(const Directory::Ptr& directory, const string& realPath) { - for(auto& i: directories) { - if(Util::stricmp(i->getName(), directory->getName()) == 0) { - dcdebug("Merging directory <%s> into %s\n", realPath.c_str(), directory->getName().c_str()); - i->merge(directory, realPath); - return i; - } + auto i = directories.find(directory->getName()); + if(i != directories.end()) { + dcdebug("Merging directory <%s> into %s\n", realPath.c_str(), directory->getName().c_str()); + i->second->merge(directory, realPath); + return i->second; } dcdebug("Adding new directory %s\n", directory->getName().c_str()); - directories.push_back(directory); + directories[directory->getName()] = directory; return directory; } @@ -570,7 +571,7 @@ vname = base + " (" + Util::toString(num) + ")" + ext; } while(parent->nameInUse(vname)); dcdebug("Renaming duplicate <%s> to <%s>\n", name.c_str(), vname.c_str()); - realPath = sourcePath + name; + realPath = sourcePath + move(name); name = move(vname); } else { realPath.reset(); @@ -591,13 +592,7 @@ } auto vName = i->second; - for(auto j = directories.begin(); j != directories.end(); ) { - if(Util::stricmp((*j)->getName(), vName) == 0) { - directories.erase(j++); - } else { - ++j; - } - } + directories.erase(vName); shares.erase(i); @@ -606,7 +601,7 @@ // Readd all directories with the same vName for(i = shares.begin(); i != shares.end(); ++i) { if(Util::stricmp(i->second, vName) == 0 && checkHidden(i->first)) { - Directory::Ptr dp = buildTree(i->first, 0); + auto dp = buildTree(i->first); dp->setName(i->second); merge(dp, i->first); } @@ -621,24 +616,15 @@ addDirectory(realPath, virtualName); } -ShareManager::DirList::const_iterator ShareManager::getByVirtual(const string& virtualName) const noexcept { - for(auto i = directories.begin(); i != directories.end(); ++i) { - if(Util::stricmp((*i)->getName(), virtualName) == 0) { - return i; - } - } - return directories.end(); -} - int64_t ShareManager::getShareSize(const string& realPath) const noexcept { Lock l(cs); dcassert(realPath.size()>0); auto i = shares.find(realPath); if(i != shares.end()) { - auto j = getByVirtual(i->second); + auto j = directories.find(i->second); if(j != directories.end()) { - return (*j)->getSize(); + return j->second->getSize(); } } return -1; @@ -658,27 +644,25 @@ return tthIndex.size(); } -ShareManager::Directory::Ptr ShareManager::buildTree(const string& aName, const Directory::Ptr& aParent) { - auto dir = Directory::create(Util::getLastDir(aName), aParent); +ShareManager::Directory::Ptr ShareManager::buildTree(const string& realPath, optional<const string&> dirName, const Directory::Ptr& parent) { + auto dir = Directory::create(dirName ? dirName.get() : Util::getLastDir(realPath), parent); auto lastFileIter = dir->files.begin(); - FileFindIter end; #ifdef _WIN32 - for(FileFindIter i(aName + "*"); i != end; ++i) { + for(FileFindIter i(realPath + "*"), end; i != end; ++i) { #else //the fileiter just searches directorys for now, not sure if more //will be needed later - //for(FileFindIter i(aName + "*"); i != end; ++i) { - for(FileFindIter i(aName); i != end; ++i) { + for(FileFindIter i(realPath), end; i != end; ++i) { #endif - string name = i->getFileName(); + auto name = i->getFileName(); if(name.empty()) { - LogManager::getInstance()->message(str(F_("Invalid file name found while hashing folder %1%") % Util::addBrackets(aName))); + LogManager::getInstance()->message(str(F_("Invalid file name found while hashing folder %1%") % Util::addBrackets(realPath))); continue; } - + if(name == "." || name == "..") continue; if(!SETTING(SHARE_HIDDEN) && i->isHidden()) @@ -687,24 +671,39 @@ continue; if(i->isDirectory()) { - string newName = aName + name + PATH_SEPARATOR; - if(Util::stricmp(newName, SETTING(TEMP_DOWNLOAD_DIRECTORY)) != 0) { - dir->directories[name] = buildTree(newName, dir); - } + auto newRealPath = realPath + name + PATH_SEPARATOR; + + // don't share unfinished downloads + if(newRealPath == SETTING(TEMP_DOWNLOAD_DIRECTORY)) { continue; } + + auto virtualName = name; + if(dir->nameInUse(virtualName)) { + uint32_t num = 0; + do { + ++num; + virtualName = name + " (" + Util::toString(num) + ")"; + } while(dir->nameInUse(virtualName)); + } + + dir->directories[virtualName] = buildTree(newRealPath, virtualName, dir); + + if(virtualName != name) { + dir->directories[virtualName]->setRealName(move(name)); + } + } else { // Not a directory, assume it's a file...make sure we're not sharing the settings file... - if(Util::stricmp(name.c_str(), "DCPlusPlus.xml") == 0 || - Util::stricmp(name.c_str(), "Favorites.xml") == 0) { continue; } + if(name == "DCPlusPlus.xml" || name == "Favorites.xml") { continue; } - int64_t size = i->getSize(); - string fileName = aName + name; + auto size = i->getSize(); + auto fileName = realPath + name; // don't share the private key file - if(Util::stricmp(fileName, SETTING(TLS_PRIVATE_KEY_FILE)) == 0) { continue; } + if(fileName == SETTING(TLS_PRIVATE_KEY_FILE)) { continue; } Directory::File f(name, size, dir, HashManager::getInstance()->getTTH(fileName, size, i->getLastWriteTime())); - f.validateName(aName); + f.validateName(realPath); lastFileIter = dir->files.insert(lastFileIter, move(f)); } } @@ -712,8 +711,8 @@ return dir; } -bool ShareManager::checkHidden(const string& aName) const { - FileFindIter ff = FileFindIter(aName.substr(0, aName.size() - 1)); +bool ShareManager::checkHidden(const string& realPath) const { + FileFindIter ff = FileFindIter(realPath.substr(0, realPath.size() - 1)); if (ff != FileFindIter()) { return (SETTING(SHARE_HIDDEN) || !ff->isHidden()); @@ -741,11 +740,11 @@ bloom.clear(); for(auto& i: directories) { - updateIndices(*i); + updateIndices(*i.second); } } -void ShareManager::updateIndices(Directory& dir, const Directory::File::Set::iterator& i) { +void ShareManager::updateIndices(Directory& dir, const decltype(std::declval<Directory>().files.begin())& i) { const Directory::File& f = *i; if(!f.tth) { @@ -826,7 +825,7 @@ vector<pair<Directory::Ptr, string>> newDirs; for(auto& i: dirs) { if (checkHidden(i.second)) { - Directory::Ptr dp = buildTree(i.second, Directory::Ptr()); + auto dp = buildTree(i.second); dp->setName(i.first); newDirs.emplace_back(dp, i.second); } @@ -888,7 +887,7 @@ newXmlFile.write(SimpleXML::utf8Header); newXmlFile.write("<FileListing Version=\"1\" CID=\"" + ClientManager::getInstance()->getMe()->getCID().toBase32() + "\" Base=\"/\" Generator=\"" APPNAME " " VERSIONSTRING "\">\r\n"); for(auto& i: directories) { - i->toXml(newXmlFile, indent, tmp2, -1); + i.second->toXml(newXmlFile, indent, tmp2, -1); } newXmlFile.write("</FileListing>"); newXmlFile.flush(); @@ -941,7 +940,7 @@ if(dir == "/") { for(auto& i: directories) { tmp.clear(); - i->toXml(sos, indent, tmp, recurse ? -1 : 0); + i.second->toXml(sos, indent, tmp, recurse ? -1 : 0); } } else { string::size_type i = 1, j = 1; @@ -957,11 +956,10 @@ if(first) { first = false; - auto it = getByVirtual(dir.substr(j, i-j)); - + auto it = directories.find(dir.substr(j, i-j)); if(it == directories.end()) return 0; - root = *it; + root = it->second; } else { auto it2 = root->directories.find(dir.substr(j, i-j)); @@ -1254,7 +1252,7 @@ return; for(auto j = directories.begin(); (j != directories.end()) && (results.size() < maxResults); ++j) { - (*j)->search(results, ssl, aSearchType, aSize, aFileType, aClient, maxResults); + j->second->search(results, ssl, aSearchType, aSize, aFileType, aClient, maxResults); } } @@ -1410,37 +1408,42 @@ } for(auto j = directories.begin(); (j != directories.end()) && (results.size() < maxResults); ++j) { - (*j)->search(results, srch, maxResults); + j->second->search(results, srch, maxResults); } } ShareManager::Directory::Ptr ShareManager::getDirectory(const string& realPath) noexcept { for(auto& mi: shares) { if(Util::strnicmp(realPath, mi.first, mi.first.length()) == 0) { - Directory::Ptr d; - for(auto& i: directories) { - if(Util::stricmp(i->getName(), mi.second) == 0) { - d = i; - } - } - - if(!d) { - return Directory::Ptr(); - } + auto di = directories.find(mi.second); + if(di == directories.end()) { + return nullptr; + } + auto d = di->second; string::size_type i; string::size_type j = mi.first.length(); - while( (i = realPath.find(PATH_SEPARATOR, j)) != string::npos) { - auto dmi = d->directories.find(realPath.substr(j, i-j)); + while((i = realPath.find(PATH_SEPARATOR, j)) != string::npos) { + auto dirName = realPath.substr(j, i - j); + + auto& subDirs = d->directories; + d.reset(); + for(auto& subDir: subDirs) { + if(subDir.second->getRealName() == dirName) { + d = subDir.second; + break; + } + } + if(!d) { + return nullptr; + } + j = i + 1; - if(dmi == d->directories.end()) - return Directory::Ptr(); - d = dmi->second; } return d; } } - return Directory::Ptr(); + return nullptr; } optional<const ShareManager::Directory::File&> ShareManager::getFile(const string& realPath, Directory::Ptr d) noexcept { === modified file 'dcpp/ShareManager.h' --- dcpp/ShareManager.h 2012-12-13 17:50:01 +0000 +++ dcpp/ShareManager.h 2012-12-17 17:07:08 +0000 @@ -19,7 +19,6 @@ #ifndef DCPLUSPLUS_DCPP_SHARE_MANAGER_H #define DCPLUSPLUS_DCPP_SHARE_MANAGER_H -#include <list> #include <map> #include <memory> #include <set> @@ -130,10 +129,16 @@ class Directory : public FastAlloc<Directory>, public intrusive_ptr_base<Directory>, boost::noncopyable { public: typedef boost::intrusive_ptr<Directory> Ptr; - typedef unordered_map<string, Ptr, noCaseStringHash, noCaseStringEq> Map; - typedef Map::iterator MapIter; struct File { + File() : size(0), parent(0) { } + File(const string& aName, int64_t aSize, const Directory::Ptr& aParent, const optional<TTHValue>& aRoot) : + name(aName), tth(aRoot), size(aSize), parent(aParent.get()) { } + + bool operator==(const File& rhs) const { + return getParent() == rhs.getParent() && (Util::stricmp(getName(), rhs.getName()) == 0); + } + struct StringComp { StringComp(const string& s) : a(s) { } bool operator()(const File& b) const { return Util::stricmp(a, b.getName()) == 0; } @@ -142,15 +147,6 @@ struct FileLess { bool operator()(const File& a, const File& b) const { return (Util::stricmp(a.getName(), b.getName()) < 0); } }; - typedef set<File, FileLess> Set; - - File() : size(0), parent(0) { } - File(const string& aName, int64_t aSize, const Directory::Ptr& aParent, const optional<TTHValue>& aRoot) : - name(aName), tth(aRoot), size(aSize), parent(aParent.get()) { } - - bool operator==(const File& rhs) const { - return getParent() == rhs.getParent() && (Util::stricmp(getName(), rhs.getName()) == 0); - } /** Ensure this file's name doesn't clash with the names of the parent directory's sub- directories or files; rename to "file (N).ext" otherwise (and set realPath to the @@ -170,8 +166,8 @@ }; int64_t size; - Map directories; - File::Set files; + unordered_map<string, Ptr, noCaseStringHash, noCaseStringEq> directories; + set<File, File::FileLess> files; static Ptr create(const string& aName, const Ptr& aParent = Ptr()) { return Ptr(new Directory(aName, aParent)); } @@ -180,6 +176,9 @@ } void addType(uint32_t type) noexcept; + const string& getRealName() const noexcept; + template<typename SetT> void setRealName(SetT&& realName) noexcept { this->realName = std::forward<SetT>(realName); } + string getADCPath() const noexcept; string getFullName() const noexcept; string getRealPath(const std::string& path) const; @@ -197,21 +196,23 @@ void toXml(OutputStream& xmlFile, string& indent, string& tmp2, int8_t level) const; void filesToXml(OutputStream& xmlFile, string& indent, string& tmp2) const; - File::Set::const_iterator findFile(const string& aFile) const { return find_if(files.begin(), files.end(), Directory::File::StringComp(aFile)); } + auto findFile(const string& aFile) const -> decltype(files.cbegin()) { return find_if(files.begin(), files.end(), File::StringComp(aFile)); } void merge(const Ptr& source, const string& realPath); GETSET(string, name, Name); GETSET(Directory*, parent, Parent); + private: friend void intrusive_ptr_release(intrusive_ptr_base<Directory>*); Directory(const string& aName, const Ptr& aParent); ~Directory() { } + optional<string> realName; // only defined if this directory had to be renamed to avoid duplication. + /** Set of flags that say which SearchManager::TYPE_* a directory contains */ uint32_t fileTypes; - }; friend class Directory; @@ -264,8 +265,7 @@ mutable CriticalSection cs; // List of root directory items - typedef std::list<Directory::Ptr> DirList; - DirList directories; + unordered_map<string, Directory::Ptr, noCaseStringHash, noCaseStringEq> directories; /** Map real name to virtual name - multiple real names may be mapped to a single virtual one. The map is sorted to make sure conflicts are always resolved in the same order when merging. */ @@ -277,19 +277,18 @@ const Directory::File& findFile(const string& virtualFile) const; - Directory::Ptr buildTree(const string& aName, const Directory::Ptr& aParent); - bool checkHidden(const string& aName) const; + Directory::Ptr buildTree(const string& realPath, optional<const string&> dirName = nullptr, const Directory::Ptr& parent = nullptr); + bool checkHidden(const string& realPath) const; void rebuildIndices(); void updateIndices(Directory& aDirectory); - void updateIndices(Directory& dir, const Directory::File::Set::iterator& i); + void updateIndices(Directory& dir, const decltype(std::declval<Directory>().files.begin())& i); Directory::Ptr merge(const Directory::Ptr& directory, const string& realPath); void generateXmlList(); bool loadCache() noexcept; - DirList::const_iterator getByVirtual(const string& virtualName) const noexcept; pair<Directory::Ptr, string> splitVirtual(const string& virtualPath) const; string findRealRoot(const string& virtualRoot, const string& virtualLeaf) const;
_______________________________________________ Mailing list: https://launchpad.net/~linuxdcpp-team Post to : linuxdcpp-team@lists.launchpad.net Unsubscribe : https://launchpad.net/~linuxdcpp-team More help : https://help.launchpad.net/ListHelp