bool Store::Sink::push(Fountain::Combination &incoming) { std::unique_lock<std::mutex> lock(mMutex); mSink.solve(incoming); if(!mSink.isDecoded()) return false; BinaryString sinkDigest; mSink.hash(sinkDigest); LogDebug("Store::push", "Block is complete, digest is " + sinkDigest.toString()); if(!mDigest.empty() && sinkDigest != mDigest) { LogWarn("Store::push", "Block digest is invalid (expected " + mDigest.toString() + ")"); mSink.clear(); return false; } mPath = Cache::Instance->path(mDigest); File file(mPath, File::Write); mSize = mSink.dump(file); file.close(); return true; }
void Resource::fetch(const BinaryString &digest, bool localOnly) { delete mIndexBlock; delete mIndexRecord; mIndexRecord = NULL; mIndexBlock = NULL; if(localOnly && !Store::Instance->hasBlock(digest)) throw Exception(String("Local resource not found: ") + digest.toString()); //LogDebug("Resource::fetch", "Fetching resource " + digest.toString()); try { mIndexBlock = new Block(digest); mIndexRecord = new IndexRecord; //LogDebug("Resource::fetch", "Reading index block for " + digest.toString()); BinarySerializer serializer(mIndexBlock); AssertIO(static_cast<Serializer*>(&serializer)->input(mIndexRecord)); } catch(const std::exception &e) { delete mIndexBlock; delete mIndexRecord; mIndexRecord = NULL; mIndexBlock = NULL; throw Exception(String("Unable to fetch resource index block: ") + e.what()); } }
bool Store::waitBlock(const BinaryString &digest, duration timeout) { if(!hasBlock(digest)) { Network::Caller caller(digest); // Block is missing locally, call it LogDebug("Store::waitBlock", "Waiting for block: " + digest.toString()); { std::unique_lock<std::mutex> lock(mMutex); if(!mCondition.wait_for(lock, timeout, [this, digest]() { return hasBlock(digest); })) return false; } LogDebug("Store::waitBlock", "Block is now available: " + digest.toString()); } return true; }
bool Cache::prefetch(const BinaryString &target) { // Test local availability if(Store::Instance->hasBlock(target)) { Resource resource(target, true); // local only if(resource.isLocallyAvailable()) return true; } mScheduler.schedule(Scheduler::clock::now(), [target]() { try { Resource resource(target); Resource::Reader reader(&resource); reader.discard(); // read everything } catch(const Exception &e) { LogWarn("Cache::prefetch", "Prefetching failed for " + target.toString()); } }); return false; }
String Cache::path(const BinaryString &digest) const { Assert(!digest.empty()); return mDirectory + Directory::Separator + digest.toString(); }