mirror of
https://github.com/MariaDB/server.git
synced 2025-09-13 12:52:18 +02:00
362 lines
13 KiB
C++
362 lines
13 KiB
C++
/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
|
|
#ident "$Id$"
|
|
/*======
|
|
This file is part of PerconaFT.
|
|
|
|
|
|
Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
|
|
|
|
PerconaFT is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License, version 2,
|
|
as published by the Free Software Foundation.
|
|
|
|
PerconaFT 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 PerconaFT. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
----------------------------------------
|
|
|
|
PerconaFT is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Affero General Public License, version 3,
|
|
as published by the Free Software Foundation.
|
|
|
|
PerconaFT 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 Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
|
|
======= */
|
|
|
|
#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
|
|
|
|
#pragma once
|
|
|
|
#include "portability/toku_stdint.h"
|
|
|
|
#include "ft/txn/txn_state.h"
|
|
#include "ft/serialize/block_table.h"
|
|
#include "ft/ft-status.h"
|
|
#include "util/omt.h"
|
|
|
|
typedef uint64_t TXNID;
|
|
|
|
typedef struct tokutxn *TOKUTXN;
|
|
|
|
#define TXNID_NONE_LIVING ((TXNID)0)
|
|
#define TXNID_NONE ((TXNID)0)
|
|
#define TXNID_MAX ((TXNID)-1)
|
|
|
|
typedef struct txnid_pair_s {
|
|
TXNID parent_id64;
|
|
TXNID child_id64;
|
|
} TXNID_PAIR;
|
|
|
|
static const TXNID_PAIR TXNID_PAIR_NONE = { .parent_id64 = TXNID_NONE, .child_id64 = TXNID_NONE };
|
|
|
|
// We include the child manager here beacuse it uses the TXNID / TOKUTXN types
|
|
#include "ft/txn/txn_child_manager.h"
|
|
|
|
/* Log Sequence Number (LSN)
|
|
* Make the LSN be a struct instead of an integer so that we get better type checking. */
|
|
typedef struct __toku_lsn { uint64_t lsn; } LSN;
|
|
static const LSN ZERO_LSN = { .lsn = 0 };
|
|
static const LSN MAX_LSN = { .lsn = UINT64_MAX };
|
|
|
|
//
|
|
// Types of snapshots that can be taken by a tokutxn
|
|
// - TXN_SNAPSHOT_NONE: means that there is no snapshot. Reads do not use snapshot reads.
|
|
// used for SERIALIZABLE and READ UNCOMMITTED
|
|
// - TXN_SNAPSHOT_ROOT: means that all tokutxns use their root transaction's snapshot
|
|
// used for REPEATABLE READ
|
|
// - TXN_SNAPSHOT_CHILD: means that each child tokutxn creates its own snapshot
|
|
// used for READ COMMITTED
|
|
//
|
|
|
|
typedef enum __TXN_SNAPSHOT_TYPE {
|
|
TXN_SNAPSHOT_NONE=0,
|
|
TXN_SNAPSHOT_ROOT=1,
|
|
TXN_SNAPSHOT_CHILD=2,
|
|
TXN_COPIES_SNAPSHOT=3
|
|
} TXN_SNAPSHOT_TYPE;
|
|
|
|
typedef toku::omt<struct tokutxn *> txn_omt_t;
|
|
typedef toku::omt<TXNID> xid_omt_t;
|
|
typedef toku::omt<struct referenced_xid_tuple, struct referenced_xid_tuple *> rx_omt_t;
|
|
|
|
inline bool txn_pair_is_none(TXNID_PAIR txnid) {
|
|
return txnid.parent_id64 == TXNID_NONE && txnid.child_id64 == TXNID_NONE;
|
|
}
|
|
|
|
struct tokulogger;
|
|
|
|
struct txn_roll_info {
|
|
// these are number of rollback nodes and rollback entries for this txn.
|
|
//
|
|
// the current rollback node below has sequence number num_rollback_nodes - 1
|
|
// (because they are numbered 0...num-1). often, the current rollback is
|
|
// already set to this block num, which means it exists and is available to
|
|
// log some entries. if the current rollback is NONE and the number of
|
|
// rollback nodes for this transaction is non-zero, then we will use
|
|
// the number of rollback nodes to know which sequence number to assign
|
|
// to a new one we create
|
|
uint64_t num_rollback_nodes;
|
|
uint64_t num_rollentries;
|
|
uint64_t num_rollentries_processed;
|
|
uint64_t rollentry_raw_count; // the total count of every byte in the transaction and all its children.
|
|
|
|
// spilled rollback nodes are rollback nodes that were gorged by this
|
|
// transaction, retired, and saved in a list.
|
|
|
|
// the spilled rollback head is the block number of the first rollback node
|
|
// that makes up the rollback log chain
|
|
BLOCKNUM spilled_rollback_head;
|
|
|
|
// the spilled rollback is the block number of the last rollback node that
|
|
// makes up the rollback log chain.
|
|
BLOCKNUM spilled_rollback_tail;
|
|
|
|
// the current rollback node block number we may use. if this is ROLLBACK_NONE,
|
|
// then we need to create one and set it here before using it.
|
|
BLOCKNUM current_rollback;
|
|
};
|
|
|
|
struct tokutxn {
|
|
// These don't change after create:
|
|
|
|
TXNID_PAIR txnid;
|
|
|
|
uint64_t snapshot_txnid64; // this is the lsn of the snapshot
|
|
const TXN_SNAPSHOT_TYPE snapshot_type;
|
|
const bool for_recovery;
|
|
struct tokulogger *const logger;
|
|
struct tokutxn *const parent;
|
|
// The child txn is protected by the child_txn_manager lock
|
|
// and by the user contract. The user contract states (and is
|
|
// enforced at the ydb layer) that a child txn should not be created
|
|
// while another child exists. The txn_child_manager will protect
|
|
// other threads from trying to read this value while another
|
|
// thread commits/aborts the child
|
|
struct tokutxn *child;
|
|
|
|
// statically allocated child manager, if this
|
|
// txn is a root txn, this manager will be used and set to
|
|
// child_manager for this transaction and all of its children
|
|
txn_child_manager child_manager_s;
|
|
|
|
// child manager for this transaction, all of its children,
|
|
// and all of its ancestors
|
|
txn_child_manager* child_manager;
|
|
|
|
// These don't change but they're created in a way that's hard to make
|
|
// strictly const.
|
|
DB_TXN *container_db_txn; // reference to DB_TXN that contains this tokutxn
|
|
xid_omt_t *live_root_txn_list; // the root txns live when the root ancestor (self if a root) started.
|
|
struct XIDS_S *xids; // Represents the xid list
|
|
|
|
struct tokutxn *snapshot_next;
|
|
struct tokutxn *snapshot_prev;
|
|
|
|
bool begin_was_logged;
|
|
bool declared_read_only; // true if the txn was declared read only when began
|
|
|
|
// These are not read until a commit, prepare, or abort starts, and
|
|
// they're "monotonic" (only go false->true) during operation:
|
|
bool do_fsync;
|
|
bool force_fsync_on_commit; //This transaction NEEDS an fsync once (if) it commits. (commit means root txn)
|
|
|
|
// Not used until commit, prepare, or abort starts:
|
|
LSN do_fsync_lsn;
|
|
TOKU_XA_XID xa_xid; // for prepared transactions
|
|
TXN_PROGRESS_POLL_FUNCTION progress_poll_fun;
|
|
void *progress_poll_fun_extra;
|
|
|
|
toku_mutex_t txn_lock;
|
|
// Protected by the txn lock:
|
|
toku::omt<struct ft*> open_fts; // a collection of the fts that we touched. Indexed by filenum.
|
|
struct txn_roll_info roll_info; // Info used to manage rollback entries
|
|
|
|
// mutex that protects the transition of the state variable
|
|
// the rest of the variables are used by the txn code and
|
|
// hot indexing to ensure that when hot indexing is processing a
|
|
// leafentry, a TOKUTXN cannot dissappear or change state out from
|
|
// underneath it
|
|
toku_mutex_t state_lock;
|
|
toku_cond_t state_cond;
|
|
TOKUTXN_STATE state;
|
|
uint32_t num_pin; // number of threads (all hot indexes) that want this
|
|
// txn to not transition to commit or abort
|
|
uint64_t client_id;
|
|
void *client_extra;
|
|
time_t start_time;
|
|
};
|
|
typedef struct tokutxn *TOKUTXN;
|
|
|
|
void toku_txn_lock(struct tokutxn *txn);
|
|
void toku_txn_unlock(struct tokutxn *txn);
|
|
|
|
uint64_t toku_txn_get_root_id(struct tokutxn *txn);
|
|
bool txn_declared_read_only(struct tokutxn *txn);
|
|
|
|
int toku_txn_begin_txn (
|
|
DB_TXN *container_db_txn,
|
|
struct tokutxn *parent_tokutxn,
|
|
struct tokutxn **tokutxn,
|
|
struct tokulogger *logger,
|
|
TXN_SNAPSHOT_TYPE snapshot_type,
|
|
bool read_only
|
|
);
|
|
|
|
DB_TXN * toku_txn_get_container_db_txn (struct tokutxn *tokutxn);
|
|
void toku_txn_set_container_db_txn(struct tokutxn *txn, DB_TXN *db_txn);
|
|
|
|
// toku_txn_begin_with_xid is called from recovery and has no containing DB_TXN
|
|
int toku_txn_begin_with_xid (
|
|
struct tokutxn *parent_tokutxn,
|
|
struct tokutxn **tokutxn,
|
|
struct tokulogger *logger,
|
|
TXNID_PAIR xid,
|
|
TXN_SNAPSHOT_TYPE snapshot_type,
|
|
DB_TXN *container_db_txn,
|
|
bool for_recovery,
|
|
bool read_only
|
|
);
|
|
|
|
void toku_txn_update_xids_in_txn(struct tokutxn *txn, TXNID xid);
|
|
|
|
int toku_txn_load_txninfo (struct tokutxn *txn, struct txninfo *info);
|
|
|
|
int toku_txn_commit_txn (struct tokutxn *txn, int nosync,
|
|
TXN_PROGRESS_POLL_FUNCTION poll, void *poll_extra);
|
|
int toku_txn_commit_with_lsn(struct tokutxn *txn, int nosync, LSN oplsn,
|
|
TXN_PROGRESS_POLL_FUNCTION poll, void *poll_extra);
|
|
|
|
int toku_txn_abort_txn(struct tokutxn *txn,
|
|
TXN_PROGRESS_POLL_FUNCTION poll, void *poll_extra);
|
|
int toku_txn_abort_with_lsn(struct tokutxn *txn, LSN oplsn,
|
|
TXN_PROGRESS_POLL_FUNCTION poll, void *poll_extra);
|
|
|
|
int toku_txn_discard_txn(struct tokutxn *txn);
|
|
|
|
void toku_txn_prepare_txn (struct tokutxn *txn, TOKU_XA_XID *xid, int nosync);
|
|
// Effect: Do the internal work of preparing a transaction (does not log the prepare record).
|
|
|
|
void toku_txn_get_prepared_xa_xid(struct tokutxn *txn, TOKU_XA_XID *xa_xid);
|
|
// Effect: Fill in the XID information for a transaction. The caller allocates the XID and the function fills in values.
|
|
|
|
void toku_txn_maybe_fsync_log(struct tokulogger *logger, LSN do_fsync_lsn, bool do_fsync);
|
|
|
|
void toku_txn_get_fsync_info(struct tokutxn *ttxn, bool* do_fsync, LSN* do_fsync_lsn);
|
|
|
|
// Complete and destroy a txn
|
|
void toku_txn_close_txn(struct tokutxn *txn);
|
|
|
|
// Remove a txn from any live txn lists
|
|
void toku_txn_complete_txn(struct tokutxn *txn);
|
|
|
|
// Free the memory of a txn
|
|
void toku_txn_destroy_txn(struct tokutxn *txn);
|
|
|
|
struct XIDS_S *toku_txn_get_xids(struct tokutxn *txn);
|
|
|
|
// Force fsync on commit
|
|
void toku_txn_force_fsync_on_commit(struct tokutxn *txn);
|
|
|
|
void toku_txn_get_status(TXN_STATUS s);
|
|
|
|
bool toku_is_txn_in_live_root_txn_list(const xid_omt_t &live_root_txn_list, TXNID xid);
|
|
|
|
TXNID toku_get_oldest_in_live_root_txn_list(struct tokutxn *txn);
|
|
|
|
TOKUTXN_STATE toku_txn_get_state(struct tokutxn *txn);
|
|
|
|
struct tokulogger_preplist {
|
|
TOKU_XA_XID xid;
|
|
DB_TXN *txn;
|
|
};
|
|
int toku_logger_recover_txn (struct tokulogger *logger, struct tokulogger_preplist preplist[/*count*/], long count, /*out*/ long *retp, uint32_t flags);
|
|
|
|
void toku_maybe_log_begin_txn_for_write_operation(struct tokutxn *txn);
|
|
|
|
// Return whether txn (or it's descendents) have done no work.
|
|
bool toku_txn_is_read_only(struct tokutxn *txn);
|
|
|
|
void toku_txn_lock_state(struct tokutxn *txn);
|
|
void toku_txn_unlock_state(struct tokutxn *txn);
|
|
void toku_txn_pin_live_txn_unlocked(struct tokutxn *txn);
|
|
void toku_txn_unpin_live_txn(struct tokutxn *txn);
|
|
|
|
bool toku_txn_has_spilled_rollback(struct tokutxn *txn);
|
|
|
|
void toku_txn_get_client_id(struct tokutxn *txn, uint64_t *client_id, void **client_extra);
|
|
void toku_txn_set_client_id(struct tokutxn *txn, uint64_t client_id, void *client_extra);
|
|
|
|
time_t toku_txn_get_start_time(struct tokutxn *txn);
|
|
|
|
//
|
|
// This function is used by the leafentry iterators.
|
|
// returns TOKUDB_ACCEPT if live transaction context is allowed to read a value
|
|
// that is written by transaction with LSN of id
|
|
// live transaction context may read value if either id is the root ancestor of context, or if
|
|
// id was committed before context's snapshot was taken.
|
|
// For id to be committed before context's snapshot was taken, the following must be true:
|
|
// - id < context->snapshot_txnid64 AND id is not in context's live root transaction list
|
|
// For the above to NOT be true:
|
|
// - id > context->snapshot_txnid64 OR id is in context's live root transaction list
|
|
//
|
|
int toku_txn_reads_txnid(TXNID txnid, struct tokutxn *txn, bool is_provisional UU());
|
|
|
|
// For serialize / deserialize
|
|
|
|
#include "ft/serialize/wbuf.h"
|
|
|
|
static inline void wbuf_TXNID(struct wbuf *wb, TXNID txnid) {
|
|
wbuf_ulonglong(wb, txnid);
|
|
}
|
|
|
|
static inline void wbuf_nocrc_TXNID(struct wbuf *wb, TXNID txnid) {
|
|
wbuf_nocrc_ulonglong(wb, txnid);
|
|
}
|
|
|
|
static inline void wbuf_nocrc_TXNID_PAIR(struct wbuf *wb, TXNID_PAIR txnid) {
|
|
wbuf_nocrc_ulonglong(wb, txnid.parent_id64);
|
|
wbuf_nocrc_ulonglong(wb, txnid.child_id64);
|
|
}
|
|
|
|
static inline void wbuf_nocrc_LSN(struct wbuf *wb, LSN lsn) {
|
|
wbuf_nocrc_ulonglong(wb, lsn.lsn);
|
|
}
|
|
|
|
static inline void wbuf_LSN(struct wbuf *wb, LSN lsn) {
|
|
wbuf_ulonglong(wb, lsn.lsn);
|
|
}
|
|
|
|
#include "ft/serialize/rbuf.h"
|
|
|
|
static inline void rbuf_TXNID(struct rbuf *rb, TXNID *txnid) {
|
|
*txnid = rbuf_ulonglong(rb);
|
|
}
|
|
|
|
static inline void rbuf_TXNID_PAIR(struct rbuf *rb, TXNID_PAIR *txnid) {
|
|
txnid->parent_id64 = rbuf_ulonglong(rb);
|
|
txnid->child_id64 = rbuf_ulonglong(rb);
|
|
}
|
|
|
|
static inline void rbuf_ma_TXNID(struct rbuf *rb, memarena *UU(ma), TXNID *txnid) {
|
|
rbuf_TXNID(rb, txnid);
|
|
}
|
|
|
|
static inline void rbuf_ma_TXNID_PAIR (struct rbuf *r, memarena *ma __attribute__((__unused__)), TXNID_PAIR *txnid) {
|
|
rbuf_TXNID_PAIR(r, txnid);
|
|
}
|
|
|
|
static inline LSN rbuf_LSN(struct rbuf *rb) {
|
|
LSN lsn = { .lsn = rbuf_ulonglong(rb) };
|
|
return lsn;
|
|
}
|