// ********************************************************************** // // Copyright (c) 2002 // Mutable Realms, Inc. // Huntsville, AL, USA // // All Rights Reserved // // ********************************************************************** #include #include using namespace std; using namespace Ice; using namespace IcePatch; IceUtil::RWRecMutex IcePatch::FileI::_globalMutex; IcePatch::FileI::FileI(const ObjectAdapterPtr& adapter) : _adapter(adapter), _logger(adapter->getCommunicator()->getLogger()) { PropertiesPtr properties = adapter->getCommunicator()->getProperties(); _traceLevel = properties->getPropertyAsInt("IcePatch.Trace.Files"); _busyTimeout = IceUtil::Time::seconds(properties->getPropertyAsIntWithDefault("IcePatch.BusyTimeout", 10)); } IcePatch::DirectoryI::DirectoryI(const ObjectAdapterPtr& adapter) : FileI(adapter) { } FileDescPtr IcePatch::DirectoryI::describe(const Ice::Current& current) { // No lock necessary. string path = identityToPath(current.id); DirectoryDescPtr desc = new DirectoryDesc; desc->directory = DirectoryPrx::uncheckedCast(_adapter->createProxy(current.id)); return desc; } FileDescSeq IcePatch::DirectoryI::getContents(const Ice::Current& current) { StringSeq filteredPaths; try { IceUtil::RWRecMutex::TryRLock sync(_globalMutex, _busyTimeout); bool syncUpgraded = false; string path = identityToPath(current.id); StringSeq paths = readDirectory(path); filteredPaths.reserve(paths.size() / 3); for(StringSeq::const_iterator p = paths.begin(); p != paths.end(); ++p) { if(ignoreSuffix(*p)) { pair r = equal_range(paths.begin(), paths.end(), removeSuffix(*p)); if(r.first == r.second) { if(!syncUpgraded) { sync.timedUpgrade(_busyTimeout); syncUpgraded = true; } StringSeq paths2 = readDirectory(path); pair r2 = equal_range(paths2.begin(), paths2.end(), removeSuffix(*p)); if(r2.first == r2.second) { removeRecursive(*p); if(_traceLevel > 0) { Trace out(_logger, "IcePatch"); out << "removed orphaned file `" << *p << "'"; } } } } else { filteredPaths.push_back(*p); } } } catch(const IceUtil::LockedException&) { throw BusyException(); } // // Call describe() outside the thread synchronization, to avoid // deadlocks. // FileDescSeq result; result.reserve(filteredPaths.size()); for(StringSeq::const_iterator p = filteredPaths.begin(); p != filteredPaths.end(); ++p) { FilePrx file = FilePrx::uncheckedCast(_adapter->createProxy(pathToIdentity(*p))); try { result.push_back(file->describe()); } catch(const ObjectNotExistException&) { // // Ignore. This can for example happen if the file // locator cannot call stat() on the file. // } } return result; } IcePatch::RegularI::RegularI(const ObjectAdapterPtr& adapter) : FileI(adapter) { } FileDescPtr IcePatch::RegularI::describe(const Ice::Current& current) { try { IceUtil::RWRecMutex::TryRLock sync(_globalMutex, _busyTimeout); string path = identityToPath(current.id); FileInfo info = getFileInfo(path, true); FileInfo infoMD5 = getFileInfo(path + ".md5", false); if(infoMD5.type != FileTypeRegular || infoMD5.time <= info.time) { sync.timedUpgrade(_busyTimeout); infoMD5 = getFileInfo(path + ".md5", false); if(infoMD5.type != FileTypeRegular || infoMD5.time <= info.time) { createMD5(path); if(_traceLevel > 0) { Trace out(_logger, "IcePatch"); out << "created .md5 file for `" << path << "'"; } } } RegularDescPtr desc = new RegularDesc; desc->regular = RegularPrx::uncheckedCast(_adapter->createProxy(current.id)); desc->md5 = getMD5(path); return desc; } catch(const IceUtil::LockedException&) { throw BusyException(); } } Int IcePatch::RegularI::getBZ2Size(const Ice::Current& current) { try { IceUtil::RWRecMutex::TryRLock sync(_globalMutex, _busyTimeout); string path = identityToPath(current.id); FileInfo info = getFileInfo(path, true); FileInfo infoBZ2 = getFileInfo(path + ".bz2", false); if(infoBZ2.type != FileTypeRegular || infoBZ2.time <= info.time) { sync.timedUpgrade(_busyTimeout); infoBZ2 = getFileInfo(path + ".bz2", false); if(infoBZ2.type != FileTypeRegular || infoBZ2.time <= info.time) { createBZ2(path); if(_traceLevel > 0) { Trace out(_logger, "IcePatch"); out << "created .bz2 file for `" << path << "'"; } // Get the .bz2 file info again, so that we can return the // size below. This time the .bz2 file must exist, // otherwise an exception is raised. infoBZ2 = getFileInfo(path + ".bz2", true); } } return infoBZ2.size; } catch(const IceUtil::LockedException&) { throw BusyException(); } } ByteSeq IcePatch::RegularI::getBZ2(Ice::Int pos, Ice::Int num, const Ice::Current& current) { try { IceUtil::RWRecMutex::TryRLock sync(_globalMutex, _busyTimeout); string path = identityToPath(current.id); FileInfo info = getFileInfo(path, true); FileInfo infoBZ2 = getFileInfo(path + ".bz2", false); if(infoBZ2.type != FileTypeRegular || infoBZ2.time <= info.time) { sync.timedUpgrade(_busyTimeout); infoBZ2 = getFileInfo(path + ".bz2", false); if(infoBZ2.type != FileTypeRegular || infoBZ2.time <= info.time) { createBZ2(path); if(_traceLevel > 0) { Trace out(_logger, "IcePatch"); out << "created .bz2 file for `" << path << "'"; } } } return IcePatch::getBZ2(path, pos, num); } catch(const IceUtil::LockedException&) { throw BusyException(); } } ByteSeq IcePatch::RegularI::getBZ2MD5(Ice::Int size, const Ice::Current& current) { try { IceUtil::RWRecMutex::TryRLock sync(_globalMutex, _busyTimeout); string path = identityToPath(current.id); FileInfo info = getFileInfo(path, true); FileInfo infoBZ2 = getFileInfo(path + ".bz2", false); if(infoBZ2.type != FileTypeRegular || infoBZ2.time <= info.time) { sync.timedUpgrade(_busyTimeout); infoBZ2 = getFileInfo(path + ".bz2", false); if(infoBZ2.type != FileTypeRegular || infoBZ2.time <= info.time) { createBZ2(path); if(_traceLevel > 0) { Trace out(_logger, "IcePatch"); out << "created .bz2 file for `" << path << "'"; } } } return IcePatch::getPartialMD5(path + ".bz2", size); } catch(const IceUtil::LockedException&) { throw BusyException(); } }