46
46
#include "drizzled/db.h"
47
47
#include "drizzled/pthread_globals.h"
48
48
#include "drizzled/transaction_services.h"
49
#include "drizzled/drizzled.h"
51
#include "drizzled/table_share_instance.h"
50
53
#include "plugin/myisam/myisam.h"
51
54
#include "drizzled/internal/iocache.h"
55
#include "drizzled/internal/thread_var.h"
56
#include "drizzled/plugin/event_observer.h"
54
59
#include <algorithm>
74
73
const char * const Session::DEFAULT_WHERE= "field list";
75
74
extern pthread_key_t THR_Session;
76
75
extern pthread_key_t THR_Mem_root;
77
extern uint32_t max_used_connections;
78
extern atomic<uint32_t> connection_count;
81
/****************************************************************************
83
****************************************************************************/
84
unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool )
86
*length= entry->name.length;
87
return (unsigned char*) entry->name.str;
90
void free_user_var(user_var_entry *entry)
95
77
bool Key_part_spec::operator==(const Key_part_spec& other) const
99
81
!strcmp(field_name.str, other.field_name.str);
102
Open_tables_state::Open_tables_state(uint64_t version_arg)
103
:version(version_arg), backups_available(false)
84
Open_tables_state::Open_tables_state(uint64_t version_arg) :
105
reset_open_tables_state();
87
open_tables= temporary_tables= derived_tables= NULL;
88
extra_lock= lock= NULL;
109
92
The following functions form part of the C plugin API
111
extern "C" int mysql_tmpfile(const char *prefix)
94
int mysql_tmpfile(const char *prefix)
113
96
char filename[FN_REFLEN];
114
int fd = internal::create_temp_file(filename, drizzle_tmpdir, prefix, MYF(MY_WME));
97
int fd = internal::create_temp_file(filename, drizzle_tmpdir.c_str(), prefix, MYF(MY_WME));
134
116
@see Session::set_proc_info
137
set_session_proc_info(Session *session, const char *info)
118
void set_session_proc_info(Session *session, const char *info)
139
120
session->set_proc_info(info);
143
123
const char *get_session_proc_info(Session *session)
145
125
return session->get_proc_info();
156
136
return &ha_data[monitored->getId()].resource_context[index];
160
139
int64_t session_test_options(const Session *session, int64_t test_options)
162
141
return session->options & test_options;
166
144
int session_sql_command(const Session *session)
168
146
return (int) session->lex->sql_command;
172
int session_tx_isolation(const Session *session)
149
enum_tx_isolation session_tx_isolation(const Session *session)
174
return (int) session->variables.tx_isolation;
151
return (enum_tx_isolation)session->variables.tx_isolation;
177
Session::Session(plugin::Client *client_arg)
154
Session::Session(plugin::Client *client_arg) :
179
155
Open_tables_state(refresh_version),
180
156
mem_root(&main_mem_root),
268
245
/* Initialize sub structures */
269
246
memory::init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
270
hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
271
(hash_get_key) get_var_key,
272
(hash_free_key) free_user_var, 0);
274
248
substitute_null_with_insert_id = false;
275
thr_lock_info_init(&lock_info); /* safety: will be reset after start */
249
lock_info.init(); /* safety: will be reset after start */
276
250
thr_lock_owner_init(&main_lock_id, &lock_info);
278
252
m_internal_handler= NULL;
254
plugin::EventObserver::registerSessionEvents(*this);
281
257
void Session::free_items()
310
286
return false; // 'false', as per coding style
289
void Session::setAbort(bool arg)
291
mysys_var->abort= arg;
294
void Session::lockOnSys()
300
pthread_mutex_lock(&mysys_var->mutex);
301
if (mysys_var->current_cond)
303
pthread_mutex_lock(mysys_var->current_mutex);
304
pthread_cond_broadcast(mysys_var->current_cond);
305
pthread_mutex_unlock(mysys_var->current_mutex);
307
pthread_mutex_unlock(&mysys_var->mutex);
313
310
void Session::pop_internal_handler()
315
312
assert(m_internal_handler != NULL);
316
313
m_internal_handler= NULL;
319
#if defined(__cplusplus)
323
void *session_alloc(Session *session, unsigned int size)
325
return session->alloc(size);
328
void *session_calloc(Session *session, unsigned int size)
330
return session->calloc(size);
333
char *session_strdup(Session *session, const char *str)
335
return session->strdup(str);
338
char *session_strmake(Session *session, const char *str, unsigned int size)
340
return session->strmake(str, size);
343
void *session_memdup(Session *session, const void* str, unsigned int size)
345
return session->memdup(str, size);
348
void session_get_xid(const Session *session, DRIZZLE_XID *xid)
350
*xid = *(DRIZZLE_XID *) &session->transaction.xid_state.xid;
353
#if defined(__cplusplus)
316
void Session::get_xid(DRIZZLE_XID *xid)
318
*xid = *(DRIZZLE_XID *) &transaction.xid_state.xid;
357
321
/* Do operations that may take a long time */
371
335
TransactionServices &transaction_services= TransactionServices::singleton();
372
transaction_services.ha_rollback_trans(this, true);
336
transaction_services.rollbackTransaction(this, true);
373
337
xid_cache_delete(&transaction.xid_state);
375
hash_free(&user_vars);
340
for (UserVars::iterator iter= user_vars.begin();
341
iter != user_vars.end();
344
user_var_entry *entry= (*iter).second;
376
350
close_temporary_tables();
378
352
if (global_read_lock)
406
379
plugin::StorageEngine::closeConnection(this);
407
380
plugin_sessionvar_cleanup(this);
409
free_root(&warn_root,MYF(0));
382
warn_root.free_root(MYF(0));
410
383
mysys_var=0; // Safety (shouldn't be needed)
411
384
dbug_sentry= Session_SENTRY_GONE;
413
free_root(&main_mem_root, MYF(0));
386
main_mem_root.free_root(MYF(0));
414
387
pthread_setspecific(THR_Session, 0);
416
389
plugin::Logging::postEndDo(this);
390
plugin::EventObserver::deregisterSessionEvents(*this);
418
392
/* Ensure that no one is using Session */
419
pthread_mutex_unlock(&LOCK_delete);
420
pthread_mutex_destroy(&LOCK_delete);
424
Add all status variables to another status variable array
428
to_var add to this array
429
from_var from this array
432
This function assumes that all variables are long/ulong.
433
If this assumption will change, then we have to explictely add
434
the other variables after the while loop
436
void add_to_status(system_status_var *to_var, system_status_var *from_var)
438
ulong *end= (ulong*) ((unsigned char*) to_var +
439
offsetof(system_status_var, last_system_status_var) +
441
ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
448
Add the difference between two status variable arrays to another one.
452
to_var add to this array
453
from_var from this array
454
dec_var minus this array
457
This function assumes that all variables are long/ulong.
459
void add_diff_to_status(system_status_var *to_var, system_status_var *from_var,
460
system_status_var *dec_var)
462
ulong *end= (ulong*) ((unsigned char*) to_var + offsetof(system_status_var,
463
last_system_status_var) +
465
ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var;
468
*(to++)+= *(from++) - *(dec++);
393
LOCK_delete.unlock();
471
396
void Session::awake(Session::killed_state state_to_set)
560
486
command= COM_SLEEP;
563
reset_root_defaults(mem_root, variables.query_alloc_block_size,
564
variables.query_prealloc_size);
489
mem_root->reset_root_defaults(variables.query_alloc_block_size,
490
variables.query_prealloc_size);
565
491
transaction.xid_state.xid.null();
566
492
transaction.xid_state.in_session=1;
604
530
connection_count.increment();
606
if (connection_count > max_used_connections)
607
max_used_connections= connection_count;
532
if (connection_count > current_global_counters.max_used_connections)
534
current_global_counters.max_used_connections= connection_count;
609
537
thread_id= variables.pseudo_thread_id= global_thread_id++;
611
pthread_mutex_lock(&LOCK_thread_count);
539
LOCK_thread_count.lock();
612
540
getSessionList().push_back(this);
613
pthread_mutex_unlock(&LOCK_thread_count);
541
LOCK_thread_count.unlock();
615
543
if (scheduler->addSession(this))
636
const char* Session::enter_cond(pthread_cond_t *cond,
637
pthread_mutex_t* mutex,
564
const char* Session::enter_cond(boost::condition_variable &cond, boost::mutex &mutex, const char* msg)
640
566
const char* old_msg = get_proc_info();
641
567
safe_mutex_assert_owner(mutex);
642
mysys_var->current_mutex = mutex;
643
mysys_var->current_cond = cond;
568
mysys_var->current_mutex = mutex.native_handle();
569
mysys_var->current_cond = cond.native_handle();
644
570
this->set_proc_info(msg);
1049
985
if (!internal::dirname_length(exchange->file_name))
1051
strcpy(path, drizzle_real_data_home);
987
strcpy(path, data_home_real);
1052
988
if (! session->db.empty())
1053
strncat(path, session->db.c_str(), FN_REFLEN-strlen(drizzle_real_data_home)-1);
989
strncat(path, session->db.c_str(), FN_REFLEN-strlen(data_home_real)-1);
1054
990
(void) internal::fn_format(path, exchange->file_name, path, "", option);
1057
(void) internal::fn_format(path, exchange->file_name, drizzle_real_data_home, "", option);
993
(void) internal::fn_format(path, exchange->file_name, data_home_real, "", option);
1059
995
if (opt_secure_file_priv &&
1060
996
strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
1592
/****************************************************************************
1593
Handling of open and locked tables states.
1595
This is used when we want to open/lock (and then close) some tables when
1596
we already have a set of tables open and locked. We use these methods for
1597
access to mysql.proc table to find definitions of stored routines.
1598
****************************************************************************/
1600
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
1602
backup->set_open_tables_state(this);
1603
reset_open_tables_state();
1604
backups_available= false;
1608
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
1611
Before we will throw away current open tables state we want
1612
to be sure that it was properly cleaned up.
1614
assert(open_tables == 0 && temporary_tables == 0 &&
1615
derived_tables == 0 &&
1617
set_open_tables_state(backup);
1620
1528
bool Session::set_db(const std::string &new_db)
1622
1530
/* Do not reallocate memory if current chunk is big enough. */
1637
1545
@retval 0 the user thread is active
1638
1546
@retval 1 the user thread has been killed
1640
extern "C" int session_killed(const Session *session)
1548
int session_killed(const Session *session)
1642
1550
return(session->killed);
1646
Return the session id of a user session
1647
@param pointer to Session object
1648
@return session's id
1650
extern "C" unsigned long session_get_thread_id(const Session *session)
1652
return (unsigned long) session->getSessionId();
1656
1554
const struct charset_info_st *session_charset(Session *session)
1658
1556
return(session->charset());
1661
int session_non_transactional_update(const Session *session)
1663
return(session->transaction.all.hasModifiedNonTransData());
1666
void session_mark_transaction_to_rollback(Session *session, bool all)
1668
mark_transaction_to_rollback(session, all);
1672
1560
Mark transaction to rollback and mark error as fatal to a sub-statement.
1804
1698
void Session::nukeTable(Table *table)
1806
plugin::StorageEngine *table_type= table->s->db_type();
1700
plugin::StorageEngine *table_type= table->getShare()->db_type();
1808
1702
table->free_io_cache();
1809
table->closefrm(false);
1703
table->delete_table();
1811
TableIdentifier identifier(table->s->getSchemaName(), table->s->table_name.str, table->s->path.str);
1705
TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1812
1706
rm_temporary_table(table_type, identifier);
1814
table->s->free_table_share();
1708
delete table->getMutableShare();
1816
1710
/* This makes me sad, but we're allocating it via malloc */
1820
1714
/** Clear most status variables. */
1821
1715
extern time_t flush_status_time;
1822
extern uint32_t max_used_connections;
1824
1717
void Session::refresh_status()
1826
pthread_mutex_lock(&LOCK_status);
1828
/* Add thread's status variabes to global status */
1829
add_to_status(&global_status_var, &status_var);
1831
1719
/* Reset thread's status variables */
1832
1720
memset(&status_var, 0, sizeof(status_var));
1834
/* Reset some global variables */
1835
reset_status_vars();
1837
/* Reset the counters of all key caches (default and named). */
1838
reset_key_cache_counters();
1839
1722
flush_status_time= time((time_t*) 0);
1840
max_used_connections= 1; /* We set it to one, because we know we exist */
1841
pthread_mutex_unlock(&LOCK_status);
1723
current_global_counters.max_used_connections= 1; /* We set it to one, because we know we exist */
1844
1726
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1846
1728
user_var_entry *entry= NULL;
1729
UserVarsRange ppp= user_vars.equal_range(std::string(name.str, name.length));
1848
entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
1731
for (UserVars::iterator iter= ppp.first;
1732
iter != ppp.second; ++iter)
1734
entry= (*iter).second;
1850
1737
if ((entry == NULL) && create_if_not_exists)
1852
if (!hash_inited(&user_vars))
1854
1739
entry= new (nothrow) user_var_entry(name.str, query_id);
1856
1741
if (entry == NULL)
1859
if (my_hash_insert(&user_vars, (unsigned char*) entry))
1744
std::pair<UserVars::iterator, bool> returnable= user_vars.insert(make_pair(std::string(name.str, name.length), entry));
1746
if (not returnable.second)
1862
free((char*) entry);
1904
1789
void Session::close_thread_tables()
1909
We are assuming here that session->derived_tables contains ONLY derived
1910
tables for this substatement. i.e. instead of approach which uses
1911
query_id matching for determining which of the derived tables belong
1912
to this substatement we rely on the ability of substatements to
1913
save/restore session->derived_tables during their execution.
1915
TODO: Probably even better approach is to simply associate list of
1916
derived tables with (sub-)statement instead of thread and destroy
1917
them at the end of its execution.
1919
1791
if (derived_tables)
1923
Close all derived tables generated in queries like
1924
SELECT * FROM (SELECT * FROM t1)
1926
for (table= derived_tables ; table ; table= next)
1929
table->free_tmp_table(this);
1792
derived_tables= NULL; // They should all be invalid by this point
1935
1795
Mark all temporary tables used by this statement as free for reuse.
1943
1803
does not belong to statement for which we do close_thread_tables()).
1944
1804
TODO: This should be fixed in later releases.
1946
if (backups_available == false)
1948
1807
TransactionServices &transaction_services= TransactionServices::singleton();
1949
1808
main_da.can_overwrite_status= true;
1950
transaction_services.ha_autocommit_or_rollback(this, is_error());
1809
transaction_services.autocommitOrRollback(this, is_error());
1951
1810
main_da.can_overwrite_status= false;
1952
1811
transaction.stmt.reset();
2022
1881
assert(ret == false);
2023
1882
if (open_tables_from_list(&tables, &counter, flags) ||
2024
1883
mysql_handle_derived(lex, &mysql_derived_prepare))
2029
bool Session::rm_temporary_table(TableIdentifier &identifier)
1891
@note "best_effort" is used in cases were if a failure occurred on this
1892
operation it would not be surprising because we are only removing because there
1893
might be an issue (lame engines).
1896
bool Session::rm_temporary_table(TableIdentifier &identifier, bool best_effort)
2031
1898
if (plugin::StorageEngine::dropTable(*this, identifier))
2033
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2034
identifier.getSQLPath().c_str(), errno);
2035
dumpTemporaryTableNames("rm_temporary_table()");
1900
if (not best_effort)
1902
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
1903
identifier.getSQLPath().c_str(), errno);
2070
1938
cerr << "Begin Run: " << foo << "\n";
2071
for (table= temporary_tables; table; table= table->next)
1939
for (table= temporary_tables; table; table= table->getNext())
2073
1941
bool have_proto= false;
2075
message::Table *proto= table->s->getTableProto();
2076
if (table->s->getTableProto())
1943
message::Table *proto= table->getShare()->getTableProto();
1944
if (table->getShare()->getTableProto())
2077
1945
have_proto= true;
2079
1947
const char *answer= have_proto ? "true" : "false";
2081
1949
if (have_proto)
2083
cerr << "\tTable Name " << table->s->getSchemaName() << "." << table->s->table_name.str << " : " << answer << "\n";
1951
cerr << "\tTable Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2084
1952
cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2087
cerr << "\tTabl;e Name " << table->s->getSchemaName() << "." << table->s->table_name.str << " : " << answer << "\n";
1955
cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2091
bool Session::storeTableMessage(TableIdentifier &identifier, message::Table &table_message)
1959
bool Session::storeTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2093
1961
table_message_cache.insert(make_pair(identifier.getPath(), table_message));
2098
bool Session::removeTableMessage(TableIdentifier &identifier)
1966
bool Session::removeTableMessage(const TableIdentifier &identifier)
2100
1968
TableMessageCache::iterator iter;