mirror of
https://github.com/MariaDB/server.git
synced 2025-01-19 05:22:25 +01:00
Merge bk-internal.mysql.com:/home/bk/mysql-5.1-new
into mysql.com:/mnt/raid/MySQL/devel/5.1-rt-wl3158-merged
This commit is contained in:
commit
f0a01456e5
74 changed files with 4737 additions and 2703 deletions
|
@ -1770,3 +1770,4 @@ vio/viotest-sslconnect.cpp
|
|||
vio/viotest.cpp
|
||||
zlib/*.ds?
|
||||
zlib/*.vcproj
|
||||
libmysqld/event_scheduler.cc
|
||||
|
|
|
@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc)
|
|||
AC_CANONICAL_SYSTEM
|
||||
# The Docs Makefile.am parses this line!
|
||||
# remember to also change ndb version below and update version.c in ndb
|
||||
AM_INIT_AUTOMAKE(mysql, 5.1.11-beta)
|
||||
AM_INIT_AUTOMAKE(mysql, 5.1.12-beta)
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
|
||||
PROTOCOL_VERSION=10
|
||||
|
|
|
@ -65,7 +65,8 @@ THREAD_RETURN YASSL_API echoserver_test(void* args)
|
|||
while (!shutdown) {
|
||||
sockaddr_in client;
|
||||
socklen_t client_len = sizeof(client);
|
||||
int clientfd = accept(sockfd, (sockaddr*)&client, &client_len);
|
||||
int clientfd = accept(sockfd, (sockaddr*)&client,
|
||||
(ACCEPT_THIRD_T)&client_len);
|
||||
if (clientfd == -1) err_sys("tcp accept failed");
|
||||
|
||||
SSL* ssl = SSL_new(ctx);
|
||||
|
|
|
@ -273,6 +273,7 @@ int SSL_pending(SSL*);
|
|||
|
||||
|
||||
enum { /* ssl Constants */
|
||||
SSL_WOULD_BLOCK = -8,
|
||||
SSL_BAD_STAT = -7,
|
||||
SSL_BAD_PATH = -6,
|
||||
SSL_BAD_FILETYPE = -5,
|
||||
|
@ -494,7 +495,7 @@ ASN1_TIME* X509_get_notAfter(X509* x);
|
|||
|
||||
|
||||
typedef struct MD4_CTX {
|
||||
void* ptr;
|
||||
int buffer[32]; /* big enough to hold, check size in Init */
|
||||
} MD4_CTX;
|
||||
|
||||
void MD4_Init(MD4_CTX*);
|
||||
|
|
|
@ -66,6 +66,7 @@ typedef unsigned char byte;
|
|||
// Wraps Windows Sockets and BSD Sockets
|
||||
class Socket {
|
||||
socket_t socket_; // underlying socket descriptor
|
||||
bool wouldBlock_; // for non-blocking data
|
||||
public:
|
||||
explicit Socket(socket_t s = INVALID_SOCKET);
|
||||
~Socket();
|
||||
|
@ -75,9 +76,10 @@ public:
|
|||
socket_t get_fd() const;
|
||||
|
||||
uint send(const byte* buf, unsigned int len, int flags = 0) const;
|
||||
uint receive(byte* buf, unsigned int len, int flags = 0) const;
|
||||
uint receive(byte* buf, unsigned int len, int flags = 0);
|
||||
|
||||
bool wait() const;
|
||||
bool wait();
|
||||
bool WouldBlock() const;
|
||||
|
||||
void closeSocket();
|
||||
void shutDown(int how = SD_SEND);
|
||||
|
|
|
@ -46,8 +46,10 @@ public:
|
|||
// for compiler generated call, never used
|
||||
static void operator delete(void*) { assert(0); }
|
||||
private:
|
||||
#if defined(__hpux)
|
||||
// don't allow dynamic creation of exceptions
|
||||
static void* operator new(size_t);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -656,7 +656,7 @@ mySTL::auto_ptr<input_buffer>
|
|||
DoProcessReply(SSL& ssl, mySTL::auto_ptr<input_buffer> buffered)
|
||||
{
|
||||
// wait for input if blocking
|
||||
if (!ssl.getSocket().wait()) {
|
||||
if (!ssl.useSocket().wait()) {
|
||||
ssl.SetError(receive_error);
|
||||
buffered.reset(0);
|
||||
return buffered;
|
||||
|
@ -673,7 +673,7 @@ DoProcessReply(SSL& ssl, mySTL::auto_ptr<input_buffer> buffered)
|
|||
}
|
||||
|
||||
// add new data
|
||||
uint read = ssl.getSocket().receive(buffer.get_buffer() + buffSz, ready);
|
||||
uint read = ssl.useSocket().receive(buffer.get_buffer() + buffSz, ready);
|
||||
buffer.add_size(read);
|
||||
uint offset = 0;
|
||||
const MessageFactory& mf = ssl.getFactory().getMessage();
|
||||
|
@ -858,6 +858,9 @@ void sendFinished(SSL& ssl, ConnectionEnd side, BufferOutput buffer)
|
|||
// send data
|
||||
int sendData(SSL& ssl, const void* buffer, int sz)
|
||||
{
|
||||
if (ssl.GetError() == YasslError(SSL_ERROR_WANT_READ))
|
||||
ssl.SetError(no_error);
|
||||
|
||||
ssl.verfiyHandShakeComplete();
|
||||
if (ssl.GetError()) return 0;
|
||||
int sent = 0;
|
||||
|
@ -893,6 +896,9 @@ int sendAlert(SSL& ssl, const Alert& alert)
|
|||
// process input data
|
||||
int receiveData(SSL& ssl, Data& data)
|
||||
{
|
||||
if (ssl.GetError() == YasslError(SSL_ERROR_WANT_READ))
|
||||
ssl.SetError(no_error);
|
||||
|
||||
ssl.verfiyHandShakeComplete();
|
||||
if (ssl.GetError()) return 0;
|
||||
|
||||
|
@ -902,6 +908,11 @@ int receiveData(SSL& ssl, Data& data)
|
|||
ssl.useLog().ShowData(data.get_length());
|
||||
|
||||
if (ssl.GetError()) return 0;
|
||||
|
||||
if (data.get_length() == 0 && ssl.getSocket().WouldBlock()) {
|
||||
ssl.SetError(YasslError(SSL_ERROR_WANT_READ));
|
||||
return SSL_WOULD_BLOCK;
|
||||
}
|
||||
return data.get_length();
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace yaSSL {
|
|||
|
||||
|
||||
Socket::Socket(socket_t s)
|
||||
: socket_(s)
|
||||
: socket_(s), wouldBlock_(false)
|
||||
{}
|
||||
|
||||
|
||||
|
@ -123,17 +123,21 @@ uint Socket::send(const byte* buf, unsigned int sz, int flags) const
|
|||
}
|
||||
|
||||
|
||||
uint Socket::receive(byte* buf, unsigned int sz, int flags) const
|
||||
uint Socket::receive(byte* buf, unsigned int sz, int flags)
|
||||
{
|
||||
assert(socket_ != INVALID_SOCKET);
|
||||
wouldBlock_ = false;
|
||||
|
||||
int recvd = ::recv(socket_, reinterpret_cast<char *>(buf), sz, flags);
|
||||
|
||||
// idea to seperate error from would block by arnetheduck@gmail.com
|
||||
if (recvd == -1) {
|
||||
if (get_lastError() == SOCKET_EWOULDBLOCK ||
|
||||
get_lastError() == SOCKET_EAGAIN)
|
||||
get_lastError() == SOCKET_EAGAIN) {
|
||||
wouldBlock_ = true;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (recvd == 0)
|
||||
return static_cast<uint>(-1);
|
||||
|
||||
|
@ -142,7 +146,7 @@ uint Socket::receive(byte* buf, unsigned int sz, int flags) const
|
|||
|
||||
|
||||
// wait if blocking for input, return false for error
|
||||
bool Socket::wait() const
|
||||
bool Socket::wait()
|
||||
{
|
||||
byte b;
|
||||
return receive(&b, 1, MSG_PEEK) != static_cast<uint>(-1);
|
||||
|
@ -166,6 +170,12 @@ int Socket::get_lastError()
|
|||
}
|
||||
|
||||
|
||||
bool Socket::WouldBlock() const
|
||||
{
|
||||
return wouldBlock_;
|
||||
}
|
||||
|
||||
|
||||
void Socket::set_lastError(int errorCode)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "handshake.hpp"
|
||||
#include "yassl_int.hpp"
|
||||
#include "md5.hpp" // for TaoCrypt MD5 size assert
|
||||
#include "md4.hpp" // for TaoCrypt MD4 size assert
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -1131,17 +1132,26 @@ void* X509_get_ext_d2i(X509* x, int nid, int* crit, int* idx)
|
|||
|
||||
void MD4_Init(MD4_CTX* md4)
|
||||
{
|
||||
assert(0); // not yet supported, build compat. only
|
||||
// make sure we have a big enough buffer
|
||||
typedef char ok[sizeof(md4->buffer) >= sizeof(TaoCrypt::MD4) ? 1 : -1];
|
||||
(void) sizeof(ok);
|
||||
|
||||
// using TaoCrypt since no dynamic memory allocated
|
||||
// and no destructor will be called
|
||||
new (reinterpret_cast<yassl_pointer>(md4->buffer)) TaoCrypt::MD4();
|
||||
}
|
||||
|
||||
|
||||
void MD4_Update(MD4_CTX* md4, const void* data, unsigned long sz)
|
||||
{
|
||||
reinterpret_cast<TaoCrypt::MD4*>(md4->buffer)->Update(
|
||||
static_cast<const byte*>(data), static_cast<unsigned int>(sz));
|
||||
}
|
||||
|
||||
|
||||
void MD4_Final(unsigned char* hash, MD4_CTX* md4)
|
||||
{
|
||||
reinterpret_cast<TaoCrypt::MD4*>(md4->buffer)->Final(hash);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "hmac.hpp"
|
||||
#include "md5.hpp"
|
||||
#include "sha.hpp"
|
||||
#include "ripemd.hpp"
|
||||
#include "openssl/ssl.h"
|
||||
|
||||
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
|
||||
|
|
|
@ -26,13 +26,17 @@
|
|||
#include "runtime.hpp"
|
||||
#include "timer.hpp"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
namespace yaSSL {
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
timer_d timer()
|
||||
{
|
||||
static bool init(false);
|
||||
|
@ -57,8 +61,6 @@ namespace yaSSL {
|
|||
|
||||
#else // _WIN32
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
timer_d timer()
|
||||
{
|
||||
struct timeval tv;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "runtime.hpp"
|
||||
#include "yassl_error.hpp"
|
||||
#include "error.hpp" // TaoCrypt error numbers
|
||||
#include "openssl/ssl.h" // SSL_ERROR_WANT_READ
|
||||
|
||||
namespace yaSSL {
|
||||
|
||||
|
@ -117,6 +118,11 @@ void SetErrorString(YasslError error, char* buffer)
|
|||
strncpy(buffer, "unable to proccess cerificate", max);
|
||||
break;
|
||||
|
||||
// openssl errors
|
||||
case SSL_ERROR_WANT_READ :
|
||||
strncpy(buffer, "the read operation would block", max);
|
||||
break;
|
||||
|
||||
// TaoCrypt errors
|
||||
case NO_ERROR :
|
||||
strncpy(buffer, "not in error state", max);
|
||||
|
|
|
@ -1415,15 +1415,6 @@ BulkCipher* CryptProvider::NewDesEde()
|
|||
}
|
||||
|
||||
|
||||
extern "C" void yaSSL_CleanUp()
|
||||
{
|
||||
TaoCrypt::CleanUp();
|
||||
ysDelete(cryptProviderInstance);
|
||||
ysDelete(sslFactoryInstance);
|
||||
ysDelete(sessionsInstance);
|
||||
}
|
||||
|
||||
|
||||
typedef Mutex::Lock Lock;
|
||||
|
||||
|
||||
|
@ -2109,9 +2100,18 @@ ASN1_STRING* StringHolder::GetString()
|
|||
}
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
extern "C" void yaSSL_CleanUp()
|
||||
{
|
||||
TaoCrypt::CleanUp();
|
||||
ysDelete(yaSSL::cryptProviderInstance);
|
||||
ysDelete(yaSSL::sslFactoryInstance);
|
||||
ysDelete(yaSSL::sessionsInstance);
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
|
||||
namespace mySTL {
|
||||
template yaSSL::yassl_int_cpp_local1::SumData for_each<mySTL::list<yaSSL::input_buffer*>::iterator, yaSSL::yassl_int_cpp_local1::SumData>(mySTL::list<yaSSL::input_buffer*>::iterator, mySTL::list<yaSSL::input_buffer*>::iterator, yaSSL::yassl_int_cpp_local1::SumData);
|
||||
|
|
|
@ -2,7 +2,7 @@ INCLUDE_DIRECTORIES(../mySTL include)
|
|||
|
||||
ADD_LIBRARY(taocrypt src/aes.cpp src/aestables.cpp src/algebra.cpp src/arc4.cpp src/asn.cpp src/coding.cpp
|
||||
src/des.cpp src/dh.cpp src/dsa.cpp src/file.cpp src/hash.cpp src/integer.cpp src/md2.cpp
|
||||
src/md5.cpp src/misc.cpp src/random.cpp src/ripemd.cpp src/rsa.cpp src/sha.cpp
|
||||
src/md4.cpp src/md5.cpp src/misc.cpp src/random.cpp src/ripemd.cpp src/rsa.cpp src/sha.cpp
|
||||
include/aes.hpp include/algebra.hpp include/arc4.hpp include/asn.hpp include/block.hpp
|
||||
include/coding.hpp include/des.hpp include/dh.hpp include/dsa.hpp include/dsa.hpp
|
||||
include/error.hpp include/file.hpp include/hash.hpp include/hmac.hpp include/integer.hpp
|
||||
|
|
|
@ -96,7 +96,7 @@ public:
|
|||
|
||||
pointer allocate(size_type n, const void* = 0)
|
||||
{
|
||||
CheckSize(n);
|
||||
this->CheckSize(n);
|
||||
if (n == 0)
|
||||
return 0;
|
||||
return NEW_TC T[n];
|
||||
|
|
65
extra/yassl/taocrypt/include/md4.hpp
Normal file
65
extra/yassl/taocrypt/include/md4.hpp
Normal file
|
@ -0,0 +1,65 @@
|
|||
/* md4.hpp
|
||||
*
|
||||
* Copyright (C) 2003 Sawtooth Consulting Ltd.
|
||||
*
|
||||
* This file is part of yaSSL.
|
||||
*
|
||||
* yaSSL is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* yaSSL is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
/* md4.hpp provides MD4 digest support
|
||||
* WANRING: MD4 is considered insecure, only use if you have to, e.g., yaSSL
|
||||
* libcurl supports needs this for NTLM authentication
|
||||
*/
|
||||
|
||||
#ifndef TAO_CRYPT_MD4_HPP
|
||||
#define TAO_CRYPT_MD4_HPP
|
||||
|
||||
#include "hash.hpp"
|
||||
|
||||
namespace TaoCrypt {
|
||||
|
||||
|
||||
// MD4 digest
|
||||
class MD4 : public HASHwithTransform {
|
||||
public:
|
||||
enum { BLOCK_SIZE = 64, DIGEST_SIZE = 16, PAD_SIZE = 56,
|
||||
TAO_BYTE_ORDER = LittleEndianOrder }; // in Bytes
|
||||
MD4() : HASHwithTransform(DIGEST_SIZE / sizeof(word32), BLOCK_SIZE)
|
||||
{ Init(); }
|
||||
ByteOrder getByteOrder() const { return ByteOrder(TAO_BYTE_ORDER); }
|
||||
word32 getBlockSize() const { return BLOCK_SIZE; }
|
||||
word32 getDigestSize() const { return DIGEST_SIZE; }
|
||||
word32 getPadSize() const { return PAD_SIZE; }
|
||||
|
||||
MD4(const MD4&);
|
||||
MD4& operator= (const MD4&);
|
||||
|
||||
void Init();
|
||||
void Swap(MD4&);
|
||||
private:
|
||||
void Transform();
|
||||
};
|
||||
|
||||
inline void swap(MD4& a, MD4& b)
|
||||
{
|
||||
a.Swap(b);
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // TAO_CRYPT_MD4_HPP
|
||||
|
|
@ -28,10 +28,6 @@
|
|||
#ifndef yaSSL_NEW_HPP
|
||||
#define yaSSL_NEW_HPP
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __sun
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ noinst_LTLIBRARIES = libtaocrypt.la
|
|||
|
||||
libtaocrypt_la_SOURCES = aes.cpp aestables.cpp algebra.cpp arc4.cpp \
|
||||
asn.cpp bftables.cpp blowfish.cpp coding.cpp des.cpp dh.cpp \
|
||||
dsa.cpp file.cpp hash.cpp integer.cpp md2.cpp md5.cpp misc.cpp \
|
||||
dsa.cpp file.cpp hash.cpp integer.cpp md2.cpp md4.cpp md5.cpp misc.cpp \
|
||||
random.cpp ripemd.cpp rsa.cpp sha.cpp template_instnt.cpp \
|
||||
tftables.cpp twofish.cpp
|
||||
|
||||
|
|
154
extra/yassl/taocrypt/src/md4.cpp
Normal file
154
extra/yassl/taocrypt/src/md4.cpp
Normal file
|
@ -0,0 +1,154 @@
|
|||
/* md4.cpp
|
||||
*
|
||||
* Copyright (C) 2003 Sawtooth Consulting Ltd.
|
||||
*
|
||||
* This file is part of yaSSL.
|
||||
*
|
||||
* yaSSL is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* yaSSL is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
|
||||
/* based on Wei Dai's md4.cpp from CryptoPP */
|
||||
|
||||
#include "runtime.hpp"
|
||||
#include "md4.hpp"
|
||||
#include "algorithm.hpp" // mySTL::swap
|
||||
|
||||
|
||||
|
||||
namespace TaoCrypt {
|
||||
|
||||
void MD4::Init()
|
||||
{
|
||||
digest_[0] = 0x67452301L;
|
||||
digest_[1] = 0xefcdab89L;
|
||||
digest_[2] = 0x98badcfeL;
|
||||
digest_[3] = 0x10325476L;
|
||||
|
||||
buffLen_ = 0;
|
||||
loLen_ = 0;
|
||||
hiLen_ = 0;
|
||||
}
|
||||
|
||||
|
||||
MD4::MD4(const MD4& that) : HASHwithTransform(DIGEST_SIZE / sizeof(word32),
|
||||
BLOCK_SIZE)
|
||||
{
|
||||
buffLen_ = that.buffLen_;
|
||||
loLen_ = that.loLen_;
|
||||
hiLen_ = that.hiLen_;
|
||||
|
||||
memcpy(digest_, that.digest_, DIGEST_SIZE);
|
||||
memcpy(buffer_, that.buffer_, BLOCK_SIZE);
|
||||
}
|
||||
|
||||
MD4& MD4::operator= (const MD4& that)
|
||||
{
|
||||
MD4 tmp(that);
|
||||
Swap(tmp);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void MD4::Swap(MD4& other)
|
||||
{
|
||||
mySTL::swap(loLen_, other.loLen_);
|
||||
mySTL::swap(hiLen_, other.hiLen_);
|
||||
mySTL::swap(buffLen_, other.buffLen_);
|
||||
|
||||
memcpy(digest_, other.digest_, DIGEST_SIZE);
|
||||
memcpy(buffer_, other.buffer_, BLOCK_SIZE);
|
||||
}
|
||||
|
||||
|
||||
void MD4::Transform()
|
||||
{
|
||||
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
|
||||
#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
|
||||
word32 A, B, C, D;
|
||||
|
||||
A = digest_[0];
|
||||
B = digest_[1];
|
||||
C = digest_[2];
|
||||
D = digest_[3];
|
||||
|
||||
#define function(a,b,c,d,k,s) a=rotlFixed(a+F(b,c,d)+buffer_[k],s);
|
||||
function(A,B,C,D, 0, 3);
|
||||
function(D,A,B,C, 1, 7);
|
||||
function(C,D,A,B, 2,11);
|
||||
function(B,C,D,A, 3,19);
|
||||
function(A,B,C,D, 4, 3);
|
||||
function(D,A,B,C, 5, 7);
|
||||
function(C,D,A,B, 6,11);
|
||||
function(B,C,D,A, 7,19);
|
||||
function(A,B,C,D, 8, 3);
|
||||
function(D,A,B,C, 9, 7);
|
||||
function(C,D,A,B,10,11);
|
||||
function(B,C,D,A,11,19);
|
||||
function(A,B,C,D,12, 3);
|
||||
function(D,A,B,C,13, 7);
|
||||
function(C,D,A,B,14,11);
|
||||
function(B,C,D,A,15,19);
|
||||
|
||||
#undef function
|
||||
#define function(a,b,c,d,k,s) a=rotlFixed(a+G(b,c,d)+buffer_[k]+0x5a827999,s);
|
||||
function(A,B,C,D, 0, 3);
|
||||
function(D,A,B,C, 4, 5);
|
||||
function(C,D,A,B, 8, 9);
|
||||
function(B,C,D,A,12,13);
|
||||
function(A,B,C,D, 1, 3);
|
||||
function(D,A,B,C, 5, 5);
|
||||
function(C,D,A,B, 9, 9);
|
||||
function(B,C,D,A,13,13);
|
||||
function(A,B,C,D, 2, 3);
|
||||
function(D,A,B,C, 6, 5);
|
||||
function(C,D,A,B,10, 9);
|
||||
function(B,C,D,A,14,13);
|
||||
function(A,B,C,D, 3, 3);
|
||||
function(D,A,B,C, 7, 5);
|
||||
function(C,D,A,B,11, 9);
|
||||
function(B,C,D,A,15,13);
|
||||
|
||||
#undef function
|
||||
#define function(a,b,c,d,k,s) a=rotlFixed(a+H(b,c,d)+buffer_[k]+0x6ed9eba1,s);
|
||||
function(A,B,C,D, 0, 3);
|
||||
function(D,A,B,C, 8, 9);
|
||||
function(C,D,A,B, 4,11);
|
||||
function(B,C,D,A,12,15);
|
||||
function(A,B,C,D, 2, 3);
|
||||
function(D,A,B,C,10, 9);
|
||||
function(C,D,A,B, 6,11);
|
||||
function(B,C,D,A,14,15);
|
||||
function(A,B,C,D, 1, 3);
|
||||
function(D,A,B,C, 9, 9);
|
||||
function(C,D,A,B, 5,11);
|
||||
function(B,C,D,A,13,15);
|
||||
function(A,B,C,D, 3, 3);
|
||||
function(D,A,B,C,11, 9);
|
||||
function(C,D,A,B, 7,11);
|
||||
function(B,C,D,A,15,15);
|
||||
|
||||
digest_[0] += A;
|
||||
digest_[1] += B;
|
||||
digest_[2] += C;
|
||||
digest_[3] += D;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
|
@ -30,11 +30,11 @@
|
|||
#include "sha.hpp"
|
||||
#include "md5.hpp"
|
||||
#include "hmac.hpp"
|
||||
#include "ripemd.hpp"
|
||||
#include "pwdbased.hpp"
|
||||
#include "algebra.hpp"
|
||||
#include "vector.hpp"
|
||||
#include "hash.hpp"
|
||||
#include "ripemd.hpp"
|
||||
|
||||
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
|
||||
namespace TaoCrypt {
|
||||
|
|
|
@ -146,6 +146,10 @@ SOURCE=.\src\md2.cpp
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\md4.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\md5.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -246,6 +250,10 @@ SOURCE=.\include\md2.hpp
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\include\md4.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\include\md5.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "sha.hpp"
|
||||
#include "md5.hpp"
|
||||
#include "md2.hpp"
|
||||
#include "md4.hpp"
|
||||
#include "ripemd.hpp"
|
||||
#include "hmac.hpp"
|
||||
#include "arc4.hpp"
|
||||
|
@ -30,6 +31,7 @@ using TaoCrypt::word32;
|
|||
using TaoCrypt::SHA;
|
||||
using TaoCrypt::MD5;
|
||||
using TaoCrypt::MD2;
|
||||
using TaoCrypt::MD4;
|
||||
using TaoCrypt::RIPEMD160;
|
||||
using TaoCrypt::HMAC;
|
||||
using TaoCrypt::ARC4;
|
||||
|
@ -89,6 +91,7 @@ void file_test(int, char**);
|
|||
int sha_test();
|
||||
int md5_test();
|
||||
int md2_test();
|
||||
int md4_test();
|
||||
int ripemd_test();
|
||||
int hmac_test();
|
||||
int arc4_test();
|
||||
|
@ -165,6 +168,11 @@ void taocrypt_test(void* args)
|
|||
else
|
||||
printf( "MD2 test passed!\n");
|
||||
|
||||
if ( (ret = md4_test()) )
|
||||
err_sys("MD4 test failed!\n", ret);
|
||||
else
|
||||
printf( "MD4 test passed!\n");
|
||||
|
||||
if ( (ret = ripemd_test()) )
|
||||
err_sys("RIPEMD test failed!\n", ret);
|
||||
else
|
||||
|
@ -348,6 +356,51 @@ int md5_test()
|
|||
}
|
||||
|
||||
|
||||
int md4_test()
|
||||
{
|
||||
MD4 md4;
|
||||
byte hash[MD4::DIGEST_SIZE];
|
||||
|
||||
testVector test_md4[] =
|
||||
{
|
||||
testVector("",
|
||||
"\x31\xd6\xcf\xe0\xd1\x6a\xe9\x31\xb7\x3c\x59\xd7\xe0\xc0\x89"
|
||||
"\xc0"),
|
||||
testVector("a",
|
||||
"\xbd\xe5\x2c\xb3\x1d\xe3\x3e\x46\x24\x5e\x05\xfb\xdb\xd6\xfb"
|
||||
"\x24"),
|
||||
testVector("abc",
|
||||
"\xa4\x48\x01\x7a\xaf\x21\xd8\x52\x5f\xc1\x0a\xe8\x7a\xa6\x72"
|
||||
"\x9d"),
|
||||
testVector("message digest",
|
||||
"\xd9\x13\x0a\x81\x64\x54\x9f\xe8\x18\x87\x48\x06\xe1\xc7\x01"
|
||||
"\x4b"),
|
||||
testVector("abcdefghijklmnopqrstuvwxyz",
|
||||
"\xd7\x9e\x1c\x30\x8a\xa5\xbb\xcd\xee\xa8\xed\x63\xdf\x41\x2d"
|
||||
"\xa9"),
|
||||
testVector("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345"
|
||||
"6789",
|
||||
"\x04\x3f\x85\x82\xf2\x41\xdb\x35\x1c\xe6\x27\xe1\x53\xe7\xf0"
|
||||
"\xe4"),
|
||||
testVector("1234567890123456789012345678901234567890123456789012345678"
|
||||
"9012345678901234567890",
|
||||
"\xe3\x3b\x4d\xdc\x9c\x38\xf2\x19\x9c\x3e\x7b\x16\x4f\xcc\x05"
|
||||
"\x36")
|
||||
};
|
||||
|
||||
int times( sizeof(test_md4) / sizeof(testVector) );
|
||||
for (int i = 0; i < times; ++i) {
|
||||
md4.Update(test_md4[i].input_, test_md4[i].inLen_);
|
||||
md4.Final(hash);
|
||||
|
||||
if (memcmp(hash, test_md4[i].output_, MD4::DIGEST_SIZE) != 0)
|
||||
return -5 - i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int md2_test()
|
||||
{
|
||||
MD2 md5;
|
||||
|
|
|
@ -33,10 +33,16 @@
|
|||
|
||||
|
||||
// HPUX doesn't use socklent_t for third parameter to accept
|
||||
#if !defined(__hpux__)
|
||||
#if !defined(__hpux)
|
||||
typedef socklen_t* ACCEPT_THIRD_T;
|
||||
#else
|
||||
typedef int* ACCEPT_THIRD_T;
|
||||
|
||||
// HPUX does not define _POSIX_THREADS as it's not _fully_ implemented
|
||||
#ifndef _POSIX_THREADS
|
||||
#define _POSIX_THREADS
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
|
|||
spatial.cc gstream.cc sql_help.cc tztime.cc sql_cursor.cc \
|
||||
sp_head.cc sp_pcontext.cc sp.cc sp_cache.cc sp_rcontext.cc \
|
||||
parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \
|
||||
event_executor.cc event.cc event_timed.cc \
|
||||
event_scheduler.cc event.cc event_timed.cc \
|
||||
rpl_filter.cc sql_partition.cc sql_builtin.cc sql_plugin.cc \
|
||||
sql_tablespace.cc \
|
||||
rpl_injector.cc my_user.c partition_info.cc
|
||||
|
|
|
@ -17,13 +17,13 @@ db_x
|
|||
SHOW TABLES FROM db_x;
|
||||
Tables_in_db_x
|
||||
x_table
|
||||
SET GLOBAL event_scheduler=0;
|
||||
SET GLOBAL event_scheduler=2;
|
||||
DROP EVENT e_x1;
|
||||
DROP EVENT e_x2;
|
||||
DROP DATABASE db_x;
|
||||
DROP USER pauline@localhost;
|
||||
USE events_test;
|
||||
SET GLOBAL event_scheduler=0;
|
||||
SET GLOBAL event_scheduler=2;
|
||||
drop event if exists event1;
|
||||
Warnings:
|
||||
Note 1305 Event event1 does not exist
|
||||
|
@ -100,7 +100,7 @@ a
|
|||
800219
|
||||
drop event non_qualif_ev;
|
||||
drop table non_qualif;
|
||||
set global event_scheduler = 0;
|
||||
set global event_scheduler = 2;
|
||||
create table t_event3 (a int, b float);
|
||||
drop event if exists event3;
|
||||
Warnings:
|
||||
|
@ -324,18 +324,18 @@ events_test one_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
|
|||
events_test three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
|
||||
events_test two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
|
||||
"This should show us only 3 events:";
|
||||
SHOW FULL EVENTS;
|
||||
SHOW EVENTS;
|
||||
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
|
||||
events_test one_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
|
||||
events_test three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
|
||||
events_test two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
|
||||
"This should show us only 2 events:";
|
||||
SHOW FULL EVENTS LIKE 't%event';
|
||||
SHOW EVENTS LIKE 't%event';
|
||||
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
|
||||
events_test three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
|
||||
events_test two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
|
||||
"This should show us no events:";
|
||||
SHOW FULL EVENTS FROM test LIKE '%';
|
||||
SHOW EVENTS FROM test LIKE '%';
|
||||
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
|
||||
DROP DATABASE events_test2;
|
||||
"should see 1 event:";
|
||||
|
@ -343,11 +343,8 @@ SHOW EVENTS;
|
|||
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
|
||||
events_test one_event root@localhost RECURRING NULL 10 SECOND # # ENABLED
|
||||
"we should see 4 events now:";
|
||||
SHOW FULL EVENTS;
|
||||
SHOW EVENTS;
|
||||
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
|
||||
events_test one_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
|
||||
events_test three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
|
||||
events_test two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
|
||||
events_test one_event root@localhost RECURRING NULL 10 SECOND # # ENABLED
|
||||
SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events;
|
||||
EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT
|
||||
|
@ -373,12 +370,12 @@ ERROR HY000: Incorrect AT value: 'definitely not a datetime'
|
|||
set names utf8;
|
||||
create event задачка on schedule every 123 minute starts now() ends now() + interval 1 month do select 1;
|
||||
drop event задачка;
|
||||
set event_scheduler=0;
|
||||
set event_scheduler=2;
|
||||
ERROR HY000: Variable 'event_scheduler' is a GLOBAL variable and should be set with SET GLOBAL
|
||||
set global event_scheduler=2;
|
||||
ERROR 42000: Variable 'event_scheduler' can't be set to the value of '2'
|
||||
set global event_scheduler=3;
|
||||
ERROR 42000: Variable 'event_scheduler' can't be set to the value of '3'
|
||||
"DISABLE the scheduler. Testing that it does not work when the variable is 0"
|
||||
set global event_scheduler=0;
|
||||
set global event_scheduler=2;
|
||||
select definer, name, db from mysql.event;
|
||||
definer name db
|
||||
select get_lock("test_lock1", 20);
|
||||
|
@ -389,9 +386,10 @@ create event закачка on schedule every 10 hour do select get_lock("test_l
|
|||
select definer, name, db from mysql.event;
|
||||
definer name db
|
||||
root@localhost закачка events_test
|
||||
"Should be 0 processes"
|
||||
"Should be only 1 process"
|
||||
select /*1*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
|
||||
user host db command state info
|
||||
event_scheduler localhost NULL Connect Suspended NULL
|
||||
select release_lock("test_lock1");
|
||||
release_lock("test_lock1")
|
||||
1
|
||||
|
@ -409,11 +407,12 @@ get_lock("test_lock2", 20)
|
|||
create event закачка on schedule every 10 hour do select get_lock("test_lock2", 20);
|
||||
"Let some time pass to the event starts"
|
||||
"Should have only 2 processes: the scheduler and the locked event"
|
||||
select /*1*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
|
||||
select /*2*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
|
||||
user host db command state info
|
||||
event_scheduler localhost NULL Connect Sleeping NULL
|
||||
root localhost events_test Connect User lock select get_lock("test_lock2", 20)
|
||||
"Release the mutex, the event worker should finish."
|
||||
"Release the mutex, the event worker should finish."
|
||||
select release_lock("test_lock2");
|
||||
release_lock("test_lock2")
|
||||
1
|
||||
|
@ -423,21 +422,17 @@ select get_lock("test_lock2_1", 20);
|
|||
get_lock("test_lock2_1", 20)
|
||||
1
|
||||
create event закачка21 on schedule every 10 hour do select get_lock("test_lock2_1", 20);
|
||||
"Should see 1 process, locked on get_lock("
|
||||
"Shutting down the scheduler, it should wait for the running event"
|
||||
set global event_scheduler=0;
|
||||
"Should have only 2 processes: the scheduler and the locked event"
|
||||
select /*4*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
|
||||
"Should have only 3 processes: the scheduler, our conn and the locked event"
|
||||
select /*3*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
|
||||
user host db command state info
|
||||
event_scheduler localhost NULL Connect Sleeping NULL
|
||||
root localhost events_test Connect User lock select get_lock("test_lock2_1", 20)
|
||||
"Release the lock so the child process should finish. Hence the scheduler also"
|
||||
select release_lock("test_lock2_1");
|
||||
release_lock("test_lock2_1")
|
||||
1
|
||||
"Should see 0 processes now:"
|
||||
select /*5*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
|
||||
set global event_scheduler=2;
|
||||
"Should have only our process now:"
|
||||
select /*4*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
|
||||
user host db command state info
|
||||
event_scheduler localhost NULL Connect Suspended NULL
|
||||
root localhost events_test Connect User lock select get_lock("test_lock2_1", 20)
|
||||
drop event закачка21;
|
||||
create table t_16 (s1 int);
|
||||
create trigger t_16_bi before insert on t_16 for each row create event e_16 on schedule every 1 second do set @a=5;
|
||||
|
@ -457,6 +452,9 @@ select 2;
|
|||
select event_schema, event_name, definer, event_body from information_schema.events where event_name='white_space';
|
||||
event_schema event_name definer event_body
|
||||
events_test white_space root@localhost select 2
|
||||
select event_schema, event_name, definer, event_body from information_schema.events where event_name='white_space';
|
||||
event_schema event_name definer event_body
|
||||
events_test white_space root@localhost select 2
|
||||
drop event white_space;
|
||||
create event white_space on schedule every 10 hour disable do select 3;
|
||||
select event_schema, event_name, definer, event_body from information_schema.events where event_name='white_space';
|
||||
|
|
|
@ -35,7 +35,7 @@ create event e_55 on schedule every 10 hour starts 99990101000000 do drop table
|
|||
ERROR HY000: Incorrect STARTS value: '99990101000000'
|
||||
create event e_55 on schedule every 10 minute ends 99990101000000 do drop table t;
|
||||
ERROR HY000: ENDS is either invalid or before STARTS
|
||||
set global event_scheduler=0;
|
||||
set global event_scheduler=2;
|
||||
"Wait a bit to settle down"
|
||||
delete from mysql.event;
|
||||
set global event_scheduler= 1;
|
||||
|
@ -57,7 +57,7 @@ root localhost events_test Connect User lock select get_lock('test_bug16407', 60
|
|||
select release_lock('test_bug16407');
|
||||
release_lock('test_bug16407')
|
||||
1
|
||||
set global event_scheduler= 0;
|
||||
set global event_scheduler= 2;
|
||||
select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
|
||||
event_schema event_name sql_mode
|
||||
events_test e_16407 REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI
|
||||
|
@ -115,7 +115,7 @@ release_lock('ee_16407_2')
|
|||
select /*3*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
|
||||
user host db command state info
|
||||
event_scheduler localhost NULL Connect Sleeping NULL
|
||||
set global event_scheduler= 0;
|
||||
set global event_scheduler= 2;
|
||||
select * from events_smode_test order by ev_name, a;
|
||||
ev_name a
|
||||
ee_16407_3 1980-02-19
|
||||
|
@ -175,7 +175,7 @@ drop event ee_16407_5;
|
|||
drop event ee_16407_6;
|
||||
drop procedure ee_16407_5_pendant;
|
||||
drop procedure ee_16407_6_pendant;
|
||||
set global event_scheduler= 0;
|
||||
set global event_scheduler= 2;
|
||||
drop table events_smode_test;
|
||||
set sql_mode=@old_sql_mode;
|
||||
drop database events_test;
|
||||
|
|
|
@ -8,7 +8,7 @@ BEGIN
|
|||
SELECT user_host, argument FROM mysql.general_log WHERE argument LIKE '%alabala%';
|
||||
END|
|
||||
"Check General Query Log"
|
||||
SET GLOBAL event_scheduler=0;
|
||||
SET GLOBAL event_scheduler=2;
|
||||
create event log_general on schedule every 1 minute do SELect 'alabala', sleep(3) from dual;
|
||||
TRUNCATE mysql.general_log;
|
||||
"1 row, the current statement!"
|
||||
|
@ -22,7 +22,7 @@ user_host argument
|
|||
root[root] @ localhost [localhost] SELect 'alabala', sleep(3) from dual
|
||||
DROP PROCEDURE select_general_log;
|
||||
DROP EVENT log_general;
|
||||
SET GLOBAL event_scheduler=0;
|
||||
SET GLOBAL event_scheduler=2;
|
||||
"Check slow query log"
|
||||
"Save the values"
|
||||
SET @old_global_long_query_time:=(select get_value());
|
||||
|
@ -36,14 +36,14 @@ SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
|
|||
user_host query_time db sql_text
|
||||
"Set new values"
|
||||
SET GLOBAL long_query_time=4;
|
||||
SET SESSION long_query_time=2;
|
||||
SET SESSION long_query_time=1;
|
||||
"Check that logging is working"
|
||||
SELECT SLEEP(3);
|
||||
SLEEP(3)
|
||||
SELECT SLEEP(2);
|
||||
SLEEP(2)
|
||||
0
|
||||
SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
|
||||
user_host query_time db sql_text
|
||||
root[root] @ localhost [] SLEEPVAL events_test SELECT SLEEP(3)
|
||||
root[root] @ localhost [] SLEEPVAL events_test SELECT SLEEP(2)
|
||||
TRUNCATE mysql.slow_log;
|
||||
CREATE TABLE slow_event_test (slo_val tinyint, val tinyint);
|
||||
"This won't go to the slow log"
|
||||
|
@ -54,7 +54,7 @@ SET GLOBAL event_scheduler=1;
|
|||
"Sleep some more time than the actual event run will take"
|
||||
SHOW VARIABLES LIKE 'event_scheduler';
|
||||
Variable_name Value
|
||||
event_scheduler ON
|
||||
event_scheduler 1
|
||||
"Check our table. Should see 1 row"
|
||||
SELECT * FROM slow_event_test;
|
||||
slo_val val
|
||||
|
@ -64,18 +64,19 @@ SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
|
|||
user_host query_time db sql_text
|
||||
"This should go to the slow log"
|
||||
SET SESSION long_query_time=10;
|
||||
SET GLOBAL long_query_time=1;
|
||||
DROP EVENT long_event;
|
||||
CREATE EVENT long_event2 ON SCHEDULE EVERY 1 MINUTE DO INSERT INTO slow_event_test SELECT @@long_query_time, SLEEP(5);
|
||||
CREATE EVENT long_event2 ON SCHEDULE EVERY 1 MINUTE DO INSERT INTO slow_event_test SELECT @@long_query_time, SLEEP(2);
|
||||
"Sleep some more time than the actual event run will take"
|
||||
"Check our table. Should see 2 rows"
|
||||
SELECT * FROM slow_event_test;
|
||||
slo_val val
|
||||
4 0
|
||||
4 0
|
||||
"Check slow log. Should see 1 row because 5 is over the threshold of 4 for GLOBAL, though under SESSION which is 10"
|
||||
1 0
|
||||
"Check slow log. Should see 1 row because 4 is over the threshold of 3 for GLOBAL, though under SESSION which is 10"
|
||||
SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
|
||||
user_host query_time db sql_text
|
||||
root[root] @ localhost [localhost] SLEEPVAL events_test INSERT INTO slow_event_test SELECT @@long_query_time, SLEEP(5)
|
||||
root[root] @ localhost [localhost] SLEEPVAL events_test INSERT INTO slow_event_test SELECT @@long_query_time, SLEEP(2)
|
||||
DROP EVENT long_event2;
|
||||
SET GLOBAL long_query_time =@old_global_long_query_time;
|
||||
SET SESSION long_query_time =@old_session_long_query_time;
|
||||
|
|
|
@ -10,50 +10,4 @@ CREATE EVENT micro_test ON SCHEDULE EVERY 100 MINUTE_MICROSECOND DO SELECT 1;
|
|||
ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND'
|
||||
CREATE EVENT micro_test ON SCHEDULE EVERY 100 SECOND_MICROSECOND DO SELECT 1;
|
||||
ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND'
|
||||
"Now create normal event and change it on SQL level"
|
||||
CREATE EVENT micro_test2 ON SCHEDULE EVERY 1 MONTH DO SELECT 1;
|
||||
UPDATE mysql.event SET interval_field='MICROSECOND' WHERE db=database() AND definer=user() AND name='micro_test2';
|
||||
SHOW CREATE EVENT micro_test2;
|
||||
ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND'
|
||||
SET GLOBAL event_scheduler=0;
|
||||
"Should not be running:"
|
||||
SHOW VARIABLES like 'event_scheduler';
|
||||
Variable_name Value
|
||||
event_scheduler OFF
|
||||
UPDATE mysql.event SET interval_field='DAY_MICROSECOND' WHERE db=database() AND definer=user() AND name='micro_test2';
|
||||
SHOW CREATE EVENT micro_test2;
|
||||
ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND'
|
||||
SET GLOBAL event_scheduler=0;
|
||||
"Should not be running:"
|
||||
SHOW VARIABLES like 'event_scheduler';
|
||||
Variable_name Value
|
||||
event_scheduler OFF
|
||||
UPDATE mysql.event SET interval_field='SECOND_MICROSECOND' WHERE db=database() AND definer=user() AND name='micro_test2';
|
||||
SHOW CREATE EVENT micro_test2;
|
||||
ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND'
|
||||
SET GLOBAL event_scheduler=0;
|
||||
"Should not be running:"
|
||||
SHOW VARIABLES like 'event_scheduler';
|
||||
Variable_name Value
|
||||
event_scheduler OFF
|
||||
UPDATE mysql.event SET interval_field='HOUR_MICROSECOND' WHERE db=database() AND definer=user() AND name='micro_test2';
|
||||
SHOW CREATE EVENT micro_test2;
|
||||
ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND'
|
||||
SET GLOBAL event_scheduler=0;
|
||||
"Should not be running:"
|
||||
SHOW VARIABLES like 'event_scheduler';
|
||||
Variable_name Value
|
||||
event_scheduler OFF
|
||||
UPDATE mysql.event SET interval_field='MINUTE_MICROSECOND' WHERE db=database() AND definer=user() AND name='micro_test2';
|
||||
SHOW CREATE EVENT micro_test2;
|
||||
ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND'
|
||||
SET GLOBAL event_scheduler=0;
|
||||
"Should not be running:"
|
||||
SHOW VARIABLES like 'event_scheduler';
|
||||
Variable_name Value
|
||||
event_scheduler OFF
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER='event_scheduler';
|
||||
COUNT(*)
|
||||
0
|
||||
DROP EVENT micro_test2;
|
||||
drop database events_test;
|
||||
|
|
|
@ -14,7 +14,7 @@ ENDS NOW() + INTERVAL 6 SECOND
|
|||
ON COMPLETION PRESERVE
|
||||
DO INSERT INTO table_2 VALUES(1);
|
||||
CREATE EVENT only_one_time ON SCHEDULE EVERY 2 SECOND ENDS NOW() + INTERVAL 1 SECOND DO INSERT INTO table_3 VALUES(1);
|
||||
CREATE EVENT two_time ON SCHEDULE EVERY 1 SECOND ENDS NOW() + INTERVAL 1 SECOND DO INSERT INTO table_4 VALUES(1);
|
||||
CREATE EVENT two_time ON SCHEDULE EVERY 1 SECOND ENDS NOW() + INTERVAL 1 SECOND ON COMPLETION PRESERVE DO INSERT INTO table_4 VALUES(1);
|
||||
SELECT IF(SUM(a) >= 4, 'OK', 'ERROR') FROM table_1;
|
||||
IF(SUM(a) >= 4, 'OK', 'ERROR')
|
||||
OK
|
||||
|
@ -38,9 +38,12 @@ DROP EVENT start_n_end;
|
|||
"Already dropped because ended. Therefore an error."
|
||||
DROP EVENT only_one_time;
|
||||
ERROR HY000: Unknown event 'only_one_time'
|
||||
"Already dropped because ended. Therefore an error."
|
||||
"Should be preserved"
|
||||
SELECT EVENT_NAME, STATUS FROM INFORMATION_SCHEMA.EVENTS;
|
||||
EVENT_NAME STATUS
|
||||
E19170 ENABLED
|
||||
two_time DISABLED
|
||||
DROP EVENT two_time;
|
||||
ERROR HY000: Unknown event 'two_time'
|
||||
DROP TABLE table_1;
|
||||
DROP TABLE table_2;
|
||||
DROP TABLE table_3;
|
||||
|
|
|
@ -1,46 +1,61 @@
|
|||
CREATE DATABASE IF NOT EXISTS events_test;
|
||||
CREATE DATABASE events_test2;
|
||||
USE events_test2;
|
||||
CREATE DATABASE events_conn1_test2;
|
||||
CREATE TABLE events_test.fill_it(test_name varchar(20), occur datetime);
|
||||
CREATE USER event_user2@localhost;
|
||||
CREATE DATABASE events_conn2_db;
|
||||
GRANT ALL ON *.* TO event_user2@localhost;
|
||||
CREATE USER event_user3@localhost;
|
||||
CREATE DATABASE events_conn3_db;
|
||||
GRANT ALL ON *.* TO event_user3@localhost;
|
||||
"In the second connection we create some events which won't be dropped till the end"
|
||||
"In the second connection we create some events which won't be dropped till the end"
|
||||
USE events_conn1_test2;
|
||||
CREATE EVENT ev_drop1 ON SCHEDULE EVERY 10 MINUTE DISABLE DO SELECT 1;
|
||||
CREATE EVENT ev_drop2 ON SCHEDULE EVERY 10 MINUTE DISABLE DO SELECT 1;
|
||||
CREATE EVENT ev_drop3 ON SCHEDULE EVERY 10 MINUTE DISABLE DO SELECT 1;
|
||||
USE events_test;
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS;
|
||||
COUNT(*)
|
||||
203
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
|
||||
COUNT(*)
|
||||
3
|
||||
DROP DATABASE events_test2;
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
|
||||
DROP DATABASE events_conn1_test2;
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
|
||||
COUNT(*)
|
||||
0
|
||||
"Now testing stability - dropping db -> events while they are running"
|
||||
CREATE DATABASE events_test2;
|
||||
USE events_test2;
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
|
||||
CREATE DATABASE events_conn1_test2;
|
||||
USE events_conn1_test2;
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
|
||||
COUNT(*)
|
||||
1000
|
||||
100
|
||||
SET GLOBAL event_scheduler=1;
|
||||
DROP DATABASE events_test2;
|
||||
SET GLOBAL event_scheduler=0;
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
|
||||
DROP DATABASE events_conn1_test2;
|
||||
SET GLOBAL event_scheduler=2;
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
|
||||
COUNT(*)
|
||||
0
|
||||
CREATE DATABASE events_test3;
|
||||
USE events_test3;
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test3';
|
||||
COUNT(*)
|
||||
950
|
||||
CREATE DATABASE events_test4;
|
||||
USE events_test4;
|
||||
CREATE DATABASE events_test2;
|
||||
USE events_test2;
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
|
||||
COUNT(*)
|
||||
1050
|
||||
DROP DATABASE events_test2;
|
||||
SET GLOBAL event_scheduler=0;
|
||||
DROP DATABASE events_test3;
|
||||
CREATE DATABASE events_conn1_test3;
|
||||
USE events_conn1_test3;
|
||||
SET GLOBAL event_scheduler=1;
|
||||
DROP DATABASE events_test4;
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test3';
|
||||
COUNT(*)
|
||||
100
|
||||
CREATE DATABASE events_conn1_test4;
|
||||
USE events_conn1_test4;
|
||||
CREATE DATABASE events_conn1_test2;
|
||||
USE events_conn1_test2;
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
|
||||
COUNT(*)
|
||||
100
|
||||
DROP DATABASE events_conn2_db;
|
||||
DROP DATABASE events_conn3_db;
|
||||
DROP DATABASE events_conn1_test2;
|
||||
DROP DATABASE events_conn1_test3;
|
||||
SET GLOBAL event_scheduler=2;
|
||||
DROP DATABASE events_conn1_test4;
|
||||
SET GLOBAL event_scheduler=1;
|
||||
USE events_test;
|
||||
DROP TABLE fill_it;
|
||||
DROP DATABASE events_test;
|
||||
|
|
|
@ -821,144 +821,6 @@ SELECT MAX(id) FROM t1 WHERE id < 3 AND a=2 AND b=6;
|
|||
MAX(id)
|
||||
NULL
|
||||
DROP TABLE t1;
|
||||
create table t1m (a int) engine=myisam;
|
||||
create table t1i (a int) engine=innodb;
|
||||
create table t2m (a int) engine=myisam;
|
||||
create table t2i (a int) engine=innodb;
|
||||
insert into t2m values (5);
|
||||
insert into t2i values (5);
|
||||
select min(a) from t1m;
|
||||
min(a)
|
||||
NULL
|
||||
select min(7) from t1m;
|
||||
min(7)
|
||||
NULL
|
||||
select min(7) from DUAL;
|
||||
min(7)
|
||||
NULL
|
||||
explain select min(7) from t2m join t1m;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
||||
select min(7) from t2m join t1m;
|
||||
min(7)
|
||||
NULL
|
||||
select max(a) from t1m;
|
||||
max(a)
|
||||
NULL
|
||||
select max(7) from t1m;
|
||||
max(7)
|
||||
NULL
|
||||
select max(7) from DUAL;
|
||||
max(7)
|
||||
NULL
|
||||
explain select max(7) from t2m join t1m;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
||||
select max(7) from t2m join t1m;
|
||||
max(7)
|
||||
NULL
|
||||
select 1, min(a) from t1m where a=99;
|
||||
1 min(a)
|
||||
1 NULL
|
||||
select 1, min(a) from t1m where 1=99;
|
||||
1 min(a)
|
||||
1 NULL
|
||||
select 1, min(1) from t1m where a=99;
|
||||
1 min(1)
|
||||
1 NULL
|
||||
select 1, min(1) from t1m where 1=99;
|
||||
1 min(1)
|
||||
1 NULL
|
||||
select 1, max(a) from t1m where a=99;
|
||||
1 max(a)
|
||||
1 NULL
|
||||
select 1, max(a) from t1m where 1=99;
|
||||
1 max(a)
|
||||
1 NULL
|
||||
select 1, max(1) from t1m where a=99;
|
||||
1 max(1)
|
||||
1 NULL
|
||||
select 1, max(1) from t1m where 1=99;
|
||||
1 max(1)
|
||||
1 NULL
|
||||
select min(a) from t1i;
|
||||
min(a)
|
||||
NULL
|
||||
select min(7) from t1i;
|
||||
min(7)
|
||||
NULL
|
||||
select min(7) from DUAL;
|
||||
min(7)
|
||||
NULL
|
||||
explain select min(7) from t2i join t1i;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2i ALL NULL NULL NULL NULL 1
|
||||
1 SIMPLE t1i ALL NULL NULL NULL NULL 1
|
||||
select min(7) from t2i join t1i;
|
||||
min(7)
|
||||
NULL
|
||||
select max(a) from t1i;
|
||||
max(a)
|
||||
NULL
|
||||
select max(7) from t1i;
|
||||
max(7)
|
||||
NULL
|
||||
select max(7) from DUAL;
|
||||
max(7)
|
||||
NULL
|
||||
explain select max(7) from t2i join t1i;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2i ALL NULL NULL NULL NULL 1
|
||||
1 SIMPLE t1i ALL NULL NULL NULL NULL 1
|
||||
select max(7) from t2i join t1i;
|
||||
max(7)
|
||||
NULL
|
||||
select 1, min(a) from t1i where a=99;
|
||||
1 min(a)
|
||||
1 NULL
|
||||
select 1, min(a) from t1i where 1=99;
|
||||
1 min(a)
|
||||
1 NULL
|
||||
select 1, min(1) from t1i where a=99;
|
||||
1 min(1)
|
||||
1 NULL
|
||||
select 1, min(1) from t1i where 1=99;
|
||||
1 min(1)
|
||||
1 NULL
|
||||
select 1, max(a) from t1i where a=99;
|
||||
1 max(a)
|
||||
1 NULL
|
||||
select 1, max(a) from t1i where 1=99;
|
||||
1 max(a)
|
||||
1 NULL
|
||||
select 1, max(1) from t1i where a=99;
|
||||
1 max(1)
|
||||
1 NULL
|
||||
select 1, max(1) from t1i where 1=99;
|
||||
1 max(1)
|
||||
1 NULL
|
||||
explain select count(*), min(7), max(7) from t1m, t1i;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1m system NULL NULL NULL NULL 0 const row not found
|
||||
1 SIMPLE t1i ALL NULL NULL NULL NULL 1
|
||||
select count(*), min(7), max(7) from t1m, t1i;
|
||||
count(*) min(7) max(7)
|
||||
0 NULL NULL
|
||||
explain select count(*), min(7), max(7) from t1m, t2i;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1m system NULL NULL NULL NULL 0 const row not found
|
||||
1 SIMPLE t2i ALL NULL NULL NULL NULL 1
|
||||
select count(*), min(7), max(7) from t1m, t2i;
|
||||
count(*) min(7) max(7)
|
||||
0 NULL NULL
|
||||
explain select count(*), min(7), max(7) from t2m, t1i;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2m system NULL NULL NULL NULL 1
|
||||
1 SIMPLE t1i ALL NULL NULL NULL NULL 1
|
||||
select count(*), min(7), max(7) from t2m, t1i;
|
||||
count(*) min(7) max(7)
|
||||
0 NULL NULL
|
||||
drop table t1m, t1i, t2m, t2i;
|
||||
create table t2 (ff double);
|
||||
insert into t2 values (2.2);
|
||||
select cast(sum(distinct ff) as decimal(5,2)) from t2;
|
||||
|
|
|
@ -54,3 +54,141 @@ c.c_id = 218 and expiredate is null;
|
|||
slai_id
|
||||
12
|
||||
drop table t1, t2;
|
||||
create table t1m (a int) engine=myisam;
|
||||
create table t1i (a int) engine=innodb;
|
||||
create table t2m (a int) engine=myisam;
|
||||
create table t2i (a int) engine=innodb;
|
||||
insert into t2m values (5);
|
||||
insert into t2i values (5);
|
||||
select min(a) from t1m;
|
||||
min(a)
|
||||
NULL
|
||||
select min(7) from t1m;
|
||||
min(7)
|
||||
NULL
|
||||
select min(7) from DUAL;
|
||||
min(7)
|
||||
NULL
|
||||
explain select min(7) from t2m join t1m;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
||||
select min(7) from t2m join t1m;
|
||||
min(7)
|
||||
NULL
|
||||
select max(a) from t1m;
|
||||
max(a)
|
||||
NULL
|
||||
select max(7) from t1m;
|
||||
max(7)
|
||||
NULL
|
||||
select max(7) from DUAL;
|
||||
max(7)
|
||||
NULL
|
||||
explain select max(7) from t2m join t1m;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
||||
select max(7) from t2m join t1m;
|
||||
max(7)
|
||||
NULL
|
||||
select 1, min(a) from t1m where a=99;
|
||||
1 min(a)
|
||||
1 NULL
|
||||
select 1, min(a) from t1m where 1=99;
|
||||
1 min(a)
|
||||
1 NULL
|
||||
select 1, min(1) from t1m where a=99;
|
||||
1 min(1)
|
||||
1 NULL
|
||||
select 1, min(1) from t1m where 1=99;
|
||||
1 min(1)
|
||||
1 NULL
|
||||
select 1, max(a) from t1m where a=99;
|
||||
1 max(a)
|
||||
1 NULL
|
||||
select 1, max(a) from t1m where 1=99;
|
||||
1 max(a)
|
||||
1 NULL
|
||||
select 1, max(1) from t1m where a=99;
|
||||
1 max(1)
|
||||
1 NULL
|
||||
select 1, max(1) from t1m where 1=99;
|
||||
1 max(1)
|
||||
1 NULL
|
||||
select min(a) from t1i;
|
||||
min(a)
|
||||
NULL
|
||||
select min(7) from t1i;
|
||||
min(7)
|
||||
NULL
|
||||
select min(7) from DUAL;
|
||||
min(7)
|
||||
NULL
|
||||
explain select min(7) from t2i join t1i;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2i ALL NULL NULL NULL NULL 1
|
||||
1 SIMPLE t1i ALL NULL NULL NULL NULL 1
|
||||
select min(7) from t2i join t1i;
|
||||
min(7)
|
||||
NULL
|
||||
select max(a) from t1i;
|
||||
max(a)
|
||||
NULL
|
||||
select max(7) from t1i;
|
||||
max(7)
|
||||
NULL
|
||||
select max(7) from DUAL;
|
||||
max(7)
|
||||
NULL
|
||||
explain select max(7) from t2i join t1i;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2i ALL NULL NULL NULL NULL 1
|
||||
1 SIMPLE t1i ALL NULL NULL NULL NULL 1
|
||||
select max(7) from t2i join t1i;
|
||||
max(7)
|
||||
NULL
|
||||
select 1, min(a) from t1i where a=99;
|
||||
1 min(a)
|
||||
1 NULL
|
||||
select 1, min(a) from t1i where 1=99;
|
||||
1 min(a)
|
||||
1 NULL
|
||||
select 1, min(1) from t1i where a=99;
|
||||
1 min(1)
|
||||
1 NULL
|
||||
select 1, min(1) from t1i where 1=99;
|
||||
1 min(1)
|
||||
1 NULL
|
||||
select 1, max(a) from t1i where a=99;
|
||||
1 max(a)
|
||||
1 NULL
|
||||
select 1, max(a) from t1i where 1=99;
|
||||
1 max(a)
|
||||
1 NULL
|
||||
select 1, max(1) from t1i where a=99;
|
||||
1 max(1)
|
||||
1 NULL
|
||||
select 1, max(1) from t1i where 1=99;
|
||||
1 max(1)
|
||||
1 NULL
|
||||
explain select count(*), min(7), max(7) from t1m, t1i;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1m system NULL NULL NULL NULL 0 const row not found
|
||||
1 SIMPLE t1i ALL NULL NULL NULL NULL 1
|
||||
select count(*), min(7), max(7) from t1m, t1i;
|
||||
count(*) min(7) max(7)
|
||||
0 NULL NULL
|
||||
explain select count(*), min(7), max(7) from t1m, t2i;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1m system NULL NULL NULL NULL 0 const row not found
|
||||
1 SIMPLE t2i ALL NULL NULL NULL NULL 1
|
||||
select count(*), min(7), max(7) from t1m, t2i;
|
||||
count(*) min(7) max(7)
|
||||
0 NULL NULL
|
||||
explain select count(*), min(7), max(7) from t2m, t1i;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2m system NULL NULL NULL NULL 1
|
||||
1 SIMPLE t1i ALL NULL NULL NULL NULL 1
|
||||
select count(*), min(7), max(7) from t2m, t1i;
|
||||
count(*) min(7) max(7)
|
||||
0 NULL NULL
|
||||
drop table t1m, t1i, t2m, t2i;
|
||||
|
|
|
@ -9,11 +9,10 @@
|
|||
# Do not use any TAB characters for whitespace.
|
||||
#
|
||||
##############################################################################
|
||||
events_bugs : BUG#17619 2006-02-21 andrey Race conditions
|
||||
events_stress : BUG#17619 2006-02-21 andrey Race conditions
|
||||
events : BUG#17619 2006-02-21 andrey Race conditions
|
||||
events_scheduling : BUG#19170 2006-04-26 andrey Test case of 19170 fails on some platforms. Has to be checked.
|
||||
events_logs_tests : BUG#17619 2006-05-16 andrey Test case problems
|
||||
#events_bugs : BUG#17619 2006-02-21 andrey Race conditions
|
||||
#events_stress : BUG#17619 2006-02-21 andrey Race conditions
|
||||
#events : BUG#17619 2006-02-21 andrey Race conditions
|
||||
#events_scheduling : BUG#19170 2006-04-26 andrey Test case of 19170 fails on some platforms. Has to be checked.
|
||||
ndb_autodiscover : BUG#18952 2006-02-16 jmiller Needs to be fixed w.r.t binlog
|
||||
ndb_autodiscover2 : BUG#18952 2006-02-16 jmiller Needs to be fixed w.r.t binlog
|
||||
#ndb_binlog_discover : BUG#19395 2006-04-28 tomas/knielsen mysqld does not always detect cluster shutdown
|
||||
|
|
|
@ -15,11 +15,10 @@ CREATE EVENT e_x2 ON SCHEDULE EVERY 1 SECOND DO DROP TABLE x_table;
|
|||
connection default;
|
||||
SHOW DATABASES LIKE 'db_x';
|
||||
SET GLOBAL event_scheduler=1;
|
||||
--sleep 2
|
||||
--sleep 1.5
|
||||
SHOW DATABASES LIKE 'db_x';
|
||||
SHOW TABLES FROM db_x;
|
||||
SET GLOBAL event_scheduler=0;
|
||||
--sleep 1
|
||||
SET GLOBAL event_scheduler=2;
|
||||
connection priv_conn;
|
||||
DROP EVENT e_x1;
|
||||
DROP EVENT e_x2;
|
||||
|
@ -31,8 +30,7 @@ USE events_test;
|
|||
#
|
||||
# END: BUG #17289 Events: missing privilege check for drop database
|
||||
#
|
||||
SET GLOBAL event_scheduler=0;
|
||||
--sleep 1
|
||||
SET GLOBAL event_scheduler=2;
|
||||
drop event if exists event1;
|
||||
create event event1 on schedule every 15 minute starts now() ends date_add(now(), interval 5 hour) DO begin end;
|
||||
alter event event1 rename to event2 enable;
|
||||
|
@ -92,11 +90,11 @@ drop event e_43;
|
|||
--echo "Let's check whether we can use non-qualified names"
|
||||
create table non_qualif(a int);
|
||||
create event non_qualif_ev on schedule every 10 minute do insert into non_qualif values (800219);
|
||||
--sleep 2
|
||||
--sleep 1
|
||||
select * from non_qualif;
|
||||
drop event non_qualif_ev;
|
||||
drop table non_qualif;
|
||||
set global event_scheduler = 0;
|
||||
set global event_scheduler = 2;
|
||||
|
||||
create table t_event3 (a int, b float);
|
||||
drop event if exists event3;
|
||||
|
@ -281,15 +279,15 @@ SHOW EVENTS;
|
|||
|
||||
--echo "This should show us only 3 events:";
|
||||
--replace_column 8 # 9 #
|
||||
SHOW FULL EVENTS;
|
||||
SHOW EVENTS;
|
||||
|
||||
--echo "This should show us only 2 events:";
|
||||
--replace_column 8 # 9 #
|
||||
SHOW FULL EVENTS LIKE 't%event';
|
||||
SHOW EVENTS LIKE 't%event';
|
||||
|
||||
--echo "This should show us no events:";
|
||||
--replace_column 8 # 9 #
|
||||
SHOW FULL EVENTS FROM test LIKE '%';
|
||||
SHOW EVENTS FROM test LIKE '%';
|
||||
#ok, we are back
|
||||
connection default;
|
||||
DROP DATABASE events_test2;
|
||||
|
@ -300,7 +298,7 @@ SHOW EVENTS;
|
|||
|
||||
--echo "we should see 4 events now:";
|
||||
--replace_column 8 # 9 #
|
||||
SHOW FULL EVENTS;
|
||||
SHOW EVENTS;
|
||||
SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events;
|
||||
|
||||
connection ev_con1;
|
||||
|
@ -330,21 +328,21 @@ create event задачка on schedule every 123 minute starts now() ends now()
|
|||
drop event задачка;
|
||||
|
||||
# event_scheduler is a global var
|
||||
--error 1229
|
||||
set event_scheduler=0;
|
||||
# event_scheduler could be only either 0 or 1
|
||||
--error 1231
|
||||
set global event_scheduler=2;
|
||||
--error ER_GLOBAL_VARIABLE
|
||||
set event_scheduler=2;
|
||||
# event_scheduler could be only either 1 or 2
|
||||
--error ER_WRONG_VALUE_FOR_VAR
|
||||
set global event_scheduler=3;
|
||||
|
||||
--echo "DISABLE the scheduler. Testing that it does not work when the variable is 0"
|
||||
set global event_scheduler=0;
|
||||
set global event_scheduler=2;
|
||||
select definer, name, db from mysql.event;
|
||||
select get_lock("test_lock1", 20);
|
||||
create event закачка on schedule every 10 hour do select get_lock("test_lock1", 20);
|
||||
--echo "Should return 1 row"
|
||||
select definer, name, db from mysql.event;
|
||||
|
||||
--echo "Should be 0 processes"
|
||||
--echo "Should be only 1 process"
|
||||
select /*1*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
|
||||
select release_lock("test_lock1");
|
||||
drop event закачка;
|
||||
|
@ -362,7 +360,7 @@ create event закачка on schedule every 10 hour do select get_lock("test_l
|
|||
--echo "Let some time pass to the event starts"
|
||||
--sleep 2
|
||||
--echo "Should have only 2 processes: the scheduler and the locked event"
|
||||
select /*1*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
|
||||
select /*2*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;--echo "Release the mutex, the event worker should finish."
|
||||
--echo "Release the mutex, the event worker should finish."
|
||||
select release_lock("test_lock2");
|
||||
drop event закачка;
|
||||
|
@ -379,18 +377,11 @@ set global event_scheduler=1;
|
|||
select get_lock("test_lock2_1", 20);
|
||||
create event закачка21 on schedule every 10 hour do select get_lock("test_lock2_1", 20);
|
||||
--sleep 1
|
||||
--echo "Should see 1 process, locked on get_lock("
|
||||
#select /*3*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
|
||||
--echo "Shutting down the scheduler, it should wait for the running event"
|
||||
set global event_scheduler=0;
|
||||
--sleep 1
|
||||
--echo "Should have only 2 processes: the scheduler and the locked event"
|
||||
--echo "Should have only 3 processes: the scheduler, our conn and the locked event"
|
||||
select /*3*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
|
||||
set global event_scheduler=2;
|
||||
--echo "Should have only our process now:"
|
||||
select /*4*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
|
||||
--echo "Release the lock so the child process should finish. Hence the scheduler also"
|
||||
select release_lock("test_lock2_1");
|
||||
--sleep 1
|
||||
--echo "Should see 0 processes now:"
|
||||
select /*5*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
|
||||
drop event закачка21;
|
||||
|
||||
####
|
||||
|
@ -418,6 +409,7 @@ create event white_space on schedule every 10 hour disable do
|
|||
|
||||
select 2;
|
||||
select event_schema, event_name, definer, event_body from information_schema.events where event_name='white_space';
|
||||
select event_schema, event_name, definer, event_body from information_schema.events where event_name='white_space';
|
||||
drop event white_space;
|
||||
create event white_space on schedule every 10 hour disable do select 3;
|
||||
select event_schema, event_name, definer, event_body from information_schema.events where event_name='white_space';
|
||||
|
@ -426,7 +418,7 @@ drop event white_space;
|
|||
# END: BUG #17453: Creating Event crash the server
|
||||
#
|
||||
|
||||
##set global event_scheduler=1;
|
||||
#
|
||||
# Bug#17403 "Events: packets out of order with show create event"
|
||||
#
|
||||
create event e1 on schedule every 1 year do set @a = 5;
|
||||
|
@ -440,7 +432,7 @@ drop event e1;
|
|||
##select get_lock("test_lock3", 20);
|
||||
##create event закачка on schedule every 10 hour do select get_lock("test_lock3", 20);
|
||||
##select sleep(2);
|
||||
##show processlist;
|
||||
##select /*5*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
|
||||
##drop event закачка;
|
||||
##select release_lock("test_lock3");
|
||||
|
||||
|
@ -450,14 +442,14 @@ drop event e1;
|
|||
##select get_lock("test_lock4", 20);
|
||||
##create event закачка4 on schedule every 1 second do select get_lock("test_lock4", 20);
|
||||
##select sleep(3);
|
||||
##--replace_column 1 # 6 #
|
||||
##select /*6*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
|
||||
##drop event закачка4;
|
||||
##select release_lock("test_lock4");
|
||||
|
||||
##set global event_scheduler=0;
|
||||
##set global event_scheduler=2;
|
||||
##select sleep(2);
|
||||
##--replace_column 1 # 6 #
|
||||
##show processlist;
|
||||
##select count(*) from mysql.event;
|
||||
|
||||
drop database events_test;
|
||||
|
||||
|
|
|
@ -30,13 +30,13 @@ set @a=3;
|
|||
CREATE PROCEDURE p_16 () CREATE EVENT e_16 ON SCHEDULE EVERY @a SECOND DO SET @a=5;
|
||||
call p_16();
|
||||
--echo "Here we used to crash!"
|
||||
--error 1516
|
||||
--error ER_EVENT_ALREADY_EXISTS
|
||||
call p_16();
|
||||
--error 1516
|
||||
--error ER_EVENT_ALREADY_EXISTS
|
||||
call p_16();
|
||||
DROP EVENT e_16;
|
||||
CALL p_16();
|
||||
--error 1516
|
||||
--error ER_EVENT_ALREADY_EXISTS
|
||||
CALL p_16();
|
||||
DROP PROCEDURE p_16;
|
||||
DROP EVENT e_16;
|
||||
|
@ -47,9 +47,9 @@ DROP EVENT e_16;
|
|||
#
|
||||
# Start - 16396: Events: Distant-future dates become past dates
|
||||
#
|
||||
--error 1504
|
||||
--error ER_WRONG_VALUE
|
||||
create event e_55 on schedule at 99990101000000 do drop table t;
|
||||
--error 1504
|
||||
--error ER_WRONG_VALUE
|
||||
create event e_55 on schedule every 10 hour starts 99990101000000 do drop table t;
|
||||
--error ER_EVENT_ENDS_BEFORE_STARTS
|
||||
create event e_55 on schedule every 10 minute ends 99990101000000 do drop table t;
|
||||
|
@ -60,7 +60,7 @@ create event e_55 on schedule every 10 minute ends 99990101000000 do drop table
|
|||
#
|
||||
# Start - 16407: Events: Changes in sql_mode won't be taken into account
|
||||
#
|
||||
set global event_scheduler=0;
|
||||
set global event_scheduler=2;
|
||||
--echo "Wait a bit to settle down"
|
||||
--sleep 1
|
||||
delete from mysql.event;
|
||||
|
@ -79,7 +79,7 @@ delimiter ;|
|
|||
--echo "Now if everything is fine the event has compiled and is locked
|
||||
select /*1*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
|
||||
select release_lock('test_bug16407');
|
||||
set global event_scheduler= 0;
|
||||
set global event_scheduler= 2;
|
||||
select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
|
||||
--echo "Let's check whether we change the sql_mode on ALTER EVENT"
|
||||
set sql_mode='traditional';
|
||||
|
@ -121,9 +121,9 @@ set global event_scheduler= 1;
|
|||
--sleep 1
|
||||
select /*2*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
|
||||
select release_lock('ee_16407_2');
|
||||
--sleep 3
|
||||
--sleep 2
|
||||
select /*3*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
|
||||
set global event_scheduler= 0;
|
||||
set global event_scheduler= 2;
|
||||
select * from events_smode_test order by ev_name, a;
|
||||
--echo "OK, last check before we drop them"
|
||||
select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
|
||||
|
@ -156,7 +156,7 @@ set global event_scheduler= 1;
|
|||
--echo "Should have 2 locked processes"
|
||||
select /*4*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
|
||||
select release_lock('ee_16407_5');
|
||||
--sleep 3
|
||||
--sleep 2
|
||||
--echo "Should have 0 processes locked"
|
||||
select /*5*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
|
||||
select * from events_smode_test order by ev_name, a;
|
||||
|
@ -166,7 +166,7 @@ drop event ee_16407_5;
|
|||
drop event ee_16407_6;
|
||||
drop procedure ee_16407_5_pendant;
|
||||
drop procedure ee_16407_6_pendant;
|
||||
set global event_scheduler= 0;
|
||||
set global event_scheduler= 2;
|
||||
drop table events_smode_test;
|
||||
set sql_mode=@old_sql_mode;
|
||||
#
|
||||
|
|
|
@ -10,7 +10,7 @@ BEGIN
|
|||
END|
|
||||
delimiter ;|
|
||||
--echo "Check General Query Log"
|
||||
SET GLOBAL event_scheduler=0;
|
||||
SET GLOBAL event_scheduler=2;
|
||||
create event log_general on schedule every 1 minute do SELect 'alabala', sleep(3) from dual;
|
||||
TRUNCATE mysql.general_log;
|
||||
--echo "1 row, the current statement!"
|
||||
|
@ -22,7 +22,7 @@ SET GLOBAL event_scheduler=1;
|
|||
call select_general_log();
|
||||
DROP PROCEDURE select_general_log;
|
||||
DROP EVENT log_general;
|
||||
SET GLOBAL event_scheduler=0;
|
||||
SET GLOBAL event_scheduler=2;
|
||||
--sleep 1
|
||||
|
||||
--echo "Check slow query log"
|
||||
|
@ -53,10 +53,10 @@ TRUNCATE mysql.slow_log;
|
|||
SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
|
||||
--echo "Set new values"
|
||||
SET GLOBAL long_query_time=4;
|
||||
SET SESSION long_query_time=2;
|
||||
SET SESSION long_query_time=1;
|
||||
--echo "Check that logging is working"
|
||||
SELECT SLEEP(3);
|
||||
--replace_regex /00:00:0[3-5]/SLEEPVAL/
|
||||
SELECT SLEEP(2);
|
||||
--replace_regex /00:00:0[2-4]/SLEEPVAL/
|
||||
SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
|
||||
TRUNCATE mysql.slow_log;
|
||||
CREATE TABLE slow_event_test (slo_val tinyint, val tinyint);
|
||||
|
@ -73,14 +73,15 @@ SELECT * FROM slow_event_test;
|
|||
SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
|
||||
--echo "This should go to the slow log"
|
||||
SET SESSION long_query_time=10;
|
||||
SET GLOBAL long_query_time=1;
|
||||
DROP EVENT long_event;
|
||||
CREATE EVENT long_event2 ON SCHEDULE EVERY 1 MINUTE DO INSERT INTO slow_event_test SELECT @@long_query_time, SLEEP(5);
|
||||
CREATE EVENT long_event2 ON SCHEDULE EVERY 1 MINUTE DO INSERT INTO slow_event_test SELECT @@long_query_time, SLEEP(2);
|
||||
--echo "Sleep some more time than the actual event run will take"
|
||||
--sleep 7
|
||||
--sleep 3
|
||||
--echo "Check our table. Should see 2 rows"
|
||||
SELECT * FROM slow_event_test;
|
||||
--echo "Check slow log. Should see 1 row because 5 is over the threshold of 4 for GLOBAL, though under SESSION which is 10"
|
||||
--replace_regex /00:00:0[5-7]/SLEEPVAL/
|
||||
--echo "Check slow log. Should see 1 row because 4 is over the threshold of 3 for GLOBAL, though under SESSION which is 10"
|
||||
--replace_regex /00:00:0[2-4]/SLEEPVAL/
|
||||
SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
|
||||
DROP EVENT long_event2;
|
||||
SET GLOBAL long_query_time =@old_global_long_query_time;
|
||||
|
|
|
@ -1,55 +1,15 @@
|
|||
create database if not exists events_test;
|
||||
use events_test;
|
||||
|
||||
--error 1235
|
||||
--error ER_NOT_SUPPORTED_YET
|
||||
CREATE EVENT micro_test ON SCHEDULE EVERY 100 MICROSECOND DO SELECT 1;
|
||||
--error 1235
|
||||
--error ER_NOT_SUPPORTED_YET
|
||||
CREATE EVENT micro_test ON SCHEDULE EVERY 100 DAY_MICROSECOND DO SELECT 1;
|
||||
--error 1235
|
||||
--error ER_NOT_SUPPORTED_YET
|
||||
CREATE EVENT micro_test ON SCHEDULE EVERY 100 HOUR_MICROSECOND DO SELECT 1;
|
||||
--error 1235
|
||||
--error ER_NOT_SUPPORTED_YET
|
||||
CREATE EVENT micro_test ON SCHEDULE EVERY 100 MINUTE_MICROSECOND DO SELECT 1;
|
||||
--error 1235
|
||||
--error ER_NOT_SUPPORTED_YET
|
||||
CREATE EVENT micro_test ON SCHEDULE EVERY 100 SECOND_MICROSECOND DO SELECT 1;
|
||||
|
||||
--echo "Now create normal event and change it on SQL level"
|
||||
CREATE EVENT micro_test2 ON SCHEDULE EVERY 1 MONTH DO SELECT 1;
|
||||
UPDATE mysql.event SET interval_field='MICROSECOND' WHERE db=database() AND definer=user() AND name='micro_test2';
|
||||
--error 1235
|
||||
SHOW CREATE EVENT micro_test2;
|
||||
SET GLOBAL event_scheduler=0;
|
||||
--sleep 1
|
||||
--echo "Should not be running:"
|
||||
SHOW VARIABLES like 'event_scheduler';
|
||||
UPDATE mysql.event SET interval_field='DAY_MICROSECOND' WHERE db=database() AND definer=user() AND name='micro_test2';
|
||||
--error 1235
|
||||
SHOW CREATE EVENT micro_test2;
|
||||
SET GLOBAL event_scheduler=0;
|
||||
--sleep 1
|
||||
--echo "Should not be running:"
|
||||
SHOW VARIABLES like 'event_scheduler';
|
||||
UPDATE mysql.event SET interval_field='SECOND_MICROSECOND' WHERE db=database() AND definer=user() AND name='micro_test2';
|
||||
--error 1235
|
||||
SHOW CREATE EVENT micro_test2;
|
||||
SET GLOBAL event_scheduler=0;
|
||||
--sleep 1
|
||||
--echo "Should not be running:"
|
||||
SHOW VARIABLES like 'event_scheduler';
|
||||
UPDATE mysql.event SET interval_field='HOUR_MICROSECOND' WHERE db=database() AND definer=user() AND name='micro_test2';
|
||||
--error 1235
|
||||
SHOW CREATE EVENT micro_test2;
|
||||
SET GLOBAL event_scheduler=0;
|
||||
--sleep 1
|
||||
--echo "Should not be running:"
|
||||
SHOW VARIABLES like 'event_scheduler';
|
||||
UPDATE mysql.event SET interval_field='MINUTE_MICROSECOND' WHERE db=database() AND definer=user() AND name='micro_test2';
|
||||
--error 1235
|
||||
SHOW CREATE EVENT micro_test2;
|
||||
SET GLOBAL event_scheduler=0;
|
||||
--sleep 1
|
||||
--echo "Should not be running:"
|
||||
SHOW VARIABLES like 'event_scheduler';
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER='event_scheduler';
|
||||
DROP EVENT micro_test2;
|
||||
|
||||
drop database events_test;
|
||||
|
|
|
@ -15,7 +15,7 @@ CREATE EVENT start_n_end
|
|||
DO INSERT INTO table_2 VALUES(1);
|
||||
--sleep 5
|
||||
CREATE EVENT only_one_time ON SCHEDULE EVERY 2 SECOND ENDS NOW() + INTERVAL 1 SECOND DO INSERT INTO table_3 VALUES(1);
|
||||
CREATE EVENT two_time ON SCHEDULE EVERY 1 SECOND ENDS NOW() + INTERVAL 1 SECOND DO INSERT INTO table_4 VALUES(1);
|
||||
CREATE EVENT two_time ON SCHEDULE EVERY 1 SECOND ENDS NOW() + INTERVAL 1 SECOND ON COMPLETION PRESERVE DO INSERT INTO table_4 VALUES(1);
|
||||
--sleep 5
|
||||
SELECT IF(SUM(a) >= 4, 'OK', 'ERROR') FROM table_1;
|
||||
SELECT IF(SUM(a) >= 5, 'OK', 'ERROR') FROM table_2;
|
||||
|
@ -28,8 +28,8 @@ DROP EVENT start_n_end;
|
|||
--echo "Already dropped because ended. Therefore an error."
|
||||
--error ER_EVENT_DOES_NOT_EXIST
|
||||
DROP EVENT only_one_time;
|
||||
--echo "Already dropped because ended. Therefore an error."
|
||||
--error ER_EVENT_DOES_NOT_EXIST
|
||||
--echo "Should be preserved"
|
||||
SELECT EVENT_NAME, STATUS FROM INFORMATION_SCHEMA.EVENTS;
|
||||
DROP EVENT two_time;
|
||||
DROP TABLE table_1;
|
||||
DROP TABLE table_2;
|
||||
|
|
|
@ -2,78 +2,120 @@ CREATE DATABASE IF NOT EXISTS events_test;
|
|||
#
|
||||
# DROP DATABASE test start (bug #16406)
|
||||
#
|
||||
CREATE DATABASE events_test2;
|
||||
USE events_test2;
|
||||
CREATE DATABASE events_conn1_test2;
|
||||
CREATE TABLE events_test.fill_it(test_name varchar(20), occur datetime);
|
||||
CREATE USER event_user2@localhost;
|
||||
CREATE DATABASE events_conn2_db;
|
||||
GRANT ALL ON *.* TO event_user2@localhost;
|
||||
CREATE USER event_user3@localhost;
|
||||
CREATE DATABASE events_conn3_db;
|
||||
GRANT ALL ON *.* TO event_user3@localhost;
|
||||
connect (conn2,localhost,event_user2,,events_conn2_db);
|
||||
--echo "In the second connection we create some events which won't be dropped till the end"
|
||||
--disable_query_log
|
||||
let $1= 100;
|
||||
while ($1)
|
||||
{
|
||||
eval CREATE EVENT conn2_ev$1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_test.fill_it VALUES("conn2_ev$1", NOW());
|
||||
dec $1;
|
||||
}
|
||||
--enable_query_log
|
||||
connect (conn3,localhost,event_user3,,events_conn3_db);
|
||||
--echo "In the second connection we create some events which won't be dropped till the end"
|
||||
--disable_query_log
|
||||
let $1= 100;
|
||||
while ($1)
|
||||
{
|
||||
eval CREATE EVENT conn3_ev$1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_test.fill_it VALUES("conn3_ev$1", NOW());
|
||||
dec $1;
|
||||
}
|
||||
--enable_query_log
|
||||
connection default;
|
||||
USE events_conn1_test2;
|
||||
CREATE EVENT ev_drop1 ON SCHEDULE EVERY 10 MINUTE DISABLE DO SELECT 1;
|
||||
CREATE EVENT ev_drop2 ON SCHEDULE EVERY 10 MINUTE DISABLE DO SELECT 1;
|
||||
CREATE EVENT ev_drop3 ON SCHEDULE EVERY 10 MINUTE DISABLE DO SELECT 1;
|
||||
USE events_test;
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
|
||||
DROP DATABASE events_test2;
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS;
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
|
||||
DROP DATABASE events_conn1_test2;
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
|
||||
|
||||
--echo "Now testing stability - dropping db -> events while they are running"
|
||||
CREATE DATABASE events_test2;
|
||||
USE events_test2;
|
||||
CREATE DATABASE events_conn1_test2;
|
||||
USE events_conn1_test2;
|
||||
--disable_query_log
|
||||
let $1= 1000;
|
||||
let $1= 100;
|
||||
while ($1)
|
||||
{
|
||||
eval CREATE EVENT ev_drop$1 ON SCHEDULE EVERY 1 SECOND DO SELECT $1;
|
||||
eval CREATE EVENT conn1_round1_ev$1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_test.fill_it VALUES("conn1_round1_ev$1", NOW());
|
||||
dec $1;
|
||||
}
|
||||
--enable_query_log
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
|
||||
SET GLOBAL event_scheduler=1;
|
||||
--sleep 4
|
||||
DROP DATABASE events_test2;
|
||||
|
||||
SET GLOBAL event_scheduler=0;
|
||||
--sleep 2
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
|
||||
CREATE DATABASE events_test3;
|
||||
USE events_test3;
|
||||
--disable_query_log
|
||||
let $1= 950;
|
||||
while ($1)
|
||||
{
|
||||
eval CREATE EVENT ev_drop$1 ON SCHEDULE EVERY 1 SECOND DO SELECT $1;
|
||||
dec $1;
|
||||
}
|
||||
--enable_query_log
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test3';
|
||||
--sleep 3
|
||||
CREATE DATABASE events_test4;
|
||||
USE events_test4;
|
||||
--disable_query_log
|
||||
let $1= 860;
|
||||
while ($1)
|
||||
{
|
||||
eval CREATE EVENT ev_drop$1 ON SCHEDULE EVERY 1 SECOND DO SELECT $1;
|
||||
dec $1;
|
||||
}
|
||||
--enable_query_log
|
||||
|
||||
|
||||
CREATE DATABASE events_test2;
|
||||
USE events_test2;
|
||||
--disable_query_log
|
||||
let $1= 1050;
|
||||
while ($1)
|
||||
{
|
||||
eval CREATE EVENT ev_drop$1 ON SCHEDULE EVERY 1 SECOND DO SELECT $1;
|
||||
dec $1;
|
||||
}
|
||||
--enable_query_log
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
|
||||
--sleep 6
|
||||
DROP DATABASE events_test2;
|
||||
SET GLOBAL event_scheduler=0;
|
||||
DROP DATABASE events_test3;
|
||||
DROP DATABASE events_conn1_test2;
|
||||
|
||||
SET GLOBAL event_scheduler=2;
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
|
||||
CREATE DATABASE events_conn1_test3;
|
||||
USE events_conn1_test3;
|
||||
--disable_query_log
|
||||
let $1= 100;
|
||||
while ($1)
|
||||
{
|
||||
eval CREATE EVENT conn1_round2_ev$1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_test.fill_it VALUES("conn1_round2_ev$1", NOW());
|
||||
dec $1;
|
||||
}
|
||||
--enable_query_log
|
||||
SET GLOBAL event_scheduler=1;
|
||||
DROP DATABASE events_test4;
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test3';
|
||||
CREATE DATABASE events_conn1_test4;
|
||||
USE events_conn1_test4;
|
||||
--disable_query_log
|
||||
let $1= 100;
|
||||
while ($1)
|
||||
{
|
||||
eval CREATE EVENT conn1_round3_ev$1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_test.fill_it VALUES("conn1_round3_ev$1", NOW());
|
||||
dec $1;
|
||||
}
|
||||
--enable_query_log
|
||||
|
||||
CREATE DATABASE events_conn1_test2;
|
||||
USE events_conn1_test2;
|
||||
--disable_query_log
|
||||
let $1= 100;
|
||||
while ($1)
|
||||
{
|
||||
eval CREATE EVENT ev_round4_drop$1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_test.fill_it VALUES("conn1_round4_ev$1", NOW());
|
||||
dec $1;
|
||||
}
|
||||
--enable_query_log
|
||||
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
|
||||
--sleep 6
|
||||
connection conn2;
|
||||
--send
|
||||
DROP DATABASE events_conn2_db;
|
||||
connection conn3;
|
||||
--send
|
||||
DROP DATABASE events_conn3_db;
|
||||
connection default;
|
||||
--send
|
||||
DROP DATABASE events_conn1_test2;
|
||||
DROP DATABASE events_conn1_test3;
|
||||
SET GLOBAL event_scheduler=2;
|
||||
DROP DATABASE events_conn1_test4;
|
||||
SET GLOBAL event_scheduler=1;
|
||||
connection conn2;
|
||||
reap;
|
||||
disconnect conn2;
|
||||
connection conn3;
|
||||
reap;
|
||||
disconnect conn3;
|
||||
connection default;
|
||||
USE events_test;
|
||||
DROP TABLE fill_it;
|
||||
#
|
||||
# DROP DATABASE test end (bug #16406)
|
||||
#
|
||||
|
|
|
@ -539,77 +539,6 @@ INSERT INTO t1 VALUES
|
|||
SELECT MAX(id) FROM t1 WHERE id < 3 AND a=2 AND b=6;
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Bug #12882 min/max inconsistent on empty table
|
||||
#
|
||||
|
||||
--disable_warnings
|
||||
create table t1m (a int) engine=myisam;
|
||||
create table t1i (a int) engine=innodb;
|
||||
create table t2m (a int) engine=myisam;
|
||||
create table t2i (a int) engine=innodb;
|
||||
--enable_warnings
|
||||
insert into t2m values (5);
|
||||
insert into t2i values (5);
|
||||
|
||||
# test with MyISAM
|
||||
select min(a) from t1m;
|
||||
select min(7) from t1m;
|
||||
select min(7) from DUAL;
|
||||
explain select min(7) from t2m join t1m;
|
||||
select min(7) from t2m join t1m;
|
||||
|
||||
select max(a) from t1m;
|
||||
select max(7) from t1m;
|
||||
select max(7) from DUAL;
|
||||
explain select max(7) from t2m join t1m;
|
||||
select max(7) from t2m join t1m;
|
||||
|
||||
select 1, min(a) from t1m where a=99;
|
||||
select 1, min(a) from t1m where 1=99;
|
||||
select 1, min(1) from t1m where a=99;
|
||||
select 1, min(1) from t1m where 1=99;
|
||||
|
||||
select 1, max(a) from t1m where a=99;
|
||||
select 1, max(a) from t1m where 1=99;
|
||||
select 1, max(1) from t1m where a=99;
|
||||
select 1, max(1) from t1m where 1=99;
|
||||
|
||||
# test with InnoDB
|
||||
select min(a) from t1i;
|
||||
select min(7) from t1i;
|
||||
select min(7) from DUAL;
|
||||
explain select min(7) from t2i join t1i;
|
||||
select min(7) from t2i join t1i;
|
||||
|
||||
select max(a) from t1i;
|
||||
select max(7) from t1i;
|
||||
select max(7) from DUAL;
|
||||
explain select max(7) from t2i join t1i;
|
||||
select max(7) from t2i join t1i;
|
||||
|
||||
select 1, min(a) from t1i where a=99;
|
||||
select 1, min(a) from t1i where 1=99;
|
||||
select 1, min(1) from t1i where a=99;
|
||||
select 1, min(1) from t1i where 1=99;
|
||||
|
||||
select 1, max(a) from t1i where a=99;
|
||||
select 1, max(a) from t1i where 1=99;
|
||||
select 1, max(1) from t1i where a=99;
|
||||
select 1, max(1) from t1i where 1=99;
|
||||
|
||||
# mixed MyISAM/InnoDB test
|
||||
explain select count(*), min(7), max(7) from t1m, t1i;
|
||||
select count(*), min(7), max(7) from t1m, t1i;
|
||||
|
||||
explain select count(*), min(7), max(7) from t1m, t2i;
|
||||
select count(*), min(7), max(7) from t1m, t2i;
|
||||
|
||||
explain select count(*), min(7), max(7) from t2m, t1i;
|
||||
select count(*), min(7), max(7) from t2m, t1i;
|
||||
|
||||
drop table t1m, t1i, t2m, t2i;
|
||||
|
||||
# End of 4.1 tests
|
||||
|
||||
#
|
||||
|
|
|
@ -57,3 +57,75 @@ where
|
|||
c.c_id = 218 and expiredate is null;
|
||||
|
||||
drop table t1, t2;
|
||||
|
||||
#
|
||||
# Bug #12882 min/max inconsistent on empty table
|
||||
#
|
||||
|
||||
--disable_warnings
|
||||
create table t1m (a int) engine=myisam;
|
||||
create table t1i (a int) engine=innodb;
|
||||
create table t2m (a int) engine=myisam;
|
||||
create table t2i (a int) engine=innodb;
|
||||
--enable_warnings
|
||||
insert into t2m values (5);
|
||||
insert into t2i values (5);
|
||||
|
||||
# test with MyISAM
|
||||
select min(a) from t1m;
|
||||
select min(7) from t1m;
|
||||
select min(7) from DUAL;
|
||||
explain select min(7) from t2m join t1m;
|
||||
select min(7) from t2m join t1m;
|
||||
|
||||
select max(a) from t1m;
|
||||
select max(7) from t1m;
|
||||
select max(7) from DUAL;
|
||||
explain select max(7) from t2m join t1m;
|
||||
select max(7) from t2m join t1m;
|
||||
|
||||
select 1, min(a) from t1m where a=99;
|
||||
select 1, min(a) from t1m where 1=99;
|
||||
select 1, min(1) from t1m where a=99;
|
||||
select 1, min(1) from t1m where 1=99;
|
||||
|
||||
select 1, max(a) from t1m where a=99;
|
||||
select 1, max(a) from t1m where 1=99;
|
||||
select 1, max(1) from t1m where a=99;
|
||||
select 1, max(1) from t1m where 1=99;
|
||||
|
||||
# test with InnoDB
|
||||
select min(a) from t1i;
|
||||
select min(7) from t1i;
|
||||
select min(7) from DUAL;
|
||||
explain select min(7) from t2i join t1i;
|
||||
select min(7) from t2i join t1i;
|
||||
|
||||
select max(a) from t1i;
|
||||
select max(7) from t1i;
|
||||
select max(7) from DUAL;
|
||||
explain select max(7) from t2i join t1i;
|
||||
select max(7) from t2i join t1i;
|
||||
|
||||
select 1, min(a) from t1i where a=99;
|
||||
select 1, min(a) from t1i where 1=99;
|
||||
select 1, min(1) from t1i where a=99;
|
||||
select 1, min(1) from t1i where 1=99;
|
||||
|
||||
select 1, max(a) from t1i where a=99;
|
||||
select 1, max(a) from t1i where 1=99;
|
||||
select 1, max(1) from t1i where a=99;
|
||||
select 1, max(1) from t1i where 1=99;
|
||||
|
||||
# mixed MyISAM/InnoDB test
|
||||
explain select count(*), min(7), max(7) from t1m, t1i;
|
||||
select count(*), min(7), max(7) from t1m, t1i;
|
||||
|
||||
explain select count(*), min(7), max(7) from t1m, t2i;
|
||||
select count(*), min(7), max(7) from t1m, t2i;
|
||||
|
||||
explain select count(*), min(7), max(7) from t2m, t1i;
|
||||
select count(*), min(7), max(7) from t2m, t1i;
|
||||
|
||||
drop table t1m, t1i, t2m, t2i;
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ ADD_EXECUTABLE(mysqld ../sql-common/client.c derror.cc des_key_file.cc
|
|||
sql_table.cc sql_test.cc sql_trigger.cc sql_udf.cc sql_union.cc
|
||||
sql_update.cc sql_view.cc strfunc.cc table.cc thr_malloc.cc
|
||||
time.cc tztime.cc uniques.cc unireg.cc item_xmlfunc.cc
|
||||
rpl_tblmap.cc sql_binlog.cc event_executor.cc event_timed.cc
|
||||
rpl_tblmap.cc sql_binlog.cc event_scheduler.cc event_timed.cc
|
||||
sql_tablespace.cc event.cc ../sql-common/my_user.c
|
||||
partition_info.cc
|
||||
${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc
|
||||
|
|
|
@ -66,7 +66,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
|
|||
parse_file.h sql_view.h sql_trigger.h \
|
||||
sql_array.h sql_cursor.h event.h event_priv.h \
|
||||
sql_plugin.h authors.h sql_partition.h \
|
||||
partition_info.h partition_element.h
|
||||
partition_info.h partition_element.h event_scheduler.h
|
||||
mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
|
||||
item.cc item_sum.cc item_buff.cc item_func.cc \
|
||||
item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \
|
||||
|
@ -103,7 +103,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
|
|||
tztime.cc my_time.c my_user.c my_decimal.cc\
|
||||
sp_head.cc sp_pcontext.cc sp_rcontext.cc sp.cc \
|
||||
sp_cache.cc parse_file.cc sql_trigger.cc \
|
||||
event_executor.cc event.cc event_timed.cc \
|
||||
event_scheduler.cc event.cc event_timed.cc \
|
||||
sql_plugin.cc sql_binlog.cc \
|
||||
sql_builtin.cc sql_tablespace.cc partition_info.cc
|
||||
|
||||
|
|
1017
sql/event.cc
1017
sql/event.cc
File diff suppressed because it is too large
Load diff
330
sql/event.h
330
sql/event.h
|
@ -1,4 +1,6 @@
|
|||
/* Copyright (C) 2004-2005 MySQL AB
|
||||
#ifndef _EVENT_H_
|
||||
#define _EVENT_H_
|
||||
/* Copyright (C) 2004-2006 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -14,66 +16,109 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef _EVENT_H_
|
||||
#define _EVENT_H_
|
||||
|
||||
#include "sp.h"
|
||||
#include "sp_head.h"
|
||||
|
||||
#define EVEX_OK SP_OK
|
||||
#define EVEX_KEY_NOT_FOUND SP_KEY_NOT_FOUND
|
||||
#define EVEX_OPEN_TABLE_FAILED SP_OPEN_TABLE_FAILED
|
||||
#define EVEX_WRITE_ROW_FAILED SP_WRITE_ROW_FAILED
|
||||
#define EVEX_DELETE_ROW_FAILED SP_DELETE_ROW_FAILED
|
||||
#define EVEX_GET_FIELD_FAILED SP_GET_FIELD_FAILED
|
||||
#define EVEX_PARSE_ERROR SP_PARSE_ERROR
|
||||
#define EVEX_INTERNAL_ERROR SP_INTERNAL_ERROR
|
||||
#define EVEX_NO_DB_ERROR SP_NO_DB_ERROR
|
||||
#define EVEX_OK 0
|
||||
#define EVEX_KEY_NOT_FOUND -1
|
||||
#define EVEX_OPEN_TABLE_FAILED -2
|
||||
#define EVEX_WRITE_ROW_FAILED -3
|
||||
#define EVEX_DELETE_ROW_FAILED -4
|
||||
#define EVEX_GET_FIELD_FAILED -5
|
||||
#define EVEX_PARSE_ERROR -6
|
||||
#define EVEX_INTERNAL_ERROR -7
|
||||
#define EVEX_NO_DB_ERROR -8
|
||||
#define EVEX_COMPILE_ERROR -19
|
||||
#define EVEX_GENERAL_ERROR -20
|
||||
#define EVEX_BAD_IDENTIFIER SP_BAD_IDENTIFIER
|
||||
#define EVEX_BODY_TOO_LONG SP_BODY_TOO_LONG
|
||||
#define EVEX_BAD_PARAMS -21
|
||||
#define EVEX_NOT_RUNNING -22
|
||||
#define EVEX_MICROSECOND_UNSUP -23
|
||||
#define EVEX_BAD_IDENTIFIER -21
|
||||
#define EVEX_BODY_TOO_LONG -22
|
||||
#define EVEX_BAD_PARAMS -23
|
||||
#define EVEX_NOT_RUNNING -24
|
||||
#define EVEX_MICROSECOND_UNSUP -25
|
||||
#define EVEX_CANT_KILL -26
|
||||
|
||||
#define EVENT_EXEC_NO_MORE (1L << 0)
|
||||
#define EVENT_NOT_USED (1L << 1)
|
||||
#define EVENT_FREE_WHEN_FINISHED (1L << 2)
|
||||
|
||||
extern ulong opt_event_executor;
|
||||
class Event_timed;
|
||||
|
||||
enum enum_event_on_completion
|
||||
class Events
|
||||
{
|
||||
MYSQL_EVENT_ON_COMPLETION_DROP = 1,
|
||||
MYSQL_EVENT_ON_COMPLETION_PRESERVE
|
||||
public:
|
||||
static ulong opt_event_scheduler;
|
||||
static TYPELIB opt_typelib;
|
||||
|
||||
enum enum_table_field
|
||||
{
|
||||
FIELD_DB = 0,
|
||||
FIELD_NAME,
|
||||
FIELD_BODY,
|
||||
FIELD_DEFINER,
|
||||
FIELD_EXECUTE_AT,
|
||||
FIELD_INTERVAL_EXPR,
|
||||
FIELD_TRANSIENT_INTERVAL,
|
||||
FIELD_CREATED,
|
||||
FIELD_MODIFIED,
|
||||
FIELD_LAST_EXECUTED,
|
||||
FIELD_STARTS,
|
||||
FIELD_ENDS,
|
||||
FIELD_STATUS,
|
||||
FIELD_ON_COMPLETION,
|
||||
FIELD_SQL_MODE,
|
||||
FIELD_COMMENT,
|
||||
FIELD_COUNT /* a cool trick to count the number of fields :) */
|
||||
};
|
||||
|
||||
static int
|
||||
create_event(THD *thd, Event_timed *et, uint create_options,
|
||||
uint *rows_affected);
|
||||
|
||||
static int
|
||||
update_event(THD *thd, Event_timed *et, sp_name *new_name,
|
||||
uint *rows_affected);
|
||||
|
||||
static int
|
||||
drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
|
||||
uint *rows_affected);
|
||||
|
||||
static int
|
||||
open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
|
||||
|
||||
static int
|
||||
show_create_event(THD *thd, sp_name *spn, LEX_STRING definer);
|
||||
|
||||
static int
|
||||
reconstruct_interval_expression(String *buf, interval_type interval,
|
||||
longlong expression);
|
||||
|
||||
static int
|
||||
drop_schema_events(THD *thd, char *db);
|
||||
|
||||
static int
|
||||
dump_internal_status(THD *thd);
|
||||
|
||||
static int
|
||||
init();
|
||||
|
||||
static void
|
||||
shutdown();
|
||||
|
||||
static void
|
||||
init_mutexes();
|
||||
|
||||
static void
|
||||
destroy_mutexes();
|
||||
|
||||
|
||||
private:
|
||||
/* Prevent use of these */
|
||||
Events(const Events &);
|
||||
void operator=(Events &);
|
||||
};
|
||||
|
||||
enum enum_event_status
|
||||
{
|
||||
MYSQL_EVENT_ENABLED = 1,
|
||||
MYSQL_EVENT_DISABLED
|
||||
};
|
||||
|
||||
enum evex_table_field
|
||||
{
|
||||
EVEX_FIELD_DB = 0,
|
||||
EVEX_FIELD_NAME,
|
||||
EVEX_FIELD_BODY,
|
||||
EVEX_FIELD_DEFINER,
|
||||
EVEX_FIELD_EXECUTE_AT,
|
||||
EVEX_FIELD_INTERVAL_EXPR,
|
||||
EVEX_FIELD_TRANSIENT_INTERVAL,
|
||||
EVEX_FIELD_CREATED,
|
||||
EVEX_FIELD_MODIFIED,
|
||||
EVEX_FIELD_LAST_EXECUTED,
|
||||
EVEX_FIELD_STARTS,
|
||||
EVEX_FIELD_ENDS,
|
||||
EVEX_FIELD_STATUS,
|
||||
EVEX_FIELD_ON_COMPLETION,
|
||||
EVEX_FIELD_SQL_MODE,
|
||||
EVEX_FIELD_COMMENT,
|
||||
EVEX_FIELD_COUNT /* a cool trick to count the number of fields :) */
|
||||
} ;
|
||||
|
||||
class sp_head;
|
||||
|
||||
class Event_timed
|
||||
{
|
||||
|
@ -82,12 +127,26 @@ class Event_timed
|
|||
my_bool in_spawned_thread;
|
||||
ulong locked_by_thread_id;
|
||||
my_bool running;
|
||||
ulong thread_id;
|
||||
pthread_mutex_t LOCK_running;
|
||||
pthread_cond_t COND_finished;
|
||||
|
||||
bool status_changed;
|
||||
bool last_executed_changed;
|
||||
|
||||
public:
|
||||
enum enum_status
|
||||
{
|
||||
ENABLED = 1,
|
||||
DISABLED
|
||||
};
|
||||
|
||||
enum enum_on_completion
|
||||
{
|
||||
ON_COMPLETION_DROP = 1,
|
||||
ON_COMPLETION_PRESERVE
|
||||
};
|
||||
|
||||
TIME last_executed;
|
||||
|
||||
LEX_STRING dbname;
|
||||
|
@ -111,8 +170,8 @@ public:
|
|||
|
||||
ulonglong created;
|
||||
ulonglong modified;
|
||||
enum enum_event_on_completion on_completion;
|
||||
enum enum_event_status status;
|
||||
enum enum_on_completion on_completion;
|
||||
enum enum_status status;
|
||||
sp_head *sphead;
|
||||
ulong sql_mode;
|
||||
const uchar *body_begin;
|
||||
|
@ -153,36 +212,15 @@ public:
|
|||
DBUG_ASSERT(0);
|
||||
}
|
||||
|
||||
Event_timed();
|
||||
|
||||
Event_timed():in_spawned_thread(0),locked_by_thread_id(0),
|
||||
running(0), status_changed(false),
|
||||
last_executed_changed(false), expression(0), created(0),
|
||||
modified(0), on_completion(MYSQL_EVENT_ON_COMPLETION_DROP),
|
||||
status(MYSQL_EVENT_ENABLED), sphead(0), sql_mode(0),
|
||||
body_begin(0), dropped(false),
|
||||
free_sphead_on_delete(true), flags(0)
|
||||
|
||||
{
|
||||
pthread_mutex_init(&this->LOCK_running, MY_MUTEX_INIT_FAST);
|
||||
init();
|
||||
}
|
||||
|
||||
~Event_timed()
|
||||
{
|
||||
deinit_mutexes();
|
||||
|
||||
if (free_sphead_on_delete)
|
||||
free_sp();
|
||||
}
|
||||
~Event_timed();
|
||||
|
||||
void
|
||||
init();
|
||||
|
||||
|
||||
void
|
||||
deinit_mutexes()
|
||||
{
|
||||
pthread_mutex_destroy(&this->LOCK_running);
|
||||
}
|
||||
deinit_mutexes();
|
||||
|
||||
int
|
||||
init_definer(THD *thd);
|
||||
|
@ -214,12 +252,12 @@ public:
|
|||
bool
|
||||
compute_next_execution_time();
|
||||
|
||||
void
|
||||
mark_last_executed(THD *thd);
|
||||
|
||||
int
|
||||
drop(THD *thd);
|
||||
|
||||
void
|
||||
mark_last_executed(THD *thd);
|
||||
|
||||
bool
|
||||
update_fields(THD *thd);
|
||||
|
||||
|
@ -227,142 +265,32 @@ public:
|
|||
get_create_event(THD *thd, String *buf);
|
||||
|
||||
int
|
||||
execute(THD *thd, MEM_ROOT *mem_root= NULL);
|
||||
execute(THD *thd, MEM_ROOT *mem_root);
|
||||
|
||||
int
|
||||
compile(THD *thd, MEM_ROOT *mem_root= NULL);
|
||||
compile(THD *thd, MEM_ROOT *mem_root);
|
||||
|
||||
my_bool
|
||||
is_running()
|
||||
{
|
||||
my_bool ret;
|
||||
|
||||
VOID(pthread_mutex_lock(&this->LOCK_running));
|
||||
ret= running;
|
||||
VOID(pthread_mutex_unlock(&this->LOCK_running));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
Checks whether the object is being used in a spawned thread.
|
||||
This method is for very basic checking. Use ::can_spawn_now_n_lock()
|
||||
for most of the cases.
|
||||
*/
|
||||
|
||||
my_bool
|
||||
can_spawn_now()
|
||||
{
|
||||
my_bool ret;
|
||||
VOID(pthread_mutex_lock(&this->LOCK_running));
|
||||
ret= !in_spawned_thread;
|
||||
VOID(pthread_mutex_unlock(&this->LOCK_running));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
Checks whether this thread can lock the object for modification ->
|
||||
preventing being spawned for execution, and locks if possible.
|
||||
use ::can_spawn_now() only for basic checking because a race
|
||||
condition may occur between the check and eventual modification (deletion)
|
||||
of the object.
|
||||
*/
|
||||
|
||||
my_bool
|
||||
can_spawn_now_n_lock(THD *thd);
|
||||
bool
|
||||
is_running();
|
||||
|
||||
int
|
||||
spawn_unlock(THD *thd);
|
||||
|
||||
int
|
||||
spawn_now(void * (*thread_func)(void*));
|
||||
spawn_now(void * (*thread_func)(void*), void *arg);
|
||||
|
||||
void
|
||||
bool
|
||||
spawn_thread_finish(THD *thd);
|
||||
|
||||
void
|
||||
free_sp()
|
||||
{
|
||||
delete sphead;
|
||||
sphead= 0;
|
||||
}
|
||||
protected:
|
||||
free_sp();
|
||||
|
||||
bool
|
||||
change_security_context(THD *thd, Security_context *s_ctx,
|
||||
Security_context **backup);
|
||||
has_equal_db(Event_timed *etn);
|
||||
|
||||
int
|
||||
kill_thread(THD *thd);
|
||||
|
||||
void
|
||||
restore_security_context(THD *thd, Security_context *backup);
|
||||
set_thread_id(ulong tid) { thread_id= tid; }
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
evex_create_event(THD *thd, Event_timed *et, uint create_options,
|
||||
uint *rows_affected);
|
||||
|
||||
int
|
||||
evex_update_event(THD *thd, Event_timed *et, sp_name *new_name,
|
||||
uint *rows_affected);
|
||||
|
||||
int
|
||||
evex_drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
|
||||
uint *rows_affected);
|
||||
|
||||
int
|
||||
evex_open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
|
||||
|
||||
int
|
||||
evex_show_create_event(THD *thd, sp_name *spn, LEX_STRING definer);
|
||||
|
||||
int sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs);
|
||||
|
||||
int
|
||||
event_reconstruct_interval_expression(String *buf,
|
||||
interval_type interval,
|
||||
longlong expression);
|
||||
|
||||
int
|
||||
evex_drop_db_events(THD *thd, char *db);
|
||||
|
||||
|
||||
int
|
||||
init_events();
|
||||
|
||||
void
|
||||
shutdown_events();
|
||||
|
||||
|
||||
// auxiliary
|
||||
int
|
||||
event_timed_compare(Event_timed **a, Event_timed **b);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
CREATE TABLE event (
|
||||
db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
|
||||
name char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
|
||||
body longblob NOT NULL,
|
||||
definer char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
|
||||
execute_at DATETIME default NULL,
|
||||
interval_value int(11) default NULL,
|
||||
interval_field ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK',
|
||||
'SECOND','MICROSECOND', 'YEAR_MONTH','DAY_HOUR',
|
||||
'DAY_MINUTE','DAY_SECOND',
|
||||
'HOUR_MINUTE','HOUR_SECOND',
|
||||
'MINUTE_SECOND','DAY_MICROSECOND',
|
||||
'HOUR_MICROSECOND','MINUTE_MICROSECOND',
|
||||
'SECOND_MICROSECOND') default NULL,
|
||||
created TIMESTAMP NOT NULL,
|
||||
modified TIMESTAMP NOT NULL,
|
||||
last_executed DATETIME default NULL,
|
||||
starts DATETIME default NULL,
|
||||
ends DATETIME default NULL,
|
||||
status ENUM('ENABLED','DISABLED') NOT NULL default 'ENABLED',
|
||||
on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP',
|
||||
comment varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
|
||||
PRIMARY KEY (definer,db,name)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';
|
||||
*/
|
||||
|
||||
#endif /* _EVENT_H_ */
|
||||
|
|
|
@ -13,998 +13,3 @@
|
|||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include "event_priv.h"
|
||||
#include "event.h"
|
||||
#include "sp.h"
|
||||
|
||||
#define WAIT_STATUS_READY 0
|
||||
#define WAIT_STATUS_EMPTY_QUEUE 1
|
||||
#define WAIT_STATUS_NEW_TOP_EVENT 2
|
||||
#define WAIT_STATUS_STOP_EXECUTOR 3
|
||||
|
||||
|
||||
/*
|
||||
Make this define DBUG_FAULTY_THR to be able to put breakpoints inside
|
||||
code used by the scheduler's thread(s). In this case user connections
|
||||
are not possible because the scheduler thread code is ran inside the
|
||||
main thread (no spawning takes place. If you want to debug client
|
||||
connection then start with --one-thread and make the define
|
||||
DBUG_FAULTY_THR !
|
||||
*/
|
||||
#define DBUG_FAULTY_THR2
|
||||
|
||||
extern ulong thread_created;
|
||||
extern const char *my_localhost;
|
||||
extern pthread_attr_t connection_attrib;
|
||||
|
||||
pthread_mutex_t LOCK_event_arrays, // mutex for when working with the queue
|
||||
LOCK_workers_count, // mutex for when inc/dec uint workers_count
|
||||
LOCK_evex_running; // mutes for managing bool evex_is_running
|
||||
|
||||
static pthread_mutex_t LOCK_evex_main_thread; // mutex for when working with the queue
|
||||
bool scheduler_main_thread_running= false;
|
||||
|
||||
bool evex_is_running= false;
|
||||
|
||||
ulonglong evex_main_thread_id= 0;
|
||||
ulong opt_event_executor;
|
||||
my_bool event_executor_running_global_var;
|
||||
static my_bool evex_mutexes_initted= FALSE;
|
||||
static uint workers_count;
|
||||
|
||||
static int
|
||||
evex_load_events_from_db(THD *thd);
|
||||
|
||||
bool
|
||||
evex_print_warnings(THD *thd, Event_timed *et);
|
||||
|
||||
/*
|
||||
TODO Andrey: Check for command line option whether to start
|
||||
the main thread or not.
|
||||
*/
|
||||
|
||||
pthread_handler_t
|
||||
event_executor_worker(void *arg);
|
||||
|
||||
pthread_handler_t
|
||||
event_executor_main(void *arg);
|
||||
|
||||
|
||||
/*
|
||||
Returns the seconds difference of 2 TIME structs
|
||||
|
||||
SYNOPSIS
|
||||
evex_time_diff()
|
||||
a - TIME struct 1
|
||||
b - TIME struct 2
|
||||
|
||||
Returns:
|
||||
the seconds difference
|
||||
*/
|
||||
|
||||
static int
|
||||
evex_time_diff(TIME *a, TIME *b)
|
||||
{
|
||||
return sec_since_epoch_TIME(a) - sec_since_epoch_TIME(b);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Inits the mutexes used by the scheduler module
|
||||
|
||||
SYNOPSIS
|
||||
evex_init_mutexes()
|
||||
|
||||
NOTES
|
||||
The mutexes are :
|
||||
LOCK_event_arrays
|
||||
LOCK_workers_count
|
||||
LOCK_evex_running
|
||||
*/
|
||||
|
||||
static void
|
||||
evex_init_mutexes()
|
||||
{
|
||||
if (evex_mutexes_initted)
|
||||
return;
|
||||
|
||||
evex_mutexes_initted= TRUE;
|
||||
pthread_mutex_init(&LOCK_event_arrays, MY_MUTEX_INIT_FAST);
|
||||
pthread_mutex_init(&LOCK_workers_count, MY_MUTEX_INIT_FAST);
|
||||
pthread_mutex_init(&LOCK_evex_running, MY_MUTEX_INIT_FAST);
|
||||
pthread_mutex_init(&LOCK_evex_main_thread, MY_MUTEX_INIT_FAST);
|
||||
|
||||
event_executor_running_global_var= opt_event_executor;
|
||||
}
|
||||
|
||||
extern TABLE_FIELD_W_TYPE mysql_db_table_fields[];
|
||||
extern time_t mysql_db_table_last_check;
|
||||
|
||||
/*
|
||||
Opens mysql.db and mysql.user and checks whether
|
||||
1. mysql.db has column Event_priv at column 20 (0 based);
|
||||
2. mysql.user has column Event_priv at column 29 (0 based);
|
||||
|
||||
Synopsis
|
||||
evex_check_system_tables()
|
||||
*/
|
||||
|
||||
void
|
||||
evex_check_system_tables()
|
||||
{
|
||||
THD *thd= current_thd;
|
||||
TABLE_LIST tables;
|
||||
Open_tables_state backup;
|
||||
|
||||
/* thd is 0x0 during boot of the server. Later it's !=0x0 */
|
||||
if (!thd)
|
||||
return;
|
||||
|
||||
thd->reset_n_backup_open_tables_state(&backup);
|
||||
|
||||
bzero((char*) &tables, sizeof(tables));
|
||||
tables.db= (char*) "mysql";
|
||||
tables.table_name= tables.alias= (char*) "db";
|
||||
tables.lock_type= TL_READ;
|
||||
|
||||
if (simple_open_n_lock_tables(thd, &tables))
|
||||
sql_print_error("Cannot open mysql.db");
|
||||
else
|
||||
{
|
||||
table_check_intact(tables.table, MYSQL_DB_FIELD_COUNT, mysql_db_table_fields,
|
||||
&mysql_db_table_last_check,ER_CANNOT_LOAD_FROM_TABLE);
|
||||
close_thread_tables(thd);
|
||||
}
|
||||
|
||||
bzero((char*) &tables, sizeof(tables));
|
||||
tables.db= (char*) "mysql";
|
||||
tables.table_name= tables.alias= (char*) "user";
|
||||
tables.lock_type= TL_READ;
|
||||
|
||||
if (simple_open_n_lock_tables(thd, &tables))
|
||||
sql_print_error("Cannot open mysql.db");
|
||||
else
|
||||
{
|
||||
if (tables.table->s->fields < 29 ||
|
||||
strncmp(tables.table->field[29]->field_name,
|
||||
STRING_WITH_LEN("Event_priv")))
|
||||
sql_print_error("mysql.user has no `Event_priv` column at position 29");
|
||||
|
||||
close_thread_tables(thd);
|
||||
}
|
||||
|
||||
thd->restore_backup_open_tables_state(&backup);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Inits the scheduler. Called on server start and every time the scheduler
|
||||
is started with switching the event_scheduler global variable to TRUE
|
||||
|
||||
SYNOPSIS
|
||||
init_events()
|
||||
|
||||
NOTES
|
||||
Inits the mutexes used by the scheduler. Done at server start.
|
||||
*/
|
||||
|
||||
int
|
||||
init_events()
|
||||
{
|
||||
pthread_t th;
|
||||
DBUG_ENTER("init_events");
|
||||
|
||||
DBUG_PRINT("info",("Starting events main thread"));
|
||||
|
||||
evex_check_system_tables();
|
||||
|
||||
evex_init_mutexes();
|
||||
|
||||
VOID(pthread_mutex_lock(&LOCK_evex_running));
|
||||
evex_is_running= false;
|
||||
VOID(pthread_mutex_unlock(&LOCK_evex_running));
|
||||
|
||||
if (event_executor_running_global_var)
|
||||
{
|
||||
#ifndef DBUG_FAULTY_THR
|
||||
/* TODO Andrey: Change the error code returned! */
|
||||
if (pthread_create(&th, &connection_attrib, event_executor_main,(void*)NULL))
|
||||
DBUG_RETURN(ER_SLAVE_THREAD);
|
||||
#else
|
||||
event_executor_main(NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Cleans up scheduler memory. Called on server shutdown.
|
||||
|
||||
SYNOPSIS
|
||||
shutdown_events()
|
||||
|
||||
NOTES
|
||||
Destroys the mutexes.
|
||||
*/
|
||||
|
||||
void
|
||||
shutdown_events()
|
||||
{
|
||||
DBUG_ENTER("shutdown_events");
|
||||
|
||||
if (evex_mutexes_initted)
|
||||
{
|
||||
evex_mutexes_initted= FALSE;
|
||||
VOID(pthread_mutex_lock(&LOCK_evex_running));
|
||||
VOID(pthread_mutex_unlock(&LOCK_evex_running));
|
||||
|
||||
pthread_mutex_destroy(&LOCK_event_arrays);
|
||||
pthread_mutex_destroy(&LOCK_workers_count);
|
||||
pthread_mutex_destroy(&LOCK_evex_running);
|
||||
pthread_mutex_destroy(&LOCK_evex_main_thread);
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Inits an scheduler thread handler, both the main and a worker
|
||||
|
||||
SYNOPSIS
|
||||
init_event_thread()
|
||||
thd - the THD of the thread. Has to be allocated by the caller.
|
||||
|
||||
NOTES
|
||||
1. The host of the thead is my_localhost
|
||||
2. thd->net is initted with NULL - no communication.
|
||||
|
||||
Returns
|
||||
0 - OK
|
||||
-1 - Error
|
||||
*/
|
||||
|
||||
static int
|
||||
init_event_thread(THD* thd)
|
||||
{
|
||||
DBUG_ENTER("init_event_thread");
|
||||
thd->client_capabilities= 0;
|
||||
thd->security_ctx->master_access= 0;
|
||||
thd->security_ctx->db_access= 0;
|
||||
thd->security_ctx->host_or_ip= (char*)my_localhost;
|
||||
my_net_init(&thd->net, 0);
|
||||
thd->net.read_timeout = slave_net_timeout;
|
||||
thd->slave_thread= 0;
|
||||
thd->options|= OPTION_AUTO_IS_NULL;
|
||||
thd->client_capabilities= CLIENT_LOCAL_FILES;
|
||||
thd->real_id=pthread_self();
|
||||
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
||||
thd->thread_id= thread_id++;
|
||||
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
||||
|
||||
if (init_thr_lock() || thd->store_globals())
|
||||
{
|
||||
thd->cleanup();
|
||||
delete thd;
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
#if !defined(__WIN__) && !defined(__NETWARE__)
|
||||
sigset_t set;
|
||||
VOID(sigemptyset(&set)); // Get mask in use
|
||||
VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
|
||||
#endif
|
||||
|
||||
thd->proc_info= "Initialized";
|
||||
thd->version= refresh_version;
|
||||
thd->set_time();
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This function waits till the time next event in the queue should be
|
||||
executed.
|
||||
|
||||
Returns
|
||||
WAIT_STATUS_READY There is an event to be executed right now
|
||||
WAIT_STATUS_EMPTY_QUEUE No events or the last event was dropped.
|
||||
WAIT_STATUS_NEW_TOP_EVENT New event has entered the queue and scheduled
|
||||
on top. Restart ticking.
|
||||
WAIT_STATUS_STOP_EXECUTOR The thread was killed or SET global event_scheduler=0;
|
||||
*/
|
||||
|
||||
static int
|
||||
executor_wait_till_next_event_exec(THD *thd)
|
||||
{
|
||||
Event_timed *et;
|
||||
TIME time_now;
|
||||
int t2sleep;
|
||||
|
||||
DBUG_ENTER("executor_wait_till_next_event_exec");
|
||||
/*
|
||||
now let's see how much time to sleep, we know there is at least 1
|
||||
element in the queue.
|
||||
*/
|
||||
VOID(pthread_mutex_lock(&LOCK_event_arrays));
|
||||
if (!evex_queue_num_elements(EVEX_EQ_NAME))
|
||||
{
|
||||
VOID(pthread_mutex_unlock(&LOCK_event_arrays));
|
||||
DBUG_RETURN(WAIT_STATUS_EMPTY_QUEUE);
|
||||
}
|
||||
et= evex_queue_first_element(&EVEX_EQ_NAME, Event_timed*);
|
||||
DBUG_ASSERT(et);
|
||||
if (et->status == MYSQL_EVENT_DISABLED)
|
||||
{
|
||||
DBUG_PRINT("evex main thread",("Now it is disabled-exec no more"));
|
||||
if (et->dropped)
|
||||
et->drop(thd);
|
||||
delete et;
|
||||
evex_queue_delete_element(&EVEX_EQ_NAME, 0);// 0 is top, internally 1
|
||||
VOID(pthread_mutex_unlock(&LOCK_event_arrays));
|
||||
sql_print_information("Event found disabled, dropping.");
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
DBUG_PRINT("evex main thread",("computing time to sleep till next exec"));
|
||||
/* set the internal clock of thd */
|
||||
thd->end_time();
|
||||
my_tz_UTC->gmt_sec_to_TIME(&time_now, thd->query_start());
|
||||
t2sleep= evex_time_diff(&et->execute_at, &time_now);
|
||||
VOID(pthread_mutex_unlock(&LOCK_event_arrays));
|
||||
|
||||
t2sleep*=20;
|
||||
DBUG_PRINT("evex main thread",("unlocked LOCK_event_arrays"));
|
||||
if (t2sleep > 0)
|
||||
{
|
||||
ulonglong modified= et->modified;
|
||||
/*
|
||||
We sleep t2sleep seconds but we check every second whether this thread
|
||||
has been killed, or there is a new candidate
|
||||
*/
|
||||
while (t2sleep-- && !thd->killed && event_executor_running_global_var &&
|
||||
evex_queue_num_elements(EVEX_EQ_NAME) &&
|
||||
(evex_queue_first_element(&EVEX_EQ_NAME, Event_timed*) == et &&
|
||||
evex_queue_first_element(&EVEX_EQ_NAME, Event_timed*)->modified ==
|
||||
modified))
|
||||
{
|
||||
DBUG_PRINT("evex main thread",("will sleep a bit more."));
|
||||
my_sleep(50000);
|
||||
}
|
||||
DBUG_PRINT("info",("saved_modified=%llu current=%llu", modified,
|
||||
evex_queue_num_elements(EVEX_EQ_NAME)?
|
||||
evex_queue_first_element(&EVEX_EQ_NAME, Event_timed*)->modified:
|
||||
(ulonglong)~0));
|
||||
}
|
||||
|
||||
int ret= WAIT_STATUS_READY;
|
||||
if (!evex_queue_num_elements(EVEX_EQ_NAME))
|
||||
ret= WAIT_STATUS_EMPTY_QUEUE;
|
||||
else if (evex_queue_first_element(&EVEX_EQ_NAME, Event_timed*) != et)
|
||||
ret= WAIT_STATUS_NEW_TOP_EVENT;
|
||||
if (thd->killed && event_executor_running_global_var)
|
||||
ret= WAIT_STATUS_STOP_EXECUTOR;
|
||||
|
||||
DBUG_RETURN(ret);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
The main scheduler thread. Inits the priority queue on start and
|
||||
destroys it on thread shutdown. Forks child threads for every event
|
||||
execution. Sleeps between thread forking and does not do a busy wait.
|
||||
|
||||
SYNOPSIS
|
||||
event_executor_main()
|
||||
arg unused
|
||||
|
||||
NOTES
|
||||
1. The host of the thead is my_localhost
|
||||
2. thd->net is initted with NULL - no communication.
|
||||
|
||||
*/
|
||||
|
||||
pthread_handler_t
|
||||
event_executor_main(void *arg)
|
||||
{
|
||||
THD *thd; /* needs to be first for thread_stack */
|
||||
uint i=0, j=0;
|
||||
my_ulonglong cnt= 0;
|
||||
|
||||
DBUG_ENTER("event_executor_main");
|
||||
DBUG_PRINT("event_executor_main", ("EVEX thread started"));
|
||||
|
||||
pthread_mutex_lock(&LOCK_evex_main_thread);
|
||||
if (!scheduler_main_thread_running)
|
||||
scheduler_main_thread_running= true;
|
||||
else
|
||||
{
|
||||
DBUG_PRINT("event_executor_main", ("already running. thd_id=%d",
|
||||
evex_main_thread_id));
|
||||
pthread_mutex_unlock(&LOCK_evex_main_thread);
|
||||
my_thread_end();
|
||||
pthread_exit(0);
|
||||
DBUG_RETURN(0); // Can't return anything here
|
||||
}
|
||||
pthread_mutex_unlock(&LOCK_evex_main_thread);
|
||||
|
||||
/* init memory root */
|
||||
init_alloc_root(&evex_mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
|
||||
|
||||
/* needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff*/
|
||||
my_thread_init();
|
||||
|
||||
if (sizeof(my_time_t) != sizeof(time_t))
|
||||
{
|
||||
sql_print_error("SCHEDULER: sizeof(my_time_t) != sizeof(time_t) ."
|
||||
"The scheduler will not work correctly. Stopping.");
|
||||
DBUG_ASSERT(0);
|
||||
goto err_no_thd;
|
||||
}
|
||||
|
||||
/* note that contructor of THD uses DBUG_ ! */
|
||||
if (!(thd = new THD))
|
||||
{
|
||||
sql_print_error("SCHEDULER: Cannot create THD for the main thread.");
|
||||
goto err_no_thd;
|
||||
}
|
||||
thd->thread_stack = (char*)&thd; // remember where our stack is
|
||||
|
||||
pthread_detach_this_thread();
|
||||
|
||||
if (init_event_thread(thd))
|
||||
goto finish;
|
||||
|
||||
/*
|
||||
make this thread visible it has no vio -> show processlist won't see it
|
||||
unless it's marked as system thread
|
||||
*/
|
||||
thd->system_thread= 1;
|
||||
|
||||
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
||||
threads.append(thd);
|
||||
thread_count++;
|
||||
thread_running++;
|
||||
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
||||
|
||||
DBUG_PRINT("EVEX main thread", ("Initing events_queue"));
|
||||
|
||||
/*
|
||||
eventually manifest that we are running, not to crashe because of
|
||||
usage of non-initialized memory structures.
|
||||
*/
|
||||
VOID(pthread_mutex_lock(&LOCK_evex_running));
|
||||
VOID(pthread_mutex_lock(&LOCK_event_arrays));
|
||||
evex_queue_init(&EVEX_EQ_NAME);
|
||||
VOID(pthread_mutex_unlock(&LOCK_event_arrays));
|
||||
evex_is_running= true;
|
||||
VOID(pthread_mutex_unlock(&LOCK_evex_running));
|
||||
|
||||
thd->security_ctx->user= my_strdup("event_scheduler", MYF(0));
|
||||
|
||||
if (evex_load_events_from_db(thd))
|
||||
goto finish;
|
||||
|
||||
evex_main_thread_id= thd->thread_id;
|
||||
|
||||
sql_print_information("SCHEDULER: Main thread started");
|
||||
while (!thd->killed)
|
||||
{
|
||||
TIME time_now;
|
||||
Event_timed *et;
|
||||
|
||||
cnt++;
|
||||
DBUG_PRINT("info", ("EVEX External Loop %d thd->k", cnt));
|
||||
|
||||
thd->proc_info = "Sleeping";
|
||||
if (!event_executor_running_global_var)
|
||||
{
|
||||
sql_print_information("SCHEDULER: Asked to stop.");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!evex_queue_num_elements(EVEX_EQ_NAME))
|
||||
{
|
||||
my_sleep(100000);// sleep 0.1s
|
||||
continue;
|
||||
}
|
||||
|
||||
restart_ticking:
|
||||
switch (executor_wait_till_next_event_exec(thd)) {
|
||||
case WAIT_STATUS_READY: // time to execute the event on top
|
||||
DBUG_PRINT("evex main thread",("time to execute an event"));
|
||||
break;
|
||||
case WAIT_STATUS_EMPTY_QUEUE: // no more events
|
||||
DBUG_PRINT("evex main thread",("no more events"));
|
||||
continue;
|
||||
break;
|
||||
case WAIT_STATUS_NEW_TOP_EVENT: // new event on top in the queue
|
||||
DBUG_PRINT("evex main thread",("restart ticking"));
|
||||
goto restart_ticking;
|
||||
case WAIT_STATUS_STOP_EXECUTOR:
|
||||
sql_print_information("SCHEDULER: Asked to stop.");
|
||||
goto finish;
|
||||
break;
|
||||
default:
|
||||
DBUG_ASSERT(0);
|
||||
}
|
||||
|
||||
|
||||
VOID(pthread_mutex_lock(&LOCK_event_arrays));
|
||||
thd->end_time();
|
||||
my_tz_UTC->gmt_sec_to_TIME(&time_now, thd->query_start());
|
||||
|
||||
if (!evex_queue_num_elements(EVEX_EQ_NAME))
|
||||
{
|
||||
VOID(pthread_mutex_unlock(&LOCK_event_arrays));
|
||||
DBUG_PRINT("evex main thread",("empty queue"));
|
||||
continue;
|
||||
}
|
||||
et= evex_queue_first_element(&EVEX_EQ_NAME, Event_timed*);
|
||||
DBUG_PRINT("evex main thread",("got event from the queue"));
|
||||
|
||||
if (!et->execute_at_null && my_time_compare(&time_now,&et->execute_at) == -1)
|
||||
{
|
||||
DBUG_PRINT("evex main thread",("still not the time for execution"));
|
||||
VOID(pthread_mutex_unlock(&LOCK_event_arrays));
|
||||
continue;
|
||||
}
|
||||
|
||||
DBUG_PRINT("evex main thread",("it's right time"));
|
||||
if (et->status == MYSQL_EVENT_ENABLED)
|
||||
{
|
||||
int fork_ret_code;
|
||||
|
||||
DBUG_PRINT("evex main thread", ("[%10s] this exec at [%llu]", et->name.str,
|
||||
TIME_to_ulonglong_datetime(&et->execute_at)));
|
||||
et->mark_last_executed(thd);
|
||||
if (et->compute_next_execution_time())
|
||||
{
|
||||
sql_print_error("SCHEDULER: Error while computing time of %s.%s . "
|
||||
"Disabling after execution.",
|
||||
et->dbname.str, et->name.str);
|
||||
et->status= MYSQL_EVENT_DISABLED;
|
||||
}
|
||||
DBUG_PRINT("evex main thread", ("[%10s] next exec at [%llu]", et->name.str,
|
||||
TIME_to_ulonglong_datetime(&et->execute_at)));
|
||||
|
||||
et->update_fields(thd);
|
||||
#ifndef DBUG_FAULTY_THR
|
||||
thread_safe_increment(workers_count, &LOCK_workers_count);
|
||||
switch ((fork_ret_code= et->spawn_now(event_executor_worker))) {
|
||||
case EVENT_EXEC_CANT_FORK:
|
||||
thread_safe_decrement(workers_count, &LOCK_workers_count);
|
||||
sql_print_error("SCHEDULER: Problem while trying to create a thread");
|
||||
UNLOCK_MUTEX_AND_BAIL_OUT(LOCK_event_arrays, finish);
|
||||
case EVENT_EXEC_ALREADY_EXEC:
|
||||
thread_safe_decrement(workers_count, &LOCK_workers_count);
|
||||
sql_print_information("SCHEDULER: %s.%s in execution. Skip this time.",
|
||||
et->dbname.str, et->name.str);
|
||||
break;
|
||||
default:
|
||||
DBUG_ASSERT(!fork_ret_code);
|
||||
if (fork_ret_code)
|
||||
thread_safe_decrement(workers_count, &LOCK_workers_count);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
event_executor_worker((void *) et);
|
||||
#endif
|
||||
/*
|
||||
1. For one-time event : year is > 0 and expression is 0
|
||||
2. For recurring, expression is != -=> check execute_at_null in this case
|
||||
*/
|
||||
if ((et->execute_at.year && !et->expression) || et->execute_at_null)
|
||||
et->flags |= EVENT_EXEC_NO_MORE;
|
||||
|
||||
if ((et->flags & EVENT_EXEC_NO_MORE) || et->status == MYSQL_EVENT_DISABLED)
|
||||
evex_queue_delete_element(&EVEX_EQ_NAME, 0);// 0 is top, internally 1
|
||||
else
|
||||
evex_queue_first_updated(&EVEX_EQ_NAME);
|
||||
}
|
||||
DBUG_PRINT("evex main thread",("unlocking"));
|
||||
VOID(pthread_mutex_unlock(&LOCK_event_arrays));
|
||||
}/* while */
|
||||
finish:
|
||||
|
||||
/* First manifest that this thread does not work and then destroy */
|
||||
VOID(pthread_mutex_lock(&LOCK_evex_running));
|
||||
evex_is_running= false;
|
||||
evex_main_thread_id= 0;
|
||||
VOID(pthread_mutex_unlock(&LOCK_evex_running));
|
||||
|
||||
|
||||
/*
|
||||
TODO: A better will be with a conditional variable
|
||||
*/
|
||||
/*
|
||||
Read workers_count without lock, no need for locking.
|
||||
In the worst case we have to wait 1sec more.
|
||||
*/
|
||||
sql_print_information("SCHEDULER: Stopping. Waiting for worker threads to finish.");
|
||||
while (1)
|
||||
{
|
||||
VOID(pthread_mutex_lock(&LOCK_workers_count));
|
||||
if (!workers_count)
|
||||
{
|
||||
VOID(pthread_mutex_unlock(&LOCK_workers_count));
|
||||
break;
|
||||
}
|
||||
VOID(pthread_mutex_unlock(&LOCK_workers_count));
|
||||
my_sleep(1000000);// 1s
|
||||
}
|
||||
|
||||
/*
|
||||
First we free all objects ...
|
||||
Lock because a DROP DATABASE could be running in parallel and it locks on these
|
||||
*/
|
||||
sql_print_information("SCHEDULER: Emptying the queue.");
|
||||
VOID(pthread_mutex_lock(&LOCK_event_arrays));
|
||||
for (i= 0; i < evex_queue_num_elements(EVEX_EQ_NAME); ++i)
|
||||
{
|
||||
Event_timed *et= evex_queue_element(&EVEX_EQ_NAME, i, Event_timed*);
|
||||
et->free_sp();
|
||||
delete et;
|
||||
}
|
||||
VOID(pthread_mutex_unlock(&LOCK_event_arrays));
|
||||
/* ... then we can thrash the whole queue at once */
|
||||
evex_queue_destroy(&EVEX_EQ_NAME);
|
||||
|
||||
thd->proc_info = "Clearing";
|
||||
DBUG_ASSERT(thd->net.buff != 0);
|
||||
net_end(&thd->net); // destructor will not free it, because we are weird
|
||||
THD_CHECK_SENTRY(thd);
|
||||
|
||||
pthread_mutex_lock(&LOCK_thread_count);
|
||||
thread_count--;
|
||||
thread_running--;
|
||||
#ifndef DBUG_FAULTY_THR
|
||||
THD_CHECK_SENTRY(thd);
|
||||
delete thd;
|
||||
#endif
|
||||
pthread_mutex_unlock(&LOCK_thread_count);
|
||||
|
||||
|
||||
err_no_thd:
|
||||
VOID(pthread_mutex_lock(&LOCK_evex_running));
|
||||
evex_is_running= false;
|
||||
event_executor_running_global_var= false;
|
||||
VOID(pthread_mutex_unlock(&LOCK_evex_running));
|
||||
|
||||
free_root(&evex_mem_root, MYF(0));
|
||||
sql_print_information("SCHEDULER: Stopped.");
|
||||
|
||||
#ifndef DBUG_FAULTY_THR
|
||||
pthread_mutex_lock(&LOCK_evex_main_thread);
|
||||
scheduler_main_thread_running= false;
|
||||
pthread_mutex_unlock(&LOCK_evex_main_thread);
|
||||
|
||||
my_thread_end();
|
||||
pthread_exit(0);
|
||||
#endif
|
||||
DBUG_RETURN(0); // Can't return anything here
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Function that executes an event in a child thread. Setups the
|
||||
environment for the event execution and cleans after that.
|
||||
|
||||
SYNOPSIS
|
||||
event_executor_worker()
|
||||
arg The Event_timed object to be processed
|
||||
*/
|
||||
|
||||
pthread_handler_t
|
||||
event_executor_worker(void *event_void)
|
||||
{
|
||||
THD *thd; /* needs to be first for thread_stack */
|
||||
Event_timed *event = (Event_timed *) event_void;
|
||||
MEM_ROOT worker_mem_root;
|
||||
|
||||
DBUG_ENTER("event_executor_worker");
|
||||
|
||||
init_alloc_root(&worker_mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
|
||||
|
||||
#ifndef DBUG_FAULTY_THR
|
||||
my_thread_init();
|
||||
|
||||
if (!(thd = new THD)) /* note that contructor of THD uses DBUG_ ! */
|
||||
{
|
||||
sql_print_error("SCHEDULER: Cannot create a THD structure in an worker.");
|
||||
goto err_no_thd;
|
||||
}
|
||||
thd->thread_stack = (char*)&thd; // remember where our stack is
|
||||
thd->mem_root= &worker_mem_root;
|
||||
|
||||
pthread_detach_this_thread();
|
||||
|
||||
if (init_event_thread(thd))
|
||||
goto err;
|
||||
|
||||
thd->init_for_queries();
|
||||
|
||||
/* make this thread visible it has no vio -> show processlist needs this flag */
|
||||
thd->system_thread= 1;
|
||||
|
||||
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
||||
threads.append(thd);
|
||||
thread_count++;
|
||||
thread_running++;
|
||||
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
||||
#else
|
||||
thd= current_thd;
|
||||
#endif
|
||||
|
||||
thd->enable_slow_log= TRUE;
|
||||
{
|
||||
int ret;
|
||||
sql_print_information("SCHEDULER: Executing event %s.%s of %s [EXPR:%d]",
|
||||
event->dbname.str, event->name.str,
|
||||
event->definer.str, (int) event->expression);
|
||||
|
||||
ret= event->execute(thd, &worker_mem_root);
|
||||
|
||||
evex_print_warnings(thd, event);
|
||||
sql_print_information("SCHEDULER: Executed event %s.%s of %s [EXPR:%d]. "
|
||||
"RetCode=%d", event->dbname.str, event->name.str,
|
||||
event->definer.str, (int) event->expression, ret);
|
||||
if (ret == EVEX_COMPILE_ERROR)
|
||||
sql_print_information("SCHEDULER: COMPILE ERROR for event %s.%s of",
|
||||
event->dbname.str, event->name.str,
|
||||
event->definer.str);
|
||||
else if (ret == EVEX_MICROSECOND_UNSUP)
|
||||
sql_print_information("SCHEDULER: MICROSECOND is not supported");
|
||||
}
|
||||
event->spawn_thread_finish(thd);
|
||||
|
||||
|
||||
err:
|
||||
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
||||
#ifndef DBUG_FAULTY_THR
|
||||
thread_count--;
|
||||
thread_running--;
|
||||
/*
|
||||
Some extra safety, which should not been needed (normally, event deletion
|
||||
should already have done these assignments (each event which sets these
|
||||
variables is supposed to set them to 0 before terminating)).
|
||||
*/
|
||||
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
||||
|
||||
thd->proc_info = "Clearing";
|
||||
DBUG_ASSERT(thd->net.buff != 0);
|
||||
net_end(&thd->net); // destructor will not free it, because we are weird
|
||||
THD_CHECK_SENTRY(thd);
|
||||
|
||||
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
||||
THD_CHECK_SENTRY(thd);
|
||||
delete thd;
|
||||
#endif
|
||||
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
||||
|
||||
err_no_thd:
|
||||
|
||||
free_root(&worker_mem_root, MYF(0));
|
||||
thread_safe_decrement(workers_count, &LOCK_workers_count);
|
||||
|
||||
#ifndef DBUG_FAULTY_THR
|
||||
my_thread_end();
|
||||
pthread_exit(0);
|
||||
#endif
|
||||
DBUG_RETURN(0); // Can't return anything here
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Loads all ENABLED events from mysql.event into the prioritized
|
||||
queue. Called during scheduler main thread initialization. Compiles
|
||||
the events. Creates Event_timed instances for every ENABLED event
|
||||
from mysql.event.
|
||||
|
||||
SYNOPSIS
|
||||
evex_load_events_from_db()
|
||||
thd - Thread context. Used for memory allocation in some cases.
|
||||
|
||||
RETURNS
|
||||
0 OK
|
||||
!0 Error
|
||||
|
||||
NOTES
|
||||
Reports the error to the console
|
||||
*/
|
||||
|
||||
static int
|
||||
evex_load_events_from_db(THD *thd)
|
||||
{
|
||||
TABLE *table;
|
||||
READ_RECORD read_record_info;
|
||||
int ret= -1;
|
||||
uint count= 0;
|
||||
|
||||
DBUG_ENTER("evex_load_events_from_db");
|
||||
|
||||
if ((ret= evex_open_event_table(thd, TL_READ, &table)))
|
||||
{
|
||||
sql_print_error("SCHEDULER: Table mysql.event is damaged. Can not open.");
|
||||
DBUG_RETURN(SP_OPEN_TABLE_FAILED);
|
||||
}
|
||||
|
||||
VOID(pthread_mutex_lock(&LOCK_event_arrays));
|
||||
|
||||
init_read_record(&read_record_info, thd, table ,NULL,1,0);
|
||||
while (!(read_record_info.read_record(&read_record_info)))
|
||||
{
|
||||
Event_timed *et;
|
||||
if (!(et= new Event_timed))
|
||||
{
|
||||
DBUG_PRINT("evex_load_events_from_db", ("Out of memory"));
|
||||
ret= -1;
|
||||
goto end;
|
||||
}
|
||||
DBUG_PRINT("evex_load_events_from_db", ("Loading event from row."));
|
||||
|
||||
if ((ret= et->load_from_row(&evex_mem_root, table)))
|
||||
{
|
||||
sql_print_error("SCHEDULER: Error while loading from mysql.event. "
|
||||
"Table probably corrupted");
|
||||
goto end;
|
||||
}
|
||||
if (et->status != MYSQL_EVENT_ENABLED)
|
||||
{
|
||||
DBUG_PRINT("evex_load_events_from_db",("%s is disabled",et->name.str));
|
||||
delete et;
|
||||
continue;
|
||||
}
|
||||
|
||||
DBUG_PRINT("evex_load_events_from_db",
|
||||
("Event %s loaded from row. Time to compile", et->name.str));
|
||||
|
||||
switch (ret= et->compile(thd, &evex_mem_root)) {
|
||||
case EVEX_MICROSECOND_UNSUP:
|
||||
sql_print_error("SCHEDULER: mysql.event is tampered. MICROSECOND is not "
|
||||
"supported but found in mysql.event");
|
||||
goto end;
|
||||
case EVEX_COMPILE_ERROR:
|
||||
sql_print_error("SCHEDULER: Error while compiling %s.%s. Aborting load.",
|
||||
et->dbname.str, et->name.str);
|
||||
goto end;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* let's find when to be executed */
|
||||
if (et->compute_next_execution_time())
|
||||
{
|
||||
sql_print_error("SCHEDULER: Error while computing execution time of %s.%s."
|
||||
" Skipping", et->dbname.str, et->name.str);
|
||||
continue;
|
||||
}
|
||||
|
||||
DBUG_PRINT("evex_load_events_from_db", ("Adding to the exec list."));
|
||||
|
||||
evex_queue_insert(&EVEX_EQ_NAME, (EVEX_PTOQEL) et);
|
||||
DBUG_PRINT("evex_load_events_from_db", ("%p %*s",
|
||||
et, et->name.length,et->name.str));
|
||||
count++;
|
||||
}
|
||||
|
||||
ret= 0;
|
||||
|
||||
end:
|
||||
VOID(pthread_mutex_unlock(&LOCK_event_arrays));
|
||||
end_read_record(&read_record_info);
|
||||
|
||||
/* Force close to free memory */
|
||||
thd->version--;
|
||||
|
||||
close_thread_tables(thd);
|
||||
if (!ret)
|
||||
sql_print_information("SCHEDULER: Loaded %d event%s", count, (count == 1)?"":"s");
|
||||
DBUG_PRINT("info", ("Status code %d. Loaded %d event(s)", ret, count));
|
||||
|
||||
DBUG_RETURN(ret);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
The update method of the global variable event_scheduler.
|
||||
If event_scheduler is switched from 0 to 1 then the scheduler main
|
||||
thread is started.
|
||||
|
||||
SYNOPSIS
|
||||
event_executor_worker()
|
||||
thd - Thread context (unused)
|
||||
car - the new value
|
||||
|
||||
Returns
|
||||
0 OK (always)
|
||||
*/
|
||||
|
||||
bool
|
||||
sys_var_event_executor::update(THD *thd, set_var *var)
|
||||
{
|
||||
/* here start the thread if not running. */
|
||||
DBUG_ENTER("sys_var_event_executor::update");
|
||||
VOID(pthread_mutex_lock(&LOCK_evex_running));
|
||||
*value= var->save_result.ulong_value;
|
||||
|
||||
DBUG_PRINT("new_value", ("%d", *value));
|
||||
if ((my_bool) *value && !evex_is_running)
|
||||
{
|
||||
VOID(pthread_mutex_unlock(&LOCK_evex_running));
|
||||
init_events();
|
||||
} else
|
||||
VOID(pthread_mutex_unlock(&LOCK_evex_running));
|
||||
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
extern LEX_STRING warning_level_names[];
|
||||
|
||||
typedef void (*sql_print_xxx_func)(const char *format, ...);
|
||||
static sql_print_xxx_func sql_print_xxx_handlers[3] =
|
||||
{
|
||||
sql_print_information,
|
||||
sql_print_warning,
|
||||
sql_print_error
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Prints the stack of infos, warnings, errors from thd to
|
||||
the console so it can be fetched by the logs-into-tables and
|
||||
checked later.
|
||||
|
||||
Synopsis
|
||||
evex_print_warnings
|
||||
thd - thread used during the execution of the event
|
||||
et - the event itself
|
||||
|
||||
Returns
|
||||
0 - OK (always)
|
||||
|
||||
*/
|
||||
|
||||
bool
|
||||
evex_print_warnings(THD *thd, Event_timed *et)
|
||||
{
|
||||
MYSQL_ERROR *err;
|
||||
DBUG_ENTER("evex_show_warnings");
|
||||
char msg_buf[1024];
|
||||
char prefix_buf[512];
|
||||
String prefix(prefix_buf, sizeof(prefix_buf), system_charset_info);
|
||||
prefix.length(0);
|
||||
|
||||
List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
|
||||
while ((err= it++))
|
||||
{
|
||||
String err_msg(msg_buf, sizeof(msg_buf), system_charset_info);
|
||||
/* set it to 0 or we start adding at the end. That's the trick ;) */
|
||||
err_msg.length(0);
|
||||
if (!prefix.length())
|
||||
{
|
||||
prefix.append("SCHEDULER: [");
|
||||
|
||||
append_identifier(thd,&prefix,et->definer_user.str,et->definer_user.length);
|
||||
prefix.append('@');
|
||||
append_identifier(thd,&prefix,et->definer_host.str,et->definer_host.length);
|
||||
prefix.append("][", 2);
|
||||
append_identifier(thd,&prefix, et->dbname.str, et->dbname.length);
|
||||
prefix.append('.');
|
||||
append_identifier(thd,&prefix, et->name.str, et->name.length);
|
||||
prefix.append("] ", 2);
|
||||
}
|
||||
|
||||
err_msg.append(prefix);
|
||||
err_msg.append(err->msg, strlen(err->msg), system_charset_info);
|
||||
err_msg.append("]");
|
||||
DBUG_ASSERT(err->level < 3);
|
||||
(sql_print_xxx_handlers[err->level])("%*s", err_msg.length(), err_msg.c_ptr());
|
||||
}
|
||||
|
||||
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
/* Copyright (C) 2004-2005 MySQL AB
|
||||
#ifndef _EVENT_PRIV_H_
|
||||
#define _EVENT_PRIV_H_
|
||||
/* Copyright (C) 2004-2006 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -14,8 +16,6 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef _EVENT_PRIV_H_
|
||||
#define _EVENT_PRIV_H_
|
||||
#include "mysql_priv.h"
|
||||
|
||||
|
||||
|
@ -23,11 +23,6 @@
|
|||
#define EVENT_EXEC_ALREADY_EXEC 1
|
||||
#define EVENT_EXEC_CANT_FORK 2
|
||||
|
||||
#define EVEX_USE_QUEUE
|
||||
|
||||
#define UNLOCK_MUTEX_AND_BAIL_OUT(__mutex, __label) \
|
||||
{ VOID(pthread_mutex_unlock(&__mutex)); goto __label; }
|
||||
|
||||
#define EVEX_DB_FIELD_LEN 64
|
||||
#define EVEX_NAME_FIELD_LEN 64
|
||||
#define EVEX_MAX_INTERVAL_VALUE 2147483647L
|
||||
|
@ -44,39 +39,49 @@ evex_db_find_event_by_name(THD *thd, const LEX_STRING dbname,
|
|||
int
|
||||
event_timed_compare_q(void *vptr, byte* a, byte *b);
|
||||
|
||||
int db_drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
|
||||
int
|
||||
db_drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
|
||||
uint *rows_affected);
|
||||
int
|
||||
db_find_event(THD *thd, sp_name *name, LEX_STRING *definer, Event_timed **ett,
|
||||
TABLE *tbl, MEM_ROOT *root);
|
||||
|
||||
int
|
||||
db_create_event(THD *thd, Event_timed *et, my_bool create_if_not,
|
||||
uint *rows_affected);
|
||||
|
||||
int
|
||||
db_drop_events_from_table(THD *thd, LEX_STRING *db);
|
||||
|
||||
#define EXEC_QUEUE_QUEUE_NAME executing_queue
|
||||
#define EXEC_QUEUE_DARR_NAME evex_executing_queue
|
||||
|
||||
|
||||
#define EVEX_QUEUE_TYPE QUEUE
|
||||
#define EVEX_PTOQEL byte *
|
||||
|
||||
#define EVEX_EQ_NAME executing_queue
|
||||
#define evex_queue_first_element(queue, __cast) ((__cast)queue_top(queue))
|
||||
#define evex_queue_element(queue, idx, __cast) ((__cast)queue_element(queue, idx))
|
||||
#define evex_queue_delete_element(queue, idx) queue_remove(queue, idx)
|
||||
#define evex_queue_destroy(queue) delete_queue(queue)
|
||||
#define evex_queue_first_updated(queue) queue_replaced(queue)
|
||||
#define evex_queue_insert(queue, element) queue_insert_safe(queue, element);
|
||||
int
|
||||
sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs);
|
||||
|
||||
/* Compares only the name part of the identifier */
|
||||
bool
|
||||
event_timed_name_equal(Event_timed *et, LEX_STRING *name);
|
||||
|
||||
/* Compares only the schema part of the identifier */
|
||||
bool
|
||||
event_timed_db_equal(Event_timed *et, LEX_STRING *db);
|
||||
|
||||
/*
|
||||
Compares only the definer part of the identifier. Use during DROP USER
|
||||
to drop user's events. (Still not implemented)
|
||||
*/
|
||||
bool
|
||||
event_timed_definer_equal(Event_timed *et, LEX_STRING *definer);
|
||||
|
||||
/* Compares the whole identifier*/
|
||||
bool
|
||||
event_timed_identifier_equal(Event_timed *a, Event_timed *b);
|
||||
|
||||
|
||||
bool
|
||||
change_security_context(THD *thd, LEX_STRING user, LEX_STRING host,
|
||||
LEX_STRING db, Security_context *s_ctx,
|
||||
Security_context **backup);
|
||||
|
||||
void
|
||||
evex_queue_init(EVEX_QUEUE_TYPE *queue);
|
||||
|
||||
#define evex_queue_num_elements(queue) queue.elements
|
||||
|
||||
|
||||
extern bool evex_is_running;
|
||||
extern MEM_ROOT evex_mem_root;
|
||||
extern pthread_mutex_t LOCK_event_arrays,
|
||||
LOCK_workers_count,
|
||||
LOCK_evex_running;
|
||||
extern ulonglong evex_main_thread_id;
|
||||
extern QUEUE EVEX_EQ_NAME;
|
||||
restore_security_context(THD *thd, Security_context *backup);
|
||||
|
||||
#endif /* _EVENT_PRIV_H_ */
|
||||
|
|
2411
sql/event_scheduler.cc
Normal file
2411
sql/event_scheduler.cc
Normal file
File diff suppressed because it is too large
Load diff
254
sql/event_scheduler.h
Normal file
254
sql/event_scheduler.h
Normal file
|
@ -0,0 +1,254 @@
|
|||
#ifndef _EVENT_SCHEDULER_H_
|
||||
#define _EVENT_SCHEDULER_H_
|
||||
/* Copyright (C) 2004-2006 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
class THD;
|
||||
typedef bool * (*event_timed_identifier_comparator)(Event_timed*, Event_timed*);
|
||||
|
||||
int
|
||||
events_init();
|
||||
|
||||
void
|
||||
events_shutdown();
|
||||
|
||||
|
||||
class Event_scheduler
|
||||
{
|
||||
public:
|
||||
/* Return codes */
|
||||
enum enum_error_code
|
||||
{
|
||||
OP_OK= 0,
|
||||
OP_NOT_RUNNING,
|
||||
OP_CANT_KILL,
|
||||
OP_CANT_INIT,
|
||||
OP_DISABLED_EVENT,
|
||||
OP_LOAD_ERROR,
|
||||
OP_ALREADY_EXISTS
|
||||
};
|
||||
|
||||
enum enum_state
|
||||
{
|
||||
UNINITIALIZED= 0,
|
||||
INITIALIZED,
|
||||
COMMENCING,
|
||||
CANTSTART,
|
||||
RUNNING,
|
||||
SUSPENDED,
|
||||
IN_SHUTDOWN
|
||||
};
|
||||
|
||||
enum enum_suspend_or_resume
|
||||
{
|
||||
SUSPEND= 1,
|
||||
RESUME= 2
|
||||
};
|
||||
|
||||
/* Singleton access */
|
||||
static Event_scheduler*
|
||||
get_instance();
|
||||
|
||||
/* Methods for queue management follow */
|
||||
|
||||
enum enum_error_code
|
||||
add_event(THD *thd, Event_timed *et, bool check_existence);
|
||||
|
||||
bool
|
||||
drop_event(THD *thd, Event_timed *et);
|
||||
|
||||
enum enum_error_code
|
||||
replace_event(THD *thd, Event_timed *et, LEX_STRING *new_schema,
|
||||
LEX_STRING *new_name);
|
||||
|
||||
int
|
||||
drop_schema_events(THD *thd, LEX_STRING *schema);
|
||||
|
||||
int
|
||||
drop_user_events(THD *thd, LEX_STRING *definer, uint *dropped_num)
|
||||
{ DBUG_ASSERT(0); return 0;}
|
||||
|
||||
uint
|
||||
events_count();
|
||||
|
||||
/* State changing methods follow */
|
||||
|
||||
bool
|
||||
start();
|
||||
|
||||
enum enum_error_code
|
||||
stop();
|
||||
|
||||
bool
|
||||
start_suspended();
|
||||
|
||||
bool
|
||||
run(THD *thd);
|
||||
|
||||
enum enum_error_code
|
||||
suspend_or_resume(enum enum_suspend_or_resume action);
|
||||
|
||||
bool
|
||||
init();
|
||||
|
||||
void
|
||||
destroy();
|
||||
|
||||
static void
|
||||
init_mutexes();
|
||||
|
||||
static void
|
||||
destroy_mutexes();
|
||||
|
||||
void
|
||||
report_error_during_start();
|
||||
|
||||
/* Information retrieving methods follow */
|
||||
|
||||
enum enum_state
|
||||
get_state();
|
||||
|
||||
bool
|
||||
initialized();
|
||||
|
||||
static int
|
||||
dump_internal_status(THD *thd);
|
||||
|
||||
static bool
|
||||
check_system_tables(THD *thd);
|
||||
|
||||
private:
|
||||
Event_timed *
|
||||
find_event(Event_timed *etn, bool remove_from_q);
|
||||
|
||||
uint
|
||||
workers_count();
|
||||
|
||||
bool
|
||||
is_running_or_suspended();
|
||||
|
||||
/* helper functions */
|
||||
bool
|
||||
execute_top(THD *thd);
|
||||
|
||||
void
|
||||
clean_queue(THD *thd);
|
||||
|
||||
void
|
||||
stop_all_running_events(THD *thd);
|
||||
|
||||
enum enum_error_code
|
||||
load_event(THD *thd, Event_timed *etn, Event_timed **etn_new);
|
||||
|
||||
int
|
||||
load_events_from_db(THD *thd);
|
||||
|
||||
void
|
||||
drop_matching_events(THD *thd, LEX_STRING *pattern,
|
||||
bool (*)(Event_timed *,LEX_STRING *));
|
||||
|
||||
bool
|
||||
check_n_suspend_if_needed(THD *thd);
|
||||
|
||||
bool
|
||||
check_n_wait_for_non_empty_queue(THD *thd);
|
||||
|
||||
/* Singleton DP is used */
|
||||
Event_scheduler();
|
||||
|
||||
enum enum_cond_vars
|
||||
{
|
||||
COND_NONE= -1,
|
||||
/*
|
||||
COND_new_work is a conditional used to signal that there is a change
|
||||
of the queue that should inform the executor thread that new event should
|
||||
be executed sooner than previously expected, because of add/replace event.
|
||||
*/
|
||||
COND_new_work= 0,
|
||||
/*
|
||||
COND_started is a conditional used to synchronize the thread in which
|
||||
::start() was called and the spawned thread. ::start() spawns a new thread
|
||||
and then waits on COND_started but also checks when awaken that `state` is
|
||||
either RUNNING or CANTSTART. Then it returns back.
|
||||
*/
|
||||
COND_started_or_stopped,
|
||||
/*
|
||||
Conditional used for signalling from the scheduler thread back to the
|
||||
thread that calls ::suspend() or ::resume. Synchronizing the calls.
|
||||
*/
|
||||
COND_suspend_or_resume,
|
||||
/* Must be always last */
|
||||
COND_LAST,
|
||||
};
|
||||
|
||||
/* Singleton instance */
|
||||
static Event_scheduler singleton;
|
||||
|
||||
/* This is the current status of the life-cycle of the manager. */
|
||||
enum enum_state state;
|
||||
|
||||
/* Set to start the scheduler in suspended state */
|
||||
bool start_scheduler_suspended;
|
||||
|
||||
/*
|
||||
LOCK_scheduler_data is the mutex which protects the access to the
|
||||
manager's queue as well as used when signalling COND_new_work,
|
||||
COND_started and COND_shutdown.
|
||||
*/
|
||||
pthread_mutex_t LOCK_scheduler_data;
|
||||
|
||||
/*
|
||||
Holds the thread id of the executor thread or 0 if the executor is not
|
||||
running. It is used by ::shutdown() to know which thread to kill with
|
||||
kill_one_thread(). The latter wake ups a thread if it is waiting on a
|
||||
conditional variable and sets thd->killed to non-zero.
|
||||
*/
|
||||
ulong thread_id;
|
||||
|
||||
pthread_cond_t cond_vars[COND_LAST];
|
||||
static const char * const cond_vars_names[COND_LAST];
|
||||
|
||||
/* The MEM_ROOT of the object */
|
||||
MEM_ROOT scheduler_root;
|
||||
|
||||
/* The sorted queue with the Event_timed objects */
|
||||
QUEUE queue;
|
||||
|
||||
uint mutex_last_locked_at_line;
|
||||
uint mutex_last_unlocked_at_line;
|
||||
const char* mutex_last_locked_in_func;
|
||||
const char* mutex_last_unlocked_in_func;
|
||||
enum enum_cond_vars cond_waiting_on;
|
||||
bool mutex_scheduler_data_locked;
|
||||
|
||||
/* helper functions for working with mutexes & conditionals */
|
||||
void
|
||||
lock_data(const char *func, uint line);
|
||||
|
||||
void
|
||||
unlock_data(const char *func, uint line);
|
||||
|
||||
int
|
||||
cond_wait(enum enum_cond_vars, pthread_mutex_t *mutex);
|
||||
|
||||
private:
|
||||
/* Prevent use of these */
|
||||
Event_scheduler(const Event_scheduler &);
|
||||
void operator=(Event_scheduler &);
|
||||
};
|
||||
|
||||
#endif /* _EVENT_SCHEDULER_H_ */
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2004-2005 MySQL AB
|
||||
/* Copyright (C) 2004-2006 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -17,7 +17,82 @@
|
|||
#define MYSQL_LEX 1
|
||||
#include "event_priv.h"
|
||||
#include "event.h"
|
||||
#include "sp.h"
|
||||
#include "sp_head.h"
|
||||
|
||||
|
||||
/*
|
||||
Constructor
|
||||
|
||||
SYNOPSIS
|
||||
Event_timed::Event_timed()
|
||||
*/
|
||||
|
||||
Event_timed::Event_timed():in_spawned_thread(0),locked_by_thread_id(0),
|
||||
running(0), thread_id(0), status_changed(false),
|
||||
last_executed_changed(false), expression(0),
|
||||
created(0), modified(0),
|
||||
on_completion(Event_timed::ON_COMPLETION_DROP),
|
||||
status(Event_timed::ENABLED), sphead(0),
|
||||
sql_mode(0), body_begin(0), dropped(false),
|
||||
free_sphead_on_delete(true), flags(0)
|
||||
|
||||
{
|
||||
pthread_mutex_init(&this->LOCK_running, MY_MUTEX_INIT_FAST);
|
||||
pthread_cond_init(&this->COND_finished, NULL);
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Destructor
|
||||
|
||||
SYNOPSIS
|
||||
Event_timed::~Event_timed()
|
||||
*/
|
||||
|
||||
Event_timed::~Event_timed()
|
||||
{
|
||||
deinit_mutexes();
|
||||
|
||||
if (free_sphead_on_delete)
|
||||
free_sp();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Destructor
|
||||
|
||||
SYNOPSIS
|
||||
Event_timed::~deinit_mutexes()
|
||||
*/
|
||||
|
||||
void
|
||||
Event_timed::deinit_mutexes()
|
||||
{
|
||||
pthread_mutex_destroy(&this->LOCK_running);
|
||||
pthread_cond_destroy(&this->COND_finished);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Checks whether the event is running
|
||||
|
||||
SYNOPSIS
|
||||
Event_timed::is_running()
|
||||
*/
|
||||
|
||||
bool
|
||||
Event_timed::is_running()
|
||||
{
|
||||
bool ret;
|
||||
|
||||
VOID(pthread_mutex_lock(&this->LOCK_running));
|
||||
ret= running;
|
||||
VOID(pthread_mutex_unlock(&this->LOCK_running));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Init all member variables
|
||||
|
@ -238,7 +313,7 @@ Event_timed::init_execute_at(THD *thd, Item *expr)
|
|||
expr how much?
|
||||
new_interval what is the interval
|
||||
|
||||
RETURNS
|
||||
RETURN VALUE
|
||||
0 OK
|
||||
EVEX_PARSE_ERROR fix_fields failed
|
||||
EVEX_BAD_PARAMS Interval is not positive
|
||||
|
@ -342,7 +417,7 @@ Event_timed::init_interval(THD *thd, Item *expr, interval_type new_interval)
|
|||
DATE_ADD(NOW(), INTERVAL 1 DAY) -- start tommorow at
|
||||
same time.
|
||||
|
||||
RETURNS
|
||||
RETURN VALUE
|
||||
0 OK
|
||||
EVEX_PARSE_ERROR fix_fields failed
|
||||
EVEX_BAD_PARAMS starts before now
|
||||
|
@ -408,7 +483,7 @@ Event_timed::init_starts(THD *thd, Item *new_starts)
|
|||
DATE_ADD(NOW(), INTERVAL 1 DAY) -- end tommorow at
|
||||
same time.
|
||||
|
||||
RETURNS
|
||||
RETURN VALUE
|
||||
0 OK
|
||||
EVEX_PARSE_ERROR fix_fields failed
|
||||
ER_WRONG_VALUE starts distant date (after year 2037)
|
||||
|
@ -492,6 +567,9 @@ Event_timed::init_comment(THD *thd, LEX_STRING *set_comment)
|
|||
|
||||
SYNOPSIS
|
||||
Event_timed::init_definer()
|
||||
|
||||
RETURN VALUE
|
||||
0 OK
|
||||
*/
|
||||
|
||||
int
|
||||
|
@ -534,6 +612,10 @@ Event_timed::init_definer(THD *thd)
|
|||
SYNOPSIS
|
||||
Event_timed::load_from_row(MEM_ROOT *mem_root, TABLE *table)
|
||||
|
||||
RETURN VALUE
|
||||
0 OK
|
||||
EVEX_GET_FIELD_FAILED Error
|
||||
|
||||
NOTES
|
||||
This method is silent on errors and should behave like that. Callers
|
||||
should handle throwing of error messages. The reason is that the class
|
||||
|
@ -555,29 +637,29 @@ Event_timed::load_from_row(MEM_ROOT *mem_root, TABLE *table)
|
|||
|
||||
et= this;
|
||||
|
||||
if (table->s->fields != EVEX_FIELD_COUNT)
|
||||
if (table->s->fields != Events::FIELD_COUNT)
|
||||
goto error;
|
||||
|
||||
if ((et->dbname.str= get_field(mem_root,
|
||||
table->field[EVEX_FIELD_DB])) == NULL)
|
||||
table->field[Events::FIELD_DB])) == NULL)
|
||||
goto error;
|
||||
|
||||
et->dbname.length= strlen(et->dbname.str);
|
||||
|
||||
if ((et->name.str= get_field(mem_root,
|
||||
table->field[EVEX_FIELD_NAME])) == NULL)
|
||||
table->field[Events::FIELD_NAME])) == NULL)
|
||||
goto error;
|
||||
|
||||
et->name.length= strlen(et->name.str);
|
||||
|
||||
if ((et->body.str= get_field(mem_root,
|
||||
table->field[EVEX_FIELD_BODY])) == NULL)
|
||||
table->field[Events::FIELD_BODY])) == NULL)
|
||||
goto error;
|
||||
|
||||
et->body.length= strlen(et->body.str);
|
||||
|
||||
if ((et->definer.str= get_field(mem_root,
|
||||
table->field[EVEX_FIELD_DEFINER])) == NullS)
|
||||
table->field[Events::FIELD_DEFINER])) == NullS)
|
||||
goto error;
|
||||
et->definer.length= strlen(et->definer.str);
|
||||
|
||||
|
@ -594,69 +676,71 @@ Event_timed::load_from_row(MEM_ROOT *mem_root, TABLE *table)
|
|||
et->definer_host.str= strmake_root(mem_root, ptr + 1, len);/* 1:because of @*/
|
||||
et->definer_host.length= len;
|
||||
|
||||
et->starts_null= table->field[EVEX_FIELD_STARTS]->is_null();
|
||||
res1= table->field[EVEX_FIELD_STARTS]->get_date(&et->starts,TIME_NO_ZERO_DATE);
|
||||
et->starts_null= table->field[Events::FIELD_STARTS]->is_null();
|
||||
res1= table->field[Events::FIELD_STARTS]->
|
||||
get_date(&et->starts,TIME_NO_ZERO_DATE);
|
||||
|
||||
et->ends_null= table->field[EVEX_FIELD_ENDS]->is_null();
|
||||
res2= table->field[EVEX_FIELD_ENDS]->get_date(&et->ends, TIME_NO_ZERO_DATE);
|
||||
et->ends_null= table->field[Events::FIELD_ENDS]->is_null();
|
||||
res2= table->field[Events::FIELD_ENDS]->get_date(&et->ends, TIME_NO_ZERO_DATE);
|
||||
|
||||
if (!table->field[EVEX_FIELD_INTERVAL_EXPR]->is_null())
|
||||
et->expression= table->field[EVEX_FIELD_INTERVAL_EXPR]->val_int();
|
||||
if (!table->field[Events::FIELD_INTERVAL_EXPR]->is_null())
|
||||
et->expression= table->field[Events::FIELD_INTERVAL_EXPR]->val_int();
|
||||
else
|
||||
et->expression= 0;
|
||||
/*
|
||||
If res1 and res2 are true then both fields are empty.
|
||||
Hence if EVEX_FIELD_EXECUTE_AT is empty there is an error.
|
||||
Hence if Events::FIELD_EXECUTE_AT is empty there is an error.
|
||||
*/
|
||||
et->execute_at_null= table->field[EVEX_FIELD_EXECUTE_AT]->is_null();
|
||||
et->execute_at_null=
|
||||
table->field[Events::FIELD_EXECUTE_AT]->is_null();
|
||||
DBUG_ASSERT(!(et->starts_null && et->ends_null && !et->expression &&
|
||||
et->execute_at_null));
|
||||
if (!et->expression &&
|
||||
table->field[EVEX_FIELD_EXECUTE_AT]->get_date(&et->execute_at,
|
||||
TIME_NO_ZERO_DATE))
|
||||
table->field[Events::FIELD_EXECUTE_AT]-> get_date(&et->execute_at,
|
||||
TIME_NO_ZERO_DATE))
|
||||
goto error;
|
||||
|
||||
/*
|
||||
In DB the values start from 1 but enum interval_type starts
|
||||
from 0
|
||||
*/
|
||||
if (!table->field[EVEX_FIELD_TRANSIENT_INTERVAL]->is_null())
|
||||
et->interval= (interval_type)
|
||||
((ulonglong) table->field[EVEX_FIELD_TRANSIENT_INTERVAL]->val_int() - 1);
|
||||
if (!table->field[Events::FIELD_TRANSIENT_INTERVAL]->is_null())
|
||||
et->interval= (interval_type) ((ulonglong)
|
||||
table->field[Events::FIELD_TRANSIENT_INTERVAL]->val_int() - 1);
|
||||
else
|
||||
et->interval= (interval_type) 0;
|
||||
|
||||
et->created= table->field[EVEX_FIELD_CREATED]->val_int();
|
||||
et->modified= table->field[EVEX_FIELD_MODIFIED]->val_int();
|
||||
et->created= table->field[Events::FIELD_CREATED]->val_int();
|
||||
et->modified= table->field[Events::FIELD_MODIFIED]->val_int();
|
||||
|
||||
table->field[EVEX_FIELD_LAST_EXECUTED]->
|
||||
table->field[Events::FIELD_LAST_EXECUTED]->
|
||||
get_date(&et->last_executed, TIME_NO_ZERO_DATE);
|
||||
|
||||
last_executed_changed= false;
|
||||
|
||||
/* ToDo : Andrey . Find a way not to allocate ptr on event_mem_root */
|
||||
if ((ptr= get_field(mem_root, table->field[EVEX_FIELD_STATUS])) == NullS)
|
||||
if ((ptr= get_field(mem_root, table->field[Events::FIELD_STATUS])) == NullS)
|
||||
goto error;
|
||||
|
||||
DBUG_PRINT("load_from_row", ("Event [%s] is [%s]", et->name.str, ptr));
|
||||
et->status= (ptr[0]=='E'? MYSQL_EVENT_ENABLED:MYSQL_EVENT_DISABLED);
|
||||
et->status= (ptr[0]=='E'? Event_timed::ENABLED:Event_timed::DISABLED);
|
||||
|
||||
/* ToDo : Andrey . Find a way not to allocate ptr on event_mem_root */
|
||||
if ((ptr= get_field(mem_root,
|
||||
table->field[EVEX_FIELD_ON_COMPLETION])) == NullS)
|
||||
table->field[Events::FIELD_ON_COMPLETION])) == NullS)
|
||||
goto error;
|
||||
|
||||
et->on_completion= (ptr[0]=='D'? MYSQL_EVENT_ON_COMPLETION_DROP:
|
||||
MYSQL_EVENT_ON_COMPLETION_PRESERVE);
|
||||
et->on_completion= (ptr[0]=='D'? Event_timed::ON_COMPLETION_DROP:
|
||||
Event_timed::ON_COMPLETION_PRESERVE);
|
||||
|
||||
et->comment.str= get_field(mem_root, table->field[EVEX_FIELD_COMMENT]);
|
||||
et->comment.str= get_field(mem_root, table->field[Events::FIELD_COMMENT]);
|
||||
if (et->comment.str != NullS)
|
||||
et->comment.length= strlen(et->comment.str);
|
||||
else
|
||||
et->comment.length= 0;
|
||||
|
||||
|
||||
et->sql_mode= (ulong) table->field[EVEX_FIELD_SQL_MODE]->val_int();
|
||||
et->sql_mode= (ulong) table->field[Events::FIELD_SQL_MODE]->val_int();
|
||||
|
||||
DBUG_RETURN(0);
|
||||
error:
|
||||
|
@ -676,7 +760,7 @@ error:
|
|||
i_value quantity of time type interval to add
|
||||
i_type type of interval to add (SECOND, MINUTE, HOUR, WEEK ...)
|
||||
|
||||
RETURNS
|
||||
RETURN VALUE
|
||||
0 OK
|
||||
1 Error
|
||||
|
||||
|
@ -834,6 +918,10 @@ done:
|
|||
SYNOPSIS
|
||||
Event_timed::compute_next_execution_time()
|
||||
|
||||
RETURN VALUE
|
||||
FALSE OK
|
||||
TRUE Error
|
||||
|
||||
NOTES
|
||||
The time is set in execute_at, if no more executions the latter is set to
|
||||
0000-00-00.
|
||||
|
@ -843,7 +931,6 @@ bool
|
|||
Event_timed::compute_next_execution_time()
|
||||
{
|
||||
TIME time_now;
|
||||
my_time_t now;
|
||||
int tmp;
|
||||
|
||||
DBUG_ENTER("Event_timed::compute_next_execution_time");
|
||||
|
@ -852,7 +939,7 @@ Event_timed::compute_next_execution_time()
|
|||
TIME_to_ulonglong_datetime(&ends),
|
||||
TIME_to_ulonglong_datetime(&last_executed)));
|
||||
|
||||
if (status == MYSQL_EVENT_DISABLED)
|
||||
if (status == Event_timed::DISABLED)
|
||||
{
|
||||
DBUG_PRINT("compute_next_execution_time",
|
||||
("Event %s is DISABLED", name.str));
|
||||
|
@ -866,14 +953,15 @@ Event_timed::compute_next_execution_time()
|
|||
{
|
||||
DBUG_PRINT("info",("One-time event %s.%s of was already executed",
|
||||
dbname.str, name.str, definer.str));
|
||||
dropped= (on_completion == MYSQL_EVENT_ON_COMPLETION_DROP);
|
||||
dropped= (on_completion == Event_timed::ON_COMPLETION_DROP);
|
||||
DBUG_PRINT("info",("One-time event will be dropped=%d.", dropped));
|
||||
|
||||
status= MYSQL_EVENT_DISABLED;
|
||||
status= Event_timed::DISABLED;
|
||||
status_changed= true;
|
||||
}
|
||||
goto ret;
|
||||
}
|
||||
current_thd->end_time();
|
||||
my_tz_UTC->gmt_sec_to_TIME(&time_now, current_thd->query_start());
|
||||
|
||||
DBUG_PRINT("info",("NOW=[%llu]", TIME_to_ulonglong_datetime(&time_now)));
|
||||
|
@ -885,9 +973,9 @@ Event_timed::compute_next_execution_time()
|
|||
/* time_now is after ends. don't execute anymore */
|
||||
set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME);
|
||||
execute_at_null= TRUE;
|
||||
if (on_completion == MYSQL_EVENT_ON_COMPLETION_DROP)
|
||||
if (on_completion == Event_timed::ON_COMPLETION_DROP)
|
||||
dropped= true;
|
||||
status= MYSQL_EVENT_DISABLED;
|
||||
status= Event_timed::DISABLED;
|
||||
status_changed= true;
|
||||
|
||||
goto ret;
|
||||
|
@ -937,7 +1025,6 @@ Event_timed::compute_next_execution_time()
|
|||
{
|
||||
TIME next_exec;
|
||||
|
||||
DBUG_PRINT("info", ("Executed at least once"));
|
||||
if (get_next_time(&next_exec, &starts, &time_now,
|
||||
last_executed.year? &last_executed:&starts,
|
||||
expression, interval))
|
||||
|
@ -946,12 +1033,15 @@ Event_timed::compute_next_execution_time()
|
|||
/* There was previous execution */
|
||||
if (my_time_compare(&ends, &next_exec) == -1)
|
||||
{
|
||||
DBUG_PRINT("info", ("Next execution after ENDS. Stop executing."));
|
||||
DBUG_PRINT("info", ("Next execution of %s after ENDS. Stop executing.",
|
||||
name.str));
|
||||
/* Next execution after ends. No more executions */
|
||||
set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME);
|
||||
execute_at_null= TRUE;
|
||||
if (on_completion == MYSQL_EVENT_ON_COMPLETION_DROP)
|
||||
if (on_completion == Event_timed::ON_COMPLETION_DROP)
|
||||
dropped= true;
|
||||
status= Event_timed::DISABLED;
|
||||
status_changed= true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1006,7 +1096,6 @@ Event_timed::compute_next_execution_time()
|
|||
|
||||
{
|
||||
TIME next_exec;
|
||||
DBUG_PRINT("info", ("Executed at least once."));
|
||||
if (get_next_time(&next_exec, &starts, &time_now,
|
||||
last_executed.year? &last_executed:&starts,
|
||||
expression, interval))
|
||||
|
@ -1042,7 +1131,9 @@ Event_timed::compute_next_execution_time()
|
|||
DBUG_PRINT("info", ("Next execution after ENDS. Stop executing."));
|
||||
set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME);
|
||||
execute_at_null= TRUE;
|
||||
if (on_completion == MYSQL_EVENT_ON_COMPLETION_DROP)
|
||||
status= Event_timed::DISABLED;
|
||||
status_changed= true;
|
||||
if (on_completion == Event_timed::ON_COMPLETION_DROP)
|
||||
dropped= true;
|
||||
}
|
||||
else
|
||||
|
@ -1083,9 +1174,6 @@ Event_timed::mark_last_executed(THD *thd)
|
|||
my_tz_UTC->gmt_sec_to_TIME(&time_now, (my_time_t) thd->query_start());
|
||||
|
||||
last_executed= time_now; /* was execute_at */
|
||||
#ifdef ANDREY_0
|
||||
last_executed= execute_at;
|
||||
#endif
|
||||
last_executed_changed= true;
|
||||
}
|
||||
|
||||
|
@ -1125,7 +1213,7 @@ Event_timed::drop(THD *thd)
|
|||
|
||||
RETURN VALUE
|
||||
0 OK
|
||||
SP_OPEN_TABLE_FAILED Error while opening mysql.event for writing
|
||||
EVEX_OPEN_TABLE_FAILED Error while opening mysql.event for writing
|
||||
EVEX_WRITE_ROW_FAILED On error to write to disk
|
||||
|
||||
others return code from SE in case deletion of the event
|
||||
|
@ -1149,9 +1237,9 @@ Event_timed::update_fields(THD *thd)
|
|||
|
||||
thd->reset_n_backup_open_tables_state(&backup);
|
||||
|
||||
if (evex_open_event_table(thd, TL_WRITE, &table))
|
||||
if (Events::open_event_table(thd, TL_WRITE, &table))
|
||||
{
|
||||
ret= SP_OPEN_TABLE_FAILED;
|
||||
ret= EVEX_OPEN_TABLE_FAILED;
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
@ -1165,15 +1253,15 @@ Event_timed::update_fields(THD *thd)
|
|||
|
||||
if (last_executed_changed)
|
||||
{
|
||||
table->field[EVEX_FIELD_LAST_EXECUTED]->set_notnull();
|
||||
table->field[EVEX_FIELD_LAST_EXECUTED]->store_time(&last_executed,
|
||||
MYSQL_TIMESTAMP_DATETIME);
|
||||
table->field[Events::FIELD_LAST_EXECUTED]->set_notnull();
|
||||
table->field[Events::FIELD_LAST_EXECUTED]->store_time(&last_executed,
|
||||
MYSQL_TIMESTAMP_DATETIME);
|
||||
last_executed_changed= false;
|
||||
}
|
||||
if (status_changed)
|
||||
{
|
||||
table->field[EVEX_FIELD_STATUS]->set_notnull();
|
||||
table->field[EVEX_FIELD_STATUS]->store((longlong)status, true);
|
||||
table->field[Events::FIELD_STATUS]->set_notnull();
|
||||
table->field[Events::FIELD_STATUS]->store((longlong)status, true);
|
||||
status_changed= false;
|
||||
}
|
||||
|
||||
|
@ -1215,8 +1303,8 @@ Event_timed::get_create_event(THD *thd, String *buf)
|
|||
DBUG_ENTER("get_create_event");
|
||||
DBUG_PRINT("ret_info",("body_len=[%d]body=[%s]", body.length, body.str));
|
||||
|
||||
if (expression &&
|
||||
event_reconstruct_interval_expression(&expr_buf, interval, expression))
|
||||
if (expression && Events::reconstruct_interval_expression(&expr_buf, interval,
|
||||
expression))
|
||||
DBUG_RETURN(EVEX_MICROSECOND_UNSUP);
|
||||
|
||||
buf->append(STRING_WITH_LEN("CREATE EVENT "));
|
||||
|
@ -1243,12 +1331,12 @@ Event_timed::get_create_event(THD *thd, String *buf)
|
|||
buf->append(STRING_WITH_LEN("'"));
|
||||
}
|
||||
|
||||
if (on_completion == MYSQL_EVENT_ON_COMPLETION_DROP)
|
||||
if (on_completion == Event_timed::ON_COMPLETION_DROP)
|
||||
buf->append(STRING_WITH_LEN(" ON COMPLETION NOT PRESERVE "));
|
||||
else
|
||||
buf->append(STRING_WITH_LEN(" ON COMPLETION PRESERVE "));
|
||||
|
||||
if (status == MYSQL_EVENT_ENABLED)
|
||||
if (status == Event_timed::ENABLED)
|
||||
buf->append(STRING_WITH_LEN("ENABLE"));
|
||||
else
|
||||
buf->append(STRING_WITH_LEN("DISABLE"));
|
||||
|
@ -1273,7 +1361,7 @@ Event_timed::get_create_event(THD *thd, String *buf)
|
|||
thd THD
|
||||
mem_root If != NULL use it to compile the event on it
|
||||
|
||||
RETURNS
|
||||
RETURN VALUE
|
||||
0 success
|
||||
-99 No rights on this.dbname.str
|
||||
-100 event in execution (parallel execution is impossible)
|
||||
|
@ -1283,7 +1371,6 @@ Event_timed::get_create_event(THD *thd, String *buf)
|
|||
int
|
||||
Event_timed::execute(THD *thd, MEM_ROOT *mem_root)
|
||||
{
|
||||
Security_context *save_ctx;
|
||||
/* this one is local and not needed after exec */
|
||||
Security_context security_ctx;
|
||||
int ret= 0;
|
||||
|
@ -1301,16 +1388,8 @@ Event_timed::execute(THD *thd, MEM_ROOT *mem_root)
|
|||
running= true;
|
||||
VOID(pthread_mutex_unlock(&this->LOCK_running));
|
||||
|
||||
DBUG_PRINT("info", ("master_access=%d db_access=%d",
|
||||
thd->security_ctx->master_access, thd->security_ctx->db_access));
|
||||
change_security_context(thd, &security_ctx, &save_ctx);
|
||||
DBUG_PRINT("info", ("master_access=%d db_access=%d",
|
||||
thd->security_ctx->master_access, thd->security_ctx->db_access));
|
||||
|
||||
if (!sphead && (ret= compile(thd, mem_root)))
|
||||
goto done;
|
||||
/* Now we are sure we have valid this->sphead so we can copy the context */
|
||||
sphead->m_security_ctx= security_ctx;
|
||||
/*
|
||||
THD::~THD will clean this or if there is DROP DATABASE in the SP then
|
||||
it will be free there. It should not point to our buffer which is allocated
|
||||
|
@ -1334,12 +1413,11 @@ Event_timed::execute(THD *thd, MEM_ROOT *mem_root)
|
|||
definer_host.str, dbname.str));
|
||||
ret= -99;
|
||||
}
|
||||
restore_security_context(thd, save_ctx);
|
||||
DBUG_PRINT("info", ("master_access=%d db_access=%d",
|
||||
thd->security_ctx->master_access, thd->security_ctx->db_access));
|
||||
|
||||
VOID(pthread_mutex_lock(&this->LOCK_running));
|
||||
running= false;
|
||||
/* Will compile every time a new sp_head on different root */
|
||||
free_sp();
|
||||
VOID(pthread_mutex_unlock(&this->LOCK_running));
|
||||
|
||||
done:
|
||||
|
@ -1361,55 +1439,16 @@ done:
|
|||
|
||||
|
||||
/*
|
||||
Switches the security context
|
||||
Synopsis
|
||||
Event_timed::change_security_context()
|
||||
thd - thread
|
||||
backup - where to store the old context
|
||||
|
||||
RETURN
|
||||
0 - OK
|
||||
1 - Error (generates error too)
|
||||
*/
|
||||
bool
|
||||
Event_timed::change_security_context(THD *thd, Security_context *s_ctx,
|
||||
Security_context **backup)
|
||||
{
|
||||
DBUG_ENTER("Event_timed::change_security_context");
|
||||
DBUG_PRINT("info",("%s@%s@%s",definer_user.str,definer_host.str, dbname.str));
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
s_ctx->init();
|
||||
*backup= 0;
|
||||
if (acl_getroot_no_password(s_ctx, definer_user.str, definer_host.str,
|
||||
definer_host.str, dbname.str))
|
||||
{
|
||||
my_error(ER_NO_SUCH_USER, MYF(0), definer_user.str, definer_host.str);
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
*backup= thd->security_ctx;
|
||||
thd->security_ctx= s_ctx;
|
||||
#endif
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Restores the security context
|
||||
Synopsis
|
||||
Event_timed::restore_security_context()
|
||||
thd - thread
|
||||
backup - switch to this context
|
||||
Frees the memory of the sp_head object we hold
|
||||
SYNOPSIS
|
||||
Event_timed::free_sp()
|
||||
*/
|
||||
|
||||
void
|
||||
Event_timed::restore_security_context(THD *thd, Security_context *backup)
|
||||
Event_timed::free_sp()
|
||||
{
|
||||
DBUG_ENTER("Event_timed::restore_security_context");
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (backup)
|
||||
thd->security_ctx= backup;
|
||||
#endif
|
||||
DBUG_VOID_RETURN;
|
||||
delete sphead;
|
||||
sphead= 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1445,6 +1484,9 @@ Event_timed::compile(THD *thd, MEM_ROOT *mem_root)
|
|||
CHARSET_INFO *old_character_set_client,
|
||||
*old_collation_connection,
|
||||
*old_character_set_results;
|
||||
Security_context *save_ctx;
|
||||
/* this one is local and not needed after exec */
|
||||
Security_context security_ctx;
|
||||
|
||||
DBUG_ENTER("Event_timed::compile");
|
||||
|
||||
|
@ -1488,8 +1530,10 @@ Event_timed::compile(THD *thd, MEM_ROOT *mem_root)
|
|||
|
||||
thd->query= show_create.c_ptr();
|
||||
thd->query_length= show_create.length();
|
||||
DBUG_PRINT("Event_timed::compile", ("query:%s",thd->query));
|
||||
DBUG_PRINT("info", ("query:%s",thd->query));
|
||||
|
||||
change_security_context(thd, definer_user, definer_host, dbname,
|
||||
&security_ctx, &save_ctx);
|
||||
thd->lex= &lex;
|
||||
lex_start(thd, (uchar*)thd->query, thd->query_length);
|
||||
lex.et_compile_phase= TRUE;
|
||||
|
@ -1527,6 +1571,7 @@ done:
|
|||
lex.et->deinit_mutexes();
|
||||
|
||||
lex_end(&lex);
|
||||
restore_security_context(thd, save_ctx);
|
||||
DBUG_PRINT("note", ("return old data on its place. set back NAMES"));
|
||||
|
||||
thd->lex= old_lex;
|
||||
|
@ -1548,72 +1593,63 @@ done:
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Checks whether this thread can lock the object for modification ->
|
||||
preventing being spawned for execution, and locks if possible.
|
||||
use ::can_spawn_now() only for basic checking because a race
|
||||
condition may occur between the check and eventual modification (deletion)
|
||||
of the object.
|
||||
|
||||
Returns
|
||||
true - locked
|
||||
false - cannot lock
|
||||
*/
|
||||
|
||||
my_bool
|
||||
Event_timed::can_spawn_now_n_lock(THD *thd)
|
||||
{
|
||||
my_bool ret= FALSE;
|
||||
VOID(pthread_mutex_lock(&this->LOCK_running));
|
||||
if (!in_spawned_thread)
|
||||
{
|
||||
in_spawned_thread= TRUE;
|
||||
ret= TRUE;
|
||||
locked_by_thread_id= thd->thread_id;
|
||||
}
|
||||
VOID(pthread_mutex_unlock(&this->LOCK_running));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
extern pthread_attr_t connection_attrib;
|
||||
|
||||
/*
|
||||
Checks whether is possible and forks a thread. Passes self as argument.
|
||||
|
||||
Returns
|
||||
EVENT_EXEC_STARTED - OK
|
||||
EVENT_EXEC_ALREADY_EXEC - Thread not forked, already working
|
||||
EVENT_EXEC_CANT_FORK - Unable to spawn thread (error)
|
||||
RETURN VALUE
|
||||
EVENT_EXEC_STARTED OK
|
||||
EVENT_EXEC_ALREADY_EXEC Thread not forked, already working
|
||||
EVENT_EXEC_CANT_FORK Unable to spawn thread (error)
|
||||
*/
|
||||
|
||||
int
|
||||
Event_timed::spawn_now(void * (*thread_func)(void*))
|
||||
Event_timed::spawn_now(void * (*thread_func)(void*), void *arg)
|
||||
{
|
||||
THD *thd= current_thd;
|
||||
int ret= EVENT_EXEC_STARTED;
|
||||
static uint exec_num= 0;
|
||||
DBUG_ENTER("Event_timed::spawn_now");
|
||||
DBUG_PRINT("info", ("this=0x%lx", this));
|
||||
DBUG_PRINT("info", ("[%s.%s]", dbname.str, name.str));
|
||||
|
||||
VOID(pthread_mutex_lock(&this->LOCK_running));
|
||||
|
||||
DBUG_PRINT("info", ("SCHEDULER: execute_at of %s is %lld", name.str,
|
||||
TIME_to_ulonglong_datetime(&execute_at)));
|
||||
mark_last_executed(thd);
|
||||
if (compute_next_execution_time())
|
||||
{
|
||||
sql_print_error("SCHEDULER: Error while computing time of %s.%s . "
|
||||
"Disabling after execution.", dbname.str, name.str);
|
||||
status= DISABLED;
|
||||
}
|
||||
DBUG_PRINT("evex manager", ("[%10s] next exec at [%llu]", name.str,
|
||||
TIME_to_ulonglong_datetime(&execute_at)));
|
||||
/*
|
||||
1. For one-time event : year is > 0 and expression is 0
|
||||
2. For recurring, expression is != -=> check execute_at_null in this case
|
||||
*/
|
||||
if ((execute_at.year && !expression) || execute_at_null)
|
||||
{
|
||||
sql_print_information("SCHEDULER: [%s.%s of %s] no more executions "
|
||||
"after this one", dbname.str, name.str,
|
||||
definer.str);
|
||||
flags |= EVENT_EXEC_NO_MORE | EVENT_FREE_WHEN_FINISHED;
|
||||
}
|
||||
|
||||
update_fields(thd);
|
||||
|
||||
if (!in_spawned_thread)
|
||||
{
|
||||
pthread_t th;
|
||||
in_spawned_thread= true;
|
||||
if (pthread_create(&th, &connection_attrib, thread_func, (void*)this))
|
||||
|
||||
if (pthread_create(&th, &connection_attrib, thread_func, arg))
|
||||
{
|
||||
DBUG_PRINT("info", ("problem while spawning thread"));
|
||||
ret= EVENT_EXEC_CANT_FORK;
|
||||
in_spawned_thread= false;
|
||||
}
|
||||
#ifndef DBUG_OFF
|
||||
else
|
||||
{
|
||||
sql_print_information("SCHEDULER: Started thread %d", ++exec_num);
|
||||
DBUG_PRINT("info", ("thread spawned"));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1626,55 +1662,207 @@ Event_timed::spawn_now(void * (*thread_func)(void*))
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
bool
|
||||
Event_timed::spawn_thread_finish(THD *thd)
|
||||
{
|
||||
bool should_free;
|
||||
DBUG_ENTER("Event_timed::spawn_thread_finish");
|
||||
VOID(pthread_mutex_lock(&this->LOCK_running));
|
||||
VOID(pthread_mutex_lock(&LOCK_running));
|
||||
in_spawned_thread= false;
|
||||
if ((flags & EVENT_EXEC_NO_MORE) || status == MYSQL_EVENT_DISABLED)
|
||||
{
|
||||
DBUG_PRINT("info", ("%s exec no more. to drop=%d", name.str, dropped));
|
||||
if (dropped)
|
||||
drop(thd);
|
||||
VOID(pthread_mutex_unlock(&this->LOCK_running));
|
||||
delete this;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
VOID(pthread_mutex_unlock(&this->LOCK_running));
|
||||
DBUG_VOID_RETURN;
|
||||
DBUG_PRINT("info", ("Sending COND_finished for thread %d", thread_id));
|
||||
thread_id= 0;
|
||||
if (dropped)
|
||||
drop(thd);
|
||||
pthread_cond_broadcast(&COND_finished);
|
||||
should_free= flags & EVENT_FREE_WHEN_FINISHED;
|
||||
VOID(pthread_mutex_unlock(&LOCK_running));
|
||||
DBUG_RETURN(should_free);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Unlocks the object after it has been locked with ::can_spawn_now_n_lock()
|
||||
|
||||
Returns
|
||||
0 - ok
|
||||
1 - not locked by this thread
|
||||
Kills a running event
|
||||
SYNOPSIS
|
||||
Event_timed::kill_thread()
|
||||
|
||||
RETURN VALUE
|
||||
0 OK
|
||||
-1 EVEX_CANT_KILL
|
||||
!0 Error
|
||||
*/
|
||||
|
||||
int
|
||||
Event_timed::spawn_unlock(THD *thd)
|
||||
Event_timed::kill_thread(THD *thd)
|
||||
{
|
||||
int ret= 0;
|
||||
VOID(pthread_mutex_lock(&this->LOCK_running));
|
||||
if (!in_spawned_thread)
|
||||
DBUG_ENTER("Event_timed::kill_thread");
|
||||
pthread_mutex_lock(&LOCK_running);
|
||||
DBUG_PRINT("info", ("thread_id=%lu", thread_id));
|
||||
|
||||
if (thread_id == thd->thread_id)
|
||||
{
|
||||
if (locked_by_thread_id == thd->thread_id)
|
||||
{
|
||||
in_spawned_thread= FALSE;
|
||||
locked_by_thread_id= 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sql_print_error("A thread tries to unlock when he hasn't locked. "
|
||||
"thread_id=%ld locked by %ld",
|
||||
thd->thread_id, locked_by_thread_id);
|
||||
DBUG_ASSERT(0);
|
||||
ret= 1;
|
||||
}
|
||||
/*
|
||||
We don't kill ourselves in cases like :
|
||||
alter event e_43 do alter event e_43 do set @a = 4 because
|
||||
we will never receive COND_finished.
|
||||
*/
|
||||
DBUG_PRINT("info", ("It's not safe to kill ourselves in self altering queries"));
|
||||
ret= EVEX_CANT_KILL;
|
||||
}
|
||||
VOID(pthread_mutex_unlock(&this->LOCK_running));
|
||||
return ret;
|
||||
else if (thread_id && !(ret= kill_one_thread(thd, thread_id, false)))
|
||||
{
|
||||
thd->enter_cond(&COND_finished, &LOCK_running, "Waiting for finished");
|
||||
DBUG_PRINT("info", ("Waiting for COND_finished from thread %d", thread_id));
|
||||
while (thread_id)
|
||||
pthread_cond_wait(&COND_finished, &LOCK_running);
|
||||
|
||||
DBUG_PRINT("info", ("Got COND_finished"));
|
||||
/* This will implicitly unlock LOCK_running. Hence we return before that */
|
||||
thd->exit_cond("");
|
||||
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
else if (!thread_id && in_spawned_thread)
|
||||
{
|
||||
/*
|
||||
Because the manager thread waits for the forked thread to update thread_id
|
||||
this situation is impossible.
|
||||
*/
|
||||
DBUG_ASSERT(0);
|
||||
}
|
||||
pthread_mutex_unlock(&LOCK_running);
|
||||
DBUG_PRINT("exit", ("%d", ret));
|
||||
DBUG_RETURN(ret);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Checks whether two events have the same name
|
||||
|
||||
SYNOPSIS
|
||||
event_timed_name_equal()
|
||||
|
||||
RETURN VALUE
|
||||
TRUE names are equal
|
||||
FALSE names are not equal
|
||||
*/
|
||||
|
||||
bool
|
||||
event_timed_name_equal(Event_timed *et, LEX_STRING *name)
|
||||
{
|
||||
return !sortcmp_lex_string(et->name, *name, system_charset_info);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Checks whether two events are in the same schema
|
||||
|
||||
SYNOPSIS
|
||||
event_timed_db_equal()
|
||||
|
||||
RETURN VALUE
|
||||
TRUE schemas are equal
|
||||
FALSE schemas are not equal
|
||||
*/
|
||||
|
||||
bool
|
||||
event_timed_db_equal(Event_timed *et, LEX_STRING *db)
|
||||
{
|
||||
return !sortcmp_lex_string(et->dbname, *db, system_charset_info);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Checks whether two events have the same definer
|
||||
|
||||
SYNOPSIS
|
||||
event_timed_definer_equal()
|
||||
|
||||
Returns
|
||||
TRUE definers are equal
|
||||
FALSE definers are not equal
|
||||
*/
|
||||
|
||||
bool
|
||||
event_timed_definer_equal(Event_timed *et, LEX_STRING *definer)
|
||||
{
|
||||
return !sortcmp_lex_string(et->definer, *definer, system_charset_info);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Checks whether two events are equal by identifiers
|
||||
|
||||
SYNOPSIS
|
||||
event_timed_identifier_equal()
|
||||
|
||||
RETURN VALUE
|
||||
TRUE equal
|
||||
FALSE not equal
|
||||
*/
|
||||
|
||||
bool
|
||||
event_timed_identifier_equal(Event_timed *a, Event_timed *b)
|
||||
{
|
||||
return event_timed_name_equal(a, &b->name) &&
|
||||
event_timed_db_equal(a, &b->dbname) &&
|
||||
event_timed_definer_equal(a, &b->definer);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Switches the security context
|
||||
SYNOPSIS
|
||||
change_security_context()
|
||||
thd Thread
|
||||
user The user
|
||||
host The host of the user
|
||||
db The schema for which the security_ctx will be loaded
|
||||
s_ctx Security context to load state into
|
||||
backup Where to store the old context
|
||||
|
||||
RETURN VALUE
|
||||
0 - OK
|
||||
1 - Error (generates error too)
|
||||
*/
|
||||
|
||||
bool
|
||||
change_security_context(THD *thd, LEX_STRING user, LEX_STRING host,
|
||||
LEX_STRING db, Security_context *s_ctx,
|
||||
Security_context **backup)
|
||||
{
|
||||
DBUG_ENTER("change_security_context");
|
||||
DBUG_PRINT("info",("%s@%s@%s", user.str, host.str, db.str));
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
s_ctx->init();
|
||||
*backup= 0;
|
||||
if (acl_getroot_no_password(s_ctx, user.str, host.str, host.str, db.str))
|
||||
{
|
||||
my_error(ER_NO_SUCH_USER, MYF(0), user.str, host.str);
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
*backup= thd->security_ctx;
|
||||
thd->security_ctx= s_ctx;
|
||||
#endif
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Restores the security context
|
||||
SYNOPSIS
|
||||
restore_security_context()
|
||||
thd - thread
|
||||
backup - switch to this context
|
||||
*/
|
||||
|
||||
void
|
||||
restore_security_context(THD *thd, Security_context *backup)
|
||||
{
|
||||
DBUG_ENTER("restore_security_context");
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (backup)
|
||||
thd->security_ctx= backup;
|
||||
#endif
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
|
|
@ -453,6 +453,7 @@ static SYMBOL symbols[] = {
|
|||
{ "RTREE", SYM(RTREE_SYM)},
|
||||
{ "SAVEPOINT", SYM(SAVEPOINT_SYM)},
|
||||
{ "SCHEDULE", SYM(SCHEDULE_SYM)},
|
||||
{ "SCHEDULER", SYM(SCHEDULER_SYM)},
|
||||
{ "SCHEMA", SYM(DATABASE)},
|
||||
{ "SCHEMAS", SYM(DATABASES)},
|
||||
{ "SECOND", SYM(SECOND_SYM)},
|
||||
|
|
|
@ -55,6 +55,14 @@ static int binlog_commit(THD *thd, bool all);
|
|||
static int binlog_rollback(THD *thd, bool all);
|
||||
static int binlog_prepare(THD *thd, bool all);
|
||||
|
||||
sql_print_message_func sql_print_message_handlers[3] =
|
||||
{
|
||||
sql_print_information,
|
||||
sql_print_warning,
|
||||
sql_print_error
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
This is a POD. Please keep it that way!
|
||||
|
||||
|
|
|
@ -79,7 +79,8 @@ char *sql_strmake_with_convert(const char *str, uint32 arg_length,
|
|||
CHARSET_INFO *from_cs,
|
||||
uint32 max_res_length,
|
||||
CHARSET_INFO *to_cs, uint32 *result_length);
|
||||
void kill_one_thread(THD *thd, ulong id, bool only_kill_query);
|
||||
uint kill_one_thread(THD *thd, ulong id, bool only_kill_query);
|
||||
void sql_kill(THD *thd, ulong id, bool only_kill_query);
|
||||
bool net_request_file(NET* net, const char* fname);
|
||||
char* query_table_status(THD *thd,const char *db,const char *table_name);
|
||||
|
||||
|
@ -1378,10 +1379,13 @@ bool init_errmessage(void);
|
|||
#endif /* MYSQL_SERVER */
|
||||
void sql_perror(const char *message);
|
||||
|
||||
|
||||
int vprint_msg_to_log(enum loglevel level, const char *format, va_list args);
|
||||
void sql_print_error(const char *format, ...);
|
||||
void sql_print_warning(const char *format, ...);
|
||||
void sql_print_information(const char *format, ...);
|
||||
typedef void (*sql_print_message_func)(const char *format, ...);
|
||||
extern sql_print_message_func sql_print_message_handlers[];
|
||||
|
||||
/* type of the log table */
|
||||
#define QUERY_LOG_SLOW 1
|
||||
|
|
|
@ -864,8 +864,8 @@ static void close_connections(void)
|
|||
{
|
||||
DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
|
||||
tmp->thread_id));
|
||||
/* We skip slave threads on this first loop through. */
|
||||
if (tmp->slave_thread)
|
||||
/* We skip slave threads & scheduler on this first loop through. */
|
||||
if (tmp->slave_thread || tmp->system_thread == SYSTEM_THREAD_EVENT_SCHEDULER)
|
||||
continue;
|
||||
|
||||
tmp->killed= THD::KILL_CONNECTION;
|
||||
|
@ -884,6 +884,7 @@ static void close_connections(void)
|
|||
}
|
||||
(void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list
|
||||
|
||||
Events::shutdown();
|
||||
end_slave();
|
||||
|
||||
if (thread_count)
|
||||
|
@ -1299,6 +1300,7 @@ static void clean_up_mutexes()
|
|||
(void) pthread_mutex_destroy(&LOCK_bytes_sent);
|
||||
(void) pthread_mutex_destroy(&LOCK_bytes_received);
|
||||
(void) pthread_mutex_destroy(&LOCK_user_conn);
|
||||
Events::destroy_mutexes();
|
||||
#ifdef HAVE_OPENSSL
|
||||
(void) pthread_mutex_destroy(&LOCK_des_key_file);
|
||||
#ifndef HAVE_YASSL
|
||||
|
@ -2854,6 +2856,7 @@ static int init_thread_environment()
|
|||
(void) pthread_mutex_init(&LOCK_server_started, MY_MUTEX_INIT_FAST);
|
||||
(void) pthread_cond_init(&COND_server_started,NULL);
|
||||
sp_cache_init();
|
||||
Events::init_mutexes();
|
||||
/* Parameter for threads created for connections */
|
||||
(void) pthread_attr_init(&connection_attrib);
|
||||
(void) pthread_attr_setdetachstate(&connection_attrib,
|
||||
|
@ -2999,7 +3002,6 @@ static int init_server_components()
|
|||
#ifdef HAVE_REPLICATION
|
||||
init_slave_list();
|
||||
#endif
|
||||
init_events();
|
||||
|
||||
/* Setup logs */
|
||||
|
||||
|
@ -3573,6 +3575,7 @@ we force server id to 2, but this MySQL server will not act as a slave.");
|
|||
|
||||
if (!opt_noacl)
|
||||
{
|
||||
Events::init();
|
||||
plugin_load();
|
||||
#ifdef HAVE_DLOPEN
|
||||
udf_init();
|
||||
|
@ -3674,7 +3677,6 @@ we force server id to 2, but this MySQL server will not act as a slave.");
|
|||
clean_up(1);
|
||||
wait_for_signal_thread_to_end();
|
||||
clean_up_mutexes();
|
||||
shutdown_events();
|
||||
my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
|
||||
|
||||
exit(0);
|
||||
|
@ -4665,7 +4667,7 @@ enum options_mysqld
|
|||
OPT_MAX_BINLOG_DUMP_EVENTS, OPT_SPORADIC_BINLOG_DUMP_FAIL,
|
||||
OPT_SAFE_USER_CREATE, OPT_SQL_MODE,
|
||||
OPT_HAVE_NAMED_PIPE,
|
||||
OPT_DO_PSTACK, OPT_EVENT_EXECUTOR, OPT_REPORT_HOST,
|
||||
OPT_DO_PSTACK, OPT_EVENT_SCHEDULER, OPT_REPORT_HOST,
|
||||
OPT_REPORT_USER, OPT_REPORT_PASSWORD, OPT_REPORT_PORT,
|
||||
OPT_SHOW_SLAVE_AUTH_INFO,
|
||||
OPT_SLAVE_LOAD_TMPDIR, OPT_NO_MIX_TYPE,
|
||||
|
@ -4998,9 +5000,9 @@ Disable with --skip-bdb (will save memory).",
|
|||
(gptr*) &global_system_variables.engine_condition_pushdown,
|
||||
(gptr*) &global_system_variables.engine_condition_pushdown,
|
||||
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"event-scheduler", OPT_EVENT_EXECUTOR, "Enable/disable the event scheduler.",
|
||||
(gptr*) &opt_event_executor, (gptr*) &opt_event_executor, 0, GET_BOOL, NO_ARG,
|
||||
0/*default*/, 0/*min-value*/, 1/*max-value*/, 0, 0, 0},
|
||||
{"event-scheduler", OPT_EVENT_SCHEDULER, "Enable/disable the event scheduler.",
|
||||
(gptr*) &Events::opt_event_scheduler, (gptr*) &Events::opt_event_scheduler, 0, GET_STR,
|
||||
REQUIRED_ARG, 2/*default*/, 0/*min-value*/, 2/*max-value*/, 0, 0, 0},
|
||||
{"exit-info", 'T', "Used for debugging; Use at your own risk!", 0, 0, 0,
|
||||
GET_LONG, OPT_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"external-locking", OPT_USE_LOCKING, "Use system (external) locking. With this option enabled you can run myisamchk to test (not repair) tables while the MySQL server is running.",
|
||||
|
@ -7327,6 +7329,24 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
|||
break;
|
||||
}
|
||||
#endif
|
||||
case OPT_EVENT_SCHEDULER:
|
||||
if (!argument)
|
||||
Events::opt_event_scheduler= 2;
|
||||
else
|
||||
{
|
||||
int type;
|
||||
if ((type=find_type(argument, &Events::opt_typelib, 1)) <= 0)
|
||||
{
|
||||
fprintf(stderr,"Unknown option to event-scheduler: %s\n",argument);
|
||||
exit(1);
|
||||
}
|
||||
/*
|
||||
type= 1 2 3 4 5 6
|
||||
(OFF | 0) - (ON | 1) - (2 | SUSPEND)
|
||||
*/
|
||||
Events::opt_event_scheduler= (type-1) / 2;
|
||||
}
|
||||
break;
|
||||
case (int) OPT_SKIP_NEW:
|
||||
opt_specialflag|= SPECIAL_NO_NEW_FUNC;
|
||||
delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE;
|
||||
|
|
|
@ -61,12 +61,13 @@ static Slave_log_event* find_slave_event(IO_CACHE* log,
|
|||
static int init_failsafe_rpl_thread(THD* thd)
|
||||
{
|
||||
DBUG_ENTER("init_failsafe_rpl_thread");
|
||||
thd->system_thread = SYSTEM_THREAD_DELAYED_INSERT;
|
||||
/*
|
||||
thd->bootstrap is to report errors barely to stderr; if this code is
|
||||
enable again one day, one should check if bootstrap is still needed (maybe
|
||||
this thread has no other error reporting method).
|
||||
*/
|
||||
thd->system_thread = thd->bootstrap = 1;
|
||||
thd->bootstrap = 1;
|
||||
thd->security_ctx->skip_grants();
|
||||
my_net_init(&thd->net, 0);
|
||||
thd->net.read_timeout = slave_net_timeout;
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
#include <thr_alarm.h>
|
||||
#include <myisam.h>
|
||||
|
||||
#include "event_scheduler.h"
|
||||
|
||||
/* WITH_BERKELEY_STORAGE_ENGINE */
|
||||
extern bool berkeley_shared_data;
|
||||
extern ulong berkeley_max_lock, berkeley_log_buffer_size;
|
||||
|
@ -106,7 +108,6 @@ extern ulong ndb_report_thresh_binlog_mem_usage;
|
|||
|
||||
|
||||
|
||||
extern my_bool event_executor_running_global_var;
|
||||
|
||||
static HASH system_variable_hash;
|
||||
const char *bool_type_names[]= { "OFF", "ON", NullS };
|
||||
|
@ -225,9 +226,8 @@ sys_var_long_ptr sys_delayed_insert_timeout("delayed_insert_timeout",
|
|||
&delayed_insert_timeout);
|
||||
sys_var_long_ptr sys_delayed_queue_size("delayed_queue_size",
|
||||
&delayed_queue_size);
|
||||
sys_var_event_executor sys_event_executor("event_scheduler",
|
||||
(my_bool *)
|
||||
&event_executor_running_global_var);
|
||||
|
||||
sys_var_event_scheduler sys_event_scheduler("event_scheduler");
|
||||
sys_var_long_ptr sys_expire_logs_days("expire_logs_days",
|
||||
&expire_logs_days);
|
||||
sys_var_bool_ptr sys_flush("flush", &myisam_flush);
|
||||
|
@ -768,7 +768,7 @@ SHOW_VAR init_vars[]= {
|
|||
{sys_div_precincrement.name,(char*) &sys_div_precincrement,SHOW_SYS},
|
||||
{sys_engine_condition_pushdown.name,
|
||||
(char*) &sys_engine_condition_pushdown, SHOW_SYS},
|
||||
{sys_event_executor.name, (char*) &sys_event_executor, SHOW_SYS},
|
||||
{sys_event_scheduler.name, (char*) &sys_event_scheduler, SHOW_SYS},
|
||||
{sys_expire_logs_days.name, (char*) &sys_expire_logs_days, SHOW_SYS},
|
||||
{sys_flush.name, (char*) &sys_flush, SHOW_SYS},
|
||||
{sys_flush_time.name, (char*) &sys_flush_time, SHOW_SYS},
|
||||
|
@ -3632,6 +3632,69 @@ byte *sys_var_thd_dbug::value_ptr(THD *thd, enum_var_type type, LEX_STRING *b)
|
|||
return (byte*) thd->strdup(buf);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
The update method of the global variable event_scheduler.
|
||||
If event_scheduler is switched from 0 to 1 then the scheduler main
|
||||
thread is resumed and if from 1 to 0 the scheduler thread is suspended
|
||||
|
||||
SYNOPSIS
|
||||
sys_var_event_scheduler::update()
|
||||
thd Thread context (unused)
|
||||
var The new value
|
||||
|
||||
Returns
|
||||
FALSE OK
|
||||
TRUE Error
|
||||
*/
|
||||
|
||||
bool
|
||||
sys_var_event_scheduler::update(THD *thd, set_var *var)
|
||||
{
|
||||
enum Event_scheduler::enum_error_code res;
|
||||
Event_scheduler *scheduler= Event_scheduler::get_instance();
|
||||
/* here start the thread if not running. */
|
||||
DBUG_ENTER("sys_var_event_scheduler::update");
|
||||
|
||||
DBUG_PRINT("new_value", ("%lu", (bool)var->save_result.ulong_value));
|
||||
if (!scheduler->initialized())
|
||||
{
|
||||
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--event-scheduler=0");
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
if (var->save_result.ulonglong_value < 1 ||
|
||||
var->save_result.ulonglong_value > 2)
|
||||
{
|
||||
char buf[64];
|
||||
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "event_scheduler",
|
||||
llstr(var->save_result.ulonglong_value, buf));
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
if ((res= scheduler->suspend_or_resume(var->save_result.ulonglong_value == 1?
|
||||
Event_scheduler::RESUME :
|
||||
Event_scheduler::SUSPEND)))
|
||||
my_error(ER_EVENT_SET_VAR_ERROR, MYF(0), (uint) res);
|
||||
DBUG_RETURN((bool) res);
|
||||
}
|
||||
|
||||
|
||||
byte *sys_var_event_scheduler::value_ptr(THD *thd, enum_var_type type,
|
||||
LEX_STRING *base)
|
||||
{
|
||||
Event_scheduler *scheduler= Event_scheduler::get_instance();
|
||||
|
||||
if (!scheduler->initialized())
|
||||
thd->sys_var_tmp.long_value= 0;
|
||||
else if (scheduler->get_state() == Event_scheduler::RUNNING)
|
||||
thd->sys_var_tmp.long_value= 1;
|
||||
else
|
||||
thd->sys_var_tmp.long_value= 2;
|
||||
|
||||
return (byte*) &thd->sys_var_tmp;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Used templates
|
||||
****************************************************************************/
|
||||
|
|
|
@ -871,13 +871,14 @@ public:
|
|||
};
|
||||
|
||||
|
||||
class sys_var_event_executor :public sys_var_bool_ptr
|
||||
class sys_var_event_scheduler :public sys_var_long_ptr
|
||||
{
|
||||
/* We need a derived class only to have a warn_deprecated() */
|
||||
public:
|
||||
sys_var_event_executor(const char *name_arg, my_bool *value_arg) :
|
||||
sys_var_bool_ptr(name_arg, value_arg) {};
|
||||
sys_var_event_scheduler(const char *name_arg) :
|
||||
sys_var_long_ptr(name_arg, NULL, NULL) {};
|
||||
bool update(THD *thd, set_var *var);
|
||||
byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
|
||||
};
|
||||
|
||||
extern void fix_binlog_format_after_update(THD *thd, enum_var_type type);
|
||||
|
|
|
@ -5042,7 +5042,7 @@ ER_OPTION_PREVENTS_STATEMENT
|
|||
ger "Der MySQL-Server läuft mit der Option %s und kann diese Anweisung deswegen nicht ausführen"
|
||||
por "O servidor MySQL está rodando com a opção %s razão pela qual não pode executar esse commando"
|
||||
spa "El servidor MySQL está rodando con la opción %s tal que no puede ejecutar este comando"
|
||||
swe "MySQL är startad med --skip-grant-tables. Pga av detta kan du inte använda detta kommando"
|
||||
swe "MySQL är startad med %s. Pga av detta kan du inte använda detta kommando"
|
||||
ER_DUPLICATED_VALUE_IN_TYPE
|
||||
eng "Column '%-.100s' has duplicated value '%-.64s' in %s"
|
||||
ger "Feld '%-.100s' hat doppelten Wert '%-.64s' in %s"
|
||||
|
@ -5842,3 +5842,7 @@ ER_WRONG_PARTITION_NAME
|
|||
swe "Felaktigt partitionsnamn"
|
||||
ER_CANT_CHANGE_TX_ISOLATION 25001
|
||||
eng "Transaction isolation level can't be changed while a transaction is in progress"
|
||||
ER_EVENT_MODIFY_QUEUE_ERROR
|
||||
eng "Internal scheduler error %d"
|
||||
ER_EVENT_SET_VAR_ERROR
|
||||
eng "Error during starting/stopping of the scheduler. Error code %u"
|
||||
|
|
|
@ -253,7 +253,8 @@ THD::THD()
|
|||
net.last_error[0]=0; // If error on boot
|
||||
net.query_cache_query=0; // If error on boot
|
||||
ull=0;
|
||||
system_thread= cleanup_done= abort_on_warning= no_warnings_for_error= 0;
|
||||
system_thread= NON_SYSTEM_THREAD;
|
||||
cleanup_done= abort_on_warning= no_warnings_for_error= 0;
|
||||
peer_port= 0; // For SHOW PROCESSLIST
|
||||
#ifdef HAVE_ROW_BASED_REPLICATION
|
||||
transaction.m_pending_rows_event= 0;
|
||||
|
@ -512,6 +513,8 @@ void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var)
|
|||
|
||||
void THD::awake(THD::killed_state state_to_set)
|
||||
{
|
||||
DBUG_ENTER("THD::awake");
|
||||
DBUG_PRINT("enter", ("this=0x%lx", this));
|
||||
THD_CHECK_SENTRY(this);
|
||||
safe_mutex_assert_owner(&LOCK_delete);
|
||||
|
||||
|
@ -555,6 +558,7 @@ void THD::awake(THD::killed_state state_to_set)
|
|||
}
|
||||
pthread_mutex_unlock(&mysys_var->mutex);
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2031,6 +2035,13 @@ void Security_context::skip_grants()
|
|||
}
|
||||
|
||||
|
||||
bool Security_context::set_user(char *user_arg)
|
||||
{
|
||||
safeFree(user);
|
||||
user= my_strdup(user_arg, MYF(0));
|
||||
return user == 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Handling of open and locked tables states.
|
||||
|
||||
|
|
|
@ -629,6 +629,8 @@ public:
|
|||
{
|
||||
return (*priv_host ? priv_host : (char *)"%");
|
||||
}
|
||||
|
||||
bool set_user(char *user_arg);
|
||||
};
|
||||
|
||||
|
||||
|
@ -770,6 +772,19 @@ public:
|
|||
};
|
||||
|
||||
|
||||
/* Flags for the THD::system_thread variable */
|
||||
enum enum_thread_type
|
||||
{
|
||||
NON_SYSTEM_THREAD= 0,
|
||||
SYSTEM_THREAD_DELAYED_INSERT= 1,
|
||||
SYSTEM_THREAD_SLAVE_IO= 2,
|
||||
SYSTEM_THREAD_SLAVE_SQL= 4,
|
||||
SYSTEM_THREAD_NDBCLUSTER_BINLOG= 8,
|
||||
SYSTEM_THREAD_EVENT_SCHEDULER= 16,
|
||||
SYSTEM_THREAD_EVENT_WORKER= 32
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
For each client connection we create a separate thread with THD serving as
|
||||
a thread/connection descriptor
|
||||
|
@ -1103,7 +1118,8 @@ public:
|
|||
long dbug_thread_id;
|
||||
pthread_t real_id;
|
||||
uint tmp_table, global_read_lock;
|
||||
uint server_status,open_options,system_thread;
|
||||
uint server_status,open_options;
|
||||
enum enum_thread_type system_thread;
|
||||
uint32 db_length;
|
||||
uint select_number; //number of select (used for EXPLAIN)
|
||||
/* variables.transaction_isolation is reset to this after each commit */
|
||||
|
@ -1404,11 +1420,6 @@ public:
|
|||
|
||||
#define reenable_binlog(A) (A)->options= tmp_disable_binlog__save_options;}
|
||||
|
||||
/* Flags for the THD::system_thread (bitmap) variable */
|
||||
#define SYSTEM_THREAD_DELAYED_INSERT 1
|
||||
#define SYSTEM_THREAD_SLAVE_IO 2
|
||||
#define SYSTEM_THREAD_SLAVE_SQL 4
|
||||
#define SYSTEM_THREAD_NDBCLUSTER_BINLOG 8
|
||||
|
||||
/*
|
||||
Used to hold information about file and file structure in exchainge
|
||||
|
|
|
@ -871,7 +871,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
|
|||
|
||||
exit:
|
||||
(void)sp_drop_db_routines(thd, db); /* QQ Ignore errors for now */
|
||||
(void)evex_drop_db_events(thd, db); /* QQ Ignore errors for now */
|
||||
error= Events::drop_schema_events(thd, db);
|
||||
start_waiting_global_read_lock(thd);
|
||||
/*
|
||||
If this database was the client's selected database, we silently change the
|
||||
|
|
|
@ -40,3 +40,5 @@ void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level,
|
|||
uint code, const char *format, ...);
|
||||
void mysql_reset_errors(THD *thd, bool force);
|
||||
bool mysqld_show_warnings(THD *thd, ulong levels_to_show);
|
||||
|
||||
extern LEX_STRING warning_level_names[];
|
||||
|
|
|
@ -111,7 +111,8 @@ enum enum_sql_command {
|
|||
SQLCOM_SHOW_AUTHORS, SQLCOM_BINLOG_BASE64_EVENT,
|
||||
SQLCOM_SHOW_PLUGINS,
|
||||
SQLCOM_CREATE_EVENT, SQLCOM_ALTER_EVENT, SQLCOM_DROP_EVENT,
|
||||
SQLCOM_SHOW_CREATE_EVENT, SQLCOM_SHOW_EVENTS,
|
||||
SQLCOM_SHOW_CREATE_EVENT, SQLCOM_SHOW_EVENTS,
|
||||
SQLCOM_SHOW_SCHEDULER_STATUS,
|
||||
|
||||
/* This should be the last !!! */
|
||||
|
||||
|
|
|
@ -2049,7 +2049,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||
{
|
||||
statistic_increment(thd->status_var.com_stat[SQLCOM_KILL], &LOCK_status);
|
||||
ulong id=(ulong) uint4korr(packet);
|
||||
kill_one_thread(thd,id,false);
|
||||
sql_kill(thd,id,false);
|
||||
break;
|
||||
}
|
||||
case COM_SET_OPTION:
|
||||
|
@ -3836,14 +3836,17 @@ end_with_restore_list:
|
|||
|
||||
switch (lex->sql_command) {
|
||||
case SQLCOM_CREATE_EVENT:
|
||||
res= evex_create_event(thd, lex->et, (uint) lex->create_info.options,
|
||||
&rows_affected);
|
||||
res= Events::create_event(thd, lex->et,
|
||||
(uint) lex->create_info.options,
|
||||
&rows_affected);
|
||||
break;
|
||||
case SQLCOM_ALTER_EVENT:
|
||||
res= evex_update_event(thd, lex->et, lex->spname, &rows_affected);
|
||||
res= Events::update_event(thd, lex->et, lex->spname,
|
||||
&rows_affected);
|
||||
break;
|
||||
case SQLCOM_DROP_EVENT:
|
||||
res= evex_drop_event(thd, lex->et, lex->drop_if_exists, &rows_affected);
|
||||
res= Events::drop_event(thd, lex->et, lex->drop_if_exists,
|
||||
&rows_affected);
|
||||
default:;
|
||||
}
|
||||
DBUG_PRINT("info", ("CREATE/ALTER/DROP returned error code=%d af_rows=%d",
|
||||
|
@ -3881,9 +3884,16 @@ end_with_restore_list:
|
|||
my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str);
|
||||
goto error;
|
||||
}
|
||||
res= evex_show_create_event(thd, lex->spname, lex->et->definer);
|
||||
res= Events::show_create_event(thd, lex->spname, lex->et->definer);
|
||||
break;
|
||||
}
|
||||
#ifndef DBUG_OFF
|
||||
case SQLCOM_SHOW_SCHEDULER_STATUS:
|
||||
{
|
||||
res= Events::dump_internal_status(thd);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case SQLCOM_CREATE_FUNCTION: // UDF function
|
||||
{
|
||||
if (check_access(thd,INSERT_ACL,"mysql",0,1,0,0))
|
||||
|
@ -4123,7 +4133,7 @@ end_with_restore_list:
|
|||
MYF(0));
|
||||
goto error;
|
||||
}
|
||||
kill_one_thread(thd, (ulong)it->val_int(), lex->type & ONLY_KILL_QUERY);
|
||||
sql_kill(thd, (ulong)it->val_int(), lex->type & ONLY_KILL_QUERY);
|
||||
break;
|
||||
}
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
|
@ -6917,22 +6927,26 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
kill on thread
|
||||
kills a thread
|
||||
|
||||
SYNOPSIS
|
||||
kill_one_thread()
|
||||
thd Thread class
|
||||
id Thread id
|
||||
only_kill_query Should it kill the query or the connection
|
||||
|
||||
NOTES
|
||||
This is written such that we have a short lock on LOCK_thread_count
|
||||
*/
|
||||
|
||||
void kill_one_thread(THD *thd, ulong id, bool only_kill_query)
|
||||
uint kill_one_thread(THD *thd, ulong id, bool only_kill_query)
|
||||
{
|
||||
THD *tmp;
|
||||
uint error=ER_NO_SUCH_THREAD;
|
||||
DBUG_ENTER("kill_one_thread");
|
||||
DBUG_PRINT("enter", ("id=%lu only_kill=%d", id, only_kill_query));
|
||||
VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
|
||||
I_List_iterator<THD> it(threads);
|
||||
while ((tmp=it++))
|
||||
|
@ -6958,8 +6972,25 @@ void kill_one_thread(THD *thd, ulong id, bool only_kill_query)
|
|||
error=ER_KILL_DENIED_ERROR;
|
||||
pthread_mutex_unlock(&tmp->LOCK_delete);
|
||||
}
|
||||
DBUG_PRINT("exit", ("%d", error));
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
if (!error)
|
||||
|
||||
/*
|
||||
kills a thread and sends response
|
||||
|
||||
SYNOPSIS
|
||||
sql_kill()
|
||||
thd Thread class
|
||||
id Thread id
|
||||
only_kill_query Should it kill the query or the connection
|
||||
*/
|
||||
|
||||
void sql_kill(THD *thd, ulong id, bool only_kill_query)
|
||||
{
|
||||
uint error;
|
||||
if (!(error= kill_one_thread(thd, id, only_kill_query)))
|
||||
send_ok(thd);
|
||||
else
|
||||
my_error(error, MYF(0), id);
|
||||
|
|
|
@ -4063,8 +4063,9 @@ fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
|
|||
/* type */
|
||||
sch_table->field[5]->store(STRING_WITH_LEN("RECURRING"), scs);
|
||||
|
||||
if (event_reconstruct_interval_expression(&show_str, et.interval,
|
||||
et.expression))
|
||||
if (Events::reconstruct_interval_expression(&show_str,
|
||||
et.interval,
|
||||
et.expression))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
sch_table->field[7]->set_notnull();
|
||||
|
@ -4094,13 +4095,13 @@ fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
|
|||
}
|
||||
|
||||
//status
|
||||
if (et.status == MYSQL_EVENT_ENABLED)
|
||||
if (et.status == Event_timed::ENABLED)
|
||||
sch_table->field[12]->store(STRING_WITH_LEN("ENABLED"), scs);
|
||||
else
|
||||
sch_table->field[12]->store(STRING_WITH_LEN("DISABLED"), scs);
|
||||
|
||||
//on_completion
|
||||
if (et.on_completion == MYSQL_EVENT_ON_COMPLETION_DROP)
|
||||
if (et.on_completion == Event_timed::ON_COMPLETION_DROP)
|
||||
sch_table->field[13]->store(STRING_WITH_LEN("NOT PRESERVE"), scs);
|
||||
else
|
||||
sch_table->field[13]->store(STRING_WITH_LEN("PRESERVE"), scs);
|
||||
|
@ -4152,7 +4153,7 @@ int fill_schema_events(THD *thd, TABLE_LIST *tables, COND *cond)
|
|||
|
||||
thd->reset_n_backup_open_tables_state(&backup);
|
||||
|
||||
if ((ret= evex_open_event_table(thd, TL_READ, &event_table)))
|
||||
if ((ret= Events::open_event_table(thd, TL_READ, &event_table)))
|
||||
{
|
||||
sql_print_error("Table mysql.event is damaged.");
|
||||
ret= 1;
|
||||
|
@ -4161,13 +4162,10 @@ int fill_schema_events(THD *thd, TABLE_LIST *tables, COND *cond)
|
|||
|
||||
event_table->file->ha_index_init(0, 1);
|
||||
|
||||
/*
|
||||
see others' events only if you have PROCESS_ACL !!
|
||||
thd->lex->verbose is set either if SHOW FULL EVENTS or
|
||||
in case of SELECT FROM I_S.EVENTS
|
||||
*/
|
||||
verbose= (thd->lex->verbose
|
||||
&& (thd->security_ctx->master_access & PROCESS_ACL));
|
||||
/* see others' events only if you have PROCESS_ACL !! */
|
||||
verbose= ((thd->lex->verbose ||
|
||||
thd->lex->orig_sql_command != SQLCOM_SHOW_EVENTS) &&
|
||||
(thd->security_ctx->master_access & PROCESS_ACL));
|
||||
|
||||
if (verbose && thd->security_ctx->user)
|
||||
{
|
||||
|
@ -4176,12 +4174,13 @@ int fill_schema_events(THD *thd, TABLE_LIST *tables, COND *cond)
|
|||
}
|
||||
else
|
||||
{
|
||||
event_table->field[EVEX_FIELD_DEFINER]->store(definer, strlen(definer), scs);
|
||||
event_table->field[Events::FIELD_DEFINER]->
|
||||
store(definer, strlen(definer), scs);
|
||||
key_len= event_table->key_info->key_part[0].store_length;
|
||||
|
||||
if (thd->lex->select_lex.db)
|
||||
{
|
||||
event_table->field[EVEX_FIELD_DB]->
|
||||
event_table->field[Events::FIELD_DB]->
|
||||
store(thd->lex->select_lex.db, strlen(thd->lex->select_lex.db), scs);
|
||||
key_len+= event_table->key_info->key_part[1].store_length;
|
||||
}
|
||||
|
|
|
@ -568,6 +568,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
|||
%token RTREE_SYM
|
||||
%token SAVEPOINT_SYM
|
||||
%token SCHEDULE_SYM
|
||||
%token SCHEDULER_SYM
|
||||
%token SECOND_MICROSECOND_SYM
|
||||
%token SECOND_SYM
|
||||
%token SECURITY_SYM
|
||||
|
@ -1401,7 +1402,7 @@ opt_ev_status: /* empty */ { $$= 0; }
|
|||
{
|
||||
LEX *lex=Lex;
|
||||
if (!lex->et_compile_phase)
|
||||
lex->et->status= MYSQL_EVENT_ENABLED;
|
||||
lex->et->status= Event_timed::ENABLED;
|
||||
$$= 1;
|
||||
}
|
||||
| DISABLE_SYM
|
||||
|
@ -1409,7 +1410,7 @@ opt_ev_status: /* empty */ { $$= 0; }
|
|||
LEX *lex=Lex;
|
||||
|
||||
if (!lex->et_compile_phase)
|
||||
lex->et->status= MYSQL_EVENT_DISABLED;
|
||||
lex->et->status= Event_timed::DISABLED;
|
||||
$$= 1;
|
||||
}
|
||||
;
|
||||
|
@ -1473,14 +1474,14 @@ ev_on_completion:
|
|||
{
|
||||
LEX *lex=Lex;
|
||||
if (!lex->et_compile_phase)
|
||||
lex->et->on_completion= MYSQL_EVENT_ON_COMPLETION_PRESERVE;
|
||||
lex->et->on_completion= Event_timed::ON_COMPLETION_PRESERVE;
|
||||
$$= 1;
|
||||
}
|
||||
| ON COMPLETION_SYM NOT_SYM PRESERVE_SYM
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
if (!lex->et_compile_phase)
|
||||
lex->et->on_completion= MYSQL_EVENT_ON_COMPLETION_DROP;
|
||||
lex->et->on_completion= Event_timed::ON_COMPLETION_DROP;
|
||||
$$= 1;
|
||||
}
|
||||
;
|
||||
|
@ -8067,15 +8068,24 @@ show_param:
|
|||
if (prepare_schema_table(YYTHD, lex, 0, SCH_TRIGGERS))
|
||||
YYABORT;
|
||||
}
|
||||
| opt_full EVENTS_SYM opt_db wild_and_where
|
||||
| EVENTS_SYM opt_db wild_and_where
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
lex->sql_command= SQLCOM_SELECT;
|
||||
lex->orig_sql_command= SQLCOM_SHOW_EVENTS;
|
||||
lex->select_lex.db= $3;
|
||||
lex->select_lex.db= $2;
|
||||
if (prepare_schema_table(YYTHD, lex, 0, SCH_EVENTS))
|
||||
YYABORT;
|
||||
}
|
||||
| SCHEDULER_SYM STATUS_SYM
|
||||
{
|
||||
#ifndef DBUG_OFF
|
||||
Lex->sql_command= SQLCOM_SHOW_SCHEDULER_STATUS;
|
||||
#else
|
||||
yyerror(ER(ER_SYNTAX_ERROR));
|
||||
YYABORT;
|
||||
#endif
|
||||
}
|
||||
| TABLE_SYM STATUS_SYM opt_db wild_and_where
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
|
@ -9512,6 +9522,7 @@ keyword_sp:
|
|||
| ROW_SYM {}
|
||||
| RTREE_SYM {}
|
||||
| SCHEDULE_SYM {}
|
||||
| SCHEDULER_SYM {}
|
||||
| SECOND_SYM {}
|
||||
| SERIAL_SYM {}
|
||||
| SERIALIZABLE_SYM {}
|
||||
|
|
|
@ -2401,9 +2401,7 @@ table_check_intact(TABLE *table, uint table_f_count,
|
|||
table running on a old server will be valid.
|
||||
*/
|
||||
field->sql_type(sql_type);
|
||||
if (sql_type.length() < table_def->type.length - 1 ||
|
||||
strncmp(sql_type.ptr(),
|
||||
table_def->type.str,
|
||||
if (strncmp(sql_type.c_ptr_safe(), table_def->type.str,
|
||||
table_def->type.length - 1))
|
||||
{
|
||||
sql_print_error("(%s) Expected field %s at position %d to have type "
|
||||
|
|
|
@ -849,16 +849,6 @@ extern "C" {
|
|||
enum ndb_mgm_event_category category,
|
||||
int level,
|
||||
struct ndb_mgm_reply* reply);
|
||||
|
||||
/**
|
||||
* Returns the port number where statistics information is sent
|
||||
*
|
||||
* @param handle NDB management handle.
|
||||
* @param reply Reply message.
|
||||
* @return -1 on error.
|
||||
*/
|
||||
int ndb_mgm_get_stat_port(NdbMgmHandle handle,
|
||||
struct ndb_mgm_reply* reply);
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
|
@ -48,58 +48,66 @@ read_socket(NDB_SOCKET_TYPE socket, int timeout_millis,
|
|||
|
||||
extern "C"
|
||||
int
|
||||
readln_socket(NDB_SOCKET_TYPE socket, int timeout_millis,
|
||||
readln_socket(NDB_SOCKET_TYPE socket, int timeout_millis,
|
||||
char * buf, int buflen){
|
||||
if(buflen <= 1)
|
||||
return 0;
|
||||
|
||||
int sock_flags= fcntl(socket, F_GETFL);
|
||||
if(fcntl(socket, F_SETFL, sock_flags | O_NONBLOCK) == -1)
|
||||
return -1;
|
||||
|
||||
fd_set readset;
|
||||
FD_ZERO(&readset);
|
||||
FD_SET(socket, &readset);
|
||||
|
||||
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = (timeout_millis / 1000);
|
||||
timeout.tv_usec = (timeout_millis % 1000) * 1000;
|
||||
|
||||
const int selectRes = select(socket + 1, &readset, 0, 0, &timeout);
|
||||
if(selectRes == 0)
|
||||
if(selectRes == 0){
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
if(selectRes == -1){
|
||||
fcntl(socket, F_SETFL, sock_flags);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int pos = 0; buf[pos] = 0;
|
||||
while(true){
|
||||
const int t = recv(socket, &buf[pos], 1, 0);
|
||||
if(t != 1){
|
||||
return -1;
|
||||
}
|
||||
if(buf[pos] == '\n'){
|
||||
buf[pos] = 0;
|
||||
|
||||
if(pos > 0 && buf[pos-1] == '\r'){
|
||||
pos--;
|
||||
buf[pos] = 0;
|
||||
buf[0] = 0;
|
||||
const int t = recv(socket, buf, buflen, MSG_PEEK);
|
||||
|
||||
if(t < 1)
|
||||
{
|
||||
fcntl(socket, F_SETFL, sock_flags);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(int i=0; i< t;i++)
|
||||
{
|
||||
if(buf[i] == '\n'){
|
||||
recv(socket, buf, i+1, 0);
|
||||
buf[i] = 0;
|
||||
|
||||
if(i > 0 && buf[i-1] == '\r'){
|
||||
i--;
|
||||
buf[i] = 0;
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
pos++;
|
||||
if(pos == (buflen - 1)){
|
||||
buf[pos] = 0;
|
||||
return buflen;
|
||||
}
|
||||
|
||||
FD_ZERO(&readset);
|
||||
FD_SET(socket, &readset);
|
||||
timeout.tv_sec = (timeout_millis / 1000);
|
||||
timeout.tv_usec = (timeout_millis % 1000) * 1000;
|
||||
const int selectRes = select(socket + 1, &readset, 0, 0, &timeout);
|
||||
if(selectRes != 1){
|
||||
return -1;
|
||||
fcntl(socket, F_SETFL, sock_flags);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
if(t == (buflen - 1)){
|
||||
recv(socket, buf, t, 0);
|
||||
buf[t] = 0;
|
||||
fcntl(socket, F_SETFL, sock_flags);
|
||||
return buflen;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
|
|
|
@ -827,7 +827,7 @@ void Qmgr::execCM_REGCONF(Signal* signal)
|
|||
ptrCheckGuard(myNodePtr, MAX_NDB_NODES, nodeRec);
|
||||
|
||||
ndbrequire(c_start.m_gsn == GSN_CM_REGREQ);
|
||||
ndbrequire(myNodePtr.p->phase = ZSTARTING);
|
||||
ndbrequire(myNodePtr.p->phase == ZSTARTING);
|
||||
|
||||
cpdistref = cmRegConf->presidentBlockRef;
|
||||
cpresident = cmRegConf->presidentNodeId;
|
||||
|
|
|
@ -49,7 +49,9 @@ extern EventLogger g_eventLogger;
|
|||
enum ndbd_options {
|
||||
OPT_INITIAL = NDB_STD_OPTIONS_LAST,
|
||||
OPT_NODAEMON,
|
||||
OPT_FOREGROUND
|
||||
OPT_FOREGROUND,
|
||||
OPT_NOWAIT_NODES,
|
||||
OPT_INITIAL_START
|
||||
};
|
||||
|
||||
NDB_STD_OPTS_VARS;
|
||||
|
@ -88,11 +90,11 @@ static struct my_option my_long_options[] =
|
|||
" (implies --nodaemon)",
|
||||
(gptr*) &_foreground, (gptr*) &_foreground, 0,
|
||||
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
|
||||
{ "nowait-nodes", NO_ARG,
|
||||
{ "nowait-nodes", OPT_NOWAIT_NODES,
|
||||
"Nodes that will not be waited for during start",
|
||||
(gptr*) &_nowait_nodes, (gptr*) &_nowait_nodes, 0,
|
||||
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
|
||||
{ "initial-start", NO_ARG,
|
||||
{ "initial-start", OPT_INITIAL_START,
|
||||
"Perform initial start",
|
||||
(gptr*) &_initialstart, (gptr*) &_initialstart, 0,
|
||||
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
|
||||
|
|
|
@ -1306,33 +1306,6 @@ ndb_mgm_listen_event(NdbMgmHandle handle, const int filter[])
|
|||
return ndb_mgm_listen_event_internal(handle,filter,0);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
int
|
||||
ndb_mgm_get_stat_port(NdbMgmHandle handle, struct ndb_mgm_reply* /*reply*/)
|
||||
{
|
||||
SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_stat_port");
|
||||
const ParserRow<ParserDummy> stat_reply[] = {
|
||||
MGM_CMD("error", NULL, ""),
|
||||
MGM_ARG("result", String, Mandatory, "Error message"),
|
||||
MGM_CMD("get statport reply", NULL, ""),
|
||||
MGM_ARG("tcpport", Int, Mandatory, "TCP port for statistics"),
|
||||
MGM_END()
|
||||
};
|
||||
CHECK_HANDLE(handle, -1);
|
||||
CHECK_CONNECTED(handle, -1);
|
||||
|
||||
Properties args;
|
||||
const Properties *reply;
|
||||
reply = ndb_mgm_call(handle, stat_reply, "get statport", &args);
|
||||
CHECK_REPLY(reply, -1);
|
||||
|
||||
Uint32 port;
|
||||
reply->get("tcpport", &port);
|
||||
|
||||
delete reply;
|
||||
return port;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
int
|
||||
ndb_mgm_dump_state(NdbMgmHandle handle, int nodeId, int* _args,
|
||||
|
|
|
@ -121,8 +121,6 @@ static const unsigned int MAX_WRITE_TIMEOUT = 100 ;
|
|||
|
||||
const
|
||||
ParserRow<MgmApiSession> commands[] = {
|
||||
MGM_CMD("get statport", &MgmApiSession::getStatPort, ""),
|
||||
|
||||
MGM_CMD("get config", &MgmApiSession::getConfig, ""),
|
||||
MGM_ARG("version", Int, Mandatory, "Configuration version number"),
|
||||
MGM_ARG("node", Int, Optional, "Node ID"),
|
||||
|
@ -649,15 +647,6 @@ MgmApiSession::getConfig_common(Parser_t::Context &,
|
|||
return;
|
||||
}
|
||||
|
||||
void
|
||||
MgmApiSession::getStatPort(Parser_t::Context &,
|
||||
const class Properties &) {
|
||||
|
||||
m_output->println("get statport reply");
|
||||
m_output->println("tcpport: %d", 0);
|
||||
m_output->println("");
|
||||
}
|
||||
|
||||
void
|
||||
MgmApiSession::insertError(Parser<MgmApiSession>::Context &,
|
||||
Properties const &args) {
|
||||
|
|
|
@ -53,7 +53,6 @@ public:
|
|||
virtual ~MgmApiSession();
|
||||
void runSession();
|
||||
|
||||
void getStatPort(Parser_t::Context &ctx, const class Properties &args);
|
||||
void getConfig(Parser_t::Context &ctx, const class Properties &args);
|
||||
#ifdef MGM_GET_CONFIG_BACKWARDS_COMPAT
|
||||
void getConfig_old(Parser_t::Context &ctx);
|
||||
|
|
Loading…
Reference in a new issue