Example #1
0
void nextBandBenchmark()
{
	ByteStream bs;
	pthread_t threads[columns];
	uint i, rowCount = 1;
	JobStepAssociation inJs;

	for (i = 0; i < columns; ++i) {
		AnyDataListSPtr spdl1(new AnyDataList());

		FIFO<UintRowGroup>* dl1 = new FIFO<UintRowGroup>(1, fifoSize);

		dl1->OID(i);	// lineitem first col object id	
		spdl1->fifoDL(dl1);
		inJs.outAdd(spdl1);

		pthread_create(&threads[i], 0, nextBandBenchProducer, dl1 );
		cout << "started thread " << i << endl;
	}

	DeliveryStep ds(inJs, JobStepAssociation(), 8);
	stringstream ss;

	ss << "nextBandBenchmark with " << columns << " columns\n";

	timer.start(ss.str());
	while (rowCount != 0) {
//		cout << "getting a BS\n";
		rowCount = ds.nextBand(bs);
		bs.restart();
//		cout << "got a BS\n";
	}
	timer.stop(ss.str());
	for (i = 0; i < columns; ++i)
		pthread_join(threads[i], NULL);
}
Example #2
0
DropTableProcessor::DDLResult DropTableProcessor::processPackage(ddlpackage::DropTableStatement& dropTableStmt)
{
	SUMMARY_INFO("DropTableProcessor::processPackage");
	
	DDLResult result;
	result.result = NO_ERROR;   
	std::string err;
	VERBOSE_INFO(dropTableStmt);

	// Commit current transaction.
	// all DDL statements cause an implicit commit
	VERBOSE_INFO("Getting current txnID");
	ByteStream::byte rc = 0;
	BRM::TxnID txnID;
	txnID.id= fTxnid.id;
	txnID.valid= fTxnid.valid;
	int rc1 = 0;
	rc1= fDbrm->isReadWrite();
	if (rc1 != 0 )
	{
		Message::Args args;
		Message message(9);
		args.add("Unable to execute the statement due to DBRM is read only");
		message.format(args);
		result.result = DROP_ERROR;	
		result.message = message;
		fSessionManager.rolledback(txnID);
		return result;
	}
	
	string stmt = dropTableStmt.fSql + "|" + dropTableStmt.fTableName->fSchema +"|";
	SQLLogger logger(stmt, fDDLLoggingId, dropTableStmt.fSessionID, txnID.id);
	
	std::vector <CalpontSystemCatalog::OID> oidList;
	CalpontSystemCatalog::RIDList tableColRidList;
	CalpontSystemCatalog::DictOIDList dictOIDList;
	execplan::CalpontSystemCatalog::ROPair roPair;
	std::string errorMsg;
	ByteStream bytestream;
	uint64_t uniqueId = 0;
	//Bug 5070. Added exception handling
	try {
		uniqueId = fDbrm->getUnique64();
	}
	catch (std::exception& ex)
	{
		Message::Args args;
		Message message(9);
		args.add(ex.what());
		message.format(args);
		result.result = DROP_ERROR;	
		result.message = message;
		fSessionManager.rolledback(txnID);
		return result;
	}
	catch ( ... )
	{
		Message::Args args;
		Message message(9);
		args.add("Unknown error occured while getting unique number.");
		message.format(args);
		result.result = DROP_ERROR;	
		result.message = message;
		fSessionManager.rolledback(txnID);
		return result;
	}
	
	fWEClient->addQueue(uniqueId);
	int pmNum = 1;
	boost::shared_ptr<messageqcpp::ByteStream> bsIn;
	uint64_t tableLockId = 0;
	OamCache* oamcache = OamCache::makeOamCache();
	std::vector<int> moduleIds = oamcache->getModuleIds();
	try 
	{	
		//check table lock
		CalpontSystemCatalog *systemCatalogPtr = CalpontSystemCatalog::makeCalpontSystemCatalog(dropTableStmt.fSessionID);
		systemCatalogPtr->identity(CalpontSystemCatalog::EC);
		systemCatalogPtr->sessionID(dropTableStmt.fSessionID);
		CalpontSystemCatalog::TableName tableName;
		tableName.schema = dropTableStmt.fTableName->fSchema;
		tableName.table = dropTableStmt.fTableName->fName;
		roPair = systemCatalogPtr->tableRID( tableName );

		u_int32_t  processID = ::getpid();
		int32_t   txnid = txnID.id;
		int32_t sessionId = dropTableStmt.fSessionID;
		std::string  processName("DDLProc");
		int i = 0;
			
		std::vector<uint> pms;
		for (unsigned i=0; i < moduleIds.size(); i++)
		{
			pms.push_back((uint)moduleIds[i]);
		}
			
		try {
			tableLockId = fDbrm->getTableLock(pms, roPair.objnum, &processName, &processID, &sessionId, &txnid, BRM::LOADING );
		}
		catch (std::exception&)
		{
			throw std::runtime_error(IDBErrorInfo::instance()->errorMsg(ERR_HARD_FAILURE));
		}
		
		if ( tableLockId  == 0 )
		{
			int waitPeriod = 10;
			int sleepTime = 100; // sleep 100 milliseconds between checks
			int numTries = 10;  // try 10 times per second
			waitPeriod = WriteEngine::Config::getWaitPeriod();
			numTries = 	waitPeriod * 10;
			struct timespec rm_ts;

			rm_ts.tv_sec = sleepTime/1000;
			rm_ts.tv_nsec = sleepTime%1000 *1000000;

			for (; i < numTries; i++)
			{
#ifdef _MSC_VER
				Sleep(rm_ts.tv_sec * 1000);
#else
				struct timespec abs_ts;
				do
				{
					abs_ts.tv_sec = rm_ts.tv_sec;
					abs_ts.tv_nsec = rm_ts.tv_nsec;
				}
				while(nanosleep(&abs_ts,&rm_ts) < 0);
#endif
				try {
					processID = ::getpid();
					txnid = txnID.id;
					sessionId = dropTableStmt.fSessionID;;
					processName = "DDLProc";
					tableLockId = fDbrm->getTableLock(pms, roPair.objnum, &processName, &processID, &sessionId, &txnid, BRM::LOADING );
				}
				catch (std::exception&)
				{
					throw std::runtime_error(IDBErrorInfo::instance()->errorMsg(ERR_HARD_FAILURE));
				}

				if (tableLockId > 0)
					break;
			}
			if (i >= numTries) //error out
			{
				Message::Args args;
				args.add(processName);
				args.add((uint64_t)processID);
				args.add(sessionId);
				throw std::runtime_error(IDBErrorInfo::instance()->errorMsg(ERR_TABLE_LOCKED,args));
			}			
		}
		
		// 1. Get the OIDs for the columns
		// 2. Get the OIDs for the dictionaries
		// 3. Save the OIDs to a log file
		// 4. Remove the Table from SYSTABLE
		// 5. Remove the columns from SYSCOLUMN
		// 6. Commit the changes made to systables
		// 7. Flush PrimProc Cache
		// 8. Update extent map
		// 9. Remove the column and dictionary files
		// 10.Return the OIDs

		CalpontSystemCatalog::TableName userTableName;
		userTableName.schema = dropTableStmt.fTableName->fSchema;
		userTableName.table = dropTableStmt.fTableName->fName;

		tableColRidList = systemCatalogPtr->columnRIDs( userTableName );

		dictOIDList = systemCatalogPtr->dictOIDs( userTableName );
		Oam oam;

		//Save qualified tablename, all column, dictionary OIDs, and transaction ID into a file in ASCII format
		for ( unsigned i=0; i < tableColRidList.size(); i++ )
		{
			if ( tableColRidList[i].objnum > 3000 )
				oidList.push_back( tableColRidList[i].objnum );
		}
		for ( unsigned i=0; i < dictOIDList.size(); i++ )
		{
			if (  dictOIDList[i].dictOID > 3000 )
				oidList.push_back( dictOIDList[i].dictOID );
		}
		
		//get a unique number
		VERBOSE_INFO("Removing the SYSTABLE meta data");
#ifdef IDB_DDL_DEBUG
cout << "Removing the SYSTABLEs meta data" << endl;
#endif
		bytestream << (ByteStream::byte)WE_SVR_DELETE_SYSTABLES;
		bytestream << uniqueId;
		bytestream << (u_int32_t) dropTableStmt.fSessionID;
		bytestream << (u_int32_t)txnID.id;
		bytestream << dropTableStmt.fTableName->fSchema;
		bytestream << dropTableStmt.fTableName->fName;
		
		//Find out where systable is
		BRM::OID_t sysOid = 1001;
		ByteStream::byte rc = 0;
		
		u_int16_t  dbRoot;
		rc = fDbrm->getSysCatDBRoot(sysOid, dbRoot);  
		if (rc != 0)
		{
			result.result =(ResultCode) rc;
			Message::Args args;
			Message message(9);
			args.add("Error while calling getSysCatDBRoot");
			args.add(errorMsg);
			result.message = message;
			//release transaction
			fSessionManager.rolledback(txnID);
			return result;
		}
		
		boost::shared_ptr<std::map<int, int> > dbRootPMMap = oamcache->getDBRootToPMMap();
		pmNum = (*dbRootPMMap)[dbRoot];
		try
		{
			//cout << "deleting systable entries with txnid " << txnID.id << endl;
			fWEClient->write(bytestream, (uint)pmNum);
#ifdef IDB_DDL_DEBUG
cout << "Drop table sending WE_SVR_DELETE_SYSTABLES to pm " << pmNum << endl;
#endif				
			while (1)
			{
				bsIn.reset(new ByteStream());
				fWEClient->read(uniqueId, bsIn);
				if ( bsIn->length() == 0 ) //read error
				{
					rc = NETWORK_ERROR;
					errorMsg = "Lost connection to Write Engine Server while updating SYSTABLES";
					break;
				}			
				else {
					*bsIn >> rc;
					if (rc != 0) {
						*bsIn >> errorMsg;
					}
					break;
				}
			}
		}
		catch (runtime_error& ex) //write error
		{
#ifdef IDB_DDL_DEBUG
cout << "Drop table got exception" << endl;
#endif
			rc = NETWORK_ERROR;
			errorMsg = ex.what();
		}
		catch (...)
		{
			rc = NETWORK_ERROR;
#ifdef IDB_DDL_DEBUG
cout << "Drop table got unknown exception" << endl;
#endif
		}
	
		if (rc != 0)
		{
			Message::Args args;
			Message message(9);
			args.add("Error in dropping table from systables.");
			args.add(errorMsg);
			message.format(args);
			result.result = (ResultCode)rc;
			result.message = message;
			//release table lock and session
			fSessionManager.rolledback(txnID);
			(void)fDbrm->releaseTableLock(tableLockId);
			fWEClient->removeQueue(uniqueId);
			return result;				
		}
		
		rc = commitTransaction(uniqueId, txnID);
		//cout << "commiting transaction " << txnID.id << " and valid is " << txnID.valid << endl;
		if (rc != 0)
			fSessionManager.rolledback(txnID);
		else
			fSessionManager.committed(txnID);
						
		if (rc != 0) 
		{
			Message::Args args;
			Message message(9);
			ostringstream oss;
			oss << " Commit failed with error code " << rc;					
			args.add(oss.str());
			fSessionManager.rolledback(txnID);
			(void)fDbrm->releaseTableLock(tableLockId);
			message.format(args);
			result.result = (ResultCode)rc;
			result.message = message;
			fWEClient->removeQueue(uniqueId);
			return result;
		}
		
		// Log the DDL statement
		logDDL(dropTableStmt.fSessionID, txnID.id, dropTableStmt.fSql, dropTableStmt.fOwner);
	}
	catch (std::exception& ex)
	{
		result.result = DROP_ERROR;
		Message::Args args;
		Message message(9);
		args.add("Drop table failed due to ");
		args.add(ex.what());
		fSessionManager.rolledback(txnID);
		try {
			(void)fDbrm->releaseTableLock(tableLockId);
		}
		catch (std::exception&)
		{
			args.add(IDBErrorInfo::instance()->errorMsg(ERR_HARD_FAILURE));
		}
		message.format( args );
		result.message = message;
		fWEClient->removeQueue(uniqueId);
		return result;
	}
	catch (...)
	{
		result.result = DROP_ERROR;
		errorMsg = "Error in getting information from system catalog or from dbrm.";
		Message::Args args;
		Message message(9);
		args.add("Drop table failed due to ");
		args.add(errorMsg);
		fSessionManager.rolledback(txnID);
		try {
			(void)fDbrm->releaseTableLock(tableLockId);
		}
		catch (std::exception&)
		{
			args.add(IDBErrorInfo::instance()->errorMsg(ERR_HARD_FAILURE));
		}
		message.format( args );
		result.message = message;
		fWEClient->removeQueue(uniqueId);
		return result;
	}
	
	try {
			(void)fDbrm->releaseTableLock(tableLockId);
	}
	catch (std::exception&)
	{
		result.result = DROP_ERROR;
		Message::Args args;
		Message message(9);
		args.add("Drop table failed due to ");
		args.add(IDBErrorInfo::instance()->errorMsg(ERR_HARD_FAILURE));
		fSessionManager.rolledback(txnID);
		message.format( args );
		result.message = message;
		fWEClient->removeQueue(uniqueId);
		return result;
	}		
	
	//Save the oids to a file
	try {
		createWriteDropLogFile( roPair.objnum, uniqueId, oidList );
	}
	catch (std::exception& ex)
	{
		result.result = WARNING;
		Message::Args args;
		Message message(9);
		args.add("Drop table failed due to ");
		args.add(ex.what());
		message.format(args);
		result.message = message;
		fSessionManager.rolledback(txnID);
		fWEClient->removeQueue(uniqueId);
		return result;
	}
    // Bug 4208 Drop the PrimProcFDCache before droping the column files
    // FOr Windows, this ensures (most likely) that the column files have
    // no open handles to hinder the deletion of the files.
	rc = cacheutils::dropPrimProcFdCache();

    //Drop files
	bytestream.restart();
	bytestream << (ByteStream::byte)WE_SVR_WRITE_DROPFILES;
	bytestream << uniqueId;
	bytestream << (uint32_t) oidList.size();
	for (unsigned i=0; i < oidList.size(); i++)
	{
		bytestream << (uint32_t) oidList[i];
	}
#ifdef IDB_DDL_DEBUG
cout << "Drop table removing column files" << endl;
#endif		
	uint msgRecived = 0;
	try {
		fWEClient->write_to_all(bytestream);

		bsIn.reset(new ByteStream());
		ByteStream::byte tmp8;
		while (1)
		{
			if (msgRecived == fWEClient->getPmCount())
				break;
			fWEClient->read(uniqueId, bsIn);
			if ( bsIn->length() == 0 ) //read error
			{
				rc = NETWORK_ERROR;
				fWEClient->removeQueue(uniqueId);
				break;
			}			
			else {
				*bsIn >> tmp8;
				rc = tmp8;
				if (rc != 0) {
					*bsIn >> errorMsg;
					fWEClient->removeQueue(uniqueId);
					break;
				}
			else
				msgRecived++;						
			}
		}
int RedistributeWorkerThread::sendData()
{
	WriteEngine::FileOp fileOp;  // just to get filename, not for file operations
	bool remotePM = (fMyId.second != fPeerId.second);
	uint32_t dbroot = fPlanEntry.source;
	uint32_t partition = fPlanEntry.partition;
	int16_t source = fPlanEntry.source;
	int16_t dest = fPlanEntry.destination;

	IDBDataFile::Types fileType = 
		(IDBPolicy::useHdfs() ? IDBDataFile::HDFS : IDBDataFile::UNBUFFERED);
	IDBFileSystem& fs = IDBFileSystem::getFs( fileType );

	if ((remotePM) && (fileType != IDBDataFile::HDFS))
	{
		if (connectToWes(fPeerId.second) != 0)
		{
			fErrorCode = RED_EC_CONNECT_FAIL;
			ostringstream oss;
			oss << "Failed to connect to PM" << fPeerId.second << " from PM" << fMyId.second;
			fErrorMsg = oss.str();
			logMessage(fErrorMsg, __LINE__);
			return fErrorCode;
		}

		// start to send each segment file
		uint32_t seq = 0;
		ByteStream bs;

		// start conversion with peer, hand shaking.
		RedistributeMsgHeader header(dest, source, seq++, RED_DATA_INIT);
		bs << (ByteStream::byte) WriteEngine::WE_SVR_REDISTRIBUTE;
		bs.append((const ByteStream::byte*) &header, sizeof(header));
		fMsgQueueClient->write(bs);

		SBS sbs = fMsgQueueClient->read();
		if (!checkDataTransferAck(sbs, 0))
			return fErrorCode;

		for (vector<int64_t>::iterator i = fOids.begin(); i != fOids.end(); i++)
		{
			for (set<int16_t>::iterator j = fSegments.begin(); j != fSegments.end(); ++j)
			{
				char fileName[WriteEngine::FILE_NAME_SIZE];
				int rc = fileOp.oid2FileName(*i, fileName, false, dbroot, partition, *j);
				if (rc == WriteEngine::NO_ERROR)
				{
					ostringstream oss;
					oss << "<=redistributing: " << fileName << ", oid=" << *i << ", db="
						<< source << ", part=" << partition << ", seg=" << *j << " to db="
						<< dest;
					logMessage(oss.str(), __LINE__);
				}
				else
				{
					fErrorCode = RED_EC_OID_TO_FILENAME;
					ostringstream oss;
					oss << "Failed to get file name: oid=" << *i << ", dbroot=" << dbroot
						<< ", partition=" << partition << ", segment=" << *j;
					fErrorMsg = oss.str();
					logMessage(fErrorMsg, __LINE__);
					return fErrorCode;
				}

				if (fOldFilePtr != NULL)
					closeFile(fOldFilePtr);

				errno = 0;
				FILE* fOldFilePtr = fopen(fileName, "rb");
				if (fOldFilePtr != NULL)
				{
					ostringstream oss;
					oss << "open " << fileName << ", oid=" << *i << ", dbroot=" << dbroot
						<< ", partition=" << partition << ", segment=" << *j
						<< ". " << fOldFilePtr;
					logMessage(oss.str(), __LINE__);
				}
				else
				{
					int e = errno;
					fErrorCode = RED_EC_OPEN_FILE_FAIL;
					ostringstream oss;
					oss << "Failed to open " << fileName << ", oid=" << *i << ", dbroot=" << dbroot
						<< ", partition=" << partition << ", segment=" << *j
						<< ". " << strerror(e) << " (" << e << ")";
					fErrorMsg = oss.str();
					logMessage(fErrorMsg, __LINE__);
					return fErrorCode;
				}

				// add to set for remove after commit
				addToDirSet(fileName, true);

				char chunk[CHUNK_SIZE];
				errno = 0;
				fseek(fOldFilePtr, 0, SEEK_END);       // go to end of file
				long fileSize = ftell(fOldFilePtr);    // get current file size
				if (fileSize < 0)
				{
					int e = errno;
					ostringstream oss;
					oss << "Fail to tell file size: " << strerror(e) << " (" << e << ")";
					fErrorMsg = oss.str();
					fErrorCode = RED_EC_FSEEK_FAIL;
					logMessage(fErrorMsg, __LINE__);
					return fErrorCode;
				}

				// send start message to have the file of fileSize created at target dbroot.
				bs.restart();
				RedistributeMsgHeader header(dest, source, seq++, RED_DATA_START);
				RedistributeDataControl dataControl(*i, dest, partition, *j, fileSize);
				bs << (ByteStream::byte) WriteEngine::WE_SVR_REDISTRIBUTE;
				bs.append((const ByteStream::byte*) &header, sizeof(header));
				bs.append((const ByteStream::byte*) &dataControl, sizeof(dataControl));
				fMsgQueueClient->write(bs);

				sbs = fMsgQueueClient->read();
				if (!checkDataTransferAck(sbs, fileSize))
					return fErrorCode;

				// now send the file chunk by chunk.
				rewind(fOldFilePtr);
				int64_t bytesLeft = fileSize;
				size_t  bytesSend = CHUNK_SIZE;
				header.messageId = RED_DATA_CONT;
				while (bytesLeft > 0)
				{
					if (fStopAction)
					{
						closeFile(fOldFilePtr);
						fOldFilePtr = NULL;
						return RED_EC_USER_STOP;
					}

					if (bytesLeft < (long) CHUNK_SIZE)
						bytesSend = bytesLeft;

					errno = 0;
					size_t n = fread(chunk, 1, bytesSend, fOldFilePtr);
					if (n != bytesSend)
					{
						int e = errno;
						ostringstream oss;
						oss << "Fail to read: " << strerror(e) << " (" << e << ")";
						fErrorMsg = oss.str();
						fErrorCode = RED_EC_FREAD_FAIL;
						logMessage(fErrorMsg, __LINE__);
						return fErrorCode;
					}

					header.sequenceNum = seq++;
					bs.restart();
					bs << (ByteStream::byte) WriteEngine::WE_SVR_REDISTRIBUTE;
   				 	bs.append((const ByteStream::byte*) &header, sizeof(header));
   				 	bs << (size_t) bytesSend;
					bs.append((const ByteStream::byte*) chunk, bytesSend);
   				 	fMsgQueueClient->write(bs);

					sbs = fMsgQueueClient->read();
					if (!checkDataTransferAck(sbs, bytesSend))
						return fErrorCode;

					bytesLeft -= bytesSend;
				}

				closeFile(fOldFilePtr);
				fOldFilePtr = NULL;

				header.messageId = RED_DATA_FINISH;
				header.sequenceNum = seq++;
				bs.restart();
				bs << (ByteStream::byte) WriteEngine::WE_SVR_REDISTRIBUTE;
  			 	bs.append((const ByteStream::byte*) &header, sizeof(header));
  			 	bs << (uint64_t) fileSize;
  			 	fMsgQueueClient->write(bs);

				sbs = fMsgQueueClient->read();
				if (!checkDataTransferAck(sbs, fileSize))
					return fErrorCode;

			}  // segments
		}  // for oids
	}   // remote peer non-hdfs
	else                                           // local or HDFS file copy
	{
		std::map<int,std::string> rootToPathMap;

		// use cp, in case failed in middle.  May consider to use rename if possible.
		for (vector<int64_t>::iterator i = fOids.begin(); i != fOids.end(); i++)
		{
			for (set<int16_t>::iterator j = fSegments.begin(); j != fSegments.end(); ++j)
			{
				if (fStopAction)
					return RED_EC_USER_STOP;

				if (fileType == IDBDataFile::HDFS) // HDFS file copy
				{
					string sourceName;
					int rc = buildFullHdfsPath(
						rootToPathMap, // map of root to path
                        *i,            // OID
						source,        // dbroot
						partition,     // partition
						*j,            // segment
						sourceName );  // full path name
					if (rc != 0)
					{
						fErrorCode = RED_EC_OID_TO_FILENAME;
						ostringstream oss;
						oss << "Failed to get src file name: oid=" << *i
							<< ", dbroot=" << source
							<< ", partition=" << partition
							<< ", segment=" << *j;
						fErrorMsg = oss.str();
						logMessage(fErrorMsg, __LINE__);
						return fErrorCode;
					}

					string destName;
					rc = buildFullHdfsPath(
						rootToPathMap, // map of root to path
                        *i,            // OID
						dest,          // dbroot
						partition,     // partition
						*j,            // segment
						destName );    // full path name
					if (rc != 0)
					{
						fErrorCode = RED_EC_OID_TO_FILENAME;
						ostringstream oss;
						oss << "Failed to get dest file name: oid=" << *i
							<< ", dbroot=" << dest
							<< ", partition=" << partition
							<< ", segment=" << *j;
						fErrorMsg = oss.str();
						logMessage(fErrorMsg, __LINE__);
						return fErrorCode;
					}

					ostringstream oss;
					oss << "<=redistributing(hdfs): " << sourceName << ", oid="
						<< *i << ", db=" << source << ", part=" << partition
						<< ", seg=" << *j << " to db=" << dest;
					logMessage(oss.str(), __LINE__);

					// add to set for remove after commit/abort
					addToDirSet(sourceName.c_str(), true);
					addToDirSet(destName.c_str(), false);

					int ret = fs.copyFile(sourceName.c_str(), destName.c_str());
					if (ret != 0)
					{
						fErrorCode = RED_EC_COPY_FILE_FAIL;
						ostringstream oss;
						oss << "Failed to copy " << sourceName << " to " <<
							destName << "; error is: " << strerror(errno);
						fErrorMsg = oss.str();
						logMessage(fErrorMsg, __LINE__);
						return fErrorCode;
					}
				}
				else                               // local file copy
				{
					char sourceName[WriteEngine::FILE_NAME_SIZE];
					int rc = fileOp.oid2FileName(*i, sourceName, false, source,
						partition, *j);
					if (rc != WriteEngine::NO_ERROR)
					{
						fErrorCode = RED_EC_OID_TO_FILENAME;
						ostringstream oss;
						oss << "Failed to get file name: oid=" << *i
							<< ", dbroot=" << source
							<< ", partition=" << partition
							<< ", segment=" << *j;
						fErrorMsg = oss.str();
						logMessage(fErrorMsg, __LINE__);
						return fErrorCode;
					}

					char destName[WriteEngine::FILE_NAME_SIZE];
					rc = fileOp.oid2FileName(*i, destName, true,
						dest, partition, *j);
					if (rc != WriteEngine::NO_ERROR)
					{
						fErrorCode = RED_EC_OID_TO_FILENAME;
						ostringstream oss;
						oss << "Failed to get file name: oid=" << *i
							<< ", dbroot=" << dest
							<< ", partition=" << partition
							<< ", segment=" << *j;
						fErrorMsg = oss.str();
						logMessage(fErrorMsg, __LINE__);
						return fErrorCode;
					}

					ostringstream oss;
					oss << "<=redistributing(copy): " << sourceName << ", oid="
						<< *i << ", db=" << source << ", part=" << partition
						<< ", seg=" << *j << " to db=" << dest;
					logMessage(oss.str(), __LINE__);

					// add to set for remove after commit/abort
					addToDirSet(sourceName, true);
					addToDirSet(destName, false);

					// Using boost::copy_file() instead of IDBFileSystem::copy-
					// File() so we can capture/report any boost exception error
					// msg that IDBFileSystem::copyFile() currently swallows.
					try
					{
						filesystem::copy_file(sourceName, destName);
					}
#if BOOST_VERSION >= 105200
					catch(filesystem::filesystem_error& e)
#else
					catch(filesystem::basic_filesystem_error<filesystem::path>& e)
#endif
					{
						fErrorCode = RED_EC_COPY_FILE_FAIL;
						ostringstream oss;
						oss << "Failed to copy " << sourceName << " to " <<
							destName << "; error is: " << e.what();
						fErrorMsg = oss.str();
						logMessage(fErrorMsg, __LINE__);
						return fErrorCode;
					}
				}
			}  // segment
		}  // oid
	}  // !remote

	return 0;
}
Example #4
0
CreateTableProcessor::DDLResult CreateTableProcessor::processPackage(
										ddlpackage::CreateTableStatement& createTableStmt)
{
	SUMMARY_INFO("CreateTableProcessor::processPackage");

	DDLResult result;
	BRM::TxnID txnID;
	txnID.id= fTxnid.id;
	txnID.valid= fTxnid.valid;
	result.result = NO_ERROR;
	int rc1 = 0;
	rc1 = fDbrm->isReadWrite();
	if (rc1 != 0 )
	{
		Message::Args args;
		Message message(9);
		args.add("Unable to execute the statement due to DBRM is read only");
		message.format(args);
		result.result = CREATE_ERROR;	
		result.message = message;
		fSessionManager.rolledback(txnID);
		return result;
	}
	DETAIL_INFO(createTableStmt);
	ddlpackage::TableDef& tableDef = *createTableStmt.fTableDef;
	//If schema = CALPONTSYS, do not create table
	boost::algorithm::to_lower(tableDef.fQualifiedName->fSchema);
	if (tableDef.fQualifiedName->fSchema == CALPONT_SCHEMA)
	{
		//release the transaction
		fSessionManager.rolledback(txnID);
		return result;
	}
	// Commit current transaction.
	// all DDL statements cause an implicut commit
	VERBOSE_INFO("Getting current txnID");

	//Check whether the table is existed already
	boost::shared_ptr<CalpontSystemCatalog> systemCatalogPtr =
		CalpontSystemCatalog::makeCalpontSystemCatalog(createTableStmt.fSessionID);
	execplan::CalpontSystemCatalog::TableName tableName;
	tableName.schema = tableDef.fQualifiedName->fSchema;
	tableName.table = tableDef.fQualifiedName->fName;
	execplan::CalpontSystemCatalog::ROPair roPair;
	roPair.objnum = 0;
	ByteStream::byte rc = 0;
	/** @Bug 217 */
	/** @Bug 225 */
	try
	{
		roPair = systemCatalogPtr->tableRID(tableName);
	}
    catch (IDBExcept &ie) 
    {
        // TODO: What is and is not an error here?
        if (ie.errorCode() == ERR_DATA_OFFLINE)
        {
            //release transaction
            fSessionManager.rolledback(txnID);
            // Return the error for display to user
            Message::Args args;
            Message message(9);
            args.add(ie.what());
            message.format(args);
            result.result = CREATE_ERROR;
            result.message = message;
            return result;
        }
        else if ( ie.errorCode() == ERR_TABLE_NOT_IN_CATALOG)
        {
            roPair.objnum = 0;
        }
		else //error out
		{
			//release transaction
            fSessionManager.rolledback(txnID);
            // Return the error for display to user
            Message::Args args;
            Message message(9);
            args.add(ie.what());
            message.format(args);
            result.result = CREATE_ERROR;
            result.message = message;
            return result;
		}
    }
	catch (std::exception& ex)  //error out
	{
		//release transaction
        fSessionManager.rolledback(txnID);
        // Return the error for display to user
        Message::Args args;
        Message message(9);
        args.add(ex.what());
        message.format(args);
        result.result = CREATE_ERROR;
        result.message = message;
        return result;
	}
	catch (...) //error out
	{
		//release transaction
        fSessionManager.rolledback(txnID);
        // Return the error for display to user
        Message::Args args;
        Message message(9);
        args.add("Unknown exception caught when checking if the table name is already in use.");
        message.format(args);
        result.result = CREATE_ERROR;
        result.message = message;
        return result;
	}

	//This is a current db bug, it should not turn OID is it cannot find
	if (roPair.objnum >= 3000)
	{
#ifdef _MSC_VER
		//FIXME: Why do we need to do this???
		systemCatalogPtr->flushCache();
		try { roPair = systemCatalogPtr->tableRID(tableName); }
		catch (...) { roPair.objnum = 0; }
		if (roPair.objnum < 3000)
			goto keepGoing;
#endif
		Message::Args args;
		Message message(9);
		args.add("Internal create table error for");
		args.add(tableName.toString());
		args.add(": table already exists");
		args.add("(your schema is probably out-of-sync)");
		message.format(args);

		result.result = CREATE_ERROR;
		result.message = message;
		//release the transaction
		fSessionManager.rolledback(txnID);
		return result;
	}
#ifdef _MSC_VER
keepGoing:
#endif
	// Start a new transaction
	VERBOSE_INFO("Starting a new transaction");

	string stmt = createTableStmt.fSql + "|" + tableDef.fQualifiedName->fSchema +"|";
	SQLLogger logger(stmt, fDDLLoggingId, createTableStmt.fSessionID, txnID.id);


	std::string err;
	execplan::ObjectIDManager fObjectIDManager; 
	OamCache * oamcache = OamCache::makeOamCache();
	string errorMsg;
	//get a unique number
	uint64_t uniqueId = 0;
	//Bug 5070. Added exception handling
	try {
		uniqueId = fDbrm->getUnique64();
	}
	catch (std::exception& ex)
	{
		Message::Args args;
		Message message(9);
		args.add(ex.what());
		message.format(args);
		result.result = CREATE_ERROR;	
		result.message = message;
		fSessionManager.rolledback(txnID);
		return result;
	}
	catch ( ... )
	{
		Message::Args args;
		Message message(9);
		args.add("Unknown error occured while getting unique number.");
		message.format(args);
		result.result = CREATE_ERROR;	
		result.message = message;
		fSessionManager.rolledback(txnID);
		return result;
	}
	
	fWEClient->addQueue(uniqueId);
	try
	{
		//Allocate tableoid table identification
		VERBOSE_INFO("Allocating object ID for table");	
		// Allocate a object ID for each column we are about to create
		VERBOSE_INFO("Allocating object IDs for columns");
		uint32_t numColumns = tableDef.fColumns.size();
		uint32_t numDictCols = 0;
		for (unsigned i=0; i < numColumns; i++)
		{
			int dataType;
			dataType = convertDataType(tableDef.fColumns[i]->fType->fType);
			if ( (dataType == CalpontSystemCatalog::CHAR && tableDef.fColumns[i]->fType->fLength > 8) ||
				 (dataType == CalpontSystemCatalog::VARCHAR && tableDef.fColumns[i]->fType->fLength > 7) ||
				 (dataType == CalpontSystemCatalog::VARBINARY && tableDef.fColumns[i]->fType->fLength > 7) )			 
				 numDictCols++;
		}
		fStartingColOID = fObjectIDManager.allocOIDs(numColumns+numDictCols+1); //include column, oids,dictionary oids and tableoid
#ifdef IDB_DDL_DEBUG
cout << "Create table allocOIDs got the stating oid " << fStartingColOID << endl;
#endif		
		if (fStartingColOID < 0)
		{
			result.result = CREATE_ERROR;
			errorMsg = "Error in getting objectid from oidmanager.";
			Message::Args args;
			Message message(9);
			args.add("Create table failed due to ");
			args.add(errorMsg);
			message.format(args);
			result.message = message;
			fSessionManager.rolledback(txnID);
			return result;
		}

		// Write the table metadata to the systemtable
		VERBOSE_INFO("Writing meta data to SYSTABLE");
		ByteStream bytestream;
		bytestream << (ByteStream::byte)WE_SVR_WRITE_SYSTABLE;
		bytestream << uniqueId;
		bytestream << (uint32_t) createTableStmt.fSessionID;
		bytestream << (uint32_t)txnID.id;
		bytestream << (uint32_t)fStartingColOID;
		bytestream << (uint32_t)createTableStmt.fTableWithAutoi;
		uint16_t  dbRoot;
		BRM::OID_t sysOid = 1001;
		//Find out where systable is
		rc = fDbrm->getSysCatDBRoot(sysOid, dbRoot); 
		if (rc != 0)
		{
			result.result =(ResultCode) rc;
			Message::Args args;
			Message message(9);
			args.add("Error while calling getSysCatDBRoot ");
			args.add(errorMsg);
			message.format(args);
			result.message = message;
			//release transaction
			fSessionManager.rolledback(txnID);
			return result;
		}
	
		int pmNum = 1;
		bytestream << (uint32_t)dbRoot; 
		tableDef.serialize(bytestream);
		boost::shared_ptr<messageqcpp::ByteStream> bsIn;
		boost::shared_ptr<std::map<int, int> > dbRootPMMap = oamcache->getDBRootToPMMap();
		pmNum = (*dbRootPMMap)[dbRoot];
		try
		{			
			fWEClient->write(bytestream, (unsigned)pmNum);
#ifdef IDB_DDL_DEBUG
cout << "create table sending We_SVR_WRITE_SYSTABLE to pm " << pmNum << endl;
#endif	
			while (1)
			{
				bsIn.reset(new ByteStream());
				fWEClient->read(uniqueId, bsIn);
				if ( bsIn->length() == 0 ) //read error
				{
					rc = NETWORK_ERROR;
					errorMsg = "Lost connection to Write Engine Server while updating SYSTABLES";
					break;
				}			
				else {
					*bsIn >> rc;
					if (rc != 0) {
                        errorMsg.clear();
						*bsIn >> errorMsg;
#ifdef IDB_DDL_DEBUG
cout << "Create table We_SVR_WRITE_CREATETABLEFILES: " << errorMsg << endl;
#endif
					}
					break;
				}
			}
		}
		catch (runtime_error& ex) //write error
		{
#ifdef IDB_DDL_DEBUG
cout << "create table got exception" << ex.what() << endl;
#endif			
			rc = NETWORK_ERROR;
			errorMsg = ex.what();
		}
		catch (...)
		{
			rc = NETWORK_ERROR;
#ifdef IDB_DDL_DEBUG
cout << "create table got unknown exception" << endl;
#endif
		}
		
		if (rc != 0)
		{
			result.result =(ResultCode) rc;
			Message::Args args;
			Message message(9);
			args.add("Create table failed due to ");
			args.add(errorMsg);
			message.format( args );
			result.message = message;
			if (rc != NETWORK_ERROR)
			{
				rollBackTransaction( uniqueId, txnID, createTableStmt.fSessionID );	//What to do with the error code			
			}
			//release transaction
			fSessionManager.rolledback(txnID);
			return result;
		}
			
		VERBOSE_INFO("Writing meta data to SYSCOLUMN");
		bytestream.restart();
		bytestream << (ByteStream::byte)WE_SVR_WRITE_CREATE_SYSCOLUMN;
		bytestream << uniqueId;
		bytestream << (uint32_t) createTableStmt.fSessionID;
		bytestream << (uint32_t)txnID.id;			
		bytestream << numColumns;
		for (unsigned i = 0; i <numColumns; ++i) {
			bytestream << (uint32_t)(fStartingColOID+i+1);
		}	
		bytestream << numDictCols;
		for (unsigned i = 0; i <numDictCols; ++i) {
			bytestream << (uint32_t)(fStartingColOID+numColumns+i+1);
		}	
		
		uint8_t alterFlag = 0;
		int colPos = 0;
		bytestream << (ByteStream::byte)alterFlag;
		bytestream << (uint32_t)colPos;
				
		sysOid = 1021;
		//Find out where syscolumn is
		rc = fDbrm->getSysCatDBRoot(sysOid, dbRoot); 
		if (rc != 0)
		{
			result.result =(ResultCode) rc;
			Message::Args args;
			Message message(9);
			args.add("Error while calling getSysCatDBRoot ");
			args.add(errorMsg);
			message.format(args);
			result.message = message;
			//release transaction
			fSessionManager.rolledback(txnID);
			return result;
		}

		bytestream << (uint32_t)dbRoot; 
		tableDef.serialize(bytestream);
		pmNum = (*dbRootPMMap)[dbRoot];
		try
		{			
			fWEClient->write(bytestream, (uint32_t)pmNum);
#ifdef IDB_DDL_DEBUG
cout << "create table sending We_SVR_WRITE_SYSTABLE to pm " << pmNum << endl;
#endif	
			while (1)
			{
				bsIn.reset(new ByteStream());
				fWEClient->read(uniqueId, bsIn);
				if ( bsIn->length() == 0 ) //read error
				{
					rc = NETWORK_ERROR;
					errorMsg = "Lost connection to Write Engine Server while updating SYSTABLES";
					break;
				}			
				else {
					*bsIn >> rc;
					if (rc != 0) {
                        errorMsg.clear();
						*bsIn >> errorMsg;
#ifdef IDB_DDL_DEBUG
cout << "Create table We_SVR_WRITE_CREATETABLEFILES: " << errorMsg << endl;
#endif
					}
					break;
				}
			}
		}
		catch (runtime_error& ex) //write error
		{
#ifdef IDB_DDL_DEBUG
cout << "create table got exception" << ex.what() << endl;
#endif			
			rc = NETWORK_ERROR;
			errorMsg = ex.what();
		}
		catch (...)
		{
			rc = NETWORK_ERROR;
#ifdef IDB_DDL_DEBUG
cout << "create table got unknown exception" << endl;
#endif
		}
		
		if (rc != 0)
		{
			result.result =(ResultCode) rc;
			Message::Args args;
			Message message(9);
			args.add("Create table failed due to ");
			args.add(errorMsg);
			message.format( args );
			result.message = message;
			if (rc != NETWORK_ERROR)
			{
				rollBackTransaction( uniqueId, txnID, createTableStmt.fSessionID );	//What to do with the error code			
			}
			//release transaction
			fSessionManager.rolledback(txnID);
			return result;
		}
		
		
		//Get the number of tables in the database, the current table is included.
		int tableCount = systemCatalogPtr->getTableCount();

		//Calculate which dbroot the columns should start
		DBRootConfigList dbRootList = oamcache->getDBRootNums();
		
		uint16_t useDBRootIndex = tableCount % dbRootList.size();
		//Find out the dbroot# corresponding the useDBRootIndex from oam
		uint16_t useDBRoot = dbRootList[useDBRootIndex];
		
		VERBOSE_INFO("Creating column files");
		ColumnDef* colDefPtr;
		ddlpackage::ColumnDefList tableDefCols = tableDef.fColumns;
		ColumnDefList::const_iterator iter = tableDefCols.begin();
		bytestream.restart();
		bytestream << (ByteStream::byte)WE_SVR_WRITE_CREATETABLEFILES;
		bytestream << uniqueId;
		bytestream << (uint32_t)txnID.id;
		bytestream << (numColumns + numDictCols);
		unsigned colNum = 0;
		unsigned dictNum = 0;
		while (iter != tableDefCols.end())
		{
			colDefPtr = *iter;

			CalpontSystemCatalog::ColDataType dataType = convertDataType(colDefPtr->fType->fType);
			if (dataType == CalpontSystemCatalog::DECIMAL ||
                dataType == CalpontSystemCatalog::UDECIMAL)
			{
				if (colDefPtr->fType->fPrecision == -1 || colDefPtr->fType->fPrecision == 0)
				{
					colDefPtr->fType->fLength = 8;
				}
				else if ((colDefPtr->fType->fPrecision > 0) && (colDefPtr->fType->fPrecision < 3))
				{
					colDefPtr->fType->fLength = 1;
				}

				else if (colDefPtr->fType->fPrecision < 5 && (colDefPtr->fType->fPrecision > 2))
				{
					colDefPtr->fType->fLength = 2;
				}
				else if (colDefPtr->fType->fPrecision > 4 && colDefPtr->fType->fPrecision < 10)
				{
					colDefPtr->fType->fLength = 4;
				}
				else if (colDefPtr->fType->fPrecision > 9 && colDefPtr->fType->fPrecision < 19)
				{
					colDefPtr->fType->fLength = 8;
				}	
			}
			bytestream << (fStartingColOID + (colNum++) + 1);
			bytestream << (uint8_t) dataType;
			bytestream << (uint8_t) false;

			bytestream << (uint32_t) colDefPtr->fType->fLength;
			bytestream << (uint16_t) useDBRoot;
			bytestream << (uint32_t) colDefPtr->fType->fCompressiontype;
			if ( (dataType == CalpontSystemCatalog::CHAR && colDefPtr->fType->fLength > 8) ||
				 (dataType == CalpontSystemCatalog::VARCHAR && colDefPtr->fType->fLength > 7) ||
				 (dataType == CalpontSystemCatalog::VARBINARY && colDefPtr->fType->fLength > 7) )
			{
				bytestream << (uint32_t) (fStartingColOID+numColumns+(dictNum++)+1);
				bytestream << (uint8_t) dataType;
				bytestream << (uint8_t) true;
				bytestream << (uint32_t) colDefPtr->fType->fLength;
				bytestream << (uint16_t) useDBRoot;
				bytestream << (uint32_t) colDefPtr->fType->fCompressiontype;
			}
			++iter;
		}
		//@Bug 4176. save oids to a log file for cleanup after fail over.
		std::vector <CalpontSystemCatalog::OID> oidList;
		for (unsigned i = 0; i <numColumns; ++i) 
		{
			oidList.push_back(fStartingColOID+i+1);
		}	
		bytestream << numDictCols;
		for (unsigned i = 0; i <numDictCols; ++i) 
		{
			oidList.push_back(fStartingColOID+numColumns+i+1);
		}	
		
		try {
			createWriteDropLogFile( fStartingColOID, uniqueId, oidList );
		}
		catch (std::exception& ex)
		{
			result.result =(ResultCode) rc;
			Message::Args args;
			Message message(9);
			args.add("Create table failed due to ");
			args.add(ex.what());
			message.format( args );
			result.message = message;
			if (rc != NETWORK_ERROR)
			{
				rollBackTransaction( uniqueId, txnID, createTableStmt.fSessionID );	//What to do with the error code			
			}
			//release transaction
			fSessionManager.rolledback(txnID);
			return result;
		}
		
		pmNum = (*dbRootPMMap)[useDBRoot];
		try
		{
			fWEClient->write(bytestream, pmNum);
			while (1)
			{
				bsIn.reset(new ByteStream());
				fWEClient->read(uniqueId, bsIn);
				if ( bsIn->length() == 0 ) //read error
				{
					rc = NETWORK_ERROR;
					errorMsg = "Lost connection to Write Engine Server while updating SYSTABLES";
					break;
				}			
				else {
					*bsIn >> rc;
					if (rc != 0) {
                        errorMsg.clear();
						*bsIn >> errorMsg;
#ifdef IDB_DDL_DEBUG
cout << "Create table We_SVR_WRITE_CREATETABLEFILES: " << errorMsg << endl;
#endif
					}
					break;
				}
			}
			
			if (rc != 0) {
				//drop the newly created files
				bytestream.restart();
				bytestream << (ByteStream::byte) WE_SVR_WRITE_DROPFILES;
				bytestream << uniqueId;
				bytestream << (uint32_t)(numColumns+numDictCols);
				for (unsigned i = 0; i < (numColumns+numDictCols); i++)
				{
					bytestream << (uint32_t)(fStartingColOID + i + 1);
				}
				fWEClient->write(bytestream, pmNum);
				while (1)
				{
					bsIn.reset(new ByteStream());
					fWEClient->read(uniqueId, bsIn);
					if ( bsIn->length() == 0 ) //read error
					{	
						break;
					}			
					else {
						break;
					}
				}
				//@Bug 5464. Delete from extent map.
				fDbrm->deleteOIDs(oidList);
				
			}		
		}
		catch (runtime_error&)
		{
			errorMsg = "Lost connection to Write Engine Server";
		}
		
		if (rc != 0)
		{
			rollBackTransaction( uniqueId, txnID, createTableStmt.fSessionID); //What to do with the error code
			fSessionManager.rolledback(txnID);
		}
		else
		{
			commitTransaction(uniqueId, txnID);
			fSessionManager.committed(txnID);
			fWEClient->removeQueue(uniqueId);	
			deleteLogFile(DROPTABLE_LOG, fStartingColOID, uniqueId);
		}
		
		// Log the DDL statement.
		logDDL(createTableStmt.fSessionID, txnID.id, createTableStmt.fSql, createTableStmt.fOwner);
	}