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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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.
35
#ifndef __TRANSLOG_MS_H__
36
#define __TRANSLOG_MS_H__
39
#include "cslib/CSDefs.h"
40
#include "cslib/CSFile.h"
45
extern uint32_t trans_test_crash_point;
46
#define MAX_CRASH_POINT 10
48
#define MAX_CRASH_POINT 0
51
typedef uint32_t TRef;
56
The transaction log is a circular log of fixed length records. There is assumed to be one
57
reader thread and multiple writer threads. As records are written the 'eol' (End Of Log)
58
marker is advanced and as they are read the 'start' marker is advanved. When iether marker
59
reaches the end of the log a wrap around is done the marker is position back to the top of
62
When both markers are at the same location then the log is empty. The log is full if the
63
eol marker is just behind the start marker.
65
If an overflow occurs then the overflow flag in the log header is set and records are written
66
to the end of the log. New records will continue to be written to the end of log until the
67
reader thread has read ALL of the records in the non overflow portion of the list. When all
68
of these records have been read then the list size will be adjusted to include the overflow
69
record and the start and eol markers are repositioned and the overflow flag in the
70
header is switched off.
74
typedef struct MSDiskTransHead {
75
CSDiskValue4 th_magic_4; /* Table magic number. */
76
CSDiskValue2 th_version_2; /* The header version. */
78
CSDiskValue4 th_next_txn_id_4; /* The next valid transaction ID. */
80
CSDiskValue2 th_check_point_2; /* The frequency whith which the start/end positions are updated in the header. */
82
CSDiskValue4 th_requested_cache_size_4; /* The transaction cache list size in transaction. */
84
CSDiskValue8 th_list_size_8; /* The transaction log list size in records. */
85
CSDiskValue8 th_requested_list_size_8; /* The desired list size. The log will be adjusted to this size as soon as it is convenient.*/
87
CSDiskValue1 th_recovered_1; /* A flag to indicate if the log was closed properly. */
89
CSDiskValue1 th_overflow_1; /* A flag to indicate if overflow has occurred. */
91
// th_start_8 and th_eol_8 are always written at the same time.
92
CSDiskValue8 th_start_8; /* The index of the first valid record. */
93
CSDiskValue8 th_eol_8; /* The index of the first unused record or End Of Log (eol). */
94
CSDiskValue1 th_checksum_1; /* The current record checksum seed. */
95
} MSDiskTransHeadRec, *MSDiskTransHeadPtr;
98
typedef struct MSTrans_tag {
99
uint32_t tr_id; // The transaction ID
100
uint8_t tr_type; // The transaction type. If the first bit is set then the transaction is an autocommit.
101
uint32_t tr_db_id; // The database ID for the operation.
102
uint32_t tr_tab_id; // The table ID for the operation.
103
uint64_t tr_blob_id; // The blob ID for the operation.
104
uint64_t tr_blob_ref_id; // The blob reference id.
105
uint8_t tr_check; // The transaction record checksum.
106
} MSTransRec, *MSTransPtr;
109
typedef struct MSTransStats {
110
uint64_t ts_LogSize; // The number of records in the transaction log.
111
uint32_t ts_PercentFull; // The % of the desired log size in use. This can be > 100%.
112
uint64_t ts_MaxSize; // The log size high water mark.
113
uint32_t ts_OverflowCount; // The number of times the log has overflowen.
114
bool ts_IsOverflowing;
116
uint32_t ts_TransCacheSize; // The number of transactions currently in the cache.
117
uint32_t ts_PercentTransCacheUsed; // The number of transactions currently in the cache.
118
uint32_t ts_PercentCacheHit; // The % of the transactions that were cached on writing.
119
} MSTransStatsRec, *MSTransStatsPtr;
121
typedef enum { MS_RollBackTxn = 0,
122
MS_PartialRollBackTxn,
129
typedef enum { MS_Running = 0,
136
#define TRANS_SET_AUTOCOMMIT(t) (t |= 0X80)
137
#define TRANS_IS_AUTOCOMMIT(t) (t & 0X80)
139
#define TRANS_SET_START(t) (t |= 0X40)
140
#define TRANS_IS_START(t) (t & 0X40)
142
#define TRANS_TYPE_IS_TERMINATED(t) (((t) == MS_RollBackTxn) || ((t) == MS_CommitTxn) || ((t) == MS_RecoveredTxn))
143
#define TRANS_IS_TERMINATED(t) (TRANS_TYPE_IS_TERMINATED(TRANS_TYPE(t)) || TRANS_IS_AUTOCOMMIT(t))
144
#define TRANS_TYPE(t) (t & 0X0F)
146
typedef bool (*CanContinueFunc)();
147
typedef void (*LoadFunc)(uint64_t log_position, MSTransPtr rec);
150
class MSTrans : public CSSharedRefObject {
157
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);
159
void txn_LogPartialRollBack(uint32_t rollBackCount)
161
/* Partial rollbacks store the rollback count in the place of the database id. */
162
txn_LogTransaction(MS_PartialRollBackTxn, false, rollBackCount);
165
void txn_SetCheckPoint(uint16_t checkpoint)
169
// Important lock order. Writer threads never lock the reader but the reader
170
// may lock this object so always lock the reader first.
174
txn_MaxCheckPoint = checkpoint;
176
if (txn_MaxCheckPoint < 10)
177
txn_MaxCheckPoint = 10;
179
if (txn_MaxCheckPoint > txn_MaxRecords)
180
txn_MaxCheckPoint = txn_MaxRecords/2;
182
if (txn_MaxCheckPoint > txn_ReqestedMaxRecords)
183
txn_MaxCheckPoint = txn_ReqestedMaxRecords/2;
185
CS_SET_DISK_2(txn_DiskHeader.th_check_point_2, txn_MaxCheckPoint);
187
txn_File->write(&(txn_DiskHeader.th_check_point_2), offsetof(MSDiskTransHeadRec, th_check_point_2), 2);
197
void txn_SetCacheSize(uint32_t new_size);
199
// txn_SetLogSize() may not take effect immediately but will be done
200
// when there is free space at the end of the log.
201
void txn_SetLogSize(uint64_t new_size);
205
uint64_t txn_GetSize(); // Returns the size of the log in transaction records.
207
uint64_t txn_GetNumRecords() // Returns the number of transactions records waiting to be processed.
208
{ // This doesn't include overflow.
210
if (txn_Start == txn_EOL)
212
else if (txn_Start < txn_EOL)
213
size = txn_EOL - txn_Start;
215
size = txn_MaxRecords - (txn_Start - txn_EOL);
220
// While a backup is in progress the transaction thread will not be signaled
221
// about completed transactions.
222
void txn_BackupStarting()
224
txn_Doingbackup = true;
225
txn_reader->suspend();
228
bool txn_haveNextTransaction();
230
void txn_BackupCompleted()
232
txn_Doingbackup = false;
233
txn_reader->resume();
236
// The following should only be called by the transaction processing thread.
238
// txn_GetNextTransaction() gets the next completed transaction.
239
// If there is none ready it waits for one.
240
void txn_GetNextTransaction(MSTransPtr tran, MS_TxnState *state);
242
void txn_SetReader(CSDaemon *reader) {txn_reader = reader;}
244
// Search the transaction log for a MS_ReferenceTxn record for the given BLOB.
245
bool txn_FindBlobRef(MS_TxnState *state, uint32_t db_id, uint32_t tab_id, uint64_t blob_id);
247
// Mark all transactions for a given database as dropped. Including commited transactions.
248
void txn_dropDatabase(uint32_t db_id);
251
uint64_t txn_GetStartPosition() { return txn_Start;}
253
const char *txn_GetTXNLogPath() {return txn_File->myFilePath->getCString();}
255
friend class ReadTXNLog;
257
uint16_t txn_MaxCheckPoint; // The maximum records to be written ore read before the positions in the header are updated.
259
// These fields are only used by the reader thread:
260
bool txn_Doingbackup;// Is the database being backed up.
261
CSDaemon *txn_reader; // THe transaction log reader daemon. (unreferenced)
262
bool txn_IsTxnValid; // Is the current transaction valid.
263
TRef txn_CurrentTxn; // The current transaction.
264
uint32_t txn_TxnIndex; // The record index into the current transaction.
265
int32_t txn_StartCheckPoint; // Counter to determin when the read position should be flushed.
267
void txn_PerformIdleTasks();
269
MSTransCache *txn_TransCache; // Transaction cache
271
void txn_ResizeLog();
273
void txn_NewTransaction(); // Clears the old transaction ID
277
return (txn_HaveOverflow || ((txn_GetNumRecords() +1) == txn_MaxRecords));
281
uint32_t txn_BlockingTransaction; // The transaction ID the transaction thread is waiting on.
283
MSDiskTransHeadRec txn_DiskHeader;
286
int32_t txn_EOLCheckPoint; // Counter to determin when the EOL position should be flushed.
288
// The size of the transaction log can be adjusted by setting txn_ReqestedMaxRecords.
289
// The log size will be adjusted as soon as there are free slots at the bottom of the list.
290
uint64_t txn_MaxRecords; // The number of record slots in the current list.
291
uint64_t txn_ReqestedMaxRecords; // The number of record slots requested.
293
uint64_t txn_HighWaterMark; // Keeps track of the log size high water mark.
294
uint64_t txn_OverflowCount; // A count of the number of times the transaction log has over flown.
297
void txn_DumpLog(const char *file);
300
bool txn_Recovered; // Has the log been recovered.
301
bool txn_HaveOverflow; // A flag to indicate the list has overfown.
302
uint64_t txn_Overflow; // The index of the next overflow record.
303
uint64_t txn_EOL; // The index of the first unused record or End Of Log (eol).
304
uint64_t txn_Start; // The index of the first valid record.
307
void txn_GetStats(MSTransStatsPtr stats); // Get the current performance statistics.
310
uint8_t txn_Checksum; // The current record checksum seed.
312
void txn_SetFile(CSFile *tr_file); // Set the file to use for the transaction log.
313
bool txn_ValidRecord(MSTransPtr rec); // Check to see if a record is valid.
314
void txn_GetRecordAt(uint64_t index, MSTransPtr rec); // Reads 1 record from the log.
315
void txn_ResetReadPosition(uint64_t pos); // Reset txn_Start
318
void txn_Recover(); // Recover the transaction log.
320
void txn_ReadLog(uint64_t read_start, bool log_locked, CanContinueFunc canContinue, LoadFunc load); // A generic method for reading the log
321
void txn_LoadTransactionCache(uint64_t read_start); // Load the transactions in the log into cache.
323
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);
327
static MSTrans* txn_NewMSTrans(const char *log_path, bool dump_log = false);
332
ReadTXNLog(MSTrans *txn_log): rl_log(txn_log){}
333
virtual ~ReadTXNLog(){}
336
void rl_ReadLog(uint64_t read_start, bool log_locked);
337
virtual bool rl_CanContinue();
338
virtual void rl_Load(uint64_t log_position, MSTransPtr rec);
339
void rl_Store(uint64_t log_position, MSTransPtr rec);
343
#endif //__TRANSLOG_MS_H__