Server Module development

Started by szll2010, December 09, 2010, 06:37:16 PM

Previous topic - Next topic

szll2010

Hi Victor,

Is there any sample code  for the server module development like the agent's skeleton for reference.

Victor Kirhenshtein

Hi!

There are no really working sample code like agent skeleton. I quickly trim code from one of our commercial modules - it can be used as starting point. I added comments on important parts of the code.

Best regards,
Victor

szll2010

Hi Victor,

How to construct the method in the server module to process the Agent's originated CMD(if custom define)? I read the source code and not found in the AgentConnection Class. Has it been put in the m_pMsgWaitQueue for processing by Session, for example CMD_GET_MY CONFIG.

Victor Kirhenshtein

Hi!

Yes, all custom messages comes to m_pMsgWaitQueue of AgentConnection. You can call waitForMessage in separate thread to wait for these messages and process them. For convenience, I have added new virtual methiod in AgentConnection class - processCustomMessage - which can be overriden in derived classes for processing custom messages. It will be avaiable since 1.0.9. Also, you can use CMD_TRAP message instead of custom one - then AgentConnection::onTrap will be called for each CMD_TRAP.

Best regards,
Victor

szll2010

Hi Victor,

Another question, how to use the db function in the module? I mean there are globals, like g_nDBSyntax and
g_hCoreDB . I want to add an audit log module the system using the module?

BTW, the new feature is not previewed in windows console, is the windows console deprecated?




Victor Kirhenshtein

Hi!

All DB functions located in libnxsrv in 1.0.x versions, and in separate library libnxdb in 1.1.x versions. They are defined in nxsrvapi.h (1.0.x) or nxdbapi.h (1.1.x). All functions require DB connection handle. You can either use global "default" handle (g_hCoreDB variable), or get handle from connection pool using function DBConnectionPoolAcquireConnection - this is the preferred method. Connections acquired from pool must be released with call to DBConnectionPoolReleaseConnection. Most of DB functions is straightforward. Two common patterns of usage are following:

1. Non-SELECT query: use DBQuery(handle, query); Function will return TRUE on success.

2. SELECT query: use DBSelect(handle, query); Function will return result set or NULL on failure. Then you can use DBGetNumRows(set) to get number of rows, DBGetValue(set, row, column, buffer, bufsize) (or any variations, like DBGetColumnLong) to retrieve data from set. When you finish, you must destroy result set by calling DBFreeResult(set);

In fact, there are audit log inside the server, it's just not accessible from management console. You can use server's function WriteAuditLog to add records to it.

Windows console is deprecated - I plan that 1.0.9 will be the last version with Windows management console as primary management tool. In 1.1.x branch, we are migrating to new cross-platform Java console. It is based on Eclipse, so it can be extended with plugins very easily. It's half-working already, and I hope to implement all functionality of legacy Windows console soon.

Best regards,
Victor

szll2010

Hi Victor

Can I use DBAsyncSelect function in module?  I use it in my server module, it makes server crash.

Pls advise.

Thanks.

szll2010

Hi Victor,

The DBAsyncSelect is no problem without using the StartCommandHandler to start new thread to process the command. It's very strange. The code is very simple, just a dbgprintf() and use your skeleton of module, crash with thread and ok with normal process.

BTW, the server code is the trunk's snapshot.

Best regards,   

szll2010

Hi Victor,

The thread process code of server module need to delete the message object, but in main thread  the message object will be deleted too. So could you consider a solution:
1 copy the the message pointer(msg) to another pointer
2 set the pointer (msg) to NULL
3 main thread delete msg(NULL)
4 server module is responsible to delete the msg (delete data->msg) in the pfHandler

Best regards,

Victor Kirhenshtein

Hi!

It's already implemented - if module's command handler returns NXMOD_COMMAND_ACCEPTED_ASYNC, main session processing thread will not delete message. Also, session's usage counter increased in this case, so it is guaranteed that session object passed to handler will be valid. When your module finishes async command processing, it must delete message and call method decRefCount() on session object. My code to start async command processing in the module looks like following:


typedef struct
{
void (*m_handler)(CSCPMessage *, ClientSession *);
CSCPMessage *m_msg;
ClientSession *m_session;
} PROCESSING_THREAD_DATA;

static THREAD_RESULT THREAD_CALL ProcessingThread(void *arg)
{
PROCESSING_THREAD_DATA *data = (PROCESSING_THREAD_DATA *)arg;

data->m_handler(data->m_msg, data->m_session);
delete data->m_msg;
data->m_session->decRefCount();
free(data);
return THREAD_OK;
}

static void StartCommandHandler(void (*pfHandler)(CSCPMessage *, ClientSession *),
  CSCPMessage *msg, ClientSession *session)
{
PROCESSING_THREAD_DATA *data;

data = (PROCESSING_THREAD_DATA *)malloc(sizeof(PROCESSING_THREAD_DATA));
data->m_handler = pfHandler;
data->m_msg = msg;
data->m_session = session;
ThreadCreate(ProcessingThread, 0, data);
}


and then somewhere in the command handler:


StartCommandHandler(GetSnapshot, msg, session);
return NXMOD_COMMAND_ACCEPTED_ASYNC;



Best regards,
Victor

szll2010

I've got it.

Thanks very much.

Best regards,

Szll2010