1
2 /* Web Polygraph http://www.web-polygraph.org/
3 * Copyright 2003-2011 The Measurement Factory
4 * Licensed under the Apache License, Version 2.0 */
5
6 #ifndef POLYGRAPH__BASE_OLOG_H
7 #define POLYGRAPH__BASE_OLOG_H
8
9 #include "xstd/h/iosfwd.h"
10 #include "xstd/Time.h"
11 #include "xstd/Size.h"
12 #include "xstd/NetDouble.h"
13 #include "xstd/BigSize.h"
14 #include "xstd/String.h"
15 #include "xstd/NetAddr.h"
16 #include "xstd/Array.h"
17 #include "xstd/Endian.h"
18
19 // some environments do not know better than #define these
20 #ifdef getc
21 # undef getc
22 #endif
23 #ifdef putc
24 # undef putc
25 #endif
26
27 namespace zlib {
28 class OFStream;
29 }
30
31 // buffered binary output log
32 class OLog {
33 public:
34 typedef void (Manip)(class OLog &);
35
36 public:
37 OLog();
38 virtual ~OLog();
39
capacity()40 Size capacity() const { return theCapacity; }
size()41 Size size() const { return theSize; }
42
43 void stream(const String &aName, ostream *aStream);
44 void capacity(Size aCap);
45
putc(char c)46 void putc(char c) { put(&c, 1); }
putb(bool b)47 void putb(bool b) { putc((char)(b ? 1 : 0)); }
puti(int x)48 void puti(int x) { x = htonl(x); put(&x, SizeOf(x)); }
49 void puti(const int *x, int count);
puti64(int64_t x)50 void puti64(int64_t x) { x = htobe64(x); put(&x, SizeOf(x)); }
puts(const char * s,Size size)51 void puts(const char *s, Size size) { puti(size); if (size) put(s, size); }
puta(const struct sockaddr_storage & a)52 void puta(const struct sockaddr_storage &a) { put(&a, SizeOf(a)); }
53
54 virtual void begEntry(int tag);
55 void endEntry();
56
57 void flush(Size maxSize); // flushes up-to max size
flush()58 void flush() { flush(theSize); }
59 void close(); // flushes if needed
60
61 protected:
62 void resize(Size minCap);
63
64 inline void put(const void *buf, Size size);
65 void write(const char *const buf, const Size size);
66 void overflow(const void *buf, Size size);
67
68 virtual void putHeader();
69 virtual void putTrailer();
70
71 protected:
72 ostream *theStream;
73 zlib::OFStream *theZStream;
74 String theName;
75
76 char *theBuf;
77 Size theCapacity; // buffer space allocated
78 Size theSize; // buffer space used
79 Size thePos; // global offset
80
81 char *theEntry; // start of the current entry
82 int theEntryTag; // tag saved until endEntry()
83
84 Array<int> theDir; // directory (one entry per tag)
85 };
86
87
88 /* manipulators to begin and end logging of a named entry */
89
90 struct bege {
begebege91 bege(int t, int cat): tag(t | (cat << 16)) {}
92 int tag;
93 };
94
ende(OLog & log)95 inline void ende(OLog &log) { log.endEntry(); }
96
97
98 /* logging of common types */
99
100 inline
101 OLog &operator <<(OLog &ol, char c) {
102 ol.putc(c);
103 return ol;
104 }
105
106 inline
107 OLog &operator <<(OLog &ol, bool b) {
108 ol.putb(b);
109 return ol;
110 }
111
112 inline
113 OLog &operator <<(OLog &ol, int x) {
114 ol.puti(x);
115 return ol;
116 }
117
118 inline
119 OLog &operator <<(OLog &ol, const int64_t x) {
120 ol.puti64(x);
121 return ol;
122 }
123
124 inline
125 OLog &operator <<(OLog &ol, double x) {
126 NetDouble nd(x);
127 return ol << nd.mnt << nd.exp;
128 }
129
130 inline
131 OLog &operator <<(OLog &ol, const char *s) {
132 ol.puts(s, strlen(s)+1);
133 return ol;
134 }
135
136 inline
137 OLog &operator <<(OLog &ol, const String &s) {
138 if (s)
139 ol.puts(s.cstr(), s.len()+1);
140 else
141 ol.puts(0, 0);
142 return ol;
143 }
144
145 inline
146 OLog &operator <<(OLog &ol, const Time &t) {
147 ol.puti(t.tv_sec);
148 ol.puti(t.tv_usec);
149 return ol;
150 }
151
152 inline
153 OLog &operator <<(OLog &ol, const BigSize &bs) {
154 return ol << bs.theAcc << bs.theCnt;
155 }
156
157 // XXX: should log either A or N
158 inline
159 OLog &operator <<(OLog &ol, const NetAddr &a) {
160 ol.puta(a.addrN().sockAddr(a.port()));
161 return ol;
162 }
163
164 inline
165 OLog &operator <<(OLog &ol, const bege &b) {
166 ol.begEntry(b.tag);
167 return ol;
168 }
169
170 inline
171 OLog &operator <<(OLog &ol, OLog::Manip m) {
172 m(ol);
173 return ol;
174 }
175
176 template <class Item>
177 inline
178 OLog &operator <<(OLog &ol, const Array<Item> &a) {
179 ol.puti(a.count());
180 for (int i = 0; i < a.count(); ++i)
181 ol << a[i];
182 return ol;
183 }
184
185 // store array of not-null pointers to items
186 template <class Item>
187 inline
188 OLog &operator <<(OLog &ol, const Array<Item *> &a) {
189 ol.puti(a.count());
190 for (int i = 0; i < a.count(); ++i) {
191 if (a[i])
192 ol << i << *a[i];
193 }
194 ol << -1;
195 return ol;
196 }
197
198 /* inlined methods */
199
200 inline
put(const void * buf,Size size)201 void OLog::put(const void *buf, Size size) {
202 if (size > 0 && theStream) {
203 // just append if fits
204 if (theSize + size <= theCapacity) {
205 memcpy(theBuf + theSize, buf, size);
206 theSize += size;
207 thePos += size;
208 } else {
209 overflow(buf, size); // always uses put() recursively
210 }
211 }
212 }
213
214 #endif
215