File: [OMI] / omi / agent / agent.c
(download)
Revision: 1.1,
Wed May 30 21:47:49 2012 UTC (12 years, 1 month ago) by mike
Branch: MAIN
Initial revision
|
/*
**==============================================================================
**
** Open Management Infrastructure (OMI)
**
** Copyright (c) Microsoft Corporation
**
** Licensed under the Apache License, Version 2.0 (the "License"); you may not
** use this file except in compliance with the License. You may obtain a copy
** of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
** MERCHANTABLITY OR NON-INFRINGEMENT.
**
** See the Apache 2 License for the specific language governing permissions
** and limitations under the License.
**
**==============================================================================
*/
#include <protocol/protocol.h>
#include <base/time.h>
#include <provmgr/provmgr.h>
#include <base/strings.h>
#include <base/args.h>
#include <base/log.h>
#include <base/env.h>
#include <base/paths.h>
#include <base/getopt.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#define T MI_T
typedef struct _AgentData AgentData;
struct _AgentData
{
Protocol* protocol;
ProvMgr provmgr;
Selector selector;
} ;
typedef struct _Options
{
const char* provDir;
MI_Boolean help;
MI_Uint32 idletimeout;
}
Options;
static AgentData s_data;
static Options s_opts;
static const char* arg0 = 0;
static const char HELP[] = "\
Usage: %s [OPTIONS]\n\
\n\
This program starts the OMI agent.\n\
\n\
OPTIONS:\n\
--version Print version information.\n\
--providerdir Find providers in this directory.\n\
--loglevel LEVEL Set the log level (0-4).\n\
\n";
PRINTF_FORMAT(1, 2)
void FUNCTION_NEVER_RETURNS err(const char* fmt, ...)
{
va_list ap;
memset(&ap, 0, sizeof(ap));
fprintf(stderr, "%s: ", arg0);
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
fputc('\n', stderr);
exit(1);
}
static void _ProviderCallback(Message* msg, void* callbackData)
{
/* forward message to the other side */
/*if (msg->request)
msg->clientID = msg->request->clientID;*/
Protocol_Send(s_data.protocol, msg);
}
/* Called by protocol stack to dispatch an incoming request message */
static MI_Boolean _RequestCallback(
Protocol* protocol_,
Message* msg,
void* data)
{
//ServerCallbackData* self = (ServerCallbackData*)data;
MI_Result r;
MI_UNUSED(protocol_);
msg->callback = _ProviderCallback;
//msg->callbackData = self;
r = ProvMgr_PostMessage(&s_data.provmgr, msg->libraryName, msg);
if (MI_RESULT_OK != r)
{
PostResultMsg* resp;
resp = PostResultMsg_New( msg->msgID );
if (!resp)
return MI_FALSE;
resp->result = r;
Message_SetRequest(&resp->base,msg);
(*msg->callback)(&resp->base, msg->callbackData);
PostResultMsg_Release(resp);
}
return MI_TRUE;
}
static void GetCommandLineDestDirOption(
int* argc_,
const char* argv[])
{
int argc = *argc_;
int i;
const char* destdir = NULL;
for (i = 1; i < argc; )
{
if (strcmp(argv[i], "--destdir") == 0)
{
if (i + 1 == argc)
err("missing argument for --destdir option");
destdir = argv[i+1];
memmove((char*)&argv[i], (char*)&argv[i+2],
sizeof(char*) * (argc-i-1));
argc -= 2;
}
else if (strncmp(argv[i], "--destdir=", 10) == 0)
{
destdir = argv[i] + 10;
memmove((char*)&argv[i], (char*)&argv[i+1],
sizeof(char*) * (argc-i));
argc -= 1;
}
else
i++;
}
if (destdir)
{
if (SetPath(ID_DESTDIR, destdir) != 0)
err("failed to set destdir");
}
*argc_ = argc;
}
static void GetCommandLineOptions(int* argc, const char* argv[])
{
GetOptState state = GETOPTSTATE_INITIALIZER;
const char* opts[] =
{
"-h",
"--help",
"-v",
"--version",
"--providerdir:",
"--idletimeout:",
"--loglevel:",
NULL,
};
for (;;)
{
int r = GetOpt(argc, argv, opts, &state);
if (r == 1)
break;
if (r == -1)
err("%s", state.err);
/* Check for -h option */
if (strcmp(state.opt, "-h") == 0 || strcmp(state.opt, "--help") == 0)
{
s_opts.help = MI_TRUE;
}
else if (strcmp(state.opt, "--version") == 0)
{
printf("%s: %s\n", arg0,
CONFIG_PRODUCT "-" CONFIG_VERSION " - " CONFIG_DATE);
exit(0);
}
else if (strcmp(state.opt, "--providerdir") == 0)
{
s_opts.provDir = state.arg;
}
else if (strcmp(state.opt, "--idletimeout") == 0)
{
char* end;
MI_Uint64 x = Strtoull(state.arg, &end, 10);
if (*end != '\0')
err("bad option argument for --idletimeout: %s", state.arg);
s_opts.idletimeout = x;
}
else if (strcmp(state.opt, "--loglevel") == 0)
{
if (Log_SetLevelFromString(state.arg) != 0)
{
err("bad option argument for %s: %s", state.opt, state.arg);
}
}
}
}
static void _EventCallback(
Protocol* protocol,
ProtocolEvent event,
void* data)
{
MI_UNUSED(protocol);
MI_UNUSED(event);
MI_UNUSED(data);
LOGI_CHAR(("disconnected form server; exiting"));
exit(0);
}
static void _ProvMgrCallbackOnIdle(
ProvMgr* mgr,
void* callbackData)
{
BinProtocolNotification* notification;
MI_UNUSED(mgr);
MI_UNUSED(callbackData);
LOGI_CHAR(("sending 'agent-idle' notification to the server"));
notification = BinProtocolNotification_New( BinNotificationAgentIdle );
if (!notification)
return;
Protocol_Send(s_data.protocol, ¬ification->base);
BinProtocolNotification_Release(notification);
}
int agent_main(int argc, const char* argv[])
{
MI_Result r;
Sock fd;
int logfd;
arg0 = argv[0];
memset(&s_data, 0, sizeof(s_data));
/* Get --destdir option first (other options may depend on it) */
GetCommandLineDestDirOption(&argc, argv);
/* Extract options */
GetCommandLineOptions(&argc, argv);
/* Print help */
if (s_opts.help)
{
fprintf(stderr, HELP, arg0);
exit(1);
}
/* extract socket number */
if (argc < 3)
{
LOGE_CHAR(("parameter is missing (fd)"));
exit(1);
}
fd = Strtol(argv[1], 0, 10);
logfd = Strtol(argv[2], 0, 10);
/* Attach log file */
{
/* Open the log file */
if (Log_OpenFD(logfd) != MI_RESULT_OK)
{
err("failed to attach log file to fd: %d; errno %d", logfd,
(int)errno);
}
}
/* selector */
{
/* Initialize the network */
Sock_Start();
if(Selector_Init(&s_data.selector) != MI_RESULT_OK)
err("Selector_Init() failed");
}
/* Create new protocol object */
{
r = Protocol_New_From_Socket(
&s_data.protocol,
&s_data.selector,
fd,
MI_FALSE,
_RequestCallback,
0,
_EventCallback,
0);
if (r != MI_RESULT_OK)
err("Protocol_New_Listener() failed");
}
/* Provider manager */
{
r = ProvMgr_Init(&s_data.provmgr, &s_data.selector, _ProvMgrCallbackOnIdle, &s_data, s_opts.provDir);
if (r != MI_RESULT_OK)
err("ProvMgr_Init() failed");
}
/* idle timeout */
if (s_opts.idletimeout)
{
/* convert it to usec */
s_data.provmgr.idleTimeoutUsec = s_opts.idletimeout * 1000000;
LOGI((T("changing idle timeout to %d sec"), (int)s_opts.idletimeout));
}
/* Log start up message */
LOGI((T("agent started; fd %d"), (int)fd));
/* Run the protocol object (waiting for new messages) */
r = Protocol_Run(s_data.protocol, TIME_NEVER);
if (r != MI_RESULT_OK)
err("Protocol_Run() failed (%d)", (int)r);
// Destroy all global objects
Selector_RemoveAllHandlers(&s_data.selector);
Protocol_Delete(s_data.protocol);
Selector_Destroy(&s_data.selector);
return 0;
}