1 /*
2  * Copyright 2006-2008 The FLWOR Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 #ifndef ZORBA_BINARY_SERIALIZATION_ARCHIVER
18 #define ZORBA_BINARY_SERIALIZATION_ARCHIVER
19 
20 #include <stack>
21 
22 #include "zorbaserialization/class_serializer.h"
23 #include "zorbaserialization/plan_settings.h"
24 #include "zorbaserialization/archiver_consts.h"
25 
26 #include "zorbatypes/zstring.h"
27 
28 #include "zorbautils/hashfun.h"
29 
30 namespace zorba
31 {
32 
33 namespace store
34 {
35 class Item;
36 }
37 
38 
39 class CompilerCB;
40 class SerializationCallback;
41 
42 template <class T, class V, class C> class HashMap;
43 
44 
45 namespace serialization
46 {
47 
48 class archive_field;
49 class ClassSerializer;
50 
51 
52 /*******************************************************************************
53 
54   Archiver is working with fields. During serialization, an intermediate tree of
55   fields is constructed in memory to represent all the objects that need to be
56   serialized. Then, the fields are written to disk in depth-first order, creating
57   an archive. During deserialization, the fields in the archive are read and the
58   associated objects recreated directly in memory, without going through the
59   intermediate representation of the fields-tree.
60 
61   Notice that in the context of the serializer, an "object" is defined as any
62   address in memory that contains information to be serialized. For example,
63   it can be a C++ class object, an std::vector<> or a C++ integer. The object
64   can be heap-allocated, or on the stack.
65 
66   Fileds can be "simple" or "compound". Simple fields represent values of simple
67   types; they always appear as leaves in the fields-tree. Compound fields represent
68   C++-class objects and other structured types like vectors, maps, etc. They
69   typically contain subtrees of other fields.
70 
71   Each field has a unique id.
72 
73 ********************************************************************************/
74 
75 
76 /*******************************************************************************
77 
78   theArchiveName:
79   ---------------
80 
81   theArchiveInfo:
82   ---------------
83 
84   theArchiveVersion:
85   ------------------
86 
87   theSerializingOut :
88   -------------------
89   Whether the archiver is used to serialize or deserialize a plan.
90 
91   theSerializeBaseClass:
92   ----------------------
93   If true, then we are in the process of (de)serializing a class obj O, and the
94   next bunch of data members to serialize belong to an internal class in the
95   class hierarchy. These data members will form a fields subtree, rooted at a
96   field of kind BASECLASS, within the bigger subtree of obj O. This data member
97   is required in order for the function operator&(Archiver& ar, T*& obj) to know
98   which serialize_internal() method to invoke.
99 
100   theIsTempField:
101   ---------------
102   If > 0, then the next obj to (de)serialize should not be registered or looked
103   up in any of the fields registries. This is the case when, for example, we are
104   seriazing an obj that resides on the program stack.
105 
106   theFieldCounter:
107   ----------------
108   The number of fields generated so far (during serialization). It is used to
109   generated field ids. It is written to "disk" and used, during deserializrion
110   to allocate the correct size for the all_references_list.
111 
112   theRootField :
113   --------------
114   The root of the fields tree.
115 
116   theCurrentCompoundField:
117   ------------------------
118   The compound field under which the next field to be created will be placed.
119 
120   theCurrentLevel:
121   ----------------
122   The tree level of the most recently added field
123 
124 ********************************************************************************/
125 class Archiver
126 {
127   friend class ClassSerializer;
128 
129   class FieldCompare
130   {
131   public:
hash(const void * f)132     uint32_t hash(const void* f) const
133     {
134       return hashfun::h32((void*)&f, sizeof(void*));
135     }
136 
equal(const void * f1,const void * f2)137     bool equal(const void* f1, const void* f2) const
138     {
139       return (f1 == f2);
140     }
141   };
142 
143   typedef HashMap<const void*, archive_field*, FieldCompare> FieldMap;
144 
145 protected:
146   zstring                       theArchiveName;
147 
148   zstring                       theArchiveInfo;
149 
150   unsigned long                 theArchiveVersion;
151 
152   bool                          theSerializingOut;
153 
154   int                           theSerializeBaseClass;
155 
156   int                           theIsTempField;
157 
158   std::stack<unsigned int>      limit_temp_level_stack;
159 
160 
161   CompilerCB                  * theCompilerCB;
162 
163   int                           theFieldCounter;
164 
165   archive_field               * theRootField;
166 
167   archive_field               * theCurrentCompoundField;
168 
169   unsigned int                  theCurrentLevel;
170 
171   FieldMap                    * theNonClassFieldsMap;
172 
173   FieldMap                    * theClassFieldsMap;
174 
175   int                           theOnlyForEval;
176 
177 
178   void                       ** all_reference_list;
179 
180 
181   std::vector<archive_field*>   orphan_fields;
182 
183   bool                          internal_archive;
184 
185   bool                          theSerializeEverything;
186 
187   bool                          loading_hardcoded_objects;
188 
189   ENUM_ALLOW_DELAY              theAllowDelay2;
190 
191   std::vector<store::Item*>     registered_items;
192 
193   SerializationCallback       * theUserCallback;
194 
195 public:
196   bool                          dont_allow_delay_for_plan_sctx;
197 
198 public:
199   Archiver(bool is_serializing_out, bool internal_archive=false);
200 
201   virtual ~Archiver();
202 
set_ccb(CompilerCB * ccb)203   void set_ccb(CompilerCB* ccb) { theCompilerCB = ccb; }
204 
get_ccb()205   CompilerCB* get_ccb() const { return theCompilerCB; }
206 
is_serializing_out()207   bool is_serializing_out() { return theSerializingOut; }
208 
set_loading_hardcoded_objects(bool v)209   void set_loading_hardcoded_objects(bool v) { loading_hardcoded_objects = v; }
210 
is_loading_hardcoded_objects()211   bool is_loading_hardcoded_objects() { return loading_hardcoded_objects; }
212 
getUserCallback()213   SerializationCallback* getUserCallback() const { return theUserCallback; }
214 
setUserCallback(SerializationCallback * cb)215   void setUserCallback(SerializationCallback* cb) { theUserCallback = cb; }
216 
217   //
218   // Methods used during serialization only
219   //
220 
221   void add_simple_temp_field(TypeCode type, const void* ptr);
222 
223   bool add_simple_ptr_field(TypeCode type, const void* ptr);
224 
225   bool add_compound_field(
226       TypeCode type,
227       bool is_class,
228       const void* ptr,
229       ArchiveFieldKind kind);
230 
231   void add_end_compound_field();
232 
is_serialize_everything()233   bool is_serialize_everything() { return theSerializeEverything; }
234 
set_serialize_everything()235   void set_serialize_everything() { theSerializeEverything = true; }
236 
237   //
238   // Methods used during de-serialization only
239   //
240   void read_next_compound_field(
241       bool is_class,
242       ArchiveFieldKind& field_kind,
243       TypeCode& type,
244       int& id,
245       int& referencing);
246 
247   void read_next_simple_temp_field(TypeCode type, void* obj);
248 
249   void read_next_simple_ptr_field(TypeCode type, void** obj);
250 
251   void read_end_current_level();
252 
253   void check_nonclass_field(
254       ArchiveFieldKind field_kind,
255       ArchiveFieldKind required_field_kind,
256       int id);
257 
258   void check_class_field(
259       TypeCode type,
260       TypeCode required_type,
261       ArchiveFieldKind field_kind,
262       ArchiveFieldKind required_field_kind,
263       int id);
264 
265   void register_reference(int id, ArchiveFieldKind field_kind, const void* ptr);
266 
267   void* get_reference_value(int refid);
268 
269   void finalize_input_serialization();
270 
271   //
272   // Methods used during both serialization and deserialization.
273   //
set_serialize_base_class(bool s)274   void set_serialize_base_class(bool s)
275   {
276     if (s)
277       theSerializeBaseClass++;
278     else
279       theSerializeBaseClass--;
280 
281     assert(theSerializeBaseClass >= 0);
282     assert(theSerializeBaseClass <= 1);
283   }
284 
is_serialize_base_class()285   bool is_serialize_base_class() { return theSerializeBaseClass > 0; }
286 
set_is_temp_field(bool is_temp)287   void set_is_temp_field(bool is_temp)
288   {
289     if (is_temp)
290       theIsTempField++;
291     else
292       theIsTempField--;
293 
294     assert(theIsTempField >= 0);
295   }
296 
get_is_temp_field()297   bool get_is_temp_field() { return (theIsTempField > 0); }
298 
set_is_temp_field_one_level(bool is_temp)299  void set_is_temp_field_one_level(bool is_temp)
300   {
301     if (is_temp)
302       limit_temp_level_stack.push(theCurrentLevel + 1);
303     else
304       limit_temp_level_stack.pop();
305   }
306 
307   bool get_is_temp_field_one_level();
308 
309 protected:
310 
311   //
312   // Methods used during serialization only
313   //
314 
315   archive_field* lookup_non_class_field(const void* ptr);
316 
317   archive_field* lookup_class_field(const void* ptr);
318 
319   void prepare_serialize_out();
320 
321   archive_field* get_prev(archive_field* field);
322 
323   void replace_field(archive_field* new_field, archive_field* ref_field);
324 
325   archive_field* replace_with_null(archive_field* current_field);
326 
327   void register_pointers_internal(archive_field* fields);
328 
329   int compute_field_depth(archive_field* field);
330 
331   int get_only_for_eval(archive_field* field);
332 
333   archive_field* find_top_most_eval_only_field(archive_field* parent_field);
334 
335   bool check_only_for_eval_nondelay_referencing(archive_field* parent_field);
336 
337   void replace_only_for_eval_with_null(archive_field* parent_field);
338 
339   void clean_only_for_eval(archive_field* field, int substract_value);
340 
341   void check_compound_fields(archive_field* parent_field);
342 
343   bool check_allowed_delays(archive_field* parent_field);
344 
345   int check_order(archive_field* field1, archive_field* field2);
346 
347   void exchange_mature_fields(archive_field* field1, archive_field* field2);
348 
349   virtual void serialize_out() = 0;
350 
351   //
352   // Methods used during de-serialization only
353   //
354 
355   void root_tag_is_read();
356 
357   virtual void read_next_compound_field_impl(
358       bool is_class,
359       ArchiveFieldKind& field_kind,
360       TypeCode& type,
361       int& id,
362       int& referencing) = 0;
363 
364   virtual void read_next_simple_temp_field_impl(TypeCode type, void* obj) = 0;
365 
366   virtual void read_next_simple_ptr_field_impl(TypeCode type, void** obj) = 0;
367 
368   virtual void read_end_current_level_impl() = 0;
369 
370 public:
371   void register_item(store::Item* i);
372 
get_serialize_only_for_eval()373   int get_serialize_only_for_eval() { return theOnlyForEval; }
374 
set_serialize_only_for_eval(bool evalonly)375   void set_serialize_only_for_eval(bool evalonly)
376   {
377     if (evalonly)
378       theOnlyForEval++;
379     else
380       theOnlyForEval--;
381 
382     assert(theOnlyForEval >= 0);
383   }
384 
385   void dont_allow_delay(ENUM_ALLOW_DELAY d = DONT_ALLOW_DELAY)
386   {
387     theAllowDelay2 = d;
388   }
389 
reset_allow_delay()390   void reset_allow_delay() { theAllowDelay2 = ALLOW_DELAY; }
391 
get_allow_delay()392   ENUM_ALLOW_DELAY get_allow_delay() { return theAllowDelay2; }
393 };
394 
395 
396 }}
397 #endif
398 /* vim:set et sw=2 ts=2: */
399