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