source: libcf/trunk/src/cf_log.c@ 12

Last change on this file since 12 was 12, checked in by cheese, 11 years ago

#1 implement logging module

File size: 7.0 KB
Line 
1/*
2 * cf_log.c
3 */
4#include "cf_log.h"
5#include "cf_file.h"
6#include "cf_thread.h"
7#include "cf_local.h"
8
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include <stdarg.h>
13#include <time.h>
14
15#ifdef _WIN32
16#else // #ifdef _WIN32
17# include <sys/stat.h>
18# include <sys/time.h>
19#endif // #ifdef _WIN32
20
21#define CHECK_INVALID_CTX(__ctx) \
22 if (__ctx == NULL) \
23 return CF_ERROR_LOG_INVALID_CTX
24
25#define LOCK_LOG_CTX(__ctx) \
26 if (CF_Mutex_Lock (&__ctx->mutex) < 0) \
27 return CF_ERROR_LOG_LOCK_CTX
28
29#define UNLOCK_LOG_CTX(__ctx) \
30 if (CF_Mutex_Unlock (&__ctx->mutex) < 0) \
31 return CF_ERROR_LOG_UNLOCK_CTX
32
33#define CF_LOG_BUFFER_DEFAULT_SIZE 128 * 1024
34
35typedef struct __cf_util_datetime__
36{
37 int year;
38 int month;
39 int day;
40 int week; /* SUN:0 ~ SAT:6 */
41
42 int hour;
43 int min;
44 int sec;
45 int usec;
46} S_CF_Log_DateTime, CF_Log_DateTime;
47
48typedef struct __cf_log_ctx__ {
49 char path[NAME_LENGTH + 1];
50 int fd;
51 char * buffer;
52 size_t size; /* entire size of buffer */
53 size_t length; /* data length in current */
54 CF_Mutex mutex;
55} S_CF_LOG_CTX, CF_LOG_CTX;
56
57typedef struct __cf_log_environment__ {
58 __blksize_t fsBlockSize;
59 CF_Log_Ctx * ctxPool;
60 int ctxSize;
61} S_CF_LOG_ENVIRONMENT, CF_LOG_ENVIRONMENT;
62
63CF_LOG_ENVIRONMENT gLogEnvironment;
64
65#if defined(_WIN32) || defined(_WIN64)
66/* #if defined(_WIN32) || defined(_WIN64) {{{ */
67struct timezone
68{
69 int tz_minuteswest; /* minutes W of Greenwich */
70 int tz_dsttime; /* type of dst correction */
71};
72
73// Definition of a gettimeofday function
74int gettimeofday(struct timeval *tv, struct timezone *tz)
75{
76 // Define a structure to receive the current Windows filetime
77 FILETIME ft;
78
79 // Initialize the present time to 0 and the timezone to UTC
80 unsigned __int64 ui64 =0;
81 static int tzflag = 0;
82
83 if (NULL != tv)
84 {
85 GetSystemTimeAsFileTime(&ft);
86
87 ui64 = (((unsigned __int64) ft.dwHighDateTime << 32)
88 + (unsigned __int64) ft.dwLowDateTime);
89
90 if (ui64)
91 {
92 ui64 /= 10;
93 ui64 -= ((369 * 365 + 89) * (unsigned __int64) 86400) * 1000000;
94 }
95
96 // Finally change microseconds to seconds and place in the seconds value.
97 // The modulus picks up the microseconds.
98 tv->tv_sec = (long)(ui64 / 1000000UL);
99 tv->tv_usec = (long)(ui64 % 1000000UL);
100 }
101
102 if (NULL != tz)
103 {
104 if (!tzflag)
105 {
106 _tzset();
107 tzflag++;
108 }
109
110 // Adjust for the timezone west of Greenwich
111 tz->tz_minuteswest = _timezone / 60;
112 tz->tz_dsttime = _daylight;
113 }
114
115 return 0;
116}
117#endif // #if defined(_WIN32) || defined(_WIN64)
118/* }}} #if defined(_WIN32) || defined(_WIN64) */
119
120int
121CF_Log_Local_GetTime (CF_Log_DateTime * dt)
122{
123 struct timeval timeVal;
124 struct tm * timeSt;
125
126 gettimeofday (&timeVal, NULL);
127 timeSt = localtime (&timeVal.tv_sec);
128
129 dt->year = timeSt->tm_year + 1900;
130 dt->month = timeSt->tm_mon + 1;
131 dt->day = timeSt->tm_mday;
132 dt->week = timeSt->tm_wday;
133
134 dt->hour = timeSt->tm_hour;
135 dt->min = timeSt->tm_min;
136 dt->sec = timeSt->tm_sec;
137
138 dt->usec = (int) timeVal.tv_usec;
139
140 return CF_OK;
141}
142
143int
144CF_Log_Local_GetTimeString (char * buffer)
145{
146 CF_Log_DateTime dt;
147 CF_Log_Local_GetTime (&dt);
148
149 sprintf (buffer, "%02d-%02d-%02d %02d:%02d:%02d.%03d",
150 dt.year, dt.month, dt.day,
151 dt.hour, dt.min, dt.sec, dt.usec);
152
153 return CF_OK;
154}
155
156int
157CF_Log_Local_Push (CF_LOG_CTX * ctx,
158 const char * buffer)
159{
160 strncat (ctx->buffer + ctx->length,
161 buffer,
162 ctx->size - ctx->length);
163 ctx->length = strlen (ctx->buffer);
164
165 return CF_OK;
166}
167
168int
169CF_Log_Local_Flush (CF_LOG_CTX * ctx)
170{
171 if (CF_File_Write (ctx->fd, ctx->buffer, ctx->length) < 0)
172 return CF_ERROR_LOG_FLUSH;
173
174 memset (ctx->buffer, 0x00, ctx->size);
175 ctx->length = 0;
176
177 return CF_OK;
178}
179
180int
181CF_Log_Initialize (const int logPool)
182{
183 struct stat fsstat;
184
185 memset (&gLogEnvironment, 0x00, sizeof (CF_LOG_ENVIRONMENT));
186
187 if (stat (".", &fsstat) < 0)
188 return CF_ERROR_LOG_INITIALIZE;
189
190 gLogEnvironment.fsBlockSize = fsstat.st_blksize;
191 if (logPool > 0)
192 {
193 gLogEnvironment.ctxPool =
194 (CF_Log_Ctx *) calloc ((size_t) logPool, sizeof (CF_Log_Ctx));
195 gLogEnvironment.ctxSize = logPool;
196 }
197
198 return CF_OK;
199}
200
201int
202CF_Log_Finalize (void)
203{
204 memset (&gLogEnvironment, 0x00, sizeof (CF_LOG_ENVIRONMENT));
205
206 return CF_OK;
207}
208
209CF_Log_Ctx
210CF_Log_CreateCtx (const char * path,
211 const int memsize)
212{
213 int result = 0;
214 int size = (memsize == CF_LOG_BUFFER_DEFAULT)
215 ? CF_LOG_BUFFER_DEFAULT_SIZE
216 : memsize;
217 CF_LOG_CTX * context = NULL;
218
219 if (path == NULL)
220 return NULL;
221
222 TRY
223 {
224 context = (CF_LOG_CTX *) calloc (sizeof (CF_LOG_CTX), 1);
225 if (context == NULL)
226 {
227 result = -1;
228 TRY_BREAK;
229 }
230
231 context->fd = CF_File_Create (path);
232 if (context->fd < 0)
233 {
234 result = -2;
235 TRY_BREAK;
236 }
237 sprintf (context->path, "%s", path);
238
239 if (size > 0)
240 {
241 context->buffer = (char *) calloc ((size_t) size + 1, 1);
242 if (context->buffer == NULL)
243 {
244 result = -3;
245 TRY_BREAK;
246 }
247 context->size = (size_t) size;
248 }
249 }
250 CATCH_IF (result < 0)
251 {
252 CF_Log_DestroyCtx ((CF_Log_Ctx) context);
253 return NULL;
254 }
255
256 return (CF_Log_Ctx) context;
257}
258
259int
260CF_Log_SetMultiThread (CF_Log_Ctx ctx)
261{
262 CF_LOG_CTX * context = (CF_LOG_CTX *) ctx;
263
264 CHECK_INVALID_CTX (ctx);
265
266 if (CF_Mutex_Create (&context->mutex) < 0)
267 return CF_ERROR_LOG_SET_MULTITHREAD;
268
269 return CF_OK;
270}
271
272int
273CF_Log_UnsetMultiThread (CF_Log_Ctx ctx)
274{
275 CF_LOG_CTX * context = (CF_LOG_CTX *) ctx;
276
277 CHECK_INVALID_CTX (ctx);
278
279 if (CF_Mutex_Destory (&context->mutex) < 0)
280 return CF_ERROR_LOG_UNSET_MULTITHREAD;
281
282 return CF_OK;
283}
284
285int
286CF_Log_DestroyCtx (CF_Log_Ctx ctx)
287{
288 CF_LOG_CTX * context = (CF_LOG_CTX *) ctx;
289
290 CHECK_INVALID_CTX (ctx);
291
292 memset (context->path, 0x00, sizeof (context->path));
293
294 if (context->buffer != NULL)
295 {
296 /* FIXME : write residual data in buffer */
297
298 free (context->buffer);
299 context->buffer = NULL;
300 context->size = 0;
301 }
302
303 CF_File_Close (context->fd);
304
305 if (context->mutex != NULL)
306 {
307 if (CF_Mutex_Destory (&context->mutex) < 0)
308 /* do something ? */;
309
310 context->mutex = NULL;
311 }
312
313 return CF_OK;
314}
315
316int
317CF_Log_Write (CF_Log_Ctx ctx,
318 const char * prefix,
319 const char * fmt, ...)
320{
321 CF_LOG_CTX * context = (CF_LOG_CTX *) ctx;
322 va_list valist;
323 char buffer[4096] = {0x00,};
324 size_t length = 0;
325
326 CHECK_INVALID_CTX (ctx);
327
328 LOCK_LOG_CTX (context);
329 va_start (valist, fmt);
330
331 strncat (buffer, "[", 1);
332 CF_Log_Local_GetTimeString (buffer + strlen (buffer));
333 sprintf (buffer + strlen (buffer), "][%s] ", prefix);
334 vsprintf (buffer + strlen (buffer), fmt, valist);
335
336 if (context->size == CF_LOG_BUFFER_NO)
337 {
338 context->buffer = buffer;
339 context->length = strlen (buffer);
340
341 CF_Log_Local_Flush (context);
342
343 context->buffer = NULL;
344 /* context->length = 0; // already did this in flush */
345 }
346 else /* (context->size > 0) */
347 {
348 length = context->size - context->length;
349 CF_Log_Local_Push (context, buffer);
350
351 if (context->length == context->size)
352 {
353 CF_Log_Local_Flush (context);
354 CF_Log_Local_Push (context, buffer + length);
355 }
356 }
357
358 va_end (valist);
359 UNLOCK_LOG_CTX (context);
360
361 return CF_OK;
362}
363
364int
365CF_Log_Flush (CF_Log_Ctx ctx)
366{
367 CF_LOG_CTX * context = (CF_LOG_CTX *) ctx;
368
369 CHECK_INVALID_CTX (ctx);
370
371 LOCK_LOG_CTX (context);
372 CF_Log_Local_Flush (context);
373 UNLOCK_LOG_CTX (context);
374
375 return CF_OK;
376}
Note: See TracBrowser for help on using the repository browser.