24
24
#include "config.h"
25
25
#include "drizzled/session.h"
26
#include "drizzled/session/cache.h"
26
#include "drizzled/session_list.h"
27
27
#include <sys/stat.h>
28
28
#include "drizzled/error.h"
29
29
#include "drizzled/gettext.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
63
#include <boost/filesystem.hpp>
70
#include "drizzled/util/backtrace.h"
72
65
using namespace std;
74
67
namespace fs=boost::filesystem;
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) :
166
159
mem_root(&main_mem_root),
169
query(new std::string),
170
_schema(new std::string("")),
171
162
catalog("LOCAL"),
172
163
client(client_arg),
174
165
scheduler_arg(NULL),
175
166
lock_id(&main_lock_id),
177
security_ctx(identifier::User::make_shared()),
179
168
ha_data(plugin::num_trx_monitored_objects),
180
concurrent_execute_allowed(true),
181
169
arg_of_last_insert_id_function(false),
182
170
first_successful_insert_id_in_prev_stmt(0),
183
171
first_successful_insert_id_in_cur_stmt(0),
184
172
limit_found_rows(0),
185
_global_read_lock(NONE),
187
174
some_tables_deleted(false),
188
175
no_errors(false),
199
186
session_event_observers(NULL),
189
memset(process_list_info, 0, PROCESS_LIST_WIDTH);
202
190
client->setSession(this);
382
370
if (client->isConnected())
384
assert(security_ctx);
385
372
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());
373
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),internal::my_progname,
375
(getSecurityContext().getUser().c_str() ?
376
getSecurityContext().getUser().c_str() : ""));
393
377
disconnect(0, false);
419
403
delete (*iter).second;
421
405
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))
407
/* Ensure that no one is using Session */
408
LOCK_delete.unlock();
411
void Session::awake(Session::killed_state state_to_set)
435
413
this->checkSentry();
437
setKilled(state_to_set);
438
scheduler->killSession(this);
414
safe_mutex_assert_owner(&LOCK_delete);
416
killed= state_to_set;
440
417
if (state_to_set != Session::KILL_QUERY)
419
scheduler->killSession(this);
442
420
DRIZZLE_CONNECTION_DONE(thread_id);
447
424
boost_unique_lock_t scopedLock(mysys_var->mutex);
555
532
prepareForQueries();
557
while (not client->haveError() && getKilled() != KILL_CONNECTION)
534
while (! client->haveError() && killed != KILL_CONNECTION)
559
if (not executeStatement())
536
if (! executeStatement())
563
540
disconnect(0, true);
566
bool Session::schedule(Session::shared_ptr &arg)
543
bool Session::schedule()
568
arg->scheduler= plugin::Scheduler::getScheduler();
569
assert(arg->scheduler);
545
scheduler= plugin::Scheduler::getScheduler();
571
548
connection_count.increment();
578
555
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());
556
thread_id= variables.pseudo_thread_id= global_thread_id++;
559
boost::mutex::scoped_lock scoped(LOCK_thread_count);
560
getSessionList().push_back(this);
563
if (unlikely(plugin::EventObserver::connectSession(*this)))
565
// We should do something about an error...
568
if (unlikely(plugin::EventObserver::connectSession(*this)))
570
// We should do something about an error...
573
if (scheduler->addSession(this))
575
DRIZZLE_CONNECTION_START(thread_id);
591
576
char error_message_buff[DRIZZLE_ERRMSG_SIZE];
593
arg->setKilled(Session::KILL_CONNECTION);
578
killed= Session::KILL_CONNECTION;
595
arg->status_var.aborted_connects++;
580
status_var.aborted_connects++;
597
582
/* Can't use my_error() since store_globals has not been called. */
598
583
/* TODO replace will better error message */
599
584
snprintf(error_message_buff, sizeof(error_message_buff),
600
585
ER(ER_CANT_CREATE_THREAD), 1);
601
arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
586
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
594
const char* Session::enter_cond(boost::condition_variable_any &cond, boost::mutex &mutex, const char* msg)
623
596
const char* old_msg = get_proc_info();
658
631
const std::string &in_db)
660
633
bool is_authenticated=
661
plugin::Authentication::isAuthenticated(user(), passwd_str);
634
plugin::Authentication::isAuthenticated(getSecurityContext(),
663
637
if (is_authenticated != true)
700
674
main_da.reset_diagnostics_area();
702
676
if (client->readCommand(&l_packet, &packet_length) == false)
707
if (getKilled() == KILL_CONNECTION)
679
if (killed == KILL_CONNECTION)
710
682
if (packet_length == 0)
713
l_command= static_cast<enum_server_command>(l_packet[0]);
685
l_command= (enum enum_server_command) (unsigned char) l_packet[0];
715
687
if (command >= COM_END)
716
688
command= COM_END; // Wrong command
718
690
assert(packet_length);
719
return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
691
return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
722
694
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
728
700
in_packet_length--;
730
702
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])))
703
while (in_packet_length > 0 &&
704
(pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
734
707
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));
710
query.assign(in_packet, in_packet + in_packet_length);
798
764
if (result == false)
800
765
my_error(killed_errno(), MYF(0));
802
766
else if ((result == true) && do_release)
804
setKilled(Session::KILL_CONNECTION);
767
killed= Session::KILL_CONNECTION;
961
923
my_message(errcode, err, MYF(0));
964
(void) cache->end_io_cache();
926
(void) end_io_cache(cache);
965
927
(void) internal::my_close(file, MYF(0));
966
928
(void) internal::my_delete(path.file_string().c_str(), MYF(0)); // Delete file on error
972
934
bool select_to_file::send_eof()
974
int error= test(cache->end_io_cache());
936
int error= test(end_io_cache(cache));
975
937
if (internal::my_close(file, MYF(MY_WME)))
993
955
/* In case of error send_eof() may be not called: close the file here. */
996
(void) cache->end_io_cache();
958
(void) end_io_cache(cache);
997
959
(void) internal::my_close(file, MYF(0));
1052
1014
if (not to_file.has_root_directory())
1054
1016
target_path= fs::system_complete(getDataHomeCatalog());
1055
util::string::const_shared_ptr schema(session->schema());
1056
if (schema and not schema->empty())
1017
if (not session->db.empty())
1058
1019
int count_elements= 0;
1059
1020
for (fs::path::iterator iter= to_file.begin();
1092
1053
if ((file= internal::my_create(target_path.file_string().c_str(), 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1094
1055
(void) fchmod(file, 0666); // Because of umask()
1095
if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1056
if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1097
1058
internal::my_close(file, MYF(0));
1098
1059
internal::my_delete(target_path.file_string().c_str(), MYF(0)); // Delete file on error, it was just created
1560
1520
void Session::end_statement()
1562
1522
/* Cleanup SQL processing state to reuse this statement in next query. */
1564
1524
query_cache_key= ""; // reset the cache key
1565
1525
resetResultsetMessage();
1568
1528
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();
1532
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1535
*p_db= strmake(db.c_str(), db.length());
1536
*p_db_length= db.length();
1625
void Session::set_db(const std::string &new_db)
1576
bool Session::set_db(const std::string &new_db)
1627
1578
/* Do not reallocate memory if current chunk is big enough. */
1628
1579
if (new_db.length())
1630
_schema.reset(new std::string(new_db));
1634
_schema.reset(new std::string(""));
1591
Check the killed state of a user thread
1592
@param session user thread
1593
@retval 0 the user thread is active
1594
@retval 1 the user thread has been killed
1596
int session_killed(const Session *session)
1598
return(session->killed);
1602
const struct charset_info_st *session_charset(Session *session)
1604
return(session->charset());
1640
1608
Mark transaction to rollback and mark error as fatal to a sub-statement.
1657
1625
plugin_sessionvar_cleanup(this);
1659
1627
/* If necessary, log any aborted or unauthorized connections */
1660
if (getKilled() || client->wasAborted())
1628
if (killed || client->wasAborted())
1662
1630
status_var.aborted_threads++;
1665
1633
if (client->wasAborted())
1667
if (not getKilled() && variables.log_warnings > 1)
1635
if (! killed && variables.log_warnings > 1)
1637
SecurityContext *sctx= &security_ctx;
1669
1639
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()
1641
, (db.empty() ? "unconnected" : db.c_str())
1642
, sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
1643
, sctx->getIp().c_str()
1674
1644
, (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1678
1648
/* Close out our connection to the client */
1679
1649
if (should_lock)
1680
session::Cache::singleton().mutex().lock();
1682
setKilled(Session::KILL_CONNECTION);
1650
LOCK_thread_count.lock();
1651
killed= Session::KILL_CONNECTION;
1684
1652
if (client->isConnected())
1778
1743
If this is needed, use close_temporary_table()
1781
void Open_tables_state::nukeTable(Table *table)
1746
void Session::nukeTable(Table *table)
1783
1748
plugin::StorageEngine *table_type= table->getShare()->db_type();
1852
1817
DERIVATION_IMPLICIT, false);
1855
void Open_tables_state::mark_temp_tables_as_free_for_reuse()
1820
void Session::mark_temp_tables_as_free_for_reuse()
1857
1822
for (Table *table= temporary_tables ; table ; table= table->getNext())
1859
if (table->query_id == getQueryId())
1824
if (table->query_id == query_id)
1861
1826
table->query_id= 0;
1862
1827
table->cursor->ha_reset();
1920
1886
handled either before writing a query log event (inside
1921
1887
binlog_query()) or when preparing a pending event.
1889
mysql_unlock_tables(this, lock);
1927
Note that we need to hold table::Cache::singleton().mutex() while changing the
1893
Note that we need to hold LOCK_open while changing the
1928
1894
open_tables list. Another thread may work on it.
1929
1895
(See: table::Cache::singleton().removeTable(), mysql_wait_completed_table())
1930
1896
Closing a MERGE child before the parent would be fatal if the
1978
1944
might be an issue (lame engines).
1981
bool Open_tables_state::rm_temporary_table(const TableIdentifier &identifier, bool best_effort)
1947
bool Session::rm_temporary_table(TableIdentifier &identifier, bool best_effort)
1983
if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
1949
if (plugin::StorageEngine::dropTable(*this, identifier))
1985
1951
if (not best_effort)
1988
identifier.getSQLPath(path);
1989
1953
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
1990
path.c_str(), errno);
1954
identifier.getSQLPath().c_str(), errno);
1999
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const TableIdentifier &identifier)
1963
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
2003
if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier))
1967
if (plugin::StorageEngine::dropTable(*this, *base, identifier))
2006
identifier.getSQLPath(path);
2007
1969
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2008
path.c_str(), errno);
1970
identifier.getSQLPath().c_str(), errno);
2017
1979
@note this will be removed, I am looking through Hudson to see if it is finding
2018
1980
any tables that are missed during cleanup.
2020
void Open_tables_state::dumpTemporaryTableNames(const char *foo)
1982
void Session::dumpTemporaryTableNames(const char *foo)
2041
2003
cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2045
2006
cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2050
bool Session::TableMessages::storeTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2010
bool Session::storeTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2052
2012
table_message_cache.insert(make_pair(identifier.getPath(), table_message));
2057
bool Session::TableMessages::removeTableMessage(const TableIdentifier &identifier)
2017
bool Session::removeTableMessage(const TableIdentifier &identifier)
2059
2019
TableMessageCache::iterator iter;
2071
bool Session::TableMessages::getTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2031
bool Session::getTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2073
2033
TableMessageCache::iterator iter;
2099
bool Session::TableMessages::renameTableMessage(const TableIdentifier &from, const TableIdentifier &to)
2059
bool Session::renameTableMessage(const TableIdentifier &from, const TableIdentifier &to)
2101
2061
TableMessageCache::iterator iter;
2156
2116
return tmp_share;
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
2119
} /* namespace drizzled */