(file) Return to agent.c CVS log (file) (dir) Up to [OMI] / omi / agent

Diff for /omi/agent/agent.c between version 1.2 and 1.3

version 1.2, 2015/04/20 18:10:09 version 1.3, 2015/04/20 18:19:49
Line 23 
Line 23 
 */ */
  
 #include <protocol/protocol.h> #include <protocol/protocol.h>
 #include <base/time.h>  #include <pal/sleep.h>
 #include <provmgr/provmgr.h> #include <provmgr/provmgr.h>
 #include <base/strings.h>  #include <pal/strings.h>
 #include <base/args.h>  
 #include <base/log.h> #include <base/log.h>
 #include <base/env.h> #include <base/env.h>
 #include <base/paths.h> #include <base/paths.h>
 #include <base/getopt.h>  #include <base/omigetopt.h>
   #include <base/multiplex.h>
   #include <base/Strand.h>
   #include <pal/format.h>
 #include <sys/types.h> #include <sys/types.h>
   #include <sys/resource.h>
 #include <pwd.h> #include <pwd.h>
 #include <grp.h> #include <grp.h>
  
 #define T MI_T  STRAND_DEBUGNAME( IdleNotification );
  
 typedef struct _AgentData AgentData; typedef struct _AgentData AgentData;
  
 struct _AgentData struct _AgentData
 { {
     Protocol*   protocol;      MuxIn                   mux;
       ProtocolSocketAndBase*  protocol;
     ProvMgr     provmgr;     ProvMgr     provmgr;
     Selector    selector;     Selector    selector;
       Strand                  idleNotificationStrand;
 } ; } ;
  
 typedef struct _Options typedef struct _Options
Line 58 
Line 63 
  
 static Options s_opts; static Options s_opts;
 static const char* arg0 = 0; static const char* arg0 = 0;
 static const char HELP[] = "\  static const ZChar HELP[] = ZT("\
 Usage: %s [OPTIONS]\n\ Usage: %s [OPTIONS]\n\
 \n\ \n\
 This program starts the OMI agent.\n\ This program starts the OMI agent.\n\
Line 66 
Line 71 
 OPTIONS:\n\ OPTIONS:\n\
     --version           Print version information.\n\     --version           Print version information.\n\
     --providerdir       Find providers in this directory.\n\     --providerdir       Find providers in this directory.\n\
     --loglevel LEVEL    Set the log level (0-4).\n\      --loglevel LEVEL    Set the log level (0-5).\n\
 \n";  \n");
  
 PRINTF_FORMAT(1, 2) PRINTF_FORMAT(1, 2)
 void FUNCTION_NEVER_RETURNS err(const char* fmt, ...)  static void FUNCTION_NEVER_RETURNS err(const ZChar* fmt, ...)
 { {
       ZChar* buf = NULL;
       ZChar* buf2 = NULL;
     va_list ap;     va_list ap;
     memset(&ap, 0, sizeof(ap));      size_t buflen = PAL_MAX_PATH_SIZE;
       buf = (ZChar*) PAL_Malloc( sizeof(ZChar) * buflen * 2 );
     fprintf(stderr, "%s: ", arg0);      if (buf)
       {
           buf2 = buf + buflen;
  
           memset(&ap, 0, sizeof(ap));
     va_start(ap, fmt);     va_start(ap, fmt);
     vfprintf(stderr, fmt, ap);          Vstprintf(buf, buflen, fmt, ap);
     va_end(ap);     va_end(ap);
           Stprintf(buf2, buflen, ZT("%s: %T"), scs(arg0), buf);
   
           Ftprintf(stderr, ZT("%T\n"), buf2);
           trace_CriticalError(buf2);
  
     fputc('\n', stderr);          PAL_Free(buf);
       }
     exit(1);     exit(1);
 } }
  
 static void _ProviderCallback(Message* msg, void* callbackData)  /* enable core dump for current process */
   static void _EnableCoreDump()
 { {
       struct rlimit core_limits;
       core_limits.rlim_cur = RLIM_INFINITY;
       core_limits.rlim_max = RLIM_INFINITY;
       setrlimit(RLIMIT_CORE, &core_limits);
   }
  
     /* forward message to the other side */  void _IdleNotification_Post( _In_ Strand* self_, _In_ Message* msg)
     /*if (msg->request)  {
         msg->clientID = msg->request->clientID;*/      DEBUG_ASSERT( MI_FALSE );  // not used
   }
  
     Protocol_Send(s_data.protocol, msg);  void _IdleNotification_PostControl( _In_ Strand* self_, _In_ Message* msg)
   {
       DEBUG_ASSERT( MI_FALSE );  // not used
 } }
  
 /* Called by protocol stack to dispatch an incoming request message */  void _IdleNotification_Ack( _In_ Strand* self_ )
 static MI_Boolean _RequestCallback(  
     Protocol* protocol_,  
     Message* msg,  
     void* data)  
 { {
     //ServerCallbackData* self = (ServerCallbackData*)data;      // Nothing to do
     MI_Result r;  }
  
     MI_UNUSED(protocol_);  void _IdleNotification_Finish( _In_ Strand* self_ )
   {
       // Nothing to do
   }
  
     msg->callback = _ProviderCallback;  /*
     //msg->callbackData = self;      Object that is just used to send to agent manager BinProtocolNotification
  
     r = ProvMgr_PostMessage(&s_data.provmgr, msg->libraryName, msg);      Behavior:
       - It is created when the initial BinProtocolNotification is sent by the server
          then kept alive as long as the connection is alive.
       - Post, PostControl and Ack are not actually used
       - Shutdown:
          The objects are deleted thru the normal Strand logic once the connection is closed.
  
     if (MI_RESULT_OK != r)      Unique features and special Behavior:
     {      - If the agent is idle it will be use to post a BinProtocolNotification
         PostResultMsg* resp;         thru the many-to-one interface so there are no problem or races with
          a request being received or a response to a normal request going out
          at the same time
   */
   static StrandFT _IdleNotification_FT = {
       _IdleNotification_Post,
       _IdleNotification_PostControl,
       _IdleNotification_Ack,
       NULL,
       NULL,
       _IdleNotification_Finish,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL,
       NULL };
  
         resp = PostResultMsg_New( msg->msgID );  /* Called by mux to dispatch an incoming request message */
   static void _RequestCallback(
       _Inout_     InteractionOpenParams*    interactionParams )
   {
       DEBUG_ASSERT( NULL != interactionParams );
       DEBUG_ASSERT( NULL != interactionParams->msg );
       DEBUG_ASSERT( NULL == interactionParams->callbackData );
  
         if (!resp)      if (BinProtocolNotificationTag == interactionParams->msg->tag)
             return MI_FALSE;      {
           BinProtocolNotification* notification = (BinProtocolNotification*)interactionParams->msg;
           (void) notification; /* In case DEBUG_ASSERT is compiled out, avoid compiler warnings */
  
         resp->result = r;          DEBUG_ASSERT(BinNotificationAgentIdle == notification->type);
         Message_SetRequest(&resp->base,msg);  
         (*msg->callback)(&resp->base, msg->callbackData);  
  
         PostResultMsg_Release(resp);          Strand_Init( STRAND_DEBUG(IdleNotification) &s_data.idleNotificationStrand, &_IdleNotification_FT, 0, interactionParams );
     }     }
       else
       {
           MI_Result result;
           ProvRegEntry regentry;
           RequestMsg* request = (RequestMsg*)interactionParams->msg;
   
           DEBUG_ASSERT( Message_IsRequest(interactionParams->msg) );
  
     return MI_TRUE;          memset(&regentry, 0, sizeof(regentry));
           regentry.libraryName = request->libraryName;
           regentry.instanceLifetimeContext = request->instanceLifetimeContext;
   
           result = ProvMgr_NewRequest(&s_data.provmgr, &regentry, interactionParams );
   
           if (MI_RESULT_OK != result)
           {
               trace_Agent_ProvMgrNewRequest_Failed( result );
               Strand_FailOpenWithResult(interactionParams, result, PostResultMsg_NewAndSerialize);
           }
       }
 } }
  
 static void GetCommandLineDestDirOption( static void GetCommandLineDestDirOption(
Line 143 
Line 211 
         if (strcmp(argv[i], "--destdir") == 0)         if (strcmp(argv[i], "--destdir") == 0)
         {         {
             if (i + 1 == argc)             if (i + 1 == argc)
                 err("missing argument for --destdir option");                  err(ZT("missing argument for --destdir option"));
  
             destdir = argv[i+1];             destdir = argv[i+1];
             memmove((char*)&argv[i], (char*)&argv[i+2],             memmove((char*)&argv[i], (char*)&argv[i+2],
Line 165 
Line 233 
     if (destdir)     if (destdir)
     {     {
         if (SetPath(ID_DESTDIR, destdir) != 0)         if (SetPath(ID_DESTDIR, destdir) != 0)
             err("failed to set destdir");              err(ZT("failed to set destdir"));
     }     }
  
     *argc_ = argc;     *argc_ = argc;
Line 194 
Line 262 
             break;             break;
  
         if (r == -1)         if (r == -1)
             err("%s", state.err);              err(ZT("%s"), scs(state.err));
  
         /* Check for -h option */         /* Check for -h option */
         if (strcmp(state.opt, "-h") == 0 || strcmp(state.opt, "--help") == 0)         if (strcmp(state.opt, "-h") == 0 || strcmp(state.opt, "--help") == 0)
Line 203 
Line 271 
         }         }
         else if (strcmp(state.opt, "--version") == 0)         else if (strcmp(state.opt, "--version") == 0)
         {         {
             printf("%s: %s\n", arg0,              Tprintf(ZT("%s: %s\n"), scs(arg0),
                 CONFIG_PRODUCT "-" CONFIG_VERSION " - " CONFIG_DATE);                  scs(CONFIG_PRODUCT "-" CONFIG_VERSION " - " CONFIG_DATE));
             exit(0);             exit(0);
         }         }
         else if (strcmp(state.opt, "--providerdir") == 0)         else if (strcmp(state.opt, "--providerdir") == 0)
Line 217 
Line 285 
             MI_Uint64 x = Strtoull(state.arg, &end, 10);             MI_Uint64 x = Strtoull(state.arg, &end, 10);
  
             if (*end != '\0')             if (*end != '\0')
                 err("bad option argument for --idletimeout: %s", state.arg);              {
                   err(ZT("bad option argument for --idletimeout: %s"),
                       scs(state.arg));
               }
  
             s_opts.idletimeout = x;             s_opts.idletimeout = x;
         }         }
Line 225 
Line 296 
         {         {
             if (Log_SetLevelFromString(state.arg) != 0)             if (Log_SetLevelFromString(state.arg) != 0)
             {             {
                 err("bad option argument for %s: %s", state.opt, state.arg);                  err(ZT("bad option argument for %s: %s"),
                       scs(state.opt), scs(state.arg));
             }             }
         }         }
     }     }
 } }
  
 static void _EventCallback(  static void _OnCloseCallback(
     Protocol* protocol,      _In_        void*       object)
     ProtocolEvent event,  
     void* data)  
 { {
     MI_UNUSED(protocol);      MI_UNUSED(object);
     MI_UNUSED(event);  
     MI_UNUSED(data);  
  
     LOGI_CHAR(("disconnected form server; exiting"));      trace_Agent_DisconnectedFromServer();
     exit(0);      Selector_StopRunning(&s_data.selector);
 } }
  
 static void _ProvMgrCallbackOnIdle( static void _ProvMgrCallbackOnIdle(
Line 253 
Line 321 
     MI_UNUSED(mgr);     MI_UNUSED(mgr);
     MI_UNUSED(callbackData);     MI_UNUSED(callbackData);
  
     LOGI_CHAR(("sending 'agent-idle' notification to the server"));      DEBUG_ASSERT( s_data.idleNotificationStrand.info.opened );
   
       trace_Agent_SendingIdleNotification();
  
     notification = BinProtocolNotification_New( BinNotificationAgentIdle );     notification = BinProtocolNotification_New( BinNotificationAgentIdle );
  
     if (!notification)     if (!notification)
       {
           // Nothing we can do here
           DEBUG_ASSERT( MI_FALSE );
         return;         return;
       }
  
     Protocol_Send(s_data.protocol, &notification->base);      // Call on the always opened idle notification strand
       Strand_SchedulePost( &s_data.idleNotificationStrand, &notification->base);
  
     BinProtocolNotification_Release(notification);     BinProtocolNotification_Release(notification);
 } }
Line 275 
Line 350 
  
     memset(&s_data, 0, sizeof(s_data));     memset(&s_data, 0, sizeof(s_data));
  
       /* Enable core dump */
       _EnableCoreDump();
   
     /* Get --destdir option first (other options may depend on it) */     /* Get --destdir option first (other options may depend on it) */
     GetCommandLineDestDirOption(&argc, argv);     GetCommandLineDestDirOption(&argc, argv);
  
Line 284 
Line 362 
     /* Print help */     /* Print help */
     if (s_opts.help)     if (s_opts.help)
     {     {
         fprintf(stderr, HELP, arg0);          Ftprintf(stderr, HELP, scs(arg0));
         exit(1);         exit(1);
     }     }
  
     /* extract socket number */     /* extract socket number */
     if (argc < 3)     if (argc < 3)
     {     {
         LOGE_CHAR(("parameter is missing (fd)"));          trace_Agent_FDParameterIsMissing();
         exit(1);         exit(1);
     }     }
  
Line 303 
Line 381 
         /* Open the log file */         /* Open the log file */
         if (Log_OpenFD(logfd) != MI_RESULT_OK)         if (Log_OpenFD(logfd) != MI_RESULT_OK)
         {         {
             err("failed to attach log file to fd: %d; errno %d", logfd,              err(ZT("failed to attach log file to fd: %d; errno %d"), logfd,
                 (int)errno);                 (int)errno);
         }         }
     }     }
Line 314 
Line 392 
         Sock_Start();         Sock_Start();
  
         if(Selector_Init(&s_data.selector) != MI_RESULT_OK)         if(Selector_Init(&s_data.selector) != MI_RESULT_OK)
             err("Selector_Init() failed");              err(ZT("Selector_Init() failed"));
   
           Timer_SetSelector(&s_data.selector);
       }
   
       /* mux */
       {
           if(MuxIn_Init(&s_data.mux, _RequestCallback, NULL, _OnCloseCallback, PostResultMsg_NewAndSerialize) != MI_RESULT_OK)
               err(ZT("MuxIn_Init() failed"));
     }     }
  
     /* Create new protocol object */     /* Create new protocol object */
     {     {
         r = Protocol_New_From_Socket(          r = ProtocolSocketAndBase_New_Agent(
             &s_data.protocol,             &s_data.protocol,
             &s_data.selector,             &s_data.selector,
             fd,             fd,
             MI_FALSE,              MuxIn_Open,
             _RequestCallback,              &s_data.mux);
             0,  
             _EventCallback,  
             0);  
  
         if (r != MI_RESULT_OK)         if (r != MI_RESULT_OK)
             err("Protocol_New_Listener() failed");              err(ZT("ProtocolSocketAndBase_New_Agent() failed"));
     }     }
  
     /* Provider manager */     /* Provider manager */
Line 338 
Line 421 
         r = ProvMgr_Init(&s_data.provmgr, &s_data.selector, _ProvMgrCallbackOnIdle, &s_data, s_opts.provDir);         r = ProvMgr_Init(&s_data.provmgr, &s_data.selector, _ProvMgrCallbackOnIdle, &s_data, s_opts.provDir);
  
         if (r != MI_RESULT_OK)         if (r != MI_RESULT_OK)
             err("ProvMgr_Init() failed");              err(ZT("ProvMgr_Init() failed"));
     }     }
  
     /* idle timeout */     /* idle timeout */
Line 346 
Line 429 
     {     {
         /* convert it to usec */         /* convert it to usec */
         s_data.provmgr.idleTimeoutUsec = s_opts.idletimeout * 1000000;         s_data.provmgr.idleTimeoutUsec = s_opts.idletimeout * 1000000;
         LOGI((T("changing idle timeout to %d sec"), (int)s_opts.idletimeout));          trace_Agent_ChangingIdleTimeout(s_opts.idletimeout);
  
     }     }
  
     /* Log start up message */     /* Log start up message */
     LOGI((T("agent started; fd %d"), (int)fd));      trace_Agent_Started((int)fd);
  
     /* Run the protocol object (waiting for new messages) */     /* Run the protocol object (waiting for new messages) */
     r = Protocol_Run(s_data.protocol, TIME_NEVER);      r = Protocol_Run( &s_data.protocol->internalProtocolBase, TIME_NEVER);
  
     if (r != MI_RESULT_OK)     if (r != MI_RESULT_OK)
         err("Protocol_Run() failed (%d)", (int)r);          err(ZT("Protocol_Run() failed (%d)"), (int)r);
  
     // Destroy all global objects     // Destroy all global objects
     Selector_RemoveAllHandlers(&s_data.selector);     Selector_RemoveAllHandlers(&s_data.selector);
     Protocol_Delete(s_data.protocol);  
     Selector_Destroy(&s_data.selector);     Selector_Destroy(&s_data.selector);
       ProvMgr_Destroy(&s_data.provmgr);
       ProtocolSocketAndBase_ReadyToFinish(s_data.protocol);
  
     return 0;     return 0;
 } }


Legend:
Removed from v.1.2  
changed lines
  Added in v.1.3

ViewCVS 0.9.2