Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

Event.d

Go to the documentation of this file.
00001 /*******************************************************************************
00002 
00003         @file Event.d
00004 
00005         Copyright (c) 2004 Kris Bell
00006         
00007         This software is provided 'as-is', without any express or implied
00008         warranty. In no event will the authors be held liable for damages
00009         of any kind arising from the use of this software.
00010         
00011         Permission is hereby granted to anyone to use this software for any 
00012         purpose, including commercial applications, and to alter it and/or 
00013         redistribute it freely, subject to the following restrictions:
00014         
00015         1. The origin of this software must not be misrepresented; you must 
00016            not claim that you wrote the original software. If you use this 
00017            software in a product, an acknowledgment within documentation of 
00018            said product would be appreciated but is not required.
00019 
00020         2. Altered source versions must be plainly marked as such, and must 
00021            not be misrepresented as being the original software.
00022 
00023         3. This notice may not be removed or altered from any distribution
00024            of the source.
00025 
00026         4. Derivative works are permitted, but they must carry this notice
00027            in full and credit the original source.
00028 
00029 
00030                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00031 
00032       
00033         @version        Initial version, May 2004
00034         @author         Kris
00035                         Anders F Bjorklund (Darwin patches)
00036 
00037 
00038 *******************************************************************************/
00039 
00040 module mango.log.Event;
00041 
00042 version = UseEventFreeList;
00043 
00044 private import  mango.log.Hierarchy;
00045 
00046 private import  mango.log.model.ILevel;
00047 
00048 /*******************************************************************************
00049 
00050         Haul in additional O/S specific imports
00051 
00052 *******************************************************************************/
00053 
00054 version (Win32)
00055 {
00056         private import std.c.windows.windows;
00057 
00058         extern(Windows) int QueryPerformanceCounter(ulong *count);
00059         extern(Windows) int QueryPerformanceFrequency(ulong *frequency);
00060 }
00061 
00062 version (Posix)
00063 {
00064         version (linux)
00065                  private import std.c.linux.linux;
00066 
00067         version (darwin)
00068                  private import std.c.darwin.darwin;
00069 }
00070 
00071 /*******************************************************************************
00072 
00073         Contains all information about a logging event, and is passed around
00074         between methods once it has been determined that the invoking logger
00075         is enabled for output.
00076 
00077         Note that Event instances are maintained in a freelist rather than
00078         being allocated each time, and they include a scratchpad area for
00079         Layout formatters to use.
00080 
00081 *******************************************************************************/
00082 
00083 public class Event : ILevel
00084 {
00085         // primary event attributes
00086         private char[]          msg,
00087                                 name;
00088         private ulong           time;
00089         private Level           level;
00090         private Hierarchy       hierarchy;
00091 
00092         // timestamps
00093         private static ulong    epochTime;
00094         private static ulong    beginTime;
00095 
00096         // scratch buffer for constructing output strings
00097         struct  Scratch
00098                 {
00099                 uint            length;
00100                 char[256]       content;
00101                 }
00102         package Scratch         scratch;
00103 
00104 
00105         // logging-level names
00106         package static char[][] LevelNames = 
00107         [
00108                 "TRACE ", "INFO ", "WARN ", "ERROR ", "FATAL ", "NONE "
00109         ];
00110 
00111         version (Win32)
00112         {
00113                 private static uint frequency;
00114         }
00115 
00116         version (UseEventFreeList)
00117         {
00118                 /***************************************************************
00119 
00120                         Instance variables for free-list support
00121 
00122                 ***************************************************************/
00123 
00124                 private Event           next;   
00125                 private static Event    freelist;
00126 
00127                 /***************************************************************
00128 
00129                         Allocate an Event from a list rather than 
00130                         creating a new one
00131 
00132                 ***************************************************************/
00133 
00134                 static final synchronized Event allocate ()
00135                 {       
00136                         Event e;
00137 
00138                         if (freelist)
00139                            {
00140                            e = freelist;
00141                            freelist = e.next;
00142                            }
00143                         else
00144                            e = new Event ();                                
00145                         return e;
00146                 }
00147 
00148                 /***************************************************************
00149 
00150                         Return this Event to the free-list
00151 
00152                 ***************************************************************/
00153 
00154                 static final synchronized void deallocate (Event e)
00155                 { 
00156                         e.next = freelist;
00157                         freelist = e;
00158 
00159                         version (EventReset)
00160                                  e.reset();
00161                 }
00162         }
00163 
00164         /***********************************************************************
00165                 
00166                 Setup the timing information for later use. Note how much 
00167                 effort it takes to get epoch time in Win32 ...
00168 
00169         ***********************************************************************/
00170 
00171         static this ()
00172         {
00173                 version (Posix)       
00174                 {
00175                         timeval tv;
00176 
00177                         if (gettimeofday (&tv, null))
00178                             throw new Exception ("high-resolution timer is not available");
00179                         
00180                         epochTime = 1000L * tv.tv_sec;
00181                         beginTime = epochTime + tv.tv_usec / 1000;
00182                 }
00183 
00184                 version (Win32)
00185                 {
00186                         ulong           time;
00187                         ulong           freq;
00188 
00189                         if (! QueryPerformanceFrequency (&freq))
00190                               throw new Exception ("high-resolution timer is not available");
00191                                
00192                         frequency = freq / 1000;
00193                         QueryPerformanceCounter (&time);
00194                         beginTime = time / frequency;
00195 
00196                         SYSTEMTIME      sTime;
00197                         FILETIME        fTime;
00198 
00199                         GetSystemTime (&sTime);
00200                         SystemTimeToFileTime (&sTime, &fTime);
00201                         
00202                         ulong time1 = (cast(long) fTime.dwHighDateTime) << 32 | 
00203                                                   fTime.dwLowDateTime;
00204 
00205                         // first second of 1970 ...
00206                         sTime.wYear = 1970;
00207                         sTime.wMonth = 1;
00208                         sTime.wDayOfWeek = 0;
00209                         sTime.wDay = 1;
00210                         sTime.wHour = 0;
00211                         sTime.wMinute = 0;
00212                         sTime.wSecond = 0;
00213                         sTime.wMilliseconds = 0;
00214                         SystemTimeToFileTime (&sTime, &fTime);
00215 
00216                         ulong time2 = (cast(long) fTime.dwHighDateTime) << 32 | 
00217                                                   fTime.dwLowDateTime;
00218                         
00219                         epochTime = (time1 - time2) / 10_000;
00220                 }
00221         }
00222 
00223         /***********************************************************************
00224                 
00225                 Return the number of milliseconds since the executable
00226                 was started.
00227 
00228         ***********************************************************************/
00229 
00230         final static ulong getRuntime ()
00231         {
00232                 version (Posix)       
00233                 {
00234                         timeval tv;
00235 
00236                         gettimeofday (&tv, null);
00237                         return ((cast(ulong) tv.tv_sec) * 1000 + tv.tv_usec / 1000) - beginTime;
00238                 }
00239 
00240                 version (Win32)
00241                 {
00242                         ulong time;
00243 
00244                         QueryPerformanceCounter (&time);
00245                         return (time / frequency) - beginTime;
00246                 }
00247         }
00248 
00249         /***********************************************************************
00250                 
00251                 Set the various attributes of this event.
00252 
00253         ***********************************************************************/
00254 
00255         final void set (Hierarchy hierarchy, Level level, char[] msg, char[] name)
00256         {
00257                 this.hierarchy = hierarchy;
00258                 this.time = getRuntime ();
00259                 this.level = level;
00260                 this.name = name;
00261                 this.msg = msg;
00262         }
00263 
00264         version (EventReset)
00265         {
00266                 /***************************************************************
00267 
00268                         Reset this event
00269 
00270                 ***************************************************************/
00271 
00272                 final void reset ()
00273                 {
00274                         time = 0;
00275                         msg = null;
00276                         name = null;
00277                         level = Level.None;
00278                 }
00279         }
00280 
00281         /***********************************************************************
00282                 
00283                 Return the message attached to this event.
00284 
00285         ***********************************************************************/
00286 
00287         final override char[] toString ()
00288         {
00289                 return msg;
00290         }
00291 
00292         /***********************************************************************
00293                 
00294                 Return the name of the logger which produced this event
00295 
00296         ***********************************************************************/
00297 
00298         final char[] getName ()
00299         {
00300                 return name;
00301         }
00302 
00303         /***********************************************************************
00304                 
00305                 Return the scratch buffer for formatting. This is a thread
00306                 safe place to format data within, without allocating any
00307                 memory.
00308 
00309         ***********************************************************************/
00310 
00311         final char[] getContent ()
00312         {
00313                 return scratch.content [0..scratch.length];
00314         }
00315 
00316         /***********************************************************************
00317                 
00318                 Return the logger level of this event.
00319 
00320         ***********************************************************************/
00321 
00322         final Level getLevel ()
00323         {
00324                 return level;
00325         }
00326 
00327         /***********************************************************************
00328                 
00329                 Return the logger level name of this event.
00330 
00331         ***********************************************************************/
00332 
00333         final char[] getLevelName ()
00334         {
00335                 return LevelNames[level];
00336         }
00337 
00338         /***********************************************************************
00339                 
00340                 Return the hierarchy where the event was produced from
00341 
00342         ***********************************************************************/
00343 
00344         final Hierarchy getHierarchy ()
00345         {
00346                 return hierarchy;
00347         }
00348 
00349         /***********************************************************************
00350                 
00351                 Return the time this event was produced, relative to the 
00352                 start of this executable
00353 
00354         ***********************************************************************/
00355 
00356         final long getTime ()
00357         {
00358                 return time;
00359         }
00360 
00361         /***********************************************************************
00362                
00363                 Return the time this event was produced, relative to 
00364                 Jan 1st 1970
00365 
00366         ***********************************************************************/
00367 
00368         final ulong getEpochTime ()
00369         {
00370                 return time + epochTime;
00371         }
00372 
00373         /***********************************************************************
00374 
00375                 Append some content to the scratch buffer. This is limited
00376                 to the size of said buffer, and will not expand further.
00377 
00378         ***********************************************************************/
00379 
00380         final Event append (char[] x)
00381         {
00382                 uint addition = x.length;
00383                 uint newLength = scratch.length + x.length;
00384 
00385                 if (newLength < scratch.content.length)
00386                    {
00387                    scratch.content [scratch.length..newLength] = x[0..addition];
00388                    scratch.length = newLength;
00389                    }
00390                 return this;
00391         }
00392 }

Generated on Fri May 27 18:11:55 2005 for Mango by  doxygen 1.4.0