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

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

#1 add test code and fix debug and logging error

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