int mqi_rollback_transaction(mqi_handle_t h) { uint32_t depth = TX_DEPTH(h); uint32_t useid = TX_USEID(h); mqi_transaction_t *tx; mqi_db_t *db; mqi_db_functbl_t *ftb; int err; int i; MDB_CHECKARG(h != MQI_HANDLE_INVALID && depth < MQI_TXDEPTH_MAX, -1); MDB_PREREQUISITE(dbs && ndb > 0, -1); MDB_ASSERT(txdepth > 0 && depth == (uint32_t)txdepth - 1, EBADSLT, -1); tx = txstack + depth; MDB_ASSERT(tx->useid == useid, EBADSLT, -1); for (i = 0, err = 0; i < ndb; i++) { db = dbs + i; ftb = db->functbl; if (ftb->rollback_transaction(tx->txid[i]) < 0) err = -1; } txdepth--; return err; }
// creating/waiting status edu can be deactivated (pooled) // deactivateEDU supposed only happened to AGENT EDUs // any EDUs other than AGENT will be destroyed and MDB_SYS will be returned int pmdEDUMgr::_deactivateEDU ( EDUID eduID ) { int rc = MDB_OK ; unsigned int eduStatus = PMD_EDU_CREATING ; pmdEDUCB* eduCB = NULL ; std::map<EDUID, pmdEDUCB*>::iterator it ; // cross queue operation, need X lock _mutex.get() ; if ( _runQueue.end () == ( it = _runQueue.find ( eduID )) ) { // if it's not in run queue, then is it in idle queue? // if it's already idle, we don't need to do anything if ( _idleQueue.end() != _idleQueue.find ( eduID ) ) { goto done ; } // we can't find EDU in run queue rc = MDB_SYS ; goto error ; } eduCB = ( *it ).second ; eduStatus = eduCB->getStatus () ; // if it's already idle, let's get out of here if ( PMD_IS_EDU_IDLE ( eduStatus ) ) goto done ; if ( !PMD_IS_EDU_WAITING ( eduStatus ) && !PMD_IS_EDU_CREATING ( eduStatus ) ) { rc = MDB_EDU_INVAL_STATUS ; goto error ; } // only Agent can be deactivated (pooled), other system // EDUs can only be destroyed MDB_ASSERT ( isPoolable ( eduCB->getType() ), "Only agent can be pooled" ) _runQueue.erase ( eduID ) ; eduCB->setStatus ( PMD_EDU_IDLE ) ; _idleQueue [ eduID ] = eduCB ; done : _mutex.release () ; return rc ; error : goto done ; }
mqi_handle_t mqi_begin_transaction(void) { mqi_transaction_t *tx; mqi_db_t *db; mqi_db_functbl_t *ftb; uint32_t depth; int i; MDB_PREREQUISITE(dbs && ndb > 0 && transact_handle, MQI_HANDLE_INVALID); MDB_ASSERT(txdepth < MQI_TXDEPTH_MAX - 1, EOVERFLOW, MQI_HANDLE_INVALID); depth = txdepth++; tx = txstack + depth; TX_USEID_INCREMENT(tx->useid); for (i = 0; i < ndb; i++) { db = dbs + i; ftb = db->functbl; tx->txid[i] = ftb->begin_transaction(); } return TX_HANDLE(tx->useid, depth); }
mqi_handle_t mqi_create_table(char *name, uint32_t flags, char **index_columns, mqi_column_def_t *cdefs) { mqi_db_t *db; mqi_db_functbl_t *ftb; mqi_table_t *tbl = NULL; mqi_handle_t h = MQI_HANDLE_INVALID; char *namedup = NULL; int i; MDB_CHECKARG(name && cdefs, MQI_HANDLE_INVALID); MDB_PREREQUISITE(dbs && ndb > 0, MQI_HANDLE_INVALID); for (i = 0, ftb = NULL; i < ndb; i++) { db = dbs + i; if ((DB_TYPE(db) & flags) != 0) { ftb = db->functbl; break; } } MDB_ASSERT(ftb, ENOENT, MQI_HANDLE_INVALID); if(!(tbl = calloc(1, sizeof(mqi_table_t)))) return MQI_HANDLE_INVALID; tbl->db = db; tbl->handle = NULL; if (!(namedup = strdup(name))) goto cleanup; if (!(tbl->handle = ftb->create_table(name, index_columns, cdefs))) goto cleanup; if ((h = mdb_handle_add(table_handle, tbl)) == MQI_HANDLE_INVALID) goto cleanup; if (mdb_hash_add(table_name_hash, 0,namedup, NULL + h) < 0) { mdb_handle_delete(table_handle, h); h = MQI_HANDLE_INVALID; } ftb->register_table_handle(tbl->handle, h); return h; cleanup: if (tbl) { if (tbl->handle) { mdb_handle_delete(table_handle, h); ftb->drop_table(tbl->handle); } mdb_hash_delete(table_name_hash, 0,name); free(namedup); free(tbl); } return MDB_HANDLE_INVALID; }
// get an EDU from idle pool, if idle pool is empty, create new one int pmdEDUMgr::startEDU ( EDU_TYPES type, void* arg, EDUID *eduid ) { int rc = MDB_OK ; EDUID eduID = 0 ; pmdEDUCB* eduCB = NULL ; std::map<EDUID, pmdEDUCB*>::iterator it ; if ( isQuiesced () ) { rc = MDB_QUIESCED ; goto done ; } /****************** CRITICAL SECTION **********************/ // get exclusive latch, we don't latch the entire function // in order to avoid creating new thread while holding latch _mutex.get () ; // if there's any pooled EDU? // or is the request type can be pooled ? if ( true == _idleQueue.empty () || !isPoolable ( type ) ) { // note that EDU types other than "agent" shouldn't be pooled at all // release latch before calling createNewEDU _mutex.release () ; rc = _createNewEDU ( type, arg, eduid ) ; if ( MDB_OK == rc ) goto done ; goto error ; } // if we can find something in idle queue, let's get the first of it for ( it = _idleQueue.begin () ; ( _idleQueue.end () != it ) && ( PMD_EDU_IDLE != ( *it ).second->getStatus ()) ; it ++ ) ; // if everything in idleQueue are in DESTROY status, we still need to // create a new EDU if ( _idleQueue.end () == it ) { // release latch before calling createNewEDU _mutex.release () ; rc = _createNewEDU ( type, arg, eduid ) ; if ( MDB_OK == rc ) goto done ; goto error ; } // now "it" is pointing to an idle EDU // note that all EDUs in the idleQueue should be AGENT type eduID = ( *it ).first ; eduCB = ( *it ).second ; _idleQueue.erase ( eduID ) ; MDB_ASSERT ( isPoolable ( type ), "must be agent" ) // switch agent type for the EDU ( call different agent entry point ) eduCB->setType ( type ) ; eduCB->setStatus ( PMD_EDU_WAITING ) ; _runQueue [ eduID ] = eduCB ; *eduid = eduID ; _mutex.release () ; /*************** END CRITICAL SECTION **********************/ //The edu is start, need post a resum event eduCB->postEvent( pmdEDUEvent( PMD_EDU_EVENT_RESUME, false, arg ) ) ; done : return rc ; error : goto done ; }