It's a complete re-implementation of the original C FeeServer (see Links).
The focus of this implementation is to make the code simple and clear, and provide a simple interface for customisation of the FeeServer.
FeeServer::Main m(name, detector, dns);
_Message
(see FeeServer::MessageChannel)_Command
(see FeeServer::CommandChannel)_Acknowledge
(ses FeeServer::AcknowledgeChannel)where name is the name of the server as set in the constructor of FeeServer::Main.
The command channel provides a way for clients to send commands to the server. The command contains a header (see FeeServer::Header) followed by binary large object (BLOB) of data (see FeeServer::Command). The header contains a few pieces of information for the server to use. The meaning of the binary data depends entirely on the command send and the implementation of the server.
The acknowledge channel provides the feed back channel from the command handling. After a command is processed, this channel is updated. The channel contains a header (see FeeServer::Header) followed by binary large object (BLOB) of data (see FeeServer::Acknowledge). The meaning of the BLOB depends entirely on the command sent and the implementation of the server. The header will have the same identifier field as the processed command, and contain a status code.
The message channel provides various messages about the operations of the server (see FeeServer::Message). The type of messages that are send is configurable.
if (debug) { unsigned int mask = m.GetLogLevel(); std::cout << "Log mask: 0x" << std::hex << mask << " -> "; mask |= FeeServer::Message::Debug; std::cout << "0x" << mask << std::dec << std::endl; m.SetLogLevel(mask); }
You can simple create objects of the server command type, and then add them to the server using the member function FeeServer::Main::AddCommand.
// m.AddCommand(new UpdateServer(m)); m.AddCommand(new FeeServer::RestartServer(m)); // m.AddCommand(new FeeServer::RebootMachine(m)); // m.AddCommand(new FeeServer::ShutdownMachine(m)); m.AddCommand(new FeeServer::ExitServer(m)); m.AddCommand(new FeeServer::SetDeadband(m)); m.AddCommand(new FeeServer::GetDeadband(m)); m.AddCommand(new FeeServer::SetIssueTimeout(m)); m.AddCommand(new FeeServer::GetIssueTimeout(m)); m.AddCommand(new FeeServer::SetUpdateRate(m)); m.AddCommand(new FeeServer::GetUpdateRate(m)); m.AddCommand(new FeeServer::SetLogLevel(m)); m.AddCommand(new FeeServer::GetLogLevel(m));
namespace Examples { /** A test control engine @ingroup tests */ class TestControlEngine : public FeeServer::ControlEngine { public: /** Constructor @param m Reference to FeeServer */ TestControlEngine(FeeServer::Main& m) : FeeServer::ControlEngine(m), _int_service("INT"), _float_service("FLOAT") { m.Publish(_int_service); m.Publish(_float_service); }
The derived class should do periodic stuff in the FeeServer::ControlEngine::Start member function.
/** Start the thread */ void Start() { usleep(5); Ready(); sleep(1); while (true) { TestCancel(); int ival = int(10 * float(rand())/RAND_MAX); float fval = int(10 * float(rand())/RAND_MAX) / 10.; _int_service = ival; _float_service = fval; usleep(100000); } } //End-Start
/** Handle commands send to the control engine @param idata Input data @param isize # of valid bytes in @a idata @param odata On output, the result. @param osize On output, the # of valid bytes in @a odata @return Status code */ short Issue(const std::vector<unsigned char>& idata, size_t /*isize*/, std::vector<unsigned char>& odata, size_t& osize) { switch (idata[0]) { case 1: osize = _int_service.Size(); if (odata.size() < osize) odata.resize(osize); memcpy(&(odata[0]), &(_int_service.Value()), osize); break; case 2: osize = _float_service.Size(); if (odata.size() < osize) odata.resize(osize); memcpy(&(odata[0]), &(_float_service.Value()), osize); break; case 3: osize = 0; std::cout << "Services to monitor: " << std::endl; for (FeeServer::MonitorThread::ItemMap::iterator i = _main.MonThread().Items().begin(); i != _main.MonThread().Items().end(); i++) std::cout << "\t" << i->first << "\t" << i->second->Name() << std::endl; break; default: osize = 0; } return 0; } //End-Issue
The member function FeeServer::ControlEngine::CleanUp is called when the server exists.
/** Clean-up member function */ void CleanUp() {}
The library provides a class template (see FeeServer::ServiceT) for defining types, as well as some specialisation for common types (FeeServer::IntService, FeeServer::FloatService).
// An integer service FeeServer::IntService _int_service; // A floating point service FeeServer::FloatService _float_service; }; } //End-Example
The control engine should then be registered with the FeeServer::Main object, and we can execute the server.
Examples::TestControlEngine ce(m); m.SetCtrlEngine(ce); std::cout << "Running fee server " << std::endl; return m.Run();