1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
|
/* Copyright (c) 2005 PrimeBase Technologies GmbH
*
* PrimeBase XT
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 2005-01-15 Paul McCullagh
*
* H&G2JCtL
*/
#ifndef __xt_database_h__
#define __xt_database_h__
#include <time.h>
#include "thread_xt.h"
#include "hashtab_xt.h"
#include "table_xt.h"
#include "sortedlist_xt.h"
#include "xaction_xt.h"
#include "heap_xt.h"
#include "xactlog_xt.h"
#include "restart_xt.h"
#include "index_xt.h"
#ifdef DEBUG
//#define XT_USE_XACTION_DEBUG_SIZES
#endif
#ifdef XT_USE_XACTION_DEBUG_SIZES
#define XT_DB_TABLE_POOL_SIZE 2
#else
#define XT_DB_TABLE_POOL_SIZE 10 // The number of open tables maintained by the sweeper
#endif
#define XT_ASYNC_THREAD_COUNT 10
/* Turn this switch on to enable spin lock based wait-for logic: */
#define XT_USE_SPINLOCK_WAIT_FOR
extern xtLogOffset xt_db_log_file_threshold;
extern size_t xt_db_log_buffer_size;
extern size_t xt_db_transaction_buffer_size;
extern size_t xt_db_checkpoint_frequency;
extern off_t xt_db_data_log_threshold;
extern size_t xt_db_data_file_grow_size;
extern size_t xt_db_row_file_grow_size;
extern size_t xt_db_record_write_threshold;
extern int xt_db_garbage_threshold;
extern int xt_db_log_file_count;
extern int xt_db_auto_increment_mode;
extern int xt_db_offline_log_function;
extern int xt_db_sweeper_priority;
extern int xt_db_rewrite_flushing;
extern int xt_db_index_dirty_threshold;
extern int xt_db_flush_log_at_trx_commit;
extern XTSortedListPtr xt_db_open_db_by_id;
extern XTHashTabPtr xt_db_open_databases;
extern time_t xt_db_approximate_time;
#define XT_OPEN_TABLE_POOL_HASH_SIZE 223
#define XT_SW_WORK_NORMAL 0
#define XT_SW_NO_MORE_XACT_SLOTS 1
#define XT_SW_DIRTY_RECORD_FOUND 2
#define XT_SW_TOO_FAR_BEHIND 3 /* The sweeper is getting too far behind, although it is working! */
#ifdef XT_SWEEPER_SORT_XACTS
#define XT_SW_XACT_SORT_LIST_SIZE 100 /* Size of the list of transactions sorted for sweeping. */
#endif
#define XT_TABLE_NOT_LOCKED 0
#define XT_TABLE_LOCK_WAITING 1
#define XT_TABLE_LOCK_FLUSHING 2
#define XT_TABLE_LOCKED 3
typedef struct XTOpenTablePool {
struct XTDatabase *opt_db;
xtTableID opt_tab_id; /* The table ID. */
u_int opt_total_open; /* Total number of open tables. */
int opt_locked; /* This table is locked open tables are freed on return to pool. */
u_int opt_flushing;
XTOpenTablePtr opt_free_list; /* A list of free, unused open tables. */
struct XTOpenTablePool *opt_next_hash;
} XTOpenTablePoolRec, *XTOpenTablePoolPtr;
typedef struct XTAllTablePools {
xt_mutex_type opt_lock; /* This lock protects the open table pool. */
xt_cond_type opt_cond; /* Used to wait for an exclusive lock on a table. */
u_int otp_total_free; /* This is the total number of free open tables (not in use): */
/* All free (unused tables) are on this list: */
XTOpenTablePtr otp_mr_used;
XTOpenTablePtr otp_lr_used;
time_t otp_free_time; /* The free time of the LRU open table. */
XTOpenTablePoolPtr otp_hash[XT_OPEN_TABLE_POOL_HASH_SIZE];
} XTAllTablePoolsRec, *XTAllTablePoolsPtr;
typedef struct XTTablePath {
u_int tp_tab_count; /* The number of tables using this path. */
char tp_path[XT_VAR_LENGTH]; /* The table path. */
} XTTablePathRec, *XTTablePathPtr;
#define XT_THREAD_BUSY 0
#define XT_THREAD_IDLE 1
#define XT_THREAD_INERR 2
#define XT_XA_HASH_TAB_SIZE 223
typedef struct XTDatabase : public XTHeap {
char *db_name; /* The name of the database, last component of the path! */
char *db_main_path;
xtDatabaseID db_id;
xtTableID db_curr_tab_id; /* The ID of the last table created. */
XTHashTabPtr db_tables;
XTSortedListPtr db_table_by_id;
XTSortedListPtr db_table_paths; /* A list of table paths used by this database. */
xtBool db_multi_path;
XTSortedListPtr db_error_list; /* A list of errors already reported. */
/* The open table pool: */
XTAllTablePoolsRec db_ot_pool;
/* Transaction related stuff: */
XTSpinLockRec db_xn_id_lock; /* Lock for next transaction ID. */
xtXactID db_xn_curr_id; /* The ID of the last transaction started. */
xtXactID db_xn_min_ram_id; /* The lowest ID of the transactions in memory (RAM). */
xtXactID db_xn_to_clean_id; /* The next transaction to be cleaned (>= db_xn_min_ram_id). */
xtXactID db_xn_min_run_id; /* The lowest ID of all running transactions (not up-to-date! >= db_xn_to_clean_id) */
xtWord4 db_xn_end_time; /* The time of the transaction end. */
XTXactSegRec db_xn_idx[XT_XN_NO_OF_SEGMENTS]; /* Index of transactions in RAM. */
xtWord1 *db_xn_data; /* Start of the block allocated to contain transaction data. */
xtWord1 *db_xn_data_end; /* End of the transaction data block. */
u_int db_stat_sweep_waits; /* STATISTICS: count the sweeper waits. */
XTDatabaseLogRec db_xlog; /* The transaction log for this database. */
XTXactRestartRec db_restart; /* Database recovery stuff. */
xt_mutex_type db_init_sweep_lock; /* Lock so that only one thread can does the initial sweep. */
xtBool db_init_sweep_done; /* Set to TRUE once the initial sweep has been done. */
xt_mutex_type db_xn_xa_lock;
XTXactPreparePtr db_xn_xa_table[XT_XA_HASH_TAB_SIZE];
XTSortedListPtr db_xn_xa_list; /* The "wait-for" list, of transactions waiting for other transactions. */
XTSortedListPtr db_xn_wait_for; /* The "wait-for" list, of transactions waiting for other transactions. */
u_int db_xn_call_start; /* Start of the post wait calls. */
XTSpinLockRec db_xn_wait_spinlock;
//xt_mutex_type db_xn_wait_lock; /* The lock associated with the wait for list. */
//xt_cond_type db_xn_wait_cond; /* This condition is signalled when a transaction quits. */
//u_int db_xn_wait_on_cond; /* Number of threads waiting on the condition. */
int db_xn_wait_count; /* Number of waiting transactions. */
u_int db_xn_total_writer_count; /* The total number of writers. */
int db_xn_writer_count; /* The number of writer threads. */
int db_xn_writer_wait_count; /* The number of writer threads waiting. */
int db_xn_long_running_count; /* The number of long running writer threads. */
/* Sweeper stuff: */
struct XTThread *db_sw_thread; /* The sweeper thread (cleans up transactions). */
xt_mutex_type db_sw_lock; /* The lock associated with the sweeper. */
xt_cond_type db_sw_cond; /* The sweeper wakeup condition. */
u_int db_sw_check_count;
int db_sw_idle; /* BUSY/IDLE/INERR depending on the state of the sweeper. */
int db_sw_faster; /* non-zero if the sweeper should work faster. */
xtBool db_sw_fast; /* TRUE if the sweeper is working faster. */
#ifdef XT_SWEEPER_SORT_XACTS
xtXactID db_sw_to_add; /* The next transaction to be added. */
u_int db_sw_list_size; /* The number of transaction in the list. */
XTXactDataPtr db_sw_xact_list[XT_SW_XACT_SORT_LIST_SIZE];
#endif
/* Writer stuff: */
struct XTThread *db_wr_thread; /* The writer thread (write log data to the database). */
int db_wr_idle; /* BUSY/IDLE/INERR depending on the state of the writer. */
xtBool db_wr_faster; /* Set to TRUE if the writer should work faster. */
xtBool db_wr_fast; /* TRUE if the writer is working faster. */
u_int db_wr_thread_waiting; /* Count the number of threads waiting for the writer. */
xtBool db_wr_freeer_waiting; /* TRUE if the freeer is wating for the writer. */
xt_mutex_type db_wr_lock;
xt_cond_type db_wr_cond; /* Writer condition when idle (must bw woken by log flush! */
xtLogID db_wr_log_id; /* Current write log ID. */
xtLogOffset db_wr_log_offset; /* Current write log offset. */
xtLogID db_wr_flush_point_log_id; /* This is the point to which the writer will write (log ID). */
xtLogOffset db_wr_flush_point_log_offset; /* This is the point to which the writer will write (log offset). */
/* Data log stuff: */
XTDataLogCacheRec db_datalogs; /* The database data log stuff. */
XTIndexLogPoolRec db_indlogs; /* Index logs used for consistent write. */
/* Compactor stuff: */
struct XTThread *db_co_thread; /* The compator thread (compacts data logs). */
xt_mutex_type db_co_ext_lock; /* Required when extended data is moved, or removed. */
xtBool db_co_busy; /* True of the compactor is busy compacting a data log. */
xt_mutex_type db_co_dlog_lock; /* This is the lock required to flusht the compactors data log. */
/* Checkpointer stuff: */
struct XTThread *db_cp_thread; /* The checkpoint thread (flushes the database data). */
xt_mutex_type db_cp_lock;
xt_cond_type db_cp_cond; /* Writer condition when idle (must bw woken by log flush! */
XTCheckPointStateRec db_cp_state; /* The checkpoint state. */
/* Thread pool: */
xt_mutex_type db_pool_lock;
xt_cond_type db_pool_cond;
u_int db_pool_job_count; /* The number of busy threads. */
u_int db_pool_thread_count; /* The number of threads in the pool. */
XTThreadPtr db_thread_pool;
XTTask *db_task_queue_front;
XTTask *db_task_queue_back;
/* The "flusher" thread (used when pbxt_flush_log_at_trx_commit = 0 or 2) */
struct XTThread *db_fl_thread; /* The flusher thread (flushes the transation log). */
xt_mutex_type db_fl_lock;
} XTDatabaseRec, *XTDatabaseHPtr; /* Heap pointer */
#define XT_FOR_USER 0
#define XT_FOR_COMPACTOR 1
#define XT_FOR_SWEEPER 2
#define XT_FOR_WRITER 3
#define XT_FOR_CHECKPOINTER 4
#define XT_FOR_POOL 5
void xt_create_database(XTThreadPtr th, char *path);
XTDatabaseHPtr xt_get_database(XTThreadPtr self, const char *path, xtBool multi_path);
XTDatabaseHPtr xt_get_database_by_id(XTThreadPtr self, xtDatabaseID db_id);
void xt_drop_database(XTThreadPtr self, XTDatabaseHPtr db);
void xt_add_pbxt_file(size_t size, char *path, const char *file);
void xt_add_location_file(size_t size, char *path);
void xt_add_tables_file(size_t size, char *path);
void xt_add_pbxt_dir(size_t size, char *path);
void xt_add_system_dir(size_t size, char *path);
void xt_add_data_dir(size_t size, char *path);
void xt_use_database(XTThreadPtr self, XTDatabaseHPtr db, int what_for);
void xt_unuse_database(XTThreadPtr self, XTThreadPtr other_thr);
void xt_open_database(XTThreadPtr self, const char *path, xtBool multi_path);
void xt_lock_installation(XTThreadPtr self, const char *installation_path);
void xt_unlock_installation(XTThreadPtr self, const char *installation_path);
void xt_crash_me(void);
void xt_init_databases(XTThreadPtr self);
void xt_stop_database_threads(XTThreadPtr self, xtBool sync);
void xt_exit_databases(XTThreadPtr self);
void xt_dump_database(XTThreadPtr self, XTDatabaseHPtr db);
void xt_db_init_thread_ns(XTThreadPtr new_thread);
void xt_db_exit_thread(XTThreadPtr self);
void xt_db_pool_init(XTThreadPtr self, struct XTDatabase *db);
void xt_db_pool_exit(XTThreadPtr self, struct XTDatabase *db);
XTOpenTablePoolPtr xt_db_lock_table_pool_by_name(XTThreadPtr self, XTDatabaseHPtr db, XTPathStrPtr name, xtBool no_load, xtBool flush_table, xtBool missing_ok, XTTableHPtr *ret_tab);
void xt_db_unlock_table_pool(struct XTThread *self, XTOpenTablePoolPtr table_pool);
XTOpenTablePtr xt_db_open_pool_table(XTThreadPtr self, XTDatabaseHPtr db, xtTableID tab_id, int *result, xtBool i_am_background);
XTOpenTablePtr xt_db_open_table_using_tab(XTTableHPtr tab, XTThreadPtr thread);
xtBool xt_db_open_pool_table_ns(XTOpenTablePtr *ret_ot, XTDatabaseHPtr db, xtTableID tab_id);
void xt_db_return_table_to_pool(XTThreadPtr self, XTOpenTablePtr ot);
void xt_db_return_table_to_pool_ns(XTOpenTablePtr ot);
void xt_db_free_unused_open_tables(XTThreadPtr self, XTDatabaseHPtr db);
void xt_db_thread_pool_init(XTThreadPtr self, struct XTDatabase *db);
void xt_db_thread_pool_exit(XTThreadPtr self, struct XTDatabase *db);
void xt_db_stop_pool_threads(XTThreadPtr self, struct XTDatabase *db);
xtBool xt_run_async_task(XTTask *task_data, xtBool notify_complete, xtBool notify_early, XTThreadPtr thread, struct XTDatabase *db);
void xt_wait_for_async_tasks(XTThreadPtr thread);
XTTask *xt_get_task_result(XTThreadPtr thread);
xtBool xt_wait_for_async_task_results(XTThreadPtr thread);
void xt_async_task_notify(XTTask *tk);
void xt_unit_test_async_task(XTThreadPtr self);
#define XT_LONG_RUNNING_TIME 2
inline void xt_xlog_check_long_writer(XTThreadPtr thread)
{
if (thread->st_xact_writer) {
if (xt_db_approximate_time - thread->st_xact_write_time > XT_LONG_RUNNING_TIME) {
if (!thread->st_xact_long_running) {
thread->st_xact_long_running = TRUE;
thread->st_database->db_xn_long_running_count++;
}
}
}
}
extern XTDatabaseHPtr pbxt_database; // The global open database
#endif
|