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