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

Generated on Sat Apr 9 20:11:25 2005 for Mango by doxygen 1.3.6