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

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

#1 documentation with doxygen

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