BUG#41948 Query_log_event constructor needlessly contorted

Make the caller of Query_log_event, Execute_load_log_event
constructors and THD::binlog_query to provide the error code
instead of having the constructors to figure out the error code.

sql/log_event.cc:
  Changed constructors of Query_log_event and Execute_load_log_event to accept the error code argument instead of figuring it out by itself
sql/log_event.h:
  Changed constructors of Query_log_event and Execute_load_log_event to accept the error code argument
This commit is contained in:
He Zhenxing 2009-05-30 21:32:28 +08:00
parent 88e84c1fbf
commit abf5f8dac2
18 changed files with 133 additions and 83 deletions

View File

@ -1855,9 +1855,11 @@ static void ndb_binlog_query(THD *thd, Cluster_schema *schema)
else
thd->server_id= schema->any_value;
thd->db= schema->db;
int errcode = query_error_code(thd, thd->killed == THD::NOT_KILLED);
thd->binlog_query(THD::STMT_QUERY_TYPE, schema->query,
schema->query_length, FALSE,
schema->name[0] == 0 || thd->db[0] == 0);
schema->name[0] == 0 || thd->db[0] == 0,
errcode);
thd->server_id= thd_server_id_save;
thd->db= thd_db_save;
}

View File

@ -1502,8 +1502,7 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all)
YESNO(thd->transaction.stmt.modified_non_trans_table)));
if (!in_transaction || all)
{
Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE);
qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE)
Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE, 0);
error= binlog_end_trans(thd, trx_data, &qev, all);
goto end;
}
@ -1557,8 +1556,7 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all)
transactional table in that statement as well, which needs to be
rolled back on the slave.
*/
Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, FALSE);
qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE)
Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, FALSE, 0);
error= binlog_end_trans(thd, trx_data, &qev, all);
}
else if (all && !thd->transaction.all.modified_non_trans_table ||
@ -1606,10 +1604,11 @@ static int binlog_savepoint_set(handlerton *hton, THD *thd, void *sv)
binlog_trans_log_savepos(thd, (my_off_t*) sv);
/* Write it to the binary log */
int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED);
int const error=
thd->binlog_query(THD::STMT_QUERY_TYPE,
thd->query, thd->query_length, TRUE, FALSE);
thd->query, thd->query_length, TRUE, FALSE, errcode);
DBUG_RETURN(error);
}
@ -1625,9 +1624,10 @@ static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv)
if (unlikely(thd->transaction.all.modified_non_trans_table ||
(thd->options & OPTION_KEEP_LOG)))
{
int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED);
int error=
thd->binlog_query(THD::STMT_QUERY_TYPE,
thd->query, thd->query_length, TRUE, FALSE);
thd->query, thd->query_length, TRUE, FALSE, errcode);
DBUG_RETURN(error);
}
binlog_trans_log_truncate(thd, *(my_off_t*)sv);
@ -4327,6 +4327,35 @@ int MYSQL_BIN_LOG::write_cache(IO_CACHE *cache, bool lock_log, bool sync_log)
return 0; // All OK
}
/*
Helper function to get the error code of the query to be binlogged.
*/
int query_error_code(THD *thd, bool not_killed)
{
int error;
if (not_killed)
{
error= thd->is_error() ? thd->main_da.sql_errno() : 0;
/* thd->main_da.sql_errno() might be ER_SERVER_SHUTDOWN or
ER_QUERY_INTERRUPTED, So here we need to make sure that error
is not set to these errors when specified not_killed by the
caller.
*/
if (error == ER_SERVER_SHUTDOWN || error == ER_QUERY_INTERRUPTED)
error= 0;
}
else
{
/* killed status for DELAYED INSERT thread should never be used */
DBUG_ASSERT(!(thd->system_thread & SYSTEM_THREAD_DELAYED_INSERT));
error= thd->killed_errno();
}
return error;
}
/**
Write a cached log entry to the binary log.
- To support transaction over replication, we wrap the transaction
@ -4370,19 +4399,8 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event)
transaction is either a BEGIN..COMMIT block or a single
statement in autocommit mode.
*/
Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), TRUE, FALSE);
/*
Imagine this is rollback due to net timeout, after all
statements of the transaction succeeded. Then we want a
zero-error code in BEGIN. In other words, if there was a
really serious error code it's already in the statement's
events, there is no need to put it also in this internally
generated event, and as this event is generated late it would
lead to false alarms.
Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), TRUE, FALSE, 0);
This is safer than thd->clear_error() against kills at shutdown.
*/
qinfo.error_code= 0;
/*
Now this Query_log_event has artificial log_pos 0. It must be
adjusted to reflect the real position in the log. Not doing it

View File

@ -581,4 +581,6 @@ enum enum_binlog_format {
};
extern TYPELIB binlog_format_typelib;
int query_error_code(THD *thd, bool not_killed);
#endif /* LOG_H */

View File

@ -2316,19 +2316,16 @@ Query_log_event::Query_log_event()
query_length - size of the `query_arg' array
using_trans - there is a modified transactional table
suppress_use - suppress the generation of 'USE' statements
killed_status_arg - an optional with default to THD::KILLED_NO_VALUE
if the value is different from the default, the arg
is set to the current thd->killed value.
A caller might need to masquerade thd->killed with
THD::NOT_KILLED.
errcode - the error code of the query
DESCRIPTION
Creates an event for binlogging
The value for local `killed_status' can be supplied by caller.
The value for `errcode' should be supplied by caller.
*/
Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
ulong query_length, bool using_trans,
bool suppress_use,
THD::killed_state killed_status_arg)
bool suppress_use, int errcode)
:Log_event(thd_arg,
(thd_arg->thread_specific_used ? LOG_EVENT_THREAD_SPECIFIC_F :
0) |
@ -2349,22 +2346,7 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
{
time_t end_time;
if (killed_status_arg == THD::KILLED_NO_VALUE)
killed_status_arg= thd_arg->killed;
error_code=
(killed_status_arg == THD::NOT_KILLED) ?
(thd_arg->is_error() ? thd_arg->main_da.sql_errno() : 0) :
((thd_arg->system_thread & SYSTEM_THREAD_DELAYED_INSERT) ? 0 :
thd_arg->killed_errno());
/* thd_arg->main_da.sql_errno() might be ER_SERVER_SHUTDOWN or
ER_QUERY_INTERRUPTED, So here we need to make sure that
error_code is not set to these errors when specified NOT_KILLED
by the caller
*/
if ((killed_status_arg == THD::NOT_KILLED) &&
(error_code == ER_SERVER_SHUTDOWN || error_code == ER_QUERY_INTERRUPTED))
error_code= 0;
error_code= errcode;
time(&end_time);
exec_time = (ulong) (end_time - thd_arg->start_time);
@ -6619,9 +6601,9 @@ Execute_load_query_log_event(THD *thd_arg, const char* query_arg,
uint fn_pos_end_arg,
enum_load_dup_handling dup_handling_arg,
bool using_trans, bool suppress_use,
THD::killed_state killed_err_arg):
int errcode):
Query_log_event(thd_arg, query_arg, query_length_arg, using_trans,
suppress_use, killed_err_arg),
suppress_use, errcode),
file_id(thd_arg->file_id), fn_pos_start(fn_pos_start_arg),
fn_pos_end(fn_pos_end_arg), dup_handling(dup_handling_arg)
{

View File

@ -1623,8 +1623,7 @@ public:
#ifndef MYSQL_CLIENT
Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length,
bool using_trans, bool suppress_use,
THD::killed_state killed_err_arg= THD::KILLED_NO_VALUE);
bool using_trans, bool suppress_use, int error);
const char* get_db() { return db; }
#ifdef HAVE_REPLICATION
void pack_info(Protocol* protocol);
@ -2875,8 +2874,7 @@ public:
uint fn_pos_end_arg,
enum_load_dup_handling dup_handling_arg,
bool using_trans, bool suppress_use,
THD::killed_state
killed_err_arg= THD::KILLED_NO_VALUE);
int errcode);
#ifdef HAVE_REPLICATION
void pack_info(Protocol* protocol);
#endif /* HAVE_REPLICATION */

View File

@ -941,7 +941,7 @@ sp_create_routine(THD *thd, int type, sp_head *sp)
/* Such a statement can always go directly to binlog, no trans cache */
thd->binlog_query(THD::MYSQL_QUERY_TYPE,
log_query.c_ptr(), log_query.length(),
FALSE, FALSE, THD::NOT_KILLED);
FALSE, FALSE, 0);
thd->variables.sql_mode= 0;
}

View File

@ -1779,8 +1779,9 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount,
thd->options= binlog_save_options;
if (thd->binlog_evt_union.unioned_events)
{
int errcode = query_error_code(thd, thd->killed == THD::NOT_KILLED);
Query_log_event qinfo(thd, binlog_buf.ptr(), binlog_buf.length(),
thd->binlog_evt_union.unioned_events_trans, FALSE);
thd->binlog_evt_union.unioned_events_trans, FALSE, errcode);
if (mysql_bin_log.write(&qinfo) &&
thd->binlog_evt_union.unioned_events_trans)
{

View File

@ -1655,7 +1655,7 @@ bool change_password(THD *thd, const char *host, const char *user,
new_password));
thd->clear_error();
thd->binlog_query(THD::MYSQL_QUERY_TYPE, buff, query_length,
FALSE, FALSE, THD::NOT_KILLED);
FALSE, FALSE, 0);
}
end:
close_thread_tables(thd);

View File

@ -1541,7 +1541,7 @@ void close_temporary_tables(THD *thd)
thd->variables.character_set_client= system_charset_info;
Query_log_event qinfo(thd, s_query.ptr(),
s_query.length() - 1 /* to remove trailing ',' */,
0, FALSE, THD::NOT_KILLED);
0, FALSE, 0);
thd->variables.character_set_client= cs_save;
mysql_bin_log.write(&qinfo);
thd->variables.pseudo_thread_id= save_pseudo_thread_id;
@ -4015,9 +4015,10 @@ retry:
/* this DELETE FROM is needed even with row-based binlogging */
end = strxmov(strmov(query, "DELETE FROM `"),
share->db.str,"`.`",share->table_name.str,"`", NullS);
int errcode= query_error_code(thd, TRUE);
thd->binlog_query(THD::STMT_QUERY_TYPE,
query, (ulong)(end-query),
FALSE, FALSE, THD::NOT_KILLED);
FALSE, FALSE, errcode);
my_free(query, MYF(0));
}
else

View File

@ -3658,7 +3658,7 @@ show_query_type(THD::enum_binlog_query_type qtype)
*/
int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg,
ulong query_len, bool is_trans, bool suppress_use,
THD::killed_state killed_status_arg)
int errcode)
{
DBUG_ENTER("THD::binlog_query");
DBUG_PRINT("enter", ("qtype: %s query: '%s'",
@ -3725,7 +3725,7 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg,
*/
{
Query_log_event qinfo(this, query_arg, query_len, is_trans, suppress_use,
killed_status_arg);
errcode);
qinfo.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
/*
Binlog table maps will be irrelevant after a Query_log_event

View File

@ -1914,7 +1914,7 @@ public:
int binlog_query(enum_binlog_query_type qtype,
char const *query, ulong query_len,
bool is_trans, bool suppress_use,
THD::killed_state killed_err_arg= THD::KILLED_NO_VALUE);
int errcode);
#endif
/*

View File

@ -181,8 +181,7 @@ uchar* dboptions_get_key(my_dbopt_t *opt, size_t *length,
static inline void write_to_binlog(THD *thd, char *query, uint q_len,
char *db, uint db_len)
{
Query_log_event qinfo(thd, query, q_len, 0, 0, THD::NOT_KILLED);
qinfo.error_code= 0;
Query_log_event qinfo(thd, query, q_len, 0, 0, 0);
qinfo.db= db;
qinfo.db_len= db_len;
mysql_bin_log.write(&qinfo);
@ -723,8 +722,9 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
if (mysql_bin_log.is_open())
{
int errcode= query_error_code(thd, TRUE);
Query_log_event qinfo(thd, query, query_length, 0,
/* suppress_use */ TRUE, THD::NOT_KILLED);
/* suppress_use */ TRUE, errcode);
/*
Write should use the database being created as the "current
@ -811,8 +811,9 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
if (mysql_bin_log.is_open())
{
int errcode= query_error_code(thd, TRUE);
Query_log_event qinfo(thd, thd->query, thd->query_length, 0,
/* suppress_use */ TRUE, THD::NOT_KILLED);
/* suppress_use */ TRUE, errcode);
/*
Write should use the database being created as the "current
@ -958,8 +959,9 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
}
if (mysql_bin_log.is_open())
{
int errcode= query_error_code(thd, TRUE);
Query_log_event qinfo(thd, query, query_length, 0,
/* suppress_use */ TRUE, THD::NOT_KILLED);
/* suppress_use */ TRUE, errcode);
/*
Write should use the database being created as the "current
database" and not the threads current database, which is the
@ -1958,8 +1960,9 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db)
/* Step8: logging */
if (mysql_bin_log.is_open())
{
int errcode= query_error_code(thd, TRUE);
Query_log_event qinfo(thd, thd->query, thd->query_length,
0, TRUE, THD::NOT_KILLED);
0, TRUE, errcode);
thd->clear_error();
mysql_bin_log.write(&qinfo);
}

View File

@ -389,8 +389,12 @@ cleanup:
FALSE :
transactional_table;
int errcode= 0;
if (error < 0)
thd->clear_error();
else
errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
/*
[binlog]: If 'handler::delete_all_rows()' was called and the
storage engine does not inject the rows itself, we replicate
@ -402,7 +406,7 @@ cleanup:
*/
int log_result= thd->binlog_query(query_type,
thd->query, thd->query_length,
is_trans, FALSE, killed_status);
is_trans, FALSE, errcode);
if (log_result && transactional_table)
{
@ -836,9 +840,10 @@ void multi_delete::abort()
*/
if (mysql_bin_log.is_open())
{
int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED);
thd->binlog_query(THD::ROW_QUERY_TYPE,
thd->query, thd->query_length,
transactional_tables, FALSE);
transactional_tables, FALSE, errcode);
}
thd->transaction.all.modified_non_trans_table= true;
}
@ -979,11 +984,14 @@ bool multi_delete::send_eof()
{
if (mysql_bin_log.is_open())
{
int errcode= 0;
if (local_error == 0)
thd->clear_error();
else
errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
if (thd->binlog_query(THD::ROW_QUERY_TYPE,
thd->query, thd->query_length,
transactional_tables, FALSE, killed_status) &&
transactional_tables, FALSE, errcode) &&
!normal_tables)
{
local_error=1; // Log write failed: roll back the SQL statement

View File

@ -863,6 +863,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
{
if (mysql_bin_log.is_open())
{
int errcode= 0;
if (error <= 0)
{
/*
@ -877,6 +878,9 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
/* todo: consider removing */
thd->clear_error();
}
else
errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED);
/* bug#22725:
A query which per-row-loop can not be interrupted with
@ -893,7 +897,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
if (thd->binlog_query(THD::ROW_QUERY_TYPE,
thd->query, thd->query_length,
transactional_table, FALSE,
(error>0) ? thd->killed : THD::NOT_KILLED) &&
errcode) &&
transactional_table)
{
error=1;
@ -2667,6 +2671,12 @@ bool Delayed_insert::handle_inserts(void)
thd.variables.time_zone = row->time_zone;
}
/* if the delayed insert was killed, the killed status is
ignored while binlogging */
int errcode= 0;
if (thd.killed == THD::NOT_KILLED)
errcode= query_error_code(&thd, TRUE);
/*
If the query has several rows to insert, only the first row will come
here. In row-based binlogging, this means that the first row will be
@ -2677,7 +2687,7 @@ bool Delayed_insert::handle_inserts(void)
*/
thd.binlog_query(THD::ROW_QUERY_TYPE,
row->query.str, row->query.length,
FALSE, FALSE);
FALSE, FALSE, errcode);
thd.time_zone_used = backup_time_zone_used;
thd.variables.time_zone = backup_time_zone;
@ -3194,11 +3204,14 @@ bool select_insert::send_eof()
*/
if (mysql_bin_log.is_open())
{
int errcode= 0;
if (!error)
thd->clear_error();
else
errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
thd->binlog_query(THD::ROW_QUERY_TYPE,
thd->query, thd->query_length,
trans_table, FALSE, killed_status);
trans_table, FALSE, errcode);
}
table->file->ha_release_auto_increment();
@ -3265,8 +3278,11 @@ void select_insert::abort() {
if (thd->transaction.stmt.modified_non_trans_table)
{
if (mysql_bin_log.is_open())
{
int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED);
thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query, thd->query_length,
transactional_table, FALSE);
transactional_table, FALSE, errcode);
}
if (!thd->current_stmt_binlog_row_based && !can_rollback_data())
thd->transaction.all.modified_non_trans_table= TRUE;
if (changed)
@ -3658,10 +3674,14 @@ select_create::binlog_show_create_table(TABLE **tables, uint count)
DBUG_ASSERT(result == 0); /* store_create_info() always return 0 */
if (mysql_bin_log.is_open())
{
int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED);
thd->binlog_query(THD::STMT_QUERY_TYPE,
query.ptr(), query.length(),
/* is_trans */ TRUE,
/* suppress_use */ FALSE);
/* suppress_use */ FALSE,
errcode);
}
}
void select_create::store_values(List<Item> &values)

View File

@ -86,7 +86,7 @@ static int read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
static bool write_execute_load_query_log_event(THD *thd,
bool duplicates, bool ignore,
bool transactional_table,
THD::killed_state killed_status);
int errcode);
#endif /* EMBEDDED_LIBRARY */
/*
@ -483,10 +483,12 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
/* If the file was not empty, wrote_create_file is true */
if (lf_info.wrote_create_file)
{
int errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
if (thd->transaction.stmt.modified_non_trans_table)
write_execute_load_query_log_event(thd, handle_duplicates,
ignore, transactional_table,
killed_status);
errcode);
else
{
Delete_file_log_event d(thd, db, transactional_table);
@ -528,8 +530,9 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
read_info.end_io_cache();
if (lf_info.wrote_create_file)
{
int errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
write_execute_load_query_log_event(thd, handle_duplicates, ignore,
transactional_table,killed_status);
transactional_table, errcode);
}
}
}
@ -553,7 +556,7 @@ err:
static bool write_execute_load_query_log_event(THD *thd,
bool duplicates, bool ignore,
bool transactional_table,
THD::killed_state killed_err_arg)
int errcode)
{
Execute_load_query_log_event
e(thd, thd->query, thd->query_length,
@ -561,7 +564,7 @@ static bool write_execute_load_query_log_event(THD *thd,
(uint) ((char*)thd->lex->fname_end - (char*)thd->query),
(duplicates == DUP_REPLACE) ? LOAD_DUP_REPLACE :
(ignore ? LOAD_DUP_IGNORE : LOAD_DUP_ERROR),
transactional_table, FALSE, killed_err_arg);
transactional_table, FALSE, errcode);
e.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
return mysql_bin_log.write(&e);
}

View File

@ -1460,10 +1460,13 @@ void write_bin_log(THD *thd, bool clear_error,
{
if (mysql_bin_log.is_open())
{
int errcode= 0;
if (clear_error)
thd->clear_error();
else
errcode= query_error_code(thd, TRUE);
thd->binlog_query(THD::STMT_QUERY_TYPE,
query, query_length, FALSE, FALSE, THD::NOT_KILLED);
query, query_length, FALSE, FALSE, errcode);
}
}
@ -6180,7 +6183,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
0, FALSE, THD::NOT_KILLED);
0, FALSE, 0);
mysql_bin_log.write(&qinfo);
}
my_ok(thd);

View File

@ -795,11 +795,15 @@ int mysql_update(THD *thd,
{
if (mysql_bin_log.is_open())
{
int errcode= 0;
if (error < 0)
thd->clear_error();
else
errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
if (thd->binlog_query(THD::ROW_QUERY_TYPE,
thd->query, thd->query_length,
transactional_table, FALSE, killed_status) &&
transactional_table, FALSE, errcode) &&
transactional_table)
{
error=1; // Rollback update
@ -1847,9 +1851,10 @@ void multi_update::abort()
got caught and if happens later the killed error is written
into repl event.
*/
int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED);
thd->binlog_query(THD::ROW_QUERY_TYPE,
thd->query, thd->query_length,
transactional_tables, FALSE);
transactional_tables, FALSE, errcode);
}
thd->transaction.all.modified_non_trans_table= TRUE;
}
@ -2075,11 +2080,14 @@ bool multi_update::send_eof()
{
if (mysql_bin_log.is_open())
{
int errcode= 0;
if (local_error == 0)
thd->clear_error();
else
errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
if (thd->binlog_query(THD::ROW_QUERY_TYPE,
thd->query, thd->query_length,
transactional_tables, FALSE, killed_status) &&
transactional_tables, FALSE, errcode) &&
trans_safe)
{
local_error= 1; // Rollback update

View File

@ -661,8 +661,9 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
buff.append(STRING_WITH_LEN(" AS "));
buff.append(views->source.str, views->source.length);
int errcode= query_error_code(thd, TRUE);
thd->binlog_query(THD::STMT_QUERY_TYPE,
buff.ptr(), buff.length(), FALSE, FALSE, THD::NOT_KILLED);
buff.ptr(), buff.length(), FALSE, FALSE, errcode);
}
VOID(pthread_mutex_unlock(&LOCK_open));