Main Page | Class Hierarchy | Alphabetical List | Class List | 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 
00036 
00037 *******************************************************************************/
00038 
00039 module mango.log.Event;
00040 
00041 version = UseEventFreeList;
00042 
00043 private import  mango.log.Hierarchy;
00044 
00045 private import  mango.log.model.ILevel;
00046 
00047 /*******************************************************************************
00048 
00049         Haul in additional O/S specific imports
00050 
00051 *******************************************************************************/
00052 
00053 version (Win32)
00054 {
00055         private import std.c.windows.windows;
00056 
00057         extern(Windows) int QueryPerformanceCounter(ulong *count);
00058         extern(Windows) int QueryPerformanceFrequency(ulong *frequency);
00059 }
00060 
00061 version (Posix)
00062 {
00063         private import std.c.linux.linux;
00064 }
00065 
00066 /*******************************************************************************
00067 
00068         Contains all information about a logging event, and is passed around
00069         between methods once it has been determined that the invoking logger
00070         is enabled for output.
00071 
00072         Note that Event instances are maintained in a freelist rather than
00073         being allocated each time, and they include a scratchpad area for
00074         Layout formatters to use.
00075 
00076 *******************************************************************************/
00077 
00078 public class Event : ILevel
00079 {
00080         struct  Scratch
00081                 {
00082                 uint            length;
00083                 char[256]       content;
00084                 }
00085 
00086         package Scratch         scratch;
00087         private char[]          msg,
00088                                 name;
00089         private ulong           time;
00090         private Level           level;
00091         private Hierarchy       hierarchy;
00092 
00093         private static uint     epochTime;
00094         private static ulong    beginTime;
00095 
00096         version (Win32)
00097         {
00098         private static uint     frequency;
00099         }
00100 
00101         version (UseEventFreeList)
00102         {
00103                 /***************************************************************
00104 
00105                         Instance variables for free-list support
00106 
00107                 ***************************************************************/
00108 
00109                 private Event           next;   
00110                 private static Event    freelist;
00111 
00112                 /***************************************************************
00113 
00114                         Allocate an Event from a list rather than 
00115                         creating a new one
00116 
00117                 ***************************************************************/
00118 
00119                 static final synchronized Event allocate ()
00120                 {       
00121                         Event e;
00122 
00123                         if (freelist)
00124                            {
00125                            e = freelist;
00126                            freelist = e.next;
00127                            }
00128                         else
00129                            e = new Event ();                                
00130                         return e;
00131                 }
00132 
00133                 /***************************************************************
00134 
00135                         Return this Event to the free-list
00136 
00137                 ***************************************************************/
00138 
00139                 static final synchronized void deallocate (Event e)
00140                 { 
00141                         e.next = freelist;
00142                         freelist = e;
00143 
00144                         version (EventReset)
00145                                  e.reset();
00146                 }
00147         }
00148 
00149         /***********************************************************************
00150                 
00151                 Setup the timing information for later use. Note how much 
00152                 effort it takes to get epoch time in Win32 ...
00153 
00154         ***********************************************************************/
00155 
00156         static this ()
00157         {
00158                 version (Posix)       
00159                 {
00160                         timeval tv;
00161 
00162                         if (gettimeofday (&tv, null))
00163                             throw new Exception ("high-resolution timer is not available");
00164                         
00165                         epochTime = tv.tv_sec;
00166                         beginTime = (cast(ulong) tv.tv_sec) * 1000 + tv.tv_usec / 1000;
00167                 }
00168 
00169                 version (Win32)
00170                 {
00171                         ulong           time;
00172                         ulong           freq;
00173 
00174                         if (! QueryPerformanceFrequency (&freq))
00175                               throw new Exception ("high-resolution timer is not available");
00176                                
00177                         frequency = freq / 1000;
00178                         QueryPerformanceCounter (&time);
00179                         beginTime = time / frequency;
00180 
00181                         SYSTEMTIME      sTime;
00182                         FILETIME        fTime;
00183 
00184                         GetSystemTime (&sTime);
00185                         SystemTimeToFileTime (&sTime, &fTime);
00186                         
00187                         ulong time1 = (cast(long) fTime.dwHighDateTime) << 32 | 
00188                                                   fTime.dwLowDateTime;
00189 
00190                         // first second of 1970 ...
00191                         sTime.wYear = 1969;
00192                         sTime.wMonth = 12;
00193                         sTime.wDayOfWeek = 3;
00194                         sTime.wDay = 31;
00195                         sTime.wHour = 23;
00196                         sTime.wMinute = 0;
00197                         sTime.wSecond = 0;
00198                         sTime.wMilliseconds = 0;
00199                         SystemTimeToFileTime (&sTime, &fTime);
00200 
00201                         ulong time2 = (cast(long) fTime.dwHighDateTime) << 32 | 
00202                                                   fTime.dwLowDateTime;
00203                         
00204                         epochTime = (time1 - time2) / 10_000_000;
00205                 }
00206         }
00207 
00208         /***********************************************************************
00209                 
00210                 Return the number of milliseconds since the executable
00211                 was started.
00212 
00213         ***********************************************************************/
00214 
00215         final static ulong getUptime ()
00216         {
00217                 version (Posix)       
00218                 {
00219                         timeval tv;
00220 
00221                         gettimeofday (&tv, null);
00222                         return ((cast(ulong) tv.tv_sec) * 1000 + tv.tv_usec / 1000) - beginTime;
00223                 }
00224 
00225                 version (Win32)
00226                 {
00227                         ulong time;
00228 
00229                         QueryPerformanceCounter (&time);
00230                         return (time / frequency) - beginTime;
00231                 }
00232         }
00233 
00234         /***********************************************************************
00235                 
00236                 Set the various attributes of this event.
00237 
00238         ***********************************************************************/
00239 
00240         final void set (Hierarchy hierarchy, Level level, char[] msg, char[] name)
00241         {
00242                 this.hierarchy = hierarchy;
00243                 this.time = getUptime ();
00244                 this.level = level;
00245                 this.name = name;
00246                 this.msg = msg;
00247         }
00248 
00249         version (EventReset)
00250         {
00251                 /***************************************************************
00252 
00253                         Reset this event
00254 
00255                 ***************************************************************/
00256 
00257                 final void reset ()
00258                 {
00259                         time = 0;
00260                         msg = null;
00261                         name = null;
00262                         level = Level.None;
00263                 }
00264         }
00265 
00266         /***********************************************************************
00267                 
00268                 Return the message attached to this event.
00269 
00270         ***********************************************************************/
00271 
00272         final override char[] toString ()
00273         {
00274                 return msg;
00275         }
00276 
00277         /***********************************************************************
00278                 
00279                 Return the name of the logger which produced this event
00280 
00281         ***********************************************************************/
00282 
00283         final char[] getName ()
00284         {
00285                 return name;
00286         }
00287 
00288         /***********************************************************************
00289                 
00290                 Return the scratch buffer for formatting. This is a thread
00291                 safe place to format data within, without allocating any
00292                 memory.
00293 
00294         ***********************************************************************/
00295 
00296         final char[] getContent ()
00297         {
00298                 return scratch.content [0..scratch.length];
00299         }
00300 
00301         /***********************************************************************
00302                 
00303                 Return the logger level of this event.
00304 
00305         ***********************************************************************/
00306 
00307         final Level getLevel ()
00308         {
00309                 return level;
00310         }
00311 
00312         /***********************************************************************
00313                 
00314                 Return the hierarchy where the event was produced from
00315 
00316         ***********************************************************************/
00317 
00318         final Hierarchy getHierarchy ()
00319         {
00320                 return hierarchy;
00321         }
00322 
00323         /***********************************************************************
00324                 
00325                 Return the time this event was produced
00326 
00327         ***********************************************************************/
00328 
00329         final long getTime ()
00330         {
00331                 return time;
00332         }
00333 
00334         /***********************************************************************
00335                 
00336                 Return the number of seconds since Jan 1st 1970
00337 
00338         ***********************************************************************/
00339 
00340         final uint getEpochSeconds ()
00341         {
00342                 return (time / 1000) + epochTime;
00343         }
00344 
00345         /***********************************************************************
00346                
00347                 Return the number of milliseconds since Jan 1st 1970
00348 
00349         ***********************************************************************/
00350 
00351         final ulong getEpochMilliSeconds ()
00352         {
00353                 return time + (cast(ulong) epochTime) * 1000;
00354         }
00355 
00356         /***********************************************************************
00357 
00358                 Isolate the millisecond portion of the event timestamp
00359 
00360         ***********************************************************************/
00361 
00362         final uint getMilliSeconds ()
00363         {
00364                 return time % 1000;
00365         }
00366 
00367         /***********************************************************************
00368 
00369                 Append some content to the scratch buffer. This is limited
00370                 to the size of said buffer, and will not expand further.
00371 
00372         ***********************************************************************/
00373 
00374         final Event append (char[] x)
00375         {
00376                 uint addition = x.length;
00377                 uint newLength = scratch.length + x.length;
00378 
00379                 if (newLength < scratch.content.length)
00380                    {
00381                    scratch.content [scratch.length..newLength] = x[0..addition];
00382                    scratch.length = newLength;
00383                    }
00384                 return this;
00385         }
00386 }

Generated on Tue Jan 25 21:18:21 2005 for Mango by doxygen 1.3.6