diff options
-rw-r--r-- | cpp/include/IcePatch/Util.h | 5 | ||||
-rw-r--r-- | cpp/slice/IcePatch/IcePatch.ice | 3 | ||||
-rw-r--r-- | cpp/src/IcePatch/Client.cpp | 19 | ||||
-rw-r--r-- | cpp/src/IcePatch/IcePatchI.cpp | 34 | ||||
-rw-r--r-- | cpp/src/IcePatch/IcePatchI.h | 1 | ||||
-rw-r--r-- | cpp/src/IcePatch/Util.cpp | 115 |
6 files changed, 152 insertions, 25 deletions
diff --git a/cpp/include/IcePatch/Util.h b/cpp/include/IcePatch/Util.h index 945b95fc728..5b02b854761 100644 --- a/cpp/include/IcePatch/Util.h +++ b/cpp/include/IcePatch/Util.h @@ -47,6 +47,7 @@ ICE_PATCH_API Ice::StringSeq readDirectory(const std::string&); ICE_PATCH_API void createDirectory(const std::string&); ICE_PATCH_API Ice::ByteSeq getMD5(const std::string&); +ICE_PATCH_API Ice::ByteSeq getPartialMD5(const std::string&, Ice::Int); ICE_PATCH_API void createMD5(const std::string&); ICE_PATCH_API Ice::ByteSeq getBZ2(const std::string&, Ice::Int, Ice::Int); @@ -56,11 +57,11 @@ class ICE_PATCH_API ProgressCB { public: - virtual void startDownload(Ice::Int) = 0; + virtual void startDownload(Ice::Int, Ice::Int) = 0; virtual void updateDownload(Ice::Int, Ice::Int) = 0; virtual void finishedDownload(Ice::Int) = 0; - virtual void startUncompress(Ice::Int) = 0; + virtual void startUncompress(Ice::Int, Ice::Int) = 0; virtual void updateUncompress(Ice::Int, Ice::Int) = 0; virtual void finishedUncompress(Ice::Int) = 0; }; diff --git a/cpp/slice/IcePatch/IcePatch.ice b/cpp/slice/IcePatch/IcePatch.ice index e386579fc38..dd9f392146e 100644 --- a/cpp/slice/IcePatch/IcePatch.ice +++ b/cpp/slice/IcePatch/IcePatch.ice @@ -55,6 +55,9 @@ interface Regular extends File Ice::ByteSeq getBZ2(int pos, int num) throws FileAccessException, BusyException; + + Ice::ByteSeq getBZ2MD5(int size) + throws FileAccessException, BusyException; }; class RegularDesc extends FileDesc diff --git a/cpp/src/IcePatch/Client.cpp b/cpp/src/IcePatch/Client.cpp index d238528e654..0afbea8c998 100644 --- a/cpp/src/IcePatch/Client.cpp +++ b/cpp/src/IcePatch/Client.cpp @@ -241,9 +241,10 @@ class MyProgressCB : public ProgressCB { public: - virtual void startDownload(Int) + virtual void startDownload(Int total, Int pos) { - cout << " download 0%" << flush; + Ice::Int percent = pos * 100 / total; + cout << " download " << setw(3) << percent << "%" << flush; } virtual void updateDownload(Int total, Int pos) @@ -252,19 +253,21 @@ public: cout << "\b\b\b\b" << setw(3) << percent << "%" << flush; } - virtual void finishedDownload(Int) + virtual void finishedDownload(Int total) { - cout << "\b\b\b\b" << setw(3) << 100 << "%" << flush; + updateDownload(total, total); } - virtual void startUncompress(Int) + virtual void startUncompress(Int total, Int pos) { - cout << " uncompress 0%" << flush; + Ice::Int percent = pos * 100 / total; + cout << " uncompress " << setw(3) << percent << "%" << flush; } - + virtual void updateUncompress(Int total, Int pos) { - updateDownload(total, pos); + Ice::Int percent = pos * 100 / total; + cout << "\b\b\b\b" << setw(3) << percent << "%" << flush; } virtual void finishedUncompress(Int total) diff --git a/cpp/src/IcePatch/IcePatchI.cpp b/cpp/src/IcePatch/IcePatchI.cpp index 04757c3d061..881ede32971 100644 --- a/cpp/src/IcePatch/IcePatchI.cpp +++ b/cpp/src/IcePatch/IcePatchI.cpp @@ -225,3 +225,37 @@ IcePatch::RegularI::getBZ2(Ice::Int pos, Ice::Int num, const Ice::Current& curre throw BusyException(); } } + +ByteSeq +IcePatch::RegularI::getBZ2MD5(Ice::Int size, const Ice::Current& current) +{ + try + { + IceUtil::RWRecMutex::TryRLock sync(_globalMutex, _busyTimeout); + string path = identityToPath(current.identity); + + 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(); + } +} diff --git a/cpp/src/IcePatch/IcePatchI.h b/cpp/src/IcePatch/IcePatchI.h index 7092e5ce0ed..040b7d9e9c8 100644 --- a/cpp/src/IcePatch/IcePatchI.h +++ b/cpp/src/IcePatch/IcePatchI.h @@ -54,6 +54,7 @@ public: virtual FileDescPtr describe(const Ice::Current&); virtual Ice::Int getBZ2Size(const Ice::Current&); virtual Ice::ByteSeq getBZ2(Ice::Int, Ice::Int, const Ice::Current&); + virtual Ice::ByteSeq getBZ2MD5(Ice::Int, const Ice::Current&); }; } diff --git a/cpp/src/IcePatch/Util.cpp b/cpp/src/IcePatch/Util.cpp index e22a9886043..04c830bc41a 100644 --- a/cpp/src/IcePatch/Util.cpp +++ b/cpp/src/IcePatch/Util.cpp @@ -298,6 +298,55 @@ IcePatch::getMD5(const string& path) return bytesMD5; } +ByteSeq +IcePatch::getPartialMD5(const string& path, Int size) +{ + if (size < 0) + { + FileAccessException ex; + ex.reason = "negative file size is illegal"; + throw ex; + } + + // + // Read the original file partially. + // + FileInfo info = getFileInfo(path, true); + size = std::min(size, static_cast<Int>(info.size)); + ifstream file(path.c_str(), ios::binary); + if (!file) + { + FileAccessException ex; + ex.reason = "cannot open `" + path + "' for reading: " + strerror(errno); + throw ex; + } + ByteSeq bytes; + bytes.resize(size); + file.read(&bytes[0], bytes.size()); + if (!file) + { + FileAccessException ex; + ex.reason = "cannot read `" + path + "': " + strerror(errno); + throw ex; + } + if (file.gcount() < static_cast<int>(bytes.size())) + { + FileAccessException ex; + ex.reason = "could not read all bytes from `" + path + "'"; + throw ex; + } + file.close(); + + // + // Create the MD5 hash value. + // + ByteSeq bytesMD5; + bytesMD5.resize(16); + MD5(reinterpret_cast<unsigned char*>(&bytes[0]), bytes.size(), reinterpret_cast<unsigned char*>(&bytesMD5[0])); + + return bytesMD5; +} + void IcePatch::createMD5(const string& path) { @@ -374,6 +423,27 @@ IcePatch::createMD5(const string& path) ByteSeq IcePatch::getBZ2(const string& path, Int pos, Int num) { + if (pos < 0) + { + FileAccessException ex; + ex.reason = "negative read offset is illegal"; + throw ex; + } + + if (num < 0) + { + FileAccessException ex; + ex.reason = "negative data segment size is illegal"; + throw ex; + } + + if (num > 1024 * 1024) + { + FileAccessException ex; + ex.reason = "maxium data segment size exceeded"; + throw ex; + } + string pathBZ2 = path + ".bz2"; ifstream fileBZ2(pathBZ2.c_str(), ios::binary); if (!fileBZ2) @@ -513,13 +583,29 @@ IcePatch::getRegular(const RegularPrx& regular, ProgressCB& progressCB) string path = identityToPath(regular->ice_getIdentity()); string pathBZ2 = path + ".bz2"; Int totalBZ2 = regular->getBZ2Size(); + Int posBZ2 = 0; + + // + // Check for partial BZ2 file. + // + FileInfo infoBZ2 = getFileInfo(pathBZ2, false); + if (infoBZ2.type == FileTypeRegular) + { + ByteSeq remoteBZ2MD5 = regular->getBZ2MD5(infoBZ2.size); + ByteSeq localBZ2MD5 = getPartialMD5(pathBZ2, infoBZ2.size); + + if (remoteBZ2MD5 == localBZ2MD5) + { + posBZ2 = infoBZ2.size; + } + } // // Get the BZ2 file. // - progressCB.startDownload(totalBZ2); + progressCB.startDownload(totalBZ2, posBZ2); - ofstream fileBZ2(pathBZ2.c_str(), ios::binary); + ofstream fileBZ2(pathBZ2.c_str(), ios::binary | (posBZ2 ? ios::app : 0)); if (!fileBZ2) { FileAccessException ex; @@ -527,19 +613,18 @@ IcePatch::getRegular(const RegularPrx& regular, ProgressCB& progressCB) throw ex; } - ByteSeq bytesBZ2; - Int pos = 0; - while(pos < totalBZ2) + while(posBZ2 < totalBZ2) { - static const Int num = 64 * 1024; + static const Int numBZ2 = 64 * 1024; - bytesBZ2 = regular->getBZ2(pos, num); + ByteSeq bytesBZ2 = regular->getBZ2(posBZ2, numBZ2); if (bytesBZ2.empty()) { break; } + sleep(1); - pos += bytesBZ2.size(); + posBZ2 += bytesBZ2.size(); fileBZ2.write(&bytesBZ2[0], bytesBZ2.size()); if (!fileBZ2) @@ -549,12 +634,12 @@ IcePatch::getRegular(const RegularPrx& regular, ProgressCB& progressCB) throw ex; } - if (static_cast<Int>(bytesBZ2.size()) < num) + if (static_cast<Int>(bytesBZ2.size()) < numBZ2) { break; } - progressCB.updateDownload(totalBZ2, pos); + progressCB.updateDownload(totalBZ2, posBZ2); } progressCB.finishedDownload(totalBZ2); @@ -594,14 +679,14 @@ IcePatch::getRegular(const RegularPrx& regular, ProgressCB& progressCB) throw ex; } - static const Int num = 64 * 1024; - Byte bytes[num]; + static const Int numBZ2 = 64 * 1024; + Byte bytesBZ2[numBZ2]; - progressCB.startUncompress(totalBZ2); + progressCB.startUncompress(totalBZ2, 0); while (bzError != BZ_STREAM_END) { - int sz = BZ2_bzRead(&bzError, bzFile, bytes, num); + int sz = BZ2_bzRead(&bzError, bzFile, bytesBZ2, numBZ2); if (bzError != BZ_OK && bzError != BZ_STREAM_END) { FileAccessException ex; @@ -629,7 +714,7 @@ IcePatch::getRegular(const RegularPrx& regular, ProgressCB& progressCB) progressCB.updateUncompress(totalBZ2, pos); - file.write(bytes, sz); + file.write(bytesBZ2, sz); if (!file) { FileAccessException ex; |