24
24
#include "config.h"
25
#include "drizzled/session.h"
26
#include "drizzled/session/cache.h"
25
#include <drizzled/session.h>
26
#include "drizzled/session_list.h"
27
27
#include <sys/stat.h>
28
#include "drizzled/error.h"
29
#include "drizzled/gettext.h"
30
#include "drizzled/query_id.h"
31
#include "drizzled/data_home.h"
32
#include "drizzled/sql_base.h"
33
#include "drizzled/lock.h"
34
#include "drizzled/item/cache.h"
35
#include "drizzled/item/float.h"
36
#include "drizzled/item/return_int.h"
37
#include "drizzled/item/empty_string.h"
38
#include "drizzled/show.h"
39
#include "drizzled/plugin/client.h"
28
#include <drizzled/error.h>
29
#include <drizzled/gettext.h>
30
#include <drizzled/query_id.h>
31
#include <drizzled/data_home.h>
32
#include <drizzled/sql_base.h>
33
#include <drizzled/lock.h>
34
#include <drizzled/item/cache.h>
35
#include <drizzled/item/float.h>
36
#include <drizzled/item/return_int.h>
37
#include <drizzled/item/empty_string.h>
38
#include <drizzled/show.h>
39
#include <drizzled/plugin/client.h>
40
40
#include "drizzled/plugin/scheduler.h"
41
41
#include "drizzled/plugin/authentication.h"
42
42
#include "drizzled/plugin/logging.h"
43
43
#include "drizzled/plugin/transactional_storage_engine.h"
44
#include "drizzled/plugin/query_rewrite.h"
45
44
#include "drizzled/probes.h"
46
45
#include "drizzled/table_proto.h"
47
46
#include "drizzled/db.h"
49
48
#include "drizzled/transaction_services.h"
50
49
#include "drizzled/drizzled.h"
52
#include "drizzled/identifier.h"
54
51
#include "drizzled/table/instance.h"
56
53
#include "plugin/myisam/myisam.h"
61
58
#include "drizzled/util/functors.h"
63
#include "drizzled/display.h"
66
61
#include <algorithm>
68
#include <boost/filesystem.hpp>
70
#include "drizzled/util/backtrace.h"
63
#include "boost/filesystem.hpp"
72
65
using namespace std;
89
82
return length == other.length &&
90
83
field_name.length == other.field_name.length &&
91
!my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
84
!strcmp(field_name.str, other.field_name.str);
94
87
Open_tables_state::Open_tables_state(uint64_t version_arg) :
164
157
Session::Session(plugin::Client *client_arg) :
165
158
Open_tables_state(refresh_version),
166
159
mem_root(&main_mem_root),
169
query(new std::string),
170
_schema(new std::string("")),
171
161
catalog("LOCAL"),
172
162
client(client_arg),
174
164
scheduler_arg(NULL),
175
165
lock_id(&main_lock_id),
177
security_ctx(identifier::User::make_shared()),
179
167
ha_data(plugin::num_trx_monitored_objects),
180
concurrent_execute_allowed(true),
181
168
arg_of_last_insert_id_function(false),
182
169
first_successful_insert_id_in_prev_stmt(0),
183
170
first_successful_insert_id_in_cur_stmt(0),
184
171
limit_found_rows(0),
185
_global_read_lock(NONE),
187
173
some_tables_deleted(false),
188
174
no_errors(false),
199
185
session_event_observers(NULL),
188
memset(process_list_info, 0, PROCESS_LIST_WIDTH);
202
189
client->setSession(this);
382
369
if (client->isConnected())
384
assert(security_ctx);
385
371
if (global_system_variables.log_warnings)
387
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),
388
internal::my_progname,
390
security_ctx->username().c_str());
372
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),internal::my_progname,
374
(getSecurityContext().getUser().c_str() ?
375
getSecurityContext().getUser().c_str() : ""));
393
376
disconnect(0, false);
419
402
delete (*iter).second;
421
404
life_properties.clear();
424
void Session::setClient(plugin::Client *client_arg)
427
client->setSession(this);
430
void Session::awake(Session::killed_state_t state_to_set)
432
if ((state_to_set == Session::KILL_QUERY) and (command == COM_SLEEP))
406
/* Ensure that no one is using Session */
407
LOCK_delete.unlock();
410
void Session::awake(Session::killed_state state_to_set)
435
412
this->checkSentry();
437
setKilled(state_to_set);
438
scheduler->killSession(this);
413
safe_mutex_assert_owner(&LOCK_delete);
415
killed= state_to_set;
440
416
if (state_to_set != Session::KILL_QUERY)
418
scheduler->killSession(this);
442
419
DRIZZLE_CONNECTION_DONE(thread_id);
447
423
boost_unique_lock_t scopedLock(mysys_var->mutex);
555
531
prepareForQueries();
557
while (not client->haveError() && getKilled() != KILL_CONNECTION)
533
while (! client->haveError() && killed != KILL_CONNECTION)
559
if (not executeStatement())
535
if (! executeStatement())
563
539
disconnect(0, true);
566
bool Session::schedule(Session::shared_ptr &arg)
542
bool Session::schedule()
568
arg->scheduler= plugin::Scheduler::getScheduler();
569
assert(arg->scheduler);
544
scheduler= plugin::Scheduler::getScheduler();
571
547
connection_count.increment();
578
554
current_global_counters.connections++;
579
arg->thread_id= arg->variables.pseudo_thread_id= global_thread_id++;
581
session::Cache::singleton().insert(arg);
583
if (unlikely(plugin::EventObserver::connectSession(*arg)))
585
// We should do something about an error...
588
if (plugin::Scheduler::getScheduler()->addSession(arg))
590
DRIZZLE_CONNECTION_START(arg->getSessionId());
555
thread_id= variables.pseudo_thread_id= global_thread_id++;
558
boost::mutex::scoped_lock scoped(LOCK_thread_count);
559
getSessionList().push_back(this);
562
if (unlikely(plugin::EventObserver::connectSession(*this)))
564
// We should do something about an error...
567
if (unlikely(plugin::EventObserver::connectSession(*this)))
569
// We should do something about an error...
572
if (scheduler->addSession(this))
574
DRIZZLE_CONNECTION_START(thread_id);
591
575
char error_message_buff[DRIZZLE_ERRMSG_SIZE];
593
arg->setKilled(Session::KILL_CONNECTION);
577
killed= Session::KILL_CONNECTION;
595
arg->status_var.aborted_connects++;
579
status_var.aborted_connects++;
597
581
/* Can't use my_error() since store_globals has not been called. */
598
582
/* TODO replace will better error message */
599
583
snprintf(error_message_buff, sizeof(error_message_buff),
600
584
ER(ER_CANT_CREATE_THREAD), 1);
601
arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
585
client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
611
Is this session viewable by the current user?
613
bool Session::isViewable() const
615
return plugin::Authorization::isAuthorized(current_session->user(),
621
593
const char* Session::enter_cond(boost::condition_variable_any &cond, boost::mutex &mutex, const char* msg)
623
595
const char* old_msg = get_proc_info();
658
630
const std::string &in_db)
660
632
bool is_authenticated=
661
plugin::Authentication::isAuthenticated(user(), passwd_str);
633
plugin::Authentication::isAuthenticated(getSecurityContext(),
663
636
if (is_authenticated != true)
700
673
main_da.reset_diagnostics_area();
702
675
if (client->readCommand(&l_packet, &packet_length) == false)
707
if (getKilled() == KILL_CONNECTION)
678
if (killed == KILL_CONNECTION)
710
681
if (packet_length == 0)
713
l_command= static_cast<enum_server_command>(l_packet[0]);
684
l_command= (enum enum_server_command) (unsigned char) l_packet[0];
715
686
if (command >= COM_END)
716
687
command= COM_END; // Wrong command
718
689
assert(packet_length);
719
return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
690
return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
722
693
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
728
699
in_packet_length--;
730
701
const char *pos= in_packet + in_packet_length; /* Point at end null */
731
while (in_packet_length > 0 && (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
702
while (in_packet_length > 0 &&
703
(pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
734
706
in_packet_length--;
737
std::string *new_query= new std::string(in_packet, in_packet + in_packet_length);
738
// We can not be entirely sure _schema has a value
741
plugin::QueryRewriter::rewriteQuery(*_schema, *new_query);
743
query.reset(new_query);
744
_state.reset(new State(in_packet, in_packet_length));
709
query.assign(in_packet, in_packet + in_packet_length);
798
763
if (result == false)
800
764
my_error(killed_errno(), MYF(0));
802
765
else if ((result == true) && do_release)
804
setKilled(Session::KILL_CONNECTION);
766
killed= Session::KILL_CONNECTION;
961
922
my_message(errcode, err, MYF(0));
964
(void) cache->end_io_cache();
925
(void) end_io_cache(cache);
965
926
(void) internal::my_close(file, MYF(0));
966
927
(void) internal::my_delete(path.file_string().c_str(), MYF(0)); // Delete file on error
972
933
bool select_to_file::send_eof()
974
int error= test(cache->end_io_cache());
935
int error= test(end_io_cache(cache));
975
936
if (internal::my_close(file, MYF(MY_WME)))
993
954
/* In case of error send_eof() may be not called: close the file here. */
996
(void) cache->end_io_cache();
957
(void) end_io_cache(cache);
997
958
(void) internal::my_close(file, MYF(0));
1052
1013
if (not to_file.has_root_directory())
1054
1015
target_path= fs::system_complete(getDataHomeCatalog());
1055
util::string::const_shared_ptr schema(session->schema());
1056
if (schema and not schema->empty())
1016
if (not session->db.empty())
1058
1018
int count_elements= 0;
1059
1019
for (fs::path::iterator iter= to_file.begin();
1092
1052
if ((file= internal::my_create(target_path.file_string().c_str(), 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1094
1054
(void) fchmod(file, 0666); // Because of umask()
1095
if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1055
if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1097
1057
internal::my_close(file, MYF(0));
1098
1058
internal::my_delete(target_path.file_string().c_str(), MYF(0)); // Delete file on error, it was just created
1560
1519
void Session::end_statement()
1562
1521
/* Cleanup SQL processing state to reuse this statement in next query. */
1564
1523
query_cache_key= ""; // reset the cache key
1565
1524
resetResultsetMessage();
1568
1527
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1571
if (_schema and _schema->empty())
1573
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1576
else if (not _schema)
1578
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1583
*p_db= strmake(_schema->c_str(), _schema->size());
1584
*p_db_length= _schema->size();
1531
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1534
*p_db= strmake(db.c_str(), db.length());
1535
*p_db_length= db.length();
1625
void Session::set_db(const std::string &new_db)
1575
bool Session::set_db(const std::string &new_db)
1627
1577
/* Do not reallocate memory if current chunk is big enough. */
1628
1578
if (new_db.length())
1630
_schema.reset(new std::string(new_db));
1634
_schema.reset(new std::string(""));
1590
Check the killed state of a user thread
1591
@param session user thread
1592
@retval 0 the user thread is active
1593
@retval 1 the user thread has been killed
1595
int session_killed(const Session *session)
1597
return(session->killed);
1601
const struct charset_info_st *session_charset(Session *session)
1603
return(session->charset());
1640
1607
Mark transaction to rollback and mark error as fatal to a sub-statement.
1657
1624
plugin_sessionvar_cleanup(this);
1659
1626
/* If necessary, log any aborted or unauthorized connections */
1660
if (getKilled() || client->wasAborted())
1627
if (killed || client->wasAborted())
1662
1629
status_var.aborted_threads++;
1665
1632
if (client->wasAborted())
1667
if (not getKilled() && variables.log_warnings > 1)
1634
if (! killed && variables.log_warnings > 1)
1636
SecurityContext *sctx= &security_ctx;
1669
1638
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1671
, (_schema->empty() ? "unconnected" : _schema->c_str())
1672
, security_ctx->username().empty() == false ? security_ctx->username().c_str() : "unauthenticated"
1673
, security_ctx->address().c_str()
1640
, (db.empty() ? "unconnected" : db.c_str())
1641
, sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
1642
, sctx->getIp().c_str()
1674
1643
, (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1678
1647
/* Close out our connection to the client */
1679
1648
if (should_lock)
1680
session::Cache::singleton().mutex().lock();
1682
setKilled(Session::KILL_CONNECTION);
1649
LOCK_thread_count.lock();
1650
killed= Session::KILL_CONNECTION;
1684
1651
if (client->isConnected())
1778
1742
If this is needed, use close_temporary_table()
1781
void Open_tables_state::nukeTable(Table *table)
1745
void Session::nukeTable(Table *table)
1783
1747
plugin::StorageEngine *table_type= table->getShare()->db_type();
1852
1816
DERIVATION_IMPLICIT, false);
1855
void Open_tables_state::mark_temp_tables_as_free_for_reuse()
1819
void Session::mark_temp_tables_as_free_for_reuse()
1857
1821
for (Table *table= temporary_tables ; table ; table= table->getNext())
1859
if (table->query_id == getQueryId())
1823
if (table->query_id == query_id)
1861
1825
table->query_id= 0;
1862
1826
table->cursor->ha_reset();
1920
1885
handled either before writing a query log event (inside
1921
1886
binlog_query()) or when preparing a pending event.
1888
mysql_unlock_tables(this, lock);
1927
Note that we need to hold table::Cache::singleton().mutex() while changing the
1892
Note that we need to hold LOCK_open while changing the
1928
1893
open_tables list. Another thread may work on it.
1929
(See: table::Cache::singleton().removeTable(), mysql_wait_completed_table())
1894
(See: remove_table_from_cache(), mysql_wait_completed_table())
1930
1895
Closing a MERGE child before the parent would be fatal if the
1931
1896
other thread tries to abort the MERGE lock in between.
1978
1943
might be an issue (lame engines).
1981
bool Open_tables_state::rm_temporary_table(const TableIdentifier &identifier, bool best_effort)
1946
bool Session::rm_temporary_table(TableIdentifier &identifier, bool best_effort)
1983
if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
1948
if (plugin::StorageEngine::dropTable(*this, identifier))
1985
1950
if (not best_effort)
1988
identifier.getSQLPath(path);
1989
1952
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
1990
path.c_str(), errno);
1953
identifier.getSQLPath().c_str(), errno);
1999
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const TableIdentifier &identifier)
1962
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
2003
if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier))
1966
if (plugin::StorageEngine::dropTable(*this, *base, identifier))
2006
identifier.getSQLPath(path);
2007
1968
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2008
path.c_str(), errno);
1969
identifier.getSQLPath().c_str(), errno);
2017
1978
@note this will be removed, I am looking through Hudson to see if it is finding
2018
1979
any tables that are missed during cleanup.
2020
void Open_tables_state::dumpTemporaryTableNames(const char *foo)
1981
void Session::dumpTemporaryTableNames(const char *foo)
2041
2002
cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2045
2005
cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2050
bool Session::TableMessages::storeTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2009
bool Session::storeTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2052
2011
table_message_cache.insert(make_pair(identifier.getPath(), table_message));
2057
bool Session::TableMessages::removeTableMessage(const TableIdentifier &identifier)
2016
bool Session::removeTableMessage(const TableIdentifier &identifier)
2059
2018
TableMessageCache::iterator iter;
2071
bool Session::TableMessages::getTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2030
bool Session::getTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2073
2032
TableMessageCache::iterator iter;
2099
bool Session::TableMessages::renameTableMessage(const TableIdentifier &from, const TableIdentifier &to)
2058
bool Session::renameTableMessage(const TableIdentifier &from, const TableIdentifier &to)
2101
2060
TableMessageCache::iterator iter;
2126
2085
return tmp_share;
2131
Create a reduced Table object with properly set up Field list from a
2132
list of field definitions.
2134
The created table doesn't have a table Cursor associated with
2135
it, has no keys, no group/distinct, no copy_funcs array.
2136
The sole purpose of this Table object is to use the power of Field
2137
class to read/write data to/from table->getInsertRecord(). Then one can store
2138
the record in any container (RB tree, hash, etc).
2139
The table is created in Session mem_root, so are the table's fields.
2140
Consequently, if you don't BLOB fields, you don't need to free it.
2142
@param session connection handle
2143
@param field_list list of column definitions
2146
0 if out of memory, Table object in case of success
2148
table::Instance *Session::getInstanceTable(List<CreateField> &field_list)
2150
temporary_shares.push_back(new table::Instance(this, field_list)); // This will not go into the tableshare cache, so no key is used.
2152
table::Instance *tmp_share= temporary_shares.back();
2161
static const std::string NONE= "NONE";
2162
static const std::string GOT_GLOBAL_READ_LOCK= "HAS GLOBAL READ LOCK";
2163
static const std::string MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT= "HAS GLOBAL READ LOCK WITH BLOCKING COMMIT";
2165
const std::string &type(drizzled::Session::global_read_lock_t type)
2171
case Session::GOT_GLOBAL_READ_LOCK:
2172
return GOT_GLOBAL_READ_LOCK;
2173
case Session::MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT:
2174
return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
2178
size_t max_string_length(drizzled::Session::global_read_lock_t)
2180
return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT.size();
2183
} /* namespace display */
2185
2088
} /* namespace drizzled */