Home | History | Annotate | Download | only in back
      1 /*
      2  * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
      3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      4  *
      5  * This code is free software; you can redistribute it and/or modify it
      6  * under the terms of the GNU General Public License version 2 only, as
      7  * published by the Free Software Foundation.  Oracle designates this
      8  * particular file as subject to the "Classpath" exception as provided
      9  * by Oracle in the LICENSE file that accompanied this code.
     10  *
     11  * This code is distributed in the hope that it will be useful, but WITHOUT
     12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  * version 2 for more details (a copy is included in the LICENSE file that
     15  * accompanied this code).
     16  *
     17  * You should have received a copy of the GNU General Public License version
     18  * 2 along with this work; if not, write to the Free Software Foundation,
     19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     20  *
     21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     22  * or visit www.oracle.com if you need additional information or have any
     23  * questions.
     24  */
     25 
     26 #include "util.h"
     27 
     28 #include <time.h>
     29 #include <errno.h>
     30 #include <sys/types.h>
     31 
     32 #include "proc_md.h"
     33 
     34 #include "log_messages.h"
     35 
     36 #ifdef JDWP_LOGGING
     37 
     38 #define MAXLEN_INTEGER          20
     39 #define MAXLEN_FILENAME         256
     40 #define MAXLEN_TIMESTAMP        80
     41 #define MAXLEN_LOCATION         (MAXLEN_FILENAME+MAXLEN_INTEGER+16)
     42 #define MAXLEN_MESSAGE          256
     43 #define MAXLEN_EXEC             (MAXLEN_FILENAME*2+MAXLEN_INTEGER+16)
     44 
     45 static MUTEX_T my_mutex = MUTEX_INIT;
     46 
     47 /* Static variables (should be protected with mutex) */
     48 static int logging;
     49 static FILE * log_file;
     50 static char logging_filename[MAXLEN_FILENAME+1+6];
     51 static char location_stamp[MAXLEN_LOCATION+1];
     52 static PID_T processPid;
     53 static int open_count;
     54 
     55 /* Ascii id of current native thread. */
     56 static void
     57 get_time_stamp(char *tbuf, size_t ltbuf)
     58 {
     59     char format[MAXLEN_TIMESTAMP+1];
     60     unsigned millisecs = 0;
     61     time_t t = 0;
     62 
     63     GETMILLSECS(millisecs);
     64     if ( time(&t) == (time_t)(-1) )
     65         t = 0;
     66     (void)strftime(format, sizeof(format),
     67                 /* Break this string up for SCCS's sake */
     68                 "%" "d.%" "m.%" "Y %" "T.%%.3d %" "Z", localtime(&t));
     69     (void)snprintf(tbuf, ltbuf, format, (int)(millisecs));
     70 }
     71 
     72 /* Get basename of filename */
     73 static const char *
     74 file_basename(const char *file)
     75 {
     76     char *p1;
     77     char *p2;
     78 
     79     if ( file==NULL )
     80         return "unknown";
     81     p1 = strrchr(file, '\\');
     82     p2 = strrchr(file, '/');
     83     p1 = ((p1 > p2) ? p1 : p2);
     84     if (p1 != NULL) {
     85         file = p1 + 1;
     86     }
     87     return file;
     88 }
     89 
     90 /* Fill in the exact source location of the LOG entry. */
     91 static void
     92 fill_location_stamp(const char *flavor, const char *file, int line)
     93 {
     94     (void)snprintf(location_stamp, sizeof(location_stamp),
     95                     "%s:\"%s\":%d;",
     96                     flavor, file_basename(file), line);
     97     location_stamp[sizeof(location_stamp)-1] = 0;
     98 }
     99 
    100 /* Begin a log entry. */
    101 void
    102 log_message_begin(const char *flavor, const char *file, int line)
    103 {
    104     MUTEX_LOCK(my_mutex); /* Unlocked in log_message_end() */
    105     if ( logging ) {
    106         location_stamp[0] = 0;
    107         fill_location_stamp(flavor, file, line);
    108     }
    109 }
    110 
    111 /* Standard Logging Format Entry */
    112 static void
    113 standard_logging_format(FILE *fp,
    114         const char *datetime,
    115         const char *level,
    116         const char *product,
    117         const char *module,
    118         const char *optional,
    119         const char *messageID,
    120         const char *message)
    121 {
    122     const char *format;
    123 
    124     /* "[#|Date&Time&Zone|LogLevel|ProductName|ModuleID|
    125      *     OptionalKey1=Value1;OptionalKeyN=ValueN|MessageID:MessageText|#]\n"
    126      */
    127 
    128     format="[#|%s|%s|%s|%s|%s|%s:%s|#]\n";
    129 
    130     print_message(fp, "", "", format,
    131             datetime,
    132             level,
    133             product,
    134             module,
    135             optional,
    136             messageID,
    137             message);
    138 }
    139 
    140 /* End a log entry */
    141 void
    142 log_message_end(const char *format, ...)
    143 {
    144     if ( logging ) {
    145         va_list ap;
    146         THREAD_T tid;
    147         char datetime[MAXLEN_TIMESTAMP+1];
    148         const char *level;
    149         const char *product;
    150         const char *module;
    151         char optional[MAXLEN_INTEGER+6+MAXLEN_INTEGER+6+MAXLEN_LOCATION+1];
    152         const char *messageID;
    153         char message[MAXLEN_MESSAGE+1];
    154 
    155         /* Grab the location, start file if needed, and clear the lock */
    156         if ( log_file == NULL && open_count == 0 && logging_filename[0] != 0 ) {
    157             open_count++;
    158             log_file = fopen(logging_filename, "w");
    159             if ( log_file!=NULL ) {
    160                 (void)setvbuf(log_file, NULL, _IOLBF, BUFSIZ);
    161             } else {
    162                 logging = 0;
    163             }
    164         }
    165 
    166         if ( log_file != NULL ) {
    167 
    168             /* Get the rest of the needed information */
    169             tid = GET_THREAD_ID();
    170             level = "FINEST"; /* FIXUP? */
    171             product = "J2SE1.5"; /* FIXUP? */
    172             module = "jdwp"; /* FIXUP? */
    173             messageID = ""; /* FIXUP: Unique message string ID? */
    174             (void)snprintf(optional, sizeof(optional),
    175                         "LOC=%s;PID=%d;THR=t@%d",
    176                         location_stamp,
    177                         (int)processPid,
    178                         (int)tid);
    179 
    180             /* Construct message string. */
    181             va_start(ap, format);
    182             (void)vsnprintf(message, sizeof(message), format, ap);
    183             va_end(ap);
    184 
    185             get_time_stamp(datetime, sizeof(datetime));
    186 
    187             /* Send out standard logging format message */
    188             standard_logging_format(log_file,
    189                 datetime,
    190                 level,
    191                 product,
    192                 module,
    193                 optional,
    194                 messageID,
    195                 message);
    196         }
    197         location_stamp[0] = 0;
    198     }
    199     MUTEX_UNLOCK(my_mutex); /* Locked in log_message_begin() */
    200 }
    201 
    202 #endif
    203 
    204 /* Set up the logging with the name of a logging file. */
    205 void
    206 setup_logging(const char *filename, unsigned flags)
    207 {
    208 #ifdef JDWP_LOGGING
    209     FILE *fp = NULL;
    210 
    211     /* Turn off logging */
    212     logging = 0;
    213     gdata->log_flags = 0;
    214 
    215     /* Just return if not doing logging */
    216     if ( filename==NULL || flags==0 )
    217         return;
    218 
    219     /* Create potential filename for logging */
    220     processPid = GETPID();
    221     (void)snprintf(logging_filename, sizeof(logging_filename),
    222                     "%s.%d", filename, (int)processPid);
    223 
    224     /* Turn on logging (do this last) */
    225     logging = 1;
    226     gdata->log_flags = flags;
    227 
    228 #endif
    229 }
    230 
    231 /* Finish up logging, flush output to the logfile. */
    232 void
    233 finish_logging()
    234 {
    235 #ifdef JDWP_LOGGING
    236     MUTEX_LOCK(my_mutex);
    237     if ( logging ) {
    238         logging = 0;
    239         if ( log_file != NULL ) {
    240             (void)fflush(log_file);
    241             (void)fclose(log_file);
    242             log_file = NULL;
    243         }
    244     }
    245     MUTEX_UNLOCK(my_mutex);
    246 #endif
    247 }
    248