void Controller::checkMigration(Key& key, const Choice& current, bool extraGet, shared_ptr<Value> valueGot) { Requirements requirements; size_t size; { lock_guard<mutex> guard(infoLock); if (info.count(key) == 0) return; requirements = *info[key].requirements.get(); size = info[key].size; } Condition condition = prepareCondition(key, size, requirements); double estimatedCost; Choice* choice = decider->findBetter(condition, current, extraGet, &estimatedCost); if (choice != nullptr) { Dbg() << "migrating from " << current.desc() << " to " << choice->desc() << endl; shared_ptr<Value> value; Requirements migrateRequirements; if (extraGet) { value = current.getActor()->get(key, current.getProfile()); } else { value = valueGot; } storeInto(key, value, *choice, requirements); choice_id old_id = memory->remember(key, choice->getId()); deleteFrom(key, current); accountant->recordMigrate(current.getId(), choice->getId(), size, extraGet); } }
shared_ptr<Value> Controller::handleGet(Key& key, const Requirements& requirements) { shared_ptr<Value> value; Requirements mutable_requirements = requirements; choice_id cid; if (memory->recall(key, &cid)) { auto cit = choices.find(cid); assert(cit != choices.end()); Choice choice = cit->second; accountant->recordGet(cid); Actor* actor = choice.getActor(); Dbg() << "choice " << choice.desc() << "handle this" << endl; if (requirements.prefer_url) { value = actor->get_url(key, requirements.expiration, choice.getProfile()); } if (!value) { value = actor->get(key, choice.getProfile(), requirements.range, &mutable_requirements.metadata); } if (!value) { Err() << "cannot find " << key.toString() << " in choice " << choice.desc() << endl; for (auto& choice_pair : choices) { Choice& choice = choice_pair.second; if (choice.getActor()->get(key, choice.getProfile(), requirements.range, &mutable_requirements.metadata)) { Err() << "found key in " << choice.desc() << "instead" << endl; abort(); } } } if (enableGetMigration) { bool extraGet = !value->hasUrl(); checkMigration(key, choice, extraGet, value); } } estimator->notifyGet(key, mutable_requirements); if (enableStat) { stat->notifyGet(key); } return value; }
void Controller::storeInto(Key& key, shared_ptr<Value> value, const Choice& choice, const Requirements& requirements) { Actor* actor = choice.getActor(); Dbg() << "chose " << choice.desc() << " for this" << endl; if (requirements.metadata.empty()) { actor->put(key, value, choice.getProfile()); } else { actor->put(key, value, choice.getProfile(), &requirements.metadata); } }
string Controller::handleDist() { stringstream ss; const map<Key, choice_id>& mem = memory->dump(); double tcost = 0; if (enableStat) Info() << "======== Cost Report ========" << endl; try { memory->lockIt(); for (auto& it : mem) { string key = it.first.toString(); choice_id choice_id = it.second; Choice& choice = choices.find(choice_id)->second; if (!(info.count(key) == 1)) { continue; } size_t size; Requirements requirements; { lock_guard<mutex> guard(infoLock); requirements = *info[key].requirements.get(); size = info[key].size; } ss << key << " " << size << " " << choice.desc(); if (enableStat) { double cost = 0; long get, put; stat->getInfo(key, get, put); Condition condition; condition.size = size; condition.durabilityRequired = requirements.durabilityRequired; condition.latencyRequired = requirements.latencyRequired; condition.bandwidthRequired = requirements.bandwidthRequired; condition.getRequests = get; condition.putRequests = put; condition.timeSpan = 86400 * 30; Choice *bestChoice = decider->choose(condition, &cost); if (bestChoice == nullptr) { Err() << "can't find optimal place?" << endl; } else { tcost += cost; } ss << " " << get << " " << put << " " << bestChoice->desc(); } ss << endl; } if (enableStat) { for (const auto& it : getChoices()) { double myCost = 0; double realMyCost = 0; const Choice& myChoice = it.second; for (auto& it : mem) { string key = it.first.toString(); choice_id choice_id = it.second; Choice& choice = choices.find(choice_id)->second; if (!(info.count(key) == 1)) { continue; } size_t size; { lock_guard<mutex> guard(infoLock); size = info[key].size; } long get, put; stat->getInfo(key, get, put); double cost = myChoice.calcCost(get, put, size); myCost += cost; if (choice_id == myChoice.getId()) realMyCost += cost; } Info() << myChoice.getName() << " SOLO: " << myCost / 1000 << " nano$" << " COST: " << realMyCost / 1000 << " nano$" << endl; } } memory->unlockIt(); if (enableStat) { Info() << "Optimal total cost: " << tcost / 1000 << " nano$" << endl; } } catch (...) { Err() << "got exception in handleDist" << endl; memory->unlockIt(); } return ss.str(); }