Branch data Line data Source code
1 : : // $Id: SerialObj.cc 7075 2010-09-13 02:39:38Z vern $
2 : :
3 : : #include "SerialObj.h"
4 : : #include "Serializer.h"
5 : :
6 : : TransientID::ID TransientID::counter = 0;
7 : :
8 : : SerialObj::FactoryMap* SerialObj::factories = 0;
9 : : SerialObj::ClassNameMap* SerialObj::names = 0;
10 : : uint64 SerialObj::time_counter = NEVER + ALWAYS + 1;
11 : :
12 : 0 : SerialObj* SerialObj::Instantiate(SerialType type)
13 : : {
14 : 0 : FactoryMap::iterator f = factories->find(type & SER_TYPE_MASK_EXACT);
15 [ # # ]: 0 : if ( f != factories->end() )
16 : : {
17 : 0 : SerialObj* o = (SerialObj*) (*f->second)();
18 : : #ifdef DEBUG
19 : 0 : o->serial_type = o->GetSerialType();
20 : : #endif
21 : 0 : return o;
22 : : }
23 : :
24 : 0 : run_time(fmt("Unknown object type 0x%08x", type));
25 : 0 : return 0;
26 : : }
27 : :
28 : 0 : const char* SerialObj::ClassName(SerialType type)
29 : : {
30 : 0 : ClassNameMap::iterator f = names->find(type);
31 [ # # ]: 0 : if ( f != names->end() )
32 : 0 : return f->second;
33 : :
34 : 0 : run_time(fmt("Unknown object type 0x%08x", type));
35 : 0 : return "<no-class-name>";
36 : : }
37 : :
38 : 288 : void SerialObj::Register(SerialType type, FactoryFunc f, const char* name)
39 : : {
40 [ + + ]: 288 : if ( ! factories )
41 : : {
42 : 3 : factories = new FactoryMap;
43 : 3 : names = new ClassNameMap;
44 : : }
45 : :
46 : 288 : type = type & SER_TYPE_MASK_EXACT;
47 : :
48 : 288 : FactoryMap::iterator i = factories->find(type);
49 [ - + ]: 288 : if ( i != factories->end() )
50 : 0 : internal_error("SerialType 0x%08x registered twice", type);
51 : :
52 : 288 : (*factories)[type] = f;
53 : 288 : (*names)[type] = name;
54 : 288 : }
55 : :
56 : 107 : inline bool SerializePID(SerialInfo* info, bool full, SerializationCache::PermanentID pid)
57 : : {
58 [ - + ]: 107 : if ( ! SERIALIZE(full) )
59 : 0 : return false;
60 : :
61 [ + - ]: 107 : if ( ! info->pid_32bit )
62 : 107 : return SERIALIZE(pid);
63 : :
64 : : // Broccoli compatibility mode with 32bit pids.
65 : 0 : uint32 tmp = uint32(pid);
66 : 107 : return SERIALIZE(tmp);
67 : : }
68 : :
69 : 107 : bool SerialObj::Serialize(SerialInfo* info) const
70 : : {
71 [ - + ]: 107 : assert(info);
72 : :
73 [ + - ]: 107 : if ( info->cont.NewInstance() )
74 : : {
75 : 107 : SerializationCache::PermanentID pid = SerializationCache::NONE;
76 : :
77 : 107 : const TransientID* tid = GetTID();
78 : :
79 [ - + ]: 107 : if ( ! tid )
80 : 0 : internal_error("no tid - missing DECLARE_SERIAL?");
81 : :
82 [ + - ]: 107 : if ( info->cache )
83 : 107 : pid = info->s->Cache()->Lookup(*tid);
84 : :
85 [ + + ][ + - ]: 107 : if ( pid != SerializationCache::NONE && info->cache )
86 : : {
87 : 42 : DBG_LOG(DBG_SERIAL, "%s [%p, ref pid %lld, tid %lld]", __PRETTY_FUNCTION__, this, (long long) pid, tid->Value() );
88 : :
89 : 42 : DBG_LOG(DBG_SERIAL, "-- Caching");
90 : 42 : DBG_PUSH(DBG_SERIAL);
91 : :
92 [ - + ]: 42 : if ( ! SerializePID(info, false, pid) )
93 : : {
94 : 0 : DBG_POP(DBG_SERIAL);
95 : 0 : return false;
96 : : }
97 : :
98 : 42 : DBG_POP(DBG_SERIAL);
99 : 42 : return true;
100 : : }
101 : :
102 [ + - ]: 65 : if ( info->cache )
103 : : pid = info->s->Cache()->Register(this,
104 : : SerializationCache::NONE,
105 : 65 : info->new_cache_strategy);
106 : :
107 : 65 : DBG_LOG(DBG_SERIAL, "%s [%p, new pid %lld, tid %lld]", __PRETTY_FUNCTION__, this, (long long) pid, tid->Value() );
108 : 65 : DBG_LOG(DBG_SERIAL, "-- Caching");
109 : 65 : DBG_PUSH(DBG_SERIAL);
110 : :
111 [ - + ]: 65 : if ( ! SerializePID(info, true, pid) )
112 : : {
113 : 0 : DBG_POP(DBG_SERIAL);
114 : 0 : return false;
115 : : }
116 : :
117 : 65 : info->type = SER_NONE;
118 : 65 : DBG_POP(DBG_SERIAL);
119 : : }
120 : :
121 : 65 : DBG_PUSH(DBG_SERIAL);
122 : 65 : info->cont.SaveContext();
123 : 65 : bool ret = DoSerialize(info);
124 : 65 : info->cont.RestoreContext();
125 : 65 : DBG_POP(DBG_SERIAL);
126 : :
127 [ - + ]: 65 : if ( info->cont.ChildSuspended() )
128 : 0 : return ret;
129 : :
130 : : #ifdef DEBUG
131 [ - + ][ # # ]: 65 : if ( debug_logger.IsEnabled(DBG_SERIAL) && IsBroObj(serial_type) )
[ - + ]
132 : : {
133 : 0 : ODesc desc(DESC_READABLE);
134 : 0 : ((BroObj*)this)->Describe(&desc);
135 : 0 : DBG_LOG(DBG_SERIAL, "-- Desc: %s", desc.Description());
136 : : }
137 : : #endif
138 : :
139 : 107 : return ret;
140 : : }
141 : :
142 : 0 : SerialObj* SerialObj::Unserialize(UnserialInfo* info, SerialType type)
143 : : {
144 : 0 : SerializationCache::PermanentID pid = SerializationCache::NONE;
145 : :
146 : 0 : DBG_LOG(DBG_SERIAL, "%s", __PRETTY_FUNCTION__);
147 : :
148 : : bool full_obj;
149 : :
150 : 0 : DBG_LOG(DBG_SERIAL, "-- Caching");
151 : 0 : DBG_PUSH(DBG_SERIAL);
152 : :
153 : : bool result;
154 : :
155 [ # # ]: 0 : if ( ! info->pid_32bit )
156 [ # # ][ # # ]: 0 : result = UNSERIALIZE(&full_obj) && UNSERIALIZE(&pid);
157 : : else
158 : : {
159 : : // Broccoli compatibility mode with 32bit pids.
160 : : uint32 tmp;
161 [ # # ][ # # ]: 0 : result = UNSERIALIZE(&full_obj) && UNSERIALIZE(&tmp);
162 : 0 : pid = tmp;
163 : : }
164 : :
165 [ # # ]: 0 : if ( ! result )
166 : : {
167 : 0 : DBG_POP(DBG_SERIAL);
168 : 0 : return false;
169 : : }
170 : :
171 : 0 : DBG_POP(DBG_SERIAL);
172 : :
173 [ # # ]: 0 : DBG_LOG(DBG_SERIAL, "-- [%s pid %lld]", full_obj ? "obj" : "ref", (long long) pid);
174 : :
175 [ # # ]: 0 : if ( ! full_obj )
176 : : {
177 : : // FIXME: Yet another const_cast to check eventually...
178 : : SerialObj* obj =
179 : 0 : const_cast<SerialObj*>(info->s->Cache()->Lookup(pid));
180 [ # # ]: 0 : if ( obj )
181 : : {
182 [ # # ]: 0 : if ( obj->IsBroObj() )
183 : 0 : Ref((BroObj*) obj);
184 : 0 : return obj;
185 : : }
186 : :
187 : : // In the following we'd like the format specifier to match
188 : : // the type of pid; but pid is uint64, for which there's
189 : : // no portable format specifier. So we upcast it to long long,
190 : : // which is at least that size, and use a matching format.
191 : : info->s->Error(fmt("unknown object %lld referenced",
192 : 0 : (long long) pid));
193 : 0 : return 0;
194 : : }
195 : :
196 : : uint16 stype;
197 [ # # ]: 0 : if ( ! UNSERIALIZE(&stype) )
198 : 0 : return 0;
199 : :
200 : 0 : SerialObj* obj = Instantiate(SerialType(stype));
201 : :
202 [ # # ]: 0 : if ( ! obj )
203 : : {
204 : 0 : info->s->Error("unknown object type");
205 : 0 : return 0;
206 : : }
207 : :
208 : : #ifdef DEBUG
209 : 0 : obj->serial_type = stype;
210 : : #endif
211 : :
212 : 0 : const TransientID* tid = obj->GetTID();
213 [ # # ]: 0 : if ( ! tid )
214 : 0 : internal_error("no tid - missing DECLARE_SERIAL?");
215 : :
216 [ # # ]: 0 : if ( info->cache )
217 : 0 : info->s->Cache()->Register(obj, pid, info->new_cache_strategy);
218 : :
219 : 0 : info->type = stype;
220 : :
221 : 0 : DBG_PUSH(DBG_SERIAL);
222 [ # # ]: 0 : if ( ! obj->DoUnserialize(info) )
223 : : {
224 : 0 : DBG_POP(DBG_SERIAL);
225 : 0 : return 0;
226 : : }
227 : :
228 : 0 : DBG_POP(DBG_SERIAL);
229 : :
230 [ # # ]: 0 : if ( ! SerialObj::CheckTypes(stype, type) )
231 : : {
232 : 0 : info->s->Error("type mismatch");
233 : 0 : return 0;
234 : : }
235 : :
236 : : #ifdef DEBUG
237 [ # # ][ # # ]: 0 : if ( debug_logger.IsEnabled(DBG_SERIAL) && IsBroObj(stype) )
[ # # ]
238 : : {
239 : 0 : ODesc desc(DESC_READABLE);
240 : 0 : ((BroObj*)obj)->Describe(&desc);
241 : 0 : DBG_LOG(DBG_SERIAL, "-- Desc: %s", desc.Description());
242 : : }
243 : : #endif
244 : :
245 [ # # ]: 0 : assert(obj);
246 : 0 : return obj;
247 : : }
248 : :
249 : 65 : bool SerialObj::DoSerialize(SerialInfo* info) const
250 : : {
251 [ - + ]: 65 : assert(info->type != SER_NONE);
252 : :
253 : : #ifdef DEBUG
254 : 65 : const_cast<SerialObj*>(this)->serial_type = info->type;
255 : : #endif
256 : :
257 : 65 : DBG_LOG(DBG_SERIAL, __PRETTY_FUNCTION__);
258 : 65 : DBG_PUSH(DBG_SERIAL);
259 : :
260 : 65 : uint16 stype = uint16(info->type);
261 : :
262 [ + - ]: 65 : if ( ! info->new_cache_strategy )
263 : : {
264 : : // This is a bit unfortunate: to make sure we're sending
265 : : // out the same types as in the past, we need to strip out
266 : : // the new cache stable bit.
267 : 65 : stype &= ~SER_IS_CACHE_STABLE;
268 : : }
269 : :
270 : 65 : bool ret = SERIALIZE(stype);
271 : 65 : DBG_POP(DBG_SERIAL);
272 : 65 : return ret;
273 : : }
274 : :
275 : 0 : bool SerialObj::DoUnserialize(UnserialInfo* info)
276 : : {
277 : 0 : DBG_LOG(DBG_SERIAL, __PRETTY_FUNCTION__);
278 : 0 : return true;
279 [ + - ][ + - ]: 6 : }
|