1
/* Copyright (c) 2009 PrimeBase Technologies GmbH, Germany
3
* PrimeBase Media Stream for MySQL
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
* PBMS transaction handling.
27
* PBMS uses 1 circular transaction log. All BLOB reference operations are written to this log
28
* and are applied to the repository when committed. There is 1 thread dedicated to reading the
29
* transaction log and applying the changes. During an engine level backup this thread is suspended
30
* so that no transactions will be applied to the repository files as they are backed up.
34
#ifndef __TRANSLOG_MS_H__
35
#define __TRANSLOG_MS_H__
38
#include "cslib/CSDefs.h"
39
#include "cslib/CSFile.h"
44
extern uint32_t trans_test_crash_point;
45
#define MAX_CRASH_POINT 10
47
#define MAX_CRASH_POINT 0
50
typedef uint32_t TRef;
55
The transaction log is a circular log of fixed length records. There is assumed to be one
56
reader thread and multiple writer threads. As records are written the 'eol' (End Of Log)
57
marker is advanced and as they are read the 'start' marker is advanved. When iether marker
58
reaches the end of the log a wrap around is done the marker is position back to the top of
61
When both markers are at the same location then the log is empty. The log is full if the
62
eol marker is just behind the start marker.
64
If an overflow occurs then the overflow flag in the log header is set and records are written
65
to the end of the log. New records will continue to be written to the end of log until the
66
reader thread has read ALL of the records in the non overflow portion of the list. When all
67
of these records have been read then the list size will be adjusted to include the overflow
68
record and the start and eol markers are repositioned and the overflow flag in the
69
header is switched off.
73
typedef struct MSDiskTransHead {
74
CSDiskValue4 th_magic_4; /* Table magic number. */
75
CSDiskValue2 th_version_2; /* The header version. */
77
CSDiskValue4 th_next_txn_id_4; /* The next valid transaction ID. */
79
CSDiskValue2 th_check_point_2; /* The frequency whith which the start/end positions are updated in the header. */
81
CSDiskValue4 th_requested_cache_size_4; /* The transaction cache list size in transaction. */
83
CSDiskValue8 th_list_size_8; /* The transaction log list size in records. */
84
CSDiskValue8 th_requested_list_size_8; /* The desired list size. The log will be adjusted to this size as soon as it is convenient.*/
86
CSDiskValue1 th_recovered_1; /* A flag to indicate if the log was closed properly. */
88
CSDiskValue1 th_overflow_1; /* A flag to indicate if overflow has occurred. */
90
// th_start_8 and th_eol_8 are always written at the same time.
91
CSDiskValue8 th_start_8; /* The index of the first valid record. */
92
CSDiskValue8 th_eol_8; /* The index of the first unused record or End Of Log (eol). */
93
CSDiskValue1 th_checksum_1; /* The current record checksum seed. */
94
} MSDiskTransHeadRec, *MSDiskTransHeadPtr;
97
typedef struct MSTrans_tag {
98
uint32_t tr_id; // The transaction ID
99
uint8_t tr_type; // The transaction type. If the first bit is set then the transaction is an autocommit.
100
uint32_t tr_db_id; // The database ID for the operation.
101
uint32_t tr_tab_id; // The table ID for the operation.
102
uint64_t tr_blob_id; // The blob ID for the operation.
103
uint64_t tr_blob_ref_id; // The blob reference id.
104
uint8_t tr_check; // The transaction record checksum.
105
} MSTransRec, *MSTransPtr;
108
typedef struct MSTransStats {
109
uint64_t ts_LogSize; // The number of records in the transaction log.
110
uint32_t ts_PercentFull; // The % of the desired log size in use. This can be > 100%.
111
uint64_t ts_MaxSize; // The log size high water mark.
112
uint32_t ts_OverflowCount; // The number of times the log has overflowen.
113
bool ts_IsOverflowing;
115
uint32_t ts_TransCacheSize; // The number of transactions currently in the cache.
116
uint32_t ts_PercentTransCacheUsed; // The number of transactions currently in the cache.
117
uint32_t ts_PercentCacheHit; // The % of the transactions that were cached on writing.
118
} MSTransStatsRec, *MSTransStatsPtr;
120
typedef enum { MS_RollBackTxn = 0,
121
MS_PartialRollBackTxn,
128
typedef enum { MS_Running = 0,
135
#define TRANS_SET_AUTOCOMMIT(t) (t |= 0X80)
136
#define TRANS_IS_AUTOCOMMIT(t) (t & 0X80)
138
#define TRANS_SET_START(t) (t |= 0X40)
139
#define TRANS_IS_START(t) (t & 0X40)
141
#define TRANS_TYPE_IS_TERMINATED(t) (((t) == MS_RollBackTxn) || ((t) == MS_CommitTxn) || ((t) == MS_RecoveredTxn))
142
#define TRANS_IS_TERMINATED(t) (TRANS_TYPE_IS_TERMINATED(TRANS_TYPE(t)) || TRANS_IS_AUTOCOMMIT(t))
143
#define TRANS_TYPE(t) (t & 0X0F)
145
typedef bool (*CanContinueFunc)();
146
typedef void (*LoadFunc)(uint64_t log_position, MSTransPtr rec);
149
class MSTrans : public CSSharedRefObject {
156
void txn_LogTransaction(MS_Txn type, bool autocommit = false, uint32_t db_id = 0, uint32_t tab_id = 0, uint64_t blob_id = 0, uint64_t blob_ref_id = 0);
158
void txn_LogPartialRollBack(uint32_t rollBackCount)
160
/* Partial rollbacks store the rollback count in the place of the database id. */
161
txn_LogTransaction(MS_PartialRollBackTxn, false, rollBackCount);
164
void txn_SetCheckPoint(uint16_t checkpoint)
168
// Important lock order. Writer threads never lock the reader but the reader
169
// may lock this object so always lock the reader first.
173
txn_MaxCheckPoint = checkpoint;
175
if (txn_MaxCheckPoint < 10)
176
txn_MaxCheckPoint = 10;
178
if (txn_MaxCheckPoint > txn_MaxRecords)
179
txn_MaxCheckPoint = txn_MaxRecords/2;
181
if (txn_MaxCheckPoint > txn_ReqestedMaxRecords)
182
txn_MaxCheckPoint = txn_ReqestedMaxRecords/2;
184
CS_SET_DISK_2(txn_DiskHeader.th_check_point_2, txn_MaxCheckPoint);
186
txn_File->write(&(txn_DiskHeader.th_check_point_2), offsetof(MSDiskTransHeadRec, th_check_point_2), 2);
196
void txn_SetCacheSize(uint32_t new_size);
198
// txn_SetLogSize() may not take effect immediately but will be done
199
// when there is free space at the end of the log.
200
void txn_SetLogSize(uint64_t new_size);
204
uint64_t txn_GetSize(); // Returns the size of the log in transaction records.
206
uint64_t txn_GetNumRecords() // Returns the number of transactions records waiting to be processed.
207
{ // This doesn't include overflow.
209
if (txn_Start == txn_EOL)
211
else if (txn_Start < txn_EOL)
212
size = txn_EOL - txn_Start;
214
size = txn_MaxRecords - (txn_Start - txn_EOL);
219
// While a backup is in progress the transaction thread will not be signaled
220
// about completed transactions.
221
void txn_BackupStarting()
223
txn_Doingbackup = true;
224
txn_reader->suspend();
227
bool txn_haveNextTransaction();
229
void txn_BackupCompleted()
231
txn_Doingbackup = false;
232
txn_reader->resume();
235
// The following should only be called by the transaction processing thread.
237
// txn_GetNextTransaction() gets the next completed transaction.
238
// If there is none ready it waits for one.
239
void txn_GetNextTransaction(MSTransPtr tran, MS_TxnState *state);
241
void txn_SetReader(CSDaemon *reader) {txn_reader = reader;}
243
// Search the transaction log for a MS_ReferenceTxn record for the given BLOB.
244
bool txn_FindBlobRef(MS_TxnState *state, uint32_t db_id, uint32_t tab_id, uint64_t blob_id);
246
// Mark all transactions for a given database as dropped. Including commited transactions.
247
void txn_dropDatabase(uint32_t db_id);
250
uint64_t txn_GetStartPosition() { return txn_Start;}
252
const char *txn_GetTXNLogPath() {return txn_File->myFilePath->getCString();}
254
friend class ReadTXNLog;
256
uint16_t txn_MaxCheckPoint; // The maximum records to be written ore read before the positions in the header are updated.
258
// These fields are only used by the reader thread:
259
bool txn_Doingbackup;// Is the database being backed up.
260
CSDaemon *txn_reader; // THe transaction log reader daemon. (unreferenced)
261
bool txn_IsTxnValid; // Is the current transaction valid.
262
TRef txn_CurrentTxn; // The current transaction.
263
uint32_t txn_TxnIndex; // The record index into the current transaction.
264
int32_t txn_StartCheckPoint; // Counter to determin when the read position should be flushed.
266
void txn_PerformIdleTasks();
268
MSTransCache *txn_TransCache; // Transaction cache
270
void txn_ResizeLog();
272
void txn_NewTransaction(); // Clears the old transaction ID
276
return (txn_HaveOverflow || ((txn_GetNumRecords() +1) == txn_MaxRecords));
280
uint32_t txn_BlockingTransaction; // The transaction ID the transaction thread is waiting on.
282
MSDiskTransHeadRec txn_DiskHeader;
285
int32_t txn_EOLCheckPoint; // Counter to determin when the EOL position should be flushed.
287
// The size of the transaction log can be adjusted by setting txn_ReqestedMaxRecords.
288
// The log size will be adjusted as soon as there are free slots at the bottom of the list.
289
uint64_t txn_MaxRecords; // The number of record slots in the current list.
290
uint64_t txn_ReqestedMaxRecords; // The number of record slots requested.
292
uint64_t txn_HighWaterMark; // Keeps track of the log size high water mark.
293
uint64_t txn_OverflowCount; // A count of the number of times the transaction log has over flown.
296
void txn_DumpLog(const char *file);
299
bool txn_Recovered; // Has the log been recovered.
300
bool txn_HaveOverflow; // A flag to indicate the list has overfown.
301
uint64_t txn_Overflow; // The index of the next overflow record.
302
uint64_t txn_EOL; // The index of the first unused record or End Of Log (eol).
303
uint64_t txn_Start; // The index of the first valid record.
306
void txn_GetStats(MSTransStatsPtr stats); // Get the current performance statistics.
309
uint8_t txn_Checksum; // The current record checksum seed.
311
void txn_SetFile(CSFile *tr_file); // Set the file to use for the transaction log.
312
bool txn_ValidRecord(MSTransPtr rec); // Check to see if a record is valid.
313
void txn_GetRecordAt(uint64_t index, MSTransPtr rec); // Reads 1 record from the log.
314
void txn_ResetReadPosition(uint64_t pos); // Reset txn_Start
317
void txn_Recover(); // Recover the transaction log.
319
void txn_ReadLog(uint64_t read_start, bool log_locked, CanContinueFunc canContinue, LoadFunc load); // A generic method for reading the log
320
void txn_LoadTransactionCache(uint64_t read_start); // Load the transactions in the log into cache.
322
void txn_AddTransaction(uint8_t tran_type, bool autocommit = false, uint32_t db_id = 0, uint32_t tab_id = 0, uint64_t blob_id = 0, uint64_t blob_ref_id = 0);
326
static MSTrans* txn_NewMSTrans(const char *log_path, bool dump_log = false);
331
ReadTXNLog(MSTrans *txn_log): rl_log(txn_log){}
332
virtual ~ReadTXNLog(){}
335
void rl_ReadLog(uint64_t read_start, bool log_locked);
336
virtual bool rl_CanContinue();
337
virtual void rl_Load(uint64_t log_position, MSTransPtr rec);
338
void rl_Store(uint64_t log_position, MSTransPtr rec);
342
#endif //__TRANSLOG_MS_H__