I hope to get back to this soon. Life has had too many events both good and not as good that have prevented me from returning here.
I should get back to this in a week or so.
Alohawild (Michael Wild's) Website
Michael Wild's Site
I hope to get back to this soon. Life has had too many events both good and not as good that have prevented me from returning here.
I should get back to this in a week or so.
So I have created the foundation for the next work. I have managed to get all the run parameters from an XML file and loaded them into variables in main of the MCP C++ program. I had to do a little restructuring of the code as the includes for thread and time needed to be moved to the shared include as the methods in the classes used some of the same libraries.
So the main looks like this, it will not likely get much larger than this (as always the code is better spaced in the editor in AWS cloud9):
#include "mcp.cpp"
int main()
{
// Print a header of execution out
auto result = std::time(nullptr);
std::cout << "Start: Master Control Program " << std::endl;
std::cout << "Local Time: " <<
std::asctime(std::localtime(&result)) << std::endl;
// Get running values
std::string versionnumber, storedirectory, sharedirectory, UUID[10];
MCPParms ourparms("MCP.xml"); // parms for program
try {
ourparms.load();
}
catch (std::exception const& ex) {
std::cout << ex.what() << std::endl;
return (1);
}
ourparms.version(versionnumber);
// Write out version number
std::cout << "File version: " << versionnumber << std::endl;
ourparms.UUID(UUID);
ourparms.store(storedirectory);
ourparms.share(sharedirectory);
int client = ourparms.client();
std::cout << "Client " << client;
if (client == 0) {
std::cout << " Primary!";
}
std::cout << std::endl;
std::cout << "Store: " << storedirectory << std::endl;
std::cout << "Share: " << sharedirectory << std::endl;
// Start run loop for MCP
MCPRun runit(1000, storedirectory); // set wait time
runit.run();
// Close down task
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
// Shutdown
result = std::time(nullptr);
std::cout << "Exit: Master Control Program " << std::endl;
std::cout << "Local Time: " <<
std::asctime(std::localtime(&result)) << std::endl;
// Leave politely
return 0;
}
The run routine is working and now starts up a loop with 1000 millisecond wait and checks if the file in the store directory named run.xml is present, well-formed, and has a ‘run’ value of ‘Yes’. So the MCP begins to act like a master control program now as it loops until requested to a shutdown of fail-out if it cannot find the control file that allows it to run.
The run code:
MCPRun::MCPRun(int mywaittime, const std::string &mystore)
{
runfile = mystore + "/run.xml"; // put hard coding inside
storedirectory = mystore;
waittime = mywaittime;
shutdown = "Start";
return;
}
void MCPRun::run()
/*
This is the main control loop. It runs until the check becomes false. There
must be a wait long enough to not cause this to take over the system, at
least a second.
*/
{
do {
std::this_thread::sleep_for(std::chrono::milliseconds(waittime));
} while (check());
std::cout << "Ending Condition: " << shutdown << std::endl;
return;
}
bool MCPRun::check()
/*
The check opens the run.xml in the store and stops when the run value is not
"Yes" or the file is not there or malformed.
*/
{
std::string therun;
therun = "No";
try {
pt::read_xml(runfile, tree); // exceptions must be handled!
therun = tree.get("run", "No"); // no throw if not there
}
catch (std::exception const& ex) {
therun = "Fail";
shutdown = "Fail";
}
//std::cout << "Check: " << therun << std::endl;
return (therun == "Yes");
}
Well all of the work now begins to pay. Next, and I am having issues with this step, is to scan the share directory for files to process.
So I have more C++ to relearn. I had to remember how to pass by reference and update same. I reworked the code to move all the hard coding to the routine and thus hid all of it.
Here is a bit of the main now:
int main()
{
// Print a header of execution out
auto result = std::time(nullptr);
std::cout << "Start: Master Control Program " << std::endl;
std::cout << "Local Time: " <<
std::asctime(std::localtime(&result)) << std::endl;
// Get running values
std::string versionnumber, storedirectory, sharedirectory, UUID[10];
MCPParms ourparms("MCP.xml"); // parms for program
try {
ourparms.load();
}
catch (std::exception const& ex) {
std::cout << ex.what() << std::endl;
return (1);
}
ourparms.version(versionnumber);
// Write out version number
std::cout << "File version: " << versionnumber << std::endl;
ourparms.UUID(UUID);
// write out UUID of starting value
std::cout << "UUID " << UUID[0] << std::endl;
ourparms.store(storedirectory);
ourparms.share(sharedirectory);
int client = ourparms.client();
std::cout << "Client " << client;
if (client == 0) {
std::cout << " Primary!";
}
std::cout << std::endl;
std::cout << "Store: " << storedirectory << std::endl;
std::cout << "Share: " << sharedirectory << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
// Shutdown
result = std::time(nullptr);
std::cout << "Exit: Master Control Program " << std::endl;
std::cout << "Local Time: " <<
std::asctime(std::localtime(&result)) << std::endl;
// Leave politely
return 0;
}
I have left the open of the file to be a try/except as I think it would hard to handle it in the constructor. I have moved the getting of values to methods.
That code looks like this (please notice the one bit of crazy C++ code that is obscure):
void MCPParms::version(std::string &myversion)
{
myversion = this->get("mcp.version");
return;
}
void MCPParms::UUID(std::string myUUID[10])
{
myUUID[0] = this->get("UUID.0");
myUUID[1] = this->get("UUID.1");
myUUID[2] = this->get("UUID.2");
myUUID[3] = this->get("UUID.3");
myUUID[4] = this->get("UUID.4");
myUUID[5] = this->get("UUID.5");
myUUID[6] = this->get("UUID.6");
myUUID[7] = this->get("UUID.7");
myUUID[8] = this->get("UUID.8");
myUUID[9] = this->get("UUID.9");
return;
}
void MCPParms::store(std::string &mystore)
{
mystore = this->get("mcp.store");
return;
}
void MCPParms::share(std::string &myshare)
{
myshare = this->get("mcp.share");
return;
}
int MCPParms::client()
/*
You would think this would be easy. But no.
Here is the logic I used.... Broke it in steps to be clear
*/
{
std::string myclientstr = this->get("mcp.client");
int myclient = atoi(myclientstr.c_str()); // Crazy C++ code
return myclient;
}
The spacing is better in the code. I am tired of trying to align this stuff in WordPress!
So we have added the needed items to begin the next step, actually passing files. I intend to have a file appear in the share directory, process it, accept it, move it to the store directory, and send back an acknowledgment. That is the next step. I am having trouble finding a way to get a list of files in a directory and information on the files. It appears that this is not available in C++11 that I am using. I will keep digging.
We are about to step out into the interesting bits. I hope to at least have code that can see files next time.
I forgot to add that I wrote a program to create the XML file. That is how I get all the values into the file. When I get this running the file will be create once and then copied to the various systems with different client numbers.
One of the items I will need is a wait function. I am used to having one in Arduino based C and Python 3.x, but this is new in C++ from what I can see from my searches of the web. So I thought I would cover it here for a short post.
There is a boost function for thread handling that can be used to do a wait. Apparently, the compile C++11 can also handle this in the build classes. As we are using AWS’s Cloud9 development enviroment, lets use the C++11 solution.
To code this you will need an Include of chrono and thread; this code will give you a 1/2 second sleep:
std::this_thread::sleep_for(std::chrono::milliseconds(500));
Again, we have to type std:: everywhere as that is the coding standard of the day. The definition of time is also enjoying extra typing with a whopper of stt::chrono::milliseconds. That is almost reaching silly. Almost.
I have not learned the thread safe coding stuff supplied now by C++11. More to learn one of these days.
Well I thought I would take the time to cover wait.
Well, the spacing was better in my code. I have written a utility program to create the Master Control Program data, mcpmainbuild and all the other header and class files. The program just creates a new file, MCP.xml, with all of the text for the name for the program and then ten random newly minted UUID values. These will be shared with the other running copies. This allows for a cheap and easy proof of work (POW). Well here is the code, again the editor played havoc with the formatting.
int main()
{
// Print a header of execution out
auto result = std::time(nullptr);
std::cout << "Master Control Build Program " << std::endl;
std::cout << "Local Time: " <<
std::asctime(std::localtime(&result)) << std::endl;
// Define our tree of data
pt::ptree tree;
// Create program information
tree.put("mcp", "mcpmain");
tree.put("mcp.programtext", "Master Control Program");
tree.put("mcp.version", "0.0.1");
// Create ten UUID in the file
boost::uuids::random_generator generator;
boost::uuids::uuid uuid1 = generator();
tree.put("UUID.0", uuid1);
uuid1 = generator();
tree.put("UUID.1", uuid1);
uuid1 = generator();
tree.put("UUID.2", uuid1);
uuid1 = generator();
tree.put("UUID.3", uuid1);
uuid1 = generator();
tree.put("UUID.4", uuid1);
uuid1 = generator();
tree.put("UUID.5", uuid1);
uuid1 = generator();
tree.put("UUID.6", uuid1);
uuid1 = generator();
tree.put("UUID.7", uuid1);
uuid1 = generator();
tree.put("UUID.8", uuid1);
uuid1 = generator();
tree.put("UUID.9", uuid1);
pt::write_xml("MCP.xml", tree);
result = std::time(nullptr);
std::cout << "Exit: Master Control Build Program " << std::endl;
std::cout << "Local Time: " <<
std::asctime(std::localtime(&result)) << std::endl;
// Leave politely
return 0;
}
This program just declares a tree using the boost library cool code. It then builds some data in the tree. Lastly, it just writes out the UUID values. Nothing interesting really, but we need to start somewhere.
I will add another table creation for the base value of blockchain file and the run data that is different by instance. I have decided for now to allow up to ten instances of this new blockchain code. The first and master instance is zero and must always be running. It is the one that panic calls will be sent to. If this zero instance does not reply then the blockchain instances panic and shutdown. It is easier to have one instance, I think, play the primary while letting most functions be shared and passed around.
We are starting!
Once I get further we will start referring to GitHub code and not posting it here.
The run looks like this:
Running /home/ec2-user/environment/mcpbuildmain.cpp Master Control Build Program Local Time: Fri May 4 05:08:22 2018 Exit: Master Control Build Program Local Time: Fri May 4 05:08:22 2018 Process exited with code: 0