| 1 | // =============================================================== // |
|---|
| 2 | // // |
|---|
| 3 | // File : gb_main.h // |
|---|
| 4 | // Purpose : GB_MAIN_TYPE // |
|---|
| 5 | // // |
|---|
| 6 | // Institute of Microbiology (Technical University Munich) // |
|---|
| 7 | // http://www.arb-home.de/ // |
|---|
| 8 | // // |
|---|
| 9 | // =============================================================== // |
|---|
| 10 | |
|---|
| 11 | #ifndef GB_MAIN_H |
|---|
| 12 | #define GB_MAIN_H |
|---|
| 13 | |
|---|
| 14 | #ifndef GB_LOCAL_H |
|---|
| 15 | #include "gb_local.h" |
|---|
| 16 | #endif |
|---|
| 17 | #ifndef GB_CB_H |
|---|
| 18 | #include "gb_cb.h" |
|---|
| 19 | #endif |
|---|
| 20 | |
|---|
| 21 | // ------------------------------ |
|---|
| 22 | // forward declare types |
|---|
| 23 | |
|---|
| 24 | struct g_b_undo_mgr; |
|---|
| 25 | struct gb_close_callback_list; |
|---|
| 26 | struct gb_user; |
|---|
| 27 | struct gb_project; |
|---|
| 28 | struct gb_Key; |
|---|
| 29 | struct gb_server_data; |
|---|
| 30 | struct gb_hierarchy_callback_list; |
|---|
| 31 | class gb_hierarchy_location; |
|---|
| 32 | |
|---|
| 33 | // -------------------------------------------------------------------------------- |
|---|
| 34 | |
|---|
| 35 | enum gb_open_types { |
|---|
| 36 | gb_open_all = 0, |
|---|
| 37 | gb_open_read_only_all = 16, |
|---|
| 38 | gb_open_read_only_small = 17 |
|---|
| 39 | }; |
|---|
| 40 | |
|---|
| 41 | struct gb_quick_save { |
|---|
| 42 | char *quick_save_disabled; // if set, quick save is not possible and text describes reason why |
|---|
| 43 | int last_index; |
|---|
| 44 | |
|---|
| 45 | gb_quick_save() : |
|---|
| 46 | quick_save_disabled(NULp), |
|---|
| 47 | last_index(0) |
|---|
| 48 | {} |
|---|
| 49 | }; |
|---|
| 50 | |
|---|
| 51 | // -------------------------------------------------------------------------------- |
|---|
| 52 | |
|---|
| 53 | #if defined(DEBUG) |
|---|
| 54 | // #define GEN_CACHE_STATS // unit tests will fail if enabled |
|---|
| 55 | #endif // DEBUG |
|---|
| 56 | |
|---|
| 57 | typedef uint16_t gb_cache_idx; |
|---|
| 58 | |
|---|
| 59 | struct gb_cache_entry; |
|---|
| 60 | struct gb_cache : virtual Noncopyable { |
|---|
| 61 | gb_cache_entry *entries; |
|---|
| 62 | |
|---|
| 63 | gb_cache_idx firstfree_entry; |
|---|
| 64 | gb_cache_idx newest_entry; |
|---|
| 65 | gb_cache_idx oldest_entry; |
|---|
| 66 | |
|---|
| 67 | size_t sum_data_size; |
|---|
| 68 | size_t max_data_size; |
|---|
| 69 | size_t big_data_min_size; |
|---|
| 70 | |
|---|
| 71 | #if defined(GEN_CACHE_STATS) |
|---|
| 72 | GB_HASH *not_reused; // key = DB_path, value = number of cache entries not reused |
|---|
| 73 | GB_HASH *reused; // key = DB_path, value = number of cache entries reused |
|---|
| 74 | GB_HASH *reuse_sum; // key = DB_path, value = how often entries were reused |
|---|
| 75 | #endif |
|---|
| 76 | |
|---|
| 77 | gb_cache(); |
|---|
| 78 | ~gb_cache(); |
|---|
| 79 | }; |
|---|
| 80 | |
|---|
| 81 | // -------------------------------------------------------------------------------- |
|---|
| 82 | // root structure (one for each database) |
|---|
| 83 | |
|---|
| 84 | #define ALLOWED_KEYS 15000 |
|---|
| 85 | #define ALLOWED_DATES 256 |
|---|
| 86 | |
|---|
| 87 | class GB_MAIN_TYPE : virtual Noncopyable { |
|---|
| 88 | inline GB_ERROR start_transaction() __ATTR__USERESULT; |
|---|
| 89 | GB_ERROR check_quick_save() const; |
|---|
| 90 | GB_ERROR initial_client_transaction() __ATTR__USERESULT; |
|---|
| 91 | |
|---|
| 92 | int transaction_level; |
|---|
| 93 | int aborted_transaction; |
|---|
| 94 | |
|---|
| 95 | bool i_am_server; |
|---|
| 96 | |
|---|
| 97 | struct callback_group : virtual Noncopyable { |
|---|
| 98 | gb_hierarchy_callback_list *hierarchy_cbs; // defined hierarchy callbacks |
|---|
| 99 | gb_pending_callbacks pending; // collect triggered callbacks (will be called by commit; discarded by abort) |
|---|
| 100 | |
|---|
| 101 | callback_group() : hierarchy_cbs(NULp) {} |
|---|
| 102 | |
|---|
| 103 | inline void add_hcb(const gb_hierarchy_location& loc, const TypedDatabaseCallback& dbcb); |
|---|
| 104 | inline void remove_hcb(const gb_hierarchy_location& loc, const TypedDatabaseCallback& dbcb); |
|---|
| 105 | inline void forget_hcbs(); |
|---|
| 106 | |
|---|
| 107 | void trigger(GBDATA *gbd, GB_CB_TYPE type, gb_callback_list *dataCBs); |
|---|
| 108 | }; |
|---|
| 109 | |
|---|
| 110 | callback_group changeCBs; // all but GB_CB_DELETE |
|---|
| 111 | callback_group deleteCBs; // GB_CB_DELETE |
|---|
| 112 | |
|---|
| 113 | friend class ArbDBWriter; |
|---|
| 114 | |
|---|
| 115 | public: |
|---|
| 116 | |
|---|
| 117 | gbcmc_comm *c_link; |
|---|
| 118 | gb_server_data *server_data; |
|---|
| 119 | GBCONTAINER *dummy_father; |
|---|
| 120 | GBCONTAINER *root_container; |
|---|
| 121 | GBCONTAINER *gb_key_data; |
|---|
| 122 | char *path; |
|---|
| 123 | gb_open_types opentype; |
|---|
| 124 | char *disabled_path; |
|---|
| 125 | int allow_corrupt_file_recovery; |
|---|
| 126 | |
|---|
| 127 | gb_quick_save qs; |
|---|
| 128 | gb_cache cache; |
|---|
| 129 | int compression_mask; |
|---|
| 130 | |
|---|
| 131 | int keycnt; // first non used key |
|---|
| 132 | long sizeofkeys; // malloc size |
|---|
| 133 | long first_free_key; // index of first gap |
|---|
| 134 | gb_Key *keys; |
|---|
| 135 | GB_HASH *key_2_index_hash; |
|---|
| 136 | long key_clock; // trans. nr. of last change |
|---|
| 137 | bool mapped; // true -> loaded via mapfile |
|---|
| 138 | |
|---|
| 139 | unsigned int last_updated; |
|---|
| 140 | long last_saved_time; |
|---|
| 141 | long last_saved_transaction; |
|---|
| 142 | long last_main_saved_transaction; |
|---|
| 143 | |
|---|
| 144 | GB_UNDO_TYPE requested_undo_type; |
|---|
| 145 | GB_UNDO_TYPE undo_type; |
|---|
| 146 | |
|---|
| 147 | g_b_undo_mgr *undo; |
|---|
| 148 | |
|---|
| 149 | char *dates[ALLOWED_DATES]; // @@@ saved to DB, but never used |
|---|
| 150 | unsigned int security_level; |
|---|
| 151 | long clock; |
|---|
| 152 | GB_NUMHASH *remote_hash; |
|---|
| 153 | |
|---|
| 154 | gb_callback_list *close_callbacks; |
|---|
| 155 | |
|---|
| 156 | gb_user *users[GB_MAX_USERS]; // user 0 is server |
|---|
| 157 | gb_user *this_user; |
|---|
| 158 | |
|---|
| 159 | // -------------------- |
|---|
| 160 | |
|---|
| 161 | private: |
|---|
| 162 | GBCONTAINER*& gb_main_ref() { return root_container; } |
|---|
| 163 | |
|---|
| 164 | GB_ERROR check_saveable(const char *new_path, const char *flags) const; |
|---|
| 165 | GB_ERROR check_quick_saveable(const char *new_path, const char *flags) const { |
|---|
| 166 | GB_ERROR error = check_quick_save(); |
|---|
| 167 | return error ? error : check_saveable(new_path, flags); |
|---|
| 168 | } |
|---|
| 169 | public: |
|---|
| 170 | |
|---|
| 171 | GB_MAIN_TYPE(const char *db_path); |
|---|
| 172 | ~GB_MAIN_TYPE(); |
|---|
| 173 | |
|---|
| 174 | void free_all_keys(); |
|---|
| 175 | void release_main_idx(); |
|---|
| 176 | |
|---|
| 177 | int get_transaction_level() const { return transaction_level; } |
|---|
| 178 | |
|---|
| 179 | GBDATA *gb_main() const { return (GBDATA*)root_container; } |
|---|
| 180 | |
|---|
| 181 | GB_ERROR login_remote(const char *db_path, const char *opent) __ATTR__USERESULT; |
|---|
| 182 | |
|---|
| 183 | inline GB_ERROR begin_transaction() __ATTR__USERESULT; |
|---|
| 184 | inline GB_ERROR commit_transaction() __ATTR__USERESULT; |
|---|
| 185 | inline GB_ERROR abort_transaction() __ATTR__USERESULT; |
|---|
| 186 | |
|---|
| 187 | inline GB_ERROR push_transaction() __ATTR__USERESULT; |
|---|
| 188 | inline GB_ERROR pop_transaction() __ATTR__USERESULT; |
|---|
| 189 | |
|---|
| 190 | inline GB_ERROR no_transaction(); |
|---|
| 191 | |
|---|
| 192 | __ATTR__USERESULT GB_ERROR send_update_to_server(GBDATA *gbd) __ATTR__USERESULT; |
|---|
| 193 | |
|---|
| 194 | GB_ERROR save_quick(const char *refpath); |
|---|
| 195 | |
|---|
| 196 | GB_ERROR save_as(const char *as_path, const char *savetype); |
|---|
| 197 | GB_ERROR save_quick_as(const char *as_path); |
|---|
| 198 | |
|---|
| 199 | GB_ERROR panic_save(const char *db_panic); |
|---|
| 200 | |
|---|
| 201 | void mark_as_server() { i_am_server = true; } |
|---|
| 202 | |
|---|
| 203 | bool is_server() const { return i_am_server; } |
|---|
| 204 | bool is_client() const { return !is_server(); } |
|---|
| 205 | |
|---|
| 206 | void call_pending_callbacks(); |
|---|
| 207 | |
|---|
| 208 | bool has_pending_change_callback() const { return changeCBs.pending.pending(); } |
|---|
| 209 | bool has_pending_delete_callback() const { return deleteCBs.pending.pending(); } |
|---|
| 210 | |
|---|
| 211 | GB_ERROR add_hierarchy_cb(const gb_hierarchy_location& loc, const TypedDatabaseCallback& dbcb); |
|---|
| 212 | GB_ERROR remove_hierarchy_cb(const gb_hierarchy_location& loc, const TypedDatabaseCallback& dbcb); |
|---|
| 213 | void forget_hierarchy_cbs(); |
|---|
| 214 | |
|---|
| 215 | inline void trigger_change_callbacks(GBDATA *gbd, GB_CB_TYPE type); |
|---|
| 216 | void trigger_delete_callbacks(GBDATA *gbd); |
|---|
| 217 | }; |
|---|
| 218 | |
|---|
| 219 | #else |
|---|
| 220 | #error gb_main.h included twice |
|---|
| 221 | #endif // GB_MAIN_H |
|---|
| 222 | |
|---|