You've already forked mariadb-columnstore-engine
							
							
				mirror of
				https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
				synced 2025-11-03 17:13:17 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			388 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			388 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* Copyright (C) 2014 InfiniDB, Inc.
 | 
						|
 | 
						|
   This program is free software; you can redistribute it and/or
 | 
						|
   modify it under the terms of the GNU General Public License
 | 
						|
   as published by the Free Software Foundation; version 2 of
 | 
						|
   the License.
 | 
						|
 | 
						|
   This program 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 this program; if not, write to the Free Software
 | 
						|
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 | 
						|
   MA 02110-1301, USA. */
 | 
						|
 | 
						|
/*
 | 
						|
* $Id: viewtablelock.cpp 2101 2013-01-21 14:12:52Z rdempsey $
 | 
						|
*/
 | 
						|
 | 
						|
#include <ctime>
 | 
						|
#include <iostream>
 | 
						|
#include <vector>
 | 
						|
#include <stdexcept>
 | 
						|
#include <sstream>
 | 
						|
#include <string>
 | 
						|
 | 
						|
#include "calpontsystemcatalog.h"
 | 
						|
#include "dbrm.h"
 | 
						|
#include "exceptclasses.h"
 | 
						|
 | 
						|
using namespace execplan;
 | 
						|
 | 
						|
namespace
 | 
						|
{
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
// Print command line usage
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
void usage()
 | 
						|
{
 | 
						|
    std::cout << "Usage: viewtablelock [schemaname tablename]" << std::endl
 | 
						|
              << "  If schema/table are specified, then that table's lock " <<
 | 
						|
              "information is displayed." << std::endl
 | 
						|
              << "  If no schema/table are specified, then all table locks "
 | 
						|
              "are displayed." << std::endl;
 | 
						|
}
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
// Print table locks.
 | 
						|
// This function closely resembles CommandPackageProcessor::viewTableLock().
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
int printTableLocks( boost::shared_ptr<CalpontSystemCatalog> systemCatalogPtr,
 | 
						|
                     const std::string& tableNameIn,
 | 
						|
                     const std::vector<BRM::TableLockInfo> tableLocks )
 | 
						|
{
 | 
						|
    if (tableLocks.size() == 1)
 | 
						|
        std::cout << " There is " <<  tableLocks.size() <<
 | 
						|
                  " table lock" << std::endl << std::endl;
 | 
						|
    else
 | 
						|
        std::cout << " There are " <<  tableLocks.size() <<
 | 
						|
                  " table locks" << std::endl << std::endl;
 | 
						|
 | 
						|
    std::string tableName(tableNameIn);
 | 
						|
 | 
						|
    // Make preliminary pass through the table locks in order to determine our
 | 
						|
    // output column widths based on the data.  Min column widths are based on
 | 
						|
    // the width of the column heading (except for the 'state' column).
 | 
						|
    uint64_t maxLockID                = 0;
 | 
						|
    uint32_t maxPID                   = 0;
 | 
						|
    int32_t  maxSessionID             = 0;
 | 
						|
    int32_t  minSessionID             = 0;
 | 
						|
    int32_t  maxTxnID                 = 0;
 | 
						|
 | 
						|
    unsigned int tableNameColumnWidth = 5; // "Table"
 | 
						|
    unsigned int lockIDColumnWidth    = 6; // "LockID"
 | 
						|
    unsigned int ownerColumnWidth     = 7; // "Process"
 | 
						|
    unsigned int pidColumnWidth       = 3; // "PID"
 | 
						|
    unsigned int sessionIDColumnWidth = 7; // "Session"
 | 
						|
    unsigned int txnIDColumnWidth     = 3; // "Txn"
 | 
						|
    unsigned int createTimeColumnWidth = 12; // "CreationTime"
 | 
						|
    unsigned int pmColumnWidth        = 7; // "DBRoots"
 | 
						|
    std::vector<std::string> createTimes;
 | 
						|
    char cTimeBuffer[1024];
 | 
						|
    std::vector<std::string> tableNames;
 | 
						|
 | 
						|
    std::ostringstream errMsgs;
 | 
						|
 | 
						|
    for (unsigned int i = 0; i < tableLocks.size(); i++)
 | 
						|
    {
 | 
						|
        if (tableNameIn.empty())
 | 
						|
        {
 | 
						|
            try
 | 
						|
            {
 | 
						|
                CalpontSystemCatalog::TableName tableNameStruct;
 | 
						|
                tableNameStruct = systemCatalogPtr->tableName(
 | 
						|
                                      tableLocks[i].tableOID);
 | 
						|
                tableName = tableNameStruct.toString();
 | 
						|
            }
 | 
						|
            catch ( logging::IDBExcept&)
 | 
						|
            {
 | 
						|
                tableName.clear();
 | 
						|
 | 
						|
                errMsgs << "Table with oid " << tableLocks[i].tableOID <<
 | 
						|
                        " (Lock " << tableLocks[i].id << ")" <<
 | 
						|
                        " is not in systable." << std::endl;
 | 
						|
            }
 | 
						|
            catch (std::runtime_error& e)
 | 
						|
            {
 | 
						|
                tableName.clear();
 | 
						|
 | 
						|
                errMsgs <<
 | 
						|
                        "Error searching for table " << tableLocks[i].tableOID <<
 | 
						|
                        " (Lock " << tableLocks[i].id << ")" <<
 | 
						|
                        " in system catalog. " << e.what() << std::endl;
 | 
						|
            }
 | 
						|
            catch (...)
 | 
						|
            {
 | 
						|
                tableName.clear();
 | 
						|
 | 
						|
                errMsgs <<
 | 
						|
                        "Unknown error searching for table " <<
 | 
						|
                        tableLocks[i].tableOID <<
 | 
						|
                        " (Lock " << tableLocks[i].id << ")" <<
 | 
						|
                        " in system catalog. " << std::endl;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        tableNames.push_back( tableName );
 | 
						|
 | 
						|
        tableNameColumnWidth = std::max(tableNameColumnWidth,
 | 
						|
                                        static_cast<unsigned int>(tableName.length()));
 | 
						|
        maxLockID = std::max(maxLockID, tableLocks[i].id);
 | 
						|
        ownerColumnWidth = std::max(ownerColumnWidth,
 | 
						|
                                    static_cast<unsigned int>(tableLocks[i].ownerName.length()));
 | 
						|
        maxPID = std::max(maxPID, tableLocks[i].ownerPID);
 | 
						|
        maxSessionID = std::max(maxSessionID, tableLocks[i].ownerSessionID);
 | 
						|
        minSessionID = std::min(minSessionID, tableLocks[i].ownerSessionID);
 | 
						|
        maxTxnID = std::max(maxTxnID, tableLocks[i].ownerTxnID);
 | 
						|
 | 
						|
        ctime_r( &tableLocks[i].creationTime, cTimeBuffer );
 | 
						|
        cTimeBuffer[ strlen(cTimeBuffer) - 1 ] = '\0'; // strip trailing '\n'
 | 
						|
        std::string cTimeStr( cTimeBuffer );
 | 
						|
        createTimeColumnWidth = std::max(createTimeColumnWidth,
 | 
						|
                                         static_cast<unsigned int>(cTimeStr.length()));
 | 
						|
        createTimes.push_back( cTimeStr );
 | 
						|
 | 
						|
        std::ostringstream pms;
 | 
						|
 | 
						|
        for (unsigned k = 0; k < tableLocks[i].dbrootList.size(); k++)
 | 
						|
        {
 | 
						|
            if (k > 0)
 | 
						|
                pms << ',';
 | 
						|
 | 
						|
            pms << tableLocks[i].dbrootList[k];
 | 
						|
        }
 | 
						|
 | 
						|
        pmColumnWidth = std::max(pmColumnWidth,
 | 
						|
                                 static_cast<unsigned int>(pms.str().length()));
 | 
						|
    }
 | 
						|
 | 
						|
    tableNameColumnWidth  += 2;
 | 
						|
    ownerColumnWidth      += 2;
 | 
						|
    pmColumnWidth         += 2;
 | 
						|
    createTimeColumnWidth += 2;
 | 
						|
 | 
						|
    std::ostringstream idString;
 | 
						|
    idString << maxLockID;
 | 
						|
    lockIDColumnWidth = std::max(lockIDColumnWidth,
 | 
						|
                                 static_cast<unsigned int>(idString.str().length()));
 | 
						|
    lockIDColumnWidth += 2;
 | 
						|
 | 
						|
    std::ostringstream pidString;
 | 
						|
    pidString << maxPID;
 | 
						|
    pidColumnWidth = std::max(pidColumnWidth,
 | 
						|
                              static_cast<unsigned int>(pidString.str().length()));
 | 
						|
    pidColumnWidth += 2;
 | 
						|
 | 
						|
    const std::string sessionNoneStr("BulkLoad");
 | 
						|
    std::ostringstream sessionString;
 | 
						|
    sessionString << maxSessionID;
 | 
						|
    sessionIDColumnWidth = std::max(sessionIDColumnWidth,
 | 
						|
                                    static_cast<unsigned int>(sessionString.str().length()));
 | 
						|
 | 
						|
    if (minSessionID < 0)
 | 
						|
        sessionIDColumnWidth = std::max(sessionIDColumnWidth,
 | 
						|
                                        static_cast<unsigned int>(sessionNoneStr.length()));
 | 
						|
 | 
						|
    sessionIDColumnWidth += 2;
 | 
						|
 | 
						|
    const std::string txnNoneStr("n/a");
 | 
						|
    std::ostringstream txnString;
 | 
						|
    txnString << maxTxnID;
 | 
						|
    txnIDColumnWidth = std::max(txnIDColumnWidth,
 | 
						|
                                static_cast<unsigned int>(txnString.str().length()));
 | 
						|
    txnIDColumnWidth += 2;
 | 
						|
 | 
						|
    std::cout.setf(std::ios::left, std::ios::adjustfield);
 | 
						|
    std::cout << "  " <<
 | 
						|
              std::setw(tableNameColumnWidth) << "Table"        <<
 | 
						|
              std::setw(lockIDColumnWidth)    << "LockID"       <<
 | 
						|
              std::setw(ownerColumnWidth)     << "Process"      <<
 | 
						|
              std::setw(pidColumnWidth)       << "PID"          <<
 | 
						|
              std::setw(sessionIDColumnWidth) << "Session"      <<
 | 
						|
              std::setw(txnIDColumnWidth)     << "Txn"          <<
 | 
						|
              std::setw(createTimeColumnWidth) << "CreationTime" <<
 | 
						|
              std::setw(9)                    << "State"        <<
 | 
						|
              std::setw(pmColumnWidth)        << "DBRoots"      << std::endl;
 | 
						|
 | 
						|
    // Make second pass through the table locks to display our result.
 | 
						|
    for (unsigned idx = 0; idx < tableLocks.size(); idx++)
 | 
						|
    {
 | 
						|
        std::ostringstream pms; //dbroots now
 | 
						|
 | 
						|
        for (unsigned k = 0; k < tableLocks[idx].dbrootList.size(); k++)
 | 
						|
        {
 | 
						|
            if (k > 0)
 | 
						|
                pms << ',';
 | 
						|
 | 
						|
            pms << tableLocks[idx].dbrootList[k];
 | 
						|
        }
 | 
						|
 | 
						|
        std::cout << "  " <<
 | 
						|
                  std::setw(tableNameColumnWidth) << tableNames[idx]          <<
 | 
						|
                  std::setw(lockIDColumnWidth)    << tableLocks[idx].id       <<
 | 
						|
                  std::setw(ownerColumnWidth)     << tableLocks[idx].ownerName <<
 | 
						|
                  std::setw(pidColumnWidth)       << tableLocks[idx].ownerPID;
 | 
						|
 | 
						|
        // Log session ID, or "BulkLoad" if session is -1
 | 
						|
        if (tableLocks[idx].ownerSessionID < 0)
 | 
						|
            std::cout << std::setw(sessionIDColumnWidth) << sessionNoneStr;
 | 
						|
        else
 | 
						|
            std::cout << std::setw(sessionIDColumnWidth) <<
 | 
						|
                      tableLocks[idx].ownerSessionID;
 | 
						|
 | 
						|
        // Log txn ID, or "n/a" if txn is -1
 | 
						|
        if (tableLocks[idx].ownerTxnID < 0)
 | 
						|
            std::cout << std::setw(txnIDColumnWidth) << txnNoneStr;
 | 
						|
        else
 | 
						|
            std::cout << std::setw(txnIDColumnWidth) <<
 | 
						|
                      tableLocks[idx].ownerTxnID;
 | 
						|
 | 
						|
        std::cout <<
 | 
						|
                  std::setw(createTimeColumnWidth) <<
 | 
						|
                  createTimes[idx]       <<
 | 
						|
                  std::setw(9) << ((tableLocks[idx].state == BRM::LOADING) ?
 | 
						|
                                   "LOADING" : "CLEANUP") <<
 | 
						|
                  std::setw(pmColumnWidth)        << pms.str() << std::endl;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!errMsgs.str().empty())
 | 
						|
        std::cerr << std::endl << errMsgs.str() << std::endl;
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
// Main entry point to this program
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
int main(int argc, char** argv)
 | 
						|
{
 | 
						|
    int c;
 | 
						|
 | 
						|
    while ((c = getopt(argc, argv, "h")) != EOF)
 | 
						|
    {
 | 
						|
        switch (c)
 | 
						|
        {
 | 
						|
            case 'h':
 | 
						|
            case '?':
 | 
						|
            default:
 | 
						|
                usage();
 | 
						|
                return (c == 'h' ? 0 : 1);
 | 
						|
                break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    int nargs = argc - optind;
 | 
						|
 | 
						|
    if ((nargs > 2) || (nargs == 1))
 | 
						|
    {
 | 
						|
        usage();
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    BRM::DBRM dbrm;
 | 
						|
    std::vector<BRM::TableLockInfo> tableLocks;
 | 
						|
 | 
						|
    try
 | 
						|
    {
 | 
						|
        tableLocks = dbrm.getAllTableLocks();
 | 
						|
    }
 | 
						|
    catch (std::exception& ex)
 | 
						|
    {
 | 
						|
        std::cerr << "Error getting list of table locks: " << ex.what() <<
 | 
						|
                  std::endl;
 | 
						|
        return 2;
 | 
						|
    }
 | 
						|
 | 
						|
    int rc = 0;
 | 
						|
 | 
						|
    if (nargs == 2) // List table lock information for a given table
 | 
						|
    {
 | 
						|
        std::string schema(argv[optind++]);
 | 
						|
        std::string table( argv[optind++]);
 | 
						|
 | 
						|
        // Get table oid
 | 
						|
        boost::shared_ptr<CalpontSystemCatalog> systemCatalogPtr =
 | 
						|
            CalpontSystemCatalog::makeCalpontSystemCatalog(1);
 | 
						|
        systemCatalogPtr->identity(CalpontSystemCatalog::EC);
 | 
						|
        CalpontSystemCatalog::TableName tableName;
 | 
						|
        tableName.schema = schema;
 | 
						|
        tableName.table = table;
 | 
						|
        CalpontSystemCatalog::ROPair roPair;
 | 
						|
 | 
						|
        try
 | 
						|
        {
 | 
						|
            roPair = systemCatalogPtr->tableRID( tableName );
 | 
						|
        }
 | 
						|
        catch (logging::IDBExcept& e)
 | 
						|
        {
 | 
						|
            std::cerr << e.what() << std::endl;
 | 
						|
            return 3;
 | 
						|
        }
 | 
						|
        catch (std::runtime_error& e)
 | 
						|
        {
 | 
						|
            std::cerr << "Error searching for table in system catalog. " <<
 | 
						|
                      e.what() << std::endl;
 | 
						|
            return 4;
 | 
						|
        }
 | 
						|
        catch (...)
 | 
						|
        {
 | 
						|
            std::cerr << "Unknown error searching for table in system catalog."
 | 
						|
                      << std::endl;
 | 
						|
            return 5;
 | 
						|
        }
 | 
						|
 | 
						|
        // Keep in mind the same table could have more than 1 lock
 | 
						|
        // (on different PMs), so we don't exit loop after "first" match.
 | 
						|
        std::vector<BRM::TableLockInfo> matchingTableLocks;
 | 
						|
 | 
						|
        for (unsigned int i = 0; i < tableLocks.size(); i++)
 | 
						|
        {
 | 
						|
            if (roPair.objnum == (CalpontSystemCatalog::OID)
 | 
						|
                    tableLocks[i].tableOID)
 | 
						|
            {
 | 
						|
                matchingTableLocks.push_back( tableLocks[i] );
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if (matchingTableLocks.size() > 0)
 | 
						|
        {
 | 
						|
            std::string tableName(schema);
 | 
						|
            tableName += '.';
 | 
						|
            tableName += table;
 | 
						|
            rc = printTableLocks( systemCatalogPtr,
 | 
						|
                                  tableName, matchingTableLocks );
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            std::cout << " Table " << schema << "." << table <<
 | 
						|
                      " is not locked by any process. " << std::endl;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else // List table lock information for all table locks
 | 
						|
    {
 | 
						|
        //All table lock info required
 | 
						|
        if (tableLocks.size() == 0)
 | 
						|
        {
 | 
						|
            std::cout << " No tables are locked in the database." << std::endl;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            boost::shared_ptr<CalpontSystemCatalog> systemCatalogPtr =
 | 
						|
                CalpontSystemCatalog::makeCalpontSystemCatalog();
 | 
						|
            systemCatalogPtr->identity(CalpontSystemCatalog::EC);
 | 
						|
 | 
						|
            std::string tableName;
 | 
						|
            rc = printTableLocks( systemCatalogPtr,
 | 
						|
                                  tableName, tableLocks );
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return rc;
 | 
						|
}
 |