mem.c

00001 /*
00002  * Copyright (c) 2005-2012 by KoanLogic s.r.l. <http://www.koanlogic.com>
00003  * All rights reserved.
00004  *
00005  * This file is part of KLone, and as such it is subject to the license stated
00006  * in the LICENSE file which you have received as part of this distribution.
00007  *
00008  * $Id: mem.c,v 1.12 2006/01/10 21:51:41 tat Exp $
00009  */
00010 
00011 #include "klone_conf.h"
00012 #include <time.h>
00013 #include <u/libu.h>
00014 #include <klone/klog.h>
00015 #include <klone/klogprv.h>
00016 
00017 static int klog_mem_msg_new (const char *s, int level, klog_mem_msg_t **pmmsg);
00018 static int klog_mem_msg_push (klog_mem_t *klm, klog_mem_msg_t *mmsg);
00019 static void klog_mem_msg_free (klog_mem_msg_t *mmsg);
00020 static void klog_mem_msgs_free (klog_mem_t *klm);
00021 static void klog_free_mem (klog_mem_t *klm);
00022 
00023 static int klog_mem (klog_t *kl, int level, const char *fmt, va_list ap);
00024 static int klog_getln_mem (klog_t *kl, size_t nth, char ln[]);
00025 static ssize_t klog_countln_mem (klog_t *kl);
00026 static void klog_close_mem (klog_t *kl);
00027 static int klog_clear_mem (klog_t *kl);
00028 
00029 /* mem log type initialisation */
00030 int klog_open_mem (klog_t *kl, size_t ln_max)
00031 {
00032     klog_mem_t *klm = NULL;
00033 
00034     dbg_return_if (kl == NULL, ~0);
00035 
00036     /* create a new klog_mem_t object */
00037     klm = u_zalloc(sizeof(klog_mem_t));
00038     dbg_err_if (klm == NULL);
00039     
00040     /* initialise the klog_mem_t object to the supplied values */
00041     klm->bound = ln_max ? ln_max : 1;   /* set at least a 1 msg window :) */
00042     klm->nmsgs = 0;
00043     TAILQ_INIT(&klm->msgs);
00044 
00045     /* set private methods */
00046     kl->cb_log = klog_mem;
00047     kl->cb_close = klog_close_mem;
00048     kl->cb_getln = klog_getln_mem;
00049     kl->cb_countln = klog_countln_mem;
00050     kl->cb_clear = klog_clear_mem;
00051     kl->cb_flush = NULL;
00052 
00053     /* stick the klog_mem_t object to its parent */
00054     kl->u.m = klm, klm = NULL;
00055 
00056     return 0;
00057 err:
00058     if (klm)
00059         klog_free_mem(klm);
00060     return ~0;
00061 }
00062 
00063 /* write a log msg to memory */
00064 static int klog_mem (klog_t *kl, int level, const char *fmt, va_list ap)
00065 {
00066     klog_mem_t *klm;
00067     char ln[KLOG_LN_SZ + 1];
00068     klog_mem_msg_t *mmsg = NULL;
00069 
00070     dbg_return_if (kl == NULL, ~0);
00071     dbg_return_if (kl->type != KLOG_TYPE_MEM, ~0);
00072     dbg_return_if (kl->u.m == NULL, ~0);
00073     dbg_return_if (fmt == NULL, ~0);
00074 
00075     klm = kl->u.m;
00076 
00077     /* NOTE: could check overflow here */
00078     vsnprintf(ln, sizeof ln, fmt, ap);
00079     dbg_err_if (klog_mem_msg_new(ln, level, &mmsg));
00080     dbg_err_if (klog_mem_msg_push(klm, mmsg));
00081     mmsg = NULL;
00082 
00083     return 0;
00084 err:
00085     if (mmsg)
00086         klog_mem_msg_free(mmsg);
00087     return ~0;
00088 }
00089 
00090 /* elements are retrieved in reverse order with respect to insertion */
00091 static int klog_getln_mem (klog_t *kl, size_t nth, char ln[])
00092 {
00093     size_t i = nth;
00094     klog_mem_msg_t *cur; 
00095     char *ct;
00096     klog_mem_t *klm;
00097 
00098     dbg_return_if (kl == NULL, ~0);
00099     dbg_return_if (kl->type != KLOG_TYPE_MEM, ~0);
00100     dbg_return_if (kl->u.m == NULL, ~0);
00101     nop_return_if (nth > kl->u.m->nmsgs, ~0);
00102     dbg_return_if (nth == 0, ~0);
00103 
00104     klm = kl->u.m;
00105 
00106     TAILQ_FOREACH (cur, &klm->msgs, next)
00107     {
00108         if (i-- == 1)
00109             break;
00110     }
00111     
00112     ct = ctime((const time_t *) &cur->timestamp);
00113     ct[24] = '\0';
00114 
00115     /* 
00116      * line format is:
00117      *      [DEBUG] Sep 23 13:26:19 <ident>: log message line.
00118      */
00119     snprintf(ln, KLOG_LN_SZ + 1, "[%s] %s <%s>: %s", 
00120              klog_to_str(cur->level), ct, kl->ident, cur->line);
00121 
00122     return 0;
00123 }
00124 
00125 static ssize_t klog_countln_mem (klog_t *kl)
00126 {
00127     dbg_return_if (kl == NULL, -1);
00128     dbg_return_if (kl->type != KLOG_TYPE_MEM, -1);
00129     dbg_return_if (kl->u.m == NULL, -1);
00130 
00131     return kl->u.m->nmsgs;
00132 }
00133 
00134 static void klog_close_mem (klog_t *kl)
00135 {
00136     if (kl == NULL || kl->type != KLOG_TYPE_MEM || kl->u.m == NULL)
00137         return;
00138 
00139     klog_free_mem(kl->u.m), kl->u.m = NULL;
00140 
00141     return;
00142 }
00143 
00144 static void klog_free_mem (klog_mem_t *klm)
00145 {
00146     if (klm == NULL)
00147         return;
00148     klog_mem_msgs_free(klm);
00149     U_FREE(klm);
00150     return;
00151 }
00152 
00153 /* cancel all log messages but retain header information */
00154 static int klog_clear_mem (klog_t *kl)
00155 {
00156     klog_mem_t *klm;
00157 
00158     dbg_return_if (kl == NULL, ~0);
00159     dbg_return_if (kl->type != KLOG_TYPE_MEM, ~0);
00160     dbg_return_if (kl->u.m == NULL, ~0);
00161 
00162     klm = kl->u.m;
00163 
00164     /* wipe out all msgs in buffer */
00165     klog_mem_msgs_free(klm);
00166 
00167     /* reset header informations */
00168     klm->nmsgs = 0;
00169     TAILQ_INIT(&klm->msgs);
00170 
00171     return 0;
00172 }
00173 
00174 static void klog_mem_msgs_free (klog_mem_t *klm)
00175 {
00176     klog_mem_msg_t *mmsg;
00177 
00178     dbg_ifb (klm == NULL) return;
00179     
00180     while((mmsg = TAILQ_FIRST(&klm->msgs)) != NULL)
00181     {
00182         TAILQ_REMOVE(&klm->msgs, mmsg, next);
00183         klm->nmsgs--;
00184         klog_mem_msg_free(mmsg);
00185     }
00186 
00187     return;
00188 }
00189 
00190 static int klog_mem_msg_new (const char *s, int level, klog_mem_msg_t **pmmsg)
00191 {
00192     klog_mem_msg_t *mmsg = NULL;
00193 
00194     dbg_return_if (s == NULL, ~0);
00195     dbg_return_if (pmmsg == NULL, ~0);
00196 
00197     mmsg = u_zalloc(sizeof(klog_mem_msg_t));
00198     dbg_err_if (mmsg == NULL);
00199 
00200     mmsg->line = u_strndup(s, KLOG_LN_SZ);
00201     mmsg->timestamp = time(NULL);
00202     mmsg->level = level;
00203 
00204     *pmmsg = mmsg;
00205 
00206     return 0;
00207 
00208 err:
00209     if (mmsg)
00210         klog_mem_msg_free(mmsg);
00211     return ~0;
00212 }
00213 
00214 static int klog_mem_msg_push (klog_mem_t *klm, klog_mem_msg_t *mmsg)
00215 {
00216     dbg_return_if (klm == NULL, ~0);
00217     dbg_return_if (mmsg == NULL, ~0);
00218 
00219     /* push out first-in element on KLOG_MEM_FULL event */
00220     if (KLOG_MEM_FULL(klm))
00221     {
00222         klog_mem_msg_t *last = TAILQ_LAST(&klm->msgs, mh);
00223 
00224         /* last == NULL on KLOG_MEM_FULL should never happen :-) */
00225         if (last != NULL)
00226         {
00227             TAILQ_REMOVE(&klm->msgs, last, next);
00228             klog_mem_msg_free(last);
00229             klm->nmsgs--;
00230         }
00231     }
00232 
00233     TAILQ_INSERT_HEAD(&klm->msgs, mmsg, next);
00234     klm->nmsgs++;
00235 
00236     return 0;
00237 }
00238 
00239 static void klog_mem_msg_free (klog_mem_msg_t *mmsg)
00240 {
00241     dbg_ifb (mmsg == NULL) return;
00242 
00243     U_FREE(mmsg->line);
00244     U_FREE(mmsg);
00245 
00246     return;
00247 }
00248 

←Products
Copyright © 2005-2012 - KoanLogic S.r.l. - All rights reserved