| // @@@ START COPYRIGHT @@@ |
| // |
| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| // |
| // @@@ END COPYRIGHT @@@ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <assert.h> |
| #include <sys/types.h> |
| |
| #include "seabed/ms.h" |
| #include "seabed/trace.h" |
| #include "tmlogging.h" |
| |
| #include "tmtx.h" |
| #include "tmrm.h" |
| #include "tminfo.h" |
| #include "tmrmtsebranch.h" |
| |
| // ---------------------------------------------------------------- |
| // RM_Info_TSEBranch::init |
| // Purpose : Initialize a TSE branch. |
| // ---------------------------------------------------------------- |
| void RM_Info_TSEBranch::init(int32 pv_pid, int32 pv_nid, char *pp_name, int32 pv_rmid, |
| bool pv_is_ax_reg, TSEBranch_state pv_state, bool pv_clean_init) |
| { |
| iv_state = pv_state; |
| if (pv_clean_init) |
| { |
| iv_in_use = false; |
| iv_partic = false; |
| iv_resolved = false; |
| iv_enlisted = false; |
| iv_rmid = iv_pid = iv_nid = -1; |
| } |
| else |
| { |
| iv_in_use = true; |
| iv_rmid = pv_rmid; |
| iv_pid = pv_pid; |
| iv_nid = pv_nid; |
| strncpy (ia_name, pp_name, 255); |
| |
| if (pv_is_ax_reg) |
| iv_partic = false; |
| else |
| iv_partic = true; |
| |
| // XID related fields |
| TM_RM_Branch_Data lv_bdata; |
| iv_xid.formatID = FORMAT_ID; |
| iv_xid.gtrid_length = sizeof (TM_Transid_Type); |
| iv_xid.bqual_length = sizeof (TM_RM_Branch_Data); |
| lv_bdata.iv_branchtype = 0; |
| lv_bdata.iv_branchid = pv_rmid; |
| memcpy (&iv_xid.data[iv_xid.gtrid_length], |
| &lv_bdata, sizeof (TM_RM_Branch_Data)); |
| |
| } |
| } |
| |
| |
| // ---------------------------------------------------------------- |
| // RM_Info_TSEBranch::close |
| // Purpose : Put the RM in a closed state. |
| // Periodically the TM will attempt to reopen any failed |
| // RMs. |
| // ---------------------------------------------------------------- |
| void RM_Info_TSEBranch::close() |
| { |
| TMTrace (2, ("RM_Info_TSEBranch::close ENTRY for rmid %d\n", iv_rmid)); |
| |
| state(TSEBranch_DOWN); |
| in_use(false); |
| |
| TMTrace (2, ("RM_Info_TSEBranch::close EXIT for rmid=%d.\n", iv_rmid)); |
| } //RM_Info_TSEBranch::close |
| |
| |
| // ---------------------------------------------------------------- |
| // RM_Info_TSEBranch::fail |
| // Purpose : Put the RM in a failed state. |
| // Periodically the TM will attempt to reopen any failed |
| // RMs. |
| // ---------------------------------------------------------------- |
| void RM_Info_TSEBranch::fail() |
| { |
| TMTrace (2, ("RM_Info_TSEBranch::fail ENTRY for rmid %d\n", iv_rmid)); |
| |
| state(TSEBranch_FAILED); |
| // Don't reset in_use, it will stop new transactions attempting |
| // to use this RM. Transactions started with static registration |
| // MUST enlist ALL TSEs in the transaction. |
| //in_use(false); |
| |
| TMTrace (2, ("RM_Info_TSEBranch::fail EXIT for rmid=%d.\n", iv_rmid)); |
| } //RM_Info_TSEBranch::fail |
| |
| |
| // ---------------------------------------------------------------- |
| // RM_Info_TSEBranch::up |
| // Purpose : Put the RM in a up state. |
| // Periodically the TM will attempt to reopen any failed |
| // RMs. |
| // ---------------------------------------------------------------- |
| void RM_Info_TSEBranch::up() |
| { |
| TMTrace (2, ("RM_Info_TSEBranch::up ENTRY for rmid %d\n", iv_rmid)); |
| |
| state(TSEBranch_UP); |
| in_use(true); |
| |
| TMTrace (2, ("RM_Info_TSEBranch::up EXIT for rmid=%d.\n", iv_rmid)); |
| } //RM_Info_TSEBranch::up |
| |
| |
| // ---------------------------------------------------------------- |
| // RM_Info_TSEBranch::copyto |
| // Purpose : Copy the contents of this RM_Info_TSEBranch to a RM_INFO |
| // structure. |
| // ---------------------------------------------------------------- |
| void RM_Info_TSEBranch::copyto(RM_INFO *pp_output) |
| { |
| memcpy(pp_output->ia_name, ia_name, sizeof(pp_output->ia_name)); |
| pp_output->iv_state = iv_state; |
| pp_output->iv_in_use = iv_in_use; |
| pp_output->iv_nid = iv_nid; |
| pp_output->iv_rmid = iv_rmid; |
| pp_output->iv_partic = iv_partic; |
| pp_output->iv_pid = iv_pid; |
| pp_output->iv_totalBranchesLeftToRecover = iv_totalBranchesLeftToRecover; |
| } //RM_Info_TSEBranch::copyto |
| |
| |
| // ---------------------------------------------------------------- |
| // RM_Info_TSEBranch::dec_totalBranchesLeftToRecover |
| // Purpose : For recovering RMs this decrements the |
| // iv_totalBranchesLeftToRecover counter and if it reaches 0, |
| // changes the RM state to TSEBranch_UP. |
| // This only needs to be called by commit_branches and rollback_branches |
| // as transactions can only be in hungCommitted or hungAborted. |
| // ---------------------------------------------------------------- |
| void RM_Info_TSEBranch::dec_totalBranchesLeftToRecover() |
| { |
| if (iv_state == TSEBranch_RECOVERING && |
| iv_totalBranchesLeftToRecover > 0) |
| { |
| iv_totalBranchesLeftToRecover--; |
| if (iv_totalBranchesLeftToRecover <= 0) |
| { |
| up(); |
| } |
| } |
| } // RM_Info_TSEBranch::dec_totalBranchesLeftToRecover |
| |
| |
| // ---------------------------------------------------------------- |
| // RM_Info_TSEBranch::add_partic |
| // Purpose : Add this branch as a participant in the transaction. |
| // If we calling this it means the RM sent us an ax_reg or |
| // a doomtxn, so we can assume it is up even if previously |
| // marked down. |
| // Returns true if the branch was added as a participant |
| // false if the branch is already participating |
| // pp_transid input Transid in which particpation is being requested. |
| // ---------------------------------------------------------------- |
| bool RM_Info_TSEBranch::add_partic(TM_Txid_Internal pv_transid) |
| { |
| bool lv_particAdded = false; |
| |
| if (partic()) |
| { |
| TMTrace(1,("RM_Info_TSEBranch::add_partic WARNING : Txn ID (%d,%d). " |
| "RM %d is already participating in the transaction, ignored.\n", |
| pv_transid.iv_node, pv_transid.iv_seq_num, rmid())); |
| } |
| else |
| { |
| memcpy (&iv_xid.data, &pv_transid, sizeof(TM_Txid_Internal)); |
| partic(true); |
| // If it's particpating, the RM must be up! |
| up(); |
| lv_particAdded = true; |
| TMTrace(3, ("RM_Info_TSEBranch::add_partic : Txn ID (%d,%d) participation set for rmid(%d).\n", |
| pv_transid.iv_node, pv_transid.iv_seq_num, rmid())); |
| } |
| |
| TMTrace(1, ("RM_Info_TSEBranch::add_partic EXIT : Participation set for rmid(%d) returning %d.\n ", |
| rmid(), lv_particAdded)); |
| return lv_particAdded; |
| } // RM_Info_TSEBranch::add_partic |
| |
| #ifdef DEBUG_MODE |
| void RM_Info_TSEBranch::in_use( bool pv_in_use) |
| { TMTrace(3,("RM %s(%d): set in_use old=%d, new=%d.\n",ia_name, iv_rmid, iv_in_use, pv_in_use)); |
| iv_in_use = pv_in_use;} |
| void RM_Info_TSEBranch::partic( bool pv_partic ) |
| { TMTrace(3,("RM %s(%d): set partic old=%d, new=%d.\n",ia_name, iv_rmid, iv_partic, pv_partic)); |
| iv_partic = pv_partic;} |
| void RM_Info_TSEBranch::resolved( bool pv_resolve ) |
| { TMTrace(3,("RM %s(%d): set resolved old=%d, new=%d.\n",ia_name, iv_rmid, iv_resolved, pv_resolve)); |
| iv_resolved = pv_resolve;} |
| void RM_Info_TSEBranch::enlisted( bool pv_enlist ) |
| { TMTrace(3,("RM %s(%d): set enlisted old=%d, new=%d.\n",ia_name, iv_rmid, iv_enlisted, pv_enlist)); |
| iv_enlisted = pv_enlist;} |
| #endif //DEBUG_MODE |