OSSP CVS Repository

ossp - Difference in ossp-pkg/l2/l2_ch_buffer.c versions 1.21 and 1.22
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [History

ossp-pkg/l2/l2_ch_buffer.c 1.21 -> 1.22

--- l2_ch_buffer.c       2001/09/14 07:41:49     1.21
+++ l2_ch_buffer.c       2001/10/05 10:40:17     1.22
@@ -28,18 +28,30 @@
 */
 
 #include "l2.h"
+#include "l2_p.h"   /* for TRACE() */
 
 #include <string.h>
+#include <unistd.h> /* has setitime() in standard unix functions */
+#include <signal.h> /* for use of sigaction() and SIGALRM        */
 
 /* declare private channel configuration */
 typedef struct {
     char       *buf;
     int         bufpos;
     int         bufsize;
+    int         bufinterval;
+    struct      sigaction sigalrm;
+    struct      itimerval valprev;
     int         levelflush;
     l2_level_t  level;
 } l2_ch_buffer_t;
 
+static void catchsignal(int sig, ...)
+{
+    if (sig == SIGALRM)
+        TRACE("SIGALRM caught");
+}
+
 /* create channel */
 static l2_result_t hook_create(l2_context_t *ctx, l2_channel_t *ch)
 {
@@ -50,11 +62,14 @@
         return L2_ERR_MEM;
 
     /* initialize configuration with reasonable defaults */
-    cfg->buf        = NULL;
-    cfg->bufpos     = 0;
-    cfg->bufsize    = 4096;
-    cfg->levelflush = 0;
-    cfg->level      = L2_LEVEL_NONE;
+    cfg->buf         = NULL;
+    cfg->bufpos      = 0;
+    cfg->bufsize     = 4096;
+    cfg->bufinterval = 0;
+    cfg->levelflush  = 0;
+    cfg->level       = L2_LEVEL_NONE;
+    memset(&cfg->sigalrm, 0, sizeof(cfg->sigalrm));
+    memset(&cfg->valprev, 0, sizeof(cfg->valprev));
 
     /* link private channel configuration into channel context */
     ctx->vp = cfg;
@@ -66,13 +81,14 @@
 static l2_result_t hook_configure(l2_context_t *ctx, l2_channel_t *ch, const char *fmt, va_list ap)
 {
     l2_ch_buffer_t *cfg = (l2_ch_buffer_t *)ctx->vp;
-    l2_param_t pa[3];
+    l2_param_t pa[4];
     l2_result_t rv;
 
     /* feed and call generic parameter parsing engine */
     L2_PARAM_SET(pa[0], size,       INT, &cfg->bufsize);
-    L2_PARAM_SET(pa[1], levelflush, INT, &cfg->levelflush);
-    L2_PARAM_END(pa[2]);
+    L2_PARAM_SET(pa[1], interval,   INT, &cfg->bufinterval);
+    L2_PARAM_SET(pa[2], levelflush, INT, &cfg->levelflush);
+    L2_PARAM_END(pa[3]);
     rv = l2_util_setparams(pa, fmt, ap);
     if (cfg->bufsize < 0) 
         return L2_ERR_ARG;
@@ -80,13 +96,66 @@
     return rv;
 }
 
+/************************************************************
+ * set_alarm: Helper method to hook_open                    *
+ *   Sets the VIRTUAL timer to preconfigured value in cfg   *
+ ************************************************************/
+static int set_alarm(l2_ch_buffer_t *cfg)
+{
+    struct itimerval valnew;
+
+    /* initialize auto vars before using them */
+    memset(&valnew, 0, sizeof(valnew));
+
+    valnew.it_interval.tv_sec = cfg->bufinterval;
+    valnew.it_interval.tv_usec = 0;
+    valnew.it_value.tv_sec = cfg->bufinterval;
+    valnew.it_value.tv_usec = 0;
+    return setitimer(ITIMER_VIRTUAL, &valnew, &cfg->valprev); /* set flush timer */
+}
+
+/************************************************************
+ * reset_alarm: Helper method to hook_flush                 *
+ *   Resets the VIRTUAL timer to preconfigured value in cfg *
+ ************************************************************/
+static int reset_alarm(l2_ch_buffer_t *cfg)
+{
+    struct itimerval valnew;
+
+    /* initialize auto vars before using them */
+    memset(&valnew, 0, sizeof(valnew));
+
+    valnew.it_interval.tv_sec = cfg->bufinterval;
+    valnew.it_interval.tv_usec = 0;
+    valnew.it_value.tv_sec = cfg->bufinterval;
+    valnew.it_value.tv_usec = 0;
+    return setitimer(ITIMER_VIRTUAL, &valnew, 0); /* reset flush timer */
+}
+
 /* open channel */
 static l2_result_t hook_open(l2_context_t *ctx, l2_channel_t *ch)
 {
     l2_ch_buffer_t *cfg = (l2_ch_buffer_t *)ctx->vp;
     l2_channel_t *downstream = l2_channel_downstream(ch);
+    struct sigaction locact;
     l2_result_t rv;
 
+    if (cfg->bufinterval != 0) {
+        /* initialize auto vars before using them */
+        memset(&locact, 0, sizeof(locact));
+
+        locact.sa_handler = (void(*)())catchsignal;
+        sigemptyset(&locact.sa_mask);
+        locact.sa_flags = 0;
+
+        /* save old signal context before replacing with our own */
+        if (sigaction(SIGALRM, &locact, &cfg->sigalrm) < 0)
+            return L2_ERR_SYS;
+
+        if (set_alarm(cfg))
+            return L2_ERR_SYS;
+    }
+
     /* open channel buffer */
     if (cfg->bufsize > 0) {
         if ((cfg->buf = malloc(cfg->bufsize)) == NULL)
@@ -156,6 +225,11 @@
         cfg->level  = L2_LEVEL_NONE; /* reset this->context->level */
     }
 
+    /* reset the flush alarm timer to synchronize the buffer */
+    if (cfg->bufinterval != 0)
+        if (reset_alarm(cfg))
+            return L2_ERR_SYS;
+
     /* optionally flush downstream channel, too */
     if ((rv = l2_channel_flush(downstream)) != L2_OK)
         return rv;
@@ -170,6 +244,14 @@
     l2_channel_t *downstream = l2_channel_downstream(ch);
     l2_result_t rv;
 
+    if (cfg->bufinterval != 0) {
+        setitimer(ITIMER_VIRTUAL, &cfg->valprev, 0); /* restore timer values */
+        /* restore previous signal context if previously saved & replaced    */
+        if (&cfg->sigalrm.sa_handler)
+            if (sigaction(SIGALRM, &cfg->sigalrm, 0) < 0)
+                rv = L2_ERR_SYS;
+    }
+
     /* write pending data before closing down */
     if (cfg->bufpos > 0) {
         if ((rv = l2_channel_write(downstream, cfg->level, cfg->buf, cfg->bufpos)) != L2_OK)

CVSTrac 2.0.1