| 1 | // **************************************************************************
 | 
|---|
| 2 | /** @class DimDescriptionService
 | 
|---|
| 3 | 
 | 
|---|
| 4 | @brief A DimService which broadcasts descriptions for services and commands
 | 
|---|
| 5 | 
 | 
|---|
| 6 | The DimDescriptionService creates a service with the name of the server like
 | 
|---|
| 7 | SERVER/SERVICE_DESC. This is meant in addition to the SERVICE_LIST service
 | 
|---|
| 8 | of each node to contain a description of the service and its arguments.
 | 
|---|
| 9 | 
 | 
|---|
| 10 | Assume you have created a service (or command) with the format I:2;F:1
 | 
|---|
| 11 | a valid description string would look like
 | 
|---|
| 12 | 
 | 
|---|
| 13 |    Description|int[addr]:Address range (from - to)|val[byte]:Value to be set
 | 
|---|
| 14 | 
 | 
|---|
| 15 | Description is a general description of the command or service itself,
 | 
|---|
| 16 | int and val are the names of the arguments (e.g. names of FITS columns),
 | 
|---|
| 17 | addr and byte have the meaning of a unit (e.g. unit of FITS column)
 | 
|---|
| 18 | and the text after the colon is a description of the arguments
 | 
|---|
| 19 | (e.g. comment of a FITS column). The description must not contain a
 | 
|---|
| 20 | line-break character \n.
 | 
|---|
| 21 | 
 | 
|---|
| 22 | You can omit either the name, the unit or the comment or any combination of them.
 | 
|---|
| 23 | The descriptions of the individual format strings are separated by a vertical line.
 | 
|---|
| 24 | 
 | 
|---|
| 25 | The description should contain as many descriptions as format chunks, e.g.
 | 
|---|
| 26 | 
 | 
|---|
| 27 | I:1          should contain one description chunks
 | 
|---|
| 28 | I:1;F:1      should contain two description chunks
 | 
|---|
| 29 | I:2;F:1      should contain two description chunks
 | 
|---|
| 30 | I:2;I:1;F:1  should contain three description chunks
 | 
|---|
| 31 | 
 | 
|---|
| 32 | */
 | 
|---|
| 33 | // **************************************************************************
 | 
|---|
| 34 | #include "DimDescriptionService.h"
 | 
|---|
| 35 | 
 | 
|---|
| 36 | #include <stdexcept>
 | 
|---|
| 37 | 
 | 
|---|
| 38 | #include "dis.hxx"
 | 
|---|
| 39 | 
 | 
|---|
| 40 | using namespace std;
 | 
|---|
| 41 | 
 | 
|---|
| 42 | DimService *DimDescriptionService::fService = 0;
 | 
|---|
| 43 | int         DimDescriptionService::fCount   = 0;
 | 
|---|
| 44 | std::string DimDescriptionService::fData    = "";
 | 
|---|
| 45 | 
 | 
|---|
| 46 | // --------------------------------------------------------------------------
 | 
|---|
| 47 | //
 | 
|---|
| 48 | //! When the constructor is first called, a service with the name
 | 
|---|
| 49 | //! SERVER/SERVICE_DESC is created. The server name SERVER is retrieved
 | 
|---|
| 50 | //! from DimServer::itsName. If DimServer::itsName is empty, the
 | 
|---|
| 51 | //! server name is extracted from the given name as the part before the
 | 
|---|
| 52 | //! first '/'. A string "name=format\n" is added to fData and stored
 | 
|---|
| 53 | //! in fDescription.
 | 
|---|
| 54 | //!
 | 
|---|
| 55 | //! A counter fCount for the number of instantiations is increased.
 | 
|---|
| 56 | //!
 | 
|---|
| 57 | //! @param name
 | 
|---|
| 58 | //!     The name of the service or command to be described, e.g. SERVER/COMMAND
 | 
|---|
| 59 | //!
 | 
|---|
| 60 | //! @param desc
 | 
|---|
| 61 | //!     A description string. For details see class reference
 | 
|---|
| 62 | //!
 | 
|---|
| 63 | //! @throws
 | 
|---|
| 64 | //!     If a server name couldn't be reliably determined a runtime_error
 | 
|---|
| 65 | //!     exception is thrown.
 | 
|---|
| 66 | //
 | 
|---|
| 67 | DimDescriptionService::DimDescriptionService(const std::string &name, const std::string &desc)
 | 
|---|
| 68 | {
 | 
|---|
| 69 |     string service = DimServer::itsName;
 | 
|---|
| 70 |     if (service.empty())
 | 
|---|
| 71 |     {
 | 
|---|
| 72 |         const size_t p = name.find_first_of('/');
 | 
|---|
| 73 |         if (p==string::npos)
 | 
|---|
| 74 |             throw runtime_error("Could not determine server name");
 | 
|---|
| 75 | 
 | 
|---|
| 76 |         service = name.substr(0, p);
 | 
|---|
| 77 |     }
 | 
|---|
| 78 | 
 | 
|---|
| 79 |     service += "/SERVICE_DESC";
 | 
|---|
| 80 |     if (!fService)
 | 
|---|
| 81 |         fService = new DimService(service.c_str(), const_cast<char*>(""));
 | 
|---|
| 82 | 
 | 
|---|
| 83 |     fCount++;
 | 
|---|
| 84 | 
 | 
|---|
| 85 |     fDescription = name + '=' + desc;
 | 
|---|
| 86 | 
 | 
|---|
| 87 |     if (fData.find(fDescription+'\n')!=std::string::npos)
 | 
|---|
| 88 |         return;
 | 
|---|
| 89 | 
 | 
|---|
| 90 |     fData += fDescription + '\n';
 | 
|---|
| 91 | 
 | 
|---|
| 92 |     fService->setData(const_cast<char*>(fData.c_str()));
 | 
|---|
| 93 |     fService->updateService();
 | 
|---|
| 94 | }
 | 
|---|
| 95 | 
 | 
|---|
| 96 | 
 | 
|---|
| 97 | // --------------------------------------------------------------------------
 | 
|---|
| 98 | //
 | 
|---|
| 99 | //! If fDescription is found in fData it is removed from fData.
 | 
|---|
| 100 | //! The counter fCount is decreased and fService deleted if the counter
 | 
|---|
| 101 | //! reached 0.
 | 
|---|
| 102 | //
 | 
|---|
| 103 | DimDescriptionService::~DimDescriptionService()
 | 
|---|
| 104 | {
 | 
|---|
| 105 |     const size_t pos = fData.find(fDescription+'\n');
 | 
|---|
| 106 |     if (pos!=std::string::npos)
 | 
|---|
| 107 |         fData.replace(pos, fDescription.size()+1, "");
 | 
|---|
| 108 | 
 | 
|---|
| 109 |     if (--fCount>0)
 | 
|---|
| 110 |         return;
 | 
|---|
| 111 | 
 | 
|---|
| 112 |     delete fService;
 | 
|---|
| 113 |     fService=0;
 | 
|---|
| 114 | }
 | 
|---|