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

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

#1 add doxygen prologue to .c file

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