ALMA Computing Group

acsexmplLampWheelImpl.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 *    ALMA - Atacama Large Millimiter Array
00003 *    (c) European Southern Observatory, 2002
00004 *    Copyright by ESO (in the framework of the ALMA collaboration)
00005 *    and Cosylab 2002, All rights reserved
00006 *
00007 *    This library is free software; you can redistribute it and/or
00008 *    modify it under the terms of the GNU Lesser General Public
00009 *    License as published by the Free Software Foundation; either
00010 *    version 2.1 of the License, or (at your option) any later version.
00011 *
00012 *    This library is distributed in the hope that it will be useful,
00013 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015 *    Lesser General Public License for more details.
00016 *
00017 *    You should have received a copy of the GNU Lesser General Public
00018 *    License along with this library; if not, write to the Free Software
00019 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00020 *
00021 *
00022 *
00023 * "@(#) $Id: acsexmplLampWheelImpl.cpp,v 1.21 2008/10/09 08:41:11 cparedes Exp $"
00024 *
00025 * who       when      what
00026 * --------  --------  ----------------------------------------------
00027 * acaproni 2004-04-26 Creation
00028 */
00029 
00030 
00031 #include <baciDB.h>
00032 #include <maciContainerServices.h>
00033 #include <acsexmplLampWheelImpl.h>
00034 #include <expat.h>
00035 
00039 const static int MOVE_ACTION  = 0;
00040 
00041 ACE_RCSID(acsexmpl, acsexmplLampWheelImpl, "$Id: acsexmplLampWheelImpl.cpp,v 1.21 2008/10/09 08:41:11 cparedes Exp $")
00042 
00043 using namespace baci;
00044 
00046 // LampWheel
00048 
00049 LampWheel::LampWheel(
00050                      const ACE_CString &name,
00051                      maci::ContainerServices * containerServices) :
00052     CharacteristicComponentImpl(name,containerServices),
00053     m_position_sp(this),
00054     m_desc_sp(new ROstring(name+":desc", getComponent()),this),
00055     m_slots_sp(this)
00056 {
00057     // Build the full name of the component
00058     m_fullName="alma/"+name;
00059 
00060     ACS_TRACE("::LampWheel::LampWheel");
00061         
00062 }
00063 
00064 LampWheel::~LampWheel()
00065 {
00066     
00067     ACS_TRACE("::LampWheel::~LampWheel");
00068     
00069 }
00070 
00071 /* --------------------- [CDB related methods ] -------------------- */
00072 
00073 // We need to rememeber where the parser is when a char section is found
00074 // in order to store the value of each element in the right field of the
00075 // struct
00076 #define NO_TAG    0 // We are not parsing a tag
00077 #define UNDEF_TAG 0 // We are parsing a tag we do not care about
00078 #define SLOT_TAG  1 // We are parsing the Slot tag
00079 #define LAMP_TAG  2 // We are parsing the Lamp tag
00080 #define WUT_TAG   3 // We are parsing the WarmUpTime tag
00081 #define WATT_TAG  4 // We are parsing the Watt tag
00082 #define POS_TAG   5 // We are parsing the Position tag
00083 
00084 // The libexpat allows to pass a user defined data struct between the call back
00085 // to avoid using global variables.
00086 typedef struct {
00087     // We fill the field of this slot while parsing
00088     // This slot is stored into the list when the end tag
00089     // is met (</Slot>)
00090     // While some fields are optional, they are filled at the beginning
00091     // with default values
00092     SlotDescriptor slotDescr;
00093     // The tag we're parsing
00094     short actualTag;
00095     // The list of slots (it is a pointer to m_lampWheelConfiguration)
00096     std::list<SlotDescriptor>* wheelDescriptor;
00097 } ParserStruct;
00098 
00113 int  LampWheel::retrieveConfigurationFromCDB(std::list<SlotDescriptor>& config)
00114 {
00115     // Clear the list
00116     config.clear();
00117 
00118     // We need the ContainerServices in order to retrieve the DAL
00119     maci::ContainerServices* services_p=getContainerServices();
00120     if (services_p==NULL) 
00121         {
00122         ACS_SHORT_LOG((LM_ERROR,"Error getting the ContainerServices"));
00123         return 0;
00124         }
00125 
00126     // Get the DAL from the container services
00127     CDB::DAL_ptr dal_p = services_p->getCDB();
00128     if (dal_p==NULL) 
00129         {
00130         ACS_SHORT_LOG((LM_ERROR,"Error getting the CDB from the ContainerServices"));
00131         return 0;
00132         }
00133 
00134     // dao contains the xml
00135     char* dao = NULL;
00136     try
00137         {
00138         // Stores the XML into the dao string
00139         dao = dal_p->get_DAO(m_fullName.c_str());
00140         }
00141     catch(...)
00142         {
00143         ACS_SHORT_LOG((LM_ERROR,"Error getting DAO for %s",m_fullName.c_str()));
00144         return 0;
00145         }
00146 
00147     // The following line prints the whole xml file
00148     //std::cout << "DAO is: ["<< dao <<']'<<std::endl;
00149 
00150     // Parse the xml using expat
00151     // Please have a look on the libexpat documentation
00152     // for further details (http:://libexpat.souceforge.net)
00153     XML_Parser p = XML_ParserCreate(NULL);
00154     if (! p) 
00155         {
00156         ACS_SHORT_LOG((LM_ERROR,"Could not allocate memory for the parser!"));
00157         return 0;
00158         }
00159 
00160     //Connect to the parser the handler for the end and the start of a tag
00161     XML_SetElementHandler(p, start_hndl, end_hndl);
00162 
00163     // Connect the char handler
00164     XML_SetCharacterDataHandler(p,char_hndl);
00165 
00166     // A SlotDescriptor data struct is passed throurg the handlers
00167     // While parsing all the fields of the following struct will be filled
00168     // The only field that remain immutable is the pointer to the list
00169     // of slots
00170     ParserStruct commonData;
00171     commonData.wheelDescriptor=&config; 
00172     XML_SetUserData(p,&commonData);
00173 
00174     // We have all the xml in the string so we parse all the document
00175     // with just one call
00176     if (XML_Parse(p,dao,strlen(dao),TRUE)==0)
00177         {
00178         ACS_SHORT_LOG((LM_ERROR,"Error parsing!"));
00179         config.clear();
00180         }
00181     else
00182         {
00183         ACS_SHORT_LOG((LM_INFO,"XML document parsed"));
00184         }
00185 
00186     // Release the memory used by the parser
00187     XML_ParserFree(p);
00188 
00189     return config.size();
00190 }
00191 
00197 void  LampWheel::start_hndl(void* data, const XML_Char* el, const XML_Char** attr)
00198 {
00199     ParserStruct* ps =(ParserStruct*)data;
00200 
00201     // Which is the current tag?
00202     ps->actualTag=NO_TAG;
00203     if (strcmp(el,"Slot")==0) 
00204         {
00205         //Clean the struct for the new Slot the parser is beginning to read
00206         ps->slotDescr.num=0;
00207         ps->slotDescr.lampName[0]=0;
00208         ps->slotDescr.warmUpTime=0;
00209         ps->slotDescr.watt=0;
00210         ps->slotDescr.pos=0;
00211 
00212         ps->actualTag=SLOT_TAG;
00213         }
00214     else if (strcmp(el,"Lamp")==0) ps->actualTag=LAMP_TAG;
00215     else if (strcmp(el,"WarmUpTime")==0) ps->actualTag=WUT_TAG;
00216     else if (strcmp(el,"Watt")==0) ps->actualTag=WATT_TAG;
00217     else if (strcmp(el,"Position")==0) ps->actualTag=POS_TAG;
00218     else ps->actualTag=UNDEF_TAG; // We do not care of other cases
00219         
00220     // Scan the attribute and fill the fields of the descriptor
00221     // This example is quite easy because the XML has no duplicate names
00222     // for attributes ;-)
00223     for (int t=0; attr[t]; t+=2) 
00224         {
00225         if (strcmp(attr[t],"LampType")==0) strcpy(ps->slotDescr.lampName,attr[t+1]);
00226         else if (strcmp(attr[t],"SlotNumber")==0) ps->slotDescr.num=atoi(attr[t+1]);
00227         }
00228 }
00229 
00235 void  LampWheel::end_hndl(void *data, const XML_Char* el)
00236 {
00237     ParserStruct* ps =(ParserStruct*)data;
00238     // Where are not processing a tag...
00239     ps->actualTag=NO_TAG;
00240 
00241     // The Slot tag is parsed: we got a full struct now!
00242     if (ps!=NULL && strcmp(el,"Slot")==0) 
00243         {
00244         // Insert the struct into the list
00245         ps->wheelDescriptor->push_back(ps->slotDescr);
00246         }
00247     // Where are not processing a tag...
00248     ps->actualTag=NO_TAG;
00249 }
00250 
00256 void LampWheel::char_hndl(void *data, const XML_Char *s, int len)
00257 {
00258     ParserStruct* ps =(ParserStruct*)data;
00259     char temp[512];
00260     strncpy(temp,s,len);
00261     temp[len]=0;
00262     // We have to store the string in the right field as stated 
00263     // by the actualTag field
00264     //
00265     // XML schema definition guarantee that all the strings represent
00266     // numbers i.e. atoi cannot fail
00267     switch(ps->actualTag) {
00268     case WUT_TAG   : ps->slotDescr.warmUpTime=atoi(temp); break;
00269     case WATT_TAG  : ps->slotDescr.watt=atoi(temp); break;
00270     case POS_TAG : ps->slotDescr.pos=atoi(temp); break;
00271       default: break;
00272                    }
00273 }
00274 
00275 /* --------------------- [ Life cycle methods ] -------------------- */
00276 
00277  void LampWheel::initialize()
00278 {
00279     ACS_TRACE("::LampWheel::initialize");
00280 
00281     m_position_sp=new ROdouble(getContainerServices()->getName()+":position", getComponent());
00282     // Position is 0 at the beginning
00283     ACS::Time timestamp;
00284     m_position_sp->getDevIO()->write(0.0, timestamp);
00285 
00286     // There are two ways to get an attribute of the component
00287     // 1. from the DAO of the component 
00288     //    (shown for the LampWheelDescription attribute)
00289     // 2. using the get_characteristic method
00290     //    (shown for the AvailableSlots attribute)
00291     // We'll show boths
00292 
00293     // 1
00294     // Get the description of this lamp wheel from the xml file
00295     // It is an attribute of the component
00296     CDB::DAL_ptr dal_p = getContainerServices()->getCDB();
00297     CDB::DAO_ptr dao_p = dal_p->get_DAO_Servant(m_fullName.c_str());
00298     char* descr=NULL;
00299     try 
00300         {
00301         descr = dao_p->get_string("LampWheelDescription");
00302         } 
00303     catch (...) 
00304         {
00305         // We receive an error from the CDB 
00306         // maybe a WrongDataType or a FieldDoesNotExist exception
00307         descr=NULL;
00308         ACS_SHORT_LOG((LM_ERROR,"Error reading LampWheel Description from the CDB"));
00309         }
00310     if (descr!=NULL) {
00311         m_desc_sp->getDevIO()->write(descr, timestamp);
00312     } 
00313 
00314     // 2
00315     // Get the number of available slots from the CDB
00316     // It is an attribute of the component
00317     m_slots_sp=new ROlong(getContainerServices()->getName()+":slots", getComponent());
00318     try 
00319         {
00320         CORBA::Any* characteristic = get_characteristic_by_name("AvailableSlots");
00321         const char* val;
00322         if (!(*characteristic>>=val))
00323             {
00324             ACS_SHORT_LOG((LM_ERROR,"Error getting AvailableSlots value by the CORBA::Any object"));
00325             }
00326         else
00327             {
00328             // Convert the string
00329             long availSlots=atoi(val);
00330             m_slots_sp->getDevIO()->write(availSlots, timestamp);
00331             }
00332         }
00333     catch (...)
00334         {
00335         // An error occurred reading the characteristic
00336         // This method throws ACS::NoSuchCharacteristic
00337         ACS_SHORT_LOG((LM_ERROR,"Error reading the characteristic AvailableSlots by its name"));
00338         }
00339 
00340 }
00341 
00342  void LampWheel::execute() 
00343 {
00344     ACS_TRACE("::LampWheel::execute");
00345     // Read the actual configuration from the CDB
00346     //
00347     // There is no meaning in reading the configuration from the CDB
00348     // if we had an error before but this is only an example...
00349     int size=retrieveConfigurationFromCDB(m_lampWheelConfiguration);
00350     ACS_SHORT_LOG((LM_ERROR,"%d slots found",size));
00351 
00352 }
00353 
00354 void LampWheel::cleanUp()
00355 {
00356     // Empty the list
00357     m_lampWheelConfiguration.clear();
00358 
00359 }
00360 
00361 void LampWheel::aboutToAbort()
00362 {
00363 }
00364 
00365 /* --------------- [ Action implementator interface ] -------------- */
00366 
00367 ActionRequest 
00368 LampWheel::invokeAction (int function,
00369                     BACIComponent *cob_p, 
00370                     const int &callbackID, 
00371                     const CBDescIn &descIn, 
00372                     BACIValue *value_p, 
00373                     Completion &completion, 
00374                     CBDescOut &descOut) 
00375 {
00376     ACS_SHORT_LOG((LM_INFO,"LampWheel::invokeAction"));
00377     
00378     // better implementation with array is possible
00379     switch (function) 
00380         {
00381         case MOVE_ACTION:
00382           {
00383           ACS_SHORT_LOG((LM_INFO,"LampWheel::invokeAction call moveAction"));
00384           return moveAction(cob_p, callbackID, descIn, value_p, completion, descOut);
00385           }
00386         default:
00387           {
00388           return reqDestroy;
00389           }
00390         }
00391 }
00392 
00393 /* ------------------ [ Action implementations ] ----------------- */
00394 
00395 
00397 ActionRequest 
00398 LampWheel::moveAction (BACIComponent *cob_p, 
00399                 const int &callbackID,
00400                 const CBDescIn &descIn, 
00401                 BACIValue *value_p,
00402                 Completion &completion, 
00403                 CBDescOut &descOut)
00404 {
00405     ACS_SHORT_LOG((LM_INFO,"::LampWheel::moveAction", "%s", getComponent()->getName()));
00406 
00407     int* slot_p = static_cast<int *>(const_cast<void *>(value_p->pointerValue()));
00408 
00409     // The user wish to move the wheel to a defined slot.
00410     // We look for the slot in the list of slots to retrieve the
00411     // position to rotate the wheel to
00412     std::list<SlotDescriptor>::iterator iter;
00413     bool found=false;
00414     for (iter=m_lampWheelConfiguration.begin(); iter!=m_lampWheelConfiguration.end(); ++iter) 
00415         {
00416         if ((int)iter->num==*slot_p) 
00417             {
00418             // The requested slot is on the list:
00419             // the wheel rotates to the position specified in the CDB 
00420             ACS::Time timestamp;
00421             m_position_sp->getDevIO()->write(iter->pos, timestamp);
00422             ACS_SHORT_LOG((LM_INFO,"Wheel moved to %d (using %s lamp, watt=%d)",
00423                            iter->pos,
00424                            iter->lampName,
00425                            iter->watt));
00426             found=true;
00427             break;
00428             }
00429         }
00430     if (!found) 
00431         {
00432         ACS_SHORT_LOG((LM_ERROR,"The slot %d is not defined in the CDB",*slot_p));
00433         }
00434     
00435     DBConnector::writeCommand(getComponent()->getName(), "move", getStringifiedTimeStamp());
00436     
00437     completion = ACSErrTypeOK::ACSErrOKCompletion();
00438 
00439     // if OK action will be destroyed and we do not need it anymore
00440     if (slot_p!=0) 
00441         {
00442         delete slot_p;
00443         slot_p=0;
00444         }
00445     
00446     // complete action requesting done invocation, 
00447     // otherwise return reqInvokeWorking and set descOut.estimated_timeout
00448     return reqInvokeDone;
00449 }
00450 
00451 /* --------------------- [ CORBA interface ] ----------------------*/
00452 
00453 void LampWheel::move(CORBA::Short slot, ACS::CBvoid_ptr cb,  const ACS::CBDescIn& desc) 
00454 {
00455     int* param_p= new int;
00456     *param_p=slot;
00457     
00458     ACS_SHORT_LOG((LM_INFO,"LampWheel::Move to slot %d",*param_p));
00459     getComponent()->registerAction(BACIValue::type_null, cb, desc, this, MOVE_ACTION, BACIValue(param_p));
00460 }
00461 
00462 ACS::ROdouble_ptr
00463 LampWheel::position ()
00464 {
00465     if (m_position_sp == 0)
00466         {
00467         return ACS::ROdouble::_nil();
00468         }
00469 
00470     ACS::ROdouble_var prop = ACS::ROdouble::_narrow(m_position_sp->getCORBAReference());
00471     return prop._retn();
00472 }
00473 
00474 ACS::ROstring_ptr
00475 LampWheel::desc ()
00476 {
00477     if (m_desc_sp == 0)
00478         {
00479         return ACS::ROstring::_nil();
00480         }
00481 
00482     ACS::ROstring_var prop = ACS::ROstring::_narrow(m_desc_sp->getCORBAReference());
00483     return prop._retn();
00484 }
00485 
00486 ACS::ROlong_ptr
00487 LampWheel::slots ()
00488 {
00489     if (m_slots_sp == 0)
00490         {
00491         return ACS::ROlong::_nil();
00492         }
00493 
00494     ACS::ROlong_var prop = ACS::ROlong::_narrow(m_slots_sp->getCORBAReference());
00495     return prop._retn();
00496 }
00497 
00498 /* --------------- [ MACI DLL support functions ] -----------------*/
00499 #include <maciACSComponentDefines.h>
00500 MACI_DLL_SUPPORT_FUNCTIONS(LampWheel)
00501 /* ----------------------------------------------------------------*/
00502 
00503