diff options
author | unknown <cmiller@zippy.(none)> | 2006-07-10 13:38:22 -0400 |
---|---|---|
committer | unknown <cmiller@zippy.(none)> | 2006-07-10 13:38:22 -0400 |
commit | d6e3a9ddcb6a877feb65a98953b3ec9e6426be47 (patch) | |
tree | 555b6e52dd857768fcf99821dd6c45b62b80dd30 /storage | |
parent | 9b6a1384114a41beb8b492aed335096ef03c86df (diff) | |
parent | 8154ca618b68784098dcb8b84ba2cf77707c80e4 (diff) | |
download | mariadb-git-d6e3a9ddcb6a877feb65a98953b3ec9e6426be47.tar.gz |
Merge zippy.(none):/home/cmiller/work/mysql/merge/mysql-5.1
into zippy.(none):/home/cmiller/work/mysql/merge/mysql-5.1-new-maint
mysql-test/mysql-test-run.pl:
Auto merged
mysql-test/r/create.result:
Auto merged
mysql-test/r/ps.result:
Auto merged
mysql-test/r/sp.result:
Auto merged
mysql-test/t/create.test:
Auto merged
mysql-test/t/ndb_autodiscover3.test:
Auto merged
mysql-test/t/ps.test:
Auto merged
mysql-test/t/sp.test:
Auto merged
mysql-test/t/wait_timeout.test:
Auto merged
sql/field.cc:
Auto merged
sql/field.h:
Auto merged
Diffstat (limited to 'storage')
43 files changed, 472 insertions, 192 deletions
diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index d91597e9138..91c04866b5a 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -1158,13 +1158,14 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) #ifdef HAVE_RTREE_KEYS (keyinfo->flag & HA_SPATIAL) ? rtree_find_first(info, key, info->lastkey, key_length, - SEARCH_SAME) : + MBR_EQUAL | MBR_DATA) : #endif _mi_search(info,keyinfo,info->lastkey,key_length, SEARCH_SAME, info->s->state.key_root[key]); if (search_result) { - mi_check_print_error(param,"Record at: %10s Can't find key for index: %2d", + mi_check_print_error(param,"Record at: %10s " + "Can't find key for index: %2d", llstr(start_recpos,llbuff),key+1); if (error++ > MAXERR || !(param->testflag & T_VERBOSE)) goto err2; diff --git a/storage/myisam/mi_create.c b/storage/myisam/mi_create.c index 22cbde278be..c5a9af08def 100644 --- a/storage/myisam/mi_create.c +++ b/storage/myisam/mi_create.c @@ -60,6 +60,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, my_off_t key_root[MI_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE]; MI_CREATE_INFO tmp_create_info; DBUG_ENTER("mi_create"); + DBUG_PRINT("enter", ("keys: %u columns: %u uniques: %u flags: %u", + keys, columns, uniques, flags)); if (!ci) { @@ -482,6 +484,16 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, uniques * MI_UNIQUEDEF_SIZE + (key_segs + unique_key_parts)*HA_KEYSEG_SIZE+ columns*MI_COLUMNDEF_SIZE); + DBUG_PRINT("info", ("info_length: %u", info_length)); + /* There are only 16 bits for the total header length. */ + if (info_length > 65535) + { + my_printf_error(0, "MyISAM table '%s' has too many columns and/or " + "indexes and/or unique constraints.", + MYF(0), name + dirname_length(name)); + my_errno= HA_WRONG_CREATE_OPTION; + goto err; + } bmove(share.state.header.file_version,(byte*) myisam_file_magic,4); ci->old_options=options| (ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD ? @@ -650,6 +662,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, errpos=3; } + DBUG_PRINT("info", ("write state info and base info")); if (mi_state_info_write(file, &share.state, 2) || mi_base_info_write(file, &share.base)) goto err; @@ -663,6 +676,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, #endif /* Write key and keyseg definitions */ + DBUG_PRINT("info", ("write key and keyseg definitions")); for (i=0 ; i < share.base.keys - uniques; i++) { uint sp_segs=(keydefs[i].flag & HA_SPATIAL) ? 2*SPDIMS : 0; @@ -713,6 +727,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, } /* Save unique definition */ + DBUG_PRINT("info", ("write unique definitions")); for (i=0 ; i < share.state.header.uniques ; i++) { HA_KEYSEG *keyseg_end; @@ -743,6 +758,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, goto err; } } + DBUG_PRINT("info", ("write field definitions")); for (i=0 ; i < share.base.fields ; i++) if (mi_recinfo_write(file, &recinfo[i])) goto err; @@ -757,6 +773,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, #endif /* Enlarge files */ + DBUG_PRINT("info", ("enlarge to keystart: %lu", (ulong) share.base.keystart)); if (my_chsize(file,(ulong) share.base.keystart,0,MYF(0))) goto err; diff --git a/storage/myisam/mi_delete_table.c b/storage/myisam/mi_delete_table.c index df0e9deb3ec..b72e97d3215 100644 --- a/storage/myisam/mi_delete_table.c +++ b/storage/myisam/mi_delete_table.c @@ -34,12 +34,24 @@ int mi_delete_table(const char *name) #ifdef USE_RAID { MI_INFO *info; - /* we use 'open_for_repair' to be able to delete a crashed table */ - if (!(info=mi_open(name, O_RDONLY, HA_OPEN_FOR_REPAIR))) - DBUG_RETURN(my_errno); - raid_type = info->s->base.raid_type; - raid_chunks = info->s->base.raid_chunks; - mi_close(info); + /* + When built with RAID support, we need to determine if this table + makes use of the raid feature. If yes, we need to remove all raid + chunks. This is done with my_raid_delete(). Unfortunately it is + necessary to open the table just to check this. We use + 'open_for_repair' to be able to open even a crashed table. If even + this open fails, we assume no raid configuration for this table + and try to remove the normal data file only. This may however + leave the raid chunks behind. + */ + if (!(info= mi_open(name, O_RDONLY, HA_OPEN_FOR_REPAIR))) + raid_type= 0; + else + { + raid_type= info->s->base.raid_type; + raid_chunks= info->s->base.raid_chunks; + mi_close(info); + } } #ifdef EXTRA_DEBUG check_table_is_closed(name,"delete"); diff --git a/storage/myisam/mi_dynrec.c b/storage/myisam/mi_dynrec.c index 9d76a1fb9a5..0487500ad33 100644 --- a/storage/myisam/mi_dynrec.c +++ b/storage/myisam/mi_dynrec.c @@ -1329,6 +1329,9 @@ int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, byte *buf) info->rec_cache.pos_in_file <= block_info.next_filepos && flush_io_cache(&info->rec_cache)) goto err; + /* A corrupted table can have wrong pointers. (Bug# 19835) */ + if (block_info.next_filepos == HA_OFFSET_ERROR) + goto panic; info->rec_cache.seek_not_done=1; if ((b_type=_mi_get_block_info(&block_info,file, block_info.next_filepos)) diff --git a/storage/myisam/mi_rkey.c b/storage/myisam/mi_rkey.c index e6f4d39ab49..a9a8cbacb4b 100644 --- a/storage/myisam/mi_rkey.c +++ b/storage/myisam/mi_rkey.c @@ -68,6 +68,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, if (fast_mi_readinfo(info)) goto err; + if (share->concurrent_insert) rw_rdlock(&share->key_root_lock[inx]); @@ -90,24 +91,35 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, case HA_KEY_ALG_BTREE: default: if (!_mi_search(info, keyinfo, key_buff, use_key_length, - myisam_read_vec[search_flag], info->s->state.key_root[inx])) + myisam_read_vec[search_flag], info->s->state.key_root[inx])) { - while (info->lastpos >= info->state->data_file_length) + /* + If we are searching for an exact key (including the data pointer) + and this was added by an concurrent insert, + then the result is "key not found". + */ + if ((search_flag == HA_READ_KEY_EXACT) && + (info->lastpos >= info->state->data_file_length)) + { + my_errno= HA_ERR_KEY_NOT_FOUND; + info->lastpos= HA_OFFSET_ERROR; + } + else while (info->lastpos >= info->state->data_file_length) { /* Skip rows that are inserted by other threads since we got a lock Note that this can only happen if we are not searching after an exact key, because the keys are sorted according to position */ - if (_mi_search_next(info, keyinfo, info->lastkey, - info->lastkey_length, - myisam_readnext_vec[search_flag], - info->s->state.key_root[inx])) + info->lastkey_length, + myisam_readnext_vec[search_flag], + info->s->state.key_root[inx])) break; } } } + if (share->concurrent_insert) rw_unlock(&share->key_root_lock[inx]); diff --git a/storage/myisam/rt_index.c b/storage/myisam/rt_index.c index 97554dca4e6..1806476dc39 100644 --- a/storage/myisam/rt_index.c +++ b/storage/myisam/rt_index.c @@ -183,9 +183,11 @@ int rtree_find_first(MI_INFO *info, uint keynr, uchar *key, uint key_length, return -1; } - /* Save searched key */ - memcpy(info->first_mbr_key, key, keyinfo->keylength - - info->s->base.rec_reflength); + /* + Save searched key, include data pointer. + The data pointer is required if the search_flag contains MBR_DATA. + */ + memcpy(info->first_mbr_key, key, keyinfo->keylength); info->last_rkey_length = key_length; info->rtree_recursion_depth = -1; diff --git a/storage/myisam/rt_mbr.c b/storage/myisam/rt_mbr.c index c43daec2f7c..897862c1c9a 100644 --- a/storage/myisam/rt_mbr.c +++ b/storage/myisam/rt_mbr.c @@ -52,10 +52,14 @@ if (EQUAL_CMP(amin, amax, bmin, bmax)) \ return 1; \ } \ - else /* if (nextflag & MBR_DISJOINT) */ \ + else if (nextflag & MBR_DISJOINT) \ { \ if (DISJOINT_CMP(amin, amax, bmin, bmax)) \ return 1; \ + }\ + else /* if unknown comparison operator */ \ + { \ + DBUG_ASSERT(0); \ } #define RT_CMP_KORR(type, korr_func, len, nextflag) \ diff --git a/storage/ndb/include/kernel/AttributeHeader.hpp b/storage/ndb/include/kernel/AttributeHeader.hpp index b17bb456bf0..b78b5912bec 100644 --- a/storage/ndb/include/kernel/AttributeHeader.hpp +++ b/storage/ndb/include/kernel/AttributeHeader.hpp @@ -39,12 +39,13 @@ public: STATIC_CONST( RANGE_NO = 0xFFFB ); // Read range no (when batched ranges) STATIC_CONST( ROW_SIZE = 0xFFFA ); - STATIC_CONST( FRAGMENT_MEMORY= 0xFFF9 ); + STATIC_CONST( FRAGMENT_FIXED_MEMORY= 0xFFF9 ); STATIC_CONST( RECORDS_IN_RANGE = 0xFFF8 ); STATIC_CONST( DISK_REF = 0xFFF7 ); STATIC_CONST( ROWID = 0xFFF6 ); STATIC_CONST( ROW_GCI = 0xFFF5 ); + STATIC_CONST( FRAGMENT_VARSIZED_MEMORY = 0xFFF4 ); // NOTE: in 5.1 ctors and init take size in bytes diff --git a/storage/ndb/include/mgmapi/ndbd_exit_codes.h b/storage/ndb/include/mgmapi/ndbd_exit_codes.h index b16f1a63a8d..79df36e7955 100644 --- a/storage/ndb/include/mgmapi/ndbd_exit_codes.h +++ b/storage/ndb/include/mgmapi/ndbd_exit_codes.h @@ -71,6 +71,7 @@ typedef ndbd_exit_classification_enum ndbd_exit_classification; #define NDBD_EXIT_INDEX_NOTINRANGE 2304 #define NDBD_EXIT_ARBIT_SHUTDOWN 2305 #define NDBD_EXIT_POINTER_NOTINRANGE 2306 +#define NDBD_EXIT_PARTITIONED_SHUTDOWN 2307 #define NDBD_EXIT_SR_OTHERNODEFAILED 2308 #define NDBD_EXIT_NODE_NOT_DEAD 2309 #define NDBD_EXIT_SR_REDOLOG 2310 diff --git a/storage/ndb/include/ndbapi/Ndb.hpp b/storage/ndb/include/ndbapi/Ndb.hpp index dcd03cdc467..07f11f6e78a 100644 --- a/storage/ndb/include/ndbapi/Ndb.hpp +++ b/storage/ndb/include/ndbapi/Ndb.hpp @@ -1553,6 +1553,7 @@ private: const char* aCatalogName, const char* aSchemaName); void connected(Uint32 block_reference); + void report_node_connected(Uint32 nodeId); NdbTransaction* startTransactionLocal(Uint32 aPrio, Uint32 aFragmentId); diff --git a/storage/ndb/include/ndbapi/NdbDictionary.hpp b/storage/ndb/include/ndbapi/NdbDictionary.hpp index ea4a2a9ca29..35b0d927bda 100644 --- a/storage/ndb/include/ndbapi/NdbDictionary.hpp +++ b/storage/ndb/include/ndbapi/NdbDictionary.hpp @@ -525,7 +525,8 @@ public: const char* getDefaultValue() const; static const Column * FRAGMENT; - static const Column * FRAGMENT_MEMORY; + static const Column * FRAGMENT_FIXED_MEMORY; + static const Column * FRAGMENT_VARSIZED_MEMORY; static const Column * ROW_COUNT; static const Column * COMMIT_COUNT; static const Column * ROW_SIZE; diff --git a/storage/ndb/src/common/debugger/signaldata/SignalNames.cpp b/storage/ndb/src/common/debugger/signaldata/SignalNames.cpp index 7304a46a278..a96d0de0560 100644 --- a/storage/ndb/src/common/debugger/signaldata/SignalNames.cpp +++ b/storage/ndb/src/common/debugger/signaldata/SignalNames.cpp @@ -365,6 +365,8 @@ const GsnName SignalNames [] = { ,{ GSN_EVENT_SUBSCRIBE_REF, "EVENT_SUBSCRIBE_REF" } ,{ GSN_DUMP_STATE_ORD, "DUMP_STATE_ORD" } + ,{ GSN_NODE_START_REP, "NODE_START_REP" } + ,{ GSN_START_INFOREQ, "START_INFOREQ" } ,{ GSN_START_INFOREF, "START_INFOREF" } ,{ GSN_START_INFOCONF, "START_INFOCONF" } diff --git a/storage/ndb/src/kernel/blocks/dbdict/DictLock.txt b/storage/ndb/src/kernel/blocks/dbdict/DictLock.txt index 17f24119e9d..72e23ed15a5 100644 --- a/storage/ndb/src/kernel/blocks/dbdict/DictLock.txt +++ b/storage/ndb/src/kernel/blocks/dbdict/DictLock.txt @@ -85,10 +85,14 @@ DIH/s START_MECONF DIH/s -* sp7 - release DICT lock +* (copy data, omitted) -DIH/s - DICT_UNLOCK_ORD - DICT/m +* SL_STARTED - release DICT lock + +CNTR/s + NODE_START_REP + DIH/s + DICT_UNLOCK_ORD + DICT/m # vim: set et sw=4: diff --git a/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp b/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp index 46effed867f..9d9ea6af2f5 100644 --- a/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp +++ b/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp @@ -1609,6 +1609,9 @@ private: void dump_replica_info(); + // DIH specifics for execNODE_START_REP (sendDictUnlockOrd) + void exec_node_start_rep(Signal* signal); + /* * Lock master DICT. Only current use is by starting node * during NR. A pool of slave records is convenient anyway. diff --git a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp index c265f54bf30..0595c018b2e 100644 --- a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp +++ b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp @@ -1387,24 +1387,6 @@ void Dbdih::execNDB_STTOR(Signal* signal) } ndbrequire(false); break; - case ZNDB_SPH7: - jam(); - switch (typestart) { - case NodeState::ST_INITIAL_START: - case NodeState::ST_SYSTEM_RESTART: - jam(); - ndbsttorry10Lab(signal, __LINE__); - return; - case NodeState::ST_NODE_RESTART: - case NodeState::ST_INITIAL_NODE_RESTART: - jam(); - sendDictUnlockOrd(signal, c_dictLockSlavePtrI_nodeRestart); - c_dictLockSlavePtrI_nodeRestart = RNIL; - ndbsttorry10Lab(signal, __LINE__); - return; - } - ndbrequire(false); - break; default: jam(); ndbsttorry10Lab(signal, __LINE__); @@ -1413,6 +1395,27 @@ void Dbdih::execNDB_STTOR(Signal* signal) }//Dbdih::execNDB_STTOR() void +Dbdih::exec_node_start_rep(Signal* signal) +{ + /* + * Send DICT_UNLOCK_ORD when this node is SL_STARTED. + * + * Sending it before (sp 7) conflicts with code which assumes + * SL_STARTING means we are in copy phase of NR. + * + * NodeState::starting.restartType is not supposed to be used + * when SL_STARTED. Also it seems NODE_START_REP can arrive twice. + * + * For these reasons there are no consistency checks and + * we rely on c_dictLockSlavePtrI_nodeRestart alone. + */ + if (c_dictLockSlavePtrI_nodeRestart != RNIL) { + sendDictUnlockOrd(signal, c_dictLockSlavePtrI_nodeRestart); + c_dictLockSlavePtrI_nodeRestart = RNIL; + } +} + +void Dbdih::createMutexes(Signal * signal, Uint32 count){ Callback c = { safe_cast(&Dbdih::createMutex_done), count }; @@ -1636,6 +1639,7 @@ void Dbdih::nodeRestartPh2Lab(Signal* signal) void Dbdih::recvDictLockConf_nodeRestart(Signal* signal, Uint32 data, Uint32 ret) { ndbrequire(c_dictLockSlavePtrI_nodeRestart == RNIL); + ndbrequire(data != RNIL); c_dictLockSlavePtrI_nodeRestart = data; nodeRestartPh2Lab2(signal); diff --git a/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp b/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp index c1d4175833e..be52e06eb81 100644 --- a/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp +++ b/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp @@ -238,6 +238,7 @@ class Dbtup; #define ZSCAN_MARKERS 18 #define ZOPERATION_EVENT_REP 19 #define ZPREP_DROP_TABLE 20 +#define ZENABLE_EXPAND_CHECK 21 /* ------------------------------------------------------------------------- */ /* NODE STATE DURING SYSTEM RESTART, VARIABLES CNODES_SR_STATE */ diff --git a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index 3890fb69b2e..695580d556c 100644 --- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -416,6 +416,35 @@ void Dblqh::execCONTINUEB(Signal* signal) checkDropTab(signal); return; break; + case ZENABLE_EXPAND_CHECK: + { + jam(); + fragptr.i = signal->theData[1]; + if (fragptr.i != RNIL) + { + jam(); + c_redo_complete_fragments.getPtr(fragptr); + signal->theData[0] = fragptr.p->tabRef; + signal->theData[1] = fragptr.p->fragId; + sendSignal(DBACC_REF, GSN_EXPANDCHECK2, signal, 2, JBB); + + c_redo_complete_fragments.next(fragptr); + signal->theData[0] = ZENABLE_EXPAND_CHECK; + signal->theData[1] = fragptr.i; + sendSignal(DBLQH_REF, GSN_CONTINUEB, signal, 2, JBB); + return; + } + else + { + jam(); + c_redo_complete_fragments.remove(); + StartRecConf * conf = (StartRecConf*)signal->getDataPtrSend(); + conf->startingNodeId = getOwnNodeId(); + sendSignal(cmasterDihBlockref, GSN_START_RECCONF, signal, + StartRecConf::SignalLength, JBB); + return; + } + } default: ndbrequire(false); break; @@ -469,6 +498,7 @@ void Dblqh::execSTTOR(Signal* signal) csignalKey = signal->theData[6]; #if defined VM_TRACE || defined ERROR_INSERT || defined NDBD_TRACENR char *name; + FILE *out = 0; #endif switch (tstartPhase) { case ZSTART_PHASE1: @@ -480,8 +510,14 @@ void Dblqh::execSTTOR(Signal* signal) sendsttorryLab(signal); #if defined VM_TRACE || defined ERROR_INSERT || defined NDBD_TRACENR - name = NdbConfig_SignalLogFileName(getOwnNodeId()); - tracenrout = new NdbOut(* new FileOutputStream(fopen(name, "w+"))); +#ifdef VM_TRACE + out = globalSignalLoggers.getOutputStream(); +#endif + if (out == 0) { + name = NdbConfig_SignalLogFileName(getOwnNodeId()); + out = fopen(name, "a"); + } + tracenrout = new NdbOut(* new FileOutputStream(out)); #endif #ifdef ERROR_INSERT @@ -15658,24 +15694,23 @@ void Dblqh::srFourthComp(Signal* signal) } else if ((cstartType == NodeState::ST_NODE_RESTART) || (cstartType == NodeState::ST_SYSTEM_RESTART)) { jam(); - - + if(cstartType == NodeState::ST_SYSTEM_RESTART) + { + jam(); + if (c_redo_complete_fragments.first(fragptr)) + { + jam(); + signal->theData[0] = ZENABLE_EXPAND_CHECK; + signal->theData[1] = fragptr.i; + sendSignal(DBLQH_REF, GSN_CONTINUEB, signal, 2, JBB); + return; + } + } StartRecConf * conf = (StartRecConf*)signal->getDataPtrSend(); conf->startingNodeId = getOwnNodeId(); sendSignal(cmasterDihBlockref, GSN_START_RECCONF, signal, - StartRecConf::SignalLength, JBB); - - if(cstartType == NodeState::ST_SYSTEM_RESTART){ - c_redo_complete_fragments.first(fragptr); - while(fragptr.i != RNIL){ - signal->theData[0] = fragptr.p->tabRef; - signal->theData[1] = fragptr.p->fragId; - sendSignal(DBACC_REF, GSN_EXPANDCHECK2, signal, 2, JBB); - c_redo_complete_fragments.next(fragptr); - } - c_redo_complete_fragments.remove(); - } + StartRecConf::SignalLength, JBB); } else { ndbrequire(false); }//if diff --git a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp index 9bc916c8c22..3cf62fe08ec 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp +++ b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp @@ -604,6 +604,7 @@ struct Fragrecord { Uint32 currentPageRange; Uint32 rootPageRange; Uint32 noOfPages; + Uint32 noOfVarPages; Uint32 noOfPagesToGrow; DLList<Page>::Head emptyPrimPage; // allocated pages (not init) diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupPageMap.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupPageMap.cpp index 90fdd8c69d7..82bac432545 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupPageMap.cpp +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupPageMap.cpp @@ -351,6 +351,7 @@ void Dbtup::initFragRange(Fragrecord* const regFragPtr) regFragPtr->rootPageRange = RNIL; regFragPtr->currentPageRange = RNIL; regFragPtr->noOfPages = 0; + regFragPtr->noOfVarPages = 0; regFragPtr->noOfPagesToGrow = 2; regFragPtr->nextStartRange = 0; }//initFragRange() diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp index 940ccf54ba7..677eff53559 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp @@ -1135,13 +1135,20 @@ Dbtup::read_pseudo(Uint32 attrId, case AttributeHeader::FRAGMENT: * outBuffer = fragptr.p->fragmentId; return 1; - case AttributeHeader::FRAGMENT_MEMORY: - { - Uint64 tmp= fragptr.p->noOfPages; - tmp*= 32768; - memcpy(outBuffer,&tmp,8); - } - return 2; + case AttributeHeader::FRAGMENT_FIXED_MEMORY: + { + Uint64 tmp= fragptr.p->noOfPages; + tmp*= 32768; + memcpy(outBuffer,&tmp,8); + } + return 2; + case AttributeHeader::FRAGMENT_VARSIZED_MEMORY: + { + Uint64 tmp= fragptr.p->noOfVarPages; + tmp*= 32768; + memcpy(outBuffer,&tmp,8); + } + return 2; case AttributeHeader::ROW_SIZE: * outBuffer = tabptr.p->m_offsets[MM].m_fix_header_size << 2; return 1; diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupVarAlloc.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupVarAlloc.cpp index 52ab66b5c0e..5f6dd68956a 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupVarAlloc.cpp +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupVarAlloc.cpp @@ -302,6 +302,7 @@ Dbtup::get_empty_var_page(Fragrecord* fragPtr) Uint32 cnt; allocConsPages(10, cnt, ptr.i); + fragPtr->noOfVarPages+= cnt; if (unlikely(cnt == 0)) { return RNIL; diff --git a/storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp b/storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp index 70c0fdfc988..de080237668 100644 --- a/storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp +++ b/storage/ndb/src/kernel/blocks/qmgr/Qmgr.hpp @@ -248,6 +248,7 @@ private: void execAPI_FAILCONF(Signal* signal); void execREAD_NODESREQ(Signal* signal); void execSET_VAR_REQ(Signal* signal); + void execAPI_FAILREQ(Signal* signal); void execREAD_NODESREF(Signal* signal); void execREAD_NODESCONF(Signal* signal); diff --git a/storage/ndb/src/kernel/blocks/qmgr/QmgrInit.cpp b/storage/ndb/src/kernel/blocks/qmgr/QmgrInit.cpp index 6ee24561b0a..8ec5e681045 100644 --- a/storage/ndb/src/kernel/blocks/qmgr/QmgrInit.cpp +++ b/storage/ndb/src/kernel/blocks/qmgr/QmgrInit.cpp @@ -81,6 +81,7 @@ Qmgr::Qmgr(Block_context& ctx) addRecSignal(GSN_API_REGREQ, &Qmgr::execAPI_REGREQ); addRecSignal(GSN_API_VERSION_REQ, &Qmgr::execAPI_VERSION_REQ); addRecSignal(GSN_DISCONNECT_REP, &Qmgr::execDISCONNECT_REP); + addRecSignal(GSN_API_FAILREQ, &Qmgr::execAPI_FAILREQ); addRecSignal(GSN_API_FAILCONF, &Qmgr::execAPI_FAILCONF); addRecSignal(GSN_READ_NODESREQ, &Qmgr::execREAD_NODESREQ); addRecSignal(GSN_SET_VAR_REQ, &Qmgr::execSET_VAR_REQ); diff --git a/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp b/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp index 1eac369ec65..0da2de3b7a2 100644 --- a/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp +++ b/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp @@ -438,6 +438,7 @@ void Qmgr::execCONNECT_REP(Signal* signal) void Qmgr::execREAD_NODESCONF(Signal* signal) { + jamEntry(); check_readnodes_reply(signal, refToNode(signal->getSendersBlockRef()), GSN_READ_NODESCONF); @@ -446,6 +447,7 @@ Qmgr::execREAD_NODESCONF(Signal* signal) void Qmgr::execREAD_NODESREF(Signal* signal) { + jamEntry(); check_readnodes_reply(signal, refToNode(signal->getSendersBlockRef()), GSN_READ_NODESREF); @@ -907,9 +909,9 @@ retry: char buf[255]; BaseString::snprintf(buf, sizeof(buf), - "Partitioned cluster! check StartPartialTimeout, " - " node %d thinks %d is president, " - " I think president is: %d", + "check StartPartialTimeout, " + "node %d thinks %d is president, " + "I think president is: %d", nodeId, president, cpresident); ndbout_c(buf); @@ -941,7 +943,7 @@ retry: CRASH_INSERTION(932); progError(__LINE__, - NDBD_EXIT_ARBIT_SHUTDOWN, + NDBD_EXIT_PARTITIONED_SHUTDOWN, buf); ndbrequire(false); @@ -2338,6 +2340,8 @@ void Qmgr::sendApiFailReq(Signal* signal, Uint16 failedNodeNo) ndbrequire(failedNodePtr.p->failState == NORMAL); failedNodePtr.p->failState = WAITING_FOR_FAILCONF1; + NodeReceiverGroup rg(QMGR, c_clusterNodes); + sendSignal(rg, GSN_API_FAILREQ, signal, 2, JBA); sendSignal(DBTC_REF, GSN_API_FAILREQ, signal, 2, JBA); sendSignal(DBDICT_REF, GSN_API_FAILREQ, signal, 2, JBA); sendSignal(SUMA_REF, GSN_API_FAILREQ, signal, 2, JBA); @@ -2361,6 +2365,27 @@ void Qmgr::sendApiFailReq(Signal* signal, Uint16 failedNodeNo) CloseComReqConf::SignalLength, JBA); }//Qmgr::sendApiFailReq() +void Qmgr::execAPI_FAILREQ(Signal* signal) +{ + jamEntry(); + NodeRecPtr failedNodePtr; + failedNodePtr.i = signal->theData[0]; + // signal->theData[1] == QMGR_REF + ptrCheckGuard(failedNodePtr, MAX_NODES, nodeRec); + + ndbrequire(getNodeInfo(failedNodePtr.i).getType() != NodeInfo::DB); + + // ignore if api not active + if (failedNodePtr.p->phase != ZAPI_ACTIVE) + return; + + signal->theData[0] = NDB_LE_Disconnected; + signal->theData[1] = failedNodePtr.i; + sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB); + + node_failed(signal, failedNodePtr.i); +} + void Qmgr::execAPI_FAILCONF(Signal* signal) { NodeRecPtr failedNodePtr; @@ -2798,7 +2823,7 @@ void Qmgr::failReportLab(Signal* signal, Uint16 aFailedNode, break; case FailRep::ZPARTITIONED_CLUSTER: { - code = NDBD_EXIT_ARBIT_SHUTDOWN; + code = NDBD_EXIT_PARTITIONED_SHUTDOWN; char buf1[100], buf2[100]; c_clusterNodes.getText(buf1); if (signal->getLength()== FailRep::SignalLength + FailRep::ExtraLength && @@ -2809,16 +2834,14 @@ void Qmgr::failReportLab(Signal* signal, Uint16 aFailedNode, part.assign(NdbNodeBitmask::Size, rep->partition); part.getText(buf2); BaseString::snprintf(extra, sizeof(extra), - "Partitioned cluster!" - " Our cluster: %s other cluster: %s", + "Our cluster: %s other cluster: %s", buf1, buf2); } else { jam(); BaseString::snprintf(extra, sizeof(extra), - "Partitioned cluster!" - " Our cluster: %s ", buf1); + "Our cluster: %s", buf1); } msg = extra; break; diff --git a/storage/ndb/src/kernel/blocks/suma/Suma.cpp b/storage/ndb/src/kernel/blocks/suma/Suma.cpp index 42666a9e5d9..2b746fdbdd8 100644 --- a/storage/ndb/src/kernel/blocks/suma/Suma.cpp +++ b/storage/ndb/src/kernel/blocks/suma/Suma.cpp @@ -1445,12 +1445,13 @@ Suma::initTable(Signal *signal, Uint32 tableId, TablePtr &tabPtr) tabPtr.p->m_error = 0; tabPtr.p->m_schemaVersion = RNIL; tabPtr.p->m_state = Table::DEFINING; - tabPtr.p->m_hasTriggerDefined[0] = 0; - tabPtr.p->m_hasTriggerDefined[1] = 0; - tabPtr.p->m_hasTriggerDefined[2] = 0; - tabPtr.p->m_triggerIds[0] = ILLEGAL_TRIGGER_ID; - tabPtr.p->m_triggerIds[1] = ILLEGAL_TRIGGER_ID; - tabPtr.p->m_triggerIds[2] = ILLEGAL_TRIGGER_ID; + tabPtr.p->m_drop_subbPtr.p = 0; + for (int j= 0; j < 3; j++) + { + tabPtr.p->m_hasTriggerDefined[j] = 0; + tabPtr.p->m_hasOutstandingTriggerReq[j] = 0; + tabPtr.p->m_triggerIds[j] = ILLEGAL_TRIGGER_ID; + } c_tables.add(tabPtr); @@ -2491,6 +2492,13 @@ Suma::execSUB_STOP_REQ(Signal* signal){ DBUG_VOID_RETURN; } + if (tabPtr.p->m_drop_subbPtr.p != 0) { + jam(); + DBUG_PRINT("error", ("table locked")); + sendSubStopRef(signal, 1420); + DBUG_VOID_RETURN; + } + DBUG_PRINT("info",("subscription: %u tableId: %u[i=%u] id: %u key: %u", subPtr.i, subPtr.p->m_tableId, tabPtr.i, subPtr.p->m_subscriptionId,subPtr.p->m_subscriptionKey)); @@ -2543,7 +2551,7 @@ Suma::execSUB_STOP_REQ(Signal* signal){ subPtr.p->m_senderRef = senderRef; // store ref to requestor subPtr.p->m_senderData = senderData; // store ref to requestor - tabPtr.p->m_drop_subbPtr= subbPtr; + tabPtr.p->m_drop_subbPtr = subbPtr; if (subPtr.p->m_state == Subscription::DEFINED) { @@ -2560,6 +2568,7 @@ Suma::execSUB_STOP_REQ(Signal* signal){ tabPtr.p->m_tableId, tabPtr.p->n_subscribers)); tabPtr.p->checkRelease(*this); sendSubStopComplete(signal, tabPtr.p->m_drop_subbPtr); + tabPtr.p->m_drop_subbPtr.p = 0; } else { @@ -2667,7 +2676,8 @@ Suma::reportAllSubscribers(Signal *signal, { SubTableData * data = (SubTableData*)signal->getDataPtrSend(); - if (table_event == NdbDictionary::Event::_TE_SUBSCRIBE) + if (table_event == NdbDictionary::Event::_TE_SUBSCRIBE && + !c_startup.m_restart_server_node_id) { data->gci = m_last_complete_gci + 1; data->tableId = subPtr.p->m_tableId; @@ -2893,6 +2903,9 @@ Suma::Table::dropTrigger(Signal* signal,Suma& suma) jam(); DBUG_ENTER("Suma::dropTrigger"); + m_hasOutstandingTriggerReq[0] = + m_hasOutstandingTriggerReq[1] = + m_hasOutstandingTriggerReq[2] = 1; for(Uint32 j = 0; j<3; j++){ jam(); suma.suma_ndbrequire(m_triggerIds[j] != ILLEGAL_TRIGGER_ID); @@ -2971,14 +2984,18 @@ Suma::Table::runDropTrigger(Signal* signal, suma.suma_ndbrequire(type < 3); suma.suma_ndbrequire(m_triggerIds[type] == triggerId); + suma.suma_ndbrequire(m_hasTriggerDefined[type] > 0); + suma.suma_ndbrequire(m_hasOutstandingTriggerReq[type] == 1); m_hasTriggerDefined[type]--; + m_hasOutstandingTriggerReq[type] = 0; if (m_hasTriggerDefined[type] == 0) { jam(); m_triggerIds[type] = ILLEGAL_TRIGGER_ID; } - if( m_hasTriggerDefined[0] != m_hasTriggerDefined[1] || - m_hasTriggerDefined[0] != m_hasTriggerDefined[2]) + if( m_hasOutstandingTriggerReq[0] || + m_hasOutstandingTriggerReq[1] || + m_hasOutstandingTriggerReq[2]) { // more to come jam(); @@ -2996,6 +3013,7 @@ Suma::Table::runDropTrigger(Signal* signal, checkRelease(suma); suma.sendSubStopComplete(signal, m_drop_subbPtr); + m_drop_subbPtr.p = 0; } void Suma::suma_ndbrequire(bool v) { ndbrequire(v); } @@ -3550,13 +3568,17 @@ Suma::execDROP_TAB_CONF(Signal *signal) DBUG_PRINT("info",("drop table id: %d[i=%u]", tableId, tabPtr.i)); tabPtr.p->m_state = Table::DROPPED; - tabPtr.p->m_hasTriggerDefined[0] = 0; - tabPtr.p->m_hasTriggerDefined[1] = 0; - tabPtr.p->m_hasTriggerDefined[2] = 0; - tabPtr.p->m_triggerIds[0] = ILLEGAL_TRIGGER_ID; - tabPtr.p->m_triggerIds[1] = ILLEGAL_TRIGGER_ID; - tabPtr.p->m_triggerIds[2] = ILLEGAL_TRIGGER_ID; - + for (int j= 0; j < 3; j++) + { + if (!tabPtr.p->m_hasOutstandingTriggerReq[j]) + { + tabPtr.p->m_hasTriggerDefined[j] = 0; + tabPtr.p->m_hasOutstandingTriggerReq[j] = 0; + tabPtr.p->m_triggerIds[j] = ILLEGAL_TRIGGER_ID; + } + else + tabPtr.p->m_hasTriggerDefined[j] = 1; + } if (senderRef == 0) { DBUG_VOID_RETURN; diff --git a/storage/ndb/src/kernel/blocks/suma/Suma.hpp b/storage/ndb/src/kernel/blocks/suma/Suma.hpp index 51f5fa4a8c8..4408d6aff8d 100644 --- a/storage/ndb/src/kernel/blocks/suma/Suma.hpp +++ b/storage/ndb/src/kernel/blocks/suma/Suma.hpp @@ -301,7 +301,8 @@ public: union { Uint32 m_tableId; Uint32 key; }; Uint32 m_schemaVersion; - Uint32 m_hasTriggerDefined[3]; // Insert/Update/Delete + Uint8 m_hasTriggerDefined[3]; // Insert/Update/Delete + Uint8 m_hasOutstandingTriggerReq[3]; // Insert/Update/Delete Uint32 m_triggerIds[3]; // Insert/Update/Delete Uint32 m_error; diff --git a/storage/ndb/src/kernel/error/ndbd_exit_codes.c b/storage/ndb/src/kernel/error/ndbd_exit_codes.c index 172125c35a1..2c32c31a15f 100644 --- a/storage/ndb/src/kernel/error/ndbd_exit_codes.c +++ b/storage/ndb/src/kernel/error/ndbd_exit_codes.c @@ -54,6 +54,8 @@ static const ErrStruct errArray[] = {NDBD_EXIT_ARBIT_SHUTDOWN, XAE, "Node lost connection to other nodes and " "can not form a unpartitioned cluster, please investigate if there are " "error(s) on other node(s)"}, + {NDBD_EXIT_PARTITIONED_SHUTDOWN, XAE, "Partitioned cluster detected. " + "Please check if cluster is already running"}, {NDBD_EXIT_POINTER_NOTINRANGE, XIE, "Pointer too large"}, {NDBD_EXIT_SR_OTHERNODEFAILED, XRE, "Another node failed during system " "restart, please investigate error(s) on other node(s)"}, diff --git a/storage/ndb/src/kernel/vm/SimulatedBlock.cpp b/storage/ndb/src/kernel/vm/SimulatedBlock.cpp index 1de47197867..4e01038d343 100644 --- a/storage/ndb/src/kernel/vm/SimulatedBlock.cpp +++ b/storage/ndb/src/kernel/vm/SimulatedBlock.cpp @@ -921,6 +921,15 @@ SimulatedBlock::execCONTINUE_FRAGMENTED(Signal * signal){ void SimulatedBlock::execNODE_START_REP(Signal* signal) { + // common stuff for all blocks + + // block specific stuff by virtual method override (default empty) + exec_node_start_rep(signal); +} + +void +SimulatedBlock::exec_node_start_rep(Signal* signal) +{ } void diff --git a/storage/ndb/src/kernel/vm/SimulatedBlock.hpp b/storage/ndb/src/kernel/vm/SimulatedBlock.hpp index ab698f7826c..3e90b20705e 100644 --- a/storage/ndb/src/kernel/vm/SimulatedBlock.hpp +++ b/storage/ndb/src/kernel/vm/SimulatedBlock.hpp @@ -446,7 +446,8 @@ private: void execCONTINUE_FRAGMENTED(Signal* signal); void execAPI_START_REP(Signal* signal); void execNODE_START_REP(Signal* signal); - + virtual void exec_node_start_rep(Signal* signal); + Uint32 c_fragmentIdCounter; ArrayPool<FragmentInfo> c_fragmentInfoPool; DLHashTable<FragmentInfo> c_fragmentInfoHash; diff --git a/storage/ndb/src/ndbapi/ClusterMgr.cpp b/storage/ndb/src/ndbapi/ClusterMgr.cpp index 63fdb73c49f..49815ae6c13 100644 --- a/storage/ndb/src/ndbapi/ClusterMgr.cpp +++ b/storage/ndb/src/ndbapi/ClusterMgr.cpp @@ -396,6 +396,8 @@ ClusterMgr::execNF_COMPLETEREP(const Uint32 * theData){ void ClusterMgr::reportConnected(NodeId nodeId){ + DBUG_ENTER("ClusterMgr::reportConnected"); + DBUG_PRINT("info", ("nodeId: %u", nodeId)); /** * Ensure that we are sending heartbeat every 100 ms * until we have got the first reply from NDB providing @@ -421,6 +423,7 @@ ClusterMgr::reportConnected(NodeId nodeId){ theNode.nfCompleteRep = true; theFacade.ReportNodeAlive(nodeId); + DBUG_VOID_RETURN; } void diff --git a/storage/ndb/src/ndbapi/DictCache.cpp b/storage/ndb/src/ndbapi/DictCache.cpp index 8a0bf2f8e8b..c06bb6fc62a 100644 --- a/storage/ndb/src/ndbapi/DictCache.cpp +++ b/storage/ndb/src/ndbapi/DictCache.cpp @@ -312,12 +312,15 @@ GlobalDictCache::invalidate_all() if (vers->size()) { TableVersion * ver = & vers->back(); - ver->m_impl->m_status = NdbDictionary::Object::Invalid; - ver->m_status = DROPPED; - if (ver->m_refCount == 0) + if (ver->m_status != RETREIVING) { - delete ver->m_impl; - vers->erase(vers->size() - 1); + ver->m_impl->m_status = NdbDictionary::Object::Invalid; + ver->m_status = DROPPED; + if (ver->m_refCount == 0) + { + delete ver->m_impl; + vers->erase(vers->size() - 1); + } } } curr = m_tableHash.getNext(curr); diff --git a/storage/ndb/src/ndbapi/Ndb.cpp b/storage/ndb/src/ndbapi/Ndb.cpp index 5b0a9e9d330..5eddbc35665 100644 --- a/storage/ndb/src/ndbapi/Ndb.cpp +++ b/storage/ndb/src/ndbapi/Ndb.cpp @@ -1025,14 +1025,19 @@ int Ndb::initAutoIncrement() setDatabaseName("sys"); setDatabaseSchemaName("def"); - m_sys_tab_0 = getDictionary()->getTableGlobal("SYSTAB_0"); + m_sys_tab_0 = theDictionary->getTableGlobal("SYSTAB_0"); // Restore current name space setDatabaseName(currentDb.c_str()); setDatabaseSchemaName(currentSchema.c_str()); + if (m_sys_tab_0 == NULL) { + assert(theDictionary->m_error.code != 0); + theError.code = theDictionary->m_error.code; + return -1; + } - return (m_sys_tab_0 == NULL); + return 0; } int @@ -1043,19 +1048,19 @@ Ndb::opTupleIdOnNdb(const NdbTableImpl* table, Uint32 aTableId = table->m_id; DBUG_PRINT("enter", ("table=%u value=%llu op=%u", aTableId, opValue, op)); - NdbTransaction* tConnection; - NdbOperation* tOperation= 0; // Compiler warning if not initialized + NdbTransaction* tConnection = NULL; + NdbOperation* tOperation = NULL; Uint64 tValue; NdbRecAttr* tRecAttrResult; - CHECK_STATUS_MACRO_ZERO; + CHECK_STATUS_MACRO; - if (initAutoIncrement()) - goto error_return; + if (initAutoIncrement() == -1) + goto error_handler; tConnection = this->startTransaction(); if (tConnection == NULL) - goto error_return; + goto error_handler; tOperation = tConnection->getNdbOperation(m_sys_tab_0); if (tOperation == NULL) @@ -1065,7 +1070,7 @@ Ndb::opTupleIdOnNdb(const NdbTableImpl* table, { case 0: tOperation->interpretedUpdateTuple(); - tOperation->equal("SYSKEY_0", aTableId ); + tOperation->equal("SYSKEY_0", aTableId); tOperation->incValue("NEXTID", opValue); tRecAttrResult = tOperation->getValue("NEXTID"); @@ -1130,14 +1135,21 @@ Ndb::opTupleIdOnNdb(const NdbTableImpl* table, DBUG_RETURN(0); - error_handler: - theError.code = tConnection->theError.code; - this->closeTransaction(tConnection); - error_return: +error_handler: DBUG_PRINT("error", ("ndb=%d con=%d op=%d", theError.code, - tConnection ? tConnection->theError.code : -1, - tOperation ? tOperation->theError.code : -1)); + tConnection != NULL ? tConnection->theError.code : -1, + tOperation != NULL ? tOperation->theError.code : -1)); + + if (theError.code == 0 && tConnection != NULL) + theError.code = tConnection->theError.code; + if (theError.code == 0 && tOperation != NULL) + theError.code = tOperation->theError.code; + DBUG_ASSERT(theError.code != 0); + + if (tConnection != NULL) + this->closeTransaction(tConnection); + DBUG_RETURN(-1); } diff --git a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp index 1e33a843a42..b9c03f0b209 100644 --- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp +++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp @@ -328,9 +328,14 @@ NdbColumnImpl::create_pseudo(const char * name){ col->m_impl.m_attrId = AttributeHeader::FRAGMENT; col->m_impl.m_attrSize = 4; col->m_impl.m_arraySize = 1; - } else if(!strcmp(name, "NDB$FRAGMENT_MEMORY")){ + } else if(!strcmp(name, "NDB$FRAGMENT_FIXED_MEMORY")){ col->setType(NdbDictionary::Column::Bigunsigned); - col->m_impl.m_attrId = AttributeHeader::FRAGMENT_MEMORY; + col->m_impl.m_attrId = AttributeHeader::FRAGMENT_FIXED_MEMORY; + col->m_impl.m_attrSize = 8; + col->m_impl.m_arraySize = 1; + } else if(!strcmp(name, "NDB$FRAGMENT_VARSIZED_MEMORY")){ + col->setType(NdbDictionary::Column::Bigunsigned); + col->m_impl.m_attrId = AttributeHeader::FRAGMENT_VARSIZED_MEMORY; col->m_impl.m_attrSize = 8; col->m_impl.m_arraySize = 1; } else if(!strcmp(name, "NDB$ROW_COUNT")){ @@ -1316,7 +1321,8 @@ NdbDictionaryImpl::~NdbDictionaryImpl() m_globalHash->lock(); if(--f_dictionary_count == 0){ delete NdbDictionary::Column::FRAGMENT; - delete NdbDictionary::Column::FRAGMENT_MEMORY; + delete NdbDictionary::Column::FRAGMENT_FIXED_MEMORY; + delete NdbDictionary::Column::FRAGMENT_VARSIZED_MEMORY; delete NdbDictionary::Column::ROW_COUNT; delete NdbDictionary::Column::COMMIT_COUNT; delete NdbDictionary::Column::ROW_SIZE; @@ -1326,7 +1332,8 @@ NdbDictionaryImpl::~NdbDictionaryImpl() delete NdbDictionary::Column::ROWID; delete NdbDictionary::Column::ROW_GCI; NdbDictionary::Column::FRAGMENT= 0; - NdbDictionary::Column::FRAGMENT_MEMORY= 0; + NdbDictionary::Column::FRAGMENT_FIXED_MEMORY= 0; + NdbDictionary::Column::FRAGMENT_VARSIZED_MEMORY= 0; NdbDictionary::Column::ROW_COUNT= 0; NdbDictionary::Column::COMMIT_COUNT= 0; NdbDictionary::Column::ROW_SIZE= 0; @@ -1483,8 +1490,10 @@ NdbDictionaryImpl::setTransporter(class Ndb* ndb, if(f_dictionary_count++ == 0){ NdbDictionary::Column::FRAGMENT= NdbColumnImpl::create_pseudo("NDB$FRAGMENT"); - NdbDictionary::Column::FRAGMENT_MEMORY= - NdbColumnImpl::create_pseudo("NDB$FRAGMENT_MEMORY"); + NdbDictionary::Column::FRAGMENT_FIXED_MEMORY= + NdbColumnImpl::create_pseudo("NDB$FRAGMENT_FIXED_MEMORY"); + NdbDictionary::Column::FRAGMENT_VARSIZED_MEMORY= + NdbColumnImpl::create_pseudo("NDB$FRAGMENT_VARSIZED_MEMORY"); NdbDictionary::Column::ROW_COUNT= NdbColumnImpl::create_pseudo("NDB$ROW_COUNT"); NdbDictionary::Column::COMMIT_COUNT= @@ -5041,7 +5050,8 @@ template class Vector<NdbTableImpl*>; template class Vector<NdbColumnImpl*>; const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT = 0; -const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT_MEMORY = 0; +const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT_FIXED_MEMORY = 0; +const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT_VARSIZED_MEMORY = 0; const NdbDictionary::Column * NdbDictionary::Column::ROW_COUNT = 0; const NdbDictionary::Column * NdbDictionary::Column::COMMIT_COUNT = 0; const NdbDictionary::Column * NdbDictionary::Column::ROW_SIZE = 0; diff --git a/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp b/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp index 6f096046440..06b0d7ea5b9 100644 --- a/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp +++ b/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp @@ -942,6 +942,7 @@ NdbEventBuffer::NdbEventBuffer(Ndb *ndb) : { #ifdef VM_TRACE m_latest_command= "NdbEventBuffer::NdbEventBuffer"; + m_flush_gci = 0; #endif if ((p_cond = NdbCondition_Create()) == NULL) { @@ -1109,6 +1110,8 @@ NdbEventBuffer::flushIncompleteEvents(Uint64 gci) /** * Find min complete gci */ + // called by user thread, so we need to lock the data + lock(); Uint32 i; Uint32 sz= m_active_gci.size(); Gci_container* array = (Gci_container*)m_active_gci.getBase(); @@ -1127,6 +1130,10 @@ NdbEventBuffer::flushIncompleteEvents(Uint64 gci) bzero(tmp, sizeof(Gci_container)); } } +#ifdef VM_TRACE + m_flush_gci = gci; +#endif + unlock(); return 0; } @@ -1301,7 +1308,11 @@ operator<<(NdbOut& out, const Gci_container_pod& gci) static Gci_container* -find_bucket_chained(Vector<Gci_container_pod> * active, Uint64 gci) +find_bucket_chained(Vector<Gci_container_pod> * active, Uint64 gci +#ifdef VM_TRACE + ,Uint64 flush_gci +#endif + ) { Uint32 pos = (gci & ACTIVE_GCI_MASK); Gci_container *bucket= ((Gci_container*)active->getBase()) + pos; @@ -1322,6 +1333,13 @@ find_bucket_chained(Vector<Gci_container_pod> * active, Uint64 gci) bzero(bucket, sizeof(Gci_container)); bucket->m_gci = gci; bucket->m_gcp_complete_rep_count = ~(Uint32)0; +#ifdef VM_TRACE + if (gci < flush_gci) + { + ndbout_c("received old gci %llu < flush gci %llu", gci, flush_gci); + assert(false); + } +#endif return bucket; } move_pos += ACTIVE_GCI_DIRECTORY_SIZE; @@ -1336,7 +1354,16 @@ find_bucket_chained(Vector<Gci_container_pod> * active, Uint64 gci) bucket += ACTIVE_GCI_DIRECTORY_SIZE; if(bucket->m_gci == gci) + { +#ifdef VM_TRACE + if (gci < flush_gci) + { + ndbout_c("received old gci %llu < flush gci %llu", gci, flush_gci); + assert(false); + } +#endif return bucket; + } } while(pos < size); @@ -1346,14 +1373,22 @@ find_bucket_chained(Vector<Gci_container_pod> * active, Uint64 gci) inline Gci_container* -find_bucket(Vector<Gci_container_pod> * active, Uint64 gci) +find_bucket(Vector<Gci_container_pod> * active, Uint64 gci +#ifdef VM_TRACE + ,Uint64 flush_gci +#endif + ) { Uint32 pos = (gci & ACTIVE_GCI_MASK); Gci_container *bucket= ((Gci_container*)active->getBase()) + pos; if(likely(gci == bucket->m_gci)) return bucket; - return find_bucket_chained(active,gci); + return find_bucket_chained(active,gci +#ifdef VM_TRACE + , flush_gci +#endif + ); } static @@ -1386,7 +1421,11 @@ NdbEventBuffer::execSUB_GCP_COMPLETE_REP(const SubGcpCompleteRep * const rep) const Uint64 gci= rep->gci; const Uint32 cnt= rep->gcp_complete_rep_count; - Gci_container *bucket = find_bucket(&m_active_gci, gci); + Gci_container *bucket = find_bucket(&m_active_gci, gci +#ifdef VM_TRACE + , m_flush_gci +#endif + ); if (unlikely(bucket == 0)) { @@ -1522,6 +1561,46 @@ NdbEventBuffer::complete_outof_order_gcis() } void +NdbEventBuffer::report_node_connected(Uint32 node_id) +{ + NdbEventOperation* op= m_ndb->getEventOperation(0); + if (op == 0) + return; + + DBUG_ENTER("NdbEventBuffer::report_node_connected"); + SubTableData data; + LinearSectionPtr ptr[3]; + bzero(&data, sizeof(data)); + bzero(ptr, sizeof(ptr)); + + data.tableId = ~0; + data.operation = NdbDictionary::Event::_TE_ACTIVE; + data.req_nodeid = (Uint8)node_id; + data.ndbd_nodeid = (Uint8)node_id; + data.logType = SubTableData::LOG; + data.gci = m_latestGCI + 1; + /** + * Insert this event for each operation + */ + { + // no need to lock()/unlock(), receive thread calls this + NdbEventOperationImpl* impl = &op->m_impl; + do if (!impl->m_node_bit_mask.isclear()) + { + data.senderData = impl->m_oid; + insertDataL(impl, &data, ptr); + } while((impl = impl->m_next)); + for (impl = m_dropped_ev_op; impl; impl = impl->m_next) + if (!impl->m_node_bit_mask.isclear()) + { + data.senderData = impl->m_oid; + insertDataL(impl, &data, ptr); + } + } + DBUG_VOID_RETURN; +} + +void NdbEventBuffer::report_node_failure(Uint32 node_id) { NdbEventOperation* op= m_ndb->getEventOperation(0); @@ -1579,6 +1658,10 @@ NdbEventBuffer::completeClusterFailed() data.logType = SubTableData::LOG; data.gci = m_latestGCI + 1; +#ifdef VM_TRACE + m_flush_gci = 0; +#endif + /** * Insert this event for each operation */ @@ -1712,7 +1795,11 @@ NdbEventBuffer::insertDataL(NdbEventOperationImpl *op, if ( likely((Uint32)op->mi_type & (1 << (Uint32)sdata->operation)) ) { - Gci_container* bucket= find_bucket(&m_active_gci, gci); + Gci_container* bucket= find_bucket(&m_active_gci, gci +#ifdef VM_TRACE + , m_flush_gci +#endif + ); DBUG_PRINT_EVENT("info", ("data insertion in eventId %d", op->m_eventId)); DBUG_PRINT_EVENT("info", ("gci=%d tab=%d op=%d node=%d", diff --git a/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp b/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp index c14ca83128f..561e79a137e 100644 --- a/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp +++ b/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp @@ -422,6 +422,7 @@ public: void execSUB_GCP_COMPLETE_REP(const SubGcpCompleteRep * const rep); void complete_outof_order_gcis(); + void report_node_connected(Uint32 node_id); void report_node_failure(Uint32 node_id); void completeClusterFailed(); @@ -462,6 +463,7 @@ public: #ifdef VM_TRACE const char *m_latest_command; + Uint64 m_flush_gci; #endif Ndb *m_ndb; diff --git a/storage/ndb/src/ndbapi/NdbScanOperation.cpp b/storage/ndb/src/ndbapi/NdbScanOperation.cpp index 5852570a686..21caf8349b6 100644 --- a/storage/ndb/src/ndbapi/NdbScanOperation.cpp +++ b/storage/ndb/src/ndbapi/NdbScanOperation.cpp @@ -1574,62 +1574,6 @@ NdbScanOperation::close_impl(TransporterFacade* tp, bool forceSend, return -1; } - bool holdLock = false; - if (theSCAN_TABREQ) - { - ScanTabReq * req = CAST_PTR(ScanTabReq, theSCAN_TABREQ->getDataPtrSend()); - holdLock = ScanTabReq::getHoldLockFlag(req->requestInfo); - } - - /** - * When using locks, force close of scan directly - */ - if (holdLock && theError.code == 0 && - (m_sent_receivers_count + m_conf_receivers_count + m_api_receivers_count)) - { - NdbApiSignal tSignal(theNdb->theMyRef); - tSignal.setSignal(GSN_SCAN_NEXTREQ); - - Uint32* theData = tSignal.getDataPtrSend(); - Uint64 transId = theNdbCon->theTransactionId; - theData[0] = theNdbCon->theTCConPtr; - theData[1] = 1; - theData[2] = transId; - theData[3] = (Uint32) (transId >> 32); - - tSignal.setLength(4); - int ret = tp->sendSignal(&tSignal, nodeId); - if (ret) - { - setErrorCode(4008); - return -1; - } - - /** - * If no receiver is outstanding... - * set it to 1 as execCLOSE_SCAN_REP resets it - */ - m_sent_receivers_count = m_sent_receivers_count ? m_sent_receivers_count : 1; - - while(theError.code == 0 && (m_sent_receivers_count + m_conf_receivers_count)) - { - int return_code = poll_guard->wait_scan(WAITFOR_SCAN_TIMEOUT, nodeId, forceSend); - switch(return_code){ - case 0: - break; - case -1: - setErrorCode(4008); - case -2: - m_api_receivers_count = 0; - m_conf_receivers_count = 0; - m_sent_receivers_count = 0; - theNdbCon->theReleaseOnClose = true; - return -1; - } - } - return 0; - } - /** * Wait for outstanding */ diff --git a/storage/ndb/src/ndbapi/Ndbif.cpp b/storage/ndb/src/ndbapi/Ndbif.cpp index ecaf6a3f435..0527744afe1 100644 --- a/storage/ndb/src/ndbapi/Ndbif.cpp +++ b/storage/ndb/src/ndbapi/Ndbif.cpp @@ -177,6 +177,7 @@ Ndb::executeMessage(void* NdbObject, void Ndb::connected(Uint32 ref) { +// cluster connect, a_node == own reference theMyRef= ref; Uint32 tmpTheNode= refToNode(ref); Uint64 tBlockNo= refToBlock(ref); @@ -209,16 +210,30 @@ void Ndb::connected(Uint32 ref) theNode= tmpTheNode; // flag that Ndb object is initialized } +void Ndb::report_node_connected(Uint32 nodeId) +{ + if (theEventBuffer) + { + // node connected + // eventOperations in the ndb object should be notified + theEventBuffer->report_node_connected(nodeId); + } +} + void Ndb::statusMessage(void* NdbObject, Uint32 a_node, bool alive, bool nfComplete) { DBUG_ENTER("Ndb::statusMessage"); + DBUG_PRINT("info", ("a_node: %u alive: %u nfComplete: %u", + a_node, alive, nfComplete)); Ndb* tNdb = (Ndb*)NdbObject; if (alive) { if (nfComplete) { + // cluster connect, a_node == own reference tNdb->connected(a_node); DBUG_VOID_RETURN; }//if + tNdb->report_node_connected(a_node); } else { if (nfComplete) { tNdb->report_node_failure_completed(a_node); diff --git a/storage/ndb/src/ndbapi/TransporterFacade.cpp b/storage/ndb/src/ndbapi/TransporterFacade.cpp index 15127953051..2f421271e91 100644 --- a/storage/ndb/src/ndbapi/TransporterFacade.cpp +++ b/storage/ndb/src/ndbapi/TransporterFacade.cpp @@ -794,6 +794,8 @@ TransporterFacade::connected() void TransporterFacade::ReportNodeDead(NodeId tNodeId) { + DBUG_ENTER("TransporterFacade::ReportNodeDead"); + DBUG_PRINT("enter",("nodeid= %d", tNodeId)); /** * When a node fails we must report this to each Ndb object. * The function that is used for communicating node failures is called. @@ -810,6 +812,7 @@ TransporterFacade::ReportNodeDead(NodeId tNodeId) (*RegPC) (obj, tNodeId, false, false); } } + DBUG_VOID_RETURN; } void diff --git a/storage/ndb/src/ndbapi/ndberror.c b/storage/ndb/src/ndbapi/ndberror.c index 486d78538f0..d0d26c19cfa 100644 --- a/storage/ndb/src/ndbapi/ndberror.c +++ b/storage/ndb/src/ndbapi/ndberror.c @@ -484,6 +484,8 @@ ErrorBundle ErrorCodes[] = { { 1418, DMEC, SE, "Subscription dropped, no new subscribers allowed" }, { 1419, DMEC, SE, "Subscription already dropped" }, + { 1420, DMEC, TR, "Subscriber manager busy with adding/removing a table" }, + { 4004, DMEC, AE, "Attribute name not found in the Table" }, { 4100, DMEC, AE, "Status Error in NDB" }, diff --git a/storage/ndb/test/ndbapi/testNodeRestart.cpp b/storage/ndb/test/ndbapi/testNodeRestart.cpp index 5474837228a..ad1ea5ed6f2 100644 --- a/storage/ndb/test/ndbapi/testNodeRestart.cpp +++ b/storage/ndb/test/ndbapi/testNodeRestart.cpp @@ -294,6 +294,7 @@ int runRestarts(NDBT_Context* ctx, NDBT_Step* step){ } i++; } + ctx->stopTest(); return result; } diff --git a/storage/ndb/test/run-test/daily-basic-tests.txt b/storage/ndb/test/run-test/daily-basic-tests.txt index 8d893f11288..68e653b1ead 100644 --- a/storage/ndb/test/run-test/daily-basic-tests.txt +++ b/storage/ndb/test/run-test/daily-basic-tests.txt @@ -531,6 +531,10 @@ max-time: 1500 cmd: testDict args: -n TemporaryTables T1 T6 T7 T8 +max-time: 1500 +cmd: testDict +args: -n Restart_NR2 T1 + # # TEST NDBAPI # diff --git a/storage/ndb/tools/desc.cpp b/storage/ndb/tools/desc.cpp index 7c5ce68c950..49f188d12c0 100644 --- a/storage/ndb/tools/desc.cpp +++ b/storage/ndb/tools/desc.cpp @@ -293,7 +293,8 @@ void print_part_info(Ndb* pNdb, NDBT_Table* pTab) { "Partition", 0, NdbDictionary::Column::FRAGMENT }, { "Row count", 0, NdbDictionary::Column::ROW_COUNT }, { "Commit count", 0, NdbDictionary::Column::COMMIT_COUNT }, - { "Frag memory", 0, NdbDictionary::Column::FRAGMENT_MEMORY }, + { "Frag fixed memory", 0, NdbDictionary::Column::FRAGMENT_FIXED_MEMORY }, + { "Frag varsized memory", 0, NdbDictionary::Column::FRAGMENT_VARSIZED_MEMORY }, { 0, 0, 0 } }; diff --git a/storage/ndb/tools/restore/consumer_restore.cpp b/storage/ndb/tools/restore/consumer_restore.cpp index b190652232e..6f9b025222c 100644 --- a/storage/ndb/tools/restore/consumer_restore.cpp +++ b/storage/ndb/tools/restore/consumer_restore.cpp @@ -148,17 +148,38 @@ BackupRestore::finalize_table(const TableS & table){ bool ret= true; if (!m_restore && !m_restore_meta) return ret; - if (table.have_auto_inc()) + if (!table.have_auto_inc()) + return ret; + + Uint64 max_val= table.get_max_auto_val(); + do { - Uint64 max_val= table.get_max_auto_val(); - Uint64 auto_val; + Uint64 auto_val = ~(Uint64)0; int r= m_ndb->readAutoIncrementValue(get_table(table.m_dictTable), auto_val); - if (r == -1 && m_ndb->getNdbError().code != 626) + if (r == -1 && m_ndb->getNdbError().status == NdbError::TemporaryError) + { + NdbSleep_MilliSleep(50); + continue; // retry + } + else if (r == -1 && m_ndb->getNdbError().code != 626) + { ret= false; - else if (r == -1 || max_val+1 > auto_val) - ret= m_ndb->setAutoIncrementValue(get_table(table.m_dictTable), max_val+1, false) != -1; - } - return ret; + } + else if ((r == -1 && m_ndb->getNdbError().code == 626) || + max_val+1 > auto_val || auto_val == ~(Uint64)0) + { + r= m_ndb->setAutoIncrementValue(get_table(table.m_dictTable), + max_val+1, false); + if (r == -1 && + m_ndb->getNdbError().status == NdbError::TemporaryError) + { + NdbSleep_MilliSleep(50); + continue; // retry + } + ret = (r == 0); + } + return (ret); + } while (1); } @@ -792,8 +813,6 @@ BackupRestore::table(const TableS & table){ } info << "Successfully restored table event " << event_name << endl ; } - - m_ndb->setAutoIncrementValue(tab, ~(Uint64)0, false); } const NdbDictionary::Table* null = 0; m_new_tables.fill(table.m_dictTable->getTableId(), null); |