00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
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
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
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 public class Event : ILevel
00084 {
00085
00086 private char[] msg,
00087 name;
00088 private ulong time;
00089 private Level level;
00090 private Hierarchy hierarchy;
00091
00092
00093 private static ulong epochTime;
00094 private static ulong beginTime;
00095
00096
00097 struct Scratch
00098 {
00099 uint length;
00100 char[256] content;
00101 }
00102 package Scratch scratch;
00103
00104
00105
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
00121
00122
00123
00124 private Event next;
00125 private static Event freelist;
00126
00127
00128
00129
00130
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
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
00167
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
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
00226
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
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
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
00284
00285
00286
00287 final override char[] toString ()
00288 {
00289 return msg;
00290 }
00291
00292
00293
00294
00295
00296
00297
00298 final char[] getName ()
00299 {
00300 return name;
00301 }
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311 final char[] getContent ()
00312 {
00313 return scratch.content [0..scratch.length];
00314 }
00315
00316
00317
00318
00319
00320
00321
00322 final Level getLevel ()
00323 {
00324 return level;
00325 }
00326
00327
00328
00329
00330
00331
00332
00333 final char[] getLevelName ()
00334 {
00335 return LevelNames[level];
00336 }
00337
00338
00339
00340
00341
00342
00343
00344 final Hierarchy getHierarchy ()
00345 {
00346 return hierarchy;
00347 }
00348
00349
00350
00351
00352
00353
00354
00355
00356 final long getTime ()
00357 {
00358 return time;
00359 }
00360
00361
00362
00363
00364
00365
00366
00367
00368 final ulong getEpochTime ()
00369 {
00370 return time + epochTime;
00371 }
00372
00373
00374
00375
00376
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 }