#include <simgear/io/sg_file.hxx>
#include <simgear/misc/sgstream.hxx>
#include <simgear/structure/exception.hxx>
+#include <simgear/timing/timestamp.hxx>
#include <simgear/misc/sg_hash.hxx>
typedef std::vector<HashCacheEntry> HashCache;
HashCache hashes;
+ bool hashCacheDirty;
struct Failure
{
FailureList failures;
HTTPRepoPrivate(HTTPRepository* parent) :
- p(parent),
- isUpdating(false),
- status(AbstractRepository::REPO_NO_ERROR),
- totalDownloaded(0)
+ hashCacheDirty(false),
+ p(parent),
+ isUpdating(false),
+ status(AbstractRepository::REPO_NO_ERROR),
+ totalDownloaded(0)
{ ; }
~HTTPRepoPrivate();
AbstractRepository::ResultCode fileStatus);
typedef std::vector<RepoRequestPtr> RequestVector;
- RequestVector requests;
+ RequestVector queuedRequests,
+ activeRequests;
+ void makeRequest(RepoRequestPtr req);
void finishedRequest(const RepoRequestPtr& req);
HTTPDirectory* getOrCreateDirectory(const std::string& path);
_d->http = cl;
_d->basePath = base;
_d->rootDir = new HTTPDirectory(_d.get(), "");
+ _d->parseHashCache();
}
HTTPRepository::~HTTPRepository()
size_t result = 0;
HTTPRepoPrivate::RequestVector::const_iterator r;
- for (r = _d->requests.begin(); r != _d->requests.end(); ++r) {
+ for (r = _d->queuedRequests.begin(); r != _d->queuedRequests.end(); ++r) {
+ result += (*r)->contentSize();
+ }
+
+ for (r = _d->activeRequests.begin(); r != _d->activeRequests.end(); ++r) {
result += (*r)->contentSize() - (*r)->responseBytesReceived();
}
size_t result = _d->totalDownloaded;
HTTPRepoPrivate::RequestVector::const_iterator r;
- for (r = _d->requests.begin(); r != _d->requests.end(); ++r) {
+ for (r = _d->activeRequests.begin(); r != _d->activeRequests.end(); ++r) {
result += (*r)->responseBytesReceived();
}
try {
// either way we've confirmed the index is valid so update
// children now
+ SGTimeStamp st;
+ st.stamp();
_directory->updateChildrenBasedOnHash();
+ SG_LOG(SG_TERRASYNC, SG_INFO, "after update of:" << _directory->absolutePath() << " child update took:" << st.elapsedMSec());
} catch (sg_exception& e) {
_directory->failedToUpdate(AbstractRepository::REPO_ERROR_IO);
}
}
RequestVector::iterator r;
- for (r=requests.begin(); r != requests.end(); ++r) {
+ for (r=activeRequests.begin(); r != activeRequests.end(); ++r) {
(*r)->cancel();
}
}
{
RepoRequestPtr r(new FileGetRequest(dir, name));
r->setContentSize(sz);
- requests.push_back(r);
- http->makeRequest(r);
+ makeRequest(r);
return r;
}
{
RepoRequestPtr r(new DirGetRequest(dir, hash));
r->setContentSize(sz);
- requests.push_back(r);
- http->makeRequest(r);
+ makeRequest(r);
return r;
}
HashCache::iterator it = std::find_if(hashes.begin(), hashes.end(), HashEntryWithPath(p.str()));
if (it != hashes.end()) {
hashes.erase(it);
+ hashCacheDirty = true;
}
if (newHash.empty()) {
entry.lengthBytes = p2.sizeInBytes();
hashes.push_back(entry);
- writeHashCache();
+ hashCacheDirty = true;
}
void HTTPRepoPrivate::writeHashCache()
{
+ if (!hashCacheDirty) {
+ return;
+ }
+
SGPath cachePath = basePath;
cachePath.append(".hashes");
<< it->lengthBytes << ":" << it->hashHex << "\n";
}
stream.close();
+ hashCacheDirty = false;
}
void HTTPRepoPrivate::parseHashCache()
return false;
}
+ void HTTPRepoPrivate::makeRequest(RepoRequestPtr req)
+ {
+ if (activeRequests.size() > 4) {
+ queuedRequests.push_back(req);
+ } else {
+ activeRequests.push_back(req);
+ http->makeRequest(req);
+ }
+ }
+
void HTTPRepoPrivate::finishedRequest(const RepoRequestPtr& req)
{
- RequestVector::iterator it = std::find(requests.begin(), requests.end(), req);
- if (it == requests.end()) {
+ RequestVector::iterator it = std::find(activeRequests.begin(), activeRequests.end(), req);
+ if (it == activeRequests.end()) {
throw sg_exception("lost request somehow", req->url());
}
- requests.erase(it);
- if (requests.empty()) {
+ activeRequests.erase(it);
+
+ if (!queuedRequests.empty()) {
+ RepoRequestPtr rr = queuedRequests.front();
+ queuedRequests.erase(queuedRequests.begin());
+ activeRequests.push_back(rr);
+ http->makeRequest(rr);
+ }
+
+ writeHashCache();
+
+ if (activeRequests.empty() && queuedRequests.empty()) {
isUpdating = false;
}
}