===== sql/ha_ndbcluster.cc 1.419 vs edited =====
--- 1.419/sql/ha_ndbcluster.cc	2007-03-23 08:20:31 +01:00
+++ edited/sql/ha_ndbcluster.cc	2007-03-23 09:04:18 +01:00
@@ -4742,6 +4742,7 @@
   bool create_from_engine= (create_info->table_options & HA_OPTION_CREATE_FROM_ENGINE);
   bool is_truncate= (thd->lex->sql_command == SQLCOM_TRUNCATE);
   char tablespace[FN_LEN];
+  NdbDictionary::Table::SingleUserMode single_user_mode= NdbDictionary::Table::SingleUserModeLocked;
 
   DBUG_ENTER("ha_ndbcluster::create");
   DBUG_PRINT("enter", ("name: %s", name));
@@ -4793,19 +4794,23 @@
     schema distribution table is setup
     ( unless it is a creation of the schema dist table itself )
   */
-  if (!ndb_schema_share &&
-      !(strcmp(m_dbname, NDB_REP_DB) == 0 &&
-        strcmp(m_tabname, NDB_SCHEMA_TABLE) == 0))
+  if (!ndb_schema_share)
   {
-    DBUG_PRINT("info", ("Schema distribution table not setup"));
-    DBUG_RETURN(HA_ERR_NO_CONNECTION);
+    if (!(strcmp(m_dbname, NDB_REP_DB) == 0 &&
+          strcmp(m_tabname, NDB_SCHEMA_TABLE) == 0))
+    {
+      DBUG_PRINT("info", ("Schema distribution table not setup"));
+      DBUG_RETURN(HA_ERR_NO_CONNECTION);
+    }
+    single_user_mode = NdbDictionary::Table::SingleUserModeReadWrite;
   }
 #endif /* HAVE_NDB_BINLOG */
 
   DBUG_PRINT("table", ("name: %s", m_tabname));  
   tab.setName(m_tabname);
   tab.setLogging(!(create_info->options & HA_LEX_CREATE_TMP_TABLE));    
-   
+  tab.setSingleUserMode(single_user_mode);
+
   // Save frm data for this table
   if (readfrm(name, &data, &length))
     DBUG_RETURN(1);
===== storage/ndb/include/ndb_constants.h 1.14 vs edited =====
--- 1.14/storage/ndb/include/ndb_constants.h	2006-12-23 20:20:02 +01:00
+++ edited/storage/ndb/include/ndb_constants.h	2007-03-23 09:14:37 +01:00
@@ -90,4 +90,11 @@
 #define NDB_TEMP_TAB_PERMANENT          0
 #define NDB_TEMP_TAB_TEMPORARY          1
 
+/*
+ * Table single user mode
+ */
+#define NDB_SUM_LOCKED       0
+#define NDB_SUM_READONLY     1
+#define NDB_SUM_READ_WRITE   2
+
 #endif
===== storage/ndb/include/kernel/signaldata/DictTabInfo.hpp 1.36 vs edited =====
--- 1.36/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp	2007-02-23 12:23:42 +01:00
+++ edited/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp	2007-03-23 11:04:06 +01:00
@@ -140,6 +140,8 @@
     RowGCIFlag         = 150,
     RowChecksumFlag    = 151,
     
+    SingleUserMode     = 152,
+
     TableEnd           = 999,
     
     AttributeName          = 1000, // String, Mandatory
@@ -345,6 +347,8 @@
     Uint32 RowGCIFlag;
     Uint32 RowChecksumFlag;
     
+    Uint8 SingleUserMode;
+
     Table() {}
     void init();
   };
===== storage/ndb/include/ndbapi/NdbDictionary.hpp 1.87 vs edited =====
--- 1.87/storage/ndb/include/ndbapi/NdbDictionary.hpp	2007-01-16 09:19:28 +01:00
+++ edited/storage/ndb/include/ndbapi/NdbDictionary.hpp	2007-03-23 09:17:34 +01:00
@@ -576,6 +576,15 @@
    */
   class Table : public Object {
   public:
+    /*
+     * Single user mode specifies access rights to table during single user mode
+     */
+    enum SingleUserMode {
+      SingleUserModeLocked    = NDB_SUM_LOCKED,
+      SingleUserModeReadOnly  = NDB_SUM_READONLY,
+      SingleUserModeReadWrite = NDB_SUM_READ_WRITE
+    };
+
     /** 
      * @name General
      * @{
@@ -894,6 +903,13 @@
      */
     void setMinRows(Uint64 minRows);
     Uint64 getMinRows() const;
+
+    /**
+     * Set/Get SingleUserMode
+     */
+    void setSingleUserMode(enum SingleUserMode);
+    enum SingleUserMode getSingleUserMode() const;
+
 
     /** @} *******************************************************************/
 
===== storage/ndb/src/common/debugger/signaldata/DictTabInfo.cpp 1.20 vs edited =====
--- 1.20/storage/ndb/src/common/debugger/signaldata/DictTabInfo.cpp	2006-12-23 20:20:10 +01:00
+++ edited/storage/ndb/src/common/debugger/signaldata/DictTabInfo.cpp	2007-03-23 08:30:07 +01:00
@@ -66,6 +66,7 @@
   DTIMAP(Table, MaxRowsHigh, MaxRowsHigh),
   DTIMAP(Table, MinRowsLow, MinRowsLow),
   DTIMAP(Table, MinRowsHigh, MinRowsHigh),
+  DTIMAP(Table, SingleUserMode, SingleUserMode),
   DTIBREAK(AttributeName)
 };
 
@@ -164,6 +165,8 @@
   MaxRowsHigh = 0;
   MinRowsLow = 0;
   MinRowsHigh = 0;
+
+  SingleUserMode = 0;
 }
 
 void
===== storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp 1.120 vs edited =====
--- 1.120/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp	2007-03-13 11:18:11 +01:00
+++ edited/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp	2007-03-23 09:38:44 +01:00
@@ -461,6 +461,7 @@
   w.add(DictTabInfo::FragmentCount, tablePtr.p->fragmentCount);
   w.add(DictTabInfo::MinRowsLow, tablePtr.p->minRowsLow);
   w.add(DictTabInfo::MinRowsHigh, tablePtr.p->minRowsHigh);
+  w.add(DictTabInfo::SingleUserMode, tablePtr.p->singleUserMode);
 
   if(signal)
   {
@@ -1868,6 +1869,7 @@
   tablePtr.p->maxRowsHigh = 0;
   tablePtr.p->defaultNoPartFlag = true;
   tablePtr.p->linearHashFlag = true;
+  tablePtr.p->singleUserMode = 0;
   tablePtr.p->m_bits = 0;
   tablePtr.p->minRowsLow = 0;
   tablePtr.p->minRowsHigh = 0;
@@ -5698,7 +5700,8 @@
     signal->theData[4] = (Uint32)tabPtr.p->tableType;
     signal->theData[5] = createTabPtr.p->key;
     signal->theData[6] = (Uint32)tabPtr.p->noOfPrimkey;
-    sendSignal(DBTC_REF, GSN_TC_SCHVERREQ, signal, 7, JBB);
+    signal->theData[7] = (Uint32)tabPtr.p->singleUserMode;
+    sendSignal(DBTC_REF, GSN_TC_SCHVERREQ, signal, 8, JBB);
     return;
   }
   
@@ -6128,6 +6131,7 @@
   tablePtr.p->minRowsHigh = c_tableDesc.MinRowsHigh;
   tablePtr.p->defaultNoPartFlag = c_tableDesc.DefaultNoPartFlag; 
   tablePtr.p->linearHashFlag = c_tableDesc.LinearHashFlag; 
+  tablePtr.p->singleUserMode = c_tableDesc.SingleUserMode; 
   
   {
     Rope frm(c_rope_pool, tablePtr.p->frmData);
===== storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp 1.50 vs edited =====
--- 1.50/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp	2007-03-09 12:14:33 +01:00
+++ edited/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp	2007-03-23 09:08:04 +01:00
@@ -291,6 +291,11 @@
      */
     Uint8 minLoadFactor;
 
+    /*
+     * Access rights to table during single user mode
+     */
+    Uint8 singleUserMode;
+
     /* Convenience routines */
     bool isTable() const;
     bool isIndex() const;
===== storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp 1.54 vs edited =====
--- 1.54/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp	2007-03-23 08:20:31 +01:00
+++ edited/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp	2007-03-23 10:26:44 +01:00
@@ -710,6 +710,7 @@
     Uint8 tckeyrec; // Ändrad från R
     Uint8 tcindxrec;
     Uint8 apiFailState; // Ändrad från R
+    Uint8 singleUserMode;
     ReturnSignal returnsignal;
     Uint8 timeOutCounter;
     
@@ -961,10 +962,21 @@
   struct TableRecord {
     TableRecord() {}
     Uint32 currentSchemaVersion;
-    Uint8 enabled;
-    Uint8 dropping;
+    Uint16 m_flags;
     Uint8 tableType;
-    Uint8 storedTable;
+    Uint8 singleUserMode;
+
+    enum {
+      TR_ENABLED      = 1 << 0,
+      TR_DROPPING     = 1 << 1,
+      TR_STORED_TABLE = 1 << 2
+    };
+    Uint8 get_enabled()     const { return (m_flags & TR_ENABLED)      != 0; }
+    Uint8 get_dropping()    const { return (m_flags & TR_DROPPING)     != 0; }
+    Uint8 get_storedTable() const { return (m_flags & TR_STORED_TABLE) != 0; }
+    void set_enabled(Uint8 f)     { f ? m_flags |= (Uint16)TR_ENABLED      : m_flags &= ~(Uint16)TR_ENABLED; }
+    void set_dropping(Uint8 f)    { f ? m_flags |= (Uint16)TR_DROPPING     : m_flags &= ~(Uint16)TR_DROPPING; }
+    void set_storedTable(Uint8 f) { f ? m_flags |= (Uint16)TR_STORED_TABLE : m_flags &= ~(Uint16)TR_STORED_TABLE; }
 
     Uint8 noOfKeyAttr;
     Uint8 hasCharAttr;
@@ -972,7 +984,7 @@
     Uint8 hasVarKeys;
 
     bool checkTable(Uint32 schemaVersion) const {
-      return enabled && !dropping && 
+      return get_enabled() && !get_dropping() && 
 	(table_version_major(schemaVersion) == table_version_major(currentSchemaVersion));
     }
 
@@ -1840,10 +1852,10 @@
 			Uint32 transid2);
   void removeMarkerForFailedAPI(Signal* signal, Uint32 nodeId, Uint32 bucket);
 
-  bool getAllowStartTransaction(Uint32 nodeId) const {
+  bool getAllowStartTransaction(Uint32 nodeId, Uint32 table_single_user_mode) const {
     if (unlikely(getNodeState().getSingleUserMode()))
     {
-      if (getNodeState().getSingleUserApi() == nodeId)
+      if (getNodeState().getSingleUserApi() == nodeId || table_single_user_mode)
         return true;
       else
         return false;
===== storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp 1.142 vs edited =====
--- 1.142/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp	2007-03-23 08:20:32 +01:00
+++ edited/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp	2007-03-23 10:42:08 +01:00
@@ -330,19 +330,21 @@
   tabptr.i = signal->theData[0];
   ptrCheckGuard(tabptr, ctabrecFilesize, tableRecord);
   tabptr.p->currentSchemaVersion = signal->theData[1];
-  tabptr.p->storedTable = (bool)signal->theData[2];
+  tabptr.p->m_flags = 0;
+  tabptr.p->set_storedTable((bool)signal->theData[2]);
   BlockReference retRef = signal->theData[3];
   tabptr.p->tableType = (Uint8)signal->theData[4];
   BlockReference retPtr = signal->theData[5];
   Uint32 noOfKeyAttr = signal->theData[6];
+  tabptr.p->singleUserMode = (Uint8)signal->theData[7];
   ndbrequire(noOfKeyAttr <= MAX_ATTRIBUTES_IN_INDEX);
 
   const KeyDescriptor* desc = g_key_descriptor_pool.getPtr(tabptr.i);
   ndbrequire(noOfKeyAttr == desc->noOfKeyAttr);
 
-  ndbrequire(tabptr.p->enabled == false);
-  tabptr.p->enabled = true;
-  tabptr.p->dropping = false;
+  ndbrequire(tabptr.p->get_enabled() == false);
+  tabptr.p->set_enabled(true);
+  tabptr.p->set_dropping(false);
   tabptr.p->noOfKeyAttr = desc->noOfKeyAttr;
   tabptr.p->hasCharAttr = desc->hasCharAttr;
   tabptr.p->noOfDistrKeys = desc->noOfDistrKeys;
@@ -366,7 +368,7 @@
   Uint32 senderRef = req->senderRef;
   Uint32 senderData = req->senderData;
   
-  if(!tabPtr.p->enabled){
+  if(!tabPtr.p->get_enabled()){
     jam();
     PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
     ref->senderRef = reference();
@@ -378,7 +380,7 @@
     return;
   }
 
-  if(tabPtr.p->dropping){
+  if(tabPtr.p->get_dropping()){
     jam();
     PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
     ref->senderRef = reference();
@@ -390,7 +392,7 @@
     return;
   }
   
-  tabPtr.p->dropping = true;
+  tabPtr.p->set_dropping(true);
   tabPtr.p->dropTable.senderRef = senderRef;
   tabPtr.p->dropTable.senderData = senderData;
 
@@ -426,7 +428,7 @@
   tabPtr.i = conf->tableId;
   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
   
-  ndbrequire(tabPtr.p->dropping == true);
+  ndbrequire(tabPtr.p->get_dropping() == true);
   Uint32 nodeId = refToNode(conf->senderRef);
   tabPtr.p->dropTable.waitDropTabCount.clearWaitingFor(nodeId);
   
@@ -456,7 +458,7 @@
   tabPtr.i = ref->tableId;
   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
   
-  ndbrequire(tabPtr.p->dropping == true);
+  ndbrequire(tabPtr.p->get_dropping() == true);
   Uint32 nodeId = refToNode(ref->senderRef);
   tabPtr.p->dropTable.waitDropTabCount.clearWaitingFor(nodeId);
   
@@ -493,7 +495,7 @@
   for(Uint32 i = 0; i<RT_BREAK && tabPtr.i < ctabrecFilesize; i++, tabPtr.i++){
     jam();
     ptrAss(tabPtr, tableRecord);
-    if(tabPtr.p->enabled && tabPtr.p->dropping){
+    if(tabPtr.p->get_enabled() && tabPtr.p->get_dropping()){
       if(tabPtr.p->dropTable.waitDropTabCount.isWaitingFor(nodeId)){
         jam();
 	conf->senderRef = calcLqhBlockRef(nodeId);
@@ -534,7 +536,7 @@
   Uint32 senderData = req->senderData;
   DropTabReq::RequestType rt = (DropTabReq::RequestType)req->requestType;
   
-  if(!tabPtr.p->enabled && rt == DropTabReq::OnlineDropTab){
+  if(!tabPtr.p->get_enabled() && rt == DropTabReq::OnlineDropTab){
     jam();
     DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend();
     ref->senderRef = reference();
@@ -546,7 +548,7 @@
     return;
   }
 
-  if(!tabPtr.p->dropping && rt == DropTabReq::OnlineDropTab){
+  if(!tabPtr.p->get_dropping() && rt == DropTabReq::OnlineDropTab){
     jam();
     DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend();
     ref->senderRef = reference();
@@ -558,8 +560,8 @@
     return;
   }
   
-  tabPtr.p->enabled = false;
-  tabPtr.p->dropping = false;
+  tabPtr.p->set_enabled(false);
+  tabPtr.p->set_dropping(false);
   
   DropTabConf * conf = (DropTabConf*)signal->getDataPtrSend();
   conf->tableId = tabPtr.i;
@@ -1217,8 +1219,7 @@
 	      break;
 	    case NodeState::SL_STOPPING_1:
 	    case NodeState::SL_STOPPING_2:
-              if (getNodeState().getSingleUserMode() &&
-                  getNodeState().getSingleUserApi() == senderNodeId)
+              if (getNodeState().getSingleUserMode())
                 break;
 	    case NodeState::SL_STOPPING_3:
 	    case NodeState::SL_STOPPING_4:
@@ -1228,9 +1229,6 @@
 		errCode = ZNODE_SHUTDOWN_IN_PROGRESS;
 	      break;
 	    case NodeState::SL_SINGLEUSER:
-              if (getNodeState().getSingleUserApi() == senderNodeId)
-                break;
-	      errCode = ZCLUSTER_IN_SINGLEUSER_MODE;
 	      break;
 	    default:
 	      errCode = ZWRONG_STATE;
@@ -2402,6 +2400,7 @@
   regApiPtr->buddyPtr = RNIL;
   regApiPtr->currSavePointId = 0;
   regApiPtr->m_transaction_nodes.clear();
+  regApiPtr->singleUserMode = 0;
   // Trigger data
   releaseFiredTriggerData(&regApiPtr->theFiredTriggers),
   // Index data
@@ -2555,9 +2554,12 @@
   bool isIndexOpReturn = regApiPtr->indexOpReturn;
   regApiPtr->isIndexOp = false; // Reset marker
   regApiPtr->m_exec_flag |= TexecFlag;
+  TableRecordPtr localTabptr;
+  localTabptr.i = TtabIndex;
+  localTabptr.p = &tableRecord[TtabIndex];
   switch (regApiPtr->apiConnectstate) {
   case CS_CONNECTED:{
-    if (TstartFlag == 1 && getAllowStartTransaction(sendersNodeId) == true){
+    if (TstartFlag == 1 && getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == true){
       //---------------------------------------------------------------------
       // Initialise API connect record if transaction is started.
       //---------------------------------------------------------------------
@@ -2565,7 +2567,7 @@
       initApiConnectRec(signal, regApiPtr);
       regApiPtr->m_exec_flag = TexecFlag;
     } else {
-      if(getAllowStartTransaction(sendersNodeId) == true){
+      if(getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == true){
 	/*------------------------------------------------------------------
 	 * WE EXPECTED A START TRANSACTION. SINCE NO OPERATIONS HAVE BEEN 
 	 * RECEIVED WE INDICATE THIS BY SETTING FIRST_TC_CONNECT TO RNIL TO 
@@ -2675,9 +2677,6 @@
     return;
   }//switch
   
-  TableRecordPtr localTabptr;
-  localTabptr.i = TtabIndex;
-  localTabptr.p = &tableRecord[TtabIndex];
   if (localTabptr.p->checkTable(tcKeyReq->tableSchemaVersion)) {
     ;
   } else {
@@ -2736,6 +2735,8 @@
   regTcPtr->savePointId = regApiPtr->currSavePointId;
   regApiPtr->executingIndexOp = RNIL;
 
+  regApiPtr->singleUserMode |= 1 << localTabptr.p->singleUserMode;
+
   if (TcKeyReq::getExecutingTrigger(Treqinfo)) {
     // Save the TcOperationPtr for fireing operation
     regTcPtr->triggeringOperation = TsenderData;
@@ -2867,7 +2868,7 @@
      *   THIS VARIABLE CONTROLS THE INTERVAL BETWEEN LCP'S AND 
      *   TEMP TABLES DON'T PARTICIPATE.
      * -------------------------------------------------------------------- */
-    if (localTabptr.p->storedTable) {
+    if (localTabptr.p->get_storedTable()) {
       coperationsize = ((Toperationsize + TattrLen) + TkeyLength) + 17;
     }
     c_counters.cwriteCount = TwriteCount + 1;
@@ -4700,6 +4701,7 @@
   regApiPtr->lqhkeyconfrec = Tlqhkeyconfrec;
   regApiPtr->commitAckMarker = TcommitAckMarker;
   regApiPtr->m_transaction_nodes = Tnodes;
+  regApiPtr->singleUserMode = 0;
 
   gcpPtr.i = TgcpPointer;
   ptrCheckGuard(gcpPtr, TgcpFilesize, localGcpRecord);
@@ -4711,6 +4713,7 @@
   regTmpApiPtr->firstTcConnect = RNIL;
   regTmpApiPtr->lastTcConnect = RNIL;
   regTmpApiPtr->m_transaction_nodes.clear();
+  regTmpApiPtr->singleUserMode = 0;
   releaseAllSeizedIndexOperations(regTmpApiPtr);
 }//Dbtc::copyApi()
 
@@ -6230,8 +6233,9 @@
       {
         apiConnectptr.i = api_con_ptr;
         ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
-        if (getNodeState().getSingleUserApi() ==
-            refToNode(apiConnectptr.p->ndbapiBlockref))
+        if ((getNodeState().getSingleUserApi() ==
+             refToNode(apiConnectptr.p->ndbapiBlockref)) ||
+            !(apiConnectptr.p->singleUserMode & (1 << NDB_SUM_LOCKED)))
         {
           // api allowed during single user, use original timeout
           time_out_value=
@@ -8161,6 +8165,7 @@
   apiConnectptr.p->ndbapiConnect = 0;
   apiConnectptr.p->buddyPtr = RNIL;
   apiConnectptr.p->m_transaction_nodes.clear();
+  apiConnectptr.p->singleUserMode = 0;
   setApiConTimer(apiConnectptr.i, 0, __LINE__);
   switch(ttransStatus){
   case LqhTransConf::Committed:
@@ -10076,6 +10081,7 @@
     apiConnectptr.p->buddyPtr = RNIL;
     apiConnectptr.p->currSavePointId = 0;
     apiConnectptr.p->m_transaction_nodes.clear();
+    apiConnectptr.p->singleUserMode = 0;
   }//for
   apiConnectptr.i = tiacTmp - 1;
   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
@@ -10104,6 +10110,7 @@
       apiConnectptr.p->buddyPtr = RNIL;
       apiConnectptr.p->currSavePointId = 0;
       apiConnectptr.p->m_transaction_nodes.clear();
+      apiConnectptr.p->singleUserMode = 0;
     }//for
   apiConnectptr.i = (2 * tiacTmp) - 1;
   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
@@ -10132,6 +10139,7 @@
     apiConnectptr.p->buddyPtr = RNIL;
     apiConnectptr.p->currSavePointId = 0;
     apiConnectptr.p->m_transaction_nodes.clear();
+    apiConnectptr.p->singleUserMode = 0;
   }//for
   apiConnectptr.i = (3 * tiacTmp) - 1;
   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
@@ -10316,10 +10324,11 @@
     refresh_watch_dog();
     ptrAss(tabptr, tableRecord);
     tabptr.p->currentSchemaVersion = 0;
-    tabptr.p->storedTable = true;
+    tabptr.p->m_flags = 0;
+    tabptr.p->set_storedTable(true);
     tabptr.p->tableType = 0;
-    tabptr.p->enabled = false;
-    tabptr.p->dropping = false;
+    tabptr.p->set_enabled(false);
+    tabptr.p->set_dropping(false);
     tabptr.p->noOfKeyAttr = 0;
     tabptr.p->hasCharAttr = 0;
     tabptr.p->noOfDistrKeys = 0;
@@ -10453,6 +10462,7 @@
   apiConnectptr.p->firstTcConnect = RNIL;
   apiConnectptr.p->lastTcConnect = RNIL;
   apiConnectptr.p->m_transaction_nodes.clear();
+  apiConnectptr.p->singleUserMode = 0;
 
   // MASV let state be CS_ABORTING until all 
   // signals in the "air" have been received. Reset to CS_CONNECTED
@@ -11101,7 +11111,7 @@
   const Uint32 senderData = req->senderData;
   const BlockReference senderRef = req->senderRef;
   
-  if(getAllowStartTransaction(refToNode(senderRef)) == true && !getNodeState().getSingleUserMode()){
+  if(getAllowStartTransaction(refToNode(senderRef), 0) == true && !getNodeState().getSingleUserMode()){
     jam();
 
     ref->senderData = senderData;
@@ -13378,9 +13388,9 @@
 
 Uint32 
 Dbtc::TableRecord::getErrorCode(Uint32 schemaVersion) const {
-  if(!enabled)
+  if(!get_enabled())
     return ZNO_SUCH_TABLE;
-  if(dropping)
+  if(get_dropping())
     return ZDROP_TABLE_IN_PROGRESS;
   if(table_version_major(schemaVersion) != table_version_major(currentSchemaVersion))
     return ZWRONG_SCHEMA_VERSION_ERROR;
===== storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp 1.51 vs edited =====
--- 1.51/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp	2007-03-20 21:49:51 +01:00
+++ edited/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp	2007-03-23 10:59:16 +01:00
@@ -1684,6 +1684,7 @@
   //w.add(DictTabInfo::NoOfVariable, (Uint32)0);
   //w.add(DictTabInfo::KeyLength, 1);
   w.add(DictTabInfo::TableTypeVal, (Uint32)table.tableType);
+  w.add(DictTabInfo::SingleUserMode, (Uint32)NDB_SUM_READ_WRITE);
 
   for (unsigned i = 0; i < table.columnCount; i++) {
     const SysColumn& column = table.columnList[i];
===== storage/ndb/src/ndbapi/NdbDictionary.cpp 1.67 vs edited =====
--- 1.67/storage/ndb/src/ndbapi/NdbDictionary.cpp	2007-01-16 09:19:28 +01:00
+++ edited/storage/ndb/src/ndbapi/NdbDictionary.cpp	2007-03-23 08:57:33 +01:00
@@ -461,6 +461,18 @@
   return m_impl.m_min_rows;
 }
 
+enum NdbDictionary::Table::SingleUserMode
+NdbDictionary::Table::getSingleUserMode() const
+{
+  return (enum SingleUserMode)m_impl.m_single_user_mode;
+}
+
+void
+NdbDictionary::Table::setSingleUserMode(enum NdbDictionary::Table::SingleUserMode mode)
+{
+  m_impl.m_single_user_mode = (Uint8)mode;
+}
+
 void
 NdbDictionary::Table::setDefaultNoPartitionsFlag(Uint32 flag)
 {
===== storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp 1.161 vs edited =====
--- 1.161/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp	2007-03-09 14:55:25 +01:00
+++ edited/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp	2007-03-23 11:06:56 +01:00
@@ -467,6 +467,7 @@
   m_replicaCount= 0;
   m_min_rows = 0;
   m_max_rows = 0;
+  m_single_user_mode = 0;
   m_tablespace_name.clear();
   m_tablespace_id = ~0;
   m_tablespace_version = ~0;
@@ -558,6 +559,13 @@
     DBUG_RETURN(false);
   }
 
+  if(m_single_user_mode != obj.m_single_user_mode)
+  {
+    DBUG_PRINT("info",("m_single_user_mode %d != %d",(int32)m_single_user_mode,
+                       (int32)obj.m_single_user_mode));
+    DBUG_RETURN(false);
+  }
+
   if(m_default_no_part_flag != obj.m_default_no_part_flag)
   {
     DBUG_PRINT("info",("m_default_no_part_flag %d != %d",m_default_no_part_flag,
@@ -745,6 +753,8 @@
   m_max_rows = org.m_max_rows;
   m_min_rows = org.m_min_rows;
 
+  m_single_user_mode = org.m_single_user_mode;
+
   m_tablespace_name = org.m_tablespace_name;
   m_tablespace_id= org.m_tablespace_id;
   m_tablespace_version = org.m_tablespace_version;
@@ -2103,6 +2113,7 @@
   impl->m_kvalue = tableDesc->TableKValue;
   impl->m_minLoadFactor = tableDesc->MinLoadFactor;
   impl->m_maxLoadFactor = tableDesc->MaxLoadFactor;
+  impl->m_single_user_mode = tableDesc->SingleUserMode;
 
   impl->m_indexType = (NdbDictionary::Object::Type)
     getApiConstant(tableDesc->TableType,
@@ -2564,6 +2575,7 @@
   tmpTab->MinRowsLow = (Uint32)(impl.m_min_rows & 0xFFFFFFFF);
   tmpTab->DefaultNoPartFlag = impl.m_default_no_part_flag;
   tmpTab->LinearHashFlag = impl.m_linear_flag;
+  tmpTab->SingleUserMode = impl.m_single_user_mode;
 
   if (impl.m_ts_name.length())
   {
===== storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp 1.71 vs edited =====
--- 1.71/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp	2006-12-27 10:58:06 +01:00
+++ edited/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp	2007-03-23 08:38:27 +01:00
@@ -204,6 +204,7 @@
   int m_maxLoadFactor;
   Uint16 m_keyLenInWords;
   Uint16 m_fragmentCount;
+  Uint8 m_single_user_mode;
 
   NdbIndexImpl * m_index;
   NdbColumnImpl * getColumn(unsigned attrId);
===== storage/ndb/test/src/NDBT_Table.cpp 1.11 vs edited =====
--- 1.11/storage/ndb/test/src/NDBT_Table.cpp	2006-12-23 20:20:31 +01:00
+++ edited/storage/ndb/test/src/NDBT_Table.cpp	2007-03-23 10:51:45 +01:00
@@ -33,6 +33,7 @@
   ndbout << "Length of frm data: " << tab.getFrmLength() << endl;
   ndbout << "Row Checksum: " << tab.getRowChecksumIndicator() << endl;
   ndbout << "Row GCI: " << tab.getRowGCIIndicator() << endl;
+  ndbout << "SingleUserMode: " << tab.getSingleUserMode() << endl;
 
 
   //<< ((tab.getTupleKey() == TupleId) ? " tupleid" : "") <<endl;
