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 
			
		
		
		
	
		
			
				
	
	
		
			384 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			384 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* Copyright (C) 2014 InfiniDB, Inc.
 | 
						|
   Copyright (C) 2016 MariaDB Corporaton
 | 
						|
 | 
						|
   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: bppseeder.cpp 2035 2013-01-21 14:12:19Z rdempsey $
 | 
						|
// C++ Implementation: bppseeder
 | 
						|
//
 | 
						|
// Description:
 | 
						|
//
 | 
						|
//
 | 
						|
// Author: Patrick <pleblanc@localhost.localdomain>, (C) 2008
 | 
						|
//
 | 
						|
// Copyright: See COPYING file that comes with this distribution
 | 
						|
//
 | 
						|
//
 | 
						|
 | 
						|
#include <unistd.h>
 | 
						|
#include <sstream>
 | 
						|
#ifndef _MSC_VER
 | 
						|
#include <pthread.h>
 | 
						|
#include <boost/date_time/posix_time/posix_time.hpp>
 | 
						|
#else
 | 
						|
typedef int pthread_t;
 | 
						|
#endif
 | 
						|
#include <boost/thread.hpp>
 | 
						|
 | 
						|
#include "bppseeder.h"
 | 
						|
#include "primitiveserver.h"
 | 
						|
#include "pp_logger.h"
 | 
						|
#include "errorcodes.h"
 | 
						|
#include "calpontsystemcatalog.h"
 | 
						|
#include "blockcacheclient.h"
 | 
						|
 | 
						|
using namespace messageqcpp;
 | 
						|
using namespace std;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
namespace primitiveprocessor
 | 
						|
{
 | 
						|
 | 
						|
struct PTLogs{
 | 
						|
	PTLogs() {};
 | 
						|
	PTLogs(const int t, const char * fname):thdId(t) {logFD.open(fname, ios_base::app | ios_base::ate);}
 | 
						|
	~PTLogs() {logFD.close();}
 | 
						|
 | 
						|
	int thdId;
 | 
						|
	ofstream logFD;
 | 
						|
};
 | 
						|
 | 
						|
typedef PTLogs PTLogs_t;
 | 
						|
typedef boost::shared_ptr<PTLogs_t> SPPTLogs_t;
 | 
						|
typedef std::tr1::unordered_map<pthread_t, SPPTLogs_t> PTLogsMap_t;
 | 
						|
 | 
						|
PTLogsMap_t gFDList;
 | 
						|
SPPTLogs_t gLogFD;
 | 
						|
boost::mutex gFDMutex; //pthread_mutex_t gFDMutex=PTHREAD_MUTEX_INITIALIZER;
 | 
						|
int gThdCnt=0;
 | 
						|
 | 
						|
extern dbbc::BlockRequestProcessor **BRPp;
 | 
						|
extern int fCacheCount;
 | 
						|
 | 
						|
 | 
						|
void timespec_sub(const struct timespec &tv1,
 | 
						|
				const struct timespec &tv2,
 | 
						|
				double &tm)
 | 
						|
{
 | 
						|
	tm = (double)(tv2.tv_sec - tv1.tv_sec) + 1.e-9*(tv2.tv_nsec - tv1.tv_nsec);
 | 
						|
}
 | 
						|
 | 
						|
BPPSeeder::BPPSeeder(const SBS &b,
 | 
						|
					const SP_UM_MUTEX& w,
 | 
						|
					const SP_UM_IOSOCK& s,
 | 
						|
					const int pmThreads,
 | 
						|
					const bool trace) :
 | 
						|
					bs(b), writelock(w), sock(s), fPMThreads(pmThreads), fTrace(trace),
 | 
						|
					failCount(0),
 | 
						|
					firstRun(true)
 | 
						|
{
 | 
						|
	uint8_t *buf = b->buf();
 | 
						|
	uint32_t pos = sizeof(ISMPacketHeader);
 | 
						|
 | 
						|
	sessionID = *((uint32_t *) &buf[pos]); pos += 4;
 | 
						|
	stepID = *((uint32_t *) &buf[pos]); pos += 4;
 | 
						|
	uniqueID = *((uint32_t *) &buf[pos]); pos +=4;
 | 
						|
	_priority = *((uint32_t *) &buf[pos]);
 | 
						|
 | 
						|
	dieTime = boost::posix_time::second_clock::universal_time() +
 | 
						|
                boost::posix_time::seconds(100);
 | 
						|
}
 | 
						|
 | 
						|
BPPSeeder::BPPSeeder(const BPPSeeder &b)
 | 
						|
					: bs(b.bs), writelock(b.writelock), sock(b.sock),
 | 
						|
					fPMThreads(b.fPMThreads), fTrace(b.fTrace), uniqueID(b.uniqueID),
 | 
						|
					sessionID(b.sessionID), stepID(b.stepID), failCount(b.failCount), bpp(b.bpp),
 | 
						|
					firstRun(b.firstRun), _priority(b._priority)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
BPPSeeder::~BPPSeeder()
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
int BPPSeeder::operator()()
 | 
						|
{
 | 
						|
	uint32_t pos;
 | 
						|
	const uint8_t *buf = bs->buf();
 | 
						|
	BPPMap::iterator it;
 | 
						|
	ostringstream logData;
 | 
						|
	struct timespec tm;
 | 
						|
	struct timespec tm2;
 | 
						|
	double tm3=0;
 | 
						|
	bool ptLock=false;
 | 
						|
	bool gotBPP = false;
 | 
						|
	PTLogs_t* logFD=NULL;
 | 
						|
	int ret = 0;
 | 
						|
	pthread_t tid=0;
 | 
						|
	boost::mutex::scoped_lock scoped(bppLock, boost::defer_lock_t());
 | 
						|
 | 
						|
	try {
 | 
						|
	if (firstRun) {
 | 
						|
		pos = sizeof(ISMPacketHeader) - 2;
 | 
						|
		uint16_t status = *((uint16_t *) &buf[pos]); pos += 2;
 | 
						|
 | 
						|
		sessionID = *((uint32_t *) &buf[pos]); pos += 4;
 | 
						|
		stepID = *((uint32_t *) &buf[pos]); pos += 4;
 | 
						|
		uniqueID = *((uint32_t *) &buf[pos]); pos += 4;
 | 
						|
		_priority = *((uint32_t *) &buf[pos]);
 | 
						|
 | 
						|
		if (0 < status)
 | 
						|
		{
 | 
						|
			sendErrorMsg(uniqueID, status, stepID);
 | 
						|
			return ret;
 | 
						|
		}
 | 
						|
 | 
						|
		//if (!(sessionID & 0x80000000))
 | 
						|
		//cout << "got request for <" << sessionID <<", " << stepID << ">\n";
 | 
						|
		scoped.lock();
 | 
						|
		if (!bppv) {
 | 
						|
			it = bppMap.find(uniqueID);
 | 
						|
			if (it == bppMap.end()) {
 | 
						|
				/* mitigate a small race between creation and use */
 | 
						|
				scoped.unlock();
 | 
						|
				if (boost::posix_time::second_clock::universal_time() > dieTime) {
 | 
						|
#if 0   // for debugging
 | 
						|
#ifndef _MSC_VER
 | 
						|
					boost::posix_time::ptime pt = boost::posix_time::microsec_clock::local_time();
 | 
						|
					if (sessionID & 0x80000000)
 | 
						|
						cout << "BPPSeeder couldn't find the sessionID/stepID pair.  sessionID="
 | 
						|
							<< (int) (sessionID ^ 0x80000000) << " stepID=" << stepID << " (syscat)" << pt << endl;
 | 
						|
					else
 | 
						|
						cout << "BPPSeeder couldn't find the sessionID/stepID pair.  sessionID="
 | 
						|
							<< sessionID << " stepID=" << stepID << pt << endl;
 | 
						|
#endif
 | 
						|
					throw logic_error("BPPSeeder couldn't find the sessionID/stepID pair");
 | 
						|
#endif
 | 
						|
					return 0;
 | 
						|
				}
 | 
						|
//				if (!isSysCat())
 | 
						|
					return -1;
 | 
						|
//				else {   // syscat queries aren't run by a threadpool, can't reschedule those jobs
 | 
						|
//					usleep(1000);
 | 
						|
//					goto retry;
 | 
						|
//				}
 | 
						|
			}
 | 
						|
			bppv = it->second;
 | 
						|
		}
 | 
						|
		if (bppv->aborted())
 | 
						|
			return 0;
 | 
						|
		bpp = bppv->next();
 | 
						|
		scoped.unlock();
 | 
						|
		if (!bpp) {
 | 
						|
//			if (isSysCat()) {
 | 
						|
//				usleep(1000);
 | 
						|
//				goto retry;
 | 
						|
//			}
 | 
						|
			return -1;    // all BPP instances are busy, make threadpool reschedule
 | 
						|
		}
 | 
						|
		gotBPP = true;
 | 
						|
		bpp->resetBPP(*bs, writelock, sock);
 | 
						|
		firstRun = false;
 | 
						|
	}   // firstRun
 | 
						|
 | 
						|
 | 
						|
	if (fTrace)
 | 
						|
	{
 | 
						|
		PTLogsMap_t::iterator it;
 | 
						|
#ifdef _MSC_VER
 | 
						|
		tid = GetCurrentThreadId();
 | 
						|
#else
 | 
						|
		tid = pthread_self();
 | 
						|
#endif
 | 
						|
 | 
						|
		// only lock map while inserted objects
 | 
						|
		// once there is an object for each thread
 | 
						|
		// there is not need to lock
 | 
						|
		if (gFDList.size()<(uint32_t)fPMThreads) {
 | 
						|
			gFDMutex.lock();
 | 
						|
			ptLock=true;
 | 
						|
		}
 | 
						|
 | 
						|
		it = gFDList.find(tid);
 | 
						|
		if (it==gFDList.end())
 | 
						|
		{
 | 
						|
			ostringstream LogFileName;
 | 
						|
			SPPTLogs_t spof;
 | 
						|
#ifdef _MSC_VER
 | 
						|
			LogFileName << "C:/Calpont/log/trace/pt." << tid;
 | 
						|
#else
 | 
						|
			LogFileName << "/var/log/mariadb/columnstore/trace/pt." << tid;
 | 
						|
#endif
 | 
						|
			spof.reset(new PTLogs_t(gThdCnt, LogFileName.str().c_str()));
 | 
						|
			gThdCnt++;
 | 
						|
			// TODO: add error checking
 | 
						|
			if (spof->logFD.is_open()) {
 | 
						|
				gFDList[tid] = spof;
 | 
						|
				logFD = spof.get();
 | 
						|
			}
 | 
						|
		} else
 | 
						|
			logFD =(*it).second.get();
 | 
						|
 | 
						|
		if (ptLock) {
 | 
						|
			gFDMutex.unlock();
 | 
						|
			ptLock=false;
 | 
						|
		}
 | 
						|
		clock_gettime(CLOCK_MONOTONIC, &tm);
 | 
						|
  	} // if (fTrace)
 | 
						|
 | 
						|
	uint32_t retries = 0;
 | 
						|
restart:
 | 
						|
	try {
 | 
						|
		ret = (*bpp)();
 | 
						|
	}
 | 
						|
	catch (NeedToRestartJob &e) {
 | 
						|
		ostringstream os;
 | 
						|
		// experimentally the race can exist longer than 10s.  "No way" should
 | 
						|
		// it take 10 minutes.  If it does, the user will have to resubmit their
 | 
						|
		// query.
 | 
						|
 | 
						|
		// 9/27/12 - changed the timeout to 2 mins b/c people report the system
 | 
						|
		// is hung if it does nothing for 10 mins.  2 mins should still be more
 | 
						|
		// than enough
 | 
						|
		if (++retries == 120) {
 | 
						|
			os << e.what() << ": Restarted a syscat job " << retries << " times, bailing\n";
 | 
						|
			throw NeedToRestartJob(os.str());
 | 
						|
		}
 | 
						|
		flushSyscatOIDs();
 | 
						|
		bs->rewind();
 | 
						|
		bpp->resetBPP(*bs, writelock, sock);
 | 
						|
		sleep(1);
 | 
						|
		goto restart;
 | 
						|
	}
 | 
						|
 | 
						|
	if (ret)
 | 
						|
		return ret;
 | 
						|
 | 
						|
	if (fTrace)
 | 
						|
		if (logFD && logFD->logFD.is_open()) {
 | 
						|
			clock_gettime(CLOCK_MONOTONIC, &tm2);
 | 
						|
			timespec_sub(tm, tm2, tm3);
 | 
						|
			logFD->logFD
 | 
						|
				<< left << setw(3) << logFD->thdId
 | 
						|
				<< right << fixed << ((double)(tm.tv_sec+(1.e-9*tm.tv_nsec))) << " "
 | 
						|
				<< right << fixed << tm3 << " "
 | 
						|
				<< right << setw(6) << bpp->getSessionID() << " "
 | 
						|
				<< right << setw(4) << bpp->getStepID() << " "
 | 
						|
				<< right << setw(2) << bpp->FilterCount() << " "
 | 
						|
				<< right << setw(2) << bpp->ProjectCount() << " "
 | 
						|
				<< right << setw(9) << bpp->PhysIOCount() << " "
 | 
						|
				<< right << setw(9) << bpp->CachedIOCount() << " "
 | 
						|
				<< right << setw(9) << bpp->BlocksTouchedCount()
 | 
						|
				<< endl;
 | 
						|
		} // if (logFD...
 | 
						|
 | 
						|
	}
 | 
						|
	catch (scalar_exception &se)
 | 
						|
	{
 | 
						|
		if (gotBPP)
 | 
						|
			bpp->busy(false);
 | 
						|
		if (ptLock) {
 | 
						|
			gFDMutex.unlock();
 | 
						|
			ptLock=false;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	catch(exception& ex)
 | 
						|
	{
 | 
						|
		if (gotBPP)
 | 
						|
			bpp->busy(false);
 | 
						|
		if (ptLock) {
 | 
						|
			gFDMutex.unlock();
 | 
						|
			ptLock=false;
 | 
						|
		}
 | 
						|
		catchHandler(ex.what(), uniqueID, stepID);
 | 
						|
		cout << "BPPSeeder step " << stepID << " caught an exception: " <<  ex.what() << endl;
 | 
						|
	}
 | 
						|
	catch(...)
 | 
						|
	{
 | 
						|
		if (gotBPP)
 | 
						|
			bpp->busy(false);
 | 
						|
		if (ptLock) {
 | 
						|
			gFDMutex.unlock();
 | 
						|
			ptLock=false;
 | 
						|
		}
 | 
						|
		string msg("BPPSeeder caught an unknown exception");
 | 
						|
		catchHandler(msg, uniqueID, stepID);
 | 
						|
		cout << msg << endl;
 | 
						|
	}
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
 | 
						|
void BPPSeeder::catchHandler(const string& ex, uint32_t id, uint32_t step)
 | 
						|
{
 | 
						|
	Logger log;
 | 
						|
	log.logMessage(ex);
 | 
						|
	sendErrorMsg(id, logging::bppSeederErr, step);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void BPPSeeder::sendErrorMsg(uint32_t id, uint16_t status, uint32_t step)
 | 
						|
{
 | 
						|
 | 
						|
	ISMPacketHeader ism;
 | 
						|
	PrimitiveHeader ph = {0};
 | 
						|
 | 
						|
	ism.Status =  status;
 | 
						|
	ph.UniqueID = id;
 | 
						|
	ph.StepID = step;
 | 
						|
	ByteStream msg(sizeof(ISMPacketHeader) + sizeof(PrimitiveHeader));
 | 
						|
	msg.append((uint8_t *) &ism, sizeof(ism));
 | 
						|
	msg.append((uint8_t *) &ph, sizeof(ph));
 | 
						|
 | 
						|
	boost::mutex::scoped_lock lk(*writelock);
 | 
						|
	sock->write(msg);
 | 
						|
}
 | 
						|
 | 
						|
bool BPPSeeder::isSysCat()
 | 
						|
{
 | 
						|
	const uint8_t *buf;
 | 
						|
	uint32_t sessionIDOffset = sizeof(ISMPacketHeader);
 | 
						|
	uint32_t sessionID;
 | 
						|
 | 
						|
	buf = bs->buf();
 | 
						|
	sessionID = *((uint32_t *) &buf[sessionIDOffset]);
 | 
						|
	return (sessionID & 0x80000000);
 | 
						|
}
 | 
						|
 | 
						|
uint32_t BPPSeeder::getID()
 | 
						|
{
 | 
						|
	return uniqueID;
 | 
						|
}
 | 
						|
 | 
						|
/* This is part of the syscat-retry hack.  We should get rid of it once we
 | 
						|
 * track down the source of the problem.
 | 
						|
 */
 | 
						|
void BPPSeeder::flushSyscatOIDs()
 | 
						|
{
 | 
						|
	vector<BRM::OID_t> syscatOIDs;
 | 
						|
 | 
						|
	syscatOIDs = execplan::getAllSysCatOIDs();
 | 
						|
 | 
						|
	for (int i = 0; i < fCacheCount; i++) {
 | 
						|
		dbbc::blockCacheClient bc(*BRPp[i]);
 | 
						|
		bc.flushOIDs((const uint32_t *) &syscatOIDs[0], syscatOIDs.size());
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
};
 | 
						|
 |