Files
secondo/Algebras/Distributed5/Task.cpp

1162 lines
31 KiB
C++
Raw Normal View History

2026-01-23 17:03:45 +08:00
/*
----
This file is part of SECONDO.
Copyright (C) 2015,
Faculty of Mathematics and Computer Science,
Database Systems for New Applications.
SECONDO is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
SECONDO is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SECONDO; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
----
//[$][\$]
*/
#include "Task.h"
using namespace std;
using namespace distributed2;
extern boost::mutex nlparsemtx;
/*
0 Functions from distributed2Algebra
*/
namespace distributed2
{
// Algebra instance
extern Distributed2Algebra *algInstance;
extern DFSType *filesystem;
extern ListExpr replaceWrite(ListExpr list, const string &writeVer,
const string &name);
/*
0.1 Auxiliary function fun2cmd.
*/
extern void writeLog(ConnectionInfo *ci, const string &msg);
extern void writeLog(ConnectionInfo *ci, const string &cmd, const string &msg);
extern ListExpr replaceSymbols(ListExpr list,
const map<string, string> &replacements);
extern ListExpr replaceSymbols(ListExpr list,
const map<string, ListExpr> &replacements);
template <typename T>
ListExpr fun2cmd(ListExpr funlist, const vector<T> &funargs)
{
if (!nl->HasLength(funlist, 2 + funargs.size()))
{
cout << "invalid length of list" << endl;
return nl->TheEmptyList();
}
if (!listutils::isSymbol(nl->First(funlist), "fun"))
{
return nl->TheEmptyList();
}
funlist = nl->Rest(funlist);
map<string, T> replacements;
int pos = 0;
while (!nl->HasLength(funlist, 1))
{
ListExpr first = nl->First(funlist);
funlist = nl->Rest(funlist);
if (!nl->HasLength(first, 2))
{
cerr << "invalid function argument" << endl;
return nl->TheEmptyList();
}
if (nl->AtomType(nl->First(first)) != SymbolType)
{
cerr << "invalid function argument name " << endl;
return nl->TheEmptyList();
}
replacements[nl->SymbolValue(nl->First(first))] = funargs[pos];
pos++;
}
ListExpr rep = replaceSymbols(nl->First(funlist), replacements);
return rep;
}
template <typename T>
ListExpr fun2cmd(const string &fundef, const vector<T> &funargs)
{
ListExpr funlist;
{
boost::lock_guard<boost::mutex> guard(nlparsemtx);
if (!nl->ReadFromString(fundef, funlist))
{
cerr << "Function is not a nested list" << endl;
return nl->TheEmptyList();
}
}
return fun2cmd<T>(funlist, funargs);
}
} // namespace distributed2
namespace distributed5
{
CommandLog commandLog;
int Task::nextId = 0;
thread_local TaskStatistics TaskStatistics::local;
/*
1 Constructor for Data Task Type
Creates a Data Task Type
Root task for each slot
This task has no incoming task
Only outgoing tasks
*/
DataTask::DataTask(
const DArrayElement dArrayElement,
string name,
size_t slot,
DataStorageType storageType,
ListExpr contentType)
: Task(WorkerLocation(dArrayElement.getHost(),
dArrayElement.getPort(),
dArrayElement.getConfig(),
dArrayElement.getNum()),
#ifdef TASK_VERIFY_COUNTS
0
#else
RunOnReceive
#endif
),
dataItem(name, slot, contentType,
TaskDataLocation(dArrayElement.getHost(),
dArrayElement.getPort(),
dArrayElement.getConfig(),
dArrayElement.getNum(),
storageType,
false))
{
}
/*
2 Worker Task
*/
WorkerTask::WorkerTask(
const DArrayElement dArrayElement)
: WorkerTask(WorkerLocation(dArrayElement.getHost(),
dArrayElement.getPort(),
dArrayElement.getConfig(),
dArrayElement.getNum()))
{
}
Task::~Task()
{
}
const string Task::BasicType() { return "task"; }
const bool Task::checkType(const ListExpr list)
{
if (!nl->HasLength(list, 2))
{
return false;
}
if (!listutils::isSymbol(nl->First(list), BasicType()))
{
return false;
}
return true;
}
void Task::addArgument(Task *task, size_t pos)
{
arguments.emplace_back(task, pos);
}
/*
2.3 Run methode for Data Task
*/
vector<TaskDataItem *> DataTask::run(
WorkerLocation &location,
std::vector<TaskDataItem *> args)
{
TaskDataItem *data = new TaskDataItem(dataItem);
#ifdef TASK_VERIFY_COUNTS
TaskDataLocation loc = data->getFirstLocation();
size_t count = loc.getValueCount(data);
data->setCount(count);
#endif
return vector{data};
}
/*
2.4 Run methode for dmap function task
*/
vector<TaskDataItem *> DmapFunctionTask::run(
WorkerLocation &location,
std::vector<TaskDataItem *> args)
{
string resultName = this->resultName;
TaskDataItem *firstArg = args.front();
size_t slot = firstArg->getSlot();
vector<string> funargs;
// for all input arguments
for (auto arg : args)
{
funargs.push_back(arg->getValueArgument(location) + " ");
#ifdef TASK_VERIFY_COUNTS
if (arg->getCount() > 0)
{
auto loc = arg->findLocation(location);
size_t count = loc.getValueCount(arg);
arg->verifyCount(count);
}
#endif
}
// create function comand
ListExpr funCmdList = fun2cmd(mapFunction, funargs);
funCmdList = replaceWrite(funCmdList, "write2",
resultName + "_" + std::to_string(slot));
// for dmapSX X == 1
if (args.size() == 1)
{
string name_slot = firstArg->getObjectName();
funCmdList = replaceWrite(funCmdList, "write3", name_slot);
}
string funcmd = nl->ToString(funCmdList);
// store result on the running worker
return store(location, slot, funcmd, "dmapS");
}
/*
2.5 Run methode for dproduct function task
*/
vector<TaskDataItem *> DproductFunctionTask::run(
WorkerLocation &location,
std::vector<TaskDataItem *> args)
{
TaskDataItem *first = args.front();
TaskDataItem *last = args.back();
size_t slot = first->getSlot();
string arg1 = first->getValueArgument(location);
ListExpr fsrelType = nl->TwoElemList(
listutils::basicSymbol<fsrel>(),
nl->Second(last->getContentType()));
string arg2 = "(" + nl->ToString(fsrelType) + "( ";
bool isFirst = true;
for (auto arg : args)
{
if (isFirst)
{
isFirst = false;
continue;
}
TaskDataLocation loc = arg->findLocation(location,
DataStorageType::File);
arg2 += "'" + loc.getFilePath(arg) + "' ";
}
arg2 += "))";
string funcall = "( " + mapFunction + " " + arg1 + " " + arg2 + ")";
return store(location, slot, funcall, "dproductS");
}
/*
2.6 Run methode for partition function task
*/
vector<TaskDataItem *> PartitionFunctionTask::run(
WorkerLocation &location,
std::vector<TaskDataItem *> args)
{
TaskDataItem *first = args.front();
size_t slot = first->getSlot();
TaskDataItem result(resultName, slot, resultContentType,
TaskDataLocation(
location, DataStorageType::File, false));
string path = location.getFileBase(&result);
ListExpr fsrelType = nl->TwoElemList(
listutils::basicSymbol<fsrel>(),
nl->Second(first->getContentType()));
string argExpr = "(" + nl->ToString(fsrelType) + "( ";
for (auto arg : args)
{
TaskDataLocation loc = arg->findLocation(location,
DataStorageType::File);
argExpr += "'" + loc.getFilePath(arg) + "' ";
}
argExpr += "))";
string tupleStream = "( " + mapFunction + " " +
argExpr + " " + argExpr + ")";
string distribute = "(fdistribute7 " + tupleStream + " " +
"'" + path + "' " +
partitionFunction + " " +
std::to_string(vslots) + " TRUE" +
")";
string cmd = "(query (count " + distribute + "))";
string description = "partitionFS";
ConnectionInfo* ci = location.getWorkerConnection();
// create the target directory
string targetDir = location.getFileDirectory(&result);
string cd = "query createDirectory('" + targetDir + "', TRUE)";
double duration = runCommand(ci, cd,
"create directory for file", false, "");
string countResult;
duration += runCommand(ci, cmd, description, true,
"", false, &countResult);
TaskStatistics::report("remote " + description, duration);
#ifdef TASK_VERIFY_COUNTS
string compareCmd = "(query (count " + tupleStream + "))";
string compareCountResult;
runCommand(ci, compareCmd, "partitionFS map only", true,
"", false, &compareCountResult);
size_t compareCount = TaskDataItem::parseCount(compareCountResult);
TaskDataItem::verifyCount(
TaskDataItem::parseCount(countResult),
compareCount);
size_t countSumOfFragments = 0;
#endif
vector<TaskDataItem *> results;
for (size_t i = 0; i < vslots; i++)
{
auto *data = new TaskDataItem(
resultName, slot, i + 1,
resultContentType,
TaskDataLocation(location, DataStorageType::File, true));
#ifdef TASK_VERIFY_COUNTS
size_t count = data->getFirstLocation().getValueCount(data);
data->setCount(count);
countSumOfFragments += count;
#endif
results.push_back(data);
}
#ifdef TASK_VERIFY_COUNTS
TaskDataItem::verifyCount(countSumOfFragments, compareCount);
#endif
ci -> deleteIfAllowed();
ci = nullptr;
return results;
}
/*
2.7 Run methode for collect function task
*/
vector<TaskDataItem *> CollectFunctionTask::run(
WorkerLocation &location,
std::vector<TaskDataItem *> args)
{
TaskDataItem *first = args.front();
TaskDataItem *last = args.back();
size_t slot = first->getVerticalSlot() - 1;
#ifdef TASK_VERIFY_COUNTS
size_t inputCount = 0;
#endif
ListExpr fsrelType = nl->TwoElemList(
listutils::basicSymbol<fsrel>(),
nl->Second(last->getContentType()));
string argQuery = "(" + nl->ToString(fsrelType) + "( ";
for (auto arg : args)
{
TaskDataLocation loc = arg->findLocation(location,
DataStorageType::File);
argQuery += "'" + loc.getFilePath(arg) + "' ";
#ifdef TASK_VERIFY_COUNTS
inputCount += arg->getCount();
#endif
}
argQuery += "))";
return store(location, slot, argQuery, "collectS",
#ifdef TASK_VERIFY_COUNTS
inputCount
#else
0
#endif
);
}
//returns the DArray information.
//These informations are:
//server, port, slot and the config
DArrayElement WorkerLocation::getDArrayElement() const
{
return DArrayElement(server, port, worker, config);
}
//returns the list of predecessor tasks
std::vector<Task *> Task::getPredecessors()
{
vector<Task *> list;
for (auto arg : getArguments())
list.push_back(arg.first);
return list;
}
//returns the list of predecessor tasks
std::vector<pair<Task *, size_t>> &Task::getArguments()
{
return arguments;
}
//returns the id of the task
int Task::getId()
{
return id;
}
std::string WorkerLocation::getFileBase(const TaskDataItem *data) const
{
ConnectionInfo* ci = getWorkerConnection();
string dbname = SecondoSystem::GetInstance()->GetDatabaseName();
string name = data->getName();
size_t slot = data->getSlot();
size_t vslot = data->getVerticalSlot();
string slotPrefix =
vslot != 0
? "_" + std::to_string(slot) +
"_" + std::to_string(vslot - 1)
: "_" + std::to_string(slot);
string fileBase = ci->getSecondoHome(false, commandLog) +
"/dfarrays/" + dbname + "/" +
name + "/" +
name + slotPrefix;
ci -> deleteIfAllowed();
ci = nullptr;
return fileBase;
}
std::string WorkerLocation::getFilePath(const TaskDataItem *data) const
{
return getFileBase(data) + ".bin";
}
std::string WorkerLocation::getFileDirectory(const TaskDataItem *data) const
{
ConnectionInfo* ci = getWorkerConnection();
string dbname = SecondoSystem::GetInstance()->GetDatabaseName();
string name = data->getName();
string fileDir = ci->getSecondoHome(false, commandLog) +
"/dfarrays/" + dbname + "/" +
name + "/";
ci -> deleteIfAllowed();
ci = nullptr;
return fileDir;
}
std::string TaskDataLocation::getValueArgument(const TaskDataItem *data) const
{
switch (storageType)
{
case DataStorageType::Object:
return data->getObjectName();
case DataStorageType::File:
{
string fname1 = getFilePath(data);
ListExpr contentType = data->getContentType();
if (data->isFileRelation())
{
return "(" + nl->ToString(contentType) +
" '" + fname1 + "' )";
}
else if (data->isObjectRelation())
{
ListExpr frelType = nl->TwoElemList(
listutils::basicSymbol<frel>(),
nl->Second(contentType));
return "(" + nl->ToString(frelType) +
" '" + fname1 + "' )";
}
else
{
return "(getObjectFromFile '" + fname1 + "')";
}
}
default:
throw std::invalid_argument("not implemented storage type");
}
}
#ifdef TASK_VERIFY_COUNTS
size_t TaskDataLocation::getValueCount(const TaskDataItem *data) const
{
auto* ci = getWorkerConnection();
std::string result;
try
{
Task::runCommand(
ci, "(query (count (feed " + getValueArgument(data) + ")))",
"count data items", true, "", false, &result);
ci -> deleteIfAllowed();
ci = nullptr;
return TaskDataItem::parseCount(result);
}
catch (exception &e)
{
return 0;
}
}
string TaskDataLocation::getValue(const TaskDataItem *data) const
{
auto *ci = getWorkerConnection();
std::string result;
try
{
Task::runCommand(
ci, "(query " + getValueArgument(data) + ")",
"get value", true, "", false, &result);
ci -> deleteIfAllowed();
ci = nullptr;
return result;
}
catch (exception &e)
{
return "";
}
}
#endif
double Task::runCommand(ConnectionInfo *ci,
std::string cmd,
std::string description,
bool nestedListFormat,
string expectResult,
bool ignoreError,
string *result)
{
bool showCommands = false;
int err;
string errMsg;
string r;
double runtime;
if (nestedListFormat)
{
ci->simpleCommandFromList(cmd, err, errMsg, r, false, runtime,
showCommands, commandLog, false,
algInstance->getTimeout());
}
else
{
ci->simpleCommand(cmd, err, errMsg, r, false, runtime,
showCommands, commandLog, false,
algInstance->getTimeout());
}
if (err)
{
if (ignoreError)
return 0;
writeLog(ci, cmd, errMsg);
throw RemoteException(
description,
errMsg +
" (code: " + std::to_string(err) + " " +
SecondoInterface::GetErrorMessage(err) + ")",
cmd);
}
if (expectResult != "" && r != expectResult)
{
writeLog(ci, cmd, "returned " + r + " but expected " + expectResult);
throw RemoteException(
description,
"command returned " + r + " but expected " + expectResult,
cmd);
}
if (result != 0)
*result = r;
return runtime;
}
/*
3.1.1 store methode
Executes run methode on worker
Wraps value for secondo query so that output value is in correct format
*/
vector<TaskDataItem *> FunctionTask::store(
const WorkerLocation &location,
size_t slot, std::string value, std::string description,
size_t expectedCount)
{
WorkerLocation preferredLocation = getPreferredLocation();
DataStorageType storageType =
isStream ||
(!storeRelAsObject && isRel) ||
location != preferredLocation
? DataStorageType::File
: DataStorageType::Object;
ConnectionInfo* ci = location.getWorkerConnection();
TaskDataItem result(resultName, slot, resultContentType,
TaskDataLocation(location, storageType, true));
string name2 = result.getObjectName();
string cmd;
double duration = 0;
switch (storageType)
{
case DataStorageType::Object:
{
cmd = "(let " + name2 + " = " + value + ")";
break;
}
case DataStorageType::File:
{
// create the target directory
string targetDir = location.getFileDirectory(&result);
string fname2 = location.getFilePath(&result);
// if the result of the function is a relation, we feed it
// into a stream to fconsume it
// if there is a non-temp-name and a dfs is avaiable,
// we extend the fconsume arguments by boolean values
// first : create dir, always true
// second : put result to dfs
string aa = "";
if (filesystem)
{
aa = " TRUE";
}
if (this->isStream)
{
cmd = "(query (count (fconsume5 " + value + " '" +
fname2 + "' TRUE" + aa + " )))";
}
else if (this->isRel)
{
cmd = "(query (count (fconsume5 (feed " + value + " )'" +
fname2 + "' TRUE" + aa + ")))";
}
else
{
cmd = "(query (saveObjectToFile " + value + " '" + fname2 + "'))";
}
break;
}
default:
throw std::invalid_argument("not implemented storage type");
}
string countResult;
duration += runCommand(ci, cmd, description, true, "", false, &countResult);
TaskStatistics::report("remote " + description, duration);
TaskDataItem *data = new TaskDataItem(result);
#ifdef TASK_VERIFY_COUNTS
size_t count = TaskDataItem::parseCount(countResult);
if (expectedCount > 0)
TaskDataItem::verifyCount(count, expectedCount);
data->setCount(count);
#endif
ci -> deleteIfAllowed();
ci = nullptr;
return vector{data};
}
ConnectionInfo *WorkerLocation::getWorkerConnection() const
{
string dbname = SecondoSystem::GetInstance()->GetDatabaseName();
ConnectionInfo *ci = algInstance->getWorkerConnection(
getDArrayElement(), dbname);
if (ci == 0)
{
throw new RemoteException(
"connect to worker",
"ConnectionInfo == NULL",
"(" + toString() + ").getWorkerConnection()");
}
return ci;
}
/*
4.1.1 getDistance
calculates Data Distance for a data slot for this worker
*/
DataDistance TaskDataItem::getDistance(
WorkerLocation const &location) const
{
boost::shared_lock_guard<boost::shared_mutex> lock(mutex);
DataDistance bestDistance = FarAway;
if (fileLocations > 0)
{
bestDistance = DataDistance::FileOverNetwork;
}
else if (objectLocations > 0)
{
bestDistance = DataDistance::MemoryOverNetwork;
}
auto locations = locationsByServer.find(location.getServer());
if (locations != locationsByServer.end())
{
for (auto &loc : locations->second)
{
DataDistance dist = loc.getDistance(location, isFileRelation());
if (dist < bestDistance)
{
bestDistance = dist;
}
}
}
return bestDistance;
}
DataDistance TaskDataItem::getUpcomingDistance(
WorkerLocation const &location) const
{
DataDistance bestDistance = getDistance(location);
boost::shared_lock_guard<boost::shared_mutex> lock(mutex);
for (auto &loc : upcomingLocations)
{
DataDistance dist = loc.getDistance(location, isFileRelation());
if (dist < bestDistance)
{
bestDistance = dist;
}
}
return bestDistance;
}
pair<TaskDataLocation, int> TaskDataItem::findTransferSourceLocation(
std::map<std::string, pair<bool, int>> activeTransferrators) const
{
const TaskDataLocation *bestLoc = 0;
int bestCount = 0;
for (auto &locations : locationsByServer)
{
if (locations.second.empty())
continue;
auto transferrator = activeTransferrators[locations.first];
if (!transferrator.first)
continue;
int count = transferrator.second;
if (bestLoc == 0 || count < bestCount)
{
for (auto &loc : locations.second)
{
if (loc.getStorageType() != File)
continue;
bestLoc = &loc;
bestCount = count;
break;
}
}
}
if (bestLoc == 0)
throw NoSourceLocationException(this);
return make_pair(*bestLoc, bestCount);
}
/*
5.1.1 findLocation
returns a worker location with the smallest dataDistance
*/
TaskDataLocation TaskDataItem::findLocation(WorkerLocation const &nearby) const
{
boost::shared_lock_guard<boost::shared_mutex> lock(mutex);
const TaskDataLocation *bestLoc = 0;
DataDistance bestDistance = DataDistance::AccessibleWithCorrectType;
auto locations = locationsByServer.find(nearby.getServer());
if (locations != locationsByServer.end())
{
for (auto &loc : locations->second)
{
if (loc.getWorkerLocation() == nearby)
return loc;
DataDistance dist = loc.getDistance(nearby, isFileRelation());
if (dist < bestDistance)
{
bestLoc = &loc;
bestDistance = dist;
}
}
}
if (bestLoc == 0)
throw NoNearbyLocationException(this, nearby);
return *bestLoc;
}
bool TaskDataItem::hasLocation(TaskDataLocation const &location) const
{
boost::shared_lock_guard<boost::shared_mutex> lock(mutex);
auto locations = locationsByServer.find(location.getServer());
if (locations != locationsByServer.end())
{
for (auto &loc : locations->second)
{
if (loc == location)
return true;
}
}
return false;
}
bool TaskDataItem::hasLocation(WorkerLocation const &nearby) const
{
boost::shared_lock_guard<boost::shared_mutex> lock(mutex);
auto locations = locationsByServer.find(nearby.getServer());
if (locations != locationsByServer.end())
{
for (auto &loc : locations->second)
{
DataDistance dist = loc.getDistance(nearby, isFileRelation());
if (dist <= DataDistance::AccessibleWithCorrectType)
{
return true;
}
}
}
return false;
}
bool TaskDataItem::hasLocation(WorkerLocation const &nearby,
DataStorageType storageType) const
{
boost::shared_lock_guard<boost::shared_mutex> lock(mutex);
auto locations = locationsByServer.find(nearby.getServer());
if (locations != locationsByServer.end())
{
for (auto &loc : locations->second)
{
if (loc.getStorageType() != storageType)
continue;
DataDistance dist = loc.getDistance(nearby, isFileRelation());
if (dist <= DataDistance::Accessible)
{
return true;
}
}
}
return false;
}
bool TaskDataItem::hasUpcomingLocation(WorkerLocation const &nearby) const
{
boost::shared_lock_guard<boost::shared_mutex> lock(mutex);
for (auto &loc : upcomingLocations)
{
DataDistance dist = loc.getDistance(nearby, isFileRelation());
if (dist <= DataDistance::AccessibleWithCorrectType)
{
return true;
}
}
auto locations = locationsByServer.find(nearby.getServer());
if (locations != locationsByServer.end())
{
for (auto &loc : locations->second)
{
DataDistance dist = loc.getDistance(nearby, isFileRelation());
if (dist <= DataDistance::AccessibleWithCorrectType)
{
return true;
}
}
}
return false;
}
bool TaskDataItem::hasUpcomingLocation(WorkerLocation const &nearby,
DataStorageType storageType) const
{
boost::shared_lock_guard<boost::shared_mutex> lock(mutex);
for (auto &loc : upcomingLocations)
{
if (loc.getStorageType() != storageType)
continue;
DataDistance dist = loc.getDistance(nearby, isFileRelation());
if (dist <= DataDistance::Accessible)
{
return true;
}
}
auto locations = locationsByServer.find(nearby.getServer());
if (locations != locationsByServer.end())
{
for (auto &loc : locations->second)
{
if (loc.getStorageType() != storageType)
continue;
DataDistance dist = loc.getDistance(nearby, isFileRelation());
if (dist <= DataDistance::Accessible)
{
return true;
}
}
}
return false;
}
bool TaskDataItem::addUpcomingLocation(TaskDataLocation location)
{
boost::lock_guard<boost::shared_mutex> lock(mutex);
for (auto &loc : upcomingLocations)
{
if (loc == location)
return false;
}
auto locations = locationsByServer.find(location.getServer());
if (locations != locationsByServer.end())
{
for (auto &loc : locations->second)
{
if (loc == location)
return false;
}
}
upcomingLocations.push_back(location);
return true;
}
TaskDataLocation TaskDataItem::findUpcomingLocation(
WorkerLocation const &nearby) const
{
boost::shared_lock_guard<boost::shared_mutex> lock(mutex);
const TaskDataLocation *bestLoc = 0;
DataDistance bestDistance = DataDistance::AccessibleWithCorrectType;
for (auto &loc : upcomingLocations)
{
DataDistance dist = loc.getDistance(nearby, isFileRelation());
if (dist < bestDistance)
{
bestLoc = &loc;
bestDistance = dist;
}
}
auto locations = locationsByServer.find(nearby.getServer());
if (locations != locationsByServer.end())
{
for (auto &loc : locations->second)
{
DataDistance dist = loc.getDistance(nearby, isFileRelation());
if (dist < bestDistance)
{
bestLoc = &loc;
bestDistance = dist;
}
}
}
if (bestLoc == 0)
throw NoNearbyLocationException(this, nearby);
return *bestLoc;
}
TaskDataLocation TaskDataItem::findLocation(
WorkerLocation const &nearby,
DataStorageType storageType) const
{
const TaskDataLocation *bestLoc = 0;
DataDistance bestDistance = DataDistance::Accessible;
boost::shared_lock_guard<boost::shared_mutex> lock(mutex);
auto locations = locationsByServer.find(nearby.getServer());
if (locations != locationsByServer.end())
{
for (auto &loc : locations->second)
{
if (loc.getStorageType() != storageType)
continue;
DataDistance dist = loc.getDistance(nearby, isFileRelation());
if (dist < bestDistance)
{
bestLoc = &loc;
bestDistance = dist;
}
}
}
if (bestLoc == 0)
throw NoNearbyLocationException(this, nearby);
return *bestLoc;
}
TaskDataLocation TaskDataItem::getFirstLocation() const
{
boost::shared_lock_guard<boost::shared_mutex> lock(mutex);
for (auto &locations : locationsByServer)
if (!locations.second.empty())
return locations.second[0];
throw std::invalid_argument("No locations");
}
std::vector<TaskDataLocation> TaskDataItem::getLocations() const
{
boost::shared_lock_guard<boost::shared_mutex> lock(mutex);
std::vector<TaskDataLocation> allLocations;
for (auto &locations : locationsByServer)
{
for (auto &loc : locations.second)
allLocations.push_back(loc);
}
return allLocations;
}
void TaskDataItem::merge(TaskDataItem *other)
{
boost::lock_guard<boost::shared_mutex> lock(mutex);
for (auto otherLocations : other->locationsByServer)
{
auto &ownLocations = locationsByServer[otherLocations.first];
for (auto &loc : otherLocations.second)
{
bool found = false;
for (auto &ownLoc : ownLocations)
{
if (ownLoc == loc)
{
found = true;
break;
}
}
if (!found)
{
if (loc.getStorageType() == File)
fileLocations++;
if (loc.getStorageType() == Object)
objectLocations++;
ownLocations.push_back(loc);
}
}
}
other->locationsByServer.clear();
}
//these functions are needed for the type constructor
//sets the size of a task
int SizeOfTask()
{
return 0;
}
//these functions are needed for the type constructor
//sets the task properties
ListExpr TaskProperty()
{
return (
nl->TwoElemList(
nl->FourElemList(
nl->StringAtom("Signature"),
nl->StringAtom("Example Type List"),
nl->StringAtom("List Rep"),
nl->StringAtom("Example List")),
nl->FourElemList(
nl->StringAtom("-> SIMPLE"),
nl->StringAtom("(Task, int)"),
nl->StringAtom("List Rep"),
nl->StringAtom("Example List"))));
}
//task type check
bool TaskTypeCheck(ListExpr type, ListExpr &errorInfo)
{
return Task::checkType(type);
}
//creates a task
Word CreateTask(const ListExpr typeInfo)
{
Word w;
w.addr = (new ErrorTask());
return w;
}
//deletes a task
void DeleteTask(const ListExpr typeInfo, Word &w)
{
Task *k = (Task *)w.addr;
delete k;
w.addr = 0;
}
//type constructor
TypeConstructor TaskTC(
Task::BasicType(),
TaskProperty,
0, 0,
0, 0,
CreateTask, DeleteTask,
0, 0,
0, 0,
0, SizeOfTask, TaskTypeCheck);
} // namespace distributed5