Changeset 151 in libcf for trunk/src/cf_log.c
- Timestamp:
- 10/31/13 10:17:24 (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/cf_log.c
r149 r151 19 19 #include "cf_local.h" 20 20 #include "cf_error.h" 21 #include "cf_util.h" 21 22 22 23 #include <stdio.h> … … 29 30 # include <Windows.h> 30 31 #else 31 # include <sys/time.h>32 32 #endif 33 34 #define LOG_BUFFER_DEFAULT_SIZE 128 * 1024 33 35 34 36 #define ASSERT_CTX(__ctx) \ … … 36 38 return CF_ERROR_LOG_INVALID_CTX 37 39 38 #define ASSERT_INIT() \ 39 if (gLogPool.ctxPool == NULL || \ 40 gLogPool.poolSize <= 0 ) \ 41 return CF_ERROR_LOG_NOT_INITIALIZE 42 43 #define ASSERT_MAPID(__mapid) \ 44 if (gLogPool.poolSize <= __mapid) \ 45 return CF_ERROR_LOG_INVALID_MAPID 46 47 #define ASSERT_MAPPED_CTX(__mapid) \ 48 if (gLogPool.ctxPool[__mapid] != NULL) \ 49 return CF_ERROR_LOG_ALREADY_MAPPED_ID 50 51 #define ASSERT_NOT_MAPPED_CTX(__mapid) \ 52 if (gLogPool.ctxPool[__mapid] == NULL) \ 53 return CF_ERROR_LOG_NOT_MAPPED_ID 54 55 #define LOG_BUFFER_DEFAULT_SIZE 128 * 1024 56 57 #define LOG_DATETIME_LENGTH sizeof ("0000-00-00 00:00:00.000") - 1 58 59 /** 로그 컨텍스트 (Opaque) */ 60 typedef void * CF_Log_Ctx; 61 62 typedef struct __cf_util_datetime__ 63 { 64 int year; 65 int month; 66 int day; 67 int week; /* SUN:0 ~ SAT:6 */ 68 69 int hour; 70 int min; 71 int sec; 72 int usec; 73 } CF_LOG_DATETIME; 74 75 /** 로그 컨텍스트 (CF_Log_Ctx의 구현) */ 40 #define ASSERT_ARGS(x) \ 41 if ((x)) \ 42 return CF_ERROR_LOG_INVALID_ARGS 43 44 /** 로그 컨텍스트 (cf_ctx의 구현) */ 76 45 typedef struct __cf_log_ctx__ 77 46 { 78 47 char path[NAME_LENGTH + 1]; 79 int fd;48 cf_ctx file; 80 49 char * buffer; 81 50 size_t size; /* entire size of buffer */ 82 51 size_t length; /* data length in current */ 83 CF_Mutex_Ctx mutex;52 cf_ctx mutex; 84 53 } CF_LOG_CONTEXT; 85 86 typedef struct __cf_log_array__87 {88 CF_Log_Ctx * ctxPool;89 int poolSize;90 } CF_LOG_POOL;91 92 static CF_LOG_POOL gLogPool;93 94 #if defined(_WIN32) || defined(_WIN64)95 /* {{{ */96 struct timezone97 {98 int tz_minuteswest; /* minutes W of Greenwich */99 int tz_dsttime; /* type of dst correction */100 };101 102 int gettimeofday (struct timeval *tv, struct timezone *tz)103 {104 FILETIME ft;105 unsigned __int64 buf =0;106 //static int tzflag = 0;107 108 if (NULL != tv)109 {110 GetSystemTimeAsFileTime (&ft);111 112 buf |= ft.dwHighDateTime;113 buf <<= 32;114 buf |= ft.dwLowDateTime;115 116 if (buf)117 {118 buf /= 10;119 buf -= ((369 * 365 + 89) * (unsigned __int64) 86400) * 1000000;120 }121 122 tv->tv_sec = (long)(buf / 1000000UL);123 tv->tv_usec = (long)(buf % 1000000UL);124 }125 126 /*127 if (NULL != tz)128 {129 if (!tzflag)130 {131 _tzset();132 tzflag++;133 }134 135 // Adjust for the timezone west of Greenwich136 tz->tz_minuteswest = _timezone / 60;137 tz->tz_dsttime = _daylight;138 }139 */140 141 return 0;142 }143 /* }}} */144 #endif145 146 static int147 CF_Log_Local_GetTime (CF_LOG_DATETIME * dt)148 {149 struct timeval timeVal;150 struct tm * timeSt;151 152 gettimeofday (&timeVal, NULL);153 timeSt = localtime ((const time_t *)&timeVal.tv_sec);154 155 dt->year = timeSt->tm_year + 1900;156 dt->month = timeSt->tm_mon + 1;157 dt->day = timeSt->tm_mday;158 dt->week = timeSt->tm_wday;159 160 dt->hour = timeSt->tm_hour;161 dt->min = timeSt->tm_min;162 dt->sec = timeSt->tm_sec;163 164 dt->usec = (int) timeVal.tv_usec;165 166 return CF_OK;167 }168 169 static int170 CF_Log_Local_GetTimeString (char * buffer)171 {172 CF_LOG_DATETIME dt;173 CF_Log_Local_GetTime (&dt);174 175 snprintf (buffer, LOG_DATETIME_LENGTH,176 "%04d-%02d-%02d %02d:%02d:%02d.%03d",177 dt.year, dt.month, dt.day,178 dt.hour, dt.min, dt.sec, dt.usec);179 180 return CF_OK;181 }182 54 183 55 static int 184 56 CF_Log_Local_Flush (CF_LOG_CONTEXT * ctx) 185 57 { 186 if (CF_File_Write (ctx->f d, ctx->buffer, ctx->length) < 0)58 if (CF_File_Write (ctx->file, ctx->buffer, ctx->length) < 0) 187 59 return CF_ERROR_LOG_FLUSH; 188 60 … … 208 80 const size_t demandSize) 209 81 { 210 int result = CF_OK; 82 int result = 0; 83 84 size_t writeSize; 85 size_t remainSize; 211 86 212 87 if (ctx->size > 0) /* 버퍼단위 버퍼링.... */ 213 88 { 214 size_t writeSize;215 size_t remainSize;216 217 89 remainSize = demandSize; 218 90 while (remainSize) 219 91 { 220 writeSize = (ctx->size - ctx->length) < remainSize ? (ctx->size - ctx->length) : remainSize; 221 222 memcpy (ctx->buffer + ctx->length, buffer + demandSize - remainSize, writeSize); 92 writeSize = (ctx->size - ctx->length) < remainSize 93 ? (ctx->size - ctx->length) 94 : remainSize; 95 96 memcpy (ctx->buffer + ctx->length, 97 buffer + demandSize - remainSize, 98 writeSize); 223 99 ctx->length += writeSize; 224 100 … … 247 123 * \param ctx 로그 컨텍스트 248 124 */ 249 staticint250 CF_Log_SetMultiThread ( CF_Log_Ctx ctx)251 { 252 CF_LOG_CONTEXT * context = (CF_LOG_CONTEXT *) ctx; 253 254 ASSERT_CTX (ctx); 255 256 if (CF_Mutex_Create Ctx(&context->mutex) < 0)125 int 126 CF_Log_SetMultiThread (cf_ctx ctx) 127 { 128 CF_LOG_CONTEXT * context = (CF_LOG_CONTEXT *) ctx; 129 130 ASSERT_CTX (ctx); 131 132 if (CF_Mutex_Create (&context->mutex) < 0) 257 133 return CF_ERROR_LOG_SET_MULTITHREAD; 258 134 … … 267 143 * \param ctx 로그 컨텍스트 268 144 */ 269 staticint270 CF_Log_UnsetMultiThread ( CF_Log_Ctx ctx)271 { 272 CF_LOG_CONTEXT * context = (CF_LOG_CONTEXT *) ctx; 273 274 ASSERT_CTX (ctx); 275 276 if (CF_Mutex_Destory Ctx(context->mutex) < 0)145 int 146 CF_Log_UnsetMultiThread (cf_ctx ctx) 147 { 148 CF_LOG_CONTEXT * context = (CF_LOG_CONTEXT *) ctx; 149 150 ASSERT_CTX (ctx); 151 152 if (CF_Mutex_Destory (context->mutex) < 0) 277 153 return CF_ERROR_LOG_UNSET_MULTITHREAD; 278 154 … … 293 169 */ 294 170 static int 295 CF_Log_Local_WriteVA (CF_L og_Ctx ctx,296 const char * prefix,297 const char * fmt,298 va_list valist)171 CF_Log_Local_WriteVA (CF_LOG_CONTEXT * context, 172 const char * prefix, 173 const char * fmt, 174 va_list valist) 299 175 { 300 176 #define BUF_LEN 16 * 1024 301 CF_LOG_CONTEXT * context = (CF_LOG_CONTEXT *) ctx; 302 char buffer[BUF_LEN + 1] = {0x00,}; 303 char datetime[LOG_DATETIME_LENGTH + 1] = {0x00,}; 304 int length = 0; 305 int result = 0; 306 307 ASSERT_CTX (ctx); 308 309 CF_Log_Local_GetTimeString (datetime); 177 char buffer[BUF_LEN + 1] = {0x00,}; 178 char datetime[CF_UTIL_DATETIME_LENGTH + 1] = {0x00,}; 179 int length = 0; 180 int result = 0; 181 182 CF_UTIL_DATETIME dt; 183 184 ASSERT_CTX (context); 185 186 CF_Util_GetCurrentTime (&dt); 187 CF_Util_GetTimeString (&dt, datetime); 310 188 length = snprintf (buffer, BUF_LEN, "[%s][%s] ", datetime, prefix); 311 189 vsnprintf (&buffer[length], BUF_LEN - (size_t)length, fmt, valist); … … 329 207 */ 330 208 int 331 CF_Log_WriteCtx (CF_Log_Ctx ctx, 332 const char * prefix, 333 const char * fmt, ...) 334 { 209 CF_Log_Write (cf_ctx ctx, 210 const char * prefix, 211 const char * fmt, ...) 212 { 213 CF_LOG_CONTEXT * context = (CF_LOG_CONTEXT *) ctx; 214 335 215 int result = 0; 336 216 va_list valist; 337 217 338 218 va_start (valist, fmt); 339 result = CF_Log_Local_WriteVA (c tx, prefix, fmt, valist);219 result = CF_Log_Local_WriteVA (context, prefix, fmt, valist); 340 220 va_end (valist); 341 221 … … 350 230 * \param ctx 로그 컨텍스트 351 231 */ 352 static int 353 CF_Log_FlushCtx (CF_Log_Ctx ctx) 354 { 355 CF_LOG_CONTEXT * context = (CF_LOG_CONTEXT *) ctx; 356 int result = 0; 232 int 233 CF_Log_Flush (cf_ctx ctx) 234 { 235 int result = 0; 236 237 CF_LOG_CONTEXT * context = (CF_LOG_CONTEXT *) ctx; 357 238 358 239 ASSERT_CTX (ctx); … … 372 253 * \param ctx 로그 컨텍스트 373 254 */ 374 staticint375 CF_Log_Destroy Ctx (CF_Log_Ctx ctx)255 int 256 CF_Log_Destroy (cf_ctx ctx) 376 257 { 377 258 CF_LOG_CONTEXT * context = (CF_LOG_CONTEXT *) ctx; … … 381 262 if (context->size > 0) 382 263 { 383 CF_Log_Flush Ctx(ctx);264 CF_Log_Flush (ctx); 384 265 free (context->buffer); 385 266 context->buffer = NULL; … … 387 268 } 388 269 389 CF_File_Close (context->f d);390 391 CF_Mutex_Destory Ctx(context->mutex);270 CF_File_Close (context->file); 271 272 CF_Mutex_Destory (context->mutex); 392 273 context->mutex = NULL; 274 275 free (context); 393 276 394 277 return CF_OK; … … 406 289 * \see CF_LOG_DEFAULT_BUFFER, CF_LOG_NO_BUFFER 407 290 */ 408 staticint409 CF_Log_Create Ctx (CF_Log_Ctx* ctx,410 411 const intmemsize)291 int 292 CF_Log_Create (cf_ctx * ctx, 293 const char * path, 294 const int memsize) 412 295 { 413 296 int result = 0; … … 417 300 : memsize; 418 301 419 CF_LOG_CONTEXT 420 421 if (path == NULL)422 return CF_ERROR_LOG_INVALID_ARGS;302 CF_LOG_CONTEXT * context = NULL; 303 304 ASSERT_CTX (ctx); 305 ASSERT_ARGS (path == NULL); 423 306 424 307 TRY 425 308 { 426 context = (CF_LOG_CONTEXT *) calloc (sizeof (CF_LOG_CONTEXT), 1);309 context = NEWCTX (CF_LOG_CONTEXT); 427 310 if (context == NULL) 428 311 { … … 431 314 } 432 315 433 context->fd = CF_File_Open (path, fileFlag);434 if ( context->fd< 0)316 result = CF_File_Open (&context->file, path, fileFlag); 317 if (result < 0) 435 318 { 436 319 result = CF_ERROR_LOG_CREATE_FILE; 437 320 TRY_BREAK; 438 321 } 439 snprintf (context->path, sizeof (context->path) - 1, "%s", path);322 snprintf (context->path, sizeof (context->path) - 1, "%s", path); 440 323 441 324 if (size > 0) … … 450 333 } 451 334 452 *ctx = ( CF_Log_Ctx) context;335 *ctx = (cf_ctx) context; 453 336 } 454 337 CATCH_IF (result < 0) 455 338 { 456 CF_Log_DestroyCtx ((CF_Log_Ctx) context); 457 } 458 459 return result; 460 } 461 462 /** 463 * 로그 컨텍스트에 아이디 넘버 할당<br /> 464 * 로그 기록 시, 아이디 넘버를 사용하면 해당 로그로 기록할 수 있음 465 * 466 * \return 성공 시, CF_OK; 실패 시, 오류 코드 467 * 468 * \param mapid 부여할 아이디 넘버 469 * \param ctx 로그 컨텍스트 470 * 471 * \remarks 반드시 먼저 초기화 해야하며, 초기화 시에 주어진 번호보다 작은 아이디 넘버를 사용 472 */ 473 static int 474 CF_Log_MapCtxID (const int mapid, 475 const CF_Log_Ctx ctx) 476 { 477 ASSERT_INIT (); 478 ASSERT_MAPID (mapid); 479 ASSERT_MAPPED_CTX (mapid); 480 481 gLogPool.ctxPool[mapid] = ctx; 482 483 return CF_OK; 484 } 485 486 /** 487 * 아이디 넘버에 해당하는 로그를 닫고 해당하는 컨텍스트를 해제 488 * 489 * \return 성공 시, CF_OK; 실패 시, 오류 코드 490 * 491 * \param mapid 로그의 아이디 넘버 492 * 493 * \remarks 아이디 넘버에 해당하는 컨텍스트가 해제되므로 주의 494 */ 495 static int 496 CF_Log_UnmapCtxID (const int mapid) 497 { 498 ASSERT_INIT (); 499 ASSERT_MAPID (mapid); 500 ASSERT_NOT_MAPPED_CTX (mapid); 501 502 CF_Log_DestroyCtx (gLogPool.ctxPool[mapid]); 503 504 free (gLogPool.ctxPool[mapid]); 505 gLogPool.ctxPool[mapid] = NULL; 506 507 return CF_OK; 508 } 509 510 /** 511 * 아이디 넘버에 해당하는 로그 컨텍스트를 얻기 512 * 513 * \return 성공 시, CF_OK; 실패 시, 오류 코드 514 * 515 * \param mapid 로그의 아이디 넘버 516 * \param ctx 로그 컨텍스트 받을 주소 517 */ 518 static int 519 CF_Log_GetMappedCtx (const int mapid, 520 CF_Log_Ctx * ctx) 521 { 522 ASSERT_INIT (); 523 ASSERT_MAPID (mapid); 524 ASSERT_NOT_MAPPED_CTX (mapid); 525 526 *ctx = gLogPool.ctxPool[mapid]; 527 528 return CF_OK; 529 } 530 531 /** 532 * 로그를 사용하기 위해 초기화 533 * 534 * \return 성공 시, CF_OK; 실패 시, 오류 코드 535 * 536 * \param poolSize 로그 풀 크기로, 로그 아이디 넘버의 최대 값 537 */ 538 int 539 CF_Log_Initialize (const int poolSize) 540 { 541 memset (&gLogPool, 0x00, sizeof (CF_LOG_POOL)); 542 543 if (poolSize > 0) 544 { 545 gLogPool.ctxPool = 546 (CF_Log_Ctx *) calloc ((size_t) poolSize, sizeof (CF_Log_Ctx)); 547 if (gLogPool.ctxPool == NULL) 548 return CF_ERROR_LOG_INITIALIZE; 549 gLogPool.poolSize = poolSize; 550 } 551 552 return CF_OK; 553 } 554 555 /** 556 * 로그가 모두 사용된 후 자원 해제 557 * 558 * \return CF_OK 반환 559 */ 560 int 561 CF_Log_Finalize (void) 562 { 563 int mapid = 0; 564 565 for (mapid = 0 ; mapid < gLogPool.poolSize ; mapid++) 566 { 567 CF_Log_UnmapCtxID (mapid); 568 } 569 570 if (gLogPool.ctxPool != NULL) 571 free (gLogPool.ctxPool); 572 573 memset (&gLogPool, 0x00, sizeof (CF_LOG_POOL)); 574 575 return CF_OK; 576 } 577 578 /** 579 * 로그 열기 580 * 581 * \return 성공 시, CF_OK; 실패 시, 오류 코드 582 * 583 * \param mapid 로그의 아이디 넘버 584 * \param path 로그 파일 경로 585 * \param memsize 로그 버퍼 크기 586 * 587 * \see CF_LOG_DEFAULT_BUFFER, CF_LOG_NO_BUFFER 588 */ 589 int 590 CF_Log_Open (const int mapid, 591 const char * path, 592 const int memsize) 593 { 594 int result = 0; 595 CF_Log_Ctx ctx = NULL; 596 597 result = CF_Log_CreateCtx (&ctx, path, memsize); 598 if (result < 0) 599 return result; 600 601 result = CF_Log_MapCtxID (mapid, ctx); 602 if (result < 0) 603 CF_Log_DestroyCtx (ctx); 604 605 return result; 606 } 607 608 /** 609 * 로그 닫기 610 * 611 * \return 성공 시, CF_OK; 실패 시, 오류 코드 612 * 613 * \param mapid 로그의 아이디 넘버 614 */ 615 int 616 CF_Log_Close (const int mapid) 617 { 618 return CF_Log_UnmapCtxID (mapid); 619 } 620 621 /** 622 * 로그 버퍼의 데이터를 즉시 로그 파일에 쓰기 623 * 624 * \return 성공 시, CF_OK; 실패 시, 오류 코드 625 * 626 * \param mapid 로그의 아이디 넘버 627 */ 628 int 629 CF_Log_Flush (const int mapid) 630 { 631 int result = 0; 632 CF_Log_Ctx ctx = NULL; 633 634 result = CF_Log_GetMappedCtx (mapid, &ctx); 635 if (result < 0) 636 return result; 637 638 result = CF_Log_FlushCtx (ctx); 639 640 return result; 641 } 642 643 /** 644 * 로그 컨텍스트에 멀티쓰레드 모드 설정 645 * 646 * \return 성공 시, CF_OK; 실패 시, 오류 코드 647 * 648 * \param mapid 로그의 아이디 넘버 649 * \param flag 설정/해제 bool 플래그 650 * 651 * \see CF_BOOL 652 */ 653 int 654 CF_Log_SetMT (const int mapid, 655 const CF_BOOL flag) 656 { 657 int result = 0; 658 CF_Log_Ctx ctx = NULL; 659 660 result = CF_Log_GetMappedCtx (mapid, &ctx); 661 if (result < 0) 662 return result; 663 664 result = (flag) ? CF_Log_SetMultiThread (ctx) : 665 CF_Log_UnsetMultiThread (ctx); 666 667 return result; 668 } 669 670 /** 671 * 로그 쓰기 672 * 673 * \return 성공 시, CF_OK; 실패 시, 오류 코드 674 * 675 * \param mapid 로그의 아이디 넘버 676 * \param prefix 로그의 프리픽스 문자열 677 * \param fmt 포맷 스트링 678 * \param ... 가변 인자 679 */ 680 int 681 CF_Log_Write (const int mapid, 682 const char * prefix, 683 const char * fmt, ...) 684 { 685 int result = 0; 686 CF_Log_Ctx ctx = NULL; 687 va_list valist; 688 689 result = CF_Log_GetMappedCtx (mapid, &ctx); 690 if (result < 0) 691 return result; 692 693 va_start (valist, fmt); 694 result = CF_Log_Local_WriteVA (ctx, prefix, fmt, valist); 695 va_end (valist); 696 697 return result; 698 } 339 CF_Log_Destroy ((cf_ctx) context); 340 } 341 342 return result; 343 }
Note:
See TracChangeset
for help on using the changeset viewer.