View | Details | Raw Unified | Return to bug 48501
Collapse All | Expand All

(-)native/iis/jk_isapi_plugin.c (-4 / +181 lines)
Lines 134-139 Link Here
134
#define ENABLE_CHUNKED_ENCODING_TAG ("enable_chunked_encoding")
134
#define ENABLE_CHUNKED_ENCODING_TAG ("enable_chunked_encoding")
135
#define ERROR_PAGE_TAG              ("error_page")
135
#define ERROR_PAGE_TAG              ("error_page")
136
136
137
#define LOG_ROTATION_TIME_TAG       ("log_rotationtime")
138
#define LOG_FILESIZE_TAG            ("log_filesize")
139
137
/* HTTP standard headers */
140
/* HTTP standard headers */
138
#define TRANSFER_ENCODING_CHUNKED_HEADER_COMPLETE     ("Transfer-Encoding: chunked")
141
#define TRANSFER_ENCODING_CHUNKED_HEADER_COMPLETE     ("Transfer-Encoding: chunked")
139
#define TRANSFER_ENCODING_CHUNKED_HEADER_COMPLETE_LEN (26)
142
#define TRANSFER_ENCODING_CHUNKED_HEADER_COMPLETE_LEN (26)
Lines 485-490 Link Here
485
static jk_map_t *jk_environment_map = NULL;
488
static jk_map_t *jk_environment_map = NULL;
486
489
487
static jk_logger_t *logger = NULL;
490
static jk_logger_t *logger = NULL;
491
static JK_CRIT_SEC log_cs;
488
static char *SERVER_NAME = "SERVER_NAME";
492
static char *SERVER_NAME = "SERVER_NAME";
489
static char *SERVER_SOFTWARE = "SERVER_SOFTWARE";
493
static char *SERVER_SOFTWARE = "SERVER_SOFTWARE";
490
static char *INSTANCE_ID = "INSTANCE_ID";
494
static char *INSTANCE_ID = "INSTANCE_ID";
Lines 493-499 Link Here
493
static char extension_uri[INTERNET_MAX_URL_LENGTH] =
497
static char extension_uri[INTERNET_MAX_URL_LENGTH] =
494
    "/jakarta/isapi_redirect.dll";
498
    "/jakarta/isapi_redirect.dll";
495
static char log_file[MAX_PATH * 2];
499
static char log_file[MAX_PATH * 2];
500
static char log_file_effective[MAX_PATH * 2];
496
static int  log_level = JK_LOG_DEF_LEVEL;
501
static int  log_level = JK_LOG_DEF_LEVEL;
502
static long log_rotationtime = 0;
503
static time_t log_next_rotate_time = 0;
504
static unsigned __int64 log_filesize = 0;
505
497
static char worker_file[MAX_PATH * 2];
506
static char worker_file[MAX_PATH * 2];
498
static char worker_mount_file[MAX_PATH * 2] = {0};
507
static char worker_mount_file[MAX_PATH * 2] = {0};
499
static int  worker_mount_reload = JK_URIMAP_DEF_RELOAD;
508
static int  worker_mount_reload = JK_URIMAP_DEF_RELOAD;
Lines 563-568 Link Here
563
572
564
static int init_jk(char *serverName);
573
static int init_jk(char *serverName);
565
574
575
576
static int JK_METHOD iis_log_to_file(jk_logger_t *l, int level,
577
                                    int used, char *what);
578
566
static BOOL initialize_extension(void);
579
static BOOL initialize_extension(void);
567
580
568
static int read_registry_init_data(void);
581
static int read_registry_init_data(void);
Lines 2279-2287 Link Here
2279
        }
2292
        }
2280
        wc_close(logger);
2293
        wc_close(logger);
2281
        jk_shm_close();
2294
        jk_shm_close();
2295
        JK_ENTER_CS(&(log_cs), rc);
2282
        if (logger) {
2296
        if (logger) {
2283
            jk_close_file_logger(&logger);
2297
            jk_close_file_logger(&logger);
2284
        }
2298
        }
2299
        JK_LEAVE_CS(&(log_cs), rc);
2285
    }
2300
    }
2286
    JK_LEAVE_CS(&(init_cs), rc);
2301
    JK_LEAVE_CS(&(init_cs), rc);
2287
2302
Lines 2341-2346 Link Here
2341
        StringCbPrintf(HTTP_WORKER_HEADER_INDEX, MAX_PATH, HTTP_HEADER_TEMPLATE, WORKER_HEADER_INDEX_BASE, hInst);
2356
        StringCbPrintf(HTTP_WORKER_HEADER_INDEX, MAX_PATH, HTTP_HEADER_TEMPLATE, WORKER_HEADER_INDEX_BASE, hInst);
2342
2357
2343
        JK_INIT_CS(&init_cs, rc);
2358
        JK_INIT_CS(&init_cs, rc);
2359
        JK_INIT_CS(&log_cs, rc);
2344
2360
2345
    break;
2361
    break;
2346
    case DLL_PROCESS_DETACH:
2362
    case DLL_PROCESS_DETACH:
Lines 2350-2355 Link Here
2350
        __except(1) {
2366
        __except(1) {
2351
        }
2367
        }
2352
        JK_DELETE_CS(&init_cs, rc);
2368
        JK_DELETE_CS(&init_cs, rc);
2369
        JK_DELETE_CS(&log_cs, rc);
2353
        break;
2370
        break;
2354
2371
2355
    default:
2372
    default:
Lines 2393-2406 Link Here
2393
    return 0;
2410
    return 0;
2394
}
2411
}
2395
2412
2413
/*
2414
 * Reinitializes the logger, formatting the log file name if rotation is enabled,
2415
 * and calculating the next rotation time if applicable.
2416
 */
2417
static int init_logger(int rotate, jk_logger_t **l)
2418
{
2419
    int rc = JK_TRUE;
2420
    int log_open = rotate;  /* log is assumed open if a rotate is requested */
2421
    char *log_file_name;
2422
    char log_file_name_buf[MAX_PATH*2];
2423
2424
    /* If log rotation is enabled, format the log filename */
2425
    if ((log_rotationtime > 0) || (log_filesize > 0)) {
2426
        time_t t;
2427
        t = time(NULL);
2428
2429
        if (log_rotationtime > 0) {
2430
            /* Align time to rotationtime intervals */
2431
            t = (t / log_rotationtime) * log_rotationtime;
2432
2433
            /* Calculate rotate time */
2434
            log_next_rotate_time = t + log_rotationtime;
2435
        }
2436
2437
        log_file_name = log_file_name_buf;
2438
        if (strchr(log_file, '%')) {
2439
            struct tm *tm_now;
2440
2441
            /* If there are %s in the log file name, treat it as a sprintf format */
2442
            tm_now = localtime(&t);
2443
            strftime(log_file_name, sizeof(log_file_name_buf), log_file, tm_now);
2444
        } else {
2445
            /* Otherwise append the number of seconds to the base name */        
2446
            sprintf_s(log_file_name, sizeof(log_file_name_buf), "%s.%d", log_file, (long)t);
2447
        }
2448
    } else {
2449
        log_file_name = log_file;
2450
    }
2451
2452
    /* Close the current log file if required, and the effective log file name has changed */
2453
    if (log_open && strncmp(log_file_name, log_file_effective, strlen(log_file_name)) != 0) {
2454
        FILE* lf = ((jk_file_logger_t* )logger->logger_private)->logfile;
2455
        fprintf_s(lf, "Log rotated to %s\r\n", log_file_name);
2456
        fflush(lf);
2457
2458
        rc = jk_close_file_logger(&logger);
2459
        log_open = JK_FALSE;
2460
    }
2461
2462
    if (!log_open) {
2463
        if (jk_open_file_logger(&logger, log_file_name, log_level)) {
2464
            logger->log = iis_log_to_file;
2465
2466
            /* Remember the current log file name for the next potential rotate */
2467
            strcpy_s(log_file_effective, sizeof(log_file_effective), log_file_name);
2468
            rc = JK_TRUE;
2469
        } else {
2470
            logger = NULL;
2471
            rc = JK_FALSE;
2472
        }
2473
    }
2474
2475
    /* Update logger being used for this log call so it occurs on new file */
2476
    (*l) = logger;
2477
    return rc;
2478
}
2479
2480
/*
2481
 * Checks whether the log needs to be rotated. Must be called while holding the log lock.
2482
 * The behaviour here is based on the Apache rotatelogs program.
2483
 * http://httpd.apache.org/docs/2.0/programs/rotatelogs.html
2484
 */
2485
static int JK_METHOD rotate_log_file(jk_logger_t **l)
2486
{
2487
    int rc = JK_TRUE;
2488
    int rotate = JK_FALSE;
2489
2490
    if (log_rotationtime > 0) {
2491
        time_t t = time(NULL);
2492
        
2493
        if (t >= log_next_rotate_time) {
2494
            rotate = JK_TRUE;
2495
        }
2496
    } else if (log_filesize > 0) {
2497
        LARGE_INTEGER filesize;
2498
        HANDLE h = (HANDLE)_get_osfhandle(fileno(((jk_file_logger_t *)(*l)->logger_private)->logfile));
2499
        GetFileSizeEx(h, &filesize);
2500
2501
        if ((unsigned __int64)filesize.QuadPart >= log_filesize) {
2502
            rotate = JK_TRUE;
2503
        }
2504
    }
2505
    if (rotate) {
2506
        rc = init_logger(JK_TRUE, l);
2507
    }
2508
    return rc;
2509
}
2510
2511
/*
2512
 * Log messages to the log file, rotating the log when required.
2513
 */
2514
static int JK_METHOD iis_log_to_file(jk_logger_t *l, int level,
2515
                                    int used, char *what)
2516
{
2517
    int rc = JK_FALSE;
2518
2519
    if (l &&
2520
        (l->level <= level || level == JK_LOG_REQUEST_LEVEL) &&
2521
        l->logger_private && what && used > 0) {
2522
        jk_file_logger_t *p = l->logger_private;
2523
        rc = JK_TRUE;
2524
2525
        if (p->logfile) {
2526
            what[used++] = '\r';
2527
            what[used++] = '\n';
2528
            what[used] = '\0';
2529
    
2530
            /* Perform logging within critical section to protect rotation */
2531
            JK_ENTER_CS(&(log_cs), rc);
2532
            if (rc && rotate_log_file(&l)) {
2533
                /* The rotation process will reallocate the jk_logger_t structure, so refetch */ 
2534
                FILE *rotated = ((jk_file_logger_t *)l->logger_private)->logfile;
2535
                fputs(what, rotated);
2536
                fflush(rotated);
2537
                JK_LEAVE_CS(&(log_cs), rc);
2538
            }
2539
        }
2540
    }
2541
    return rc;
2542
}
2543
2396
static int init_jk(char *serverName)
2544
static int init_jk(char *serverName)
2397
{
2545
{
2398
    char shm_name[MAX_PATH];
2546
    char shm_name[MAX_PATH];
2399
    int rc = JK_FALSE;
2547
    int rc = JK_FALSE;
2400
2548
    
2401
    if (!jk_open_file_logger(&logger, log_file, log_level)) {
2549
    init_logger(JK_FALSE, &logger);
2402
        logger = NULL;
2403
    }
2404
    StringCbCopy(shm_name, MAX_PATH, SHM_DEF_NAME);
2550
    StringCbCopy(shm_name, MAX_PATH, SHM_DEF_NAME);
2405
2551
2406
    jk_log(logger, JK_LOG_INFO, "Starting %s", (VERSION_STRING));
2552
    jk_log(logger, JK_LOG_INFO, "Starting %s", (VERSION_STRING));
Lines 2431-2436 Link Here
2431
2577
2432
        jk_log(logger, JK_LOG_DEBUG, "Using log file %s.", log_file);
2578
        jk_log(logger, JK_LOG_DEBUG, "Using log file %s.", log_file);
2433
        jk_log(logger, JK_LOG_DEBUG, "Using log level %d.", log_level);
2579
        jk_log(logger, JK_LOG_DEBUG, "Using log level %d.", log_level);
2580
        jk_log(logger, JK_LOG_DEBUG, "Using log rotation time %d seconds.", log_rotationtime);
2581
        jk_log(logger, JK_LOG_DEBUG, "Using log file size %d bytes.", log_filesize);
2582
2434
        jk_log(logger, JK_LOG_DEBUG, "Using extension uri %s.", extension_uri);
2583
        jk_log(logger, JK_LOG_DEBUG, "Using extension uri %s.", extension_uri);
2435
        jk_log(logger, JK_LOG_DEBUG, "Using worker file %s.", worker_file);
2584
        jk_log(logger, JK_LOG_DEBUG, "Using worker file %s.", worker_file);
2436
        jk_log(logger, JK_LOG_DEBUG, "Using worker mount file %s.",
2585
        jk_log(logger, JK_LOG_DEBUG, "Using worker mount file %s.",
Lines 2459-2464 Link Here
2459
                                     DEFAULT_WORKER_THREADS);
2608
                                     DEFAULT_WORKER_THREADS);
2460
    }
2609
    }
2461
2610
2611
    if ((log_rotationtime > 0) && (log_filesize > 0)) {
2612
        jk_log(logger, JK_LOG_WARNING, 
2613
            "%s is defined in configuration, but will be ignored because %s is set. ",
2614
            LOG_FILESIZE_TAG, LOG_ROTATION_TIME_TAG);
2615
    }
2616
2462
    if (rewrite_rule_file[0] && jk_map_alloc(&rewrite_map)) {
2617
    if (rewrite_rule_file[0] && jk_map_alloc(&rewrite_map)) {
2463
        if (jk_map_read_properties(rewrite_map, NULL, rewrite_rule_file,
2618
        if (jk_map_read_properties(rewrite_map, NULL, rewrite_rule_file,
2464
                                   NULL, JK_MAP_HANDLE_RAW, logger)) {
2619
                                   NULL, JK_MAP_HANDLE_RAW, logger)) {
Lines 2640-2645 Link Here
2640
    if (get_config_parameter(src, JK_LOG_LEVEL_TAG, tmpbuf, sizeof(tmpbuf))) {
2795
    if (get_config_parameter(src, JK_LOG_LEVEL_TAG, tmpbuf, sizeof(tmpbuf))) {
2641
        log_level = jk_parse_log_level(tmpbuf);
2796
        log_level = jk_parse_log_level(tmpbuf);
2642
    }
2797
    }
2798
    if (get_config_parameter(src, LOG_ROTATION_TIME_TAG, tmpbuf, sizeof(tmpbuf))) {
2799
        log_rotationtime = atol(tmpbuf);
2800
        if (log_rotationtime < 0) {
2801
            log_rotationtime = 0;
2802
        }
2803
    }
2804
    if (get_config_parameter(src, LOG_FILESIZE_TAG, tmpbuf, sizeof(tmpbuf))) {
2805
        size_t tl = strlen(tmpbuf);
2806
        if (tl > 0) {
2807
            /* rotatelogs has an 'M' suffix on filesize, which we optionally support for consistency */
2808
            if (tmpbuf[tl - 1] == 'M') {
2809
                tmpbuf[tl - 1] = '\0';
2810
            }
2811
            log_filesize = atol(tmpbuf);
2812
            if (log_filesize < 0) {
2813
                log_filesize = 0;
2814
            }
2815
            /* Convert to MB as per Apache rotatelogs */
2816
            log_filesize *= (1000 * 1000);
2817
        }
2818
    }
2819
2643
    ok = ok && get_config_parameter(src, EXTENSION_URI_TAG, extension_uri, sizeof(extension_uri));
2820
    ok = ok && get_config_parameter(src, EXTENSION_URI_TAG, extension_uri, sizeof(extension_uri));
2644
    ok = ok && get_config_parameter(src, JK_WORKER_FILE_TAG, worker_file, sizeof(worker_file));
2821
    ok = ok && get_config_parameter(src, JK_WORKER_FILE_TAG, worker_file, sizeof(worker_file));
2645
    ok = ok && get_config_parameter(src, JK_MOUNT_FILE_TAG, worker_mount_file, sizeof(worker_mount_file));
2822
    ok = ok && get_config_parameter(src, JK_MOUNT_FILE_TAG, worker_mount_file, sizeof(worker_mount_file));
(-)xdocs/reference/iis.xml (+65 lines)
Lines 75-85 Link Here
75
<attribute name="log_file" required="false"><p>
75
<attribute name="log_file" required="false"><p>
76
A value pointing to location where log file will be created.
76
A value pointing to location where log file will be created.
77
(for example <b>c:\tomcat\logs\isapi.log</b>)
77
(for example <b>c:\tomcat\logs\isapi.log</b>)
78
<br/>If one of the log rotation settings (<b>log_rotationtime</b> or <b>log_filesize</b>) are specified then the actual log file name is based on this setting.
79
If the log file name includes any '%' characters, then it is treated as a format string for <code>strftime(3)</code>, 
80
e.g. <b>c:\tomcat\logs\isapi-%Y-%m-%d-%H_%M_%S.log</b>. Otherwise, the suffix <em>.nnnnnnnnnn</em> is automatically added and is the time in seconds.
81
A full list of format string substitutions can be found in the <a href="http://httpd.apache.org/docs/2.0/programs/rotatelogs.html">Apache rotatelogs documentation</a>
78
</p></attribute>
82
</p></attribute>
79
<attribute name="log_level" required="false"><p>
83
<attribute name="log_level" required="false"><p>
80
A string value for log level 
84
A string value for log level 
81
(can be debug, info, warn, error or trace).
85
(can be debug, info, warn, error or trace).
82
</p></attribute>
86
</p></attribute>
87
<attribute name="log_rotationtime" required="false"><p>
88
The time between log file rotations in seconds.
89
Setting this to 0 (the default) disables log rotation based on time. 
90
</p></attribute>
91
<attribute name="log_filesize" required="false"><p>
92
The maximum log file size in megabytes, after which the log file will be rotated. Setting this to 0 (the default) disables log rotation based on file size.
93
<br>The value can have an optional <b>M</b> suffix, i.e. both <b>5</b> and <b>5M</b> will rotate the log file when it grows to 5MB.
94
<br>If <b>log_rotationtime</b> is specified, then this setting is ignored.  
95
</p></attribute>
83
<attribute name="worker_file" required="true"><p>
96
<attribute name="worker_file" required="true"><p>
84
A string value which is the full path to workers.properties file
97
A string value which is the full path to workers.properties file
85
(for example <b>c:\tomcat\conf\workers.properties</b>)
98
(for example <b>c:\tomcat\conf\workers.properties</b>)
Lines 289-294 Link Here
289
</source></p>
302
</source></p>
290
</section>
303
</section>
291
304
305
<section name="Log file rotation">
306
<p>
307
The ISAPI redirector with version 1.2.29 can perform log rotation, with configuration and behaviour similar to the 
308
<a href="http://httpd.apache.org/docs/2.0/programs/rotatelogs.html">rotatelogs</a> program provided with Apache HTTP Server.
309
</p>
310
<p>
311
To configure log rotation, configure a <b>log_file</b>, and one of the <b>log_rotationtime</b> or <b>log_filesize</b> options.
312
If both are specified, the <b>log_rotationtime</b> will take precedence, and <b>log_filesize</b> will be ignored. 
313
<br/>For example, to configure daily rotation of the log file:
314
</p>
315
<source>
316
# Configuration file for the Jakarta ISAPI Redirector
317
...
318
319
# Full path to the log file for the ISAPI Redirector
320
log_file=c:\tomcat\logs\isapi_redirect.%Y-%m-%d.log
321
322
# Log level (debug, info, warn, error or trace)
323
log_level=info
324
325
# Rotate the log file every day
326
log_rotationtime=86400
327
328
...
329
</source>
330
<p>
331
Or to configure rotation of the log file when it reaches 5MB in size:
332
</p>
333
<source>
334
# Configuration file for the Jakarta ISAPI Redirector
335
...
336
337
# Full path to the log file for the ISAPI Redirector
338
log_file=c:\tomcat\logs\isapi_redirect.%Y-%m-%d-%H.log
339
340
# Log level (debug, info, warn, error or trace)
341
log_level=info
342
343
# Rotate the log file at 5 MB
344
log_filesize=5M
345
346
...
347
</source>
348
<p>
349
The log will be rotated whenever the configured limit is reached, but only if the log file name would change. If you configure
350
 a log file name with <code>strftime(3)</code> format codes in it, then ensure it specifies the same granularity
351
 as the rotation time configured, e.g. <b>%Y-%m-%d</b> if rotating daily (<b>log_rotationtime=86400</b>).
352
<br/>See the <a href="http://httpd.apache.org/docs/2.0/programs/rotatelogs.html">rotatelogs</a> documentation for more examples.
353
</p>
354
355
</section>
356
292
<section name="Using a simple rewrite rules">
357
<section name="Using a simple rewrite rules">
293
<p>
358
<p>
294
The ISAPI redirector with version 1.2.16 can do a simple URL rewriting. Although not
359
The ISAPI redirector with version 1.2.16 can do a simple URL rewriting. Although not

Return to bug 48501