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; } }
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; }
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++; } }
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; }