예제 #1
0
void DMLPackageProcessor::getColumnsForTable(uint32_t sessionID, std::string schema,
	std::string table, dmlpackage::ColumnList& colList)
{

	CalpontSystemCatalog::TableName tableName;
	tableName.schema = schema;
	tableName.table = table;

	CalpontSystemCatalog* systemCatalogPtr = CalpontSystemCatalog::makeCalpontSystemCatalog( sessionID );
	CalpontSystemCatalog::RIDList ridList = systemCatalogPtr->columnRIDs(tableName, true);

	CalpontSystemCatalog::RIDList::const_iterator rid_iterator = ridList.begin();
	while (rid_iterator != ridList.end())
	{
		CalpontSystemCatalog::ROPair roPair = *rid_iterator;
		DMLColumn* columnPtr = new DMLColumn();
		CalpontSystemCatalog::TableColName tblColName = systemCatalogPtr->colName( roPair.objnum );
		columnPtr->set_Name(tblColName.column);

		colList.push_back(columnPtr);

		++rid_iterator;
	}

}
예제 #2
0
  DMLPackageProcessor::DMLResult
  DeletePackageProcessor::processPackage(dmlpackage::CalpontDMLPackage& cpackage)
  {
    SUMMARY_INFO("DeletePackageProcessor::processPackage");

    DMLResult result;
    result.result = NO_ERROR;
    BRM::TxnID txnid;
	// set-up the transaction
    txnid.id  = cpackage.get_TxnID();		
	txnid.valid = true;
    fSessionID = cpackage.get_SessionID();
	//StopWatch timer;
    VERBOSE_INFO("DeletePackageProcessor is processing CalpontDMLPackage ...");
	TablelockData * tablelockData = TablelockData::makeTablelockData(fSessionID);
	uint64_t uniqueId = 0;
	//Bug 5070. Added exception handling
	try {
		uniqueId = fDbrm->getUnique64();
	}
	catch (std::exception& ex)
	{
		logging::Message::Args args;
		logging::Message message(9);
		args.add(ex.what());
		message.format(args);
		result.result = DELETE_ERROR;	
		result.message = message;
		fSessionManager.rolledback(txnid);
		return result;
	}
	catch ( ... )
	{
		logging::Message::Args args;
		logging::Message message(9);
		args.add("Unknown error occured while getting unique number.");
		message.format(args);
		result.result = DELETE_ERROR;	
		result.message = message;
		fSessionManager.rolledback(txnid);
		return result;
	}
	
	uint64_t tableLockId = 0;
	// get the table object from the package
    DMLTable* tablePtr =  cpackage.get_Table();
	std::string schemaName = tablePtr->get_SchemaName();
    std::string tableName = tablePtr->get_TableName();
	boost::shared_ptr<CalpontSystemCatalog> csc = CalpontSystemCatalog::makeCalpontSystemCatalog( fSessionID );
	CalpontSystemCatalog::TableName aTableName;
	aTableName.table = tableName;
	aTableName.schema = schemaName;
	fWEClient->addQueue(uniqueId);
	execplan::CalpontSystemCatalog::ROPair roPair;
    try
    {
	  string stmt = cpackage.get_SQLStatement() + "|" + schemaName + "|";
      SQLLogger sqlLogger(stmt, DMLLoggingId, fSessionID, txnid.id);

      if ( 0 != tablePtr )
      {
        
		roPair = csc->tableRID(aTableName);

		tableLockId = tablelockData->getTablelockId(roPair.objnum); //check whether this table is locked already for this session
		if (tableLockId == 0)
		{
			//cout << "tablelock is not found in cache " << endl;
			uint32_t  processID = ::getpid();
			int32_t   txnId = txnid.id;
			std::string  processName("DMLProc");
			int32_t sessionId = fSessionID;
			int i = 0;
			OamCache * oamcache = OamCache::makeOamCache();
			std::vector<int> pmList = oamcache->getModuleIds();
			std::vector<uint32_t> pms;
			for (unsigned i=0; i < pmList.size(); i++)
			{
				pms.push_back((uint32_t)pmList[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 = 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 = fSessionID;
						processName = "DMLProc";
						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
				{
					result.result = DELETE_ERROR;
					logging::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));
				}
			}
		}
		
		//cout << " tablelock is obtained with id " << tableLockId << endl;
		tablelockData->setTablelock(roPair.objnum, tableLockId);	
		//@Bug 4491 start AI sequence for autoincrement column
		const CalpontSystemCatalog::RIDList ridList = csc->columnRIDs(aTableName);
		CalpontSystemCatalog::RIDList::const_iterator rid_iterator = ridList.begin();
		CalpontSystemCatalog::ColType colType;
		while (rid_iterator != ridList.end())
		{
			// If user hit ctrl+c in the mysql console, fRollbackPending will be true.
			if (fRollbackPending)
			{
				result.result = JOB_CANCELED;
				break;
			}
			CalpontSystemCatalog::ROPair roPair = *rid_iterator;
			colType = csc->colType(roPair.objnum);
			if (colType.autoincrement)
			{
                try
                {
    				uint64_t nextVal = csc->nextAutoIncrValue(aTableName);
    				fDbrm->startAISequence(roPair.objnum, nextVal, colType.colWidth, colType.colDataType);
    				break; //Only one autoincrement column per table
                }
                catch (std::exception& ex)
                {
                    result.result = DELETE_ERROR;
                    throw std::runtime_error(ex.what());
                }
			}
			++rid_iterator;
		}
		
		uint64_t  rowsProcessed = 0;
		
		rowsProcessed = fixUpRows(cpackage, result, uniqueId, roPair.objnum);
		//@Bug 4994 Cancelled job is not error
		if (result.result == JOB_CANCELED)
			throw std::runtime_error("Query execution was interrupted");
					
		if ((result.result != 0) && (result.result != DMLPackageProcessor::IDBRANGE_WARNING))
			throw std::runtime_error(result.message.msg());
					
		result.rowCount = rowsProcessed;

		// Log the DML statement.
		logging::logDML(cpackage.get_SessionID(), txnid.id, cpackage.get_SQLStatement(), cpackage.get_SchemaName());
	  }
    }
    catch (exception& ex)
    {
      cerr << "DeletePackageProcessor::processPackage: " << ex.what() << endl;
      
	  //@Bug 4994 Cancelled job is not error
      if (result.result == 0)
      {
		  result.result = DELETE_ERROR;
      }
      result.message = Message(ex.what());
    }
    catch (...)
    {
      cerr << "DeletePackageProcessor::processPackage: caught unknown exception!" << endl;
      logging::Message::Args args;
      logging::Message message(7);
      args.add( "Delete Failed: ");
      args.add( "encountered unknown exception" );
      args.add(result.message.msg());
      args.add("");
      message.format( args );

      result.result = DELETE_ERROR;
      result.message = message;
    }
	//timer.finish();
	//@Bug 1886,2870 Flush VM cache only once per statement. 
	std::map<uint32_t,uint32_t> oids;
	int rc = 0;
    if (result.result == NO_ERROR)
	{
		rc = flushDataFiles( result.result, oids, uniqueId, txnid, roPair.objnum);
		if (rc != NO_ERROR)
		{
			cerr << "UpdatePackageProcessor::processPackage: write data to disk failed" << endl;
			if (!fRollbackPending)
			{	
				logging::Message::Args args;
				logging::Message message(7);
				args.add("Delete Failed: ");
				args.add("error when writing data to disk");
				args.add("");
				args.add("");
				message.format(args);

				result.result = UPDATE_ERROR;
				result.message = message;
			}
			result.rowCount = 0;
			rc = endTransaction(uniqueId, txnid, false);
			if ( (rc != NO_ERROR) && (!fRollbackPending))
			{
				logging::Message::Args args;
				logging::Message message(7);
				args.add("Delete Failed: ");
				args.add("error when cleaning up data files");
				args.add("");
				args.add("");
				message.format(args);

				result.result = UPDATE_ERROR;
				result.message = message;
				result.rowCount = 0;
			
			}
		}
		else
		{
			if (fRollbackPending)
				rc = endTransaction(uniqueId, txnid, false);
			else
				rc = endTransaction(uniqueId, txnid, true);
		}
	}
	else
	{
		rc = flushDataFiles( result.result, oids, uniqueId, txnid, roPair.objnum);
		result.rowCount = 0;
		rc = endTransaction(uniqueId, txnid, false);
	}
	
	
	if (fRollbackPending)
	{
		result.result = JOB_CANCELED;
		logging::Message::Args args1;
		args1.add("Query execution was interrupted");
		result.message.format(args1);
	}
	
	fWEClient->removeQueue(uniqueId);

    VERBOSE_INFO("Finished Processing Delete DML Package");
    return result;
  }
int RedistributeWorkerThread::buildEntryList()
{
	int ret = 0;

	try
	{
		// get all column oids
		boost::shared_ptr<CalpontSystemCatalog> csc = CalpontSystemCatalog::makeCalpontSystemCatalog(0);
		const CalpontSystemCatalog::TableName table = csc->tableName(fPlanEntry.table);
		CalpontSystemCatalog::RIDList cols = csc->columnRIDs(table, true);
		for (CalpontSystemCatalog::RIDList::iterator i = cols.begin(); i != cols.end(); i++)
			fOids.push_back(i->objnum);

		CalpontSystemCatalog::DictOIDList dicts = csc->dictOIDs(table);
		for (CalpontSystemCatalog::DictOIDList::iterator i = dicts.begin(); i != dicts.end(); i++)
			fOids.push_back(i->dictOID);

		bool firstOid = true;  // for adding segments, all columns have the same lay out.
		uint16_t source = fPlanEntry.source;
		uint16_t target = fPlanEntry.destination;
		uint16_t partition = fPlanEntry.partition;
		uint32_t minWidth = 8;  // column width greater than 8 will be dictionary.
		for (vector<int64_t>::iterator i = fOids.begin(); i != fOids.end(); i++)
		{
			vector<EMEntry> entries;
			int rc = fDbrm->getExtents(*i, entries, false, false, true);
			if (rc != 0 || entries.size() == 0)
			{
				ostringstream oss;
				oss << "Error in DBRM getExtents; oid:" << *i << "; returnCode: " << rc;
				throw runtime_error(oss.str());
			}

			// same oid has the same column width
			uint32_t colWid = entries.front().colWid;
			vector<EMEntry>::iterator targetHwmEntry = entries.end();  // for HWM_0 workaround
			if (colWid > 0 && colWid < minWidth)
				minWidth = colWid;

			for (vector<EMEntry>::iterator j = entries.begin(); j != entries.end(); j++)
			{
				if (j->dbRoot == source && j->partitionNum == partition)
				{
					fUpdateRtEntries.push_back(BulkUpdateDBRootArg(j->range.start, target));

					if (firstOid)
						fSegments.insert(j->segmentNum);
				}
				else if (j->dbRoot == target && j->partitionNum == partition)
				{
					// the partition already exists on the target dbroot
					fErrorCode = RED_EC_PART_EXIST_ON_TARGET;
					ostringstream oss;
					oss << "oid:" << *i << ", partition:" << partition << " exists, source:" 
						<< source << ", destination:" << target;
					fErrorMsg = oss.str();
					logMessage(fErrorMsg, __LINE__);
					return fErrorCode;
				}

				// workaround for HWM_0 of highest extents of the oid on target dbroot.
				if (j->dbRoot == target)
				{
					if (targetHwmEntry == entries.end())
					{
						targetHwmEntry = j;
					}
					else
					{
						if (j->partitionNum > targetHwmEntry->partitionNum)
						{
							targetHwmEntry = j;
						}
						else if (j->partitionNum == targetHwmEntry->partitionNum &&
								 j->blockOffset   > targetHwmEntry->blockOffset)
						{
							targetHwmEntry = j;
						}
						else if (j->partitionNum == targetHwmEntry->partitionNum &&
								 j->blockOffset  == targetHwmEntry->blockOffset &&
								 j->segmentNum    > targetHwmEntry->segmentNum)
						{
							targetHwmEntry = j;
						}
					}
				}
			} // for em entries

			// HWM_0 workaround
			// HWM 0 has two possibilities:
			//     1. segment file has one extent, and the first block is not full yet.
			//     2. segment file has more than one extents, the HWM of the extents other than
			//        the last extent is set to 0, that is only last extent has none-zero HWM.
			// In tuple-bps::makeJob, there is a check to handle last extent has 0 hwm:
			//  (scannedExtents[i].HWM == 0 && (int) i < lastExtent[scannedExtents[i].dbRoot-1])
			//          lbidsToScan = scannedExtents[i].range.size * 1024;
			// Based on this check, the number of block to scan is caculated.
			// After redistributing the partitions, the original case 1 extent on destination
			// may not be the highest extent in the dbroot, and result in a full extent scan.
			// This scan will fail because there is no enough blocks if this is an abbreviated
			// extent or not enough chunks if the column is compressed.
			// The workaround is to bump up the HWM to 1 if moved in partitions are greater.
			if (targetHwmEntry != entries.end() &&                // exclude no extent case
				targetHwmEntry->colWid > 0 &&                      // exclude dictionary
				targetHwmEntry->HWM == 0 &&
				targetHwmEntry->partitionNum < partition)
			{
				BulkSetHWMArg arg;
				arg.oid = *i;
				arg.partNum = targetHwmEntry->partitionNum;
				arg.segNum = targetHwmEntry->segmentNum;
				arg.hwm = targetHwmEntry->colWid;  // will correct later based on minWidth

				fUpdateHwmEntries.push_back(arg);
			}
		} // for oids


		// HWM_0 workaround
		// Caculate the min(column width), the HWM(bump up to) for each column.
		if (fUpdateHwmEntries.size() > 0)
		{
			// update the HWM based in column width, not include dictionary extents
			for (vector<BRM::BulkSetHWMArg>::iterator j = fUpdateHwmEntries.begin();
					j != fUpdateHwmEntries.end(); j++)
			{
				if (j->hwm <= 8)
					j->hwm /= minWidth;
				else
					j->hwm = 1;  // not needed, but in case
			}
		}
	}
	catch (const std::exception& ex)
	{
		fErrorCode = RED_EC_EXTENT_ERROR;
		fErrorMsg = ex.what();
		logMessage(fErrorMsg, __LINE__);
		ret = fErrorCode;
	}
	catch (...)
	{
		fErrorCode = RED_EC_EXTENT_ERROR;
		fErrorMsg = "get extent error.";
		logMessage(fErrorMsg, __LINE__);
		ret = fErrorCode;
	}

	return ret;
}
예제 #4
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++;						
			}
		}
예제 #5
0
	DropPartitionProcessor::DDLResult DropPartitionProcessor::processPackage(ddlpackage::DropPartitionStatement& dropPartitionStmt)
	{
		SUMMARY_INFO("DropPartitionProcessor::processPackage");

		DDLResult result;
		result.result = NO_ERROR;   
		std::string err;
		VERBOSE_INFO(dropPartitionStmt);

		// Commit current transaction.
		// all DDL statements cause an implicit commit
		VERBOSE_INFO("Getting current txnID");
		
		int rc = 0;
		rc = fDbrm->isReadWrite();
		BRM::TxnID txnID;
		txnID.id= fTxnid.id;
		txnID.valid= fTxnid.valid;
		if (rc != 0 )
		{
			logging::Message::Args args;
			logging::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;
		}

	
		std::vector <CalpontSystemCatalog::OID> oidList;
		CalpontSystemCatalog::RIDList tableColRidList;
		CalpontSystemCatalog::DictOIDList dictOIDList;
		execplan::CalpontSystemCatalog::ROPair roPair;
		uint32_t processID = 0;
		u_int64_t uniqueID = 0;
		uint32_t sessionID = dropPartitionStmt.fSessionID;
		std::string  processName("DDLProc");
		u_int64_t uniqueId = 0;
		
		//Bug 5070. Added exception handling
		try {
			uniqueId = fDbrm->getUnique64();
		}
		catch (std::exception& ex)
		{
			logging::Message::Args args;
			logging::Message message(9);
			args.add(ex.what());
			message.format(args);
			result.result = ALTER_ERROR;	
			result.message = message;
			fSessionManager.rolledback(txnID);
			return result;
		}
		catch ( ... )
		{
			logging::Message::Args args;
			logging::Message message(9);
			args.add("Unknown error occured while getting unique number.");
			message.format(args);
			result.result = ALTER_ERROR;	
			result.message = message;
			fSessionManager.rolledback(txnID);
			return result;
		}
		
		string stmt = dropPartitionStmt.fSql + "|" + dropPartitionStmt.fTableName->fSchema +"|";
		SQLLogger logger(stmt, fDDLLoggingId, sessionID, txnID.id);

		try 
		{
			//check table lock
			CalpontSystemCatalog *systemCatalogPtr = CalpontSystemCatalog::makeCalpontSystemCatalog(dropPartitionStmt.fSessionID);
			systemCatalogPtr->identity(CalpontSystemCatalog::EC);
			systemCatalogPtr->sessionID(dropPartitionStmt.fSessionID);
			CalpontSystemCatalog::TableName tableName;
			tableName.schema = dropPartitionStmt.fTableName->fSchema;
			tableName.table = dropPartitionStmt.fTableName->fName;
			roPair = systemCatalogPtr->tableRID( tableName );
			//@Bug 3054 check for system catalog
			if ( roPair.objnum < 3000 )
			{
				throw std::runtime_error("Drop partition cannot be operated on Calpont system catalog.");
			}
			int i = 0;
			processID = ::getpid();
			oam::OamCache * oamcache = OamCache::makeOamCache();
			std::vector<int> pmList = oamcache->getModuleIds();
			std::vector<uint> pms;
			for (unsigned i=0; i < pmList.size(); i++)
			{
				pms.push_back((uint)pmList[i]);
			}
				
			try {
				uniqueID = fDbrm->getTableLock(pms, roPair.objnum, &processName, &processID, (int32_t*)&sessionID, (int32_t*)&txnID.id, BRM::LOADING );
			}
			catch (std::exception&)
			{
				result.result = DROP_ERROR;
				result.message = IDBErrorInfo::instance()->errorMsg(ERR_HARD_FAILURE);
				// no need to release lock. dbrm un-hold the lock
				fSessionManager.rolledback(txnID);
				return result;
			}
			
			if ( uniqueID  == 0 )
			{
				int waitPeriod = 10;
				int sleepTime = 100; // sleep 100 milliseconds between checks
				int numTries = 10;  // try 10 times per second
				waitPeriod = 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
					// reset
					sessionID = dropPartitionStmt.fSessionID;
					txnID.id= fTxnid.id;
					txnID.valid= fTxnid.valid;
					processID = ::getpid();
					processName = "DDLProc";
					try 
					{
						uniqueID = fDbrm->getTableLock(pms, roPair.objnum, &processName, &processID, (int32_t*)&sessionID, (int32_t*)&txnID.id, BRM::LOADING );
					}
					catch (std::exception&)
					{
						result.result = DROP_ERROR;
						result.message = IDBErrorInfo::instance()->errorMsg(ERR_HARD_FAILURE);
						fSessionManager.rolledback(txnID);
						return result;
					}

					if (uniqueID > 0)
						break;
				}

				if (i >= numTries) //error out
				{
					result.result = DROP_ERROR;
					logging::Message::Args args;
					args.add(processName);
					args.add((uint64_t)processID);
					args.add((uint64_t)sessionID);
					result.message = Message(IDBErrorInfo::instance()->errorMsg(ERR_TABLE_LOCKED,args));
					fSessionManager.rolledback(txnID);
					return result;
				}
			}

			// 1. Get the OIDs for the columns
			// 2. Get the OIDs for the dictionaries
			// 3. Save the OIDs to a log file
			// 4. Disable the extents from extentmap for the partition     	
			// 5. Remove the column and dictionary  files for the partition
			// 6. Flush PrimProc Cache 
			// 7. Remove the extents from extentmap for the partition

			CalpontSystemCatalog::TableName userTableName;
			userTableName.schema = dropPartitionStmt.fTableName->fSchema;
			userTableName.table = dropPartitionStmt.fTableName->fName;
		
			tableColRidList = systemCatalogPtr->columnRIDs( userTableName );
		
			dictOIDList = systemCatalogPtr->dictOIDs( userTableName );

			//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 );
			}
		
			//Mark the partition disabled from extent map
			string emsg;
			rc = fDbrm->markPartitionForDeletion( oidList, dropPartitionStmt.fPartitions, emsg);
			if (rc != 0 && rc !=BRM::ERR_PARTITION_DISABLED &&
				  rc != BRM::ERR_INVALID_OP_LAST_PARTITION &&
				  rc != BRM::ERR_NOT_EXIST_PARTITION)
			{
				throw std::runtime_error(emsg);
			}
			
			set<BRM::LogicalPartition> markedPartitions;
			set<BRM::LogicalPartition> outOfServicePartitions;
			
			// only log partitions that are successfully marked disabled.
			rc = fDbrm->getOutOfServicePartitions(oidList[0], outOfServicePartitions);
			
			if (rc != 0)
			{
				string errorMsg;
				BRM::errString(rc, errorMsg);
				ostringstream oss;
				oss << "getOutOfServicePartitions failed  due to " << errorMsg;
				     throw std::runtime_error(oss.str());
			}

			set<BRM::LogicalPartition>::iterator it;
			for (it = dropPartitionStmt.fPartitions.begin(); it != dropPartitionStmt.fPartitions.end(); ++it)
			{
				if (outOfServicePartitions.find(*it) != outOfServicePartitions.end())
					markedPartitions.insert(*it);
			}
			
			//Save the oids to a file
			createWritePartitionLogFile( roPair.objnum, markedPartitions, oidList, uniqueId);

			VERBOSE_INFO("Removing files");
			removePartitionFiles( oidList, markedPartitions, uniqueId );
			//Flush PrimProc cache for those lbids
			rc = cacheutils::flushPartition( oidList, markedPartitions );
			
			//Remove the partition from extent map
			emsg.clear();
			rc = fDbrm->deletePartition( oidList, dropPartitionStmt.fPartitions, emsg);
			if ( rc != 0 )
				throw std::runtime_error(emsg);
		}
		catch (exception& ex)
		{
			cerr << "DropPartitionProcessor::processPackage: " << ex.what() << endl;

			logging::Message::Args args;
			logging::Message message(ex.what());

			if (rc == BRM::ERR_TABLE_NOT_LOCKED)
				result.result = USER_ERROR;
			else if (rc == BRM::ERR_NOT_EXIST_PARTITION || rc == BRM::ERR_INVALID_OP_LAST_PARTITION) 
				result.result = PARTITION_WARNING;
			else if (rc == BRM::ERR_NO_PARTITION_PERFORMED)
				result.result = WARN_NO_PARTITION;
			else
				result.result = DROP_ERROR;
			result.message = message;
			try {
				fDbrm->releaseTableLock(uniqueID);
			} catch (std::exception&)
			{
				result.result = DROP_ERROR;
				result.message = IDBErrorInfo::instance()->errorMsg(ERR_HARD_FAILURE);
			}
			fSessionManager.rolledback(txnID);
			return result;
		}
		catch (...)
		{
			cerr << "DropPartitionProcessor::processPackage: caught unknown exception!" << endl;

			logging::Message::Args args;
			logging::Message message(1);
			args.add("Drop partition failed: ");
			args.add( "encountered unkown exception" );
			args.add("");
			args.add("");
		 	message.format( args );
		
			result.result = DROP_ERROR;
			result.message = message;
			try {
				fDbrm->releaseTableLock(uniqueID);
			} catch (std::exception&)
			{
				result.result = DROP_ERROR;
				result.message = IDBErrorInfo::instance()->errorMsg(ERR_HARD_FAILURE);
			}
			fSessionManager.rolledback(txnID);
			return result;
		}
		// Log the DDL statement
		logging::logDDL(dropPartitionStmt.fSessionID, txnID.id, dropPartitionStmt.fSql, dropPartitionStmt.fOwner);
		//Remove the log file
		//release the transaction
		try {
			fDbrm->releaseTableLock(uniqueID);
			deleteLogFile(DROPPART_LOG, roPair.objnum, uniqueId);
		} catch (std::exception&)
		{
			result.result = DROP_ERROR;
			result.message = IDBErrorInfo::instance()->errorMsg(ERR_HARD_FAILURE);
			fSessionManager.rolledback(txnID);
			return result;
		}
		fSessionManager.committed(txnID);
		return result;
	}