Merge lp:~mshankar/epics-base/softioclogging into lp:~epics-core/epics-base/3.15

Proposed by Andrew Johnson
Status: Merged
Merged at revision: 12239
Proposed branch: lp:~mshankar/epics-base/softioclogging
Merge into: lp:~epics-core/epics-base/3.15
Diff against target: 365 lines (+245/-14)
5 files modified
documentation/RELEASE_NOTES.html (+10/-0)
src/libCom/iocsh/libComRegister.c (+10/-0)
src/libCom/log/logClient.c (+59/-13)
src/libCom/log/logClient.h (+1/-0)
src/libCom/test/epicsErrlogTest.c (+165/-1)
To merge this branch: bzr merge lp:~mshankar/epics-base/softioclogging
Reviewer Review Type Date Requested Status
Andrew Johnson Approve
Review via email: mp+72816@code.launchpad.net

Description of the change

Codeathon: Add logClientPrefix command and functionality.
This branch includes code, tests and release notes.
AppDevGuide entry also supplied separately.

To post a comment you must log in.
Revision history for this message
Andrew Johnson (anj) wrote :

A few minor things which I will correct while merging:

* This code uses C++ comments in C files (which GCC accepts, but some compilers don't).
* The test code uses status values which are not related to the code being tested as test pass/fail results.
* New release note entries go at the top of the file, not the bottom.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'documentation/RELEASE_NOTES.html'
--- documentation/RELEASE_NOTES.html 2011-08-23 23:19:55 +0000
+++ documentation/RELEASE_NOTES.html 2011-08-25 00:35:04 +0000
@@ -280,5 +280,15 @@
280Removed the 3.13 <top>/config directory and build compatibility rules and280Removed the 3.13 <top>/config directory and build compatibility rules and
281variables, and various conversion documents.</p>281variables, and various conversion documents.</p>
282282
283<h3>
284Added support for iocLogPrefix</h3>
285
286<p>
287Added a <code>iocLogPrefix</code> command to <code>ioCsh</code>. This establishes a prefix that will be
288common to all log messages as they are sent to the iocLogServer. This lets us use the
289"fac=&lt;<i>facility</i>&gt;" syntax for displaying the facility, process name etc. in log viewers like the
290<code>cmlogviewer<code>.
291</p>
292
283</body>293</body>
284</html>294</html>
285295
=== modified file 'src/libCom/iocsh/libComRegister.c'
--- src/libCom/iocsh/libComRegister.c 2010-05-03 22:26:41 +0000
+++ src/libCom/iocsh/libComRegister.c 2011-08-25 00:35:04 +0000
@@ -191,6 +191,15 @@
191 errlogPrintfNoConsole("%s\n", args[0].sval);191 errlogPrintfNoConsole("%s\n", args[0].sval);
192}192}
193193
194/* iocLogPrefix */
195static const iocshArg iocLogPrefixArg0 = { "prefix",iocshArgString};
196static const iocshArg * const iocLogPrefixArgs[1] = {&iocLogPrefixArg0};
197static const iocshFuncDef iocLogPrefixFuncDef = {"iocLogPrefix",1,iocLogPrefixArgs};
198static void iocLogPrefixCallFunc(const iocshArgBuf *args)
199{
200 iocLogPrefix(args[0].sval);
201}
202
194/* epicsThreadShowAll */203/* epicsThreadShowAll */
195static const iocshArg epicsThreadShowAllArg0 = { "level",iocshArgInt};204static const iocshArg epicsThreadShowAllArg0 = { "level",iocshArgInt};
196static const iocshArg * const epicsThreadShowAllArgs[1] = {&epicsThreadShowAllArg0};205static const iocshArg * const epicsThreadShowAllArgs[1] = {&epicsThreadShowAllArg0};
@@ -355,6 +364,7 @@
355 iocshRegister(&errlogInitFuncDef,errlogInitCallFunc);364 iocshRegister(&errlogInitFuncDef,errlogInitCallFunc);
356 iocshRegister(&errlogInit2FuncDef,errlogInit2CallFunc);365 iocshRegister(&errlogInit2FuncDef,errlogInit2CallFunc);
357 iocshRegister(&errlogFuncDef, errlogCallFunc);366 iocshRegister(&errlogFuncDef, errlogCallFunc);
367 iocshRegister(&iocLogPrefixFuncDef, iocLogPrefixCallFunc);
358368
359 iocshRegister(&epicsThreadShowAllFuncDef,epicsThreadShowAllCallFunc);369 iocshRegister(&epicsThreadShowAllFuncDef,epicsThreadShowAllCallFunc);
360 iocshRegister(&threadFuncDef, threadCallFunc);370 iocshRegister(&threadFuncDef, threadCallFunc);
361371
=== modified file 'src/libCom/log/logClient.c'
--- src/libCom/log/logClient.c 2009-07-09 16:37:24 +0000
+++ src/libCom/log/logClient.c 2011-08-25 00:35:04 +0000
@@ -58,6 +58,11 @@
58static const double LOG_SERVER_SHUTDOWN_TIMEOUT = 30.0; /* sec */58static const double LOG_SERVER_SHUTDOWN_TIMEOUT = 30.0; /* sec */
5959
60/*60/*
61 * The logClientPrefix stores a prefix that is sent as a prefix for all log messages.
62 */
63static char* logClientPrefix = NULL;
64
65/*
61 * logClientClose ()66 * logClientClose ()
62 */67 */
63static void logClientClose ( logClient *pClient )68static void logClientClose ( logClient *pClient )
@@ -160,21 +165,13 @@
160}165}
161166
162/* 167/*
163 * logClientSend ()168 * private method with code refactored out of logClientSend.
169 * This method relies on the mutex being obtained on pClient->mutex (which happens in logClientSend prior to this method being called)
164 */170 */
165void epicsShareAPI logClientSend ( logClientId id, const char * message )171static void sendLogMessageinChunks(logClient * pClient, const char * message) {
166{
167 logClient * pClient = ( logClient * ) id;
168 unsigned strSize;172 unsigned strSize;
169173
170 if ( ! pClient || ! message ) {
171 return;
172 }
173
174 strSize = strlen ( message );174 strSize = strlen ( message );
175
176 epicsMutexMustLock ( pClient->mutex );
177
178 while ( strSize ) {175 while ( strSize ) {
179 unsigned msgBufBytesLeft = 176 unsigned msgBufBytesLeft =
180 sizeof ( pClient->msgBuf ) - pClient->nextMsgIndex;177 sizeof ( pClient->msgBuf ) - pClient->nextMsgIndex;
@@ -231,10 +228,31 @@
231 break;228 break;
232 }229 }
233 }230 }
234 231}
232
233
234/*
235 * logClientSend ()
236 */
237void epicsShareAPI logClientSend ( logClientId id, const char * message )
238{
239 logClient * pClient = ( logClient * ) id;
240
241 if ( ! pClient || ! message ) {
242 return;
243 }
244
245 epicsMutexMustLock ( pClient->mutex );
246
247 if(logClientPrefix) {
248 sendLogMessageinChunks(pClient, logClientPrefix);
249 }
250 sendLogMessageinChunks(pClient, message);
251
235 epicsMutexUnlock (pClient->mutex);252 epicsMutexUnlock (pClient->mutex);
236}253}
237254
255
238void epicsShareAPI logClientFlush ( logClientId id )256void epicsShareAPI logClientFlush ( logClientId id )
239{257{
240 logClient * pClient = ( logClient * ) id;258 logClient * pClient = ( logClient * ) id;
@@ -553,5 +571,33 @@
553 pClient->sock==INVALID_SOCKET?"INVALID":"OK",571 pClient->sock==INVALID_SOCKET?"INVALID":"OK",
554 pClient->connectCount);572 pClient->connectCount);
555 }573 }
556}574
575 if(logClientPrefix) {
576 printf ("log client: a log prefix has been set \"%s\"\n", logClientPrefix);
577 }
578}
579
580/*
581 * iocLogPrefix()
582 **/
583void epicsShareAPI iocLogPrefix(const char* prefix)
584{
585 // If we have already established a log prefix, do not let the user change it
586 // Note iocLogPrefix is expected to be set in the cmd file during initialization.
587 // We do not anticipate changing this after it has been set
588 if(logClientPrefix) {
589 printf ("log client: a log prefix has already been established \"%s\". Ignoring this call \n", logClientPrefix);
590 return;
591 }
592
593 if(prefix) {
594 unsigned prefixLen = strlen(prefix);
595 if(prefixLen > 0) {
596 char* localCopy = malloc(prefixLen+1);
597 strcpy(localCopy, prefix);
598 logClientPrefix = localCopy;
599 }
600 }
601}
602
557603
558604
=== modified file 'src/libCom/log/logClient.h'
--- src/libCom/log/logClient.h 2005-11-22 00:28:17 +0000
+++ src/libCom/log/logClient.h 2011-08-25 00:35:04 +0000
@@ -33,6 +33,7 @@
33epicsShareFunc void epicsShareAPI logClientSend (logClientId id, const char *message);33epicsShareFunc void epicsShareAPI logClientSend (logClientId id, const char *message);
34epicsShareFunc void epicsShareAPI logClientShow (logClientId id, unsigned level);34epicsShareFunc void epicsShareAPI logClientShow (logClientId id, unsigned level);
35epicsShareFunc void epicsShareAPI logClientFlush (logClientId id);35epicsShareFunc void epicsShareAPI logClientFlush (logClientId id);
36epicsShareFunc void epicsShareAPI iocLogPrefix(const char* prefix);
3637
37/* deprecated interface; retained for backward compatibility */38/* deprecated interface; retained for backward compatibility */
38/* note: implementations are in iocLog.c, not logClient.c */39/* note: implementations are in iocLog.c, not logClient.c */
3940
=== modified file 'src/libCom/test/epicsErrlogTest.c'
--- src/libCom/test/epicsErrlogTest.c 2011-03-01 21:03:33 +0000
+++ src/libCom/test/epicsErrlogTest.c 2011-08-25 00:35:04 +0000
@@ -22,6 +22,11 @@
22#include "errlog.h"22#include "errlog.h"
23#include "epicsUnitTest.h"23#include "epicsUnitTest.h"
24#include "testMain.h"24#include "testMain.h"
25#include "iocLog.h"
26#include "logClient.h"
27#include "envDefs.h"
28#include "osiSock.h"
29#include "fdmgr.h"
2530
26#define LOGBUFSIZE 204831#define LOGBUFSIZE 2048
2732
@@ -75,6 +80,27 @@
75 int jam;80 int jam;
76} clientPvt;81} clientPvt;
7782
83static void testLogPrefix(void);
84static void acceptNewClient( void *pParam );
85static void readFromClient( void *pParam );
86static void testPrefixLogandCompare( const char* logmessage);
87
88static void *pfdctx;
89static SOCKET sock;
90static SOCKET insock;
91
92static const char* prefixactualmsg[]= {
93 "A message without prefix",
94 "A message with prefix",
95 "DONE"
96 };
97static const char prefixexpectedmsg[] = "A message without prefix"
98 "fac=LI21 A message with prefix"
99 "fac=LI21 DONE"
100 ;
101static char prefixmsgbuffer[1024];
102
103
78static104static
79void logClient(void* raw, const char* msg)105void logClient(void* raw, const char* msg)
80{106{
@@ -115,7 +141,7 @@
115 char msg[256];141 char msg[256];
116 clientPvt pvt, pvt2;142 clientPvt pvt, pvt2;
117143
118 testPlan(25);144 testPlan(35);
119145
120 strcpy(msg, truncmsg);146 strcpy(msg, truncmsg);
121147
@@ -289,5 +315,143 @@
289 /* Clean up */315 /* Clean up */
290 errlogRemoveListener(&logClient);316 errlogRemoveListener(&logClient);
291317
318 testLogPrefix();
319
292 return testDone();320 return testDone();
293}321}
322/*
323 * Tests the log prefix code
324 * Since the log prefix is only applied to log messages as they are going out on the socket,
325 * we need to create a server listening on a port, accept connections etc.
326 * This code is a reduced version of the code in iocLogServer.
327 */
328static void testLogPrefix(void) {
329 struct sockaddr_in serverAddr;
330 int status;
331 struct timeval timeout;
332 struct sockaddr_in actualServerAddr;
333 osiSocklen_t actualServerAddrSize;
334
335
336 testDiag("Testing iocLogPrefix");
337
338 timeout.tv_sec = 5; /* in seconds */
339 timeout.tv_usec = 0;
340
341 memset((void*)prefixmsgbuffer, 0, sizeof prefixmsgbuffer);
342
343 /* Clear "errlog: <n> messages were discarded" status */
344 errlogPrintfNoConsole(".");
345 errlogFlush();
346
347 sock = epicsSocketCreate(AF_INET, SOCK_STREAM, 0);
348 testOk1(sock != INVALID_SOCKET);
349
350 // We listen on a an available port.
351 memset((void *)&serverAddr, 0, sizeof serverAddr);
352 serverAddr.sin_family = AF_INET;
353 serverAddr.sin_port = htons(0);
354
355 status = bind (sock,
356 (struct sockaddr *)&serverAddr,
357 sizeof (serverAddr) );
358 testOk1(status >= 0);
359
360 status = listen(sock, 10);
361 testOk1(status >= 0);
362
363 // Determine the port that the OS chose
364 actualServerAddrSize = sizeof actualServerAddr;
365 memset((void *)&actualServerAddr, 0, sizeof serverAddr);
366 status = getsockname(sock, (struct sockaddr *) &actualServerAddr, &actualServerAddrSize);
367 testOk1(status >= 0);
368
369 char portstring[16];
370 sprintf(portstring, "%d", ntohs(actualServerAddr.sin_port));
371 testDiag("Listening on port %s", portstring);
372
373 // Set the EPICS environment variables for logging.
374 epicsEnvSet ( "EPICS_IOC_LOG_INET", "localhost" );
375 epicsEnvSet ( "EPICS_IOC_LOG_PORT", portstring );
376
377 pfdctx = (void *) fdmgr_init();
378 testOk1(pfdctx != NULL);
379
380 status = fdmgr_add_callback(
381 pfdctx,
382 sock,
383 fdi_read,
384 acceptNewClient,
385 &serverAddr);
386 testOk1(status >= 0);
387
388 status = iocLogInit ();
389 testOk1(status >= 0);
390 fdmgr_pend_event(pfdctx, &timeout);
391
392 testPrefixLogandCompare(prefixactualmsg[0]);
393
394 iocLogPrefix("fac=LI21 ");
395 testPrefixLogandCompare(prefixactualmsg[1]);
396 testPrefixLogandCompare(prefixactualmsg[2]);
397
398 close(sock);
399}
400
401static void testPrefixLogandCompare( const char* logmessage ) {
402 struct timeval timeout;
403 timeout.tv_sec = 5; /* in seconds */
404 timeout.tv_usec = 0;
405
406 errlogPrintfNoConsole(logmessage);
407 errlogFlush();
408 iocLogFlush();
409 fdmgr_pend_event(pfdctx, &timeout);
410}
411
412static void acceptNewClient ( void *pParam )
413{
414 osiSocklen_t addrSize;
415 struct sockaddr_in addr;
416 int status;
417
418 addrSize = sizeof ( addr );
419 insock = epicsSocketAccept ( sock, (struct sockaddr *)&addr, &addrSize );
420 testOk1(insock!=INVALID_SOCKET && addrSize >= sizeof (addr) );
421
422 status = fdmgr_add_callback(
423 pfdctx,
424 insock,
425 fdi_read,
426 readFromClient,
427 NULL);
428 testOk1(status >= 0);
429}
430
431static void readFromClient(void *pParam)
432{
433 char recvbuf[1024];
434 int recvLength;
435
436 memset(&recvbuf, 0, 1024);
437 recvLength = recv(insock,
438 &recvbuf,
439 1024,
440 0);
441 if (recvLength > 0) {
442 strcat(prefixmsgbuffer, recvbuf);
443
444 // If we have received all of the messages.
445 if(strstr(prefixmsgbuffer, "DONE") != NULL) {
446 int prefixcmp = strncmp(prefixexpectedmsg, prefixmsgbuffer, strlen(prefixexpectedmsg));
447 if(prefixcmp != 0) {
448 printf("Expected %s\n", prefixexpectedmsg);
449 printf("Obtained %s\n", prefixmsgbuffer);
450 }
451
452 testOk1(prefixcmp == 0);
453 }
454 }
455}
456
457

Subscribers

People subscribed via source and target branches