blob: 0fa1853d6e0cdb3db7a8ba956e49ca77de7445dd [file] [log] [blame]
// @@@ 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