blob: f95c126d0e6e35e889d14707cd6a7d94e10cad77 [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 <algorithm>
#include <iostream>
#include <string>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <curses.h>
#include <term.h>
#include <time.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <sys/time.h>
#include "dtm/tm.h"
#include "../tmlibmsg.h"
#include "seabed/ms.h"
// General Seaquest includes
#include "SCMVersHelp.h"
// Version
DEFINE_EXTERN_COMP_DOVERS(dtmci)
const char ga_timestamp[] = "v 3.1.0, Nov 26, 2014";
#define MAX_NODES 256
using namespace std;
extern const char *ms_getenv_str(const char *pp_key);
enum {
INPUT_LENGTH = 1024,
TRANSID_LEN = 32
};
char * remove_white_space (char *pp_cmd)
{
if(!pp_cmd) {
return NULL;
}
char *lp_ptr = pp_cmd;
while (lp_ptr && *lp_ptr && (*lp_ptr == ' ' || *lp_ptr == '\t'))
{
lp_ptr++;
}
int length = strlen(lp_ptr) - 1;
char test = lp_ptr[length];
while ((test == ' ' || test == '\t') && (length > 0))
{
length--;
test = lp_ptr[length];
}
lp_ptr[length+1] = '\0';
return lp_ptr;
}
void get_cmd(char*& pp_input, char pa_output[])
{
// Empty string case
if(strlen(pp_input) == 0) {
pa_output[0] = '\0';
}
else {
char * lp_remaining;
pp_input = remove_white_space(pp_input);
// Find where the space is, if no space then strcpy
lp_remaining = strchr(pp_input, ' ');
if(lp_remaining == NULL) {
strncpy(pa_output, pp_input, INPUT_LENGTH);
pa_output[INPUT_LENGTH-1] = '\0';
strcpy(pp_input,"");
}
else {
int lv_wordlen = lp_remaining-pp_input;
strncpy(pa_output, pp_input, lv_wordlen);
pa_output[lv_wordlen] = '\0';
pp_input += lv_wordlen;
pp_input = remove_white_space(pp_input);
}
}
}
char *printtimeformatted(struct timeval pp_time) {
char *la_timereturn = new char[20];
int lv_microsec = pp_time.tv_usec / 1000;
unsigned int lv_hours, lv_minutes, lv_seconds, lv_timesec;
lv_timesec = pp_time.tv_sec;
//hours
lv_hours = (lv_timesec / 3600);
//minutes
lv_minutes = ((lv_timesec % 3600) / 60);
//seconds
lv_seconds = (( lv_timesec % 3600) % 60);
sprintf(la_timereturn, "%d:%02d:%02d.%02d", lv_hours, lv_minutes, lv_seconds, lv_microsec);
return la_timereturn;
}
void get_time_difference(struct timeval *pp_result, struct timeval *pp_firsttime, struct timeval *pp_secondtime) {
long int lv_difference = (pp_secondtime->tv_usec + 1000000 * pp_secondtime->tv_sec) -
(pp_firsttime->tv_usec + 1000000 * pp_firsttime->tv_sec);
pp_result->tv_sec = lv_difference / 1000000;
pp_result->tv_usec = lv_difference % 1000000;
}
void print_transid_str(int32 pv_node, int32 pv_seqnum) {
char la_transid_str[TRANSID_LEN];
sprintf(la_transid_str,"(%d,%d)", pv_node, pv_seqnum);
la_transid_str[TRANSID_LEN-1] = '\0';
printf("%-16s", la_transid_str);
}
long now()
{
struct timezone lv_tz = {0, NULL};
timeval lv_now;
int lv_success = gettimeofday(&lv_now, &lv_tz);
if (lv_success != 0)
{
printf("\n** gettimeofday returned error %d.", lv_success);
abort();
}
return lv_now.tv_sec;
}
char *booltoa(bool pv_bool)
{
static char la_text[10];
char *lp_text = (char *) &la_text;
memset(lp_text, 0, sizeof(la_text));
if (pv_bool)
strcpy(lp_text, "true");
else
strcpy(lp_text, "false");
return lp_text;
} //booltoa
char *tmstatetoa(int32 pv_state)
{
static char la_text[10];
char *lp_text = (char *) &la_text;
memset(lp_text, 0, sizeof(la_text));
switch (pv_state)
{
case TM_STATE_INITIAL:
strcpy(lp_text, "INITIAL");
break;
case TM_STATE_UP:
strcpy(lp_text, "UP");
break;
case TM_STATE_DOWN:
strcpy(lp_text, "DOWN");
break;
case TM_STATE_SHUTTING_DOWN:
strcpy(lp_text, "SHUTD_S");
break;
case TM_STATE_SHUTDOWN_FAILED:
strcpy(lp_text, "SHUTD_F");
break;
case TM_STATE_SHUTDOWN_COMPLETED:
strcpy(lp_text, "SHUTD_C");
break;
case TM_STATE_TX_DISABLED:
strcpy(lp_text, "TX_DISA");
break;
case TM_STATE_TX_DISABLED_SHUTDOWN_PHASE1:
strcpy(lp_text, "TX_DISS");
break;
case TM_STATE_QUIESCE:
strcpy(lp_text, "QUIESCE");
break;
case TM_STATE_DRAIN:
strcpy(lp_text, "DRAIN");
break;
case TM_STATE_WAITING_RM_OPEN:
strcpy(lp_text, "WAIT_RM");
break;
default:
sprintf(lp_text, "%d", pv_state);
break;
}
return lp_text;
} //tmstatetoa
char *tmsysrecovstatetoa(int32 pv_state)
{
static char la_text[10];
char *lp_text = (char *) &la_text;
memset(lp_text, 0, sizeof(la_text));
switch (pv_state)
{
case TM_SYS_RECOV_STATE_INIT:
strcpy(lp_text, "INIT");
break;
case TM_SYS_RECOV_STATE_START:
strcpy(lp_text, "START");
break;
case TM_SYS_RECOV_STATE_END:
strcpy(lp_text, "END");
break;
default:
sprintf(lp_text, "%d", pv_state);
break;
}
return lp_text;
} //tmsysrecovstatetoa
char *tmshutdownleveltoa(int32 pv_state)
{
static char la_text[10];
char *lp_text = (char *) &la_text;
memset(lp_text, 0, sizeof(la_text));
switch (pv_state)
{
case MS_Mon_ShutdownLevel_Undefined:
strcpy(lp_text, "RUNNING");
break;
case MS_Mon_ShutdownLevel_Normal:
strcpy(lp_text, "NORMAL");
break;
case MS_Mon_ShutdownLevel_Immediate:
strcpy(lp_text, "IMMEDIATE");
break;
case MS_Mon_ShutdownLevel_Abrupt:
strcpy(lp_text, "ABRUPT");
break;
default:
sprintf(lp_text, "%d", pv_state);
break;
}
return lp_text;
} //tmshutdownleveltoa
char *rmstatetoa(int32 pv_state)
{
static char la_text[10];
char *lp_text = (char *) &la_text;
memset(lp_text, 0, sizeof(la_text));
switch (pv_state)
{
case TSEBranch_UP:
strcpy(lp_text, "UP");
break;
case TSEBranch_DOWN:
strcpy(lp_text, "DOWN");
break;
case TSEBranch_FAILED:
strcpy(lp_text, "FAILED");
break;
case TSEBranch_RECOVERING:
strcpy(lp_text, "RECOVER");
break;
case TSEBranch_FAILOVER:
strcpy(lp_text, "FAILOVER");
break;
default:
sprintf(lp_text, "%d", pv_state);
break;
}
return lp_text;
} //rmstatetoa
char * rmidtoa(int32 pv_rmid)
{
RMID lv_rmid;
static char la_text[10];
char *lp_text = (char *) &la_text;
memset(lp_text, 0, sizeof(la_text));
lv_rmid.iv_rmid = pv_rmid;
sprintf(lp_text, "(%d,%d)", lv_rmid.s.iv_nid, lv_rmid.s.iv_num);
return lp_text;
} //rmidtoa
void print_timedStats(TIMEDSTATS pv_stats)
{
double lv_mean = 0;
double lv_stddevSq = 0;
double lv_stddev = 0;
if (pv_stats.iv_count > 0)
{
lv_mean = pv_stats.iv_total / pv_stats.iv_count;
lv_stddevSq = (pv_stats.iv_totalSq - (pow(pv_stats.iv_total, 2) / pv_stats.iv_count)) / pv_stats.iv_count;
if (lv_stddevSq < 0)
lv_stddevSq = -lv_stddevSq;
lv_stddev = sqrt(lv_stddevSq);
}
printf("%d(%0.3f+-%0.3fs)", pv_stats.iv_count, lv_mean, lv_stddev);
} //print_timedStats
void print_txnStats(TXNSTATS *pp_stats)
{
printf("\n Txns\tTotal ");
print_timedStats(pp_stats->iv_txnTotal);
printf("\tBegins ");
print_timedStats(pp_stats->iv_txnBegin);
printf("\n\tAborts ");
print_timedStats(pp_stats->iv_txnAbort);
printf("\tCommits ");
print_timedStats(pp_stats->iv_txnCommit);
printf("\n XA\tstart ");
print_timedStats(pp_stats->iv_xa_start);
printf("\tend ");
print_timedStats(pp_stats->iv_xa_end);
printf("\n\tprepare ");
print_timedStats(pp_stats->iv_xa_prepare);
printf("\tax_reg ");
print_timedStats(pp_stats->iv_ax_reg);
printf("\n\tcommit ");
print_timedStats(pp_stats->iv_xa_commit);
printf("\trollback ");
print_timedStats(pp_stats->iv_xa_rollback);
printf("\n RM\tSends ");
print_timedStats(pp_stats->iv_RMSend);
printf("\tPartic %d\t Non-partic %d",
pp_stats->iv_RMParticCount,
pp_stats->iv_RMNonParticCount);
} //print_txnStats
void print_poolStats(TMPOOLSTATS pv_pool)
{
int32 lv_secs;
int32 lv_Allocs_new_persec;
int32 lv_Allocs_free_persec;
int32 lv_Deallocs_free_persec;
int32 lv_Deallocs_delete_persec;
long lv_now = now();
printf("Inuse %d\tFree %d\tSSLow %d\tSSHigh %d\tMax %d",
pv_pool.iv_inUseListNow,
pv_pool.iv_freeListNow,
pv_pool.iv_steadyStateLow,
pv_pool.iv_steadyStateHigh,
pv_pool.iv_max
);
lv_secs = lv_now - (int32) pv_pool.iv_lastTimeInterval;
if (lv_secs == 0)
lv_secs = 1; //Crude, but avoids divide by 0 for now
lv_Allocs_new_persec = pv_pool.iv_totalAllocs_new / lv_secs;
lv_Allocs_free_persec = pv_pool.iv_totalAllocs_free / lv_secs;
lv_Deallocs_free_persec = pv_pool.iv_totalDeallocs_free / lv_secs;
lv_Deallocs_delete_persec = pv_pool.iv_totalDeallocs_delete / lv_secs;
printf("\n Allocs:\tnew %d(%d/sec)\tfrees %d(%d/sec)\n Deallocs:\tfrees %d(%d/sec)\tdeletes %d(%d/sec)",
pv_pool.iv_totalAllocs_new,
lv_Allocs_new_persec,
pv_pool.iv_totalAllocs_free,
lv_Allocs_free_persec,
pv_pool.iv_totalDeallocs_free,
lv_Deallocs_free_persec,
pv_pool.iv_totalDeallocs_delete,
lv_Deallocs_delete_persec
);
} //print_poolStats
void print_txnstatus(int32 pv_status)
{
switch (pv_status)
{
case TM_TX_STATE_ACTIVE:
printf("ACTIVE");
break;
case TM_TX_STATE_FORGOTTEN:
printf("FORGOTTEN");
break;
case TM_TX_STATE_COMMITTED:
printf("COMMITTED");
break;
case TM_TX_STATE_ABORTING:
printf("ABORTING");
break;
case TM_TX_STATE_ABORTING_PART2:
printf("ABORTING PT2");
break;
case TM_TX_STATE_ABORTED:
printf("ABORTED");
break;
case TM_TX_STATE_HUNGABORTED:
printf("HUNGABORTED");
break;
case TM_TX_STATE_HUNGCOMMITTED:
printf("HUNGCOMMITTED");
break;
case TM_TX_STATE_COMMITTING:
printf("COMMITTING");
break;
case TM_TX_STATE_PREPARING:
printf("PREPARING");
break;
case TM_TX_STATE_FORGETTING:
printf("FORGETTING");
break;
case TM_TX_STATE_FORGOTTEN_HEUR:
printf("FORGOTTEN_HEUR");
break;
case TM_TX_STATE_FORGETTING_HEUR:
printf("FORGETTING_HEUR");
break;
case TM_TX_STATE_BEGINNING:
printf("BEGINNING");
break;
case TM_TX_STATE_NOTX:
printf("INITIALIZE");
break;
default:
{
printf("(%d)", pv_status);
break;
}
} //switch
} // print_txnstatus
void process_tmstats_node(bool pv_reset, int32 pv_nid)
{
short lv_error = 0;
TM_TMSTATS lv_stats;
lv_error = TMSTATS(pv_nid, &lv_stats, pv_reset);
if (lv_error)
printf("Node %d\t**Error %d.", pv_nid, lv_error);
else
{
printf("Node %d:", pv_nid);
print_txnStats(&lv_stats.iv_txn);
// Pool statistics
printf("\n Txn Pool:\t");
print_poolStats(lv_stats.iv_transactionPool_stats);
printf("\n Thrd Pool:\t");
print_poolStats(lv_stats.iv_threadPool_stats);
printf("\n RMMsg Pool:\t");
print_poolStats(lv_stats.iv_RMMessagePool_stats);
}
printf("\n");
} //process_tmstats_node
void process_tmstats(bool pv_reset, int32 pv_node)
{
int lv_error = 0;
int lv_dtm_count = 0;
if (pv_node != -1)
process_tmstats_node(pv_reset, pv_node);
else
{
lv_error = msg_mon_get_node_info ( &lv_dtm_count,
MAX_NODES,
NULL);
for (int lv_inx = 0; lv_inx < lv_dtm_count; lv_inx++)
process_tmstats_node(pv_reset, lv_inx);
}
} //process_tmstats
bool sort_comparator(TM_STATUS_ALL_TRANS a, TM_STATUS_ALL_TRANS b)
{
return (a.iv_timestamp < b.iv_timestamp);
} // sort_comparator
void process_statusalltransactions_node(int32 pv_node)
{
short lv_error = FEOK;
short lv_count = 0;
time_t lv_trans_timestamp;
time_t lv_elapsed_time;
time_t lv_localtime;
struct tm * lv_trans_timeinfo;
TM_STATUS_ALL_TRANS lv_trans[TM_MAX_LIST_TRANS];
lv_error = DTM_STATUSALLTRANS((TM_STATUS_ALL_TRANS *) &lv_trans, &lv_count, pv_node);
if(lv_error)
printf("**Error returned for node %d : %d\n", pv_node, lv_error);
else
{
if (lv_count == 0)
printf("Node %d : No Transactions were returned.\n", pv_node);
else
printf("Transid Owner\tJoins\tPartic\tUnresol\tElapsed(sec)\tState\t Timestamp\n");
sort(lv_trans, lv_trans + lv_count, sort_comparator);
for(int i = 0; i < lv_count; i++)
{
print_transid_str(lv_trans[i].iv_nid, lv_trans[i].iv_seqnum);
printf("%d,%d\t%d\t%d\t%d",
lv_trans[i].iv_owner_nid,
lv_trans[i].iv_owner_pid,
lv_trans[i].iv_num_active_partic-1,
lv_trans[i].iv_num_partic_RMs,
lv_trans[i].iv_num_unresolved_RMs);
lv_localtime = time(NULL);
lv_trans_timestamp = (time_t)(lv_trans[i].iv_timestamp/1000);
lv_elapsed_time = lv_localtime - lv_trans_timestamp;
lv_trans_timeinfo = localtime (&lv_trans_timestamp);
printf("\t%ld\t\t", lv_elapsed_time);
print_txnstatus(lv_trans[i].iv_status);
if (lv_trans[i].iv_XARM_branch)
printf(" XARM");
if (lv_trans[i].iv_transactionBusy)
printf(" txnBusy");
if (lv_trans[i].iv_mark_for_rollback)
printf(" willRollback");
if (lv_trans[i].iv_tm_aborted)
printf(" tmAborted");
if (lv_trans[i].iv_read_only)
printf(" readOnly");
if (lv_trans[i].iv_recovering)
printf(" recovering");
printf("\t%s", asctime (lv_trans_timeinfo));
}
}
}//process_statusalltransactions_node
void process_statusalltransactions(int32 pv_node)
{
int lv_error = 0;
int lv_dtm_count = 0;
if(pv_node !=-1)
cout << "Info specific node: " << pv_node << "\n";
else
{
lv_error = msg_mon_get_node_info(&lv_dtm_count,
MAX_NODES,
NULL);
for(int lv_inx =0; lv_inx < lv_dtm_count; lv_inx++)
{
process_statusalltransactions_node(lv_inx);
}
}
}//process_statusalltransactions
void process_list_node(int32 pv_node)
{
short lv_error = FEOK;
short lv_count = 0;
TM_LIST_TRANS lv_trans[TM_MAX_LIST_TRANS];
lv_error = LISTTRANSACTION((TM_LIST_TRANS *) &lv_trans, &lv_count, pv_node);
if (lv_error)
printf("**Error returned for node %d : %d\n", pv_node, lv_error);
else
{
if (lv_count == 0)
printf("Node %d : No Transactions were returned.\n", pv_node);
else
printf("Transid Owner\teventQ\tpending\tJoiners\tTSEs\tState\n");
for (int i = 0; i < lv_count; i++)
{
print_transid_str(lv_trans[i].iv_nid, lv_trans[i].iv_seqnum);
printf("%d,%d\t%d\t%d\t%d\t%d\t",
lv_trans[i].iv_owner_nid,
lv_trans[i].iv_owner_pid,
lv_trans[i].iv_event_count,
lv_trans[i].iv_pendingRequest_count,
lv_trans[i].iv_num_active_partic-1,
lv_trans[i].iv_num_partic_RMs);
print_txnstatus(lv_trans[i].iv_status);
if (lv_trans[i].iv_XARM_branch)
printf(" XARM");
if (lv_trans[i].iv_transactionBusy)
printf(" txnBusy");
if (lv_trans[i].iv_mark_for_rollback)
printf(" willRollback");
if (lv_trans[i].iv_tm_aborted)
printf(" tmAborted");
if (lv_trans[i].iv_read_only)
printf(" readOnly");
if (lv_trans[i].iv_recovering)
printf(" recovering");
printf("\n");
} //else for
} //else no error.
} //process_list_node
void process_list(int32 pv_node)
{
int lv_error = 0;
int lv_dtm_count = 0;
if (pv_node != -1)
process_list_node(pv_node);
else
{
lv_error = msg_mon_get_node_info (&lv_dtm_count,
MAX_NODES,
NULL);
for (int lv_inx = 0; lv_inx < lv_dtm_count; lv_inx++)
process_list_node(lv_inx);
}
} //process_list
bool process_attachrm_node(char* pp_rmname, int32 pv_node)
{
int32 lv_error = DTM_ATTACHRM(pv_node, pp_rmname);
if (lv_error != FEOK)
{
printf("%d\tTM process down. Returned error: %d\n", pv_node, lv_error);
return false; // fail
}
else
{
printf("%d\tTM process successfully received attach rm %s request\n", pv_node, pp_rmname);
return true; // success
}
}
void process_attachrm(char* pp_rmname)
{
short lv_error = 0;
static int lv_max_dtm_count = 0;
int lv_dtm_count = 0;
lv_error = msg_mon_get_node_info ( &lv_dtm_count,
MAX_NODES,
NULL);
if (lv_error != FEOK)
cout << "** msg_mon_get_process_info_type returned error " << lv_error << endl;
else
{
// Remember the lagest number of TMs seen
if (lv_max_dtm_count < lv_dtm_count)
lv_max_dtm_count = lv_dtm_count;
if (lv_dtm_count == 0)
cout << "** No TMs running." << endl;
else
{
for (int lv_inx = 0; lv_inx < lv_max_dtm_count; lv_inx++)
{
printf("sending attach for %s to node %d\n", pp_rmname, lv_inx);
process_attachrm_node(pp_rmname, lv_inx);
}
}
}
} //process_attachrm
bool process_statustm_node(int32 pv_node, bool pv_detail, bool pv_sortrmid)
{
RM_INFO temp_rm;
char lv_buffer[TM_MsgSize(Statustm_Rsp_Type) + (sizeof(RM_INFO) * MAX_OPEN_RMS)];
memset(lv_buffer,0,TM_MsgSize(Statustm_Rsp_Type) + (sizeof(RM_INFO) * MAX_OPEN_RMS));
TMSTATUS *lp_tmstatus = (TMSTATUS *) &lv_buffer;
char *lp_string;
int32 lv_error = DTM_STATUSTM(pv_node, lp_tmstatus);
if (lv_error != FEOK)
{
printf("%d\tTM process down. Returned error: %d\n", pv_node, lv_error);
return false; // fail
}
else
{
printf("%d\t%s\t%s\t",
lp_tmstatus->iv_node,
booltoa(lp_tmstatus->iv_isLeadTM),
tmstatetoa(lp_tmstatus->iv_state));
printf("%s\t",
tmsysrecovstatetoa(lp_tmstatus->iv_sys_recovery_state));
lp_string = tmshutdownleveltoa(lp_tmstatus->iv_shutdown_level);
printf("%s\t", lp_string);
if (strlen(lp_string) < 9)
printf("\t");
printf("%d\t%d\t%s\t%d\n",
lp_tmstatus->iv_incarnation_num,
lp_tmstatus->iv_number_active_txns,
booltoa(lp_tmstatus->iv_is_isolated),
lp_tmstatus->iv_rm_count);
if (pv_detail)
{
bool done;
int j;
if(pv_sortrmid) {
for (int i=1; i<lp_tmstatus->iv_rm_count; i++)
{
temp_rm = lp_tmstatus->ia_rminfo[i];
j = i-1;
done = false;
do {
if(lp_tmstatus->ia_rminfo[j].iv_rmid > temp_rm.iv_rmid) {
lp_tmstatus->ia_rminfo[j+1] = lp_tmstatus->ia_rminfo[j];
j = j-1;
if(j < 0) {
done = true;
}
}
else {
done = true;
}
} while (done == false);
lp_tmstatus->ia_rminfo[j+1] = temp_rm;
}
}
else {
//sorting by name - insertion sort
for (int i=1; i<lp_tmstatus->iv_rm_count; i++)
{
temp_rm = lp_tmstatus->ia_rminfo[i];
j = i-1;
done = false;
do {
if(strcmp(lp_tmstatus->ia_rminfo[j].ia_name, temp_rm.ia_name) > 0) {
lp_tmstatus->ia_rminfo[j+1] = lp_tmstatus->ia_rminfo[j];
j = j-1;
if(j < 0) {
done = true;
}
}
else {
done = true;
}
} while (done == false);
lp_tmstatus->ia_rminfo[j+1] = temp_rm;
}
}
if(lp_tmstatus->iv_rm_count > 0) {
printf("\n RM State\tinuse\trmid\tpartic?\tpid\n");
for (int i=0; i<lp_tmstatus->iv_rm_count; i++)
{
printf(" %s\t", lp_tmstatus->ia_rminfo[i].ia_name);
if (strlen(lp_tmstatus->ia_rminfo[i].ia_name) < 6)
printf("\t");
printf("%s\t%s\t%s\t%s\t(%d,%d)\n",
rmstatetoa(lp_tmstatus->ia_rminfo[i].iv_state),
booltoa(lp_tmstatus->ia_rminfo[i].iv_in_use),
rmidtoa(lp_tmstatus->ia_rminfo[i].iv_rmid),
booltoa(lp_tmstatus->ia_rminfo[i].iv_partic),
lp_tmstatus->ia_rminfo[i].iv_nid,
lp_tmstatus->ia_rminfo[i].iv_pid);
}
}
}
return true; // success
}
} //process_statustm_node
void process_statustm(int32 pv_node, bool pv_sortrmid)
{
short lv_error = 0;
static int lv_max_dtm_count = 0;
int lv_dtm_count = 0;
if (pv_node != -1)
{
printf("Node\tLeadTM\tState\tSysRec\tShutdownLevel\tIncarn"
"\tTxns\tIsolTM\tRMs\n");
process_statustm_node(pv_node, true, pv_sortrmid);
}
else
{
lv_error = msg_mon_get_node_info ( &lv_dtm_count,
MAX_NODES,
NULL);
if (lv_error != FEOK)
cout << "** msg_mon_get_process_info_type returned error " << lv_error << endl;
else
{
// Remember the lagest number of TMs seen
if (lv_max_dtm_count < lv_dtm_count)
lv_max_dtm_count = lv_dtm_count;
if (lv_dtm_count == 0)
cout << "** No TMs running." << endl;
else
{
printf("Node\tLeadTM\tState\tSysRec\tShutdownLevel\tIncarn"
"\tTxns\tIsolTM\tRMs\n");
for (int lv_inx = 0; lv_inx < lv_max_dtm_count; lv_inx++)
process_statustm_node(lv_inx, false, false);
}
}
}
} //process_statustm
void process_statussystem()
{
TM_STATUSSYS lv_system_info;
//DTM_STATUSSYSTEM(&lv_system_info);
short lv_error = DTM_STATUSSYSTEM(&lv_system_info);
if (lv_error != FEOK)
printf("** DTM_STATUSSYSTEM returned error %d.\n", lv_error);
else
{
printf("Lead\tUp\tDown\tRecov\tTotal\tActive Txs\n");
printf("%d\t%d\t%d\t%d\t%d\t%d\n",
lv_system_info.iv_leadtm,
lv_system_info.iv_up,
lv_system_info.iv_down,
lv_system_info.iv_recovering,
lv_system_info.iv_totaltms,
lv_system_info.iv_activetxns
);
}
} //process_statustransaction
void process_statustransaction(const char *transid)
{
char la_transid_node[TRANSID_LEN];
char la_transid_seqn[TRANSID_LEN];
char *lp_deleteval;
short lv_error = 0;
TM_STATUS_TRANS lv_trans_info;
typedef struct txid{
int32 iv_seqnum;
int32 iv_node;
} txid;
union {
txid iv_txid;
int64 iv_int_txid;
} u;
//specify default for union
u.iv_int_txid = 0;
if (!strchr(transid, ',')) {
lv_error = DTM_STATUSTRANSACTION(atoi(transid), &lv_trans_info);
}
else {
strncpy(la_transid_node, transid, TRANSID_LEN);
la_transid_node[TRANSID_LEN -1] = '\0';
la_transid_node[strchr(transid, ',') - transid] = '\0';
strncpy(la_transid_seqn, strstr(transid, ","), TRANSID_LEN);
la_transid_seqn[TRANSID_LEN -1] = '\0';
lp_deleteval = la_transid_seqn;
++lp_deleteval;
u.iv_txid.iv_seqnum = atoi(lp_deleteval);
u.iv_txid.iv_node = atoi(la_transid_node);
lv_error = DTM_STATUSTRANSACTION(u.iv_int_txid, &lv_trans_info);
}
if (lv_error == FENOTRANSID) {
cout << "** Trans ID not found\n";
}
else if(lv_error == FEINVTRANSID) {
cout << "** Invalid Trans ID\n";
}
else if(lv_error != FEOK) {
cout << "** Unable to obtain transaction status\n";
}
else {
union txid {
TM_Txid_Internal iv_txid_internal;
TM_Transid_Type iv_transid_type;
} u;
u.iv_transid_type = lv_trans_info.iv_transid;
time_t lv_timestamp = (time_t)(u.iv_txid_internal.iv_timestamp/1000);
struct tm * lv_timeinfo;
lv_timeinfo = localtime (&lv_timestamp);
printf("Transid Owner\teventQ\tpending\tJoiners\tTSEs\tTX Fl\tTT Fl\tROnly\tRecov\tState\n");
print_transid_str(lv_trans_info.iv_nid, lv_trans_info.iv_seqnum);
printf("%d,%d\t%d\t%d\t%d\t%d\t0x%x\t0x" PFLLX "\t",
lv_trans_info.iv_owner_nid,
lv_trans_info.iv_owner_pid,
lv_trans_info.iv_event_count,
lv_trans_info.iv_pendingRequest_count,
lv_trans_info.iv_num_active_partic-1,
lv_trans_info.iv_num_partic_RMs,
lv_trans_info.iv_tx_flags,
lv_trans_info.iv_tt_flags);
fputs(lv_trans_info.iv_read_only ? "true" : "false",stdout);
fputs("\t",stdout);
fputs(lv_trans_info.iv_recovering ? "true" : "false",stdout);
fputs("\t",stdout);
print_txnstatus(lv_trans_info.iv_status);
printf ("\n");
printf("Timestamp: %s", asctime (lv_timeinfo));
}
} //process_statustransaction
void process_gettransinfo(const char *transid, bool pv_string_cmd)
{
char la_transid_node[TRANSID_LEN];
char la_transid_seqn[TRANSID_LEN];
char *lp_deleteval;
short lv_error = 0;
int32 *lp_seq_num = new int32();
int32 *lp_node = new int32();
int16 *lp_incarnation_num = new int16();
int16 *lp_tx_flags = new int16();
TM_TT_Flags *lp_tt_flags = new TM_TT_Flags();
int16 *lp_version = new int16();
int16 *lp_checksum = new int16();
int64 *lp_timestamp = new int64();
typedef struct txid{
int32 iv_seqnum;
int32 iv_node;
} txid;
union {
txid iv_txid;
int64 iv_int_txid;
} u;
union {
TM_TT_Flags iv_tt_flags;
int64 iv_int_tt_flags;
} u_flag;
//specify default for union
u.iv_int_txid = 0;
if (!strchr(transid, ',')) {
lv_error = DTM_GETTRANSINFO(atoi(transid),
lp_seq_num,
lp_node,
lp_incarnation_num,
lp_tx_flags,
lp_tt_flags,
lp_version,
lp_checksum,
lp_timestamp);
}
else {
strncpy(la_transid_node, transid, TRANSID_LEN - 1);
la_transid_node[strchr(transid, ',') - transid] = '\0';
strncpy(la_transid_seqn, strstr(transid, ","), TRANSID_LEN - 1);
lp_deleteval = la_transid_seqn;
++lp_deleteval;
u.iv_txid.iv_seqnum = atoi(lp_deleteval);
u.iv_txid.iv_node = atoi(la_transid_node);
lv_error = DTM_GETTRANSINFO(u.iv_int_txid,
lp_seq_num,
lp_node,
lp_incarnation_num,
lp_tx_flags,
lp_tt_flags,
lp_version,
lp_checksum,
lp_timestamp);
}
if (lv_error == FENOTRANSID) {
cout << "** Trans ID not found\n";
}
else if(lv_error == FEINVTRANSID) {
cout << "** Invalid Trans ID\n";
}
else if(lv_error != FEOK) {
cout << "** Unable to obtain transaction status\n";
}
if(lv_error == FEOK) {
if(pv_string_cmd) {
//process string command output
cout << "(" << *lp_node << "," << *lp_seq_num
<< "," << *lp_incarnation_num << ")" << endl;
}
else {
u_flag.iv_tt_flags = *lp_tt_flags;
//output regular transid command output
printf("Transid Node Seq # Incarn TX Flags TT Flags\n");
print_transid_str(*lp_node, *lp_seq_num);
#if __WORDSIZE == 64
printf("%-4d %-5d %-6d 0x%-6x 0x%-6lx\t\n", *lp_node, *lp_seq_num,
*lp_incarnation_num, *lp_tx_flags, u_flag.iv_int_tt_flags);
printf("Version Checksum Timestamp\n");
printf("%-7d %-8d %15ld\n", *lp_version, *lp_checksum, *lp_timestamp);
#else
printf("%-4d %-5d %-6d 0x%-6x 0x%-6llx\t\n", *lp_node, *lp_seq_num,
*lp_incarnation_num, *lp_tx_flags, u_flag.iv_int_tt_flags);
printf("Version Checksum Timestamp\n");
printf("%-7d %-8d %15lld\n", *lp_version, *lp_checksum, *lp_timestamp);
#endif
}
}
delete lp_seq_num;
delete lp_node;
delete lp_incarnation_num;
delete lp_tx_flags;
delete lp_tt_flags;
delete lp_version;
delete lp_checksum;
delete lp_timestamp;
} //process_gettransinfo
//-----------------------------------------------------------------------------------------
// process_request_regions_info
//
// Purpose: Display transaction region information from hbase and hbase-trx client.
// client.
//-----------------------------------------------------------------------------------------
void process_request_regions_info()
{
short lv_error = FEOK;
short lv_count = 0;
TM_HBASEREGIONINFO lv_trans_reg[TM_MAX_LIST_TRANS];
size_t tn_end, rid_end, h_end, p_end;
string tname, tname_tmp, regid, hname, pname;
size_t init = 0;
lv_error = HBASETM_REQUESTREGIONINFO((TM_HBASEREGIONINFO *) &lv_trans_reg, &lv_count);
if(lv_error!=FEOK)
printf("Error Returned for HBASETM_REQUESTREGIONINFO: %d\n", lv_error);
else
{
if(lv_count == 0)
printf("Error returned for HBASE_REQUESTREGIONINFO %d\n", lv_error);
else
{
printf("Transid\t\tStatus\tRegionId\tHostname\t\tPort\tTableName\n");
for(int i=0; i<lv_count; i++)
{
printf("----------------------------------------------------------------------------------------------\n");
print_transid_str(lv_trans_reg[i].iv_nid, lv_trans_reg[i].iv_seqnum);
print_txnstatus(lv_trans_reg[i].iv_status);
tname = lv_trans_reg[i].iv_tablename;
tn_end = tname.find(';');
regid = lv_trans_reg[i].iv_region_id;
rid_end = regid.find(';');
hname = lv_trans_reg[i].iv_hostname;
h_end = hname.find(';');
pname = lv_trans_reg[i].iv_port;
p_end = pname.find(';');
while(tn_end != std::string::npos){
// tablename
tname_tmp = tname.substr(init, tn_end);
if((tname_tmp.compare("TRAFODION._MD_.VIEWS") && tname_tmp.compare("TRAFODION._MD_.UNIQUE_REF_CONSTR_USAGE")
&& tname_tmp.compare("TRAFODION._MD_.OBJECTS_UNIQ_IDX") && tname_tmp.compare("TRAFODION._MD_.TABLE_CONSTRAINTS")
&& tname_tmp.compare("TRAFODION._MD_.INDEXES") && tname_tmp.compare("TRAFODION._MD_.KEYS")
&& tname_tmp.compare("TRAFODION._MD_.COLUMNS") && tname_tmp.compare("TRAFODION._MD_.TABLES")) != 0) {
// region id
cout << "\n\t\t\t" << regid.substr(init, rid_end) << '\t';
regid = regid.substr(rid_end+1);
rid_end = regid.find(';');
// hostname
cout << hname.substr(init, h_end) << '\t';
hname = hname.substr(h_end+1);
h_end = hname.find(';');
// port
cout << pname.substr(init, p_end) << '\t';
pname = pname.substr(p_end+1);
p_end = pname.find(';');
// tablename
cout << tname_tmp << '\t';
}
tname = tname.substr(tn_end+1);
tn_end = tname.find(';');
}
printf("\n");
}
}
}
}// process_request_regions_info
void process_disableTrans(int32 pv_type)
{
short lv_error = DTM_DISABLETRANSACTIONS(pv_type);
if (lv_error != FEOK)
cout << "** DTM_DISABLETRANSACITONS(" << pv_type << ") returned error "
<< lv_error << endl;
} //process_disableTrans
void process_drainTrans(int32 pv_node, bool pv_immediate)
{
short lv_error = DTM_DRAINTRANSACTIONS(pv_node, pv_immediate);
if (lv_error != FEOK)
cout << "** DTM_DRAINTRANSACITONS(" << pv_node << ", " << pv_immediate
<< ") returned error " << lv_error << endl;
} //process_drainTrans
void process_enableTrans()
{
short lv_error = DTM_ENABLETRANSACTIONS();
if (lv_error != FEOK) {
cout << "** DTM_ENABLETRANSACITONS returned error " << lv_error;
if (lv_error == 2) {
cout << ", FEINVALOP";
}
cout << endl;
}
} //process_enableTrans
void process_quiesce(int32 pv_node)
{
short lv_error = DTM_QUIESCE(pv_node);
if (lv_error != FEOK)
cout << "** DTM_QUIESCE(" << pv_node
<< ") returned error " << lv_error << endl;
} //process_quiesce
void process_unquiesce(int32 pv_node)
{
short lv_error = DTM_UNQUIESCE(pv_node);
if (lv_error != FEOK)
cout << "** DTM_UNQUIESCE(" << pv_node
<< ") returned error " << lv_error << endl;
} //process_unquiesce
FILE * openInput(char * pp_inFile)
{
FILE *lp_in = fopen(pp_inFile, "r");
if (!lp_in)
{
cout << "**Error opening input file " << pp_inFile << endl;
exit(-1);
}
return lp_in;
}
void print_helptext()
{
cout << "DTM Command line interface. " << ga_timestamp << " Help:";
cout << endl << " a | abort ";
cout << endl << " : Will abort the current transaction.";
cout << endl << " b | begin ";
cout << endl << " : Will begin a transaction and display the tag";
cout << endl << " disable trans[actions] [, shutdown normal|immediate] ";
cout << endl << " : Disable transaction processing in DTM.";
cout << endl << " : shutdown is only provided for testing and should";
cout << endl << " : not be used. Use sqstop instead.";
cout << endl << " drain <nid> [, immediate] "
<< endl << " : Drain transactions from a node."
<< endl << " : This is similar to disable but affects"
<< endl << " : only one node."
<< endl << " : Immediately causes all active transactions"
<< endl << " : in the node to be aborted.";
cout << endl << " e | commit ";
cout << endl << " : Will end the current transaction";
cout << endl << " enable trans[actions] ";
cout << endl << " : Enable transaction processing in DTM.";
cout << endl << " l | list [<nid>] ";
cout << endl << " : Will list all transactions and their status for ";
cout << endl << " : node <nid> or all nodes if none specified.";
cout << endl << " r | t | resume [<tag>]";
cout << endl << " : Will suspend the current transaction if no tag is supplied.";
cout << endl << " : if tag is specified it will resume work on the given tag";
cout << endl << " s | stats [<nid> | [reset]]";
cout << endl << " : Will list the current TM statistics";
cout << endl << " : If reset is specified, reset statistics after ";
cout << endl << " : displaying them.";
cout << endl << " status system";
cout << endl << " : Prints system TM information";
cout << endl << " status tm [<nid>] [rmid]";
cout << endl << " : Status of the TM in node <nid>. Returns TM information ";
cout << endl << " : for all nodes if none specified. Specifying a node gives ";
cout << endl << " : RM details.";
cout << endl << " : <rmid> option sorts by rmid, default is sort by rm name.";
cout << endl << " status trans[action] [transid]";
cout << endl << " : Status of the specified transaction.";
cout << endl << " : transid may be in numeric or <node>,<sequence> format.";
// cout << endl << " status regions";
// cout << endl << " : Status of the transactions on the hbase regions - client side";
cout << endl << " transid [string] <transid>";
cout << endl << " : Prints transaction ID information";
cout << endl << " : Entering string option outputs (node, sequence, incarn #)";
cout << endl << " h | ? | help";
cout << endl << " : Display this help.";
cout << endl << " q | quit | exit";
cout << endl << " : Exit dtmci" << endl;
} //print_helptext
void print_ciHelp()
{
cout << "dtmci: DTM command line interface." << endl;
cout << "Usage: dtmci [OPTION] [command]" << endl;
cout << " -h, -?, --help" << "\tdisplay help text." << endl;
cout << " --version\t\tversion information." << endl;
cout << " command\t\tdtmci command." << endl << endl;
} //print_ciHelp
void print_ciError(char *argv)
{
cout << "dtmci: Invalid option -- " << argv << endl;
} //print_ciError
int processArgs(int argc, char *argv[])
{
int i = 1; //Ignore arg[0] - prog name
bool done = false;
char *lp_arg = argv[i];
while (!done)
{
if (!memcmp(&lp_arg[0], "-", 1))
{
if (!strcmp(&lp_arg[1], "h") || !strcmp(&lp_arg[1], "H") ||
!strcmp(&lp_arg[1], "?"))
{
print_ciHelp();
exit(0);
}
else if (!strcmp(&lp_arg[1], "-help"))
{
print_ciHelp();
print_helptext();
exit(0);
}
else
{
print_ciError(argv[i]);
exit(-1);
}
i++;
if (i == argc)
done = true;
else
lp_arg = argv[i];
}
else
done = true;
}
return argc - i;
} //processArgs
int main(int argc, char *argv[])
{
char la_in[INPUT_LENGTH];
char la_cpy[INPUT_LENGTH];
char *lp_inputstr;
char lp_nextcmd[INPUT_LENGTH] = "";
bool lv_done = false;
int lv_param1;
bool lv_bool1;
const char lc_name[10] = "";
char * lp_name = (char *) &lc_name;
int32 lv_error = FEOK;
struct timeval lv_begintime, lv_endtime, lv_timedifference;
bool lv_timeset = false;
char *lp_cmd = NULL;
bool lv_singleCommand = false;
bool lv_shellExec = false;
FILE *lp_in = NULL;
CALL_COMP_DOVERS(dtmci, argc, argv);
lp_cmd = new char[INPUT_LENGTH];
memset(lp_cmd, 0, INPUT_LENGTH);
if (argc > 1)
{
int lv_startArg = 1;
if(!strcmp(argv[1], "SQMON1.0")) {
lv_shellExec = true;
}
else
// Started normally and has argument
lv_singleCommand = true;
if(lv_shellExec && argc > 11) {
lv_startArg = 11;
lv_singleCommand = true;
}
if(lv_singleCommand) {
int lv_commands = processArgs(argc, argv);
lp_cmd = new char[INPUT_LENGTH];
memset(lp_cmd, 0, INPUT_LENGTH);
for (int i=lv_startArg; i<=lv_commands; i++)
{
strcat(lp_cmd, argv[i]);
strcat(lp_cmd, " ");
argc--;
memset(argv[i], 0, 1);
}
}
}
//sleep(60);
if (!lv_singleCommand)
cout << "DTM Command line interface. " << ga_timestamp << endl;
try
{
if(lv_shellExec) {
lv_error = msg_init(&argc, &argv);
}
else {
lv_error = msg_init_attach(&argc, &argv, true, lp_name);
}
if (lv_error)
{
cout << "** Error " << lv_error
<< " while attempting to attach to Monitor, exiting." << endl;
exit(-2);
}
lv_error = msg_mon_process_startup3(false, false);
if (lv_error)
{
cout << "** Error " << lv_error
<< " from msg_mon_process_startup, exiting." << endl;
exit(-3);
}
}
catch (SB_Fatal_Excep lv_except)
{
cout << "** Error: unable to attach to Monitor or start Seaquest process, exiting." << endl;
exit(-1);
}
if(lv_shellExec)
lp_in = openInput(argv[10]);
putenv((char *) "TMLIB_ENABLE_CLEANUP=0");
while (!lv_done)
{
char *lp_readline;
if (lv_singleCommand)
lp_readline = lp_cmd;
else if (lv_shellExec) {
char *la_buffer = new char[INPUT_LENGTH];
cout << ">>";
if(fgets(la_buffer, INPUT_LENGTH, lp_in) == NULL) {
cout << "**Error: input value is NULL, exiting." << endl;
msg_mon_process_shutdown();
exit(-1);
}
la_buffer[strlen(la_buffer) - 1] = '\0';
lp_readline = la_buffer;
}
else
lp_readline = readline("DTMCI > ");
if(!lp_readline) {
lv_done = true;
cout << endl;
break;
}
strncpy(la_in , remove_white_space(lp_readline), INPUT_LENGTH);
free(lp_readline);
lp_inputstr = la_in;
strncpy(la_cpy, la_in, INPUT_LENGTH);
if(strcmp(lp_inputstr, "") != 0) {
add_history(lp_inputstr);
}
get_cmd(lp_inputstr, lp_nextcmd);
// Process commands:
if (!strcmp(lp_nextcmd, "l") || !strcmp(lp_nextcmd, "list"))
{
get_cmd(lp_inputstr, lp_nextcmd);
if (lp_nextcmd[0] == '\0')
lv_param1 = -1;
else
{
if (!strcmp(lp_nextcmd, "*") || lp_nextcmd[0] == 0)
lv_param1 = -1;
else
lv_param1 = atoi(lp_nextcmd);
}
try {
process_list(lv_param1);
}
catch(SB_Fatal_Excep &){
cout << "An error occurred while trying to process list\n";
}
}
else if ( !strcmp(lp_nextcmd, "attach"))
{
get_cmd(lp_inputstr, lp_nextcmd);
if (!strcmp(lp_nextcmd, "rm"))
{
get_cmd(lp_inputstr, lp_nextcmd);
if (lp_nextcmd[0] == '\0')
cout << "Missing qualifier [TSE name]"<<endl;
else
process_attachrm(lp_nextcmd);
}
else
cout << "Missing qualifier [rm]"<<endl;
}
else if (!strcmp(lp_nextcmd, "b") || !strcmp(lp_nextcmd, "begin"))
{
int lv_tag = 0;
int lv_begin_error = 0;
lv_begin_error = BEGINTRANSACTION( &lv_tag );
if (lv_begin_error == 86) {
cout << "Unable to begin transaction, BEGINTRANSACTION is disabled" << endl;
}
cout << "BEGINTRANSACTION returned error " << lv_begin_error
<< ", tag " << lv_tag << endl;
int32 lv_node, lv_seqnum;
bool lv_local = DTM_LOCALTRANSACTION(&lv_node, &lv_seqnum);
if (lv_local)
cout << "Beginning local transaction (" << lv_node << "," << lv_seqnum << ")." << endl;
else
cout << "Beginning global transaction (" << lv_node << "," << lv_seqnum << ")." << endl;
//set gettimeofday beginning struct here
gettimeofday(&lv_begintime, NULL);
lv_timeset = true;
}
else if (!strcmp(lp_nextcmd, "disable"))
{
get_cmd(lp_inputstr, lp_nextcmd);
// Remove any trailing comma.
char *lp_position = strchr(lp_nextcmd, ',');
if (lp_position)
*lp_position = 0;
if (!strcmp(lp_nextcmd, "transactions") || !strcmp(lp_nextcmd, "transaction") ||
!strcmp(lp_nextcmd, "trans"))
{
get_cmd(lp_inputstr, lp_nextcmd);
if (lp_nextcmd[0] == '\0')
// Not a shutdown
process_disableTrans(TM_DISABLE_NORMAL);
else
{
if (!strcmp(lp_nextcmd, ","))
get_cmd(lp_inputstr, lp_nextcmd);
if (!strcmp(lp_nextcmd, "shutdown"))
{
get_cmd(lp_inputstr, lp_nextcmd);
if (!strcmp(lp_nextcmd, "normal"))
process_disableTrans(TM_DISABLE_SHUTDOWN_NORMAL);
else if (!strcmp(lp_nextcmd, "immediate"))
process_disableTrans(TM_DISABLE_SHUTDOWN_IMMEDIATE);
else
cout << "** Disable trans shutdown missing qualifier." << endl;
}
else
cout << "** Disable trans invalid qualifier " << lp_nextcmd << "." << endl;
}
}
else
cout << "** Disable missing qualifier trans[actions]." << endl;
}
else if (!strcmp(lp_nextcmd, "drain"))
{
get_cmd(lp_inputstr, lp_nextcmd);
if (lp_nextcmd[0] == '\0')
{
// Expected node
cout << "** Drain missing node id." << endl;
lv_param1 = -1;
}
else
{
// Get nid
lv_param1 = atoi(lp_nextcmd);
lv_bool1 = false;
get_cmd(lp_inputstr, lp_nextcmd);
if (!strcmp(lp_nextcmd, "immediate"))
lv_bool1 = true;
else
lv_bool1 = false;
process_drainTrans(lv_param1, lv_bool1);
}
} //drainTrans
else if (!strcmp(lp_nextcmd, "quiesce"))
{
cout << "!!!! Quiesce is only available here for Development testing and must "
<< "not be used for any other purpose." << endl;
get_cmd(lp_inputstr, lp_nextcmd);
if (lp_nextcmd[0] == '\0')
{
// Expected node
cout << "** Quiesce missing node id." << endl;
lv_param1 = -1;
}
else
{
// Get nid
lv_param1 = atoi(lp_nextcmd);
lv_bool1 = false;
get_cmd(lp_inputstr, lp_nextcmd);
if (!strcmp(lp_nextcmd, "stop"))
lv_bool1 = true;
else
lv_bool1 = false;
if (lv_bool1)
process_unquiesce(lv_param1);
else
process_quiesce(lv_param1);
}
} //quiesce
else if (!strcmp(lp_nextcmd, "e") || !strcmp(lp_nextcmd, "commit"))
{
int lv_end_error = ENDTRANSACTION();
if(lv_end_error != 0) {
cout << "ENDTRANSACTION returned error " << lv_end_error << endl;
}
if(lv_timeset == true) {
gettimeofday(&lv_endtime, NULL);
get_time_difference(&lv_timedifference, &lv_begintime, &lv_endtime);
//Print out the time difference
cout << "Elapsed Time: " << printtimeformatted(lv_timedifference) << endl;
lv_timeset = false;
}
}
else if (!strcmp(lp_nextcmd, "a") || !strcmp(lp_nextcmd, "abort"))
{
int lv_abort_error = ABORTTRANSACTION();
if(lv_abort_error != 0) {
cout << "** ABORTTRANSACTION returned error " << lv_abort_error;
if(lv_abort_error == 75) {
cout << ", FENOTRANSID";
}
cout << endl;
}
}
else if (!strcmp(lp_nextcmd, "enable"))
{
get_cmd(lp_inputstr, lp_nextcmd);
if (!strcmp(lp_nextcmd, "transactions") || !strcmp(lp_nextcmd, "transaction") ||
!strcmp(lp_nextcmd, "trans"))
{
process_enableTrans();
}
else
cout << "** Enable missing qualifier trans[actions]." << endl;
}
else if (!strcmp(lp_nextcmd, "r") || !strcmp(lp_nextcmd, "t") || !strcmp(lp_nextcmd, "resume"))
{
get_cmd(lp_inputstr, lp_nextcmd);
int lv_resume_error = FEOK;
if (lp_nextcmd[0] == '\0')
lv_param1 = 0;
else
{
lv_param1 = atoi(lp_nextcmd);
}
if (lv_param1 == 0)
lv_resume_error= RESUMETRANSACTION(NULL);
else
lv_resume_error= RESUMETRANSACTION(lv_param1);
cout << "RESUMETRANSACTION(" << lv_param1 << ") returned error " << lv_resume_error << endl;
}
else if (!strcmp(lp_nextcmd, "s") || !strcmp(lp_nextcmd, "stats"))
{
get_cmd(lp_inputstr, lp_nextcmd);
if (lp_nextcmd[0] == '\0')
process_tmstats(false, -1);
else
{
if (!strcmp(lp_nextcmd, "*"))
lv_param1 = -1;
else
lv_param1 = atoi(lp_nextcmd);
get_cmd(lp_inputstr, lp_nextcmd);
if (lp_nextcmd[0] == '\0')
process_tmstats(false, lv_param1);
else
{
if (!strcmp(lp_nextcmd, "reset"))
process_tmstats(true, lv_param1);
else
cout << "** Stats invalid qualifier " << lp_nextcmd << "." << endl;
}
}
}
else if (!strcmp(lp_nextcmd, "status"))
{
get_cmd(lp_inputstr, lp_nextcmd);
if (!strcmp(lp_nextcmd, "tm"))
{
get_cmd(lp_inputstr, lp_nextcmd);
if (!strcmp(lp_nextcmd, "*") || lp_nextcmd[0] == '\0')
lv_param1 = -1;
else if (isdigit(lp_nextcmd[0])) {
lv_param1 = atoi(lp_nextcmd);
}
else {
lv_param1 = -1;
}
get_cmd(lp_inputstr, lp_nextcmd);
if(!strcmp(lp_nextcmd, "rmid")) {
process_statustm(lv_param1, true);
}
else{
process_statustm(lv_param1, false);
}
}
else if (!strcmp(lp_nextcmd, "transaction") || !strcmp(lp_nextcmd, "trans"))
{
get_cmd(lp_inputstr, lp_nextcmd);
if (!strcmp(lp_nextcmd, "*") || lp_nextcmd[0] == '\0')
{
get_cmd(lp_inputstr, lp_nextcmd);
if (lp_nextcmd[0]=='\0')
{
lv_param1=-1;
process_statusalltransactions(lv_param1);
}
else
{
cout << "Please specify a transaction ID or use *" << endl;
}
}
else
process_statustransaction(lp_nextcmd);
}
else if (!strcmp(lp_nextcmd, "system"))
{
process_statussystem();
}
/*else if(!strcmp(lp_nextcmd, "regions"))
{
process_request_regions_info();
}*/
else
{
cout << endl << "** Invalid qualifier '" <<lp_nextcmd
<< "' for status command." << endl;
}
}
else if (!strcmp(lp_nextcmd, "transid"))
{
get_cmd(lp_inputstr, lp_nextcmd);
if (lp_nextcmd[0] == '\0')
cout << "** Please specify a transaction ID" << endl;
else if (!strcmp(lp_nextcmd, "string")) {
get_cmd(lp_inputstr, lp_nextcmd);
if (lp_nextcmd[0] == '\0')
cout << "** Please specify a transaction ID" << endl;
else
process_gettransinfo(lp_nextcmd, true);
}
else
{
process_gettransinfo(lp_nextcmd, false);
}
}
else if (!strcmp(lp_nextcmd, "q") || !strcmp(lp_nextcmd, "quit") ||
!strcmp(lp_nextcmd, "exit"))
{
cout << "dtmci exiting, goodbye." << endl;
lv_done = true;
}
else if (!strcmp(lp_nextcmd, "h") || !strcmp(lp_nextcmd, "help") || !strcmp(lp_nextcmd, "?"))
{
print_helptext();
}
else if (strcmp(lp_nextcmd, "")!=0)
{
cout << "** Unknown command " << la_cpy << "." << endl;
}
if (lv_singleCommand)
lv_done = true;
} // while
if(lv_shellExec)
fclose(lp_in);
msg_mon_process_shutdown();
return 0;
}