From b4993c849a8aa28b3921ee7e9923abda91131403 Mon Sep 17 00:00:00 2001 From: Graeme Bragg Date: Thu, 9 Jan 2020 23:12:01 +0000 Subject: [PATCH 01/15] Added Addressbook sources with updated names --- Source/NameServer/AddressBook/AddressBook.cpp | 1368 +++++++++++++++++ Source/NameServer/AddressBook/AddressBook.hpp | 166 ++ .../AddressBook/AddressBook_Defs.cpp | 54 + .../AddressBook/AddressBook_Defs.hpp | 60 + .../AddressBook/AddressBook_Record.cpp | 40 + .../AddressBook/AddressBook_Record.hpp | 39 + .../AddressBook/AddressBook_Task.cpp | 802 ++++++++++ .../AddressBook/AddressBook_Task.hpp | 139 ++ 8 files changed, 2668 insertions(+) create mode 100644 Source/NameServer/AddressBook/AddressBook.cpp create mode 100644 Source/NameServer/AddressBook/AddressBook.hpp create mode 100644 Source/NameServer/AddressBook/AddressBook_Defs.cpp create mode 100644 Source/NameServer/AddressBook/AddressBook_Defs.hpp create mode 100644 Source/NameServer/AddressBook/AddressBook_Record.cpp create mode 100644 Source/NameServer/AddressBook/AddressBook_Record.hpp create mode 100644 Source/NameServer/AddressBook/AddressBook_Task.cpp create mode 100644 Source/NameServer/AddressBook/AddressBook_Task.hpp diff --git a/Source/NameServer/AddressBook/AddressBook.cpp b/Source/NameServer/AddressBook/AddressBook.cpp new file mode 100644 index 00000000..7f50d5f3 --- /dev/null +++ b/Source/NameServer/AddressBook/AddressBook.cpp @@ -0,0 +1,1368 @@ +//============================================================================== +#include "AddressBook.hpp" +//#include "Debug.h" + +#include + +//============================================================================== +namespace AddressBookNS +{ +#ifdef EXCEPTS +#define ERETURN(X, Y) throw(X) +#else +#define ERETURN(X, Y) return Y +#endif + +// static constant definitions +const unsigned AddressBook::SUCCESS; +const unsigned AddressBook::ERR_NONFATAL; +const unsigned AddressBook::ERR_INVALID_TASK; +const unsigned AddressBook::ERR_INVALID_DEVTYPE; +const unsigned AddressBook::ERR_INVALID_DEVICE; +const unsigned AddressBook::ERR_INVALID_MESSAGE_TYPE; +const unsigned AddressBook::ERR_INVALID_ATTRIBUTE; +const unsigned AddressBook::ERR_DEVICE_DATA_MISMATCH; +const unsigned AddressBook::ERR_TASKNAME_USED; +const unsigned AddressBook::ERR_DEVICENAME_USED; +const unsigned AddressBook::ERR_DEVICE_ADDR_USED; +const unsigned AddressBook::ERR_TASK_NOT_FOUND; +const unsigned AddressBook::ERR_DEVICE_NOT_FOUND; +const unsigned AddressBook::ERR_INVALID_MAP; +const unsigned AddressBook::ERR_INVALID_SUPERVISOR; +const unsigned AddressBook::ERR_INVALID_STATE; + +//Constructors +AddressBook::AddressBook(std::string d) +{ + ABderived = d; + TaskCount = 0; +} + +AddressBook::~AddressBook() +{ + // Teardown the TaskMap. Everything else should be handled properly. + for(TaskMap_t::iterator T=TaskMap.begin();T!=TaskMap.end();T++) + { + TaskRecord_t* TRec = &(*(T->second)); + delete TRec; + + } +} + + +/*============================================================================== + * GetTaskCount: Get the number of currently loaded tasks + *============================================================================*/ +unsigned AddressBook::GetTaskCount(void) +{ + return TaskMap.size(); +} + +//============================================================================== +//Task Manipulation +unsigned AddressBook::AddTask(const std::string &TaskName, TaskData_t &Data) +{ + // Check that the task does not already exist. + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec != PNULL) + { + //throw("Task Name Already Used"); + return ERR_TASKNAME_USED; + } + + // validate here and exit if the device type data is invalid. These will + // actually be checked again when device types are added below; a duplication, + // but the number of device types and number of message types is going to + // be relatively small, so this isn't going to be too costly + unsigned Ret = ValidateTask(Data); + if(Ret) return Ret; + + // Build a TaskRecord + TaskRecord_t * Task = new TaskRecord_t; + + Task->Name = TaskName; + Task->Path = Data.Path; + Task->XML = Data.XML; + Task->ExecPath = Data.ExecutablePath; + + Task->DevCntMax = Data.DeviceCount; + Task->ExtCntMax = Data.ExternalCount; + + // Pre-reserve the Vectors of Records for consistent pointers. + Task->Devices.reserve(Data.DeviceCount + 1); + Task->Externals.reserve(Data.ExternalCount + 1); + Task->Supervisors.reserve(MAXSUPERVISORS + 1); + + // String Data - copy it over, initialise vectors and create index maps. + // MessageType strings. + Task->MsgTypes.resize(Data.MessageTypes.size()); //pre-alloc vector + std::vector *MTypes = &(Data.MessageTypes); + for(std::vector::const_iterator M=MTypes->begin(); + M!=MTypes->end(); M++) + { + Task->MsgTypes[static_cast(M - MTypes->begin())].Name = *M; + Task->MsgTypeMap.insert(IdxMap_t::value_type(*M, (M-MTypes->begin()))); + } + + // AttributeType strings. + Task->AttrTypes.resize(Data.AttributeTypes.size()); + std::vector *ATypes = &(Data.AttributeTypes); + for(std::vector::const_iterator A=ATypes->begin(); + A!=ATypes->end(); A++) + { + AttrTypePair APair(*A,RecordVect_t()); + Task->AttrTypes[static_cast(A - ATypes->begin())] = APair; + Task->AttrTypeMap.insert(IdxMap_t::value_type(*A, (A-ATypes->begin()))); + } + + // Add to the Task Map. + TaskMap.insert(TaskMap_t::value_type(Task->Name, Task)); + ++TaskCount; // Pedantic: avoid assignment to temporary 5 July 2019 ADR + + /* Insert DeviceTypes. Changed order and call subfunction 5 July 2019 ADR + Original had pre-allocation below, but it's hard to see how this + really gains anything because a DevTypeRecord_t contains 2 internal + vectors (which would be zero-initialised) and a resize is thus inevitable + anyway when actual device types are inserted. + */ + // Task->DevTypes.resize(Data.DeviceTypes.size()); //pre-alloc vector + std::vector *DTypes = &(Data.DeviceTypes); + for(std::vector::iterator D=DTypes->begin(); + D!=DTypes->end(); D++) + AddDeviceType(Task->Name, *D); // add is bound to succeed because we have + // pre-validated. + return SUCCESS; +} + +/*============================================================================== + * AddDeviceType: Append another device type to the task. + *============================================================================*/ +unsigned AddressBook::AddDeviceType(const std::string &TaskName, const DevTypeRecord_t &DeviceType) +{ + // Check that the task exists. + TaskRecord_t *Task = FindTask(TaskName); + if(Task == PNULL) + { + return ERR_TASK_NOT_FOUND; + } + // and that the new device type has valid message indices + if (unsigned retVal = ValidateDeviceType(DeviceType, Task->MsgTypes.size())) + return retVal; + DevTypePair DPair(DeviceType,RecordVect_t()); + Task->DevTypes.push_back(DPair); + unsigned devTypIdx = Task->DevTypes.size() - 1; + Task->DevTypeMap.insert(IdxMap_t::value_type(DeviceType.Name, devTypIdx)); + + // Cross-ref to Message Types. + for(std::vector::const_iterator I=DeviceType.InMsgs.begin(); + I!=DeviceType.InMsgs.end(); I++) // Input Messages + { + Task->MsgTypes[*I].Inputs.push_back(devTypIdx); + } + for(std::vector::const_iterator O=DeviceType.OuMsgs.begin(); + O!=DeviceType.OuMsgs.end(); O++) // Output Messages + { + Task->MsgTypes[*O].Outputs.push_back(devTypIdx); + } + return SUCCESS; +} + +/*============================================================================== + * ClearTask: Removes all the devices from a task + *============================================================================*/ +unsigned AddressBook::ClearTask(const std::string &TaskName) +{ + // The easiest way to do this is simply to copy the data to be saved into + // a TaskData_t object, remove the task, then re-add it with all the device + // data removed. + TaskData_t cTask; + unsigned err = SUCCESS; + if ((err = GetTask(TaskName, cTask)) != SUCCESS) return err; + cTask.DeviceCountLd = 0; + cTask.ExternalCountLd = 0; + cTask.SupervisorCount = 0; + if ((err = DelTask(TaskName)) != SUCCESS) return err; + return AddTask(TaskName, cTask); +} + +/*============================================================================== + * ListTask: Populate a vector with all of the names of loaded tasks + *============================================================================*/ +unsigned AddressBook::ListTask(std::vector &Tasks) +{ + // Enumerate the Task List. + for(TaskMap_t::iterator T=TaskMap.begin();T!=TaskMap.end();T++) + { + Tasks.push_back(T->second->Name); + } + return SUCCESS; +} + +/*============================================================================== + * GetTask: Get a task by name + *============================================================================*/ +unsigned AddressBook::GetTask(const std::string &TaskName, TaskData_t &Task) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + //throw("Task Does Not Exist"); + return ERR_TASK_NOT_FOUND; + } + + Task.Name = TRec->Name; + Task.Path = TRec->Path; + Task.XML = TRec->XML; + Task.ExecutablePath = TRec->ExecPath; + Task.State = TRec->State; + Task.DeviceCount = TRec->DevCntMax; + Task.DeviceCountLd = TRec->DevCnt; + Task.ExternalCount = TRec->ExtCntMax; + Task.ExternalCountLd = TRec->ExtCnt; + Task.SupervisorCount = TRec->SupCnt; + + + //Clear the copied task's vectors just in case this is a re-used TaskData + Task.DeviceTypes.clear(); + Task.MessageTypes.clear(); + Task.AttributeTypes.clear(); + + + // Copy MessageType strings + for(std::vector::const_iterator M=TRec->MsgTypes.begin(); + M!=TRec->MsgTypes.end(); M++) + { + Task.MessageTypes.push_back(M->Name); + } + + // Copy DeviceType strings + for(std::vector::const_iterator D=TRec->DevTypes.begin(); + D!=TRec->DevTypes.end(); D++) + { + Task.DeviceTypes.push_back(D->first); + } + + // Copy AttributeType strings + for(std::vector::const_iterator A=TRec->AttrTypes.begin(); + A!=TRec->AttrTypes.end(); A++) + { + Task.AttributeTypes.push_back(A->first); + } + + return SUCCESS; +} + +/*============================================================================== + * DelTask: Delete the named task + *============================================================================*/ +unsigned AddressBook::DelTask(const std::string &TaskName) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + //throw("Task Does Not Exist"); + return ERR_TASK_NOT_FOUND; + } + + // Erase it + delete TRec; + TaskMap.erase(TaskName); + + TaskCount--; + + return SUCCESS; +} + +/*============================================================================== + * TaskState: Get the state of the task + *============================================================================*/ +TaskState_t AddressBook::TaskState(std::string &TaskName) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + //throw("Task Does Not Exist"); + return static_cast(Unknown); + } + + return TRec->State; +} + +/*============================================================================== + * TaskState: Set the state of the task + *============================================================================*/ +unsigned AddressBook::TaskState(std::string &TaskName, TaskState_t State) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + //throw("Task Does Not Exist"); + return ERR_TASK_NOT_FOUND; + } + + TRec->State = State; + + return SUCCESS; +} + +/*============================================================================== + * TaskExecPath: Get the path to the executables for the task + *============================================================================*/ +std::string AddressBook::TaskExecPath(std::string &TaskName) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + //throw("Task Does Not Exist"); + return ""; + } + + return TRec->ExecPath; +} + +/*============================================================================== + * TaskExecPath: Set the path to the executables for the task + *============================================================================*/ +unsigned AddressBook::TaskExecPath(std::string &TaskName, std::string &NewPath) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + } + + TRec->ExecPath = NewPath; + return SUCCESS; +} + +/*============================================================================== + * TaskValid: Indicates whether the Task's data is valid + *============================================================================*/ +bool AddressBook::TaskValid(std::string &TaskName) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", false); + } + + return TRec->TaskValid; +} + +/*============================================================================== + * TaskMapValid: Indicates whether the Task's mappings are valid + *============================================================================*/ +bool AddressBook::TaskMapValid(std::string &TaskName) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", false); + } + + return TRec->MapValid; +} + +/*============================================================================== + * TaskLinkValid: Indicates whether the Task's linkage is valid + *============================================================================*/ +bool AddressBook::TaskLinkValid(std::string &TaskName) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", false); + } + + return TRec->LinkValid; +} + + +/*============================================================================== + * RebuildTask: Rebuild the Task's MessageType/DeviceType maps + *============================================================================*/ +unsigned AddressBook::RebuildTask(std::string &TaskName) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + } + + //TODO: test this + + // Rebuild MessageType map + TRec->MsgTypeMap.clear(); + for(std::vector::iterator M=TRec->MsgTypes.begin(); + M!=TRec->MsgTypes.end(); M++) + { + M->Inputs.clear(); // Clear the Input vector data. + M->Outputs.clear(); // Clear the Output vector data. + TRec->MsgTypeMap.insert(IdxMap_t::value_type(M->Name, (M-TRec->MsgTypes.begin()))); + } + + //Rebuild DeviceType Map and links to MessageType - leave the contents of the Device Vector alone! + TRec->DevTypeMap.clear(); + for(std::vector::iterator D=TRec->DevTypes.begin(); + D!=TRec->DevTypes.end(); D++) + { + TRec->DevTypeMap.insert(IdxMap_t::value_type(D->first.Name, (D-TRec->DevTypes.begin()))); + + // Cross-ref to Message Types. + for(std::vector::iterator I=D->first.InMsgs.begin(); + I!=D->first.InMsgs.end(); I++) // Input Messages + { + TRec->MsgTypes[*I].Inputs.push_back(static_cast(D-TRec->DevTypes.begin())); + } + for(std::vector::iterator O=D->first.OuMsgs.begin(); + O!=D->first.OuMsgs.end(); O++) // Output Messages + { + TRec->MsgTypes[*O].Outputs.push_back(static_cast(D-TRec->DevTypes.begin())); + } + } + + //Rebuild AttributeType map - leave the contents of the Device Vector alone! + TRec->AttrTypeMap.clear(); + for(std::vector::iterator A=TRec->AttrTypes.begin(); + A!=TRec->AttrTypes.end(); A++) + { + TRec->AttrTypeMap.insert(IdxMap_t::value_type(A->first, (A-TRec->AttrTypes.begin()))); + } + + return SUCCESS; +} + +/*============================================================================== + * BuildMaps: Build Task Maps + *============================================================================*/ +unsigned AddressBook::BuildMaps(std::string &TaskName) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + } + + if(TRec->MapValid || TRec->NameMap.size() > 0 + || TRec->ExtCon.size() > 0) ClearMap(TRec); // Existing map, clear it + + + // Map all of the Devices + for(std::vector::iterator DRec=TRec->Devices.begin(); + DRec!=TRec->Devices.end(); DRec++) + { + MapDevice(TRec, &(*DRec)); + } + + // Map all of the Externals + for(std::vector::iterator ERec=TRec->Externals.begin(); + ERec!=TRec->Externals.end(); ERec++) + { + MapDevice(TRec, &(*ERec)); + } + + // Map all of the Supervisors + for(std::vector::iterator SRec=TRec->Supervisors.begin(); + SRec!=TRec->Supervisors.end(); SRec++) + { + // Add the supervisor to the correct DeviceType list. + TRec->DevTypes[SRec->DeviceType].second.push_back(&(*SRec)); + } + + TRec->MapValid = true; // added 18 July 2019 ADR update the map status + + return SUCCESS; +} + +/*============================================================================== + * BuildLink: Build Task linkage + *============================================================================*/ +unsigned AddressBook::BuildLink(std::string &TaskName) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + } + + if(TRec->LinkValid || TRec->AddrMap.size() > 0) ClearLink(TRec); // Existing link, clear it + + // Link all of the Devices + for(std::vector::iterator DRec=TRec->Devices.begin(); + DRec!=TRec->Devices.end(); DRec++) + { + LinkDevice(TRec, &(*DRec)); + } + + // Link all of the Externals + for(std::vector::iterator ERec=TRec->Externals.begin(); + ERec!=TRec->Externals.end(); ERec++) + { + TRec->AddrMap.insert(AddrMap_t::value_type(ERec->Address, &(*ERec))); + } + + // Link all of the Supervisors + for(std::vector::iterator SRec=TRec->Supervisors.begin(); + SRec!=TRec->Supervisors.end(); SRec++) + { + TRec->AddrMap.insert(AddrMap_t::value_type(SRec->Address, &(*SRec))); + } + + TRec->LinkValid = true; // added 18 July 2019 ADR update the link status + + return SUCCESS; +} + + +//============================================================================== +//Device Addition +unsigned AddressBook::AddDevice(std::string &TaskName, Record_t &DevRec, bool Validate) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + // DebugPrint("No such task: %s\n", TaskName.c_str()); + ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + } + + Record_t *DRec; + + if (Validate) // Check that the device does not already exist + { // and that the indices are valid. + unsigned Ret = ValidateDevice(TRec, DevRec); + // DebugPrint("Device validation %s\n", (Ret ? "failed" : "succeeded")); + if(Ret) return Ret; + } + + if ((DevRec.RecordType == Device) || (DevRec.RecordType == DeviceExt)) + { + // Add a Device + // DebugPrint("Ordinary device being added\n"); + CheckVector(TRec, TRec->Devices); // Sanity check for reallocation. + + TRec->Devices.push_back(DevRec); // Add Dev to task. + TRec->DevCnt++; + DRec = &TRec->Devices.back(); + + LinkDevice(TRec, DRec); // Add Device to name map & supervisor list. + MapDevice(TRec, DRec); // Add dev to other maps & lists. + + } else if (DevRec.RecordType == External) { + // Add an External + // DebugPrint("External device being added\n"); + CheckVector(TRec, TRec->Externals); // Sanity check for reallocation + + TRec->Externals.push_back(DevRec); + TRec->ExtCnt++; + DRec = &TRec->Externals.back(); + + TRec->AddrMap.insert(AddrMap_t::value_type(DRec->Address, DRec)); + MapDevice(TRec, DRec); // Add dev to other maps & lists. + + } else if (DevRec.RecordType == Supervisor) { + // Add a Supervisor + // DebugPrint("Supervisor device being added\n"); + CheckVector(TRec, TRec->Supervisors); // Sanity check for reallocation. + + TRec->Supervisors.push_back(DevRec); + TRec->SupCnt++; + DRec = &TRec->Supervisors.back(); + + TRec->AddrMap.insert(AddrMap_t::value_type(DRec->Address, DRec)); + + // Add the supervisor to the correct DeviceType list. + TRec->DevTypes[DRec->DeviceType].second.push_back(DRec); + + SupMap_t::iterator SSearch = TRec->SupMap.find(DRec->Address); + if (SSearch == TRec->SupMap.end()) + { //Supervisor is NOT in the map yet. + TRec->SupMap.insert(SupMap_t::value_type(DRec->Address, + RecordVect_t())); + } + } + // added 18 July 2019 ADR - if Map and Link were previously invalidated + // rebuild everything + unsigned err; + if (!TRec->MapValid && ((err = BuildMaps(TRec->Name)) != SUCCESS)) return err; + if (!TRec->LinkValid && ((err = BuildLink(TRec->Name)) != SUCCESS)) return err; + return SUCCESS; +} + + +/*============================================================================== + * UpdateDevice: Update a device with a new address and supervisor. + * This implicitly marks the Linkage as invalid. + *============================================================================*/ +unsigned AddressBook::UpdateDevice(std::string &TaskName, DeviceData_t &Data) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + } + + // Check that the Device Name exists + NameMap_t::iterator DSearch = TRec->NameMap.find(Data.Name); + if (DSearch == TRec->NameMap.end()) { + return ERR_DEVICE_NOT_FOUND; + } + Record_t *DRec = DSearch->second; + + TRec->LinkValid = false; // Mark the Task linkage as dirty + DRec->Address = Data.Address; // Update the Device Address + DRec->Supervisor = Data.Supervisor; // Update the Device Supervisor + return SUCCESS; +} + +/*============================================================================== + * GetDeviceCount: Get the number of devices reserved in the named task + *============================================================================*/ +long AddressBook::GetDeviceCount(std::string &TaskName) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", ERR_BAD_COUNT); + } + + return static_cast(TRec->DevCntMax); +} + +/*============================================================================== + * GetLoadedDeviceCount: Get the number of devices loaded in the named task + *============================================================================*/ +long AddressBook::GetLoadedDeviceCount(std::string &TaskName) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", ERR_BAD_COUNT); + } + + return static_cast(TRec->DevCnt); +} + +/*============================================================================== + * GetExternalCount: Get the number of externals reserved in the named task + *============================================================================*/ +long AddressBook::GetExternalCount(std::string &TaskName) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", ERR_BAD_COUNT); + } + + return static_cast(TRec->ExtCntMax); +} + +/*============================================================================== + * GetLoadedExternalCount: Get the number of externals loaded in the named task + *============================================================================*/ +long AddressBook::GetLoadedExternalCount(std::string &TaskName) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", ERR_BAD_COUNT); + } + + return static_cast(TRec->ExtCnt); +} + +/*============================================================================== + * GetSupervisorCount: Get the number of supervisors allocated to the task + *============================================================================*/ +int AddressBook::GetSupervisorCount(std::string &TaskName) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", ERR_BAD_COUNT); + } + + return static_cast(TRec->SupCnt); +} + + +//============================================================================== +//Device Queries + +/*============================================================================== + * FindDevice: Find a device by Address. + * Gives a Pointer to Const Device Record + *============================================================================*/ +unsigned AddressBook::FindDevice(std::string &TaskName, SymAddr_t Address, const Record_t* &DRec) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + } + + if(!(TRec->TaskValid && TRec->MapValid && TRec->LinkValid)) // Return NotFound if dirty + { + return ERR_INVALID_MAP; + } + + AddrMap_t::iterator DSearch = TRec->AddrMap.find(Address); // Find the Device + if (DSearch == TRec->AddrMap.end()) { + ERETURN("Device Not Found", ERR_DEVICE_NOT_FOUND); + } + + DRec = &(*DSearch->second); + return SUCCESS; +} + + +/*============================================================================== + * FindDevice: Find a device by Name. + * Gives a Pointer to Const Device Record + *============================================================================*/ +unsigned AddressBook::FindDevice(std::string &TaskName, std::string &Name, const Record_t* &DRec) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + } + + if(!(TRec->TaskValid && TRec->MapValid && TRec->LinkValid)) // Return NotFound if dirty + { + return ERR_INVALID_MAP; + } + + NameMap_t::iterator DSearch = TRec->NameMap.find(Name); // Find the Device + if (DSearch == TRec->NameMap.end()) { + ERETURN("Device Not Found", ERR_DEVICE_NOT_FOUND); + } + + DRec = &(*DSearch->second); + return SUCCESS; +} + + +/*============================================================================== + * FindBySuper: Find a vector of devices supervised by Supervisor. + * Gives a Pointer to a const Vector of Pointers to const Device + * Records. + *============================================================================*/ +unsigned AddressBook::FindBySuper(std::string &TaskName, SymAddr_t Supervisor, const RecordVect_t* &Records) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + } + + if(!(TRec->TaskValid && TRec->MapValid && TRec->LinkValid)) // Return NotFound if dirty + { + return ERR_INVALID_MAP; + } + + SupMap_t::iterator SSearch = TRec->SupMap.find(Supervisor); // Find the Supervisor + if (SSearch == TRec->SupMap.end()) { + ERETURN("Device Not Found", ERR_DEVICE_NOT_FOUND); + } + + Records = &SSearch->second; + return SUCCESS; +} + +unsigned AddressBook::FindByType(std::string &TaskName, std::string Type, const RecordVect_t* &Records) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + } + + if(!(TRec->TaskValid && TRec->MapValid && TRec->LinkValid)) // Return NotFound if dirty + { + return ERR_INVALID_MAP; + } + + IdxMap_t::iterator TSearch = TRec->DevTypeMap.find(Type); // Find the Index + if (TSearch == TRec->DevTypeMap.end()) { + ERETURN("Device Type Not Found", ERR_DEVICE_NOT_FOUND); + } + + Records = &(TRec->DevTypes[TSearch->second].second); + + return SUCCESS; +} + +unsigned AddressBook::FindByAttribute(std::string &TaskName, std::string Attribute, const RecordVect_t* &Records) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + } + + if(!(TRec->TaskValid && TRec->MapValid && TRec->LinkValid)) // Return NotFound if dirty + { + return ERR_INVALID_MAP; + } + + IdxMap_t::iterator ASearch = TRec->AttrTypeMap.find(Attribute); // Find the Index + if (ASearch == TRec->AttrTypeMap.end()) { + ERETURN("Device Type Not Found", ERR_DEVICE_NOT_FOUND); + } + + Records = &(TRec->AttrTypes[ASearch->second].second); + + return SUCCESS; +} + +unsigned AddressBook::FindByInMsg(std::string &TaskName, std::string Msg, const RecordVect_t* &Records) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + } + + if(!(TRec->TaskValid && TRec->MapValid && TRec->LinkValid)) // Return NotFound if dirty + { + return ERR_INVALID_MAP; + } + + return SUCCESS; +} + +unsigned AddressBook::FindByOuMsg(std::string &TaskName, std::string Msg, const RecordVect_t* &Records) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + } + + if(!(TRec->TaskValid && TRec->MapValid && TRec->LinkValid)) // Return NotFound if dirty + { + return ERR_INVALID_MAP; + } + + return SUCCESS; +} + +unsigned AddressBook::GetDevices(std::string &TaskName, const std::vector* &Records) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + } + + if(!(TRec->TaskValid && TRec->MapValid && TRec->LinkValid)) // Return NotFound if dirty + { + return ERR_INVALID_MAP; + } + + Records = &(TRec->Devices); + + return SUCCESS; +} + +unsigned AddressBook::GetExternals(std::string &TaskName, const std::vector* &Records) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + } + + if(!(TRec->TaskValid && TRec->MapValid && TRec->LinkValid)) // Return NotFound if dirty + { + return ERR_INVALID_MAP; + } + + Records = &(TRec->Externals); + + return SUCCESS; +} + +unsigned AddressBook::GetSupervisors(std::string &TaskName, const std::vector* &Records) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + } + + if(!(TRec->TaskValid && TRec->MapValid && TRec->LinkValid)) // Return NotFound if dirty + { + return ERR_INVALID_MAP; + } + + Records = &(TRec->Supervisors); + + return SUCCESS; +} + +unsigned AddressBook::GetExtCon(std::string &TaskName, const RecordVect_t* &Records) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + } + + if(!(TRec->TaskValid && TRec->MapValid && TRec->LinkValid)) // Return NotFound if dirty + { + return ERR_INVALID_MAP; + } + + Records = &(TRec->ExtCon); + + return SUCCESS; +} + + + + +//============================================================================== +//Private Methods + +/*============================================================================== + * FindTask: Return a pointer to the named task. + *============================================================================*/ +TaskRecord_t * AddressBook::FindTask(const std::string &TaskName) +{ + // Check that the task exists. + TaskMap_t::iterator TSearch = TaskMap.find(TaskName); + if (TSearch == TaskMap.end()) { + ERETURN("Task Does Not Exist", PNULL); + } + + return TSearch->second; +} + + +unsigned AddressBook::MapDevice(TaskRecord_t *TRec, Record_t *DRec) +{ + // Add device to name map + TRec->NameMap.insert(NameMap_t::value_type(DRec->Name, DRec)); + + // Add the device to the correct DeviceType list. + TRec->DevTypes[DRec->DeviceType].second.push_back(DRec); + + if(DRec->RecordType == DeviceExt) // Device has an external conn + { + TRec->ExtCon.push_back(DRec); // Add it to the list of such devices. + } + + // Add the device to the correct attribute list + if(DRec->Attribute > -1) + { + TRec->AttrTypes[static_cast(DRec->Attribute)].second.push_back(DRec); + } + + return SUCCESS; +} + +unsigned AddressBook::LinkDevice(TaskRecord_t *TRec, Record_t *DRec) +{ + // Add Device to Address map. + TRec->AddrMap.insert(AddrMap_t::value_type(DRec->Address, DRec)); + + // Add the device to the correct Supervisor list. + // Supervisors may be loaded after devices, may need to build the map. + SupMap_t::iterator SSearch = TRec->SupMap.find(DRec->Supervisor); + if (SSearch == TRec->SupMap.end()) { //Supervisor is NOT in the map yet. + std::pair LastVal; // Have to do this because C++98 does not like initialiser lists... + LastVal = TRec->SupMap.insert(SupMap_t::value_type(DRec->Supervisor, RecordVect_t())); + LastVal.first->second.push_back(DRec); // RecordVect_t({DRec}) in the insert would be neater and not need the pair. + + } else { //Supervisor is already in the map. + SSearch->second.push_back(DRec); + } + + return SUCCESS; +} + + +/*============================================================================== + * ValidateTask: Check that the task has a valid vector of DeviceTypes. + *============================================================================*/ +unsigned AddressBook::ValidateTask(TaskData_t &Data) +{ + for(std::vector::const_iterator D=Data.DeviceTypes.begin(); + D!=Data.DeviceTypes.end(); D++) + { + if (unsigned retVal = ValidateDeviceType(*D, Data.MessageTypes.size())) + return retVal; + } + + return SUCCESS; +} + +/*============================================================================== + * ValidateDeviceType: Check that DeviceType Message indices are valid and not + * out of range. + * Added and separated from ValidateTask 5 July 2019 ADR + *============================================================================*/ +unsigned AddressBook::ValidateDeviceType(const DevTypeRecord_t& DevTypRec, unsigned MaxIdx) +{ + for(std::vector::const_iterator I=DevTypRec.InMsgs.begin(); + I!=DevTypRec.InMsgs.end(); I++) + { + if(*I >= MaxIdx) + { + ERETURN("Invalid MessageType Index", ERR_INVALID_MESSAGE_TYPE); + } + } + + // changed to iterate over OuMsgs (was InMsgs) 5 July 2019 ADR + for(std::vector::const_iterator O=DevTypRec.OuMsgs.begin(); + O!=DevTypRec.OuMsgs.end(); O++) + { + if(*O >= MaxIdx) + { + ERETURN("Invalid MessageType Index", ERR_INVALID_MESSAGE_TYPE); + } + } + return 0; +} + + +/*============================================================================== + * ValidateDevice: Check that the device does not already exist in the name map + * and that indices in the Record are not out of range. + *============================================================================*/ +unsigned AddressBook::ValidateDevice(TaskRecord_t *TRec, Record_t &DevRec) +{ + // Check that the device does not already exist in the maps + AddrMap_t::const_iterator DASearch = TRec->AddrMap.find(DevRec.Address); + if (DASearch != TRec->AddrMap.end()) { + // DebugPrint("Device address %llu already exists\n", DevRec.Address); + ERETURN("DUPADDR: Device Address already added", ERR_DEVICE_ADDR_USED); + } + + NameMap_t::const_iterator DNSearch = TRec->NameMap.find(DevRec.Name); + if (DNSearch != TRec->NameMap.end()) { + // DebugPrint("Device name %s already exists\n", DevRec.Name.c_str()); + ERETURN("DUPNAME: Device Name already added", ERR_DEVICENAME_USED); + } + + // Check that the indices are valid BEFORE adding the Device. + if (DevRec.DeviceType >= TRec->DevTypes.size()) { + // DebugPrint("Device type %u does not exist\n", DevRec.DeviceType); + ERETURN("Invalid DeviceType Index", ERR_INVALID_DEVTYPE); + } + + if (DevRec.Attribute >= static_cast(TRec->AttrTypes.size())) { + // DebugPrint("Device attribute type %u does not exist\n", DevRec.Attribute); + ERETURN("Invalid AttributeType Index", ERR_INVALID_ATTRIBUTE); + } + + return SUCCESS; // Validation Successful +} + +/*============================================================================== + * CheckVector: Check that adding a Record to the vector won't cause a + * reallocation as this would silently invalidate all of the maps. + * If the vector is at capacity, increase it's size, clear the task + * linkage & mappings and mark both as dirty. + * + * As the Record vectors are pre-sized based on what should be in + * the task plus one element, there should never be a reallocation. + *============================================================================*/ +unsigned AddressBook::CheckVector(TaskRecord_t *TRec, std::vector &Vect) +{ + if(Vect.size() == Vect.capacity()) + { + Vect.reserve(static_cast(Vect.capacity()*1.25)); + ClearLink(TRec); + ClearMap(TRec); + return ERR_INVALID_MAP; + } + return SUCCESS; +} + + +/*============================================================================== + * ClearMap: Clear the Device to DeviceType/Attribute/(Message) Type links + * and mark the linkage as dirty. Also clears the Name>Record map + * and list of records with external connections. + *============================================================================*/ +unsigned AddressBook::ClearMap(TaskRecord_t *TRec) +{ + TRec->MapValid = false; // Mark the map as dirty. + TRec->NameMap.clear(); // Clear the Name map + TRec->ExtCon.clear(); // Clear External Connections List. + + // Clear DevType->DeviceRecord vectors + for(std::vector::iterator D=TRec->DevTypes.begin(); + D!=TRec->DevTypes.end();D++) + { + D->second.clear(); + } + + // Clear Attribute->DeviceRecord vectors + for(std::vector::iterator A=TRec->AttrTypes.begin(); + A!=TRec->AttrTypes.end();A++) + { + A->second.clear(); + } + + return SUCCESS; +} + + +/*============================================================================== + * ClearLink: Clear the Address>Record map and the Supervisor>Device links. + * Also marks the linkage as dirty. + *============================================================================*/ +unsigned AddressBook::ClearLink(TaskRecord_t *TRec) +{ + TRec->LinkValid = false; // Mark the linkage as dirty. + TRec->AddrMap.clear(); // Clear the Addres>DeviceRecord map. + + //Clear the Device Record vectors for each supervisor. + for(SupMap_t::iterator S=TRec->SupMap.begin();S!=TRec->SupMap.end();S++) + { + S->second.clear(); + } + + return SUCCESS; +} + + +//============================================================================== +//Integrity Checks +unsigned AddressBook::IntegCheck(void) +{ + std::vector Temp; + return IntegCheck(Temp); +} + +unsigned AddressBook::IntegCheck(std::vector &TaskIntegs) +{ + unsigned TInteg, Ret = 0; + + for(TaskMap_t::const_iterator T=TaskMap.begin(); + T!=TaskMap.end();T++) + { + TInteg = T->second->Integrity(false); + TaskIntegs.push_back(TInteg); + if(TInteg) Ret++; + } + + return Ret; +} + +unsigned AddressBook::IntegTask(std::string &TaskName, bool Verbose, FILE * fp) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + } + + return TRec->Integrity(Verbose, fp); +} + + + +//============================================================================== +//Dumps + +void AddressBook::Dump(std::string &Name) +{ + Dump(stdout, Name); +} + +void AddressBook::Dump(FILE * fp, std::string Name) +{ + fprintf(fp,"AddressBook+++++++++++++++++++++++++++++++++\n"); + fprintf(fp,"ABderived (this derived process) : %s\n",ABderived.c_str()); + + if(Name == std::string("")) // Dump high-level task data. + { + fprintf(fp,"Total number of tasks: %d:\n", TaskCount); + for(TaskMap_t::iterator T=TaskMap.begin(); + T!=TaskMap.end();T++) + { + TaskRecord_t *TRec = T->second; + fprintf(fp,"Task %ld: Key: %s At: %" PTR_FMT "\n", + static_cast(std::distance(TaskMap.begin(), T)), + T->first.c_str(), reinterpret_cast(TRec)); + fprintf(fp,"\tName: %s\n", TRec->Name.c_str()); + fprintf(fp,"\tPath: %s\n", TRec->Path.c_str()); + fprintf(fp,"\tXML: %s\n", TRec->XML.c_str()); + fprintf(fp,"\tExecPath: %s\n", TRec->ExecPath.c_str()); + fprintf(fp,"\tExternal Count: %ld\n", TRec->ExtCntMax); + fprintf(fp,"\tDevice Count: %ld\n", TRec->DevCntMax); + fprintf(fp,"\tState: %d\n", TRec->State); + fprintf(fp,"\tAllocated Supervisors: %ld\n", TRec->SupCnt); + fprintf(fp,"\tLoaded Externals: %ld\n", TRec->ExtCnt); + fprintf(fp,"\tLoaded Devices: %ld\n", TRec->DevCnt); + } + } else { // Dump task-specific data. + // Check that the task exists. + TaskMap_t::const_iterator Search = TaskMap.find(Name); + if (Search == TaskMap.end()) { + fprintf(fp,"ERROR: Task %s not found.\n", Name.c_str()); + } else { + TaskRecord_t *TRec = Search->second; + + //Dump Task Data + fprintf(fp,"Task: %s at %" PTR_FMT "\n", Search->first.c_str(), reinterpret_cast(TRec)); + fprintf(fp,"\tPath: %s\n", TRec->Path.c_str()); + fprintf(fp,"\tExecPath: %s\n", TRec->ExecPath.c_str()); + fprintf(fp,"\tExternal Count: %ld\n", TRec->ExtCntMax); + fprintf(fp,"\tDevice Count: %ld\n", TRec->DevCntMax); + fprintf(fp,"\tState: %d\tTaskValid: %d\tMap Valid: %d\tLink Valid: %d\n", + TRec->State, TRec->TaskValid, TRec->MapValid, TRec->LinkValid); + + //Dump Message Types + fprintf(fp,"\tMessage Types:\t%lu\n", static_cast(TRec->MsgTypes.size())); + fprintf(fp,"\t\tIdx\tName\tMapIdx\tMapName\tDTypeI\tDTypeO\n"); + for(std::vector::const_iterator M + =TRec->MsgTypes.begin();M!=TRec->MsgTypes.end();M++) + { + fprintf(fp,"\t\t%ld\t%s\t", static_cast(M-TRec->MsgTypes.begin()), M->Name.c_str()); + + IdxMap_t::const_iterator MSearch = TRec->MsgTypeMap.find(M->Name); + if (MSearch == TRec->MsgTypeMap.end()) { + fprintf(fp,"Not Mapped\t"); + } else { + fprintf(fp,"%d\t%s\t", MSearch->second, + TRec->MsgTypes[MSearch->second].Name.c_str()); + } + + for(std::vector::const_iterator I= + M->Inputs.begin(); I!=M->Inputs.end(); I++) + { // Input Messages + fprintf(fp,"%d,",*I); + } + fprintf(fp,"\t"); + + for(std::vector::const_iterator O= + M->Outputs.begin();O!=M->Outputs.end(); O++) + { // Output Messages + fprintf(fp,"%d,",*O); + } + fprintf(fp,"\n"); + } + fprintf(fp,"\n"); + + //Dump Device Types + fprintf(fp,"\tDevice Types:\t%lu\n", static_cast(TRec->DevTypes.size())); + fprintf(fp,"\t\tIdx\tName\tMapIdx\tMapName\tDevCnt\tInMsgs\tOuMsgs\n"); + for(std::vector::const_iterator D + =TRec->DevTypes.begin();D!=TRec->DevTypes.end();D++) + { + fprintf(fp,"\t\t%ld\t%s\t", static_cast(D-TRec->DevTypes.begin()), D->first.Name.c_str()); + + //Print the DevTypeMap mapping + IdxMap_t::const_iterator DSearch = TRec->DevTypeMap.find(D->first.Name); + if (DSearch == TRec->DevTypeMap.end()) { + fprintf(fp,"Not Mapped\t"); + } else { + fprintf(fp,"%d\t%s\t", DSearch->second, + TRec->DevTypes[DSearch->second].first.Name.c_str()); + } + + //Print the number of devices of this type. + fprintf(fp,"%lu\t", static_cast(D->second.size())); + + //Print the Input Msg Indices + for(std::vector::const_iterator I + =D->first.InMsgs.begin();I!=D->first.InMsgs.end();I++) + { + fprintf(fp,"%d,", *I); + } + fprintf(fp,"\t"); + + //Print the Output Msg Indices + for(std::vector::const_iterator O + =D->first.OuMsgs.begin();O!=D->first.OuMsgs.end();O++) + { + fprintf(fp,"%d,", *O); + } + fprintf(fp,"\n"); + + } + fprintf(fp,"\n"); + + //Dump Attribute Types + fprintf(fp,"\tAttribute Types:\t%lu\n", static_cast(TRec->AttrTypes.size())); + if(TRec->AttrTypes.size()>0) + { + fprintf(fp,"\t\tIdx\tName\tMapIdx\tMapName\tDevCnt\n"); + for(std::vector::const_iterator A + =TRec->AttrTypes.begin();A!=TRec->AttrTypes.end();A++) + { + fprintf(fp,"\t\t%ld\t%s\t", static_cast(A-TRec->AttrTypes.begin()), + A->first.c_str()); + + IdxMap_t::const_iterator ASearch = TRec->AttrTypeMap.find(A->first); + if (ASearch == TRec->AttrTypeMap.end()) { + fprintf(fp,"Not Mapped\t"); + } else { + fprintf(fp,"%d\t%s\t", ASearch->second, + TRec->AttrTypes[ASearch->second].first.c_str()); + } + + //Print the number of devices with this attribute. + fprintf(fp,"%ld\n", static_cast(A->second.size())); + } + fprintf(fp,"\n"); + } + + // Dump allocated Supervisors + fprintf(fp,"\tAllocated Supervisors: %ld\n", TRec->SupCnt); + if(TRec->SupCnt>0) + { + fprintf(fp,"\t\tIdx\tAddress\tRank\tDev Count\n"); + for(std::vector::const_iterator R + =TRec->Supervisors.begin();R!=TRec->Supervisors.end();R++) + { + //TODO: Write the map search to get count of devices for + // a supervisor. + fprintf(fp,"\t\t%ld\t%" SYMA_FMT "\t%lu\t%d\n", + static_cast(R-TRec->Supervisors.begin()), + R->Address, R->Rank, 0); + } + fprintf(fp,"\n"); + } + + // Dump loaded Externals + fprintf(fp,"\tLoaded Externals: %ld\n", TRec->ExtCnt); + if(TRec->ExtCnt>0) + { + fprintf(fp,"\t\tIdx\tName\tAddress\n"); + for(std::vector::const_iterator R + =TRec->Externals.begin();R!=TRec->Externals.end();R++) + { + fprintf(fp,"\t\t%ld\t%s\t%" SYMA_FMT "\n", + static_cast(R-TRec->Externals.begin()), + R->Name.c_str(), R->Address); + } + fprintf(fp,"\n"); + } + + + // Dump loaded Devices + fprintf(fp,"\tLoaded Devices: %ld\n", TRec->DevCnt); + if(TRec->DevCnt>0) + { + fprintf(fp,"\t\tIdx\tName\tAddress\t\tSupervisor\n"); + for(std::vector::const_iterator R + =TRec->Devices.begin();R!=TRec->Devices.end();R++) + { + fprintf(fp,"\t\t%ld\t%s\t%" SYMA_FMT "\t%" SYMA_FMT "\n", + static_cast(R-TRec->Devices.begin()), + R->Name.c_str(), R->Address, R->Supervisor); + } + } + } + } + + fprintf(fp,"AddressBook_--------------------------------\n"); + fflush(fp); +} +} /* namespace AddressBookNS */ diff --git a/Source/NameServer/AddressBook/AddressBook.hpp b/Source/NameServer/AddressBook/AddressBook.hpp new file mode 100644 index 00000000..e98036d8 --- /dev/null +++ b/Source/NameServer/AddressBook/AddressBook.hpp @@ -0,0 +1,166 @@ +/*============================================================================== + * AddressBook: A back-end implementation for the POETS sbase & Nameserver + * + * Tasks can be *maped* and *linked*: + * Mapped: Device Records connected to Device (and Message) and Attribute + * types. Device Records with External Connections also listed. + * Linked: Device Records connected to Addresses in Address Map and listed + * in the relevant Supervisor vector. + * + * Linkage is invalidated when/if a Device Record is updated after load. + * Mapping is invalidated if more devices than expected are loaded. + * + * Struct sizing with no Pragma Packing: + * Win 64-Bit Win 32-Bit Mac 64-Bit + * TaskRecord_t 560 324 464 + * Record_t 72 64 52 + * TaskData_t 280 184 216 + * DeviceData_t 56 48 40 + * + * Memory Footprint* 221.7MB 153.2MB 194MB + * *1 task with 1 million devices, 1 supervisor and 1 external. + * + * + * + *============================================================================*/ + +#ifndef AddressBook_H +#define AddressBook_H + +#include "OSFixes.hpp" + +#include "AddressBook_Defs.hpp" +#include "AddressBook_Task.hpp" + +#include +#include +#include +#include +#include +#include +#include + + + +#define MAXSUPERVISORS 16 + +//============================================================================== +namespace AddressBookNS // changed name to avoid conflicts with the class itself + // 14 July 2019 ADR +{ +typedef std::map TaskMap_t; + +class AddressBook +{ +public: + AddressBook(std::string d); + ~AddressBook(); + + unsigned GetTaskCount(void); + + // Task Manipulation + unsigned AddTask(const std::string &TaskName, TaskData_t &Data); + unsigned ListTask(std::vector &Tasks); + unsigned GetTask(const std::string &TaskName, TaskData_t &Task); + unsigned DelTask(const std::string &TaskName); + + unsigned AddDeviceType(const std::string &TaskName, const DevTypeRecord_t &DeviceType); // add a new DeviceType + unsigned ClearTask(const std::string &TaskName); // deletes all the devices for a task without removing the task. + + TaskState_t TaskState(std::string &TaskName); // Get the task state + unsigned TaskState(std::string &TaskName, TaskState_t State); // Set the task state + + std::string TaskExecPath(std::string &TaskName); // Get the path of a task + unsigned TaskExecPath(std::string &TaskName, std::string &NewPath); // Set the path of a task + + bool TaskValid(std::string &TaskName); + bool TaskMapValid(std::string &TaskName); + bool TaskLinkValid(std::string &TaskName); + + unsigned RebuildTask(std::string &TaskName); + unsigned BuildMaps(std::string &TaskName); + unsigned BuildLink(std::string &TaskName); + + // Device Manipulation + unsigned AddDevice(std::string &TaskName, Record_t &Device, bool Validate = true); + unsigned UpdateDevice(std::string &TaskName, DeviceData_t &Data); + + // Find a device + unsigned FindDevice(std::string &TaskName, std::string &Name, const Record_t* &DRec); + unsigned FindDevice(std::string &TaskName, SymAddr_t Address, const Record_t* &DRec); + + // Find all devices supervised by X + unsigned FindBySuper(std::string &TaskName, SymAddr_t Supervisor, const RecordVect_t* &Records); + + unsigned FindByType(std::string &TaskName, std::string Type, const RecordVect_t* &Records); + unsigned FindByAttribute(std::string &TaskName, std::string Attribute, const RecordVect_t* &Records); + + unsigned FindByInMsg(std::string &TaskName, std::string Msg, const RecordVect_t* &Records); //TODO + unsigned FindByOuMsg(std::string &TaskName, std::string Msg, const RecordVect_t* &Records); //TODO + + // device getters. Note that a vector is different from a RecordVect_t, + // which is a vector + unsigned GetDevices(std::string &TaskName, const std::vector* &Records); + unsigned GetExternals(std::string &TaskName, const std::vector* &Records); + unsigned GetSupervisors(std::string &TaskName, const std::vector* &Records); + unsigned GetExtCon(std::string &TaskName, const RecordVect_t* &Records); + + // Device Count getters + long GetDeviceCount(std::string &TaskName); + long GetLoadedDeviceCount(std::string &TaskName); + long GetExternalCount(std::string &TaskName); + long GetLoadedExternalCount(std::string &TaskName); + int GetSupervisorCount(std::string &TaskName); + + // Integrity + unsigned IntegCheck(void); // Integrity check of ALL tasks + unsigned IntegCheck(std::vector &TaskIntegs); + unsigned IntegTask(std::string &TaskName, bool Verbose = false, FILE * = stdout); // Ingerity Check a Task by name + //unsigned IntegTask(const TaskRecord_t *TRec, bool Verbose = false, FILE * = stdout); // Ingerity Check a Task by pointer + + // Debugging + void Dump(std::string &Name); + void Dump(FILE * = stdout, std::string Name = ""); + + static const long ERR_BAD_COUNT = -1; + + static const unsigned SUCCESS = 0; + static const unsigned ERR_NONFATAL = 0; + static const unsigned ERR_INVALID_TASK = 1; + static const unsigned ERR_INVALID_DEVTYPE = 2; + static const unsigned ERR_INVALID_DEVICE = 3; + static const unsigned ERR_INVALID_MESSAGE_TYPE = 4; + static const unsigned ERR_INVALID_ATTRIBUTE = 5; + static const unsigned ERR_DEVICE_DATA_MISMATCH = 6; + static const unsigned ERR_TASKNAME_USED = 7; + static const unsigned ERR_DEVICENAME_USED = 8; + static const unsigned ERR_DEVICE_ADDR_USED = 9; + static const unsigned ERR_TASK_NOT_FOUND = 10; + static const unsigned ERR_DEVICE_NOT_FOUND = 11; + static const unsigned ERR_INVALID_MAP = 12; + static const unsigned ERR_INVALID_SUPERVISOR = 13; + static const unsigned ERR_INVALID_STATE = 14; + +private: + TaskMap_t TaskMap; + int TaskCount; + std::string ABderived; // changed to allow multiple inheritance (from CommonBase) 14 July 2019 ADR + + TaskRecord_t * FindTask(const std::string &TaskName); + + unsigned ValidateDevice(TaskRecord_t *TRec, Record_t &DevRec); + unsigned ValidateDeviceType(const DevTypeRecord_t& DevTypRec, unsigned MaxIdx); + unsigned ValidateTask(TaskData_t &Data); + + unsigned CheckVector(TaskRecord_t *TRec, std::vector &Vect); + + unsigned LinkDevice(TaskRecord_t *TRec, Record_t *DRec); // Add Device to name map & supervisor list. + unsigned MapDevice(TaskRecord_t *TRec, Record_t *DRec); // Add Device to other maps & lists. + + unsigned ClearMap(TaskRecord_t *TRec); + unsigned ClearLink(TaskRecord_t *TRec); + +}; +} /* namespace AddressBookNS */ + +#endif /* AddressBook_H */ diff --git a/Source/NameServer/AddressBook/AddressBook_Defs.cpp b/Source/NameServer/AddressBook/AddressBook_Defs.cpp new file mode 100644 index 00000000..bc3c6e7e --- /dev/null +++ b/Source/NameServer/AddressBook/AddressBook_Defs.cpp @@ -0,0 +1,54 @@ +#include "AddressBook_Defs.hpp" + +namespace AddressBookNS +{ + +// const SymAddr_t INVALID_ADDRESS; + +int DeviceData_t::size() const +{ + int size = 0; + + size += sizeof(SymAddr_t) * 2; + size += Name.size(); + + return size; +} + + +DevTypeRecord_t::DevTypeRecord_t(std::string N) +{ + Name = N; +} + +int DevTypeRecord_t::size() const +{ + int size = 0; + + size += Name.size(); + size += sizeof(MsgIdx) * InMsgs.size(); + size += sizeof(MsgIdx) * OuMsgs.size(); + + return size; +} + + +MsgTypeRecord_t::MsgTypeRecord_t(std::string N) +{ + Name = N; +} + +int MsgTypeRecord_t::size() const +{ + int size = 0; + + size += Name.size(); + size += sizeof(MsgIdx) * Inputs.size(); + size += sizeof(MsgIdx) * Outputs.size(); + + return size; +} + + + +} /* namespace AddressBookNS */ diff --git a/Source/NameServer/AddressBook/AddressBook_Defs.hpp b/Source/NameServer/AddressBook/AddressBook_Defs.hpp new file mode 100644 index 00000000..d3b65f4d --- /dev/null +++ b/Source/NameServer/AddressBook/AddressBook_Defs.hpp @@ -0,0 +1,60 @@ +#ifndef AddressBook_Defs_H +#define AddressBook_Defs_H + +#include "OSFixes.hpp" + +#include +#include +#include +#include + +namespace AddressBookNS +{ + +//---------------------------------------- +// Temporary typedefs +typedef uint64_t SymAddr_t; // A 64-bit full-symbolic address + +static const SymAddr_t INVALID_ADDRESS = UINT64_MAX; +//typedef unsigned long SymAddr_t; // A 64-bit full-symbolic address + +//---------------------------------------- + +enum TaskState_t { Loaded = 0, Linked, Built, Deployed, Init, Running, Finished, Unknown }; + +typedef unsigned DTypeIdx; +typedef int AttrIdx; +typedef unsigned MsgIdx; + + +struct DeviceData_t { + int size() const; // Get the size of the DeviceData + + SymAddr_t Address; // Device's full sym address. + SymAddr_t Supervisor; // Full sym address of the Device's Supervisor. + std::string Name; // Device's cnonical name. +}; + + +struct DevTypeRecord_t { + DevTypeRecord_t(std::string N = ""); + int size() const; // Get the size of the DeviceType Record + + std::string Name; // Device Type cnonical name. + std::vector InMsgs; // Vector of Input Message indexes + std::vector OuMsgs; // Vector of Output Message indexes +}; + + + +struct MsgTypeRecord_t { + MsgTypeRecord_t(std::string N = ""); + int size() const; // Get the size of the MsgType Record + + std::string Name; // Message Type Name + std::vector Inputs; // Indicies of DeviceTypes that have this MessageType as an input + std::vector Outputs; // Indicies of DeviceTypes that have this MessageType as an output +}; + +} /* namespace AddressBookNS */ +#endif /* AddressBook_Defs_H */ diff --git a/Source/NameServer/AddressBook/AddressBook_Record.cpp b/Source/NameServer/AddressBook/AddressBook_Record.cpp new file mode 100644 index 00000000..c089278a --- /dev/null +++ b/Source/NameServer/AddressBook/AddressBook_Record.cpp @@ -0,0 +1,40 @@ +#include "AddressBook_Record.hpp" + +namespace AddressBookNS +{ + +Record_t::Record_t() +{ + Attribute = -1; +} + +Record_t::Record_t(std::string Name, SymAddr_t Addr, uint64_t Super, + DTypeIdx Type, RecordType_t RT, AttrIdx Attr) + : Name(Name) +{ + Address = Addr; + DeviceType = Type; + RecordType = RT; + Attribute = Attr; + Rank = 0; + Supervisor = 0; + if (RecordType == Supervisor) Rank = static_cast(Super); + else Supervisor = static_cast(Super); +} + + +int Record_t::size() const +{ + int size = 0; + + size += sizeof(SymAddr_t) * 2; // Address and Supervisor/Rank + size += sizeof(DTypeIdx); // Device Type Idx + size += sizeof(AttrIdx); // Attribute Idx + size += sizeof(RecordType_t); // Record Type + size += sizeof(char) * Name.size(); // Name + + return size; +} + + +} /* namespace AddressBookNS */ diff --git a/Source/NameServer/AddressBook/AddressBook_Record.hpp b/Source/NameServer/AddressBook/AddressBook_Record.hpp new file mode 100644 index 00000000..c1e480fc --- /dev/null +++ b/Source/NameServer/AddressBook/AddressBook_Record.hpp @@ -0,0 +1,39 @@ +#ifndef AddressBook_Record_H +#define AddressBook_Record_H + +#include "AddressBook_Defs.hpp" + +namespace AddressBookNS +{ + enum RecordType_t { Device = 0, DeviceExt, External, Supervisor }; + + // data contents factored out for serialisation 17 July 2019 ADR + struct RecordData_t + { + public: + + SymAddr_t Address; // Device's full sym address. + union + { + SymAddr_t Supervisor; // Full sym address of the Device's Supervisor. + unsigned long Rank; // OR Supervisor's MPI Rank. + }; + DTypeIdx DeviceType; // Index of the Device's type in task. + AttrIdx Attribute; // Index of the Device's attribute in task. + RecordType_t RecordType; // Class of device represented by the record. + }; + + class Record_t : public RecordData_t + { + public: + + Record_t(); + Record_t(std::string, SymAddr_t, uint64_t, DTypeIdx, RecordType_t = Device, AttrIdx = -1); + + int size() const; // Size of the record + + std::string Name; // Device's canonical name. + }; + +} /* namespace AddressBookNS */ +#endif /* AddressBook_Record_H */ diff --git a/Source/NameServer/AddressBook/AddressBook_Task.cpp b/Source/NameServer/AddressBook/AddressBook_Task.cpp new file mode 100644 index 00000000..a5e5e9f4 --- /dev/null +++ b/Source/NameServer/AddressBook/AddressBook_Task.cpp @@ -0,0 +1,802 @@ +#include "AddressBook_Task.hpp" + +namespace AddressBookNS +{ + +/*============================================================================== + * TaskData + *============================================================================*/ +TaskData_t::TaskData_t() +{ + Name = ""; + Path = ""; + XML = ""; + ExecutablePath = ""; + State = Loaded; + DeviceCount = 0; + DeviceCountLd = 0; + ExternalCount = 0; + ExternalCountLd = 0; + SupervisorCount = 0; + + State = Loaded; +} + +TaskData_t::TaskData_t(std::string &N, std::string &P, std::string &X, std::string &E, + TaskState_t S, unsigned long DC, unsigned long EC) +{ + Name = N; + Path = P; + XML = X; + ExecutablePath = E; + State = Loaded; + DeviceCount = DC; + DeviceCountLd = 0; + ExternalCount = EC; + ExternalCountLd = 0; + SupervisorCount = 0; + + State = S; +} + +int TaskData_t::size() const +{ + int size = 0; + + size += sizeof(unsigned long)*5; // Size of the 5 longs + size += sizeof(char) * Name.size(); // Size of the name + size += sizeof(char) * Path.size(); // Size of the path + size += sizeof(char) * XML.size(); // Size of the XML Filename + size += sizeof(char) * ExecutablePath.size(); // Size of the exec path + size += sizeof(TaskState_t); + + for(std::vector::const_iterator DT = DeviceTypes.begin(); + DT != DeviceTypes.end(); DT++) // Size of the device types + { + size += DT->size(); + } + + for(std::vector::const_iterator MT = MessageTypes.begin(); + MT != MessageTypes.end(); MT++) // Size of the Message Types + { + size += MT->size(); + } + + for(std::vector::const_iterator AT = AttributeTypes.begin(); + AT != AttributeTypes.end(); AT++) // Size of the Attribute Types + { + size += AT->size(); + } + + return size; +} + +/*============================================================================== + * TaskRecord + *============================================================================*/ +TaskRecord_t::TaskRecord_t() +{ + Name = ""; + Path = ""; + XML = ""; + ExecPath = ""; + DevCntMax = 0; + ExtCntMax = 0; + DevCnt = 0; + SupCnt = 0; + ExtCnt = 0; + + State = Loaded; + + TaskValid = true; + MapValid = true; + LinkValid = true; +} + +TaskRecord_t::TaskRecord_t(std::string &N, std::string &P, std::string &X, std::string &E, + TaskState_t S, unsigned long DC, unsigned long EC) +{ + Name = N; + Path = P; + XML = X; + ExecPath = E; + DevCntMax = DC; + ExtCntMax = EC; + DevCnt = 0; + SupCnt = 0; + ExtCnt = 0; + + State = S; + + TaskValid = true; + MapValid = true; + LinkValid = true; +} + +unsigned TaskRecord_t::Integrity(bool Verbose, FILE * fp) +{ + ABULONG ExtConCnt(0); + ABUNSIGNED MappedSupervisors(0); + + IntegVals_t retVal; + retVal.ret = 0; + retVal.retT = 0; + retVal.retL = 0; + retVal.retM = 0; + + //fprintf(fp,"Task: %s\n", Search->first.c_str()); + + if (Verbose) fprintf(fp, "Integrity check of %s:\n", Name.c_str()); + + //========================================================================== + // Task checks + + // Device Counts - failing these means the task is broken? + if(Devices.size() != DevCnt) + { + // Device Count mismatch. + if (Verbose) fprintf(fp, "Device Count mismatch: %lu!=%lu\n", + static_cast(Devices.size()), DevCnt); + retVal.ret++; + } + + if(Externals.size() != ExtCnt) + { + // External Count mismatch. + if (Verbose) fprintf(fp, "External Count mismatch: %lu!=%lu\n", + static_cast(Externals.size()), ExtCnt); + retVal.ret++; + } + + if(Supervisors.size() != SupCnt) + { + // Supervisor Count mismatch. + if (Verbose) fprintf(fp, "Supervisor Count mismatch: %lu!=%lu\n", + static_cast(Supervisors.size()), SupCnt); + retVal.ret++; + } + + if(SupMap.size() != SupCnt) + { + // Supervisor Count-SupMap size mismatch. + if (Verbose) fprintf(fp, "Supervisor Count<>SupMap size mismatch: %lu!=%lu\n", + static_cast(SupMap.size()), SupCnt); + retVal.ret++; + } + + +#ifdef AB_THREADING + //========================================================================== + // Multi-threaded checks of large structures. Number of threads used scales + // with the number of CPU cores. The checks are read-only so no locks for + // data structure access. Atomic types are used for return values. + unsigned threadCnt = 0, i = 0; + + // Base the scaling off of the available concurrency, with a minimum of 1 + // thread for each check, for a minimum of 4 total threads. Otherwise, + // maximum concurrency is 2* available concurrency. + unsigned int concurrency = std::thread::hardware_concurrency(); + unsigned int halfConcurrency = (concurrency < 2) ? 1 : concurrency / 2; + unsigned int qrtrConcurrency = (concurrency < 4) ? 1 : concurrency / 4; + + // Create a vector of threads of the correct size. + std::vector threads(concurrency + halfConcurrency + + qrtrConcurrency + qrtrConcurrency); + + + //========================================================================== + // Thread(s) for checking DeviceType vectors, etc. + unsigned long dtConcurrency = halfConcurrency; + if (DevTypes.size() < halfConcurrency) // Limit number of threads if we + { // have fewer DeviceTypes than + dtConcurrency = DevTypes.size(); // possible threads. + } + unsigned long devTypeSplit = DevTypes.size() / dtConcurrency; + for(i = 0; i < dtConcurrency; i++) + { + // Handle any remainder in the last thread - integ method checks bounds. + unsigned endMul = (i==(dtConcurrency-1)) ? 2 : 1; + threads[threadCnt+i] = std::thread(&TaskRecord_t::IntegDevTypeMap, this, + Verbose, fp, (devTypeSplit * i), + (devTypeSplit * (i+endMul)), + std::ref(retVal)); + } + threadCnt += i; + + //========================================================================== + // Thread(s) for checking Devices vector + unsigned long dConcurrency = concurrency; + if (Devices.size() < concurrency) // Limit number of threads if we + { // have fewer Devices than + dConcurrency = Devices.size(); // possible threads. + } + unsigned long long devSplit = Devices.size() / dConcurrency; + for(i = 0; i < dConcurrency; i++) + { + // Handle any remainder in the last thread - integ method checks bounds. + unsigned endMul = (i==(dConcurrency-1)) ? 2 : 1; + threads[threadCnt+i] = std::thread(&TaskRecord_t::IntegDevices, this, + Verbose, fp, (devSplit * i), + (devSplit * (i+endMul)), + std::ref(retVal), + std::ref(ExtConCnt)); + } + threadCnt += i; + + //========================================================================== + // Thread(s) for checking Externals vector + unsigned long eConcurrency = qrtrConcurrency; + if (Externals.size() < qrtrConcurrency) // Limit number of threads if we + { // have fewer Externals than + eConcurrency = Externals.size(); // possible threads. + } + unsigned long extSplit = Externals.size() / eConcurrency; + for(i = 0; i < eConcurrency; i++) + { + // Handle any remainder in the last thread - integ method checks bounds. + unsigned endMul = (i==(eConcurrency-1)) ? 2 : 1; + threads[threadCnt+i] = std::thread(&TaskRecord_t::IntegExternals, this, + Verbose, fp, (extSplit * i), + (extSplit * (i+endMul)), + std::ref(retVal)); + } + threadCnt += i; + + //========================================================================== + // Thread(s) for checking Supervisors vector. + unsigned long sConcurrency = qrtrConcurrency; + if (Supervisors.size() < qrtrConcurrency) // Limit number of threads if we + { // have fewer Supervisors than + sConcurrency = Supervisors.size(); // possible threads. + } + unsigned long superSplit = Supervisors.size() / sConcurrency; + for(i = 0; + i < sConcurrency; + i++) + { + // Handle any remainder in the last thread - integ method checks bounds. + unsigned endMul = (i==(sConcurrency-1)) ? 2 : 1; + threads[threadCnt+i] = std::thread(&TaskRecord_t::IntegSupervisors, this, + Verbose, fp, (superSplit * i), + (superSplit * (i+endMul)), + std::ref(retVal), + std::ref(MappedSupervisors)); + } + threadCnt += i; + + +#endif + + // Check integrity of MsgType map + for(std::vector::iterator M + =MsgTypes.begin();M!=MsgTypes.end();M++) // Iterate through message type vector + { + unsigned Idx = static_cast(std::distance(MsgTypes.begin(), M)); // Current Index + + IdxMap_t::const_iterator MSearch = MsgTypeMap.find(M->Name); // Find the Msg Name in the map + if (MSearch == MsgTypeMap.end()) { + // Message Type not mapped + if (Verbose) fprintf(fp, "T: Message Type not mapped: %s\n", + M->Name.c_str()); + retVal.retT++; + } else { + if (MsgTypes[MSearch->second].Name != M->Name){ + // Message Type > Index map is broken. + if (Verbose) fprintf(fp, "T: Message Type > Index map is broken: %s\n", + M->Name.c_str()); + retVal.retT++; + } + + if (Idx != MSearch->second) { + // Index mismatch + if (Verbose) fprintf(fp, "T: Index mismatch: %s, %u!=%u\n", + M->Name.c_str(), Idx, MSearch->second); + retVal.retT++; + } + } + } + + // Check integrity of AttributeType map + for(std::vector::iterator A + =AttrTypes.begin();A!=AttrTypes.end();A++) // Iterate through message type vector + { + unsigned Idx = static_cast(std::distance(AttrTypes.begin(), A)); // Current Index + + IdxMap_t::const_iterator ASearch = AttrTypeMap.find(A->first); // Find the Msg Name in the map + if (ASearch == AttrTypeMap.end()) { + // Attribute Type not mapped + if (Verbose) fprintf(fp, "T: Attribute Type not mapped: %s\n", + A->first.c_str()); + retVal.retT++; + } else { + if (AttrTypes[ASearch->second].first != A->first){ + // Attribute Type > Index map is broken. + if (Verbose) fprintf(fp, "T: Attribute > Index map broken: %s!=%s\n", + A->first.c_str(), AttrTypes[ASearch->second].first.c_str()); + retVal.retT++; + } + + if (Idx != ASearch->second) { + // Index mismatch + if (Verbose) fprintf(fp, "T: Attribute Index mismatch: %u!m%u\n", + Idx, ASearch->second); + retVal.retT++; + } + } + } + + + //========================================================================== + // Map checks + + // Map size integrity checks - Re-mapping should fix. + unsigned long totalDevCnt = DevCnt + ExtCnt; + if(NameMap.size() != totalDevCnt) + { + // NameMap Size mismatch - Map broken + if (Verbose) fprintf(fp, "M: NameMap size mismatch: %lu!=%lu\n", + static_cast(NameMap.size()), + totalDevCnt); + retVal.retM++; + } + + + //========================================================================== + // Link checks + + // Link integrity checks - Re-linking should fix. + if(AddrMap.size() != (totalDevCnt + SupCnt)) + { + // AddressMap Size mismatch - Link broken + if (Verbose) fprintf(fp, "L: AddrMap Size mismatch: %lu!=%lu\n", + static_cast(AddrMap.size()), + (DevCnt + SupCnt)); + retVal.retL++; + } + + +#ifdef AB_THREADING + // Wait for all of the threads to finish + for(i = 0; i < threadCnt; i++) + { + threads[i].join(); + } +#else + // If we are not using threading, run all of the (long) integrity checks single-threaded. + + //========================================================================== + // Check integrity of DeviceType map + IntegDevTypeMap(Verbose, fp, 0, DevTypes.size(), retVal); + + //========================================================================== + // Device checks + IntegDevices(Verbose, fp, 0, Devices.size(), retVal, ExtConCnt); // Check ALL devices + + //========================================================================== + // External checks + IntegExternals(Verbose, fp, 0, Externals.size(), retVal); // Check ALL externals + + //========================================================================== + // Supervisor checks + IntegSupervisors(Verbose, fp, 0, Supervisors.size(), retVal, MappedSupervisors); // Check ALL supervisors +#endif + + + //========================================================================== + // Check ExtCon size. + if(ExtCon.size() != ExtConCnt) + { + // External Connection vector size mismatch - Map broken + if (Verbose) fprintf(fp, "M: External Connection Vector size mismatch: %lu!=%lu\n", + static_cast(ExtCon.size()), + static_cast(ExtConCnt)); + retVal.retM++; + } + + //========================================================================== + // Check Supervisor map size + if (MappedSupervisors != SupMap.size()) { + // Supervisor Map size missmatch + if (Verbose) fprintf(fp, "L: Supervisor Size mismatch: %u!=%lu\n", + static_cast(MappedSupervisors), + static_cast(SupMap.size())); + retVal.retL++; + } + + //========================================================================== + // Set dirty flags if appropriate + if (Verbose) fprintf(fp, "\nResults:\n"); + + if (retVal.ret > 0) + { + if (Verbose) fprintf(fp, "\tGeneral Breakage: %d\n", static_cast(retVal.ret)); + } + + + if (retVal.retT > 0) // Task integrity compromised - need to rbuild the task + { + TaskValid = false; + if (Verbose) fprintf(fp, "\tDirty Task: %d\n", static_cast(retVal.retT)); + retVal.ret += retVal.retT; + } + + if (retVal.retM > 0) // Map integrity compromised - need to rebuild the map + { + MapValid = false; + if (Verbose) fprintf(fp, "\tDirty Map: %d\n", static_cast(retVal.retM)); + retVal.ret += retVal.retM; + } + + if (retVal.retL > 0) // Link integrity compromised - need to rebuild the link + { + LinkValid = false; + if (Verbose) fprintf(fp, "\tDirty Link: %d\n", static_cast(retVal.retL)); + retVal.ret += retVal.retL; + } + + if (Verbose && (retVal.ret == 0)) fprintf(fp, "\tTask Clean\n"); + + return retVal.ret; +} + +void TaskRecord_t::IntegDevTypeMap(bool Verbose, FILE * fp, unsigned long DTStart, + unsigned long DTEnd, IntegVals_t &retVal) +{ + for(std::vector::iterator D = DevTypes.begin() + DTStart; + (D != DevTypes.end()) && (D < (DevTypes.begin() + DTEnd)); + D++) // Iterate through device type vector + { + unsigned Idx = static_cast(std::distance(DevTypes.begin(), D)); // Current Index + + IdxMap_t::const_iterator DTSearch = DevTypeMap.find(D->first.Name); // Find the DevType name in the map + if (DTSearch == DevTypeMap.end()) { + // DevType not mapped + if (Verbose) fprintf(fp, "T: DevType not mapped: %s\n", + D->first.Name.c_str()); + retVal.retT++; + + } else { + if (DevTypes[DTSearch->second].first.Name != D->first.Name){ + // DevType > Index map is broken. + if (Verbose) fprintf(fp, "T: DevTypeMap Broken: %s!=%s\n", + D->first.Name.c_str(), + DevTypes[DTSearch->second].first.Name.c_str()); + retVal.retT++; + } + + if (Idx != DTSearch->second) { + // Index mismatch + if (Verbose) fprintf(fp, "T: DevTypeMap Index mismatch: %s, %u!=%u\n", + D->first.Name.c_str(), Idx, DTSearch->second); + retVal.retT++; + } + } + + //Check the Input Msg Indexes + for(std::vector::const_iterator I + =D->first.InMsgs.begin();I!=D->first.InMsgs.end();I++) + { + const std::vector *InMsgs = &MsgTypes[*I].Inputs; + if (std::find(InMsgs->begin(), InMsgs->end(), Idx) == InMsgs->end()) + { + // MsgType->DevType (Input Message) Vector broken. + if (Verbose) fprintf(fp, "T: MsgType->DevType(InMsg) Vector broken: \ + DevType %u (%s) not found in MsgType InMsg Vector %u\n", + Idx, D->first.Name.c_str(), *I); //DevTypes[Idx].first.Name + retVal.retT++; + } + } + + //Check the Output Msg Indexes + for(std::vector::const_iterator O + =D->first.OuMsgs.begin();O!=D->first.OuMsgs.end();O++) + { + const std::vector *OuMsgs = &MsgTypes[*O].Outputs; + if (std::find(OuMsgs->begin(), OuMsgs->end(), Idx) == OuMsgs->end()) + { + // MsgType->DevType (Output Message) Vector broken. + if (Verbose) fprintf(fp, "T: MsgType->DevType(OuMsg) Vector broken: \ + DevType %u (%s) not found in MsgType OuMsg Vector %u\n", + Idx, D->first.Name.c_str(), *O); + retVal.retT++; + } + } + } +} + + +void TaskRecord_t::IntegDevices(bool Verbose, FILE * fp, unsigned long DStart, + unsigned long DEnd, IntegVals_t &retVal, + ABULONG &ExtConCnt) +{ + for(std::vector::const_iterator D = Devices.begin() + DStart; + (D != Devices.end()) && (D < (Devices.begin() + DEnd)); + D++) // Iterate through section of Device vector + { + // Check record type + if((D->RecordType != Device) && (D->RecordType != DeviceExt)) + { + // Non-Device in the Device vector. Something, somewhere has gone very VERY wrong + if (Verbose) fprintf(fp, "Non-Device in Device Vector: %s (%" SYMA_FMT "), %u\n", + D->Name.c_str(), D->Address, D->RecordType); + retVal.ret++; + } else { + // Search Addr Map + AddrMap_t::const_iterator DASearch = AddrMap.find(D->Address); // Find the dev Addr in the map + if (DASearch == AddrMap.end()) { + // DevAddr not mapped - Link broken + if (Verbose) fprintf(fp, "L: DevAddr not mapped: %s, %" SYMA_FMT "\n", + D->Name.c_str(), D->Address); + retVal.retL++; + } else if (DASearch->second != &(*D)) { + // Address does not map to THIS device - Link broken + if (Verbose) fprintf(fp, "L: AddrMap to wrong device: %s, %" PTR_FMT "!=%" PTR_FMT "\n", + D->Name.c_str(), reinterpret_cast(DASearch->second), + reinterpret_cast(&(*D))); + retVal.retL++; + } + + // Search Name Map + NameMap_t::const_iterator DNSearch = NameMap.find(D->Name); // Find the dev Name in the map + if (DNSearch == NameMap.end()) { + // DevName not mapped + if (Verbose) fprintf(fp, "M: Device Name not mapped: %s\n", + D->Name.c_str()); + retVal.retM++; + } else if (DNSearch->second != &(*D)) { + // Name does not map to THIS device - Map Broken + if (Verbose) fprintf(fp, "M: Namemap to wrong device: %s, %" PTR_FMT "!=%" PTR_FMT "\n", + D->Name.c_str(), reinterpret_cast(DNSearch->second), + reinterpret_cast(&(*D))); + retVal.retM++; + } + + // Check Device type Index + if (D->DeviceType >= DevTypes.size()) { + // DeviceType Index out of range + if (Verbose) fprintf(fp, "DeviceType Index out of range: %s (%" SYMA_FMT "), DType: %d>%d\n", + D->Name.c_str(), D->Address, D->DeviceType, + static_cast(DevTypes.size())); + retVal.ret++; + } else { + // Find the pointer to the device record in the Device Type vector + const RecordVect_t *DTypeV = &DevTypes[D->DeviceType].second; + if (std::find(DTypeV->begin(), DTypeV->end(), &(*D)) == DTypeV->end()) + { + // Device not in Device Type vector - Map Broken + if (Verbose) fprintf(fp, "M: Device %s (%" SYMA_FMT ") not in DevicetypeVector %u (%s)\n", + D->Name.c_str(), D->Address, D->DeviceType, + DevTypes[D->DeviceType].first.Name.c_str()); + retVal.retM++; + } + } + + // Search Supervisor + SupMap_t::const_iterator DSSearch = SupMap.find(D->Supervisor); // Find the dev Addr in the map + if (DSSearch == SupMap.end()) { + // Device's Supervisor not found - Link broken + if (Verbose) fprintf(fp, "L: Dev's Supervisor not found in AddrMap: %s, %" SYMA_FMT "\n", + D->Name.c_str(), D->Supervisor); + retVal.retL++; + } else { + // Search Supervsor Vector + const RecordVect_t *SupV = &DSSearch->second; + if (std::find(SupV->begin(), SupV->end(), &(*D)) == SupV->end()) + { + // Pointer to Device Record not found in Supervisor Vector. + if (Verbose) fprintf(fp, "L: Ptr to Device not in Supervisor \ + vector: %s, Supervisor: %" SYMA_FMT "\n", + D->Name.c_str(), D->Supervisor); + retVal.retL++; + } + } + + // Check if the Attribute Index is out of range + if(D->Attribute >= static_cast(AttrTypes.size())) + { + // Attribute Index out of range. + if (Verbose) fprintf(fp, "Attribute Index out of range: %s (%" SYMA_FMT "), Attr: %d>%d\n", + D->Name.c_str(), D->Address, D->Attribute, + static_cast(AttrTypes.size())); + retVal.ret++; + } else if (D->Attribute > -1) { + // Find the pointer to the device record in the Attribute Type vector + const RecordVect_t *ATypeV = &AttrTypes[static_cast(D->Attribute)].second; + if (std::find(ATypeV->begin(), ATypeV->end(), &(*D)) == ATypeV->end()) + { + // Device not in Attribute Type vector - Map Broken + if (Verbose) fprintf(fp, "L: Dev not in Attribute vector: %s\ + , Attribute: %d (%s)\n", D->Name.c_str(), D->Attribute, + AttrTypes[static_cast(D->Attribute)].first.c_str()); + retVal.retM++; + } + } + + // If ExtCon, search ExtCon Vector, ExtConCnt++ + if(D->RecordType == DeviceExt) + { + if (std::find(ExtCon.begin(), ExtCon.end(), &(*D)) == ExtCon.end()) + { + // Device with External Connection not found in ExtCon - Map Broken + if (Verbose) fprintf(fp, "M: Device with External connection not in\ + ExtCon: %s (%" SYMA_FMT ")\n", D->Name.c_str(), D->Address); + retVal.retM++; + } + ExtConCnt++; + } + } + } +} + +void TaskRecord_t::IntegExternals(bool Verbose, FILE * fp, unsigned long EStart, + unsigned long EEnd, IntegVals_t &retVal) +{ + for(std::vector::const_iterator E = Externals.begin() + EStart; + (E != Externals.end()) && (E < (Externals.begin() + EEnd)); + E++) // Iterate through External vector + { + // Check record type + if(E->RecordType != External) + { + // Non-External in the External vector. Something, somewhere has gone very VERY wrong + if (Verbose) fprintf(fp, "Non-External in External Vector: %s, \ + %" SYMA_FMT ", %d\n", E->Name.c_str(), E->Address, E->RecordType); + retVal.ret++; + } else { + // Search Addr Map + AddrMap_t::const_iterator EASearch = AddrMap.find(E->Address); // Find the dev Addr in the map + if (EASearch == AddrMap.end()) { + // ExtAddr not mapped - Link broken + if (Verbose) fprintf(fp, "L: ExtAddr not mapped: %s, %" SYMA_FMT "\n", + E->Name.c_str(), E->Address); + retVal.retL++; + } else if (EASearch->second != &(*E)) { + // Address does not map to THIS external - Link broken + if (Verbose) fprintf(fp, "L: AddrMap to wrong External: %s, %" PTR_FMT "!=%" PTR_FMT "\n", + E->Name.c_str(), reinterpret_cast(EASearch->second), + reinterpret_cast(&(*E))); + retVal.retL++; + } + + // Search Name Map + NameMap_t::const_iterator ENSearch = NameMap.find(E->Name); // Find the dev Name in the map + if (ENSearch == NameMap.end()) { + // ExtName not mapped + if (Verbose) fprintf(fp, "M: External Name not mapped: %s (%" SYMA_FMT ")\n", + E->Name.c_str(), E->Address); + retVal.retM++; + } else if (ENSearch->second != &(*E)) { + // Name does not map to THIS external - Map Broken + if (Verbose) fprintf(fp, "M: Namemap to wrong external: %s, %" PTR_FMT "!=%" PTR_FMT "\n", + E->Name.c_str(), reinterpret_cast(ENSearch->second), + reinterpret_cast(&(*E))); + retVal.retM++; + } + + // Check Device type Index + if (E->DeviceType >= DevTypes.size()) { + // DeviceType Index out of range + if (Verbose) fprintf(fp, "DeviceType Index out of range: %s (%" SYMA_FMT ")\ + , DType: %u>%d\n", E->Name.c_str(), E->Address, E->DeviceType, + static_cast(DevTypes.size())); + retVal.ret++; + } else { + // Find the pointer to the device record in the Device Type vector + const RecordVect_t *DTypeV = &DevTypes[E->DeviceType].second; + if (std::find(DTypeV->begin(), DTypeV->end(), &(*E)) == DTypeV->end()) + { + // External not in Device Type vector - Map Broken + if (Verbose) fprintf(fp, "M: External %s (%" SYMA_FMT ") not in \ + DeviceType Vector %u (%s)\n", + E->Name.c_str(), E->Address, E->DeviceType, + DevTypes[E->DeviceType].first.Name.c_str()); + retVal.retM++; + } + } + + // Check if the Attribute Index is out of range + if(E->Attribute >= static_cast(AttrTypes.size())) + { + // Attribute Index out of range. + if (Verbose) fprintf(fp, "Attribute Index out of range: %s (%" SYMA_FMT "), \ + Attr: %d>%d\n", E->Name.c_str(), E->Address, E->Attribute, + static_cast(AttrTypes.size())); + retVal.ret++; + } else if (E->Attribute > -1) { + // Find the pointer to the external record in the Attribute Type vector + const RecordVect_t *ATypeV = &AttrTypes[static_cast(E->Attribute)].second; + if (std::find(ATypeV->begin(), ATypeV->end(), &(*E)) == ATypeV->end()) + { + // External not in Attribute Type vector - Map Broken + if (Verbose) fprintf(fp, "L: Ext not in Attribute vector: %s, \ + Attribute: %d (%s)\n", E->Name.c_str(), E->Attribute, + AttrTypes[static_cast(E->Attribute)].first.c_str()); + retVal.retM++; + } + } + } + } +} + +void TaskRecord_t::IntegSupervisors(bool Verbose, FILE * fp, unsigned long SStart, + unsigned long SEnd, IntegVals_t &retVal, + ABUNSIGNED &MappedSupervisors) +{ + for(std::vector::const_iterator S = Supervisors.begin() + SStart; + (S != Supervisors.end()) && (S < (Supervisors.begin() + SEnd)); + S++) // Iterate through Supervisor vector + { + // Check record type + if(S->RecordType != Supervisor) + { + // Non-Supervisor in the Supervisor vector. Something, somewhere has gone very VERY wrong + if (Verbose) fprintf(fp, "Non-Supervisor in Supervisor Vector: %s, \ + %" SYMA_FMT ", %d\n", S->Name.c_str(), S->Address, S->RecordType); + retVal.ret++; + } else { + // Check that Supervisor is listed in Addr Map + AddrMap_t::const_iterator SASearch = AddrMap.find(S->Address); // Find the Addr in the map + if (SASearch == AddrMap.end()) { + // SupAddr not mapped - Link broken + if (Verbose) fprintf(fp, "L: SupAddr not mapped: %s, %" SYMA_FMT "\n", + S->Name.c_str(), S->Address); + retVal.retL++; + } else if (SASearch->second != &(*S)) { + // Address does not map to THIS supervisor - Link broken + if (Verbose) fprintf(fp, "L: AddrMap to wrong Supervisor: %s, %" PTR_FMT "!=%" PTR_FMT "\n", + S->Name.c_str(), reinterpret_cast(SASearch->second), + reinterpret_cast(&(*S))); + retVal.retL++; + } + + // Check that Supervisor is listed in SupMap + SupMap_t::const_iterator SMSearch = SupMap.find(S->Address); + if (SMSearch == SupMap.end()) + { + // SupAddr not mapped - Link broken + if (Verbose) fprintf(fp, "L: SupAddr not in SupMap: %s, %" SYMA_FMT "\n", + S->Name.c_str(), S->Address); + retVal.retL++; + } else { + MappedSupervisors++; + + // Check all devices allocated to supervisor use THIS supervisor + for(RecordVect_t::const_iterator SMV + =SMSearch->second.begin();SMV!=SMSearch->second.end();SMV++) // Iterate through Supervisor's devices + { + if((*SMV)->Supervisor != SMSearch->first) + { + // Supervisor Address in device record does not match THIS supervisor - Link broken + if (Verbose) fprintf(fp, "L: Dev SupAddr mismatch: %s, %"\ + SYMA_FMT "!=%" SYMA_FMT "\n", (*SMV)->Name.c_str(), + (*SMV)->Supervisor, SMSearch->first); + retVal.retL++; + } + } + } + + // Check Device type Index + if (S->DeviceType >= DevTypes.size()) { + // DeviceType Index out of range + if (Verbose) fprintf(fp, "DeviceType Index out of range: Supervisor (%" SYMA_FMT \ + "), DType: %u>%d\n", S->Address, S->DeviceType, + static_cast(DevTypes.size())); + retVal.ret++; + } else { + // Find the pointer to the device record in the Device Type vector + const RecordVect_t *DTypeV = &DevTypes[S->DeviceType].second; + if (std::find(DTypeV->begin(), DTypeV->end(), &(*S)) == DTypeV->end()) + { + // Supervisor not in Device Type vector - Map Broken + if (Verbose) fprintf(fp, "M: Supervisor (%" SYMA_FMT \ + ") not in DeviceType Vector %u (%s)\n", + S->Address, S->DeviceType, + DevTypes[S->DeviceType].first.Name.c_str()); + retVal.retM++; + } + } + } + } +} + +} /* namespace AddressBookNS */ diff --git a/Source/NameServer/AddressBook/AddressBook_Task.hpp b/Source/NameServer/AddressBook/AddressBook_Task.hpp new file mode 100644 index 00000000..62ec4ac8 --- /dev/null +++ b/Source/NameServer/AddressBook/AddressBook_Task.hpp @@ -0,0 +1,139 @@ +#ifndef AddressBook_Task_H +#define AddressBook_Task_H + +#include "AddressBook_Defs.hpp" +#include "AddressBook_Record.hpp" + +#include +#include +#include + +#if (__cplusplus >= 201103) && (\ + (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) ||\ + defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))) + //C++11+ and C11+ or POSIX: + // fprintf is thread safe so let's thread stuff! + #include + #include + #define AB_THREADING + + // We need Atomic types if we are using threading. + #define ABUNSIGNED std::atomic + #define ABULONG std::atomic +#else + #define ABUNSIGNED unsigned + #define ABULONG unsigned long + +#endif + +namespace AddressBookNS +{ + +typedef std::map IdxMap_t; +typedef std::vector RecordVect_t; +typedef std::map SupMap_t; +typedef std::map RecordMap_t; +typedef std::map AddrMap_t; +typedef std::map NameMap_t; + +typedef std::pair DevTypePair; +typedef std::pair AttrTypePair; + +struct IntegVals_t { + ABUNSIGNED ret; + ABUNSIGNED retT; + ABUNSIGNED retL; + ABUNSIGNED retM; +}; + +struct TaskData_t { + TaskData_t(); + TaskData_t(std::string &N, std::string &P, std::string &X, std::string &E, + TaskState_t S, unsigned long DC, unsigned long EC); + + int size() const; // Get the size (in bytes) of the TaskData + + std::string Name; // = ""; + std::string Path; // = ""; + std::string XML; // = ""; + std::string ExecutablePath; // = ""; + TaskState_t State; // = Loaded; + unsigned long DeviceCount; // = 0; // The maximum number of devices in task + unsigned long DeviceCountLd; // = 0; // The number of devices currently loaded + unsigned long ExternalCount; // = 0; // The maximum number of externals in task + unsigned long ExternalCountLd; // = 0; // The number of externals currently loaded + unsigned long SupervisorCount; // = 0; // The number of allocated supervisors + std::vector DeviceTypes; + std::vector MessageTypes; + std::vector AttributeTypes; +}; + + +class TaskRecord_t { +public: + TaskRecord_t(); + TaskRecord_t(std::string &N, std::string &P, std::string &X, std::string &E, + TaskState_t S, unsigned long DC, unsigned long EC); + TaskRecord_t(TaskData_t &Data); + + unsigned Integrity(bool Verbose = false, FILE * = stdout); + + int size() const; // Get the size (in bytes) of the TaskData + + + std::string Name; // = ""; + std::string Path; // = ""; + std::string XML; // = ""; + std::string ExecPath; // = ""; + unsigned long DevCntMax; // = 0; // The expected number of devices + unsigned long ExtCntMax; // = 0; // The expected number of external devices + unsigned long DevCnt; // = 0; // The loaded number of Devices + unsigned long SupCnt; // = 0; // The loaded number of Supervisors + unsigned long ExtCnt; // = 0; // The loaded number of External Devices + + TaskState_t State; // = Loaded; //State of the task + + std::vector Devices; // List of Devices in the task + std::vector Externals; // List of Externals in the task + std::vector Supervisors; // List of Supervisors in the task + + std::vector MsgTypes; // List of task Msg types from XML + //std::vector MsgTypes; // List of task Msg types from XML + std::vector DevTypes; // List of task Dev Types from XML + std::vector AttrTypes; // List of task Attrs from XML + + RecordVect_t ExtCon; // List of Devices with external conns + + // Task String Data Maps + IdxMap_t MsgTypeMap; // Map Msg type string to Idx + IdxMap_t DevTypeMap; // Map Dev type Name to Idx + IdxMap_t AttrTypeMap; // Map Attr type string to Idx + + //Device Maps + SupMap_t SupMap; // Supervisor>DeviceAddress map + AddrMap_t AddrMap; // Addr>record map basis of DNAME, DGRP, SNAME + NameMap_t NameMap; // Name>record map basis of DNAME, DGRP, SNAME + + bool TaskValid; // = true; // Indicate whether the task string info is valid + bool MapValid; // = true; // Indicate whether the task maps are valid + bool LinkValid; // = true; // Indicate whether the Device > Address links are valid + +private: + void IntegDevices(bool Verbose, FILE * fp, unsigned long DStart, + unsigned long DEnd, IntegVals_t &retVal, + ABULONG &ExtConCnt); + + void IntegExternals(bool Verbose, FILE * fp, unsigned long EStart, + unsigned long EEnd, IntegVals_t &retVal); + + void IntegSupervisors(bool Verbose, FILE * fp, unsigned long SStart, + unsigned long SEnd, IntegVals_t &retVal, + ABUNSIGNED &MappedSupervisors); + + void IntegDevTypeMap(bool Verbose, FILE * fp, unsigned long DTStart, + unsigned long DTEnd, IntegVals_t &retVal); +}; + + +} /* namespace AddressBookNS */ +#endif /* AddressBook_Task_H */ From 03790e92d86d9e9792c345d7bdd837f0fd35e8df Mon Sep 17 00:00:00 2001 From: Graeme Bragg Date: Thu, 9 Jan 2020 23:12:42 +0000 Subject: [PATCH 02/15] Fix a divide by 0 error --- .../AddressBook/AddressBook_Task.cpp | 97 +++++++++++-------- 1 file changed, 56 insertions(+), 41 deletions(-) diff --git a/Source/NameServer/AddressBook/AddressBook_Task.cpp b/Source/NameServer/AddressBook/AddressBook_Task.cpp index a5e5e9f4..20e1d32d 100644 --- a/Source/NameServer/AddressBook/AddressBook_Task.cpp +++ b/Source/NameServer/AddressBook/AddressBook_Task.cpp @@ -191,17 +191,21 @@ unsigned TaskRecord_t::Integrity(bool Verbose, FILE * fp) { // have fewer DeviceTypes than dtConcurrency = DevTypes.size(); // possible threads. } - unsigned long devTypeSplit = DevTypes.size() / dtConcurrency; - for(i = 0; i < dtConcurrency; i++) + + if (dtConcurrency > 0) { - // Handle any remainder in the last thread - integ method checks bounds. - unsigned endMul = (i==(dtConcurrency-1)) ? 2 : 1; - threads[threadCnt+i] = std::thread(&TaskRecord_t::IntegDevTypeMap, this, - Verbose, fp, (devTypeSplit * i), - (devTypeSplit * (i+endMul)), - std::ref(retVal)); + unsigned long devTypeSplit = DevTypes.size() / dtConcurrency; + for(i = 0; i < dtConcurrency; i++) + { + // Handle any remainder in the last thread - integ method checks bounds. + unsigned endMul = (i==(dtConcurrency-1)) ? 2 : 1; + threads[threadCnt+i] = std::thread(&TaskRecord_t::IntegDevTypeMap, this, + Verbose, fp, (devTypeSplit * i), + (devTypeSplit * (i+endMul)), + std::ref(retVal)); + } + threadCnt += i; } - threadCnt += i; //========================================================================== // Thread(s) for checking Devices vector @@ -210,18 +214,22 @@ unsigned TaskRecord_t::Integrity(bool Verbose, FILE * fp) { // have fewer Devices than dConcurrency = Devices.size(); // possible threads. } - unsigned long long devSplit = Devices.size() / dConcurrency; - for(i = 0; i < dConcurrency; i++) + + if (dConcurrency > 0) // account for 0 devices, incase we are called before devices loaded { - // Handle any remainder in the last thread - integ method checks bounds. - unsigned endMul = (i==(dConcurrency-1)) ? 2 : 1; - threads[threadCnt+i] = std::thread(&TaskRecord_t::IntegDevices, this, - Verbose, fp, (devSplit * i), - (devSplit * (i+endMul)), - std::ref(retVal), - std::ref(ExtConCnt)); + unsigned long long devSplit = Devices.size() / dConcurrency; + for(i = 0; i < dConcurrency; i++) + { + // Handle any remainder in the last thread - integ method checks bounds. + unsigned endMul = (i==(dConcurrency-1)) ? 2 : 1; + threads[threadCnt+i] = std::thread(&TaskRecord_t::IntegDevices, this, + Verbose, fp, (devSplit * i), + (devSplit * (i+endMul)), + std::ref(retVal), + std::ref(ExtConCnt)); + } + threadCnt += i; } - threadCnt += i; //========================================================================== // Thread(s) for checking Externals vector @@ -230,17 +238,21 @@ unsigned TaskRecord_t::Integrity(bool Verbose, FILE * fp) { // have fewer Externals than eConcurrency = Externals.size(); // possible threads. } - unsigned long extSplit = Externals.size() / eConcurrency; - for(i = 0; i < eConcurrency; i++) + + if (eConcurrency > 0) // Account for having no externals { - // Handle any remainder in the last thread - integ method checks bounds. - unsigned endMul = (i==(eConcurrency-1)) ? 2 : 1; - threads[threadCnt+i] = std::thread(&TaskRecord_t::IntegExternals, this, - Verbose, fp, (extSplit * i), - (extSplit * (i+endMul)), - std::ref(retVal)); + unsigned long extSplit = Externals.size() / eConcurrency; + for(i = 0; i < eConcurrency; i++) + { + // Handle any remainder in the last thread - integ method checks bounds. + unsigned endMul = (i==(eConcurrency-1)) ? 2 : 1; + threads[threadCnt+i] = std::thread(&TaskRecord_t::IntegExternals, this, + Verbose, fp, (extSplit * i), + (extSplit * (i+endMul)), + std::ref(retVal)); + } + threadCnt += i; } - threadCnt += i; //========================================================================== // Thread(s) for checking Supervisors vector. @@ -249,21 +261,24 @@ unsigned TaskRecord_t::Integrity(bool Verbose, FILE * fp) { // have fewer Supervisors than sConcurrency = Supervisors.size(); // possible threads. } - unsigned long superSplit = Supervisors.size() / sConcurrency; - for(i = 0; - i < sConcurrency; - i++) + + if (sConcurrency > 0) // Account for having no supervisors { - // Handle any remainder in the last thread - integ method checks bounds. - unsigned endMul = (i==(sConcurrency-1)) ? 2 : 1; - threads[threadCnt+i] = std::thread(&TaskRecord_t::IntegSupervisors, this, - Verbose, fp, (superSplit * i), - (superSplit * (i+endMul)), - std::ref(retVal), - std::ref(MappedSupervisors)); + unsigned long superSplit = Supervisors.size() / sConcurrency; + for(i = 0; + i < sConcurrency; + i++) + { + // Handle any remainder in the last thread - integ method checks bounds. + unsigned endMul = (i==(sConcurrency-1)) ? 2 : 1; + threads[threadCnt+i] = std::thread(&TaskRecord_t::IntegSupervisors, this, + Verbose, fp, (superSplit * i), + (superSplit * (i+endMul)), + std::ref(retVal), + std::ref(MappedSupervisors)); + } + threadCnt += i; } - threadCnt += i; - #endif From 8848a04ded60c6d67225641e2319ce5ba43063cf Mon Sep 17 00:00:00 2001 From: Graeme Bragg Date: Fri, 10 Jan 2020 00:44:54 +0000 Subject: [PATCH 03/15] Reverting a change that can have performacne implications --- Source/NameServer/AddressBook/AddressBook.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Source/NameServer/AddressBook/AddressBook.cpp b/Source/NameServer/AddressBook/AddressBook.cpp index 7f50d5f3..c0a62dcd 100644 --- a/Source/NameServer/AddressBook/AddressBook.cpp +++ b/Source/NameServer/AddressBook/AddressBook.cpp @@ -582,9 +582,16 @@ unsigned AddressBook::AddDevice(std::string &TaskName, Record_t &DevRec, bool Va } // added 18 July 2019 ADR - if Map and Link were previously invalidated // rebuild everything - unsigned err; - if (!TRec->MapValid && ((err = BuildMaps(TRec->Name)) != SUCCESS)) return err; - if (!TRec->LinkValid && ((err = BuildLink(TRec->Name)) != SUCCESS)) return err; + // + // Reverted by GMB as this potentially means heafty rebuilding + // when futzing with the data structure - the correct course of + // action if to check the task validity after adding devices and + // rebuilding the link and map then if required. + // + //unsigned err; + //if (!TRec->MapValid && ((err = BuildMaps(TRec->Name)) != SUCCESS)) return err; + //if (!TRec->LinkValid && ((err = BuildLink(TRec->Name)) != SUCCESS)) return err; + return SUCCESS; } From bf007f3e584b3de899dc15449af089bd24b6d8f8 Mon Sep 17 00:00:00 2001 From: Graeme Bragg Date: Fri, 10 Jan 2020 02:10:30 +0000 Subject: [PATCH 04/15] Add a method to get mapped SUpervisor count and add the option of recovering bad link/map from integrity check --- Source/NameServer/AddressBook/AddressBook.cpp | 14 ++++++++++++++ Source/NameServer/AddressBook/AddressBook.hpp | 1 + .../AddressBook/AddressBook_Task.cpp | 18 ++++++++++++++++++ .../AddressBook/AddressBook_Task.hpp | 3 +++ 4 files changed, 36 insertions(+) diff --git a/Source/NameServer/AddressBook/AddressBook.cpp b/Source/NameServer/AddressBook/AddressBook.cpp index c0a62dcd..9904352e 100644 --- a/Source/NameServer/AddressBook/AddressBook.cpp +++ b/Source/NameServer/AddressBook/AddressBook.cpp @@ -691,6 +691,20 @@ int AddressBook::GetSupervisorCount(std::string &TaskName) return static_cast(TRec->SupCnt); } +/*============================================================================== + * GetSupervisorCount: Get the number of supervisors allocated to the task + *============================================================================*/ +int AddressBook::GetMappedSupervisorCount(std::string &TaskName) +{ + TaskRecord_t *TRec = FindTask(TaskName); + if(TRec == PNULL) + { + ERETURN("Task Does Not Exist", ERR_BAD_COUNT); + } + + return TRec->SupMap.size(); +} + //============================================================================== //Device Queries diff --git a/Source/NameServer/AddressBook/AddressBook.hpp b/Source/NameServer/AddressBook/AddressBook.hpp index e98036d8..9340e3ec 100644 --- a/Source/NameServer/AddressBook/AddressBook.hpp +++ b/Source/NameServer/AddressBook/AddressBook.hpp @@ -111,6 +111,7 @@ class AddressBook long GetExternalCount(std::string &TaskName); long GetLoadedExternalCount(std::string &TaskName); int GetSupervisorCount(std::string &TaskName); + int GetMappedSupervisorCount(std::string &TaskName); // Integrity unsigned IntegCheck(void); // Integrity check of ALL tasks diff --git a/Source/NameServer/AddressBook/AddressBook_Task.cpp b/Source/NameServer/AddressBook/AddressBook_Task.cpp index 20e1d32d..92cf001d 100644 --- a/Source/NameServer/AddressBook/AddressBook_Task.cpp +++ b/Source/NameServer/AddressBook/AddressBook_Task.cpp @@ -434,6 +434,12 @@ unsigned TaskRecord_t::Integrity(bool Verbose, FILE * fp) if (Verbose) fprintf(fp, "\tDirty Task: %d\n", static_cast(retVal.retT)); retVal.ret += retVal.retT; } +#ifdef RECOVERABLEINTEGRITY + else + { + TaskValid = true; + } +#endif if (retVal.retM > 0) // Map integrity compromised - need to rebuild the map { @@ -441,6 +447,12 @@ unsigned TaskRecord_t::Integrity(bool Verbose, FILE * fp) if (Verbose) fprintf(fp, "\tDirty Map: %d\n", static_cast(retVal.retM)); retVal.ret += retVal.retM; } +#ifdef RECOVERABLEINTEGRITY + else + { + MapValid = true; + } +#endif if (retVal.retL > 0) // Link integrity compromised - need to rebuild the link { @@ -448,6 +460,12 @@ unsigned TaskRecord_t::Integrity(bool Verbose, FILE * fp) if (Verbose) fprintf(fp, "\tDirty Link: %d\n", static_cast(retVal.retL)); retVal.ret += retVal.retL; } +#ifdef RECOVERABLEINTEGRITY + else + { + LinkValid = true; + } +#endif if (Verbose && (retVal.ret == 0)) fprintf(fp, "\tTask Clean\n"); diff --git a/Source/NameServer/AddressBook/AddressBook_Task.hpp b/Source/NameServer/AddressBook/AddressBook_Task.hpp index 62ec4ac8..58cb1eef 100644 --- a/Source/NameServer/AddressBook/AddressBook_Task.hpp +++ b/Source/NameServer/AddressBook/AddressBook_Task.hpp @@ -26,6 +26,9 @@ #endif + +#define RECOVERABLEINTEGRITY + namespace AddressBookNS { From a125988654a9d1ef73e15fb6c5e364424b0c23dd Mon Sep 17 00:00:00 2001 From: Graeme Bragg Date: Fri, 10 Jan 2020 02:11:07 +0000 Subject: [PATCH 05/15] Add some initial tests for the AddressBook --- Build/gcc/Makefile | 1 + Build/gcc/Makefile.executable_prerequisites | 7 + Build/gcc/Makefile.test_prerequisites | 1 + Tests/TestAddressBook.cpp | 745 ++++++++++++++++++++ 4 files changed, 754 insertions(+) create mode 100644 Tests/TestAddressBook.cpp diff --git a/Build/gcc/Makefile b/Build/gcc/Makefile index 622ad45d..ea77ab10 100644 --- a/Build/gcc/Makefile +++ b/Build/gcc/Makefile @@ -77,6 +77,7 @@ INCLUDE_FLAGS = -I$(GENERICS_DIR) \ -I$(SOURCE_DIR)/Parser \ -I$(SOURCE_DIR)/Root \ -I$(SOURCE_DIR)/NameServer \ + -I$(SOURCE_DIR)/NameServer/AddressBook \ -I$(SOURCE_DIR)/Softswitch/inc \ -I$(MPICH_INC_DIR) \ -I$(QT_INC_DIR) \ diff --git a/Build/gcc/Makefile.executable_prerequisites b/Build/gcc/Makefile.executable_prerequisites index 8fa80e05..3d2e2264 100644 --- a/Build/gcc/Makefile.executable_prerequisites +++ b/Build/gcc/Makefile.executable_prerequisites @@ -79,6 +79,13 @@ HARDWARE_FILE_READER_SOURCES = $(SOURCE_DIR)/OrchBase/HardwareFileReader/Hardwar $(GENERICS_DIR)/uif.cpp \ $(HARDWARE_DEPLOYER_SOURCES) +# Sources used by the Address Book object. +ADDRESS_BOOK_SOURCES = $(SOURCE_DIR)/NameServer/AddressBook/AddressBook_Defs.cpp \ + $(SOURCE_DIR)/NameServer/AddressBook/AddressBook_Record.cpp \ + $(SOURCE_DIR)/NameServer/AddressBook/AddressBook_Task.cpp \ + $(SOURCE_DIR)/NameServer/AddressBook/AddressBook.cpp + + # The orchestrate execution script uses a template. ORCHESTRATE_TEMPLATE = ./Resources/orchestrate_template.sh diff --git a/Build/gcc/Makefile.test_prerequisites b/Build/gcc/Makefile.test_prerequisites index 3552996d..0848c54e 100644 --- a/Build/gcc/Makefile.test_prerequisites +++ b/Build/gcc/Makefile.test_prerequisites @@ -29,6 +29,7 @@ TestHardwareIterator_SOURCES = $(HARDWARE_MODEL_SOURCES) TestHardwareModel_SOURCES = $(HARDWARE_MODEL_SOURCES) TestSimpleDeployment_SOURCES = $(HARDWARE_DEPLOYER_SOURCES) TestSoftwareAddress_SOURCES = $(SOFTWARE_ADDRESS_SOURCES) +TestAddressBook_SOURCES = $(ADDRESS_BOOK_SOURCES) # Define test rules. TEST_RULE_TEMPLATE defines the substitutions made in the # foreach loop below. diff --git a/Tests/TestAddressBook.cpp b/Tests/TestAddressBook.cpp new file mode 100644 index 00000000..74486e14 --- /dev/null +++ b/Tests/TestAddressBook.cpp @@ -0,0 +1,745 @@ +/* Tests the AddressBook for functionality and integrity. */ + +#define CATCH_CONFIG_MAIN + +#include "catch.hpp" + +#include "OSFixes.hpp" +#include "AddressBook.hpp" +#include "AddressBook_Defs.hpp" +#include "AddressBook_Task.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +TEST_CASE("AddressBook Small Tests", "[Simple]") +{ + // Create the AddressBook instance + AddressBookNS::AddressBook AddrBook + = AddressBookNS::AddressBook(std::string("AddressBookMain")); + AddressBookNS::TaskData_t taskData; + + //Create a Supervisor devicetype record and add some messagetypes + AddressBookNS::DevTypeRecord_t SuperDTR("Super"); + SuperDTR.InMsgs.push_back(1); + SuperDTR.OuMsgs.push_back(2); + + //Create a Cell devicetype record and add some messagetytpes + AddressBookNS::DevTypeRecord_t CellDTR("Cell"); + CellDTR.InMsgs.push_back(0); + CellDTR.InMsgs.push_back(2); + CellDTR.OuMsgs.push_back(0); + CellDTR.OuMsgs.push_back(1); + + //Create a Fixed node devicetype record and add some messagetytpes + AddressBookNS::DevTypeRecord_t FixedDTR("Fixed"); + FixedDTR.InMsgs.push_back(2); + FixedDTR.OuMsgs.push_back(0); + FixedDTR.OuMsgs.push_back(1); + + + + //========================================================================== + // Add a task (and check that it added correctly) + //========================================================================== + std::string t1Name = "Task1"; + AddressBookNS::TaskData_t T1Data; + + T1Data.DeviceCount = 5; + T1Data.ExternalCount = 2; + T1Data.Path = "/local/extra/Orchestrator/application_staging/xml"; + T1Data.XML = "task1.xml"; + T1Data.ExecutablePath = "~/"; + T1Data.MessageTypes.push_back("Update"); + T1Data.MessageTypes.push_back("Fin"); + T1Data.MessageTypes.push_back("Done"); + + T1Data.DeviceTypes.push_back(SuperDTR); + T1Data.DeviceTypes.push_back(CellDTR); + T1Data.DeviceTypes.push_back(FixedDTR); + T1Data.AttributeTypes.push_back("Test"); + + // Add the task to the AddressBook + int t1Ret = AddrBook.AddTask(t1Name, T1Data); + REQUIRE(t1Ret == AddressBookNS::AddressBook::SUCCESS); + + SECTION("Check that a task added correctly", "[Simple]") + { + REQUIRE(AddrBook.GetTaskCount() == 1); // We should have one task, + REQUIRE(AddrBook.IntegCheck() == 0); // that passes integrity. + + // Get the task for running tests on + t1Ret = AddrBook.GetTask(t1Name, taskData); + REQUIRE(t1Ret == AddressBookNS::AddressBook::SUCCESS); + + REQUIRE(taskData.Name == t1Name); // Check the task name. + REQUIRE(taskData.Path == T1Data.Path); // Check the path string. + REQUIRE(taskData.XML == T1Data.XML); // Check the XML string. + REQUIRE(taskData.ExecutablePath == T1Data.ExecutablePath); // Check the executable path string. + + REQUIRE(taskData.State == AddressBookNS::Loaded); // Check the task state. + + REQUIRE(taskData.DeviceTypes.size() == T1Data.DeviceTypes.size()); + REQUIRE(taskData.DeviceTypes.size() == 3); // with 5 device types, + REQUIRE(taskData.MessageTypes.size() == 3); // with 3 message types, + REQUIRE(taskData.AttributeTypes.size() == 1); // and 1 attribute type. + + REQUIRE(taskData.DeviceCount == T1Data.DeviceCount); // Expecting 10000 devices + REQUIRE(taskData.DeviceCountLd == 0); // With none loaded. + + REQUIRE(taskData.ExternalCount == T1Data.ExternalCount); // Expecting 1 external device + REQUIRE(taskData.ExternalCountLd == 0); // With none loaded. + + REQUIRE(taskData.SupervisorCount == 0); // Should have no supervisors. + } + //========================================================================== + + + + //========================================================================== + // Add another task + //========================================================================== + std::string t2Name = "Task2"; + AddressBookNS::TaskData_t T2Data; + + T2Data.DeviceCount = 5; + T2Data.ExternalCount = 2; + T2Data.Path = "/local/extra/Orchestrator/application_staging/xml"; + T2Data.XML = "task2.xml"; + T2Data.ExecutablePath = "~/"; + T2Data.MessageTypes.push_back("Update"); + T2Data.MessageTypes.push_back("Fin"); + T2Data.MessageTypes.push_back("Done"); + + T2Data.DeviceTypes.push_back(SuperDTR); + T2Data.DeviceTypes.push_back(CellDTR); + T2Data.DeviceTypes.push_back(FixedDTR); + + // Add the task to the AddressBook + int t2Ret = AddrBook.AddTask(t2Name, T2Data); + REQUIRE(t2Ret == AddressBookNS::AddressBook::SUCCESS); + + + SECTION("Check that a second task added correctly", "[Simple]") + { + REQUIRE(AddrBook.GetTaskCount() == 2); // We should have two tasks, + REQUIRE(AddrBook.IntegCheck() == 0); // that pass integrity. + + // Get the task for running tests on + t2Ret = AddrBook.GetTask(t2Name, taskData); + REQUIRE(t2Ret == AddressBookNS::AddressBook::SUCCESS); + + REQUIRE(taskData.Name == t2Name); // Check the task name. + REQUIRE(taskData.Path == T2Data.Path); // Check the path string. + REQUIRE(taskData.XML == T2Data.XML); // Check the XML string. + REQUIRE(taskData.ExecutablePath == T2Data.ExecutablePath); // Check the executable path string. + + REQUIRE(taskData.State == AddressBookNS::Loaded); // Check the task state. + + REQUIRE(taskData.DeviceTypes.size() == T2Data.DeviceTypes.size()); + REQUIRE(taskData.DeviceTypes.size() == 3); // with 5 device types, + REQUIRE(taskData.MessageTypes.size() == 3); // with 3 message types, + REQUIRE(taskData.AttributeTypes.size() == 0); // and no attribute types. + + REQUIRE(taskData.DeviceCount == T2Data.DeviceCount); // Expecting 10000 devices + REQUIRE(taskData.DeviceCountLd == 0); // With none loaded. + + REQUIRE(taskData.ExternalCount == T2Data.ExternalCount); // Expecting 1 external device + REQUIRE(taskData.ExternalCountLd == 0); // With none loaded. + + REQUIRE(taskData.SupervisorCount == 0); // Should have no supervisors. + } + //========================================================================== + + + + //========================================================================== + // Check that we can't add a duplicate task + //========================================================================== + SECTION("Check that a duplicate task is correctly rejected", "[Simple]") + { + int t3Ret = AddrBook.AddTask(t2Name, T2Data); + REQUIRE(t3Ret == AddressBookNS::AddressBook::ERR_TASKNAME_USED); + REQUIRE(AddrBook.GetTaskCount() == 2); // We should have two tasks, + REQUIRE(AddrBook.IntegCheck() == 0); // that pass integrity. + } + //========================================================================== + + + + //========================================================================== + // Delete a task + //========================================================================== + SECTION("Check that tasks can be deleted", "[Simple]") + { + int delRet = AddrBook.DelTask(t2Name); + REQUIRE(delRet == AddressBookNS::AddressBook::SUCCESS); + REQUIRE(AddrBook.GetTaskCount() == 1); // We should have one task, + REQUIRE(AddrBook.IntegCheck() == 0); // that passes integrity. + } + //========================================================================== + + + + SECTION("Check device handling", "[Simple]") + { + // Get the task + AddrBook.GetTask(t1Name, taskData); + + // Add a supervisor + AddressBookNS::Record_t SData1; + SData1.Name = ""; + SData1.Address = 0xFFFF0001; + SData1.Rank = 5; + SData1.DeviceType = 0; + SData1.RecordType = static_cast(AddressBookNS::Supervisor); + try { + unsigned SAdd = AddrBook.AddDevice(t1Name, SData1); + if (SAdd > 0) std::cerr << std::endl << "ERROR adding SData1: " << SAdd << std::endl; + REQUIRE(SAdd == 0); + } catch (const char* msg) { + std::cerr << std::endl << "ERROR adding SData1: " << msg << std::endl; + std::cin.get(); + } + REQUIRE(AddrBook.GetSupervisorCount(t1Name) == 1); + + + // Add another Supervisor + AddressBookNS::Record_t SData2; + SData2.Name = ""; + SData2.Address = 0xFFFF0002; + SData2.Rank = 5; + SData2.DeviceType = 0; + SData2.RecordType = static_cast(AddressBookNS::Supervisor); + try { + unsigned SAdd = AddrBook.AddDevice(t1Name, SData2); + if (SAdd > 0) std::cerr << std::endl << "ERROR adding SData2: " << SAdd << std::endl; + REQUIRE(SAdd == 0); + } catch (const char* msg) { + std::cerr << std::endl << "ERROR adding SData2: " << msg << std::endl; + std::cin.get(); + } + REQUIRE(AddrBook.GetSupervisorCount(t1Name) == 2); + + + // Add an External + AddressBookNS::Record_t EData1; + EData1.Name = "E_0,0"; + EData1.Address = 0xFFFFF001; + EData1.DeviceType = 2; + EData1.RecordType = static_cast(AddressBookNS::External); + try { + unsigned EAdd = AddrBook.AddDevice(t1Name, EData1); + if (EAdd > 0) std::cerr << std::endl << "ERROR adding EData2: " << EAdd << std::endl; + REQUIRE(EAdd == 0); + } catch (const char* msg) { + std::cerr << std::endl << "ERROR adding EData1: " << msg << std::endl; + std::cin.get(); + } + REQUIRE(AddrBook.GetLoadedExternalCount(t1Name) == 1); + + + // Setup common device data + AddressBookNS::Record_t DData1; + DData1.Supervisor = 0xFFFF0001; + DData1.DeviceType = 1; + DData1.RecordType = static_cast(AddressBookNS::Device); + AddressBookNS::SymAddr_t BaseAddr = 0x00000000; + + + // Add a Device + DData1.Name = "C_0,0"; + DData1.Address = BaseAddr++; + try { + unsigned DAdd = AddrBook.AddDevice(t1Name, DData1); + if (DAdd > 0) std::cerr << std::endl << "ERROR adding Device" + << DData1.Name << " ("<< DData1.Address << "): " + << DAdd << std::endl; + REQUIRE(DAdd == 0); + } catch (const char* msg) { + std::cerr << std::endl << "ERROR adding Device " + << DData1.Name << " (" << DData1.Address << "): " + << msg << std::endl; + std::cin.get(); + } + REQUIRE(AddrBook.GetLoadedDeviceCount(t1Name) == 1); + + + // Add another Device + DData1.Name = "C_0,1"; + DData1.Address = BaseAddr++; + try { + unsigned DAdd = AddrBook.AddDevice(t1Name, DData1); + if (DAdd > 0) std::cerr << std::endl << "ERROR adding Device" + << DData1.Name << " ("<< DData1.Address << "): " + << DAdd << std::endl; + REQUIRE(DAdd == 0); + } catch (const char* msg) { + std::cerr << std::endl << "ERROR adding Device " + << DData1.Name << " (" << DData1.Address << "): " + << msg << std::endl; + std::cin.get(); + } + REQUIRE(AddrBook.GetLoadedDeviceCount(t1Name) == 2); + + + // Add another Device + DData1.Name = "C_0,2"; + DData1.Address = BaseAddr++; + try { + unsigned DAdd = AddrBook.AddDevice(t1Name, DData1); + if (DAdd > 0) std::cerr << std::endl << "ERROR adding Device" + << DData1.Name << " ("<< DData1.Address << "): " + << DAdd << std::endl; + REQUIRE(DAdd == 0); + } catch (const char* msg) { + std::cerr << std::endl << "ERROR adding Device " + << DData1.Name << " (" << DData1.Address << "): " + << msg << std::endl; + std::cin.get(); + } + REQUIRE(AddrBook.GetLoadedDeviceCount(t1Name) == 3); + + + // Add another Device + DData1.Name = "C_0,3"; + DData1.Address = BaseAddr++; + try { + unsigned DAdd = AddrBook.AddDevice(t1Name, DData1); + if (DAdd > 0) std::cerr << std::endl << "ERROR adding Device" + << DData1.Name << " ("<< DData1.Address << "): " + << DAdd << std::endl; + REQUIRE(DAdd == 0); + } catch (const char* msg) { + std::cerr << std::endl << "ERROR adding Device " + << DData1.Name << " (" << DData1.Address << "): " + << msg << std::endl; + std::cin.get(); + } + REQUIRE(AddrBook.GetLoadedDeviceCount(t1Name) == 4); + + + // Check duplicate device handling + int DDupeRet = AddrBook.AddDevice(t1Name, DData1); + REQUIRE(AddrBook.GetLoadedDeviceCount(t1Name) == 4); // We should have 4 devices + REQUIRE(AddrBook.IntegTask(t1Name, false) == 0); // and pass integrity. + + + // Check that invalid Device types are picked up on + DData1.DeviceType = 5; + DData1.Name = "C_0,4"; + DData1.Address = BaseAddr++; + try { + unsigned DAdd = AddrBook.AddDevice(t1Name, DData1); + REQUIRE(DAdd == 2); + } catch (const char* msg) { + std::cerr << std::endl << "ERROR adding Device " + << DData1.Name << " (" << DData1.Address << "): " + << msg << std::endl; + std::cin.get(); + } + REQUIRE(AddrBook.GetLoadedDeviceCount(t1Name) == 4); + + + // Check that the task is valid + REQUIRE(AddrBook.TaskValid(t1Name) == true); + REQUIRE(AddrBook.TaskMapValid(t1Name) == true); + REQUIRE(AddrBook.TaskLinkValid(t1Name) == true); + + // Check that the rest of the data structure is valid + REQUIRE(AddrBook.GetTaskCount() == 2); // We should have two tasks, + REQUIRE(AddrBook.IntegCheck() == 0); // that passes integrity. + + + + // Add a device that forces another Supervisor + REQUIRE(AddrBook.GetMappedSupervisorCount(t1Name) == 2); + DData1.Supervisor = 0xFFFF0005; + DData1.Name = "C_0,4"; + DData1.DeviceType = 1; + try { + unsigned DAdd = AddrBook.AddDevice(t1Name, DData1); + if (DAdd > 0) std::cerr << std::endl << "ERROR adding Device" + << DData1.Name << " ("<< DData1.Address << "): " + << DAdd << std::endl; + REQUIRE(DAdd == 0); + } catch (const char* msg) { + std::cerr << std::endl << "ERROR adding Device " + << DData1.Name << " (" << DData1.Address << "): " + << msg << std::endl; + std::cin.get(); + } + REQUIRE(AddrBook.GetLoadedDeviceCount(t1Name) == 5); + REQUIRE(AddrBook.GetSupervisorCount(t1Name) == 2); // Only two added Supervisors + REQUIRE(AddrBook.GetMappedSupervisorCount(t1Name) == 3); // But 3 in the map. + REQUIRE(AddrBook.IntegCheck() != 0); // this fails integrity. + REQUIRE(AddrBook.TaskLinkValid(t1Name) == false); // and the link is invalid + + // Add the missing Supervisor + AddressBookNS::Record_t SData3; + SData3.Name = ""; + SData3.Address = 0xFFFF0005; + SData3.Rank = 5; + SData3.DeviceType = 0; + SData3.RecordType = static_cast(AddressBookNS::Supervisor); + try { + unsigned SAdd = AddrBook.AddDevice(t1Name, SData3); + if (SAdd > 0) std::cerr << std::endl << "ERROR adding SData3: " << SAdd << std::endl; + REQUIRE(SAdd == 0); + } catch (const char* msg) { + std::cerr << std::endl << "ERROR adding SData3: " << msg << std::endl; + std::cin.get(); + } + REQUIRE(AddrBook.GetLoadedDeviceCount(t1Name) == 5); + REQUIRE(AddrBook.GetSupervisorCount(t1Name) == 3); + REQUIRE(AddrBook.GetMappedSupervisorCount(t1Name) == 3); + REQUIRE(AddrBook.IntegCheck() == 0); // Should now pass integrity. +#ifdef RECOVERABLEINTEGRITY + // If RECOVERABLEINTEGRITY is defined, the link should be valid. + REQUIRE(AddrBook.TaskLinkValid(t1Name) == true); +#else + // Otherwise it is invalid and we need to relink. + REQUIRE(AddrBook.TaskLinkValid(t1Name) == false); + REQUIRE(AddrBook.BuildLink(t1Name) == AddressBookNS::AddressBook::SUCCESS); + REQUIRE(AddrBook.TaskLinkValid(t1Name) == true); // Link should now be valid +#endif + // Check that the rest of the task is valid + REQUIRE(AddrBook.TaskValid(t1Name) == true); + REQUIRE(AddrBook.TaskMapValid(t1Name) == true); + + + } + + + //TODO: Add more checks to: + // Check that adding too many devices is handled + // Check that adding too many externals is handled + // Check that adding too many Supervisors is handled + + // Update a device + + // Find by Supervisor + // Find by Attribute + // Find by Messages + // Clear Task + // Task States + + // Intentionally mess with message links + + // Rebuild Map + // Rebuild Task + // Integrity check after futzing + +} + + +TEST_CASE("AddressBook Large Plate Test", "[Simple]") +{ + // Create the AddressBook instance + AddressBookNS::AddressBook AddrBook + = AddressBookNS::AddressBook(std::string("AddressBookMain")); + + std::string tName = "plate_1000x1000"; + AddressBookNS::TaskData_t taskData; + + + //========================================================================== + // Create a "fake" 1000x1000 heated plate. + //========================================================================== + AddressBookNS::TaskData_t TData; + + TData.DeviceCount = 65536; + TData.ExternalCount = 1; + TData.Path = "/local/extra/Orchestrator/application_staging/xml"; + TData.XML = "plate_1000x1000.xml"; + TData.ExecutablePath = "~/"; + TData.MessageTypes.push_back("Update"); + TData.MessageTypes.push_back("Fin"); + TData.MessageTypes.push_back("Done"); + + //Create a Supervisor devicetype record and add some messagetypes + AddressBookNS::DevTypeRecord_t SuperDTR("Super"); + SuperDTR.InMsgs.push_back(1); + SuperDTR.OuMsgs.push_back(2); + + //Create a Cell devicetype record and add some messagetytpes + AddressBookNS::DevTypeRecord_t CellDTR("Cell"); + CellDTR.InMsgs.push_back(0); + CellDTR.InMsgs.push_back(2); + CellDTR.OuMsgs.push_back(0); + CellDTR.OuMsgs.push_back(1); + + //Create a Fixed node devicetype record and add some messagetytpes + AddressBookNS::DevTypeRecord_t FixedDTR("Fixed"); + FixedDTR.InMsgs.push_back(2); + FixedDTR.OuMsgs.push_back(0); + FixedDTR.OuMsgs.push_back(1); + + //Create a Router devicetype record and add some messagetytpes + AddressBookNS::DevTypeRecord_t RouterDTR("Router"); + RouterDTR.InMsgs.push_back(1); + RouterDTR.OuMsgs.push_back(1); + RouterDTR.OuMsgs.push_back(2); + + //Create a Extern devicetype record and add some messagetytpes + AddressBookNS::DevTypeRecord_t ExternDTR("Extern"); + ExternDTR.InMsgs.push_back(2); + ExternDTR.OuMsgs.push_back(0); + + // Add all of the device types to the Task Data + TData.DeviceTypes.push_back(SuperDTR); + TData.DeviceTypes.push_back(CellDTR); + TData.DeviceTypes.push_back(FixedDTR); + TData.DeviceTypes.push_back(RouterDTR); + TData.DeviceTypes.push_back(ExternDTR); + + // Add an attribute + TData.AttributeTypes.push_back("Test"); + + // Add the task to the AddressBook + AddrBook.AddTask(tName, TData); + //========================================================================== + + + // Get the task for running tests on + AddrBook.GetTask(tName, taskData); + + + + + + //========================================================================== + //Check that the task was added and read correctly + //========================================================================== + SECTION("Check that we have the right number of devices in the task data", "[Simple]") + { + REQUIRE(AddrBook.GetTaskCount() == 1); // We should have one task, + + REQUIRE(taskData.Name == tName); // Check the task name. + REQUIRE(taskData.Path == TData.Path); // Check the path string. + REQUIRE(taskData.XML == TData.XML); // Check the XML string. + REQUIRE(taskData.ExecutablePath == TData.ExecutablePath); // Check the executable path string. + + REQUIRE(taskData.State == AddressBookNS::Loaded); // Check the task state. + + REQUIRE(taskData.DeviceTypes.size() == TData.DeviceTypes.size()); + REQUIRE(taskData.DeviceTypes.size() == 5); // with 5 device types, + REQUIRE(taskData.MessageTypes.size() == 3); // with 3 message types, + REQUIRE(taskData.AttributeTypes.size() == 1); // and 1 attribute type. + + REQUIRE(taskData.DeviceCount == TData.DeviceCount); // Expecting 10000 devices + REQUIRE(taskData.DeviceCountLd == 0); // With none loaded. + + REQUIRE(taskData.ExternalCount == 1); // Expecting 1 external device + REQUIRE(taskData.ExternalCountLd == 0); // With none loaded. + + REQUIRE(taskData.SupervisorCount == 0); // Should have no supervisors. + } + //========================================================================== + + + + //========================================================================== + // Add a supervisor + //========================================================================== + AddressBookNS::Record_t SData1; + SData1.Name = ""; + SData1.Address = 0xFFFF0001; + SData1.Rank = 5; + SData1.DeviceType = 0; // SuperDTR + SData1.RecordType = static_cast(AddressBookNS::Supervisor); + + REQUIRE(taskData.DeviceTypes.size() == 5); // with 5 device types, + + try { + unsigned SAdd = AddrBook.AddDevice(tName, SData1); + if (SAdd > 0) std::cerr << std::endl << "ERROR adding SData1: " << SAdd << std::endl; + REQUIRE(SAdd == 0); + } catch (const char* msg) { + std::cerr << std::endl << "ERROR adding SData1: " << msg << std::endl; + std::cin.get(); + } + //========================================================================== + + + //========================================================================== + // Add two fixed nodes + //========================================================================== + AddressBookNS::Record_t FData1; + FData1.Name = "C_0,0"; + FData1.Address = 0xFFE00000; + FData1.Supervisor = 0xFFFF0001; + FData1.DeviceType = 2; + FData1.RecordType = static_cast(AddressBookNS::DeviceExt); + + try { + unsigned FAdd = AddrBook.AddDevice(tName, FData1); + if (FAdd > 0) std::cerr << std::endl << "ERROR adding FData1: " << FAdd << std::endl; + REQUIRE(FAdd == 0); + } catch (const char* msg) { + std::cerr << std::endl << "ERROR adding FData1: " << msg << std::endl; + std::cin.get(); + } + + + AddressBookNS::Record_t FData2; + FData2.Name = "C_255,255"; + FData2.Address = 0xFFE00001; + FData2.Supervisor = 0xFFFF0001; + FData2.DeviceType = 2; + FData2.RecordType = static_cast(AddressBookNS::DeviceExt); + + try { + unsigned FAdd = AddrBook.AddDevice(tName, FData2); + if (FAdd > 0) std::cerr << std::endl << "ERROR adding FData2: " << FAdd << std::endl; + REQUIRE(FAdd == 0); + } catch (const char* msg) { + std::cerr << std::endl << "ERROR adding FData2: " << msg << std::endl; + std::cin.get(); + } + //========================================================================== + + + //========================================================================== + // Add an External + //========================================================================== + AddressBookNS::Record_t EData1; + EData1.Name = "E_0,0"; + EData1.Address = 0xFFFFF001; + EData1.DeviceType = 4; + EData1.RecordType = static_cast(AddressBookNS::External); + + try { + unsigned EAdd = AddrBook.AddDevice(tName, EData1); + if (EAdd > 0) std::cerr << std::endl << "ERROR adding EData2: " << EAdd << std::endl; + REQUIRE(EAdd == 0); + } catch (const char* msg) { + std::cerr << std::endl << "ERROR adding EData1: " << msg << std::endl; + std::cin.get(); + } + //========================================================================== + + + //========================================================================== + // Add 999998 Cells + //========================================================================== + AddressBookNS::SymAddr_t BaseAddr = 0x00000000; + + AddressBookNS::Record_t DData1; + DData1.Supervisor = 0xFFFF0001; + DData1.DeviceType = 1; + DData1.RecordType = static_cast(AddressBookNS::Device); + + for (long i = 0; i < 256; i++) + { + //if(i%100 == 0) std::cout << "\t" << i*1000 << "..." << std::endl; + for (long j = 0; j < 256; j++) + { + if (!(i == 0 && j == 0) && !(i == 255 && j == 255)) + { + DData1.Name = "C_" + TO_STRING(i) + "," + TO_STRING(j); + DData1.Address = BaseAddr++; + + try{ + unsigned DAdd = AddrBook.AddDevice(tName, DData1); + if (DAdd > 0) std::cerr << std::endl << "ERROR adding Device" + << DData1.Name << " (" + << DData1.Address << "): " + << DAdd << std::endl; + } catch (const char* msg) { + std::cerr << std::endl << "ERROR adding Device " + << DData1.Name << " (" + << DData1.Address << "): " + << msg << std::endl; + std::cin.get(); + } + } + } + } + //========================================================================== + + + // Get the task for running tests on + AddrBook.GetTask(tName, taskData); + + //========================================================================== + //Check that the task hasn't been altered by adding devices + //========================================================================== + SECTION("Check that we have the right number of devices in the task data after adding", "[Simple]") + { + REQUIRE(AddrBook.GetTaskCount() == 1); // We should have one task, + + REQUIRE(taskData.Name == tName); // Check the task name. + REQUIRE(taskData.Path == TData.Path); // Check the path string. + REQUIRE(taskData.XML == TData.XML); // Check the XML string. + REQUIRE(taskData.ExecutablePath == TData.ExecutablePath); // Check the executable path string. + + REQUIRE(taskData.State == AddressBookNS::Loaded); // Check the task state. + + //REQUIRE(taskData.DeviceTypes.size() == TData.DeviceTypes.size()); + REQUIRE(taskData.DeviceTypes.size() == 5); // with 5 device types, + REQUIRE(taskData.MessageTypes.size() == 3); // with 3 message types, + REQUIRE(taskData.AttributeTypes.size() == 1); // and 1 attribute type. + + REQUIRE(taskData.DeviceCount == TData.DeviceCount); // Expecting 10000 devices + REQUIRE(taskData.DeviceCountLd == TData.DeviceCount); // With all loaded. + + REQUIRE(taskData.ExternalCount == 1); // Expecting 1 external device + REQUIRE(taskData.ExternalCountLd == 1); // With 1 loaded. + + REQUIRE(taskData.SupervisorCount == 1); // Should have one supervisors. + + + } + //========================================================================== + + + //========================================================================== + // Search for devices + //========================================================================== + SECTION("Check that devices added as expected and can be found by name and address", "[Simple]") + { + std::string DName = "C_75,199"; // Name of a device we are going to search for + AddressBookNS::SymAddr_t DNameAddr = 0x4BC6; // and its address + + std::string DAddrName = "C_1,119"; // and its name + AddressBookNS::SymAddr_t DAddr = 0x0176; // Address to search for + + const AddressBookNS::Record_t * DeviceRecord; // pointer to a const-qualified Device record + + // Find device by name + int a = AddrBook.FindDevice(tName, DName, DeviceRecord); + REQUIRE(a == 0); // Found the device? + if(a == 0) + { + REQUIRE(DName == DeviceRecord->Name); // Check the name + REQUIRE(DNameAddr == DeviceRecord->Address); // Check the address + REQUIRE(taskData.DeviceTypes[DeviceRecord->DeviceType].Name == "Cell"); // Check the type + } + + // Find device by address + int b = AddrBook.FindDevice(tName, DAddr, DeviceRecord); + REQUIRE(b == 0); // Found the device? + if(b == 0) + { + REQUIRE(DAddrName == DeviceRecord->Name); // Check the name + REQUIRE(DAddr == DeviceRecord->Address); // Check the address + REQUIRE(taskData.DeviceTypes[DeviceRecord->DeviceType].Name == "Cell"); // Check the type + } + } + + SECTION("Integrity Check - this will take some time", "[Simple]") + { + int result = AddrBook.IntegTask(tName, false); + REQUIRE(result == 0); + } +} From 3c317755fc68cc6d8e0c96f9d77f3dc4614b901b Mon Sep 17 00:00:00 2001 From: Graeme Bragg Date: Mon, 13 Jan 2020 12:37:17 +0000 Subject: [PATCH 06/15] Tidy up some comments --- .../AddressBook/AddressBook_Defs.hpp | 9 ++- .../AddressBook/AddressBook_Record.cpp | 15 ++++- .../AddressBook/AddressBook_Record.hpp | 48 +++++++------- .../AddressBook/AddressBook_Task.cpp | 66 ++++++++++++++++--- .../AddressBook/AddressBook_Task.hpp | 20 +++--- 5 files changed, 108 insertions(+), 50 deletions(-) diff --git a/Source/NameServer/AddressBook/AddressBook_Defs.hpp b/Source/NameServer/AddressBook/AddressBook_Defs.hpp index d3b65f4d..ba418aea 100644 --- a/Source/NameServer/AddressBook/AddressBook_Defs.hpp +++ b/Source/NameServer/AddressBook/AddressBook_Defs.hpp @@ -16,7 +16,6 @@ namespace AddressBookNS typedef uint64_t SymAddr_t; // A 64-bit full-symbolic address static const SymAddr_t INVALID_ADDRESS = UINT64_MAX; -//typedef unsigned long SymAddr_t; // A 64-bit full-symbolic address //---------------------------------------- @@ -30,9 +29,9 @@ typedef unsigned MsgIdx; struct DeviceData_t { int size() const; // Get the size of the DeviceData - SymAddr_t Address; // Device's full sym address. - SymAddr_t Supervisor; // Full sym address of the Device's Supervisor. - std::string Name; // Device's cnonical name. + SymAddr_t Address; // Device's full symbolic address. + SymAddr_t Supervisor; // Full symbolic address of the Device's Supervisor. + std::string Name; // Device's canonical name. }; @@ -40,7 +39,7 @@ struct DevTypeRecord_t { DevTypeRecord_t(std::string N = ""); int size() const; // Get the size of the DeviceType Record - std::string Name; // Device Type cnonical name. + std::string Name; // Device Type canonical name. std::vector InMsgs; // Vector of Input Message indexes std::vector OuMsgs; // Vector of Output Message indexes }; diff --git a/Source/NameServer/AddressBook/AddressBook_Record.cpp b/Source/NameServer/AddressBook/AddressBook_Record.cpp index c089278a..8c410ace 100644 --- a/Source/NameServer/AddressBook/AddressBook_Record.cpp +++ b/Source/NameServer/AddressBook/AddressBook_Record.cpp @@ -3,11 +3,17 @@ namespace AddressBookNS { +/*============================================================================== + * Record_t::Record_t(): Default initialiser for a Record_t. + *============================================================================*/ Record_t::Record_t() { - Attribute = -1; + Attribute = -1; // Set to -1 to ensure that we don't go out of range. } +/*============================================================================== + * Record_t::Record_t(): Full initialiser for a Record_t + *============================================================================*/ Record_t::Record_t(std::string Name, SymAddr_t Addr, uint64_t Super, DTypeIdx Type, RecordType_t RT, AttrIdx Attr) : Name(Name) @@ -23,13 +29,16 @@ Record_t::Record_t(std::string Name, SymAddr_t Addr, uint64_t Super, } +/*============================================================================== + * Record_t::size(): Return the size (in bytes) of the address record. + *============================================================================*/ int Record_t::size() const { int size = 0; size += sizeof(SymAddr_t) * 2; // Address and Supervisor/Rank - size += sizeof(DTypeIdx); // Device Type Idx - size += sizeof(AttrIdx); // Attribute Idx + size += sizeof(DTypeIdx); // Device Type Index + size += sizeof(AttrIdx); // Attribute Index size += sizeof(RecordType_t); // Record Type size += sizeof(char) * Name.size(); // Name diff --git a/Source/NameServer/AddressBook/AddressBook_Record.hpp b/Source/NameServer/AddressBook/AddressBook_Record.hpp index c1e480fc..4531735f 100644 --- a/Source/NameServer/AddressBook/AddressBook_Record.hpp +++ b/Source/NameServer/AddressBook/AddressBook_Record.hpp @@ -5,35 +5,35 @@ namespace AddressBookNS { - enum RecordType_t { Device = 0, DeviceExt, External, Supervisor }; +enum RecordType_t { Device = 0, DeviceExt, External, Supervisor }; - // data contents factored out for serialisation 17 July 2019 ADR - struct RecordData_t +// data contents factored out for serialisation 17 July 2019 ADR +struct RecordData_t +{ + public: + + SymAddr_t Address; // Device's full sym address. + union { - public: - - SymAddr_t Address; // Device's full sym address. - union - { - SymAddr_t Supervisor; // Full sym address of the Device's Supervisor. - unsigned long Rank; // OR Supervisor's MPI Rank. - }; - DTypeIdx DeviceType; // Index of the Device's type in task. - AttrIdx Attribute; // Index of the Device's attribute in task. - RecordType_t RecordType; // Class of device represented by the record. + SymAddr_t Supervisor; // Full sym address of the Device's Supervisor. + unsigned long Rank; // OR Supervisor's MPI Rank. }; + DTypeIdx DeviceType; // Index of the Device's type in task. + AttrIdx Attribute; // Index of the Device's attribute in task. + RecordType_t RecordType; // Class of device represented by the record. +}; - class Record_t : public RecordData_t - { - public: - - Record_t(); - Record_t(std::string, SymAddr_t, uint64_t, DTypeIdx, RecordType_t = Device, AttrIdx = -1); - - int size() const; // Size of the record +class Record_t : public RecordData_t +{ + public: + + Record_t(); + Record_t(std::string, SymAddr_t, uint64_t, DTypeIdx, RecordType_t = Device, AttrIdx = -1); - std::string Name; // Device's canonical name. - }; + int size() const; // Size of the record + + std::string Name; // Device's canonical name. +}; } /* namespace AddressBookNS */ #endif /* AddressBook_Record_H */ diff --git a/Source/NameServer/AddressBook/AddressBook_Task.cpp b/Source/NameServer/AddressBook/AddressBook_Task.cpp index 92cf001d..d75d9b88 100644 --- a/Source/NameServer/AddressBook/AddressBook_Task.cpp +++ b/Source/NameServer/AddressBook/AddressBook_Task.cpp @@ -4,7 +4,7 @@ namespace AddressBookNS { /*============================================================================== - * TaskData + * TaskData - used to communicate task data without maps and pointers. *============================================================================*/ TaskData_t::TaskData_t() { @@ -22,6 +22,9 @@ TaskData_t::TaskData_t() State = Loaded; } +/*============================================================================== + * TaskData_t::TaskData_t(): Full initialiser for a TaskData_t + *============================================================================*/ TaskData_t::TaskData_t(std::string &N, std::string &P, std::string &X, std::string &E, TaskState_t S, unsigned long DC, unsigned long EC) { @@ -39,6 +42,9 @@ TaskData_t::TaskData_t(std::string &N, std::string &P, std::string &X, std::stri State = S; } +/*============================================================================== + * TaskData_t::size(): Return the size (in bytes) of the address record. + *============================================================================*/ int TaskData_t::size() const { int size = 0; @@ -72,7 +78,7 @@ int TaskData_t::size() const } /*============================================================================== - * TaskRecord + * TaskRecord - stores data about the task in an instance of AddressBook *============================================================================*/ TaskRecord_t::TaskRecord_t() { @@ -93,6 +99,9 @@ TaskRecord_t::TaskRecord_t() LinkValid = true; } +/*============================================================================== + * TaskRecord_t::TaskRecord_t(): Full initialiser for a TaskRecord_t + *============================================================================*/ TaskRecord_t::TaskRecord_t(std::string &N, std::string &P, std::string &X, std::string &E, TaskState_t S, unsigned long DC, unsigned long EC) { @@ -113,10 +122,36 @@ TaskRecord_t::TaskRecord_t(std::string &N, std::string &P, std::string &X, std:: LinkValid = true; } + +/*============================================================================== + * TaskRecord_t::Integrity(): Run an integrity check on the entire task. + * + * Verbose: Print lots of information to *fp (stdout by default). + * + * Scours the data structure checking that all of the maps and vectors all + * point to valid data and that there are no invalid indicies or pointers. + * + * This will mark the underlying data structure as dirty if it finds any + * inconsistencies. If RECOVERABLEINTEGRITY is defined, a successful + * integrity check marks the data structure as clean. + * + * When AB_THREADING is defined (by default this is when built with C++11 + * (or newer) AND (C11 (or newer) OR POSIX)), the integrity checks are + * parallelised to reduce the potentially significant runtime of large + * applications. The number of threads is set based on the available + * concurrency, with at least one thread used for each check type (minimum + * 4 threads). Where concurrency is high, 2*concurrency threads are used in + * the following way: + * Devices vector 1*concurrency threads + * DeviceType vectors, etc. 0.5*concurrency threads + * Supervisors vector 0.25*concurrency threads + * Externals vector 0.25*concurrency threads + * + *============================================================================*/ unsigned TaskRecord_t::Integrity(bool Verbose, FILE * fp) { - ABULONG ExtConCnt(0); - ABUNSIGNED MappedSupervisors(0); + AB_ULONG ExtConCnt(0); + AB_UNSIGNED MappedSupervisors(0); IntegVals_t retVal; retVal.ret = 0; @@ -124,7 +159,6 @@ unsigned TaskRecord_t::Integrity(bool Verbose, FILE * fp) retVal.retL = 0; retVal.retM = 0; - //fprintf(fp,"Task: %s\n", Search->first.c_str()); if (Verbose) fprintf(fp, "Integrity check of %s:\n", Name.c_str()); @@ -472,6 +506,11 @@ unsigned TaskRecord_t::Integrity(bool Verbose, FILE * fp) return retVal.ret; } + +/*============================================================================== + * TaskRecord_t::IntegDevTypeMap(): Run an integrity check on the device type + * map in the range of DStart-DEnd. + *============================================================================*/ void TaskRecord_t::IntegDevTypeMap(bool Verbose, FILE * fp, unsigned long DTStart, unsigned long DTEnd, IntegVals_t &retVal) { @@ -537,10 +576,13 @@ void TaskRecord_t::IntegDevTypeMap(bool Verbose, FILE * fp, unsigned long DTStar } } - +/*============================================================================== + * TaskRecord_t::IntegDevices(): Run an integrity check on the devices in the + * range of DStart-DEnd. + *============================================================================*/ void TaskRecord_t::IntegDevices(bool Verbose, FILE * fp, unsigned long DStart, unsigned long DEnd, IntegVals_t &retVal, - ABULONG &ExtConCnt) + AB_ULONG &ExtConCnt) { for(std::vector::const_iterator D = Devices.begin() + DStart; (D != Devices.end()) && (D < (Devices.begin() + DEnd)); @@ -661,6 +703,10 @@ void TaskRecord_t::IntegDevices(bool Verbose, FILE * fp, unsigned long DStart, } } +/*============================================================================== + * TaskRecord_t::IntegExternals(): Run an integrity check on the externals in + * the range of DStart-DEnd. + *============================================================================*/ void TaskRecord_t::IntegExternals(bool Verbose, FILE * fp, unsigned long EStart, unsigned long EEnd, IntegVals_t &retVal) { @@ -751,9 +797,13 @@ void TaskRecord_t::IntegExternals(bool Verbose, FILE * fp, unsigned long EStart, } } +/*============================================================================== + * TaskRecord_t::IntegSupervisors(): Run an integrity check on the supervisors + * in the range of DStart-DEnd. + *============================================================================*/ void TaskRecord_t::IntegSupervisors(bool Verbose, FILE * fp, unsigned long SStart, unsigned long SEnd, IntegVals_t &retVal, - ABUNSIGNED &MappedSupervisors) + AB_UNSIGNED &MappedSupervisors) { for(std::vector::const_iterator S = Supervisors.begin() + SStart; (S != Supervisors.end()) && (S < (Supervisors.begin() + SEnd)); diff --git a/Source/NameServer/AddressBook/AddressBook_Task.hpp b/Source/NameServer/AddressBook/AddressBook_Task.hpp index 58cb1eef..e87d0c9f 100644 --- a/Source/NameServer/AddressBook/AddressBook_Task.hpp +++ b/Source/NameServer/AddressBook/AddressBook_Task.hpp @@ -18,11 +18,11 @@ #define AB_THREADING // We need Atomic types if we are using threading. - #define ABUNSIGNED std::atomic - #define ABULONG std::atomic + #define AB_UNSIGNED std::atomic + #define AB_ULONG std::atomic #else - #define ABUNSIGNED unsigned - #define ABULONG unsigned long + #define AB_UNSIGNED unsigned + #define AB_ULONG unsigned long #endif @@ -43,10 +43,10 @@ typedef std::pair DevTypePair; typedef std::pair AttrTypePair; struct IntegVals_t { - ABUNSIGNED ret; - ABUNSIGNED retT; - ABUNSIGNED retL; - ABUNSIGNED retM; + AB_UNSIGNED ret; + AB_UNSIGNED retT; + AB_UNSIGNED retL; + AB_UNSIGNED retM; }; struct TaskData_t { @@ -124,14 +124,14 @@ class TaskRecord_t { private: void IntegDevices(bool Verbose, FILE * fp, unsigned long DStart, unsigned long DEnd, IntegVals_t &retVal, - ABULONG &ExtConCnt); + AB_ULONG &ExtConCnt); void IntegExternals(bool Verbose, FILE * fp, unsigned long EStart, unsigned long EEnd, IntegVals_t &retVal); void IntegSupervisors(bool Verbose, FILE * fp, unsigned long SStart, unsigned long SEnd, IntegVals_t &retVal, - ABUNSIGNED &MappedSupervisors); + AB_UNSIGNED &MappedSupervisors); void IntegDevTypeMap(bool Verbose, FILE * fp, unsigned long DTStart, unsigned long DTEnd, IntegVals_t &retVal); From 5694fbb873addf05a9064ef2d4a07a4f446d446a Mon Sep 17 00:00:00 2001 From: Graeme Bragg Date: Mon, 13 Jan 2020 13:10:18 +0000 Subject: [PATCH 07/15] Addressing @mvousden's comment in #103 to "Use an enum." --- Source/NameServer/AddressBook/AddressBook.cpp | 18 --------- Source/NameServer/AddressBook/AddressBook.hpp | 38 +++++++++---------- Tests/TestAddressBook.cpp | 16 ++++---- 3 files changed, 27 insertions(+), 45 deletions(-) diff --git a/Source/NameServer/AddressBook/AddressBook.cpp b/Source/NameServer/AddressBook/AddressBook.cpp index 9904352e..86a90f5b 100644 --- a/Source/NameServer/AddressBook/AddressBook.cpp +++ b/Source/NameServer/AddressBook/AddressBook.cpp @@ -13,24 +13,6 @@ namespace AddressBookNS #define ERETURN(X, Y) return Y #endif -// static constant definitions -const unsigned AddressBook::SUCCESS; -const unsigned AddressBook::ERR_NONFATAL; -const unsigned AddressBook::ERR_INVALID_TASK; -const unsigned AddressBook::ERR_INVALID_DEVTYPE; -const unsigned AddressBook::ERR_INVALID_DEVICE; -const unsigned AddressBook::ERR_INVALID_MESSAGE_TYPE; -const unsigned AddressBook::ERR_INVALID_ATTRIBUTE; -const unsigned AddressBook::ERR_DEVICE_DATA_MISMATCH; -const unsigned AddressBook::ERR_TASKNAME_USED; -const unsigned AddressBook::ERR_DEVICENAME_USED; -const unsigned AddressBook::ERR_DEVICE_ADDR_USED; -const unsigned AddressBook::ERR_TASK_NOT_FOUND; -const unsigned AddressBook::ERR_DEVICE_NOT_FOUND; -const unsigned AddressBook::ERR_INVALID_MAP; -const unsigned AddressBook::ERR_INVALID_SUPERVISOR; -const unsigned AddressBook::ERR_INVALID_STATE; - //Constructors AddressBook::AddressBook(std::string d) { diff --git a/Source/NameServer/AddressBook/AddressBook.hpp b/Source/NameServer/AddressBook/AddressBook.hpp index 9340e3ec..098d45bd 100644 --- a/Source/NameServer/AddressBook/AddressBook.hpp +++ b/Source/NameServer/AddressBook/AddressBook.hpp @@ -50,6 +50,25 @@ namespace AddressBookNS // changed name to avoid conflicts with the class itself { typedef std::map TaskMap_t; +enum ReturnCode_t { ERR_BAD_COUNT = -1, + SUCCESS = 0, + ERR_NONFATAL, + ERR_INVALID_TASK, + ERR_INVALID_DEVTYPE, + ERR_INVALID_DEVICE, + ERR_INVALID_MESSAGE_TYPE, + ERR_INVALID_ATTRIBUTE, + ERR_DEVICE_DATA_MISMATCH, + ERR_TASKNAME_USED, + ERR_DEVICENAME_USED, + ERR_DEVICE_ADDR_USED, + ERR_TASK_NOT_FOUND, + ERR_DEVICE_NOT_FOUND, + ERR_INVALID_MAP, + ERR_INVALID_SUPERVISOR, + ERR_INVALID_STATE + }; + class AddressBook { public: @@ -123,25 +142,6 @@ class AddressBook void Dump(std::string &Name); void Dump(FILE * = stdout, std::string Name = ""); - static const long ERR_BAD_COUNT = -1; - - static const unsigned SUCCESS = 0; - static const unsigned ERR_NONFATAL = 0; - static const unsigned ERR_INVALID_TASK = 1; - static const unsigned ERR_INVALID_DEVTYPE = 2; - static const unsigned ERR_INVALID_DEVICE = 3; - static const unsigned ERR_INVALID_MESSAGE_TYPE = 4; - static const unsigned ERR_INVALID_ATTRIBUTE = 5; - static const unsigned ERR_DEVICE_DATA_MISMATCH = 6; - static const unsigned ERR_TASKNAME_USED = 7; - static const unsigned ERR_DEVICENAME_USED = 8; - static const unsigned ERR_DEVICE_ADDR_USED = 9; - static const unsigned ERR_TASK_NOT_FOUND = 10; - static const unsigned ERR_DEVICE_NOT_FOUND = 11; - static const unsigned ERR_INVALID_MAP = 12; - static const unsigned ERR_INVALID_SUPERVISOR = 13; - static const unsigned ERR_INVALID_STATE = 14; - private: TaskMap_t TaskMap; int TaskCount; diff --git a/Tests/TestAddressBook.cpp b/Tests/TestAddressBook.cpp index 74486e14..a644e600 100644 --- a/Tests/TestAddressBook.cpp +++ b/Tests/TestAddressBook.cpp @@ -70,7 +70,7 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") // Add the task to the AddressBook int t1Ret = AddrBook.AddTask(t1Name, T1Data); - REQUIRE(t1Ret == AddressBookNS::AddressBook::SUCCESS); + REQUIRE(t1Ret == AddressBookNS::SUCCESS); SECTION("Check that a task added correctly", "[Simple]") { @@ -79,7 +79,7 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") // Get the task for running tests on t1Ret = AddrBook.GetTask(t1Name, taskData); - REQUIRE(t1Ret == AddressBookNS::AddressBook::SUCCESS); + REQUIRE(t1Ret == AddressBookNS::SUCCESS); REQUIRE(taskData.Name == t1Name); // Check the task name. REQUIRE(taskData.Path == T1Data.Path); // Check the path string. @@ -126,7 +126,7 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") // Add the task to the AddressBook int t2Ret = AddrBook.AddTask(t2Name, T2Data); - REQUIRE(t2Ret == AddressBookNS::AddressBook::SUCCESS); + REQUIRE(t2Ret == AddressBookNS::SUCCESS); SECTION("Check that a second task added correctly", "[Simple]") @@ -136,7 +136,7 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") // Get the task for running tests on t2Ret = AddrBook.GetTask(t2Name, taskData); - REQUIRE(t2Ret == AddressBookNS::AddressBook::SUCCESS); + REQUIRE(t2Ret == AddressBookNS::SUCCESS); REQUIRE(taskData.Name == t2Name); // Check the task name. REQUIRE(taskData.Path == T2Data.Path); // Check the path string. @@ -168,7 +168,7 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") SECTION("Check that a duplicate task is correctly rejected", "[Simple]") { int t3Ret = AddrBook.AddTask(t2Name, T2Data); - REQUIRE(t3Ret == AddressBookNS::AddressBook::ERR_TASKNAME_USED); + REQUIRE(t3Ret == AddressBookNS::ERR_TASKNAME_USED); REQUIRE(AddrBook.GetTaskCount() == 2); // We should have two tasks, REQUIRE(AddrBook.IntegCheck() == 0); // that pass integrity. } @@ -182,7 +182,7 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") SECTION("Check that tasks can be deleted", "[Simple]") { int delRet = AddrBook.DelTask(t2Name); - REQUIRE(delRet == AddressBookNS::AddressBook::SUCCESS); + REQUIRE(delRet == AddressBookNS::SUCCESS); REQUIRE(AddrBook.GetTaskCount() == 1); // We should have one task, REQUIRE(AddrBook.IntegCheck() == 0); // that passes integrity. } @@ -340,7 +340,7 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") DData1.Address = BaseAddr++; try { unsigned DAdd = AddrBook.AddDevice(t1Name, DData1); - REQUIRE(DAdd == 2); + REQUIRE(DAdd == AddressBookNS::ERR_INVALID_DEVTYPE); } catch (const char* msg) { std::cerr << std::endl << "ERROR adding Device " << DData1.Name << " (" << DData1.Address << "): " @@ -409,7 +409,7 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") #else // Otherwise it is invalid and we need to relink. REQUIRE(AddrBook.TaskLinkValid(t1Name) == false); - REQUIRE(AddrBook.BuildLink(t1Name) == AddressBookNS::AddressBook::SUCCESS); + REQUIRE(AddrBook.BuildLink(t1Name) == AddressBookNS::SUCCESS); REQUIRE(AddrBook.TaskLinkValid(t1Name) == true); // Link should now be valid #endif // Check that the rest of the task is valid From cf481a73b982e148a24aac1719c27a5310e8afa9 Mon Sep 17 00:00:00 2001 From: Graeme Bragg Date: Mon, 13 Jan 2020 13:24:44 +0000 Subject: [PATCH 08/15] Addressing @mvousden's comment in #103 regarding the ERETURN pattern --- Source/NameServer/AddressBook/AddressBook.cpp | 84 +++++++++---------- 1 file changed, 39 insertions(+), 45 deletions(-) diff --git a/Source/NameServer/AddressBook/AddressBook.cpp b/Source/NameServer/AddressBook/AddressBook.cpp index 86a90f5b..dbffa9ce 100644 --- a/Source/NameServer/AddressBook/AddressBook.cpp +++ b/Source/NameServer/AddressBook/AddressBook.cpp @@ -7,12 +7,6 @@ //============================================================================== namespace AddressBookNS { -#ifdef EXCEPTS -#define ERETURN(X, Y) throw(X) -#else -#define ERETURN(X, Y) return Y -#endif - //Constructors AddressBook::AddressBook(std::string d) { @@ -310,7 +304,7 @@ unsigned AddressBook::TaskExecPath(std::string &TaskName, std::string &NewPath) TaskRecord_t *TRec = FindTask(TaskName); if(TRec == PNULL) { - ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + return(ERR_TASK_NOT_FOUND); } TRec->ExecPath = NewPath; @@ -325,7 +319,7 @@ bool AddressBook::TaskValid(std::string &TaskName) TaskRecord_t *TRec = FindTask(TaskName); if(TRec == PNULL) { - ERETURN("Task Does Not Exist", false); + return(false); } return TRec->TaskValid; @@ -339,7 +333,7 @@ bool AddressBook::TaskMapValid(std::string &TaskName) TaskRecord_t *TRec = FindTask(TaskName); if(TRec == PNULL) { - ERETURN("Task Does Not Exist", false); + return(false); } return TRec->MapValid; @@ -353,7 +347,7 @@ bool AddressBook::TaskLinkValid(std::string &TaskName) TaskRecord_t *TRec = FindTask(TaskName); if(TRec == PNULL) { - ERETURN("Task Does Not Exist", false); + return(false); } return TRec->LinkValid; @@ -368,7 +362,7 @@ unsigned AddressBook::RebuildTask(std::string &TaskName) TaskRecord_t *TRec = FindTask(TaskName); if(TRec == PNULL) { - ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + return(ERR_TASK_NOT_FOUND); } //TODO: test this @@ -422,7 +416,7 @@ unsigned AddressBook::BuildMaps(std::string &TaskName) TaskRecord_t *TRec = FindTask(TaskName); if(TRec == PNULL) { - ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + return(ERR_TASK_NOT_FOUND); } if(TRec->MapValid || TRec->NameMap.size() > 0 @@ -464,7 +458,7 @@ unsigned AddressBook::BuildLink(std::string &TaskName) TaskRecord_t *TRec = FindTask(TaskName); if(TRec == PNULL) { - ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + return(ERR_TASK_NOT_FOUND); } if(TRec->LinkValid || TRec->AddrMap.size() > 0) ClearLink(TRec); // Existing link, clear it @@ -504,7 +498,7 @@ unsigned AddressBook::AddDevice(std::string &TaskName, Record_t &DevRec, bool Va if(TRec == PNULL) { // DebugPrint("No such task: %s\n", TaskName.c_str()); - ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + return(ERR_TASK_NOT_FOUND); } Record_t *DRec; @@ -587,7 +581,7 @@ unsigned AddressBook::UpdateDevice(std::string &TaskName, DeviceData_t &Data) TaskRecord_t *TRec = FindTask(TaskName); if(TRec == PNULL) { - ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + return(ERR_TASK_NOT_FOUND); } // Check that the Device Name exists @@ -611,7 +605,7 @@ long AddressBook::GetDeviceCount(std::string &TaskName) TaskRecord_t *TRec = FindTask(TaskName); if(TRec == PNULL) { - ERETURN("Task Does Not Exist", ERR_BAD_COUNT); + return(ERR_BAD_COUNT); } return static_cast(TRec->DevCntMax); @@ -625,7 +619,7 @@ long AddressBook::GetLoadedDeviceCount(std::string &TaskName) TaskRecord_t *TRec = FindTask(TaskName); if(TRec == PNULL) { - ERETURN("Task Does Not Exist", ERR_BAD_COUNT); + return(ERR_BAD_COUNT); } return static_cast(TRec->DevCnt); @@ -639,7 +633,7 @@ long AddressBook::GetExternalCount(std::string &TaskName) TaskRecord_t *TRec = FindTask(TaskName); if(TRec == PNULL) { - ERETURN("Task Does Not Exist", ERR_BAD_COUNT); + return(ERR_BAD_COUNT); } return static_cast(TRec->ExtCntMax); @@ -653,7 +647,7 @@ long AddressBook::GetLoadedExternalCount(std::string &TaskName) TaskRecord_t *TRec = FindTask(TaskName); if(TRec == PNULL) { - ERETURN("Task Does Not Exist", ERR_BAD_COUNT); + return(ERR_BAD_COUNT); } return static_cast(TRec->ExtCnt); @@ -667,7 +661,7 @@ int AddressBook::GetSupervisorCount(std::string &TaskName) TaskRecord_t *TRec = FindTask(TaskName); if(TRec == PNULL) { - ERETURN("Task Does Not Exist", ERR_BAD_COUNT); + return(ERR_BAD_COUNT); } return static_cast(TRec->SupCnt); @@ -681,7 +675,7 @@ int AddressBook::GetMappedSupervisorCount(std::string &TaskName) TaskRecord_t *TRec = FindTask(TaskName); if(TRec == PNULL) { - ERETURN("Task Does Not Exist", ERR_BAD_COUNT); + return(ERR_BAD_COUNT); } return TRec->SupMap.size(); @@ -700,7 +694,7 @@ unsigned AddressBook::FindDevice(std::string &TaskName, SymAddr_t Address, const TaskRecord_t *TRec = FindTask(TaskName); if(TRec == PNULL) { - ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + return(ERR_TASK_NOT_FOUND); } if(!(TRec->TaskValid && TRec->MapValid && TRec->LinkValid)) // Return NotFound if dirty @@ -710,7 +704,7 @@ unsigned AddressBook::FindDevice(std::string &TaskName, SymAddr_t Address, const AddrMap_t::iterator DSearch = TRec->AddrMap.find(Address); // Find the Device if (DSearch == TRec->AddrMap.end()) { - ERETURN("Device Not Found", ERR_DEVICE_NOT_FOUND); + return(ERR_DEVICE_NOT_FOUND); } DRec = &(*DSearch->second); @@ -727,7 +721,7 @@ unsigned AddressBook::FindDevice(std::string &TaskName, std::string &Name, const TaskRecord_t *TRec = FindTask(TaskName); if(TRec == PNULL) { - ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + return(ERR_TASK_NOT_FOUND); } if(!(TRec->TaskValid && TRec->MapValid && TRec->LinkValid)) // Return NotFound if dirty @@ -737,7 +731,7 @@ unsigned AddressBook::FindDevice(std::string &TaskName, std::string &Name, const NameMap_t::iterator DSearch = TRec->NameMap.find(Name); // Find the Device if (DSearch == TRec->NameMap.end()) { - ERETURN("Device Not Found", ERR_DEVICE_NOT_FOUND); + return(ERR_DEVICE_NOT_FOUND); } DRec = &(*DSearch->second); @@ -755,7 +749,7 @@ unsigned AddressBook::FindBySuper(std::string &TaskName, SymAddr_t Supervisor, c TaskRecord_t *TRec = FindTask(TaskName); if(TRec == PNULL) { - ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + return(ERR_TASK_NOT_FOUND); } if(!(TRec->TaskValid && TRec->MapValid && TRec->LinkValid)) // Return NotFound if dirty @@ -765,7 +759,7 @@ unsigned AddressBook::FindBySuper(std::string &TaskName, SymAddr_t Supervisor, c SupMap_t::iterator SSearch = TRec->SupMap.find(Supervisor); // Find the Supervisor if (SSearch == TRec->SupMap.end()) { - ERETURN("Device Not Found", ERR_DEVICE_NOT_FOUND); + return(ERR_DEVICE_NOT_FOUND); } Records = &SSearch->second; @@ -777,7 +771,7 @@ unsigned AddressBook::FindByType(std::string &TaskName, std::string Type, const TaskRecord_t *TRec = FindTask(TaskName); if(TRec == PNULL) { - ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + return(ERR_TASK_NOT_FOUND); } if(!(TRec->TaskValid && TRec->MapValid && TRec->LinkValid)) // Return NotFound if dirty @@ -787,7 +781,7 @@ unsigned AddressBook::FindByType(std::string &TaskName, std::string Type, const IdxMap_t::iterator TSearch = TRec->DevTypeMap.find(Type); // Find the Index if (TSearch == TRec->DevTypeMap.end()) { - ERETURN("Device Type Not Found", ERR_DEVICE_NOT_FOUND); + return(ERR_DEVICE_NOT_FOUND); } Records = &(TRec->DevTypes[TSearch->second].second); @@ -800,7 +794,7 @@ unsigned AddressBook::FindByAttribute(std::string &TaskName, std::string Attribu TaskRecord_t *TRec = FindTask(TaskName); if(TRec == PNULL) { - ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + return(ERR_TASK_NOT_FOUND); } if(!(TRec->TaskValid && TRec->MapValid && TRec->LinkValid)) // Return NotFound if dirty @@ -810,7 +804,7 @@ unsigned AddressBook::FindByAttribute(std::string &TaskName, std::string Attribu IdxMap_t::iterator ASearch = TRec->AttrTypeMap.find(Attribute); // Find the Index if (ASearch == TRec->AttrTypeMap.end()) { - ERETURN("Device Type Not Found", ERR_DEVICE_NOT_FOUND); + return(ERR_DEVICE_NOT_FOUND); } Records = &(TRec->AttrTypes[ASearch->second].second); @@ -823,7 +817,7 @@ unsigned AddressBook::FindByInMsg(std::string &TaskName, std::string Msg, const TaskRecord_t *TRec = FindTask(TaskName); if(TRec == PNULL) { - ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + return(ERR_TASK_NOT_FOUND); } if(!(TRec->TaskValid && TRec->MapValid && TRec->LinkValid)) // Return NotFound if dirty @@ -839,7 +833,7 @@ unsigned AddressBook::FindByOuMsg(std::string &TaskName, std::string Msg, const TaskRecord_t *TRec = FindTask(TaskName); if(TRec == PNULL) { - ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + return(ERR_TASK_NOT_FOUND); } if(!(TRec->TaskValid && TRec->MapValid && TRec->LinkValid)) // Return NotFound if dirty @@ -855,7 +849,7 @@ unsigned AddressBook::GetDevices(std::string &TaskName, const std::vectorTaskValid && TRec->MapValid && TRec->LinkValid)) // Return NotFound if dirty @@ -873,7 +867,7 @@ unsigned AddressBook::GetExternals(std::string &TaskName, const std::vectorTaskValid && TRec->MapValid && TRec->LinkValid)) // Return NotFound if dirty @@ -891,7 +885,7 @@ unsigned AddressBook::GetSupervisors(std::string &TaskName, const std::vectorTaskValid && TRec->MapValid && TRec->LinkValid)) // Return NotFound if dirty @@ -909,7 +903,7 @@ unsigned AddressBook::GetExtCon(std::string &TaskName, const RecordVect_t* &Reco TaskRecord_t *TRec = FindTask(TaskName); if(TRec == PNULL) { - ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + return(ERR_TASK_NOT_FOUND); } if(!(TRec->TaskValid && TRec->MapValid && TRec->LinkValid)) // Return NotFound if dirty @@ -936,7 +930,7 @@ TaskRecord_t * AddressBook::FindTask(const std::string &TaskName) // Check that the task exists. TaskMap_t::iterator TSearch = TaskMap.find(TaskName); if (TSearch == TaskMap.end()) { - ERETURN("Task Does Not Exist", PNULL); + return(PNULL); } return TSearch->second; @@ -1013,7 +1007,7 @@ unsigned AddressBook::ValidateDeviceType(const DevTypeRecord_t& DevTypRec, unsig { if(*I >= MaxIdx) { - ERETURN("Invalid MessageType Index", ERR_INVALID_MESSAGE_TYPE); + return(ERR_INVALID_MESSAGE_TYPE); } } @@ -1023,7 +1017,7 @@ unsigned AddressBook::ValidateDeviceType(const DevTypeRecord_t& DevTypRec, unsig { if(*O >= MaxIdx) { - ERETURN("Invalid MessageType Index", ERR_INVALID_MESSAGE_TYPE); + return(ERR_INVALID_MESSAGE_TYPE); } } return 0; @@ -1040,24 +1034,24 @@ unsigned AddressBook::ValidateDevice(TaskRecord_t *TRec, Record_t &DevRec) AddrMap_t::const_iterator DASearch = TRec->AddrMap.find(DevRec.Address); if (DASearch != TRec->AddrMap.end()) { // DebugPrint("Device address %llu already exists\n", DevRec.Address); - ERETURN("DUPADDR: Device Address already added", ERR_DEVICE_ADDR_USED); + return(ERR_DEVICE_ADDR_USED); } NameMap_t::const_iterator DNSearch = TRec->NameMap.find(DevRec.Name); if (DNSearch != TRec->NameMap.end()) { // DebugPrint("Device name %s already exists\n", DevRec.Name.c_str()); - ERETURN("DUPNAME: Device Name already added", ERR_DEVICENAME_USED); + return(ERR_DEVICENAME_USED); } // Check that the indices are valid BEFORE adding the Device. if (DevRec.DeviceType >= TRec->DevTypes.size()) { // DebugPrint("Device type %u does not exist\n", DevRec.DeviceType); - ERETURN("Invalid DeviceType Index", ERR_INVALID_DEVTYPE); + return(ERR_INVALID_DEVTYPE); } if (DevRec.Attribute >= static_cast(TRec->AttrTypes.size())) { // DebugPrint("Device attribute type %u does not exist\n", DevRec.Attribute); - ERETURN("Invalid AttributeType Index", ERR_INVALID_ATTRIBUTE); + return(ERR_INVALID_ATTRIBUTE); } return SUCCESS; // Validation Successful @@ -1161,7 +1155,7 @@ unsigned AddressBook::IntegTask(std::string &TaskName, bool Verbose, FILE * fp) TaskRecord_t *TRec = FindTask(TaskName); if(TRec == PNULL) { - ERETURN("Task Does Not Exist", ERR_TASK_NOT_FOUND); + return(ERR_TASK_NOT_FOUND); } return TRec->Integrity(Verbose, fp); From b3001bdf217a976e19636681996f14ecab76bcf9 Mon Sep 17 00:00:00 2001 From: Graeme Bragg Date: Mon, 13 Jan 2020 13:28:45 +0000 Subject: [PATCH 09/15] Adding comment to address @mvousden's comment in #103 regarding disambiguation of a Union --- Source/NameServer/AddressBook/AddressBook_Record.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/NameServer/AddressBook/AddressBook_Record.hpp b/Source/NameServer/AddressBook/AddressBook_Record.hpp index 4531735f..e5809ba1 100644 --- a/Source/NameServer/AddressBook/AddressBook_Record.hpp +++ b/Source/NameServer/AddressBook/AddressBook_Record.hpp @@ -13,11 +13,11 @@ struct RecordData_t public: SymAddr_t Address; // Device's full sym address. - union - { - SymAddr_t Supervisor; // Full sym address of the Device's Supervisor. - unsigned long Rank; // OR Supervisor's MPI Rank. - }; + union // Disambiguated by RecordType, which appears at + { // at the end of the struct for packing reasons. + SymAddr_t Supervisor; // Full sym address of the Device's Supervisor. + unsigned long Rank; // OR Supervisor's MPI Rank. + }; DTypeIdx DeviceType; // Index of the Device's type in task. AttrIdx Attribute; // Index of the Device's attribute in task. RecordType_t RecordType; // Class of device represented by the record. From 10cddf650122e75892e5f352597b93a5d4090b6c Mon Sep 17 00:00:00 2001 From: Graeme Bragg Date: Mon, 13 Jan 2020 13:30:49 +0000 Subject: [PATCH 10/15] Typos and indentation --- .../NameServer/AddressBook/AddressBook_Task.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Source/NameServer/AddressBook/AddressBook_Task.cpp b/Source/NameServer/AddressBook/AddressBook_Task.cpp index d75d9b88..387f6b87 100644 --- a/Source/NameServer/AddressBook/AddressBook_Task.cpp +++ b/Source/NameServer/AddressBook/AddressBook_Task.cpp @@ -25,8 +25,9 @@ TaskData_t::TaskData_t() /*============================================================================== * TaskData_t::TaskData_t(): Full initialiser for a TaskData_t *============================================================================*/ -TaskData_t::TaskData_t(std::string &N, std::string &P, std::string &X, std::string &E, - TaskState_t S, unsigned long DC, unsigned long EC) +TaskData_t::TaskData_t(std::string &N, std::string &P, std::string &X, + std::string &E, TaskState_t S, unsigned long DC, + unsigned long EC) { Name = N; Path = P; @@ -102,8 +103,9 @@ TaskRecord_t::TaskRecord_t() /*============================================================================== * TaskRecord_t::TaskRecord_t(): Full initialiser for a TaskRecord_t *============================================================================*/ -TaskRecord_t::TaskRecord_t(std::string &N, std::string &P, std::string &X, std::string &E, - TaskState_t S, unsigned long DC, unsigned long EC) +TaskRecord_t::TaskRecord_t(std::string &N, std::string &P, std::string &X, + std::string &E, TaskState_t S, unsigned long DC, + unsigned long EC) { Name = N; Path = P; @@ -462,7 +464,7 @@ unsigned TaskRecord_t::Integrity(bool Verbose, FILE * fp) } - if (retVal.retT > 0) // Task integrity compromised - need to rbuild the task + if (retVal.retT > 0) // Task integrity compromised - need to rebuild the task { TaskValid = false; if (Verbose) fprintf(fp, "\tDirty Task: %d\n", static_cast(retVal.retT)); @@ -512,7 +514,7 @@ unsigned TaskRecord_t::Integrity(bool Verbose, FILE * fp) * map in the range of DStart-DEnd. *============================================================================*/ void TaskRecord_t::IntegDevTypeMap(bool Verbose, FILE * fp, unsigned long DTStart, - unsigned long DTEnd, IntegVals_t &retVal) + unsigned long DTEnd, IntegVals_t &retVal) { for(std::vector::iterator D = DevTypes.begin() + DTStart; (D != DevTypes.end()) && (D < (DevTypes.begin() + DTEnd)); @@ -708,7 +710,7 @@ void TaskRecord_t::IntegDevices(bool Verbose, FILE * fp, unsigned long DStart, * the range of DStart-DEnd. *============================================================================*/ void TaskRecord_t::IntegExternals(bool Verbose, FILE * fp, unsigned long EStart, - unsigned long EEnd, IntegVals_t &retVal) + unsigned long EEnd, IntegVals_t &retVal) { for(std::vector::const_iterator E = Externals.begin() + EStart; (E != Externals.end()) && (E < (Externals.begin() + EEnd)); From 941bcd5beecb0fff83a1a0439bb13e5e0d48c27f Mon Sep 17 00:00:00 2001 From: Graeme Bragg Date: Mon, 13 Jan 2020 14:07:22 +0000 Subject: [PATCH 11/15] Typos --- Source/NameServer/AddressBook/AddressBook.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/NameServer/AddressBook/AddressBook.hpp b/Source/NameServer/AddressBook/AddressBook.hpp index 098d45bd..e7c750c8 100644 --- a/Source/NameServer/AddressBook/AddressBook.hpp +++ b/Source/NameServer/AddressBook/AddressBook.hpp @@ -1,7 +1,7 @@ /*============================================================================== * AddressBook: A back-end implementation for the POETS sbase & Nameserver * - * Tasks can be *maped* and *linked*: + * Tasks can be *mapped* and *linked*: * Mapped: Device Records connected to Device (and Message) and Attribute * types. Device Records with External Connections also listed. * Linked: Device Records connected to Addresses in Address Map and listed From b6104016a84c24c54590366059d2ea3829172dac Mon Sep 17 00:00:00 2001 From: Graeme Bragg Date: Mon, 13 Jan 2020 14:18:09 +0000 Subject: [PATCH 12/15] Removing superfluous TaskCount variable as per @mvousden's comment in #103 --- Source/NameServer/AddressBook/AddressBook.cpp | 6 +----- Source/NameServer/AddressBook/AddressBook.hpp | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/Source/NameServer/AddressBook/AddressBook.cpp b/Source/NameServer/AddressBook/AddressBook.cpp index dbffa9ce..79704686 100644 --- a/Source/NameServer/AddressBook/AddressBook.cpp +++ b/Source/NameServer/AddressBook/AddressBook.cpp @@ -11,7 +11,6 @@ namespace AddressBookNS AddressBook::AddressBook(std::string d) { ABderived = d; - TaskCount = 0; } AddressBook::~AddressBook() @@ -93,7 +92,6 @@ unsigned AddressBook::AddTask(const std::string &TaskName, TaskData_t &Data) // Add to the Task Map. TaskMap.insert(TaskMap_t::value_type(Task->Name, Task)); - ++TaskCount; // Pedantic: avoid assignment to temporary 5 July 2019 ADR /* Insert DeviceTypes. Changed order and call subfunction 5 July 2019 ADR Original had pre-allocation below, but it's hard to see how this @@ -244,8 +242,6 @@ unsigned AddressBook::DelTask(const std::string &TaskName) delete TRec; TaskMap.erase(TaskName); - TaskCount--; - return SUCCESS; } @@ -1178,7 +1174,7 @@ void AddressBook::Dump(FILE * fp, std::string Name) if(Name == std::string("")) // Dump high-level task data. { - fprintf(fp,"Total number of tasks: %d:\n", TaskCount); + fprintf(fp,"Total number of tasks: %lu:\n", TaskMap.size()); for(TaskMap_t::iterator T=TaskMap.begin(); T!=TaskMap.end();T++) { diff --git a/Source/NameServer/AddressBook/AddressBook.hpp b/Source/NameServer/AddressBook/AddressBook.hpp index e7c750c8..ae3f828a 100644 --- a/Source/NameServer/AddressBook/AddressBook.hpp +++ b/Source/NameServer/AddressBook/AddressBook.hpp @@ -144,7 +144,6 @@ class AddressBook private: TaskMap_t TaskMap; - int TaskCount; std::string ABderived; // changed to allow multiple inheritance (from CommonBase) 14 July 2019 ADR TaskRecord_t * FindTask(const std::string &TaskName); From c896aa8afdfc0e2409dd88f51ea1687ac3925682 Mon Sep 17 00:00:00 2001 From: Graeme Bragg Date: Mon, 13 Jan 2020 15:34:32 +0000 Subject: [PATCH 13/15] Revert AddressBookNS to AddressBook --- Source/NameServer/AddressBook/AddressBook.cpp | 4 +- Source/NameServer/AddressBook/AddressBook.hpp | 5 +- .../AddressBook/AddressBook_Defs.cpp | 4 +- .../AddressBook/AddressBook_Defs.hpp | 4 +- .../AddressBook/AddressBook_Record.cpp | 4 +- .../AddressBook/AddressBook_Record.hpp | 4 +- .../AddressBook/AddressBook_Task.cpp | 4 +- .../AddressBook/AddressBook_Task.hpp | 4 +- Tests/TestAddressBook.cpp | 108 +++++++++--------- 9 files changed, 70 insertions(+), 71 deletions(-) diff --git a/Source/NameServer/AddressBook/AddressBook.cpp b/Source/NameServer/AddressBook/AddressBook.cpp index 79704686..216a8699 100644 --- a/Source/NameServer/AddressBook/AddressBook.cpp +++ b/Source/NameServer/AddressBook/AddressBook.cpp @@ -5,7 +5,7 @@ #include //============================================================================== -namespace AddressBookNS +namespace AddressBook { //Constructors AddressBook::AddressBook(std::string d) @@ -1358,4 +1358,4 @@ void AddressBook::Dump(FILE * fp, std::string Name) fprintf(fp,"AddressBook_--------------------------------\n"); fflush(fp); } -} /* namespace AddressBookNS */ +} /* namespace AddressBook */ diff --git a/Source/NameServer/AddressBook/AddressBook.hpp b/Source/NameServer/AddressBook/AddressBook.hpp index ae3f828a..8b54e47e 100644 --- a/Source/NameServer/AddressBook/AddressBook.hpp +++ b/Source/NameServer/AddressBook/AddressBook.hpp @@ -45,8 +45,7 @@ #define MAXSUPERVISORS 16 //============================================================================== -namespace AddressBookNS // changed name to avoid conflicts with the class itself - // 14 July 2019 ADR +namespace AddressBook { typedef std::map TaskMap_t; @@ -161,6 +160,6 @@ class AddressBook unsigned ClearLink(TaskRecord_t *TRec); }; -} /* namespace AddressBookNS */ +} /* namespace AddressBook */ #endif /* AddressBook_H */ diff --git a/Source/NameServer/AddressBook/AddressBook_Defs.cpp b/Source/NameServer/AddressBook/AddressBook_Defs.cpp index bc3c6e7e..93e7e13c 100644 --- a/Source/NameServer/AddressBook/AddressBook_Defs.cpp +++ b/Source/NameServer/AddressBook/AddressBook_Defs.cpp @@ -1,6 +1,6 @@ #include "AddressBook_Defs.hpp" -namespace AddressBookNS +namespace AddressBook { // const SymAddr_t INVALID_ADDRESS; @@ -51,4 +51,4 @@ int MsgTypeRecord_t::size() const -} /* namespace AddressBookNS */ +} /* namespace AddressBook */ diff --git a/Source/NameServer/AddressBook/AddressBook_Defs.hpp b/Source/NameServer/AddressBook/AddressBook_Defs.hpp index ba418aea..839a806d 100644 --- a/Source/NameServer/AddressBook/AddressBook_Defs.hpp +++ b/Source/NameServer/AddressBook/AddressBook_Defs.hpp @@ -8,7 +8,7 @@ #include #include -namespace AddressBookNS +namespace AddressBook { //---------------------------------------- @@ -55,5 +55,5 @@ struct MsgTypeRecord_t { std::vector Outputs; // Indicies of DeviceTypes that have this MessageType as an output }; -} /* namespace AddressBookNS */ +} /* namespace AddressBook */ #endif /* AddressBook_Defs_H */ diff --git a/Source/NameServer/AddressBook/AddressBook_Record.cpp b/Source/NameServer/AddressBook/AddressBook_Record.cpp index 8c410ace..0bbb5e20 100644 --- a/Source/NameServer/AddressBook/AddressBook_Record.cpp +++ b/Source/NameServer/AddressBook/AddressBook_Record.cpp @@ -1,6 +1,6 @@ #include "AddressBook_Record.hpp" -namespace AddressBookNS +namespace AddressBook { /*============================================================================== @@ -46,4 +46,4 @@ int Record_t::size() const } -} /* namespace AddressBookNS */ +} /* namespace AddressBook */ diff --git a/Source/NameServer/AddressBook/AddressBook_Record.hpp b/Source/NameServer/AddressBook/AddressBook_Record.hpp index e5809ba1..0659e1a0 100644 --- a/Source/NameServer/AddressBook/AddressBook_Record.hpp +++ b/Source/NameServer/AddressBook/AddressBook_Record.hpp @@ -3,7 +3,7 @@ #include "AddressBook_Defs.hpp" -namespace AddressBookNS +namespace AddressBook { enum RecordType_t { Device = 0, DeviceExt, External, Supervisor }; @@ -35,5 +35,5 @@ class Record_t : public RecordData_t std::string Name; // Device's canonical name. }; -} /* namespace AddressBookNS */ +} /* namespace AddressBook */ #endif /* AddressBook_Record_H */ diff --git a/Source/NameServer/AddressBook/AddressBook_Task.cpp b/Source/NameServer/AddressBook/AddressBook_Task.cpp index 387f6b87..b8fe21d3 100644 --- a/Source/NameServer/AddressBook/AddressBook_Task.cpp +++ b/Source/NameServer/AddressBook/AddressBook_Task.cpp @@ -1,6 +1,6 @@ #include "AddressBook_Task.hpp" -namespace AddressBookNS +namespace AddressBook { /*============================================================================== @@ -884,4 +884,4 @@ void TaskRecord_t::IntegSupervisors(bool Verbose, FILE * fp, unsigned long SStar } } -} /* namespace AddressBookNS */ +} /* namespace AddressBook */ diff --git a/Source/NameServer/AddressBook/AddressBook_Task.hpp b/Source/NameServer/AddressBook/AddressBook_Task.hpp index e87d0c9f..e479cb8e 100644 --- a/Source/NameServer/AddressBook/AddressBook_Task.hpp +++ b/Source/NameServer/AddressBook/AddressBook_Task.hpp @@ -29,7 +29,7 @@ #define RECOVERABLEINTEGRITY -namespace AddressBookNS +namespace AddressBook { typedef std::map IdxMap_t; @@ -138,5 +138,5 @@ class TaskRecord_t { }; -} /* namespace AddressBookNS */ +} /* namespace AddressBook */ #endif /* AddressBook_Task_H */ diff --git a/Tests/TestAddressBook.cpp b/Tests/TestAddressBook.cpp index a644e600..4890f462 100644 --- a/Tests/TestAddressBook.cpp +++ b/Tests/TestAddressBook.cpp @@ -24,24 +24,24 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") { // Create the AddressBook instance - AddressBookNS::AddressBook AddrBook - = AddressBookNS::AddressBook(std::string("AddressBookMain")); - AddressBookNS::TaskData_t taskData; + AddressBook::AddressBook AddrBook + = AddressBook::AddressBook(std::string("AddressBookMain")); + AddressBook::TaskData_t taskData; //Create a Supervisor devicetype record and add some messagetypes - AddressBookNS::DevTypeRecord_t SuperDTR("Super"); + AddressBook::DevTypeRecord_t SuperDTR("Super"); SuperDTR.InMsgs.push_back(1); SuperDTR.OuMsgs.push_back(2); //Create a Cell devicetype record and add some messagetytpes - AddressBookNS::DevTypeRecord_t CellDTR("Cell"); + AddressBook::DevTypeRecord_t CellDTR("Cell"); CellDTR.InMsgs.push_back(0); CellDTR.InMsgs.push_back(2); CellDTR.OuMsgs.push_back(0); CellDTR.OuMsgs.push_back(1); //Create a Fixed node devicetype record and add some messagetytpes - AddressBookNS::DevTypeRecord_t FixedDTR("Fixed"); + AddressBook::DevTypeRecord_t FixedDTR("Fixed"); FixedDTR.InMsgs.push_back(2); FixedDTR.OuMsgs.push_back(0); FixedDTR.OuMsgs.push_back(1); @@ -52,7 +52,7 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") // Add a task (and check that it added correctly) //========================================================================== std::string t1Name = "Task1"; - AddressBookNS::TaskData_t T1Data; + AddressBook::TaskData_t T1Data; T1Data.DeviceCount = 5; T1Data.ExternalCount = 2; @@ -70,7 +70,7 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") // Add the task to the AddressBook int t1Ret = AddrBook.AddTask(t1Name, T1Data); - REQUIRE(t1Ret == AddressBookNS::SUCCESS); + REQUIRE(t1Ret == AddressBook::SUCCESS); SECTION("Check that a task added correctly", "[Simple]") { @@ -79,14 +79,14 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") // Get the task for running tests on t1Ret = AddrBook.GetTask(t1Name, taskData); - REQUIRE(t1Ret == AddressBookNS::SUCCESS); + REQUIRE(t1Ret == AddressBook::SUCCESS); REQUIRE(taskData.Name == t1Name); // Check the task name. REQUIRE(taskData.Path == T1Data.Path); // Check the path string. REQUIRE(taskData.XML == T1Data.XML); // Check the XML string. REQUIRE(taskData.ExecutablePath == T1Data.ExecutablePath); // Check the executable path string. - REQUIRE(taskData.State == AddressBookNS::Loaded); // Check the task state. + REQUIRE(taskData.State == AddressBook::Loaded); // Check the task state. REQUIRE(taskData.DeviceTypes.size() == T1Data.DeviceTypes.size()); REQUIRE(taskData.DeviceTypes.size() == 3); // with 5 device types, @@ -109,7 +109,7 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") // Add another task //========================================================================== std::string t2Name = "Task2"; - AddressBookNS::TaskData_t T2Data; + AddressBook::TaskData_t T2Data; T2Data.DeviceCount = 5; T2Data.ExternalCount = 2; @@ -126,7 +126,7 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") // Add the task to the AddressBook int t2Ret = AddrBook.AddTask(t2Name, T2Data); - REQUIRE(t2Ret == AddressBookNS::SUCCESS); + REQUIRE(t2Ret == AddressBook::SUCCESS); SECTION("Check that a second task added correctly", "[Simple]") @@ -136,14 +136,14 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") // Get the task for running tests on t2Ret = AddrBook.GetTask(t2Name, taskData); - REQUIRE(t2Ret == AddressBookNS::SUCCESS); + REQUIRE(t2Ret == AddressBook::SUCCESS); REQUIRE(taskData.Name == t2Name); // Check the task name. REQUIRE(taskData.Path == T2Data.Path); // Check the path string. REQUIRE(taskData.XML == T2Data.XML); // Check the XML string. REQUIRE(taskData.ExecutablePath == T2Data.ExecutablePath); // Check the executable path string. - REQUIRE(taskData.State == AddressBookNS::Loaded); // Check the task state. + REQUIRE(taskData.State == AddressBook::Loaded); // Check the task state. REQUIRE(taskData.DeviceTypes.size() == T2Data.DeviceTypes.size()); REQUIRE(taskData.DeviceTypes.size() == 3); // with 5 device types, @@ -168,7 +168,7 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") SECTION("Check that a duplicate task is correctly rejected", "[Simple]") { int t3Ret = AddrBook.AddTask(t2Name, T2Data); - REQUIRE(t3Ret == AddressBookNS::ERR_TASKNAME_USED); + REQUIRE(t3Ret == AddressBook::ERR_TASKNAME_USED); REQUIRE(AddrBook.GetTaskCount() == 2); // We should have two tasks, REQUIRE(AddrBook.IntegCheck() == 0); // that pass integrity. } @@ -182,7 +182,7 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") SECTION("Check that tasks can be deleted", "[Simple]") { int delRet = AddrBook.DelTask(t2Name); - REQUIRE(delRet == AddressBookNS::SUCCESS); + REQUIRE(delRet == AddressBook::SUCCESS); REQUIRE(AddrBook.GetTaskCount() == 1); // We should have one task, REQUIRE(AddrBook.IntegCheck() == 0); // that passes integrity. } @@ -196,12 +196,12 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") AddrBook.GetTask(t1Name, taskData); // Add a supervisor - AddressBookNS::Record_t SData1; + AddressBook::Record_t SData1; SData1.Name = ""; SData1.Address = 0xFFFF0001; SData1.Rank = 5; SData1.DeviceType = 0; - SData1.RecordType = static_cast(AddressBookNS::Supervisor); + SData1.RecordType = static_cast(AddressBook::Supervisor); try { unsigned SAdd = AddrBook.AddDevice(t1Name, SData1); if (SAdd > 0) std::cerr << std::endl << "ERROR adding SData1: " << SAdd << std::endl; @@ -214,12 +214,12 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") // Add another Supervisor - AddressBookNS::Record_t SData2; + AddressBook::Record_t SData2; SData2.Name = ""; SData2.Address = 0xFFFF0002; SData2.Rank = 5; SData2.DeviceType = 0; - SData2.RecordType = static_cast(AddressBookNS::Supervisor); + SData2.RecordType = static_cast(AddressBook::Supervisor); try { unsigned SAdd = AddrBook.AddDevice(t1Name, SData2); if (SAdd > 0) std::cerr << std::endl << "ERROR adding SData2: " << SAdd << std::endl; @@ -232,11 +232,11 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") // Add an External - AddressBookNS::Record_t EData1; + AddressBook::Record_t EData1; EData1.Name = "E_0,0"; EData1.Address = 0xFFFFF001; EData1.DeviceType = 2; - EData1.RecordType = static_cast(AddressBookNS::External); + EData1.RecordType = static_cast(AddressBook::External); try { unsigned EAdd = AddrBook.AddDevice(t1Name, EData1); if (EAdd > 0) std::cerr << std::endl << "ERROR adding EData2: " << EAdd << std::endl; @@ -249,11 +249,11 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") // Setup common device data - AddressBookNS::Record_t DData1; + AddressBook::Record_t DData1; DData1.Supervisor = 0xFFFF0001; DData1.DeviceType = 1; - DData1.RecordType = static_cast(AddressBookNS::Device); - AddressBookNS::SymAddr_t BaseAddr = 0x00000000; + DData1.RecordType = static_cast(AddressBook::Device); + AddressBook::SymAddr_t BaseAddr = 0x00000000; // Add a Device @@ -340,7 +340,7 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") DData1.Address = BaseAddr++; try { unsigned DAdd = AddrBook.AddDevice(t1Name, DData1); - REQUIRE(DAdd == AddressBookNS::ERR_INVALID_DEVTYPE); + REQUIRE(DAdd == AddressBook::ERR_INVALID_DEVTYPE); } catch (const char* msg) { std::cerr << std::endl << "ERROR adding Device " << DData1.Name << " (" << DData1.Address << "): " @@ -385,12 +385,12 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") REQUIRE(AddrBook.TaskLinkValid(t1Name) == false); // and the link is invalid // Add the missing Supervisor - AddressBookNS::Record_t SData3; + AddressBook::Record_t SData3; SData3.Name = ""; SData3.Address = 0xFFFF0005; SData3.Rank = 5; SData3.DeviceType = 0; - SData3.RecordType = static_cast(AddressBookNS::Supervisor); + SData3.RecordType = static_cast(AddressBook::Supervisor); try { unsigned SAdd = AddrBook.AddDevice(t1Name, SData3); if (SAdd > 0) std::cerr << std::endl << "ERROR adding SData3: " << SAdd << std::endl; @@ -409,7 +409,7 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") #else // Otherwise it is invalid and we need to relink. REQUIRE(AddrBook.TaskLinkValid(t1Name) == false); - REQUIRE(AddrBook.BuildLink(t1Name) == AddressBookNS::SUCCESS); + REQUIRE(AddrBook.BuildLink(t1Name) == AddressBook::SUCCESS); REQUIRE(AddrBook.TaskLinkValid(t1Name) == true); // Link should now be valid #endif // Check that the rest of the task is valid @@ -445,17 +445,17 @@ TEST_CASE("AddressBook Small Tests", "[Simple]") TEST_CASE("AddressBook Large Plate Test", "[Simple]") { // Create the AddressBook instance - AddressBookNS::AddressBook AddrBook - = AddressBookNS::AddressBook(std::string("AddressBookMain")); + AddressBook::AddressBook AddrBook + = AddressBook::AddressBook(std::string("AddressBookMain")); std::string tName = "plate_1000x1000"; - AddressBookNS::TaskData_t taskData; + AddressBook::TaskData_t taskData; //========================================================================== // Create a "fake" 1000x1000 heated plate. //========================================================================== - AddressBookNS::TaskData_t TData; + AddressBook::TaskData_t TData; TData.DeviceCount = 65536; TData.ExternalCount = 1; @@ -467,31 +467,31 @@ TEST_CASE("AddressBook Large Plate Test", "[Simple]") TData.MessageTypes.push_back("Done"); //Create a Supervisor devicetype record and add some messagetypes - AddressBookNS::DevTypeRecord_t SuperDTR("Super"); + AddressBook::DevTypeRecord_t SuperDTR("Super"); SuperDTR.InMsgs.push_back(1); SuperDTR.OuMsgs.push_back(2); //Create a Cell devicetype record and add some messagetytpes - AddressBookNS::DevTypeRecord_t CellDTR("Cell"); + AddressBook::DevTypeRecord_t CellDTR("Cell"); CellDTR.InMsgs.push_back(0); CellDTR.InMsgs.push_back(2); CellDTR.OuMsgs.push_back(0); CellDTR.OuMsgs.push_back(1); //Create a Fixed node devicetype record and add some messagetytpes - AddressBookNS::DevTypeRecord_t FixedDTR("Fixed"); + AddressBook::DevTypeRecord_t FixedDTR("Fixed"); FixedDTR.InMsgs.push_back(2); FixedDTR.OuMsgs.push_back(0); FixedDTR.OuMsgs.push_back(1); //Create a Router devicetype record and add some messagetytpes - AddressBookNS::DevTypeRecord_t RouterDTR("Router"); + AddressBook::DevTypeRecord_t RouterDTR("Router"); RouterDTR.InMsgs.push_back(1); RouterDTR.OuMsgs.push_back(1); RouterDTR.OuMsgs.push_back(2); //Create a Extern devicetype record and add some messagetytpes - AddressBookNS::DevTypeRecord_t ExternDTR("Extern"); + AddressBook::DevTypeRecord_t ExternDTR("Extern"); ExternDTR.InMsgs.push_back(2); ExternDTR.OuMsgs.push_back(0); @@ -529,7 +529,7 @@ TEST_CASE("AddressBook Large Plate Test", "[Simple]") REQUIRE(taskData.XML == TData.XML); // Check the XML string. REQUIRE(taskData.ExecutablePath == TData.ExecutablePath); // Check the executable path string. - REQUIRE(taskData.State == AddressBookNS::Loaded); // Check the task state. + REQUIRE(taskData.State == AddressBook::Loaded); // Check the task state. REQUIRE(taskData.DeviceTypes.size() == TData.DeviceTypes.size()); REQUIRE(taskData.DeviceTypes.size() == 5); // with 5 device types, @@ -551,12 +551,12 @@ TEST_CASE("AddressBook Large Plate Test", "[Simple]") //========================================================================== // Add a supervisor //========================================================================== - AddressBookNS::Record_t SData1; + AddressBook::Record_t SData1; SData1.Name = ""; SData1.Address = 0xFFFF0001; SData1.Rank = 5; SData1.DeviceType = 0; // SuperDTR - SData1.RecordType = static_cast(AddressBookNS::Supervisor); + SData1.RecordType = static_cast(AddressBook::Supervisor); REQUIRE(taskData.DeviceTypes.size() == 5); // with 5 device types, @@ -574,12 +574,12 @@ TEST_CASE("AddressBook Large Plate Test", "[Simple]") //========================================================================== // Add two fixed nodes //========================================================================== - AddressBookNS::Record_t FData1; + AddressBook::Record_t FData1; FData1.Name = "C_0,0"; FData1.Address = 0xFFE00000; FData1.Supervisor = 0xFFFF0001; FData1.DeviceType = 2; - FData1.RecordType = static_cast(AddressBookNS::DeviceExt); + FData1.RecordType = static_cast(AddressBook::DeviceExt); try { unsigned FAdd = AddrBook.AddDevice(tName, FData1); @@ -591,12 +591,12 @@ TEST_CASE("AddressBook Large Plate Test", "[Simple]") } - AddressBookNS::Record_t FData2; + AddressBook::Record_t FData2; FData2.Name = "C_255,255"; FData2.Address = 0xFFE00001; FData2.Supervisor = 0xFFFF0001; FData2.DeviceType = 2; - FData2.RecordType = static_cast(AddressBookNS::DeviceExt); + FData2.RecordType = static_cast(AddressBook::DeviceExt); try { unsigned FAdd = AddrBook.AddDevice(tName, FData2); @@ -612,11 +612,11 @@ TEST_CASE("AddressBook Large Plate Test", "[Simple]") //========================================================================== // Add an External //========================================================================== - AddressBookNS::Record_t EData1; + AddressBook::Record_t EData1; EData1.Name = "E_0,0"; EData1.Address = 0xFFFFF001; EData1.DeviceType = 4; - EData1.RecordType = static_cast(AddressBookNS::External); + EData1.RecordType = static_cast(AddressBook::External); try { unsigned EAdd = AddrBook.AddDevice(tName, EData1); @@ -632,12 +632,12 @@ TEST_CASE("AddressBook Large Plate Test", "[Simple]") //========================================================================== // Add 999998 Cells //========================================================================== - AddressBookNS::SymAddr_t BaseAddr = 0x00000000; + AddressBook::SymAddr_t BaseAddr = 0x00000000; - AddressBookNS::Record_t DData1; + AddressBook::Record_t DData1; DData1.Supervisor = 0xFFFF0001; DData1.DeviceType = 1; - DData1.RecordType = static_cast(AddressBookNS::Device); + DData1.RecordType = static_cast(AddressBook::Device); for (long i = 0; i < 256; i++) { @@ -683,7 +683,7 @@ TEST_CASE("AddressBook Large Plate Test", "[Simple]") REQUIRE(taskData.XML == TData.XML); // Check the XML string. REQUIRE(taskData.ExecutablePath == TData.ExecutablePath); // Check the executable path string. - REQUIRE(taskData.State == AddressBookNS::Loaded); // Check the task state. + REQUIRE(taskData.State == AddressBook::Loaded); // Check the task state. //REQUIRE(taskData.DeviceTypes.size() == TData.DeviceTypes.size()); REQUIRE(taskData.DeviceTypes.size() == 5); // with 5 device types, @@ -709,12 +709,12 @@ TEST_CASE("AddressBook Large Plate Test", "[Simple]") SECTION("Check that devices added as expected and can be found by name and address", "[Simple]") { std::string DName = "C_75,199"; // Name of a device we are going to search for - AddressBookNS::SymAddr_t DNameAddr = 0x4BC6; // and its address + AddressBook::SymAddr_t DNameAddr = 0x4BC6; // and its address std::string DAddrName = "C_1,119"; // and its name - AddressBookNS::SymAddr_t DAddr = 0x0176; // Address to search for + AddressBook::SymAddr_t DAddr = 0x0176; // Address to search for - const AddressBookNS::Record_t * DeviceRecord; // pointer to a const-qualified Device record + const AddressBook::Record_t * DeviceRecord; // pointer to a const-qualified Device record // Find device by name int a = AddrBook.FindDevice(tName, DName, DeviceRecord); From 19f86f720b7f0b67fb784be4ac7e7999e34a3363 Mon Sep 17 00:00:00 2001 From: Graeme Bragg Date: Mon, 13 Jan 2020 16:11:31 +0000 Subject: [PATCH 14/15] Adding a vector reserve in (instead of a removed resize) to ensure reallocations are avoided --- Source/NameServer/AddressBook/AddressBook.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Source/NameServer/AddressBook/AddressBook.cpp b/Source/NameServer/AddressBook/AddressBook.cpp index 216a8699..88b610b4 100644 --- a/Source/NameServer/AddressBook/AddressBook.cpp +++ b/Source/NameServer/AddressBook/AddressBook.cpp @@ -98,8 +98,14 @@ unsigned AddressBook::AddTask(const std::string &TaskName, TaskData_t &Data) really gains anything because a DevTypeRecord_t contains 2 internal vectors (which would be zero-initialised) and a resize is thus inevitable anyway when actual device types are inserted. + + GMB: The pre-allocation here saves potentially disastrous re-allocation + later - the outer vector will not be re-sized when the inner ones are as + the inner vectors are not stored in the continuous memory space of the + outer vector, so inserting the inner vectors will not cause the outer to + reallocate. Added a reserve (rather than resize) back in for expediency. */ - // Task->DevTypes.resize(Data.DeviceTypes.size()); //pre-alloc vector + Task->DevTypes.reserve(Data.DeviceTypes.size()); //pre-alloc vector std::vector *DTypes = &(Data.DeviceTypes); for(std::vector::iterator D=DTypes->begin(); D!=DTypes->end(); D++) @@ -557,7 +563,7 @@ unsigned AddressBook::AddDevice(std::string &TaskName, Record_t &DevRec, bool Va // // Reverted by GMB as this potentially means heafty rebuilding // when futzing with the data structure - the correct course of - // action if to check the task validity after adding devices and + // action is to check the task validity after adding devices and // rebuilding the link and map then if required. // //unsigned err; From 7d800d98a492d0af7efde991a099908a5e7a4eac Mon Sep 17 00:00:00 2001 From: Graeme Bragg Date: Thu, 16 Jan 2020 13:29:48 +0000 Subject: [PATCH 15/15] Address some comments --- Source/NameServer/AddressBook/AddressBook.cpp | 6 ++---- Source/NameServer/AddressBook/AddressBook.hpp | 3 ++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Source/NameServer/AddressBook/AddressBook.cpp b/Source/NameServer/AddressBook/AddressBook.cpp index 88b610b4..4b02c245 100644 --- a/Source/NameServer/AddressBook/AddressBook.cpp +++ b/Source/NameServer/AddressBook/AddressBook.cpp @@ -10,7 +10,7 @@ namespace AddressBook //Constructors AddressBook::AddressBook(std::string d) { - ABderived = d; + AddressBookDerived = d; } AddressBook::~AddressBook() @@ -367,8 +367,6 @@ unsigned AddressBook::RebuildTask(std::string &TaskName) return(ERR_TASK_NOT_FOUND); } - //TODO: test this - // Rebuild MessageType map TRec->MsgTypeMap.clear(); for(std::vector::iterator M=TRec->MsgTypes.begin(); @@ -1176,7 +1174,7 @@ void AddressBook::Dump(std::string &Name) void AddressBook::Dump(FILE * fp, std::string Name) { fprintf(fp,"AddressBook+++++++++++++++++++++++++++++++++\n"); - fprintf(fp,"ABderived (this derived process) : %s\n",ABderived.c_str()); + fprintf(fp,"AddressBookDerived (this derived process) : %s\n",AddressBookDerived.c_str()); if(Name == std::string("")) // Dump high-level task data. { diff --git a/Source/NameServer/AddressBook/AddressBook.hpp b/Source/NameServer/AddressBook/AddressBook.hpp index 8b54e47e..46eae70a 100644 --- a/Source/NameServer/AddressBook/AddressBook.hpp +++ b/Source/NameServer/AddressBook/AddressBook.hpp @@ -39,6 +39,7 @@ #include #include #include +#include @@ -143,7 +144,7 @@ class AddressBook private: TaskMap_t TaskMap; - std::string ABderived; // changed to allow multiple inheritance (from CommonBase) 14 July 2019 ADR + std::string AddressBookDerived; // changed to allow multiple inheritance (from CommonBase) 14 July 2019 ADR TaskRecord_t * FindTask(const std::string &TaskName);