diff options
author | unknown <ndbdev@dl145b.mysql.com> | 2005-08-31 20:45:48 +0200 |
---|---|---|
committer | unknown <ndbdev@dl145b.mysql.com> | 2005-08-31 20:45:48 +0200 |
commit | 008f4121d56947245ede878c75bdad9ace25da66 (patch) | |
tree | df48637e985f4d72268ca92076f8628b73b8f077 /storage | |
parent | 5dd6e8776be709bbc04a332f450252383d2568d8 (diff) | |
parent | c6b54efea2f564d7a4d9fda7bc79f2601395250a (diff) | |
download | mariadb-git-008f4121d56947245ede878c75bdad9ace25da66.tar.gz |
merge
BitKeeper/etc/config:
Auto merged
Makefile.am:
Auto merged
VC++Files/sql/mysqld.vcproj:
Auto merged
configure.in:
Auto merged
extra/perror.c:
Auto merged
include/my_global.h:
Auto merged
mysql-test/mysql-test-run.pl:
Auto merged
mysql-test/mysql-test-run.sh:
Auto merged
mysql-test/t/alter_table.test:
Auto merged
mysql-test/t/disabled.def:
Auto merged
mysys/Makefile.am:
Auto merged
scripts/mysql_fix_privilege_tables.sql:
Auto merged
sql/Makefile.am:
Auto merged
sql/ha_innodb.cc:
Auto merged
sql/ha_innodb.h:
Auto merged
sql/handler.h:
Auto merged
sql/item.cc:
Auto merged
sql/lex.h:
Auto merged
sql/log.cc:
Auto merged
sql/log_event.cc:
Auto merged
sql/mysql_priv.h:
Auto merged
sql/mysqld.cc:
Auto merged
sql/opt_range.cc:
Auto merged
sql/set_var.cc:
Auto merged
sql/sp.cc:
Auto merged
sql/sql_class.h:
Auto merged
sql/sql_delete.cc:
Auto merged
sql/sql_insert.cc:
Auto merged
sql/sql_lex.cc:
Auto merged
sql/sql_lex.h:
Auto merged
sql/sql_parse.cc:
Auto merged
sql/sql_select.cc:
Auto merged
sql/sql_show.cc:
Auto merged
sql/sql_table.cc:
Auto merged
sql/sql_update.cc:
Auto merged
sql/examples/ha_tina.cc:
Auto merged
sql/sql_yacc.yy:
Auto merged
sql/table.h:
Auto merged
sql/unireg.h:
Auto merged
storage/innobase/lock/lock0lock.c:
Auto merged
storage/myisam/mi_check.c:
Auto merged
storage/myisam/mi_search.c:
Auto merged
storage/myisam/myisamchk.c:
Auto merged
storage/myisam/myisamlog.c:
Auto merged
storage/myisam/myisampack.c:
Auto merged
storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp:
Auto merged
storage/ndb/src/kernel/blocks/dblqh/redoLogReader/records.cpp:
Auto merged
storage/ndb/src/kernel/blocks/dblqh/redoLogReader/records.hpp:
Auto merged
storage/ndb/src/kernel/blocks/dblqh/redoLogReader/redoLogFileReader.cpp:
Auto merged
Diffstat (limited to 'storage')
-rw-r--r-- | storage/innobase/lock/lock0lock.c | 23 | ||||
-rw-r--r-- | storage/myisam/mi_check.c | 22 | ||||
-rw-r--r-- | storage/myisam/mi_search.c | 32 | ||||
-rw-r--r-- | storage/myisam/myisamchk.c | 11 | ||||
-rw-r--r-- | storage/myisam/myisampack.c | 11 | ||||
-rw-r--r-- | storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp | 10 | ||||
-rw-r--r-- | storage/ndb/src/kernel/blocks/dblqh/redoLogReader/records.cpp | 4 | ||||
-rw-r--r-- | storage/ndb/src/kernel/blocks/dblqh/redoLogReader/records.hpp | 4 | ||||
-rw-r--r-- | storage/ndb/src/kernel/blocks/dblqh/redoLogReader/redoLogFileReader.cpp | 11 |
9 files changed, 96 insertions, 32 deletions
diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index 1f222d71d6a..7844991613f 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -47,6 +47,10 @@ innobase_mysql_end_print_arbitrary_thd(void); graph of transactions */ #define LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK 1000000 +/* Restricts the recursion depth of the search we will do in the waits-for +graph of transactions */ +#define LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK 200 + /* When releasing transaction locks, this specifies how often we release the kernel mutex for a moment to give also others access to it */ @@ -389,9 +393,12 @@ lock_deadlock_recursive( trx_t* start, /* in: recursion starting point */ trx_t* trx, /* in: a transaction waiting for a lock */ lock_t* wait_lock, /* in: the lock trx is waiting to be granted */ - ulint* cost); /* in/out: number of calculation steps thus + ulint* cost, /* in/out: number of calculation steps thus far: if this exceeds LOCK_MAX_N_STEPS_... - we return TRUE */ + we return LOCK_VICTIM_IS_START */ + uint depth); /* in: recursion depth: if this exceeds + LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we + return LOCK_VICTIM_IS_START */ /************************************************************************* Gets the type of a lock. */ @@ -3180,7 +3187,7 @@ retry: mark_trx = UT_LIST_GET_NEXT(trx_list, mark_trx); } - ret = lock_deadlock_recursive(trx, trx, lock, &cost); + ret = lock_deadlock_recursive(trx, trx, lock, &cost, 0); if (ret == LOCK_VICTIM_IS_OTHER) { /* We chose some other trx as a victim: retry if there still @@ -3226,9 +3233,12 @@ lock_deadlock_recursive( trx_t* start, /* in: recursion starting point */ trx_t* trx, /* in: a transaction waiting for a lock */ lock_t* wait_lock, /* in: the lock trx is waiting to be granted */ - ulint* cost) /* in/out: number of calculation steps thus + ulint* cost, /* in/out: number of calculation steps thus far: if this exceeds LOCK_MAX_N_STEPS_... we return LOCK_VICTIM_IS_START */ + uint depth) /* in: recursion depth: if this exceeds + LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we + return LOCK_VICTIM_IS_START */ { lock_t* lock; ulint bit_no = ULINT_UNDEFINED; @@ -3249,7 +3259,8 @@ lock_deadlock_recursive( *cost = *cost + 1; - if (*cost > LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK) { + if ((depth > LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK) + || (*cost > LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK)) { return(LOCK_VICTIM_IS_START); } @@ -3375,7 +3386,7 @@ lock_deadlock_recursive( a lock */ ret = lock_deadlock_recursive(start, lock_trx, - lock_trx->wait_lock, cost); + lock_trx->wait_lock, cost, depth + 1); if (ret != 0) { return(ret); diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index 1db829808a9..ffb7cdd503f 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -1036,7 +1036,7 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) { if (mi_is_key_active(info->s->state.key_map, key)) { - if(!(keyinfo->flag & HA_FULLTEXT)) + if(!(keyinfo->flag & HA_FULLTEXT)) { uint key_length=_mi_make_key(info,key,info->lastkey,record, start_recpos); @@ -1045,14 +1045,18 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) /* We don't need to lock the key tree here as we don't allow concurrent threads when running myisamchk */ - if (_mi_search(info,keyinfo,info->lastkey,key_length, - SEARCH_SAME, info->s->state.key_root[key])) - { - 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; - } + int search_result= (keyinfo->flag & HA_SPATIAL) ? + rtree_find_first(info, key, info->lastkey, key_length, + SEARCH_SAME) : + _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", + llstr(start_recpos,llbuff),key+1); + if (error++ > MAXERR || !(param->testflag & T_VERBOSE)) + goto err2; + } } else key_checksum[key]+=mi_byte_checksum((byte*) info->lastkey, diff --git a/storage/myisam/mi_search.c b/storage/myisam/mi_search.c index ed61bbfe41a..b7360dba7f3 100644 --- a/storage/myisam/mi_search.c +++ b/storage/myisam/mi_search.c @@ -318,19 +318,21 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, get_key_pack_length(kseg_len,length_pack,kseg); key_len_skip=length_pack+kseg_len; key_len_left=(int) key_len- (int) key_len_skip; + /* If key_len is 0, then lenght_pack is 1, then key_len_left is -1. */ cmplen=(key_len_left>=0) ? kseg_len : key_len-length_pack; DBUG_PRINT("info",("key: '%.*s'",kseg_len,kseg)); /* Keys are compressed the following way: - If the max length of first key segment <= 127 characters the prefix is + If the max length of first key segment <= 127 bytes the prefix is 1 byte else it's 2 byte - prefix The high bit is set if this is a prefix for the prev key - length Packed length if the previous was a prefix byte - [length] Length character of data - next-key-seg Next key segments + (prefix) length The high bit is set if this is a prefix for the prev key. + [suffix length] Packed length of suffix if the previous was a prefix. + (suffix) data Key data bytes (past the common prefix or whole segment). + [next-key-seg] Next key segments (([packed length], data), ...) + pointer Reference to the data file (last_keyseg->length). */ matched=0; /* how many char's from prefix were alredy matched */ @@ -351,16 +353,23 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, if (packed) { - if (suffix_len == 0) /* Same key */ + if (suffix_len == 0) + { + /* == 0x80 or 0x8000, same key, prefix length == old key length. */ prefix_len=len; + } else { + /* > 0x80 or 0x8000, this is prefix lgt, packed suffix lgt follows. */ prefix_len=suffix_len; get_key_length(suffix_len,vseg); } } else + { + /* Not packed. No prefix used from last key. */ prefix_len=0; + } len=prefix_len+suffix_len; seg_len_pack=get_pack_length(len); @@ -417,7 +426,12 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, uint left; uchar *k=kseg+prefix_len; - left=(len>cmplen) ? cmplen-prefix_len : suffix_len; + /* + If prefix_len > cmplen then we are in the end-space comparison + phase. Do not try to acces the key any more ==> left= 0. + */ + left= ((len <= cmplen) ? suffix_len : + ((prefix_len < cmplen) ? cmplen - prefix_len : 0)); matched=prefix_len+left; @@ -455,7 +469,7 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, my_flag= -1; else { - /* We have to compare k and vseg as if they where space extended */ + /* We have to compare k and vseg as if they were space extended */ uchar *end= k+ (cmplen - len); for ( ; k < end && *k == ' '; k++) ; if (k == end) @@ -474,7 +488,7 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, if ((nextflag & SEARCH_PREFIX) && key_len_left == 0) goto fix_flag; - /* We have to compare k and vseg as if they where space extended */ + /* We have to compare k and vseg as if they were space extended */ for (end=vseg + (len-cmplen) ; vseg < end && *vseg == (uchar) ' '; vseg++, matched++) ; diff --git a/storage/myisam/myisamchk.c b/storage/myisam/myisamchk.c index 4856d93b320..78ae756bf7c 100644 --- a/storage/myisam/myisamchk.c +++ b/storage/myisam/myisamchk.c @@ -155,7 +155,7 @@ enum options_mc { OPT_READ_BUFFER_SIZE, OPT_WRITE_BUFFER_SIZE, OPT_SORT_BUFFER_SIZE, OPT_SORT_KEY_BLOCKS, OPT_DECODE_BITS, OPT_FT_MIN_WORD_LEN, OPT_FT_MAX_WORD_LEN, OPT_FT_STOPWORD_FILE, - OPT_MAX_RECORD_LENGTH + OPT_MAX_RECORD_LENGTH, OPT_AUTO_CLOSE }; static struct my_option my_long_options[] = @@ -163,6 +163,10 @@ static struct my_option my_long_options[] = {"analyze", 'a', "Analyze distribution of keys. Will make some joins in MySQL faster. You can check the calculated distribution.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, +#ifdef __NETWARE__ + {"auto-close", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, +#endif {"block-search", 'b', "No help available.", 0, 0, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -469,6 +473,11 @@ get_one_option(int optid, char *argument) { switch (optid) { +#ifdef __NETWARE__ + case OPT_AUTO_CLOSE: + setscreenmode(SCR_AUTOCLOSE_ON_EXIT); + break; +#endif case 'a': if (argument == disabled_my_option) check_param.testflag&= ~T_STATISTICS; diff --git a/storage/myisam/myisampack.c b/storage/myisam/myisampack.c index b3937ab9607..b8f21392f8a 100644 --- a/storage/myisam/myisampack.c +++ b/storage/myisam/myisampack.c @@ -249,10 +249,14 @@ int main(int argc, char **argv) #endif } -enum options_mp {OPT_CHARSETS_DIR_MP=256}; +enum options_mp {OPT_CHARSETS_DIR_MP=256, OPT_AUTO_CLOSE}; static struct my_option my_long_options[] = { +#ifdef __NETWARE__ + {"auto-close", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, +#endif {"backup", 'b', "Make a backup of the table as table_name.OLD.", (gptr*) &backup, (gptr*) &backup, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"character-sets-dir", OPT_CHARSETS_DIR_MP, @@ -321,6 +325,11 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), uint length; switch(optid) { +#ifdef __NETWARE__ + case OPT_AUTO_CLOSE: + setscreenmode(SCR_AUTOCLOSE_ON_EXIT); + break; +#endif case 'f': force_pack= 1; tmpfile_createflag= O_RDWR | O_TRUNC; diff --git a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp index 0a33966ef73..bfd97c6e7d5 100644 --- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp +++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp @@ -389,6 +389,9 @@ void Dbdict::execFSCLOSECONF(Signal* signal) jam(); closeWriteTableConf(signal, fsPtr); break; + case FsConnectRecord::OPEN_READ_SCHEMA2: + openSchemaFile(signal, 1, fsPtr.i, false, false); + break; default: jamLine((fsPtr.p->fsState & 0xFFF)); ndbrequire(false); @@ -1089,10 +1092,13 @@ void Dbdict::readSchemaConf(Signal* signal, void Dbdict::readSchemaRef(Signal* signal, FsConnectRecordPtr fsPtr) { + /** + * First close corrupt file + */ fsPtr.p->fsState = FsConnectRecord::OPEN_READ_SCHEMA2; - openSchemaFile(signal, 1, fsPtr.i, false, false); + closeFile(signal, fsPtr.p->filePtr, fsPtr.i); return; -}//Dbdict::readSchemaRef() +} void Dbdict::closeReadSchemaConf(Signal* signal, FsConnectRecordPtr fsPtr) diff --git a/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/records.cpp b/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/records.cpp index 092b7840c20..63c271d6b80 100644 --- a/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/records.cpp +++ b/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/records.cpp @@ -79,6 +79,7 @@ NdbOut& operator<<(NdbOut& no, const CommitTransactionRecord& ctr) { no << "----------COMMIT TRANSACTION RECORD------------" << endl << endl; printOut("Record type:", ctr.m_recordType); printOut("TableId", ctr.m_tableId); + printOut("SchemaVersion:", ctr.m_schemaVersion); printOut("FfragmentId", ctr.m_fragmentId); printOut("File no. of Prep. Op.", ctr.m_fileNumberOfPrepareOperation); printOut("Start page no. of Prep. Op.", ctr.m_startPageNumberOfPrepareOperation); @@ -127,7 +128,7 @@ bool PrepareOperationRecord::check() { if (m_operationType == 3 && m_attributeLength != 0) return false; - if (m_logRecordSize != (m_attributeLength + m_keyLength + 7)) + if (m_logRecordSize != (m_attributeLength + m_keyLength + 6)) return false; return true; @@ -142,7 +143,6 @@ NdbOut& operator<<(NdbOut& no, const PrepareOperationRecord& por) { printOut("Record type:", por.m_recordType); printOut("logRecordSize:", por.m_logRecordSize); printOut("hashValue:", por.m_hashValue); - printOut("schemaVersion:", por.m_schemaVersion); switch (por.m_operationType) { case 0: ndbout_c("%-30s%-12u%-6s", "operationType:", diff --git a/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/records.hpp b/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/records.hpp index e73986e4d73..27f2399abbe 100644 --- a/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/records.hpp +++ b/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/records.hpp @@ -36,7 +36,7 @@ #define NO_PAGES_IN_MBYTE 32 #define NO_MBYTE_IN_FILE 16 -#define COMMITTRANSACTIONRECORDSIZE 8 +#define COMMITTRANSACTIONRECORDSIZE 9 #define COMPLETEDGCIRECORDSIZE 2 #define PAGEHEADERSIZE 32 #define FILEDESCRIPTORHEADERSIZE 3 @@ -89,7 +89,6 @@ protected: Uint32 m_recordType; Uint32 m_logRecordSize; Uint32 m_hashValue; - Uint32 m_schemaVersion; Uint32 m_operationType; // 0 READ, 1 UPDATE, 2 INSERT, 3 DELETE Uint32 m_attributeLength; Uint32 m_keyLength; @@ -190,6 +189,7 @@ public: protected: Uint32 m_recordType; Uint32 m_tableId; + Uint32 m_schemaVersion; Uint32 m_fragmentId; Uint32 m_fileNumberOfPrepareOperation; Uint32 m_startPageNumberOfPrepareOperation; diff --git a/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/redoLogFileReader.cpp b/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/redoLogFileReader.cpp index 67e59c48ea6..cea05aebc64 100644 --- a/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/redoLogFileReader.cpp +++ b/storage/ndb/src/kernel/blocks/dblqh/redoLogReader/redoLogFileReader.cpp @@ -105,6 +105,7 @@ NDB_COMMAND(redoLogFileReader, "redoLogFileReader", "redoLogFileReader", "Read if (thePrintFlag) ndbout << (*thePageHeader); if (theCheckFlag) { if(!thePageHeader->check()) { + ndbout << "Error in thePageHeader->check()" << endl; doExit(); } @@ -146,6 +147,7 @@ NDB_COMMAND(redoLogFileReader, "redoLogFileReader", "redoLogFileReader", "Read if (thePrintFlag) ndbout << (*fdRecord); if (theCheckFlag) { if(!fdRecord->check()) { + ndbout << "Error in fdRecord->check()" << endl; doExit(); } } @@ -163,6 +165,7 @@ NDB_COMMAND(redoLogFileReader, "redoLogFileReader", "redoLogFileReader", "Read if (thePrintFlag) ndbout << (*nlRecord); if (theCheckFlag) { if(!nlRecord->check()) { + ndbout << "Error in nlRecord->check()" << endl; doExit(); } } @@ -176,6 +179,7 @@ NDB_COMMAND(redoLogFileReader, "redoLogFileReader", "redoLogFileReader", "Read if (thePrintFlag) ndbout << (*cGCIrecord); if (theCheckFlag) { if(!cGCIrecord->check()) { + ndbout << "Error in cGCIrecord->check()" << endl; doExit(); } } @@ -189,6 +193,7 @@ NDB_COMMAND(redoLogFileReader, "redoLogFileReader", "redoLogFileReader", "Read if (thePrintFlag) ndbout << (*poRecord); if (theCheckFlag) { if(!poRecord->check()) { + ndbout << "Error in poRecord->check()" << endl; doExit(); } } @@ -205,6 +210,7 @@ NDB_COMMAND(redoLogFileReader, "redoLogFileReader", "redoLogFileReader", "Read if (thePrintFlag) ndbout << (*ctRecord); if (theCheckFlag) { if(!ctRecord->check()) { + ndbout << "Error in ctRecord->check()" << endl; doExit(); } } @@ -221,6 +227,7 @@ NDB_COMMAND(redoLogFileReader, "redoLogFileReader", "redoLogFileReader", "Read if (thePrintFlag) ndbout << (*ictRecord); if (theCheckFlag) { if(!ictRecord->check()) { + ndbout << "Error in ictRecord->check()" << endl; doExit(); } } @@ -243,6 +250,7 @@ NDB_COMMAND(redoLogFileReader, "redoLogFileReader", "redoLogFileReader", "Read if (thePrintFlag) ndbout << (*atRecord); if (theCheckFlag) { if(!atRecord->check()) { + ndbout << "Error in atRecord->check()" << endl; doExit(); } } @@ -329,6 +337,7 @@ Uint32 readRecordOverPageBoundary(Uint32 *pagePtr, Uint32 pageIndex, Uint32 old if (recordSize < (PAGESIZE - PAGEHEADERSIZE)) { if (theCheckFlag) { if(!poRecord->check()) { + ndbout << "Error in poRecord->check() (readRecordOverPageBoundary)" << endl; doExit(); } } @@ -344,6 +353,7 @@ Uint32 readRecordOverPageBoundary(Uint32 *pagePtr, Uint32 pageIndex, Uint32 old if (recordSize < (PAGESIZE - PAGEHEADERSIZE)) { if (theCheckFlag) { if(!ctRecord->check()) { + ndbout << "Error in ctRecord->check() (readRecordOverPageBoundary)" << endl; doExit(); } } @@ -359,6 +369,7 @@ Uint32 readRecordOverPageBoundary(Uint32 *pagePtr, Uint32 pageIndex, Uint32 old if (recordSize < (PAGESIZE - PAGEHEADERSIZE)) { if (theCheckFlag) { if(!ictRecord->check()) { + ndbout << "Error in ictRecord->check() (readRecordOverPageBoundary)" << endl; doExit(); } } |