1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

Merge bk-internal.mysql.com:/data0/bk/mysql-5.1-new

into  bk-internal.mysql.com:/data0/bk/mysql-5.1-kt


include/m_string.h:
  Auto merged
include/my_sys.h:
  Auto merged
mysql-test/mysql-test-run.pl:
  Auto merged
sql/log.cc:
  Auto merged
sql/mysqld.cc:
  Auto merged
sql/set_var.cc:
  Auto merged
sql/sql_class.cc:
  Auto merged
sql/sql_class.h:
  Auto merged
sql/sql_parse.cc:
  Auto merged
sql/share/errmsg.txt:
  C
  Merged.
  ?
This commit is contained in:
unknown
2006-05-23 20:28:52 +02:00
156 changed files with 10575 additions and 4501 deletions

View File

@@ -1770,3 +1770,4 @@ vio/viotest-sslconnect.cpp
vio/viotest.cpp vio/viotest.cpp
zlib/*.ds? zlib/*.ds?
zlib/*.vcproj zlib/*.vcproj
libmysqld/event_scheduler.cc

View File

@@ -64,7 +64,7 @@
/* were just going to fake it here and get input from /* were just going to fake it here and get input from
the keyboard */ the keyboard */
char *get_tty_password(char *opt_message) char *get_tty_password(const char *opt_message)
{ {
char to[80]; char to[80];
char *pos=to,*end=to+sizeof(to)-1; char *pos=to,*end=to+sizeof(to)-1;
@@ -150,7 +150,7 @@ static void get_password(char *to,uint length,int fd,bool echo)
#endif /* ! HAVE_GETPASS */ #endif /* ! HAVE_GETPASS */
char *get_tty_password(char *opt_message) char *get_tty_password(const char *opt_message)
{ {
#ifdef HAVE_GETPASS #ifdef HAVE_GETPASS
char *passbuff; char *passbuff;

View File

@@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc)
AC_CANONICAL_SYSTEM AC_CANONICAL_SYSTEM
# The Docs Makefile.am parses this line! # The Docs Makefile.am parses this line!
# remember to also change ndb version below and update version.c in ndb # 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) AM_CONFIG_HEADER(config.h)
PROTOCOL_VERSION=10 PROTOCOL_VERSION=10

View File

@@ -65,7 +65,8 @@ THREAD_RETURN YASSL_API echoserver_test(void* args)
while (!shutdown) { while (!shutdown) {
sockaddr_in client; sockaddr_in client;
socklen_t client_len = sizeof(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"); if (clientfd == -1) err_sys("tcp accept failed");
SSL* ssl = SSL_new(ctx); SSL* ssl = SSL_new(ctx);

View File

@@ -273,6 +273,7 @@ int SSL_pending(SSL*);
enum { /* ssl Constants */ enum { /* ssl Constants */
SSL_WOULD_BLOCK = -8,
SSL_BAD_STAT = -7, SSL_BAD_STAT = -7,
SSL_BAD_PATH = -6, SSL_BAD_PATH = -6,
SSL_BAD_FILETYPE = -5, SSL_BAD_FILETYPE = -5,
@@ -494,7 +495,7 @@ ASN1_TIME* X509_get_notAfter(X509* x);
typedef struct MD4_CTX { typedef struct MD4_CTX {
void* ptr; int buffer[32]; /* big enough to hold, check size in Init */
} MD4_CTX; } MD4_CTX;
void MD4_Init(MD4_CTX*); void MD4_Init(MD4_CTX*);

View File

@@ -66,6 +66,7 @@ typedef unsigned char byte;
// Wraps Windows Sockets and BSD Sockets // Wraps Windows Sockets and BSD Sockets
class Socket { class Socket {
socket_t socket_; // underlying socket descriptor socket_t socket_; // underlying socket descriptor
bool wouldBlock_; // for non-blocking data
public: public:
explicit Socket(socket_t s = INVALID_SOCKET); explicit Socket(socket_t s = INVALID_SOCKET);
~Socket(); ~Socket();
@@ -75,9 +76,10 @@ public:
socket_t get_fd() const; socket_t get_fd() const;
uint send(const byte* buf, unsigned int len, int flags = 0) 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 closeSocket();
void shutDown(int how = SD_SEND); void shutDown(int how = SD_SEND);

View File

@@ -46,8 +46,10 @@ public:
// for compiler generated call, never used // for compiler generated call, never used
static void operator delete(void*) { assert(0); } static void operator delete(void*) { assert(0); }
private: private:
#if defined(__hpux)
// don't allow dynamic creation of exceptions // don't allow dynamic creation of exceptions
static void* operator new(size_t); static void* operator new(size_t);
#endif
}; };

View File

@@ -656,7 +656,7 @@ mySTL::auto_ptr<input_buffer>
DoProcessReply(SSL& ssl, mySTL::auto_ptr<input_buffer> buffered) DoProcessReply(SSL& ssl, mySTL::auto_ptr<input_buffer> buffered)
{ {
// wait for input if blocking // wait for input if blocking
if (!ssl.getSocket().wait()) { if (!ssl.useSocket().wait()) {
ssl.SetError(receive_error); ssl.SetError(receive_error);
buffered.reset(0); buffered.reset(0);
return buffered; return buffered;
@@ -673,7 +673,7 @@ DoProcessReply(SSL& ssl, mySTL::auto_ptr<input_buffer> buffered)
} }
// add new data // 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); buffer.add_size(read);
uint offset = 0; uint offset = 0;
const MessageFactory& mf = ssl.getFactory().getMessage(); const MessageFactory& mf = ssl.getFactory().getMessage();
@@ -858,6 +858,9 @@ void sendFinished(SSL& ssl, ConnectionEnd side, BufferOutput buffer)
// send data // send data
int sendData(SSL& ssl, const void* buffer, int sz) int sendData(SSL& ssl, const void* buffer, int sz)
{ {
if (ssl.GetError() == YasslError(SSL_ERROR_WANT_READ))
ssl.SetError(no_error);
ssl.verfiyHandShakeComplete(); ssl.verfiyHandShakeComplete();
if (ssl.GetError()) return 0; if (ssl.GetError()) return 0;
int sent = 0; int sent = 0;
@@ -893,6 +896,9 @@ int sendAlert(SSL& ssl, const Alert& alert)
// process input data // process input data
int receiveData(SSL& ssl, Data& data) int receiveData(SSL& ssl, Data& data)
{ {
if (ssl.GetError() == YasslError(SSL_ERROR_WANT_READ))
ssl.SetError(no_error);
ssl.verfiyHandShakeComplete(); ssl.verfiyHandShakeComplete();
if (ssl.GetError()) return 0; if (ssl.GetError()) return 0;
@@ -902,6 +908,11 @@ int receiveData(SSL& ssl, Data& data)
ssl.useLog().ShowData(data.get_length()); ssl.useLog().ShowData(data.get_length());
if (ssl.GetError()) return 0; 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(); return data.get_length();
} }

View File

@@ -58,7 +58,7 @@ namespace yaSSL {
Socket::Socket(socket_t s) 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); assert(socket_ != INVALID_SOCKET);
wouldBlock_ = false;
int recvd = ::recv(socket_, reinterpret_cast<char *>(buf), sz, flags); int recvd = ::recv(socket_, reinterpret_cast<char *>(buf), sz, flags);
// idea to seperate error from would block by arnetheduck@gmail.com // idea to seperate error from would block by arnetheduck@gmail.com
if (recvd == -1) { if (recvd == -1) {
if (get_lastError() == SOCKET_EWOULDBLOCK || if (get_lastError() == SOCKET_EWOULDBLOCK ||
get_lastError() == SOCKET_EAGAIN) get_lastError() == SOCKET_EAGAIN) {
wouldBlock_ = true;
return 0; return 0;
} }
}
else if (recvd == 0) else if (recvd == 0)
return static_cast<uint>(-1); 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 // wait if blocking for input, return false for error
bool Socket::wait() const bool Socket::wait()
{ {
byte b; byte b;
return receive(&b, 1, MSG_PEEK) != static_cast<uint>(-1); 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) void Socket::set_lastError(int errorCode)
{ {
#ifdef _WIN32 #ifdef _WIN32

View File

@@ -37,6 +37,7 @@
#include "handshake.hpp" #include "handshake.hpp"
#include "yassl_int.hpp" #include "yassl_int.hpp"
#include "md5.hpp" // for TaoCrypt MD5 size assert #include "md5.hpp" // for TaoCrypt MD5 size assert
#include "md4.hpp" // for TaoCrypt MD4 size assert
#include <stdio.h> #include <stdio.h>
#ifdef _WIN32 #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) 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) 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) void MD4_Final(unsigned char* hash, MD4_CTX* md4)
{ {
reinterpret_cast<TaoCrypt::MD4*>(md4->buffer)->Final(hash);
} }

View File

@@ -31,6 +31,7 @@
#include "hmac.hpp" #include "hmac.hpp"
#include "md5.hpp" #include "md5.hpp"
#include "sha.hpp" #include "sha.hpp"
#include "ripemd.hpp"
#include "openssl/ssl.h" #include "openssl/ssl.h"
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION #ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION

View File

@@ -26,13 +26,17 @@
#include "runtime.hpp" #include "runtime.hpp"
#include "timer.hpp" #include "timer.hpp"
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#include <sys/time.h>
#endif
namespace yaSSL { namespace yaSSL {
#ifdef _WIN32 #ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
timer_d timer() timer_d timer()
{ {
static bool init(false); static bool init(false);
@@ -57,8 +61,6 @@ namespace yaSSL {
#else // _WIN32 #else // _WIN32
#include <sys/time.h>
timer_d timer() timer_d timer()
{ {
struct timeval tv; struct timeval tv;

View File

@@ -26,6 +26,7 @@
#include "runtime.hpp" #include "runtime.hpp"
#include "yassl_error.hpp" #include "yassl_error.hpp"
#include "error.hpp" // TaoCrypt error numbers #include "error.hpp" // TaoCrypt error numbers
#include "openssl/ssl.h" // SSL_ERROR_WANT_READ
namespace yaSSL { namespace yaSSL {
@@ -117,6 +118,11 @@ void SetErrorString(YasslError error, char* buffer)
strncpy(buffer, "unable to proccess cerificate", max); strncpy(buffer, "unable to proccess cerificate", max);
break; break;
// openssl errors
case SSL_ERROR_WANT_READ :
strncpy(buffer, "the read operation would block", max);
break;
// TaoCrypt errors // TaoCrypt errors
case NO_ERROR : case NO_ERROR :
strncpy(buffer, "not in error state", max); strncpy(buffer, "not in error state", max);

View File

@@ -1415,15 +1415,6 @@ BulkCipher* CryptProvider::NewDesEde()
} }
extern "C" void yaSSL_CleanUp()
{
TaoCrypt::CleanUp();
ysDelete(cryptProviderInstance);
ysDelete(sslFactoryInstance);
ysDelete(sessionsInstance);
}
typedef Mutex::Lock Lock; typedef Mutex::Lock Lock;
@@ -2109,9 +2100,18 @@ ASN1_STRING* StringHolder::GetString()
} }
} // namespace } // namespace
extern "C" void yaSSL_CleanUp()
{
TaoCrypt::CleanUp();
ysDelete(yaSSL::cryptProviderInstance);
ysDelete(yaSSL::sslFactoryInstance);
ysDelete(yaSSL::sessionsInstance);
}
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION #ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
namespace mySTL { 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); 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);

View File

@@ -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 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/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/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/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 include/error.hpp include/file.hpp include/hash.hpp include/hmac.hpp include/integer.hpp

View File

@@ -96,7 +96,7 @@ public:
pointer allocate(size_type n, const void* = 0) pointer allocate(size_type n, const void* = 0)
{ {
CheckSize(n); this->CheckSize(n);
if (n == 0) if (n == 0)
return 0; return 0;
return NEW_TC T[n]; return NEW_TC T[n];

View 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

View File

@@ -28,10 +28,6 @@
#ifndef yaSSL_NEW_HPP #ifndef yaSSL_NEW_HPP
#define yaSSL_NEW_HPP #define yaSSL_NEW_HPP
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef __sun #ifdef __sun

View File

@@ -4,7 +4,7 @@ noinst_LTLIBRARIES = libtaocrypt.la
libtaocrypt_la_SOURCES = aes.cpp aestables.cpp algebra.cpp arc4.cpp \ libtaocrypt_la_SOURCES = aes.cpp aestables.cpp algebra.cpp arc4.cpp \
asn.cpp bftables.cpp blowfish.cpp coding.cpp des.cpp dh.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 \ random.cpp ripemd.cpp rsa.cpp sha.cpp template_instnt.cpp \
tftables.cpp twofish.cpp tftables.cpp twofish.cpp

View 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

View File

@@ -30,11 +30,11 @@
#include "sha.hpp" #include "sha.hpp"
#include "md5.hpp" #include "md5.hpp"
#include "hmac.hpp" #include "hmac.hpp"
#include "ripemd.hpp"
#include "pwdbased.hpp" #include "pwdbased.hpp"
#include "algebra.hpp" #include "algebra.hpp"
#include "vector.hpp" #include "vector.hpp"
#include "hash.hpp" #include "hash.hpp"
#include "ripemd.hpp"
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION #ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
namespace TaoCrypt { namespace TaoCrypt {

View File

@@ -146,6 +146,10 @@ SOURCE=.\src\md2.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\src\md4.cpp
# End Source File
# Begin Source File
SOURCE=.\src\md5.cpp SOURCE=.\src\md5.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -246,6 +250,10 @@ SOURCE=.\include\md2.hpp
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\include\md4.hpp
# End Source File
# Begin Source File
SOURCE=.\include\md5.hpp SOURCE=.\include\md5.hpp
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

@@ -8,6 +8,7 @@
#include "sha.hpp" #include "sha.hpp"
#include "md5.hpp" #include "md5.hpp"
#include "md2.hpp" #include "md2.hpp"
#include "md4.hpp"
#include "ripemd.hpp" #include "ripemd.hpp"
#include "hmac.hpp" #include "hmac.hpp"
#include "arc4.hpp" #include "arc4.hpp"
@@ -30,6 +31,7 @@ using TaoCrypt::word32;
using TaoCrypt::SHA; using TaoCrypt::SHA;
using TaoCrypt::MD5; using TaoCrypt::MD5;
using TaoCrypt::MD2; using TaoCrypt::MD2;
using TaoCrypt::MD4;
using TaoCrypt::RIPEMD160; using TaoCrypt::RIPEMD160;
using TaoCrypt::HMAC; using TaoCrypt::HMAC;
using TaoCrypt::ARC4; using TaoCrypt::ARC4;
@@ -89,6 +91,7 @@ void file_test(int, char**);
int sha_test(); int sha_test();
int md5_test(); int md5_test();
int md2_test(); int md2_test();
int md4_test();
int ripemd_test(); int ripemd_test();
int hmac_test(); int hmac_test();
int arc4_test(); int arc4_test();
@@ -165,6 +168,11 @@ void taocrypt_test(void* args)
else else
printf( "MD2 test passed!\n"); 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()) ) if ( (ret = ripemd_test()) )
err_sys("RIPEMD test failed!\n", ret); err_sys("RIPEMD test failed!\n", ret);
else 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() int md2_test()
{ {
MD2 md5; MD2 md5;

View File

@@ -33,10 +33,16 @@
// HPUX doesn't use socklent_t for third parameter to accept // HPUX doesn't use socklent_t for third parameter to accept
#if !defined(__hpux__) #if !defined(__hpux)
typedef socklen_t* ACCEPT_THIRD_T; typedef socklen_t* ACCEPT_THIRD_T;
#else #else
typedef int* ACCEPT_THIRD_T; 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 #endif

View File

@@ -240,4 +240,22 @@ extern int my_snprintf(char* to, size_t n, const char* fmt, ...);
#if defined(__cplusplus) #if defined(__cplusplus)
} }
#endif #endif
/*
LEX_STRING -- a pair of a C-string and its length.
NOTE: this exactly form of declaration is required for some C-compilers
(for one, Sun C 5.7 2005/01/07). Unfortunatelt with such declaration
LEX_STRING can not be forward declared.
*/
typedef struct
{
char *str;
uint length;
} LEX_STRING;
#define STRING_WITH_LEN(X) (X), ((uint) (sizeof(X) - 1))
#define C_STRING_WITH_SIZE(X) ((char *) (X)), ((uint) (sizeof(X) - 1))
#endif #endif

View File

@@ -77,6 +77,10 @@ extern int NEAR my_errno; /* Last error in mysys */
#define MY_GIVE_INFO 2 /* Give time info about process*/ #define MY_GIVE_INFO 2 /* Give time info about process*/
#define MY_DONT_FREE_DBUG 4 /* Do not call DBUG_END() in my_end() */ #define MY_DONT_FREE_DBUG 4 /* Do not call DBUG_END() in my_end() */
#define MY_REMOVE_NONE 0 /* Params for modify_defaults_file */
#define MY_REMOVE_OPTION 1
#define MY_REMOVE_SECTION 2
#define ME_HIGHBYTE 8 /* Shift for colours */ #define ME_HIGHBYTE 8 /* Shift for colours */
#define ME_NOCUR 1 /* Don't use curses message */ #define ME_NOCUR 1 /* Don't use curses message */
#define ME_OLDWIN 2 /* Use old window */ #define ME_OLDWIN 2 /* Use old window */

View File

@@ -423,17 +423,11 @@ char *octet2hex(char *to, const char *str, unsigned int len);
/* end of password.c */ /* end of password.c */
char *get_tty_password(char *opt_message); char *get_tty_password(const char *opt_message);
const char *mysql_errno_to_sqlstate(unsigned int mysql_errno); const char *mysql_errno_to_sqlstate(unsigned int mysql_errno);
/* Some other useful functions */ /* Some other useful functions */
my_bool my_init(void);
extern int modify_defaults_file(const char *file_location, const char *option,
const char *option_value,
const char *section_name, int remove_option);
int load_defaults(const char *conf_file, const char **groups,
int *argc, char ***argv);
my_bool my_thread_init(void); my_bool my_thread_init(void);
void my_thread_end(void); void my_thread_end(void);

View File

@@ -75,7 +75,7 @@
#define _cputs(A) putstring(A) #define _cputs(A) putstring(A)
#endif #endif
char *get_tty_password(char *opt_message) char *get_tty_password(const char *opt_message)
{ {
char to[80]; char to[80];
char *pos=to,*end=to+sizeof(to)-1; char *pos=to,*end=to+sizeof(to)-1;
@@ -159,7 +159,7 @@ static void get_password(char *to,uint length,int fd,bool echo)
#endif /* ! HAVE_GETPASS */ #endif /* ! HAVE_GETPASS */
char *get_tty_password(char *opt_message) char *get_tty_password(const char *opt_message)
{ {
#ifdef HAVE_GETPASS #ifdef HAVE_GETPASS
char *passbuff; char *passbuff;

View File

@@ -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 \ 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 \ 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 \ 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 \ rpl_filter.cc sql_partition.cc sql_builtin.cc sql_plugin.cc \
sql_tablespace.cc \ sql_tablespace.cc \
rpl_injector.cc my_user.c partition_info.cc rpl_injector.cc my_user.c partition_info.cc

View File

@@ -1220,9 +1220,12 @@ sub environment_setup () {
$ENV{'NDBCLUSTER_PORT_SLAVE'}=$opt_ndbcluster_port_slave; $ENV{'NDBCLUSTER_PORT_SLAVE'}=$opt_ndbcluster_port_slave;
$ENV{'NDB_STATUS_OK'}= "YES"; $ENV{'NDB_STATUS_OK'}= "YES";
$ENV{'IM_EXE'}= $exe_im;
$ENV{'IM_PATH_PID'}= $instance_manager->{path_pid}; $ENV{'IM_PATH_PID'}= $instance_manager->{path_pid};
$ENV{'IM_PATH_ANGEL_PID'}= $instance_manager->{path_angel_pid}; $ENV{'IM_PATH_ANGEL_PID'}= $instance_manager->{path_angel_pid};
$ENV{'IM_PORT'}= $instance_manager->{port}; $ENV{'IM_PORT'}= $instance_manager->{port};
$ENV{'IM_DEFAULTS_PATH'}= $instance_manager->{defaults_file};
$ENV{'IM_PASSWORD_PATH'}= $instance_manager->{password_file};
$ENV{'IM_MYSQLD1_SOCK'}= $instance_manager->{instances}->[0]->{path_sock}; $ENV{'IM_MYSQLD1_SOCK'}= $instance_manager->{instances}->[0]->{path_sock};
$ENV{'IM_MYSQLD1_PORT'}= $instance_manager->{instances}->[0]->{port}; $ENV{'IM_MYSQLD1_PORT'}= $instance_manager->{instances}->[0]->{port};

View File

@@ -17,13 +17,13 @@ db_x
SHOW TABLES FROM db_x; SHOW TABLES FROM db_x;
Tables_in_db_x Tables_in_db_x
x_table x_table
SET GLOBAL event_scheduler=0; SET GLOBAL event_scheduler=2;
DROP EVENT e_x1; DROP EVENT e_x1;
DROP EVENT e_x2; DROP EVENT e_x2;
DROP DATABASE db_x; DROP DATABASE db_x;
DROP USER pauline@localhost; DROP USER pauline@localhost;
USE events_test; USE events_test;
SET GLOBAL event_scheduler=0; SET GLOBAL event_scheduler=2;
drop event if exists event1; drop event if exists event1;
Warnings: Warnings:
Note 1305 Event event1 does not exist Note 1305 Event event1 does not exist
@@ -100,7 +100,7 @@ a
800219 800219
drop event non_qualif_ev; drop event non_qualif_ev;
drop table non_qualif; drop table non_qualif;
set global event_scheduler = 0; set global event_scheduler = 2;
create table t_event3 (a int, b float); create table t_event3 (a int, b float);
drop event if exists event3; drop event if exists event3;
Warnings: 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 three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
events_test two_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:"; "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 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 one_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
events_test three_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 two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
"This should show us only 2 events:"; "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 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 three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED
events_test two_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:"; "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 Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
DROP DATABASE events_test2; DROP DATABASE events_test2;
"should see 1 event:"; "should see 1 event:";
@@ -343,11 +343,8 @@ SHOW EVENTS;
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
events_test one_event root@localhost RECURRING NULL 10 SECOND # # ENABLED events_test one_event root@localhost RECURRING NULL 10 SECOND # # ENABLED
"we should see 4 events now:"; "we should see 4 events now:";
SHOW FULL EVENTS; SHOW EVENTS;
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status 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 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; 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 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; set names utf8;
create event задачка on schedule every 123 minute starts now() ends now() + interval 1 month do select 1; create event задачка on schedule every 123 minute starts now() ends now() + interval 1 month do select 1;
drop event задачка; 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 ERROR HY000: Variable 'event_scheduler' is a GLOBAL variable and should be set with SET GLOBAL
set global event_scheduler=2; set global event_scheduler=3;
ERROR 42000: Variable 'event_scheduler' can't be set to the value of '2' 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" "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 definer, name, db from mysql.event;
definer name db definer name db
select get_lock("test_lock1", 20); 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; select definer, name, db from mysql.event;
definer name db definer name db
root@localhost закачка events_test 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; 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 user host db command state info
event_scheduler localhost NULL Connect Suspended NULL
select release_lock("test_lock1"); select release_lock("test_lock1");
release_lock("test_lock1") release_lock("test_lock1")
1 1
@@ -409,11 +407,12 @@ get_lock("test_lock2", 20)
create event закачка on schedule every 10 hour do select 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" "Let some time pass to the event starts"
"Should have only 2 processes: the scheduler and the locked event" "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 user host db command state info
event_scheduler localhost NULL Connect Sleeping NULL event_scheduler localhost NULL Connect Sleeping NULL
root localhost events_test Connect User lock select get_lock("test_lock2", 20) 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."
"Release the mutex, the event worker should finish."
select release_lock("test_lock2"); select release_lock("test_lock2");
release_lock("test_lock2") release_lock("test_lock2")
1 1
@@ -423,21 +422,17 @@ select get_lock("test_lock2_1", 20);
get_lock("test_lock2_1", 20) get_lock("test_lock2_1", 20)
1 1
create event закачка21 on schedule every 10 hour do select get_lock("test_lock2_1", 20); create event закачка21 on schedule every 10 hour do select get_lock("test_lock2_1", 20);
"Should see 1 process, locked on get_lock(" "Should have only 3 processes: the scheduler, our conn and the locked event"
"Shutting down the scheduler, it should wait for the running 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=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;
user host db command state info user host db command state info
event_scheduler localhost NULL Connect Sleeping NULL event_scheduler localhost NULL Connect Sleeping NULL
root localhost events_test Connect User lock select get_lock("test_lock2_1", 20) 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" set global event_scheduler=2;
select release_lock("test_lock2_1"); "Should have only our process now:"
release_lock("test_lock2_1") select /*4*/ user, host, db, command, state, info from information_schema.processlist where info is null or info not like '%processlist%' order by info;
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;
user host db command state 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; drop event закачка21;
create table t_16 (s1 int); 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; 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'; select event_schema, event_name, definer, event_body from information_schema.events where event_name='white_space';
event_schema event_name definer event_body event_schema event_name definer event_body
events_test white_space root@localhost select 2 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; drop event white_space;
create event white_space on schedule every 10 hour disable do select 3; 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'; select event_schema, event_name, definer, event_body from information_schema.events where event_name='white_space';

View File

@@ -35,7 +35,7 @@ create event e_55 on schedule every 10 hour starts 99990101000000 do drop table
ERROR HY000: Incorrect STARTS value: '99990101000000' ERROR HY000: Incorrect STARTS value: '99990101000000'
create event e_55 on schedule every 10 minute ends 99990101000000 do drop table t; create event e_55 on schedule every 10 minute ends 99990101000000 do drop table t;
ERROR HY000: ENDS is either invalid or before STARTS 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" "Wait a bit to settle down"
delete from mysql.event; delete from mysql.event;
set global event_scheduler= 1; 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'); select release_lock('test_bug16407');
release_lock('test_bug16407') release_lock('test_bug16407')
1 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; select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
event_schema event_name sql_mode event_schema event_name sql_mode
events_test e_16407 REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI 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; 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 user host db command state info
event_scheduler localhost NULL Connect Sleeping NULL 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; select * from events_smode_test order by ev_name, a;
ev_name a ev_name a
ee_16407_3 1980-02-19 ee_16407_3 1980-02-19
@@ -175,7 +175,7 @@ drop event ee_16407_5;
drop event ee_16407_6; drop event ee_16407_6;
drop procedure ee_16407_5_pendant; drop procedure ee_16407_5_pendant;
drop procedure ee_16407_6_pendant; drop procedure ee_16407_6_pendant;
set global event_scheduler= 0; set global event_scheduler= 2;
drop table events_smode_test; drop table events_smode_test;
set sql_mode=@old_sql_mode; set sql_mode=@old_sql_mode;
drop database events_test; drop database events_test;

View File

@@ -8,7 +8,7 @@ BEGIN
SELECT user_host, argument FROM mysql.general_log WHERE argument LIKE '%alabala%'; SELECT user_host, argument FROM mysql.general_log WHERE argument LIKE '%alabala%';
END| END|
"Check General Query Log" "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; create event log_general on schedule every 1 minute do SELect 'alabala', sleep(3) from dual;
TRUNCATE mysql.general_log; TRUNCATE mysql.general_log;
"1 row, the current statement!" "1 row, the current statement!"
@@ -22,7 +22,7 @@ user_host argument
root[root] @ localhost [localhost] SELect 'alabala', sleep(3) from dual root[root] @ localhost [localhost] SELect 'alabala', sleep(3) from dual
DROP PROCEDURE select_general_log; DROP PROCEDURE select_general_log;
DROP EVENT log_general; DROP EVENT log_general;
SET GLOBAL event_scheduler=0; SET GLOBAL event_scheduler=2;
"Check slow query log" "Check slow query log"
"Save the values" "Save the values"
SET @old_global_long_query_time:=(select get_value()); 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 user_host query_time db sql_text
"Set new values" "Set new values"
SET GLOBAL long_query_time=4; SET GLOBAL long_query_time=4;
SET SESSION long_query_time=2; SET SESSION long_query_time=1;
"Check that logging is working" "Check that logging is working"
SELECT SLEEP(3); SELECT SLEEP(2);
SLEEP(3) SLEEP(2)
0 0
SELECT user_host, query_time, db, sql_text FROM mysql.slow_log; SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
user_host query_time db sql_text 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; TRUNCATE mysql.slow_log;
CREATE TABLE slow_event_test (slo_val tinyint, val tinyint); CREATE TABLE slow_event_test (slo_val tinyint, val tinyint);
"This won't go to the slow log" "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" "Sleep some more time than the actual event run will take"
SHOW VARIABLES LIKE 'event_scheduler'; SHOW VARIABLES LIKE 'event_scheduler';
Variable_name Value Variable_name Value
event_scheduler ON event_scheduler 1
"Check our table. Should see 1 row" "Check our table. Should see 1 row"
SELECT * FROM slow_event_test; SELECT * FROM slow_event_test;
slo_val val 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 user_host query_time db sql_text
"This should go to the slow log" "This should go to the slow log"
SET SESSION long_query_time=10; SET SESSION long_query_time=10;
SET GLOBAL long_query_time=1;
DROP EVENT long_event; 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" "Sleep some more time than the actual event run will take"
"Check our table. Should see 2 rows" "Check our table. Should see 2 rows"
SELECT * FROM slow_event_test; SELECT * FROM slow_event_test;
slo_val val slo_val val
4 0 4 0
4 0 1 0
"Check slow log. Should see 1 row because 5 is over the threshold of 4 for GLOBAL, though under SESSION which is 10" "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; SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
user_host query_time db sql_text 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; DROP EVENT long_event2;
SET GLOBAL long_query_time =@old_global_long_query_time; SET GLOBAL long_query_time =@old_global_long_query_time;
SET SESSION long_query_time =@old_session_long_query_time; SET SESSION long_query_time =@old_session_long_query_time;

View File

@@ -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' ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND'
CREATE EVENT micro_test ON SCHEDULE EVERY 100 SECOND_MICROSECOND DO SELECT 1; CREATE EVENT micro_test ON SCHEDULE EVERY 100 SECOND_MICROSECOND DO SELECT 1;
ERROR 42000: This version of MySQL doesn't yet support 'MICROSECOND' 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; drop database events_test;

View File

@@ -14,7 +14,7 @@ ENDS NOW() + INTERVAL 6 SECOND
ON COMPLETION PRESERVE ON COMPLETION PRESERVE
DO INSERT INTO table_2 VALUES(1); 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 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; SELECT IF(SUM(a) >= 4, 'OK', 'ERROR') FROM table_1;
IF(SUM(a) >= 4, 'OK', 'ERROR') IF(SUM(a) >= 4, 'OK', 'ERROR')
OK OK
@@ -38,9 +38,12 @@ DROP EVENT start_n_end;
"Already dropped because ended. Therefore an error." "Already dropped because ended. Therefore an error."
DROP EVENT only_one_time; DROP EVENT only_one_time;
ERROR HY000: Unknown 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; DROP EVENT two_time;
ERROR HY000: Unknown event 'two_time'
DROP TABLE table_1; DROP TABLE table_1;
DROP TABLE table_2; DROP TABLE table_2;
DROP TABLE table_3; DROP TABLE table_3;

View File

@@ -1,46 +1,61 @@
CREATE DATABASE IF NOT EXISTS events_test; CREATE DATABASE IF NOT EXISTS events_test;
CREATE DATABASE events_test2; CREATE DATABASE events_conn1_test2;
USE events_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_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_drop2 ON SCHEDULE EVERY 10 MINUTE DISABLE DO SELECT 1;
CREATE EVENT ev_drop3 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; USE events_test;
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2'; SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS;
COUNT(*)
103
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
COUNT(*) COUNT(*)
3 3
DROP DATABASE events_test2; DROP DATABASE events_conn1_test2;
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2'; SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
COUNT(*) COUNT(*)
0 0
"Now testing stability - dropping db -> events while they are running" "Now testing stability - dropping db -> events while they are running"
CREATE DATABASE events_test2; CREATE DATABASE events_conn1_test2;
USE events_test2; USE events_conn1_test2;
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2'; SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
COUNT(*) COUNT(*)
1000 50
SET GLOBAL event_scheduler=1; SET GLOBAL event_scheduler=1;
DROP DATABASE events_test2; DROP DATABASE events_conn1_test2;
SET GLOBAL event_scheduler=0; SET GLOBAL event_scheduler=2;
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2'; SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test2';
COUNT(*) COUNT(*)
0 0
CREATE DATABASE events_test3; CREATE DATABASE events_conn1_test3;
USE events_test3; USE events_conn1_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;
SET GLOBAL event_scheduler=1; SET GLOBAL event_scheduler=1;
DROP DATABASE events_test4; SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_test3';
COUNT(*)
50
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(*)
50
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; SET GLOBAL event_scheduler=1;
USE events_test; USE events_test;
DROP TABLE fill_it;
DROP DATABASE events_test; DROP DATABASE events_test;

View File

@@ -0,0 +1,40 @@
--> Listing users...
im_admin
==> Adding user 'testuser'...
--> IM password file:
testuser:*0D3CED9BEC10A777AEC23CCC353A8C08A633045E
im_admin:*598D51AD2DFF7792045D6DF3DDF9AA1AF737B295
--> EOF
--> Printing out line for 'testuser'...
testuser:*0D3CED9BEC10A777AEC23CCC353A8C08A633045E
--> Listing users...
im_admin
testuser
==> Changing the password of 'testuser'...
--> IM password file:
im_admin:*598D51AD2DFF7792045D6DF3DDF9AA1AF737B295
testuser:*39C549BDECFBA8AFC3CE6B948C9359A0ECE08DE2
--> EOF
--> Printing out line for 'testuser'...
testuser:*39C549BDECFBA8AFC3CE6B948C9359A0ECE08DE2
--> Listing users...
testuser
im_admin
==> Dropping user 'testuser'...
--> IM password file:
im_admin:*598D51AD2DFF7792045D6DF3DDF9AA1AF737B295
--> EOF
--> Listing users...
im_admin

View File

@@ -1,5 +1,5 @@
SHOW INSTANCES; SHOW INSTANCES;
instance_name status instance_name state
mysqld1 online mysqld1 online
mysqld2 offline mysqld2 offline
Killing the process... Killing the process...

View File

@@ -0,0 +1,196 @@
--------------------------------------------------------------------
server_id = 1
server_id = 2
--------------------------------------------------------------------
SHOW INSTANCES;
instance_name state
mysqld1 online
mysqld2 offline
---> connection: mysql1_con
SHOW VARIABLES LIKE 'server_id';
Variable_name Value
server_id 1
---> connection: default
CREATE INSTANCE mysqld3;
SHOW INSTANCES;
instance_name state
mysqld3 offline
mysqld2 offline
mysqld1 online
--------------------------------------------------------------------
server_id = 1
server_id = 2
--------------------------------------------------------------------
CREATE INSTANCE mysqld1;
ERROR HY000: Instance already exists
CREATE INSTANCE mysqld2;
ERROR HY000: Instance already exists
CREATE INSTANCE mysqld3;
ERROR HY000: Instance already exists
--------------------------------------------------------------------
nonguarded
--------------------------------------------------------------------
CREATE INSTANCE mysqld4 nonguarded;
SHOW INSTANCES;
instance_name state
mysqld3 offline
mysqld4 offline
mysqld1 online
mysqld2 offline
--------------------------------------------------------------------
nonguarded
nonguarded
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
CREATE INSTANCE mysqld5 test-A = 000, test-B = test;
SHOW INSTANCES;
instance_name state
mysqld1 online
mysqld4 offline
mysqld5 offline
mysqld2 offline
mysqld3 offline
--------------------------------------------------------------------
test-A=000
--------------------------------------------------------------------
test-B=test
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
CREATE INSTANCE mysqld6 test-C1 = 10 , test-C2 = 02 ;
SHOW INSTANCES;
instance_name state
mysqld1 online
mysqld2 offline
mysqld5 offline
mysqld6 offline
mysqld3 offline
mysqld4 offline
--------------------------------------------------------------------
test-C1=10
--------------------------------------------------------------------
test-C2=02
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
CREATE INSTANCE mysqld7 test-D = test-D-value ;
ERROR 42000: You have an error in your command syntax. Check the manual that corresponds to your MySQL Instance Manager version for the right syntax to use
SHOW INSTANCES;
instance_name state
mysqld1 online
mysqld2 offline
mysqld5 offline
mysqld6 offline
mysqld3 offline
mysqld4 offline
CREATE INSTANCE mysqld8 test-E 0 ;
ERROR 42000: You have an error in your command syntax. Check the manual that corresponds to your MySQL Instance Manager version for the right syntax to use
SHOW INSTANCES;
instance_name state
mysqld1 online
mysqld2 offline
mysqld5 offline
mysqld6 offline
mysqld3 offline
mysqld4 offline
CREATE INSTANCE mysqld8 test-F = ;
ERROR 42000: You have an error in your command syntax. Check the manual that corresponds to your MySQL Instance Manager version for the right syntax to use
SHOW INSTANCES;
instance_name state
mysqld1 online
mysqld2 offline
mysqld5 offline
mysqld6 offline
mysqld3 offline
mysqld4 offline
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
CREATE INSTANCE mysqld9 test-1=" hello world ", test-2=' ';
SHOW INSTANCES;
instance_name state
mysqld1 online
mysqld2 offline
mysqld5 offline
mysqld6 offline
mysqld3 offline
mysqld4 offline
mysqld9 offline
CREATE INSTANCE mysqld9a test-3='\b\babc\sdef';
SHOW INSTANCES;
instance_name state
mysqld1 online
mysqld9a offline
mysqld5 offline
mysqld6 offline
mysqld3 offline
mysqld4 offline
mysqld9 offline
mysqld2 offline
CREATE INSTANCE mysqld9b test-4='abc\tdef', test-5='abc\ndef';
SHOW INSTANCES;
instance_name state
mysqld9b offline
mysqld9a offline
mysqld5 offline
mysqld6 offline
mysqld3 offline
mysqld4 offline
mysqld9 offline
mysqld2 offline
mysqld1 online
CREATE INSTANCE mysqld9c test-6="abc\rdef", test-7="abc\\def";
SHOW INSTANCES;
instance_name state
mysqld9b offline
mysqld6 offline
mysqld5 offline
mysqld9c offline
mysqld3 offline
mysqld4 offline
mysqld9 offline
mysqld2 offline
mysqld1 online
mysqld9a offline
CREATE INSTANCE mysqld10 test-bad=' \ ';
ERROR 42000: You have an error in your command syntax. Check the manual that corresponds to your MySQL Instance Manager version for the right syntax to use
SHOW INSTANCES;
instance_name state
mysqld9b offline
mysqld6 offline
mysqld5 offline
mysqld9c offline
mysqld3 offline
mysqld4 offline
mysqld9 offline
mysqld2 offline
mysqld1 online
mysqld9a offline
--------------------------------------------------------------------
test-1= hello world
--------------------------------------------------------------------
test-2=
--------------------------------------------------------------------
test-3=abc def
--------------------------------------------------------------------
test-4=abc def
--------------------------------------------------------------------
test-5=abc
--------------------------------------------------------------------
test-6=abc
def
--------------------------------------------------------------------
test-7=abc\def
--------------------------------------------------------------------
--------------------------------------------------------------------
CREATE INSTANCE qqq1;

View File

@@ -1,69 +1,93 @@
--------------------------------------------------------------------
-- 1.1.1.
--------------------------------------------------------------------
SHOW INSTANCES; SHOW INSTANCES;
instance_name status instance_name state
mysqld1 online mysqld1 online
mysqld2 offline mysqld2 offline
SHOW INSTANCE STATUS mysqld1;
instance_name status version_number version --------------------------------------------------------------------
mysqld1 online VERSION_NUMBER VERSION -- 1.1.2.
SHOW INSTANCE STATUS mysqld2; --------------------------------------------------------------------
instance_name status version_number version
mysqld2 offline VERSION_NUMBER VERSION
START INSTANCE mysqld2; START INSTANCE mysqld2;
SHOW INSTANCES; SHOW INSTANCES;
instance_name status instance_name state
mysqld1 online mysqld1 online
mysqld2 online mysqld2 online
SHOW INSTANCE STATUS mysqld1;
instance_name status version_number version
mysqld1 online VERSION_NUMBER VERSION
SHOW INSTANCE STATUS mysqld2;
instance_name status version_number version
mysqld2 online VERSION_NUMBER VERSION
SHOW VARIABLES LIKE 'port'; SHOW VARIABLES LIKE 'port';
Variable_name Value Variable_name Value
port IM_MYSQLD1_PORT port IM_MYSQLD2_PORT
--------------------------------------------------------------------
-- 1.1.3.
--------------------------------------------------------------------
STOP INSTANCE mysqld2; STOP INSTANCE mysqld2;
SHOW INSTANCES; SHOW INSTANCES;
instance_name status instance_name state
mysqld1 online mysqld1 online
mysqld2 offline mysqld2 offline
SHOW INSTANCE STATUS mysqld1; SHOW INSTANCE STATUS mysqld1;
instance_name status version_number version instance_name state version_number version mysqld_compatible
mysqld1 online VERSION_NUMBER VERSION mysqld1 online VERSION_NUMBER VERSION no
SHOW INSTANCE STATUS mysqld2; SHOW INSTANCE STATUS mysqld2;
instance_name status version_number version instance_name state version_number version mysqld_compatible
mysqld2 offline VERSION_NUMBER VERSION mysqld2 offline VERSION_NUMBER VERSION no
--------------------------------------------------------------------
-- 1.1.4.
--------------------------------------------------------------------
START INSTANCE mysqld3; START INSTANCE mysqld3;
ERROR HY000: Bad instance name. Check that the instance with such a name exists ERROR HY000: Bad instance name. Check that the instance with such a name exists
START INSTANCE mysqld1; START INSTANCE mysqld1;
ERROR HY000: The instance is already started ERROR HY000: The instance is already started
--------------------------------------------------------------------
-- 1.1.5.
--------------------------------------------------------------------
STOP INSTANCE mysqld3; STOP INSTANCE mysqld3;
ERROR HY000: Bad instance name. Check that the instance with such a name exists ERROR HY000: Bad instance name. Check that the instance with such a name exists
--------------------------------------------------------------------
-- 1.1.6.
--------------------------------------------------------------------
SHOW INSTANCES; SHOW INSTANCES;
instance_name status instance_name state
mysqld1 online mysqld1 online
mysqld2 offline mysqld2 offline
Killing the process... Killing the process...
Sleeping... Sleeping...
Success: the process was restarted. Success: the process was restarted.
--------------------------------------------------------------------
-- 1.1.7.
--------------------------------------------------------------------
SHOW INSTANCES; SHOW INSTANCES;
instance_name status instance_name state
mysqld1 online mysqld1 online
mysqld2 offline mysqld2 offline
START INSTANCE mysqld2; START INSTANCE mysqld2;
SHOW INSTANCES; SHOW INSTANCES;
instance_name status instance_name state
mysqld1 online mysqld1 online
mysqld2 online mysqld2 online
Killing the process... Killing the process...
Sleeping... Sleeping...
Success: the process was killed. Success: the process was killed.
SHOW INSTANCES; SHOW INSTANCES;
instance_name status instance_name state
mysqld1 online mysqld1 online
mysqld2 offline mysqld2 offline
--------------------------------------------------------------------
-- 1.1.8.
--------------------------------------------------------------------
SHOW INSTANCE STATUS; SHOW INSTANCE STATUS;
ERROR 42000: You have an error in your command syntax. Check the manual that corresponds to your MySQL Instance Manager version for the right syntax to use ERROR 42000: You have an error in your command syntax. Check the manual that corresponds to your MySQL Instance Manager version for the right syntax to use
--------------------------------------------------------------------
-- BUG#12813
--------------------------------------------------------------------
START INSTANCE mysqld1,mysqld2,mysqld3; START INSTANCE mysqld1,mysqld2,mysqld3;
ERROR 42000: You have an error in your command syntax. Check the manual that corresponds to your MySQL Instance Manager version for the right syntax to use ERROR 42000: You have an error in your command syntax. Check the manual that corresponds to your MySQL Instance Manager version for the right syntax to use
STOP INSTANCE mysqld1,mysqld2,mysqld3; STOP INSTANCE mysqld1,mysqld2,mysqld3;

View File

@@ -0,0 +1,150 @@
--------------------------------------------------------------------
server_id = 1
server_id = 2
--------------------------------------------------------------------
SHOW VARIABLES LIKE 'server_id';
Variable_name Value
server_id 1
SHOW INSTANCES;
instance_name state
mysqld1 starting
mysqld2 offline
UNSET mysqld1.server_id;
ERROR HY000: The instance is active. Stop the instance first
SET mysqld1.server_id = 11;
ERROR HY000: The instance is active. Stop the instance first
CREATE INSTANCE mysqld3 datadir = '/';
START INSTANCE mysqld3;
UNSET mysqld3.server_id;
ERROR HY000: The instance is active. Stop the instance first
SET mysqld3.server_id = 11;
ERROR HY000: The instance is active. Stop the instance first
STOP INSTANCE mysqld3;
SHOW INSTANCE STATUS mysqld3;
instance_name state version_number version mysqld_compatible
mysqld3 offline VERSION_NUMBER VERSION no
UNSET mysqld2.server_id;
UNSET mysqld2.server_id;
SHOW INSTANCE OPTIONS mysqld2;
option_name value
instance_name option_value
socket option_value
pid-file option_value
port option_value
datadir option_value
log option_value
log-error option_value
log-slow-queries option_value
language option_value
character-sets-dir option_value
basedir option_value
skip-stack-trace option_value
skip-innodb option_value
skip-bdb option_value
skip-ndbcluster option_value
nonguarded option_value
log-output option_value
SET mysqld2.server_id = 2;
SET mysqld2.server_id = 2;
SHOW INSTANCE OPTIONS mysqld2;
option_name value
instance_name option_value
socket option_value
pid-file option_value
port option_value
datadir option_value
log option_value
log-error option_value
log-slow-queries option_value
language option_value
character-sets-dir option_value
basedir option_value
skip-stack-trace option_value
skip-innodb option_value
skip-bdb option_value
skip-ndbcluster option_value
nonguarded option_value
log-output option_value
server_id option_value
UNSET mysqld2.server_id = 11;
ERROR 42000: You have an error in your command syntax. Check the manual that corresponds to your MySQL Instance Manager version for the right syntax to use
SET mysqld2.aaa, mysqld3.bbb, mysqld2.ccc = 0010, mysqld3.ddd = 0020;
--------------------------------------------------------------------
aaa
--------------------------------------------------------------------
bbb
--------------------------------------------------------------------
ccc=0010
--------------------------------------------------------------------
ddd=0020
--------------------------------------------------------------------
UNSET mysqld2.aaa, mysqld3.bbb, mysqld2.ccc, mysqld3.ddd;
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
SET mysqld2.aaa, mysqld3.bbb, mysqld.ccc = 0010;
ERROR HY000: Bad instance name. Check that the instance with such a name exists
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
SET mysqld2.aaa, mysqld3.bbb, mysqld1.ccc = 0010;
ERROR HY000: The instance is active. Stop the instance first
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
UNSET mysqld2.server_id, mysqld3.server_id, mysqld.ccc;
ERROR HY000: Bad instance name. Check that the instance with such a name exists
--------------------------------------------------------------------
server_id = 1
server_id=2
--------------------------------------------------------------------
UNSET mysqld2.server_id, mysqld3.server_id, mysqld1.ccc;
ERROR HY000: The instance is active. Stop the instance first
--------------------------------------------------------------------
server_id = 1
server_id=2
--------------------------------------------------------------------
DROP INSTANCE mysqld3;
SET mysqld2.server_id=222;
SET mysqld2.server_id = 222;
SET mysqld2.server_id = 222 ;
SET mysqld2 . server_id = 222 ;
SET mysqld2 . server_id = 222 , mysqld2 . aaa , mysqld2 . bbb ;
--------------------------------------------------------------------
server_id = 1
server_id=222
--------------------------------------------------------------------
aaa
--------------------------------------------------------------------
bbb
--------------------------------------------------------------------
UNSET mysqld2 . aaa , mysqld2 . bbb ;
--------------------------------------------------------------------
server_id = 1
server_id=222
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
--------------------------------------------------------------------
server_id = 1
server_id=222
--------------------------------------------------------------------
SHOW VARIABLES LIKE 'server_id';
Variable_name Value
server_id 1
SHOW INSTANCES;
instance_name state
mysqld1 online
mysqld2 offline
FLUSH INSTANCES;
ERROR HY000: At least one instance is active. Stop all instances first
STOP INSTANCE mysqld1;
SHOW INSTANCES;
instance_name state
mysqld1 offline
mysqld2 offline
FLUSH INSTANCES;

View File

@@ -1,20 +0,0 @@
server_id = 1
server_id = 2
SHOW VARIABLES LIKE 'server_id';
Variable_name Value
server_id 1
SET mysqld1.server_id = 11;
server_id =11
server_id = 2
SHOW VARIABLES LIKE 'server_id';
Variable_name Value
server_id 1
SET mysqld2.server_id = 12;
server_id =11
server_id =12
FLUSH INSTANCES;
server_id =11
server_id =12
SHOW VARIABLES LIKE 'server_id';
Variable_name Value
server_id 1

View File

@@ -1,15 +0,0 @@
server_id = 1
server_id = 2
SHOW VARIABLES LIKE 'server_id';
Variable_name Value
server_id 1
UNSET mysqld1.server_id;
server_id = 2
SHOW VARIABLES LIKE 'server_id';
Variable_name Value
server_id 1
UNSET mysqld2.server_id;
FLUSH INSTANCES;
SHOW VARIABLES LIKE 'server_id';
Variable_name Value
server_id 1

View File

@@ -1,11 +1,10 @@
SHOW INSTANCES; SHOW INSTANCES;
instance_name status instance_name state
mysqld1 online mysqld1 online
mysqld2 offline mysqld2 offline
SHOW INSTANCE OPTIONS mysqld1; SHOW INSTANCE OPTIONS mysqld1;
option_name value option_name value
instance_name VALUE instance_name VALUE
mysqld-path VALUE
socket VALUE socket VALUE
pid-file VALUE pid-file VALUE
port VALUE port VALUE
@@ -25,8 +24,6 @@ log-output VALUE
SHOW INSTANCE OPTIONS mysqld2; SHOW INSTANCE OPTIONS mysqld2;
option_name value option_name value
instance_name VALUE instance_name VALUE
mysqld-path VALUE
nonguarded VALUE
socket VALUE socket VALUE
pid-file VALUE pid-file VALUE
port VALUE port VALUE
@@ -42,6 +39,7 @@ skip-stack-trace VALUE
skip-innodb VALUE skip-innodb VALUE
skip-bdb VALUE skip-bdb VALUE
skip-ndbcluster VALUE skip-ndbcluster VALUE
nonguarded VALUE
log-output VALUE log-output VALUE
START INSTANCE mysqld2; START INSTANCE mysqld2;
STOP INSTANCE mysqld2; STOP INSTANCE mysqld2;

View File

@@ -2,14 +2,14 @@ use mysql;
truncate table general_log; truncate table general_log;
select * from general_log; select * from general_log;
event_time user_host thread_id server_id command_type argument event_time user_host thread_id server_id command_type argument
TIMESTAMP root[root] @ localhost [] 1 1 Query select * from general_log TIMESTAMP root[root] @ localhost [] THREAD_ID 1 Query select * from general_log
truncate table slow_log; truncate table slow_log;
select * from slow_log; select * from slow_log;
start_time user_host query_time lock_time rows_sent rows_examined db last_insert_id insert_id server_id sql_text start_time user_host query_time lock_time rows_sent rows_examined db last_insert_id insert_id server_id sql_text
truncate table general_log; truncate table general_log;
select * from general_log where argument like '%general_log%'; select * from general_log where argument like '%general_log%';
event_time user_host thread_id server_id command_type argument event_time user_host thread_id server_id command_type argument
TIMESTAMP root[root] @ localhost [] 1 1 Query select * from general_log where argument like '%general_log%' TIMESTAMP root[root] @ localhost [] THREAD_ID 1 Query select * from general_log where argument like '%general_log%'
create table join_test (verbose_comment varchar (80), command_type varchar(64)); create table join_test (verbose_comment varchar (80), command_type varchar(64));
insert into join_test values ("User performed a usual SQL query", "Query"); insert into join_test values ("User performed a usual SQL query", "Query");
insert into join_test values ("New DB connection was registered", "Connect"); insert into join_test values ("New DB connection was registered", "Connect");
@@ -59,10 +59,10 @@ create table bug16905 (s char(15) character set utf8 default 'пусто');
insert into bug16905 values ('новое'); insert into bug16905 values ('новое');
select * from mysql.general_log; select * from mysql.general_log;
event_time user_host thread_id server_id command_type argument event_time user_host thread_id server_id command_type argument
TIMESTAMP root[root] @ localhost [] 2 1 Query set names utf8 TIMESTAMP root[root] @ localhost [] THREAD_ID 1 Query set names utf8
TIMESTAMP root[root] @ localhost [] 2 1 Query create table bug16905 (s char(15) character set utf8 default 'пусто') TIMESTAMP root[root] @ localhost [] THREAD_ID 1 Query create table bug16905 (s char(15) character set utf8 default 'пусто')
TIMESTAMP root[root] @ localhost [] 2 1 Query insert into bug16905 values ('новое') TIMESTAMP root[root] @ localhost [] THREAD_ID 1 Query insert into bug16905 values ('новое')
TIMESTAMP root[root] @ localhost [] 2 1 Query select * from mysql.general_log TIMESTAMP root[root] @ localhost [] THREAD_ID 1 Query select * from mysql.general_log
drop table bug16905; drop table bug16905;
truncate table mysql.slow_log; truncate table mysql.slow_log;
set session long_query_time=1; set session long_query_time=1;

View File

@@ -1,5 +1,6 @@
prepare stmt1 from ' show full processlist '; prepare stmt1 from ' show full processlist ';
execute stmt1; execute stmt1;
Id User Host db Command Time State Info Id User Host db Command Time State Info
number event_scheduler localhost NULL Connect time Suspended NULL
number root localhost test Query time NULL show full processlist number root localhost test Query time NULL show full processlist
deallocate prepare stmt1; deallocate prepare stmt1;

View File

@@ -299,7 +299,7 @@ t9 MyISAM 10 Dynamic 2 216 432 # 2048 0 NULL # # # latin1_swedish_ci NULL
prepare stmt4 from ' show status like ''Threads_running'' '; prepare stmt4 from ' show status like ''Threads_running'' ';
execute stmt4; execute stmt4;
Variable_name Value Variable_name Value
Threads_running 1 Threads_running 2
prepare stmt4 from ' show variables like ''sql_mode'' '; prepare stmt4 from ' show variables like ''sql_mode'' ';
execute stmt4; execute stmt4;
Variable_name Value Variable_name Value

View File

@@ -10,5 +10,6 @@ user()
# #
show processlist; show processlist;
Id User Host db Command Time State Info Id User Host db Command Time State Info
<id> event_scheduler <host> NULL <command> <time> <state> <info>
<id> root <host> test <command> <time> <state> <info> <id> root <host> test <command> <time> <state> <info>
<id> root <host> test <command> <time> <state> <info> <id> root <host> test <command> <time> <state> <info>

View File

@@ -34,6 +34,7 @@ lock tables t2 write;
call bug9486(); call bug9486();
show processlist; show processlist;
Id User Host db Command Time State Info Id User Host db Command Time State Info
# event_scheduler localhost NULL Connect # Suspended NULL
# root localhost test Sleep # NULL # root localhost test Sleep # NULL
# root localhost test Query # Locked update t1, t2 set val= 1 where id1=id2 # root localhost test Query # Locked update t1, t2 set val= 1 where id1=id2
# root localhost test Query # NULL show processlist # root localhost test Query # NULL show processlist

View File

@@ -18,9 +18,11 @@ show processlist;
end| end|
call bug4902_2()| call bug4902_2()|
Id User Host db Command Time State Info Id User Host db Command Time State Info
# event_scheduler localhost NULL Connect # Suspended NULL
# root localhost test Query # NULL show processlist # root localhost test Query # NULL show processlist
call bug4902_2()| call bug4902_2()|
Id User Host db Command Time State Info Id User Host db Command Time State Info
# event_scheduler localhost NULL Connect # Suspended NULL
# root localhost test Query # NULL show processlist # root localhost test Query # NULL show processlist
drop procedure bug4902_2| drop procedure bug4902_2|
drop function if exists bug5278| drop function if exists bug5278|

View File

@@ -26,20 +26,20 @@ Last_query_cost 0.000000
FLUSH STATUS; FLUSH STATUS;
SHOW STATUS LIKE 'max_used_connections'; SHOW STATUS LIKE 'max_used_connections';
Variable_name Value Variable_name Value
Max_used_connections 1 Max_used_connections 2
SET @save_thread_cache_size=@@thread_cache_size; SET @save_thread_cache_size=@@thread_cache_size;
SET GLOBAL thread_cache_size=3; SET GLOBAL thread_cache_size=3;
SHOW STATUS LIKE 'max_used_connections'; SHOW STATUS LIKE 'max_used_connections';
Variable_name Value Variable_name Value
Max_used_connections 3 Max_used_connections 4
FLUSH STATUS; FLUSH STATUS;
SHOW STATUS LIKE 'max_used_connections'; SHOW STATUS LIKE 'max_used_connections';
Variable_name Value Variable_name Value
Max_used_connections 2
SHOW STATUS LIKE 'max_used_connections';
Variable_name Value
Max_used_connections 3 Max_used_connections 3
SHOW STATUS LIKE 'max_used_connections'; SHOW STATUS LIKE 'max_used_connections';
Variable_name Value Variable_name Value
Max_used_connections 4 Max_used_connections 4
SHOW STATUS LIKE 'max_used_connections';
Variable_name Value
Max_used_connections 5
SET GLOBAL thread_cache_size=@save_thread_cache_size; SET GLOBAL thread_cache_size=@save_thread_cache_size;

View File

@@ -9,11 +9,10 @@
# Do not use any TAB characters for whitespace. # Do not use any TAB characters for whitespace.
# #
############################################################################## ##############################################################################
events_bugs : BUG#17619 2006-02-21 andrey Race conditions #events_bugs : BUG#17619 2006-02-21 andrey Race conditions
events_stress : 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 : 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_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
ndb_autodiscover : BUG#18952 2006-02-16 jmiller Needs to be fixed w.r.t binlog 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_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 #ndb_binlog_discover : BUG#19395 2006-04-28 tomas/knielsen mysqld does not always detect cluster shutdown

View File

@@ -15,11 +15,10 @@ CREATE EVENT e_x2 ON SCHEDULE EVERY 1 SECOND DO DROP TABLE x_table;
connection default; connection default;
SHOW DATABASES LIKE 'db_x'; SHOW DATABASES LIKE 'db_x';
SET GLOBAL event_scheduler=1; SET GLOBAL event_scheduler=1;
--sleep 2 --sleep 1.5
SHOW DATABASES LIKE 'db_x'; SHOW DATABASES LIKE 'db_x';
SHOW TABLES FROM db_x; SHOW TABLES FROM db_x;
SET GLOBAL event_scheduler=0; SET GLOBAL event_scheduler=2;
--sleep 1
connection priv_conn; connection priv_conn;
DROP EVENT e_x1; DROP EVENT e_x1;
DROP EVENT e_x2; DROP EVENT e_x2;
@@ -31,8 +30,7 @@ USE events_test;
# #
# END: BUG #17289 Events: missing privilege check for drop database # END: BUG #17289 Events: missing privilege check for drop database
# #
SET GLOBAL event_scheduler=0; SET GLOBAL event_scheduler=2;
--sleep 1
drop event if exists event1; 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; 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; 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" --echo "Let's check whether we can use non-qualified names"
create table non_qualif(a int); create table non_qualif(a int);
create event non_qualif_ev on schedule every 10 minute do insert into non_qualif values (800219); 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; select * from non_qualif;
drop event non_qualif_ev; drop event non_qualif_ev;
drop table non_qualif; drop table non_qualif;
set global event_scheduler = 0; set global event_scheduler = 2;
create table t_event3 (a int, b float); create table t_event3 (a int, b float);
drop event if exists event3; drop event if exists event3;
@@ -281,15 +279,15 @@ SHOW EVENTS;
--echo "This should show us only 3 events:"; --echo "This should show us only 3 events:";
--replace_column 8 # 9 # --replace_column 8 # 9 #
SHOW FULL EVENTS; SHOW EVENTS;
--echo "This should show us only 2 events:"; --echo "This should show us only 2 events:";
--replace_column 8 # 9 # --replace_column 8 # 9 #
SHOW FULL EVENTS LIKE 't%event'; SHOW EVENTS LIKE 't%event';
--echo "This should show us no events:"; --echo "This should show us no events:";
--replace_column 8 # 9 # --replace_column 8 # 9 #
SHOW FULL EVENTS FROM test LIKE '%'; SHOW EVENTS FROM test LIKE '%';
#ok, we are back #ok, we are back
connection default; connection default;
DROP DATABASE events_test2; DROP DATABASE events_test2;
@@ -300,7 +298,7 @@ SHOW EVENTS;
--echo "we should see 4 events now:"; --echo "we should see 4 events now:";
--replace_column 8 # 9 # --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; 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; connection ev_con1;
@@ -330,21 +328,21 @@ create event задачка on schedule every 123 minute starts now() ends now()
drop event задачка; drop event задачка;
# event_scheduler is a global var # event_scheduler is a global var
--error 1229 --error ER_GLOBAL_VARIABLE
set event_scheduler=0; set event_scheduler=2;
# event_scheduler could be only either 0 or 1 # event_scheduler could be only either 1 or 2
--error 1231 --error ER_WRONG_VALUE_FOR_VAR
set global event_scheduler=2; set global event_scheduler=3;
--echo "DISABLE the scheduler. Testing that it does not work when the variable is 0" --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 definer, name, db from mysql.event;
select get_lock("test_lock1", 20); select get_lock("test_lock1", 20);
create event закачка on schedule every 10 hour do 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" --echo "Should return 1 row"
select definer, name, db from mysql.event; 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 /*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"); select release_lock("test_lock1");
drop event закачка; 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" --echo "Let some time pass to the event starts"
--sleep 2 --sleep 2
--echo "Should have only 2 processes: the scheduler and the locked event" --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." --echo "Release the mutex, the event worker should finish."
select release_lock("test_lock2"); select release_lock("test_lock2");
drop event закачка; drop event закачка;
@@ -379,18 +377,11 @@ set global event_scheduler=1;
select get_lock("test_lock2_1", 20); select get_lock("test_lock2_1", 20);
create event закачка21 on schedule every 10 hour do 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 --sleep 1
--echo "Should see 1 process, locked on get_lock(" --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; 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=2;
set global event_scheduler=0; --echo "Should have only our process now:"
--sleep 1
--echo "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; 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; drop event закачка21;
#### ####
@@ -418,6 +409,7 @@ create event white_space on schedule every 10 hour disable do
select 2; 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';
select event_schema, event_name, definer, event_body from information_schema.events where event_name='white_space';
drop event white_space; drop event white_space;
create event white_space on schedule every 10 hour disable do select 3; 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'; 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 # END: BUG #17453: Creating Event crash the server
# #
##set global event_scheduler=1; #
# Bug#17403 "Events: packets out of order with show create event" # Bug#17403 "Events: packets out of order with show create event"
# #
create event e1 on schedule every 1 year do set @a = 5; 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); ##select get_lock("test_lock3", 20);
##create event закачка on schedule every 10 hour do select get_lock("test_lock3", 20); ##create event закачка on schedule every 10 hour do select get_lock("test_lock3", 20);
##select sleep(2); ##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 закачка; ##drop event закачка;
##select release_lock("test_lock3"); ##select release_lock("test_lock3");
@@ -450,14 +442,14 @@ drop event e1;
##select get_lock("test_lock4", 20); ##select get_lock("test_lock4", 20);
##create event закачка4 on schedule every 1 second do select get_lock("test_lock4", 20); ##create event закачка4 on schedule every 1 second do select get_lock("test_lock4", 20);
##select sleep(3); ##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; ##drop event закачка4;
##select release_lock("test_lock4"); ##select release_lock("test_lock4");
##set global event_scheduler=0; ##set global event_scheduler=2;
##select sleep(2); ##select sleep(2);
##--replace_column 1 # 6 # ##--replace_column 1 # 6 #
##show processlist;
##select count(*) from mysql.event; ##select count(*) from mysql.event;
drop database events_test; drop database events_test;

View File

@@ -30,13 +30,13 @@ set @a=3;
CREATE PROCEDURE p_16 () CREATE EVENT e_16 ON SCHEDULE EVERY @a SECOND DO SET @a=5; CREATE PROCEDURE p_16 () CREATE EVENT e_16 ON SCHEDULE EVERY @a SECOND DO SET @a=5;
call p_16(); call p_16();
--echo "Here we used to crash!" --echo "Here we used to crash!"
--error 1516 --error ER_EVENT_ALREADY_EXISTS
call p_16(); call p_16();
--error 1516 --error ER_EVENT_ALREADY_EXISTS
call p_16(); call p_16();
DROP EVENT e_16; DROP EVENT e_16;
CALL p_16(); CALL p_16();
--error 1516 --error ER_EVENT_ALREADY_EXISTS
CALL p_16(); CALL p_16();
DROP PROCEDURE p_16; DROP PROCEDURE p_16;
DROP EVENT e_16; DROP EVENT e_16;
@@ -47,9 +47,9 @@ DROP EVENT e_16;
# #
# Start - 16396: Events: Distant-future dates become past dates # 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; 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; create event e_55 on schedule every 10 hour starts 99990101000000 do drop table t;
--error ER_EVENT_ENDS_BEFORE_STARTS --error ER_EVENT_ENDS_BEFORE_STARTS
create event e_55 on schedule every 10 minute ends 99990101000000 do drop table t; 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 # 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" --echo "Wait a bit to settle down"
--sleep 1 --sleep 1
delete from mysql.event; delete from mysql.event;
@@ -79,7 +79,7 @@ delimiter ;|
--echo "Now if everything is fine the event has compiled and is locked --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 /*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'); 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; 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" --echo "Let's check whether we change the sql_mode on ALTER EVENT"
set sql_mode='traditional'; set sql_mode='traditional';
@@ -121,9 +121,9 @@ set global event_scheduler= 1;
--sleep 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 /*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'); 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; 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; select * from events_smode_test order by ev_name, a;
--echo "OK, last check before we drop them" --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; 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" --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 /*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'); select release_lock('ee_16407_5');
--sleep 3 --sleep 2
--echo "Should have 0 processes locked" --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 /*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; 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 event ee_16407_6;
drop procedure ee_16407_5_pendant; drop procedure ee_16407_5_pendant;
drop procedure ee_16407_6_pendant; drop procedure ee_16407_6_pendant;
set global event_scheduler= 0; set global event_scheduler= 2;
drop table events_smode_test; drop table events_smode_test;
set sql_mode=@old_sql_mode; set sql_mode=@old_sql_mode;
# #

View File

@@ -10,7 +10,7 @@ BEGIN
END| END|
delimiter ;| delimiter ;|
--echo "Check General Query Log" --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; create event log_general on schedule every 1 minute do SELect 'alabala', sleep(3) from dual;
TRUNCATE mysql.general_log; TRUNCATE mysql.general_log;
--echo "1 row, the current statement!" --echo "1 row, the current statement!"
@@ -22,7 +22,7 @@ SET GLOBAL event_scheduler=1;
call select_general_log(); call select_general_log();
DROP PROCEDURE select_general_log; DROP PROCEDURE select_general_log;
DROP EVENT log_general; DROP EVENT log_general;
SET GLOBAL event_scheduler=0; SET GLOBAL event_scheduler=2;
--sleep 1 --sleep 1
--echo "Check slow query log" --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; SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
--echo "Set new values" --echo "Set new values"
SET GLOBAL long_query_time=4; SET GLOBAL long_query_time=4;
SET SESSION long_query_time=2; SET SESSION long_query_time=1;
--echo "Check that logging is working" --echo "Check that logging is working"
SELECT SLEEP(3); SELECT SLEEP(2);
--replace_regex /00:00:0[3-5]/SLEEPVAL/ --replace_regex /00:00:0[2-4]/SLEEPVAL/
SELECT user_host, query_time, db, sql_text FROM mysql.slow_log; SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
TRUNCATE mysql.slow_log; TRUNCATE mysql.slow_log;
CREATE TABLE slow_event_test (slo_val tinyint, val tinyint); 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; SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
--echo "This should go to the slow log" --echo "This should go to the slow log"
SET SESSION long_query_time=10; SET SESSION long_query_time=10;
SET GLOBAL long_query_time=1;
DROP EVENT long_event; 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" --echo "Sleep some more time than the actual event run will take"
--sleep 7 --sleep 3
--echo "Check our table. Should see 2 rows" --echo "Check our table. Should see 2 rows"
SELECT * FROM slow_event_test; 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" --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[5-7]/SLEEPVAL/ --replace_regex /00:00:0[2-4]/SLEEPVAL/
SELECT user_host, query_time, db, sql_text FROM mysql.slow_log; SELECT user_host, query_time, db, sql_text FROM mysql.slow_log;
DROP EVENT long_event2; DROP EVENT long_event2;
SET GLOBAL long_query_time =@old_global_long_query_time; SET GLOBAL long_query_time =@old_global_long_query_time;

View File

@@ -1,55 +1,15 @@
create database if not exists events_test; create database if not exists events_test;
use events_test; use events_test;
--error 1235 --error ER_NOT_SUPPORTED_YET
CREATE EVENT micro_test ON SCHEDULE EVERY 100 MICROSECOND DO SELECT 1; 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; 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; 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; 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; 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; drop database events_test;

View File

@@ -15,7 +15,7 @@ CREATE EVENT start_n_end
DO INSERT INTO table_2 VALUES(1); DO INSERT INTO table_2 VALUES(1);
--sleep 5 --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 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 --sleep 5
SELECT IF(SUM(a) >= 4, 'OK', 'ERROR') FROM table_1; SELECT IF(SUM(a) >= 4, 'OK', 'ERROR') FROM table_1;
SELECT IF(SUM(a) >= 5, 'OK', 'ERROR') FROM table_2; 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." --echo "Already dropped because ended. Therefore an error."
--error ER_EVENT_DOES_NOT_EXIST --error ER_EVENT_DOES_NOT_EXIST
DROP EVENT only_one_time; DROP EVENT only_one_time;
--echo "Already dropped because ended. Therefore an error." --echo "Should be preserved"
--error ER_EVENT_DOES_NOT_EXIST SELECT EVENT_NAME, STATUS FROM INFORMATION_SCHEMA.EVENTS;
DROP EVENT two_time; DROP EVENT two_time;
DROP TABLE table_1; DROP TABLE table_1;
DROP TABLE table_2; DROP TABLE table_2;

View File

@@ -2,78 +2,124 @@ CREATE DATABASE IF NOT EXISTS events_test;
# #
# DROP DATABASE test start (bug #16406) # DROP DATABASE test start (bug #16406)
# #
CREATE DATABASE events_test2; CREATE DATABASE events_conn1_test2;
USE events_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= 50;
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= 50;
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_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_drop2 ON SCHEDULE EVERY 10 MINUTE DISABLE DO SELECT 1;
CREATE EVENT ev_drop3 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; USE events_test;
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2'; SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS;
DROP DATABASE events_test2; SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_conn1_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';
--echo "Now testing stability - dropping db -> events while they are running" --echo "Now testing stability - dropping db -> events while they are running"
CREATE DATABASE events_test2; CREATE DATABASE events_conn1_test2;
USE events_test2; USE events_conn1_test2;
--disable_query_log --disable_query_log
let $1= 1000; let $1= 50;
while ($1) 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; dec $1;
} }
--enable_query_log --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; 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 --sleep 6
DROP DATABASE events_test2; DROP DATABASE events_conn1_test2;
SET GLOBAL event_scheduler=0;
DROP DATABASE events_test3; 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= 50;
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; 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= 50;
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= 50;
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; SET GLOBAL event_scheduler=1;
connection conn2;
reap;
disconnect conn2;
connection conn3;
reap;
disconnect conn3;
connection default;
USE events_test; USE events_test;
DROP TABLE fill_it;
--disable_query_log
DROP USER event_user2@localhost;
DROP USER event_user3@localhost;
--enable_query_log
# #
# DROP DATABASE test end (bug #16406) # DROP DATABASE test end (bug #16406)
# #

View File

@@ -0,0 +1,68 @@
###########################################################################
#
# Tests for user-management command-line options.
#
###########################################################################
--source include/im_check_os.inc
###########################################################################
# List users so we are sure about starting conditions.
--echo --> Listing users...
--exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --list-users 2>&1 >/dev/null
--echo
# Add a new user.
--echo ==> Adding user 'testuser'...
--exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --add-user --username=testuser --password=abc 2>&1 >/dev/null
--echo
--echo --> IM password file:
--exec cat $IM_PASSWORD_PATH
--echo --> EOF
--echo
--echo --> Printing out line for 'testuser'...
--exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --passwd --username=testuser --password=abc | tail -1
--echo
--echo --> Listing users...
--exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --list-users 2>&1 >/dev/null
--echo
# Edit user's attributes.
--echo ==> Changing the password of 'testuser'...
--exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --edit-user --username=testuser --password=xyz 2>&1 >/dev/null
--echo
--echo --> IM password file:
--exec cat $IM_PASSWORD_PATH
--echo --> EOF
--echo
--echo --> Printing out line for 'testuser'...
--exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --passwd --username=testuser --password=xyz | tail -1
--echo
--echo --> Listing users...
--exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --list-users 2>&1 >/dev/null
--echo
# Drop user.
--echo ==> Dropping user 'testuser'...
--exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --drop-user --username=testuser 2>&1 >/dev/null
--echo
--echo --> IM password file:
--exec cat $IM_PASSWORD_PATH
--echo --> EOF
--echo
--echo --> Listing users...
--exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --list-users 2>&1 >/dev/null
--echo

View File

@@ -1,2 +1,3 @@
--run-as-service --run-as-service
--log=$MYSQLTEST_VARDIR/log/im.log --log=$MYSQLTEST_VARDIR/log/im.log
--monitoring-interval=1

View File

@@ -10,6 +10,9 @@
########################################################################### ###########################################################################
--sleep 3
# should be longer than monitoring interval and enough to start instance.
SHOW INSTANCES; SHOW INSTANCES;
--exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_PATH_PID restarted --exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_PATH_PID restarted

View File

@@ -0,0 +1 @@
--monitoring-interval=1

View File

@@ -0,0 +1,228 @@
###########################################################################
#
# This test suite checks the following statements:
# - CREATE INSTANCE <instance_name> [option1[=option1_value], ...];
# - DROP INSTANCE <instance_name>;
#
# For CREATE INSTANCE we check that:
# - CREATE INSTANCE succeeds for non-existing instance;
# - CREATE INSTANCE fails for existing instance;
# - CREATE INSTANCE can get additional options with and w/o values;
# - CREATE INSTANCE parses options and handles grammar errors correctly.
# Check that strings with spaces are handled correctly, unknown (for
# mysqld) options should also be handled;
# - CREATE INSTANCE updates both config file and internal configuration cache;
# - CREATE INSTANCE allows to create instances only with properly formed
# names (mysqld*);
#
# For DROP INSTANCE we check that:
# - DROP INSTANCE succeeds for existing instance;
# - DROP INSTANCE fails for non-existing instance;
# - DROP INSTANCE fails for active instance.
# - DROP INSTANCE updates both config file and internal configuration cache;
#
###########################################################################
--source include/im_check_os.inc
###########################################################################
#
# Check starting conditions.
#
###########################################################################
# Check that the configuration file contains only instances that we expect.
--echo --------------------------------------------------------------------
--exec grep server_id $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
# Check that mysqld1 is reported as running.
--sleep 3
# should be longer than monitoring interval and enough to start instance.
SHOW INSTANCES;
# Check that the expected mysqld instance is actually run (check that we can
# connect and execute something).
--echo
--echo ---> connection: mysql1_con
--connect (mysql1_con,localhost,root,,mysql,$IM_MYSQLD1_PORT,$IM_MYSQLD1_SOCK)
--connection mysql1_con
SHOW VARIABLES LIKE 'server_id';
--disconnect mysql1_con
--echo
--echo ---> connection: default
--connection default
###########################################################################
#
# CREATE INSTANCE tests.
#
###########################################################################
# Check that CREATE INSTANCE succeeds for non-existing instance and also check
# that both config file and internal configuration cache have been updated.
CREATE INSTANCE mysqld3;
SHOW INSTANCES;
--echo --------------------------------------------------------------------
--exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
--echo --------------------------------------------------------------------
# Check that CREATE INSTANCE fails for existing instance. Let's all three
# existing instances (running one, stopped one and just created one). Just in
# case...
--error 3012 # ER_CREATE_EXISTING_INSTANCE
CREATE INSTANCE mysqld1;
--error 3012 # ER_CREATE_EXISTING_INSTANCE
CREATE INSTANCE mysqld2;
--error 3012 # ER_CREATE_EXISTING_INSTANCE
CREATE INSTANCE mysqld3;
# Check that CREATE INSTANCE can get additional options with and w/o values.
# Ensure that config file is updated properly.
# - without values;
--echo --------------------------------------------------------------------
--exec grep nonguarded $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
CREATE INSTANCE mysqld4 nonguarded;
SHOW INSTANCES;
--echo --------------------------------------------------------------------
--exec grep nonguarded $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
# - with value;
--echo --------------------------------------------------------------------
--exec grep test-A $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
--exec grep test-B $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
CREATE INSTANCE mysqld5 test-A = 000, test-B = test;
SHOW INSTANCES;
--echo --------------------------------------------------------------------
--exec grep test-A $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
--exec grep test-B $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
# Check that CREATE INSTANCE parses options and handles grammar errors
# correctly. Check that strings with spaces are handled correctly,
# unknown (for mysqld) options should also be handled.
# - check handling of extra spaces;
--echo --------------------------------------------------------------------
--exec grep test-C $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
CREATE INSTANCE mysqld6 test-C1 = 10 , test-C2 = 02 ;
SHOW INSTANCES;
--echo --------------------------------------------------------------------
--exec grep test-C1 $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
--exec grep test-C2 $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
# - check handling of grammar error;
--echo --------------------------------------------------------------------
--exec grep test-D $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
--exec grep test-E $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
--error ER_SYNTAX_ERROR
CREATE INSTANCE mysqld7 test-D = test-D-value ;
SHOW INSTANCES;
--error ER_SYNTAX_ERROR
CREATE INSTANCE mysqld8 test-E 0 ;
SHOW INSTANCES;
--error ER_SYNTAX_ERROR
CREATE INSTANCE mysqld8 test-F = ;
SHOW INSTANCES;
--echo --------------------------------------------------------------------
--exec grep test-D $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
--exec grep test-E $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
# - check parsing of string option values
--echo --------------------------------------------------------------------
--exec grep test-1 $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
--exec grep test-2 $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
--exec grep test-3 $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
--exec grep test-4 $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
CREATE INSTANCE mysqld9 test-1=" hello world ", test-2=' ';
SHOW INSTANCES;
CREATE INSTANCE mysqld9a test-3='\b\babc\sdef';
# test-3='abc def'
SHOW INSTANCES;
CREATE INSTANCE mysqld9b test-4='abc\tdef', test-5='abc\ndef';
SHOW INSTANCES;
CREATE INSTANCE mysqld9c test-6="abc\rdef", test-7="abc\\def";
# test-6=abc
SHOW INSTANCES;
--error ER_SYNTAX_ERROR
CREATE INSTANCE mysqld10 test-bad=' \ ';
SHOW INSTANCES;
--echo --------------------------------------------------------------------
--exec grep test-1 $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
--exec grep test-2 $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
--exec grep test-3 $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
--exec grep test-4 $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
--exec grep test-5 $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
--exec grep test-6 $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
--exec grep test-7 $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
--exec grep test-bad $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
# Check that CREATE INSTANCE allows to create instances only with properly
# formed names (mysqld*).
--error 3014 # ER_MALFORMED_INSTANCE_NAME
CREATE INSTANCE qqq1;

View File

@@ -0,0 +1 @@
--monitoring-interval=1

View File

@@ -17,11 +17,15 @@
# #
########################################################################### ###########################################################################
--echo
--echo --------------------------------------------------------------------
--echo -- 1.1.1.
--echo --------------------------------------------------------------------
--sleep 3
# should be longer than monitoring interval and enough to start instance.
SHOW INSTANCES; SHOW INSTANCES;
--replace_column 3 VERSION_NUMBER 4 VERSION
SHOW INSTANCE STATUS mysqld1;
--replace_column 3 VERSION_NUMBER 4 VERSION
SHOW INSTANCE STATUS mysqld2;
########################################################################### ###########################################################################
# #
@@ -33,20 +37,22 @@ SHOW INSTANCE STATUS mysqld2;
# #
########################################################################### ###########################################################################
--echo
--echo --------------------------------------------------------------------
--echo -- 1.1.2.
--echo --------------------------------------------------------------------
START INSTANCE mysqld2; START INSTANCE mysqld2;
# FIXME # FIXME: START INSTANCE should be synchronous.
--sleep 3 --sleep 3
# should be longer than monitoring interval and enough to start instance.
SHOW INSTANCES; SHOW INSTANCES;
--replace_column 3 VERSION_NUMBER 4 VERSION
SHOW INSTANCE STATUS mysqld1;
--replace_column 3 VERSION_NUMBER 4 VERSION
SHOW INSTANCE STATUS mysqld2;
--connect (mysql_con,localhost,root,,mysql,$IM_MYSQLD1_PORT,$IM_MYSQLD1_SOCK) --connect (mysql_con,localhost,root,,mysql,$IM_MYSQLD2_PORT,$IM_MYSQLD2_SOCK)
--connection mysql_con --connection mysql_con
--replace_result $IM_MYSQLD1_PORT IM_MYSQLD1_PORT --replace_result $IM_MYSQLD2_PORT IM_MYSQLD2_PORT
SHOW VARIABLES LIKE 'port'; SHOW VARIABLES LIKE 'port';
--connection default --connection default
@@ -61,9 +67,15 @@ SHOW VARIABLES LIKE 'port';
# #
########################################################################### ###########################################################################
--echo
--echo --------------------------------------------------------------------
--echo -- 1.1.3.
--echo --------------------------------------------------------------------
STOP INSTANCE mysqld2; STOP INSTANCE mysqld2;
# FIXME # FIXME: STOP INSTANCE should be synchronous.
--sleep 3 --sleep 3
# should be longer than monitoring interval and enough to stop instance.
SHOW INSTANCES; SHOW INSTANCES;
--replace_column 3 VERSION_NUMBER 4 VERSION --replace_column 3 VERSION_NUMBER 4 VERSION
@@ -81,16 +93,17 @@ SHOW INSTANCE STATUS mysqld2;
# #
########################################################################### ###########################################################################
--error 3000 --echo
--echo --------------------------------------------------------------------
--echo -- 1.1.4.
--echo --------------------------------------------------------------------
--error 3000 # ER_BAD_INSTANCE_NAME
START INSTANCE mysqld3; START INSTANCE mysqld3;
--error 3002 --error 3002 # ER_INSTANCE_ALREADY_STARTED
START INSTANCE mysqld1; START INSTANCE mysqld1;
# FIXME TODO
# BUG#12813: START/STOP INSTANCE commands accept a list as argument
# START INSTANCE mysqld1, mysqld2;
########################################################################### ###########################################################################
# #
# 1.1.5. Check that Instance Manager reports correct errors for 'STOP INSTANCE' # 1.1.5. Check that Instance Manager reports correct errors for 'STOP INSTANCE'
@@ -101,39 +114,54 @@ START INSTANCE mysqld1;
# #
########################################################################### ###########################################################################
--error 3000 --echo
--echo --------------------------------------------------------------------
--echo -- 1.1.5.
--echo --------------------------------------------------------------------
--error 3000 # ER_BAD_INSTANCE_NAME
STOP INSTANCE mysqld3; STOP INSTANCE mysqld3;
# TODO: IM should be fixed. # TODO: IM should be fixed.
# BUG#12673: Instance Manager allows to stop the instance many times # BUG#12673: Instance Manager allows to stop the instance many times
# --error 3002 # --error 3002 # ER_INSTANCE_ALREADY_STARTED
# STOP INSTANCE mysqld2; # STOP INSTANCE mysqld2;
# FIXME TODO
# BUG#12813: START/STOP INSTANCE commands accept a list as argument
# STOP INSTANCE mysqld1, mysqld2;
########################################################################### ###########################################################################
# #
# 1.1.6. Check that Instance Manager is able to restart guarded instances. # 1.1.6. Check that Instance Manager is able to restart guarded instances.
# #
########################################################################### ###########################################################################
--echo
--echo --------------------------------------------------------------------
--echo -- 1.1.6.
--echo --------------------------------------------------------------------
SHOW INSTANCES; SHOW INSTANCES;
--exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_MYSQLD1_PATH_PID restarted --exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_MYSQLD1_PATH_PID restarted
--sleep 3
# should be longer than monitoring interval and enough to start instance.
########################################################################### ###########################################################################
# #
# 1.1.7. Check that Instance Manager does not restart non-guarded instance. # 1.1.7. Check that Instance Manager does not restart non-guarded instance.
# #
########################################################################### ###########################################################################
--echo
--echo --------------------------------------------------------------------
--echo -- 1.1.7.
--echo --------------------------------------------------------------------
SHOW INSTANCES; SHOW INSTANCES;
START INSTANCE mysqld2; START INSTANCE mysqld2;
# FIXME # FIXME: START INSTANCE should be synchronous.
--sleep 3 --sleep 3
# should be longer than monitoring interval and enough to start instance.
SHOW INSTANCES; SHOW INSTANCES;
@@ -147,7 +175,13 @@ SHOW INSTANCES;
# incomplete SHOW INSTANCE STATUS command. # incomplete SHOW INSTANCE STATUS command.
# #
########################################################################### ###########################################################################
--error 1149
--echo
--echo --------------------------------------------------------------------
--echo -- 1.1.8.
--echo --------------------------------------------------------------------
--error ER_SYNTAX_ERROR
SHOW INSTANCE STATUS; SHOW INSTANCE STATUS;
# #
@@ -159,8 +193,13 @@ SHOW INSTANCE STATUS;
# a list as argument. # a list as argument.
# #
--error 1149 --echo
--echo --------------------------------------------------------------------
--echo -- BUG#12813
--echo --------------------------------------------------------------------
--error ER_SYNTAX_ERROR
START INSTANCE mysqld1,mysqld2,mysqld3; START INSTANCE mysqld1,mysqld2,mysqld3;
--error 1149 --error ER_SYNTAX_ERROR
STOP INSTANCE mysqld1,mysqld2,mysqld3; STOP INSTANCE mysqld1,mysqld2,mysqld3;

View File

@@ -0,0 +1,268 @@
###########################################################################
#
# This test suite checks the following statements:
# - SET <instance id>.<option name> = <option value>;
# - UNSET <instance id>.<option name> = <option value>;
# - FLUSH INSTANCES;
#
# For SET/UNSET we check that:
# - SET ignores spaces correctly;
# - UNSET does not allow option-value part (= <option value>);
# - SET/UNSET can be applied several times w/o error;
# - SET/UNSET is allowed only for stopped instances;
# - SET/UNSET updates both the configuration cache in IM and
# the configuration file;
#
# For FLUSH INSTANCES we check that:
# - FLUSH INSTANCES is allowed only when all instances are stopped;
#
# According to the IM implementation details, we should play at least with the
# following options:
# - server_id
# - port
# - nonguarded
# Let's test SET statement on the option 'server_id'. It's expected that
# originally the instances have the following server ids and states:
# - mysqld1: server_id: 1; running (online)
# - mysqld2: server_id: 2; stopped (offline)
#
###########################################################################
--source include/im_check_os.inc
###########################################################################
#
# Check starting conditions.
#
###########################################################################
# - check the configuration file;
--echo --------------------------------------------------------------------
--exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
--echo --------------------------------------------------------------------
# - check the running instances.
--connect (mysql1_con,localhost,root,,mysql,$IM_MYSQLD1_PORT,$IM_MYSQLD1_SOCK)
--connection mysql1_con
SHOW VARIABLES LIKE 'server_id';
--connection default
# - check the internal cache.
SHOW INSTANCES;
###########################################################################
#
# Check that SET/UNSET is allowed only for stopped instances.
#
###########################################################################
# - check that SET/UNSET is denied for running instances;
--error 3015 # ER_INSTANCE_IS_ACTIVE
UNSET mysqld1.server_id;
--error 3015 # ER_INSTANCE_IS_ACTIVE
SET mysqld1.server_id = 11;
# - check that SET/UNSET is denied for active instances:
# - create dummy misconfigured instance;
# - start it;
# - try to set/unset options;
CREATE INSTANCE mysqld3 datadir = '/';
START INSTANCE mysqld3;
# FIXME: START INSTANCE should be synchronous.
--sleep 3
# should be longer than monitoring interval and enough to start instance.
# NOTE: We can not analyze state of the instance here -- it can be Failed or
# Starting because Instance Manager is trying to start the misconfigured
# instance several times.
--error 3015 # ER_INSTANCE_IS_ACTIVE
UNSET mysqld3.server_id;
--error 3015 # ER_INSTANCE_IS_ACTIVE
SET mysqld3.server_id = 11;
STOP INSTANCE mysqld3;
# FIXME: STOP INSTANCE should be synchronous.
--sleep 3
# should be longer than monitoring interval and enough to stop instance.
--replace_column 3 VERSION_NUMBER 4 VERSION
SHOW INSTANCE STATUS mysqld3;
# - check that SET/UNSET succeed for stopped instances;
# - check that SET/UNSET can be applied multiple times;
UNSET mysqld2.server_id;
UNSET mysqld2.server_id;
--replace_column 2 option_value
SHOW INSTANCE OPTIONS mysqld2;
SET mysqld2.server_id = 2;
SET mysqld2.server_id = 2;
--replace_column 2 option_value
SHOW INSTANCE OPTIONS mysqld2;
# - check that UNSET does not allow option-value part (= <option value>);
--error ER_SYNTAX_ERROR
UNSET mysqld2.server_id = 11;
# - check that SET/UNSET working properly with multiple options;
SET mysqld2.aaa, mysqld3.bbb, mysqld2.ccc = 0010, mysqld3.ddd = 0020;
--echo --------------------------------------------------------------------
--exec grep aaa $MYSQLTEST_VARDIR/im.cnf ;
--echo --------------------------------------------------------------------
--exec grep bbb $MYSQLTEST_VARDIR/im.cnf ;
--echo --------------------------------------------------------------------
--exec grep ccc $MYSQLTEST_VARDIR/im.cnf ;
--echo --------------------------------------------------------------------
--exec grep ddd $MYSQLTEST_VARDIR/im.cnf ;
--echo --------------------------------------------------------------------
UNSET mysqld2.aaa, mysqld3.bbb, mysqld2.ccc, mysqld3.ddd;
--echo --------------------------------------------------------------------
--exec grep aaa $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
--exec grep bbb $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
--exec grep ccc $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
--exec grep ddd $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
# - check that if some instance name is invalid or the active is active,
# whole SET-statement will not be executed;
--error 3000 # ER_BAD_INSTANCE_NAME
SET mysqld2.aaa, mysqld3.bbb, mysqld.ccc = 0010;
--echo --------------------------------------------------------------------
--exec grep aaa $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
--exec grep bbb $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
--exec grep ccc $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
--error 3015 # ER_INSTANCE_IS_ACTIVE
SET mysqld2.aaa, mysqld3.bbb, mysqld1.ccc = 0010;
--echo --------------------------------------------------------------------
--exec grep aaa $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
--exec grep bbb $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
--exec grep ccc $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
# - check that if some instance name is invalid or the active is active,
# whole UNSET-statement will not be executed;
--error 3000 # ER_BAD_INSTANCE_NAME
UNSET mysqld2.server_id, mysqld3.server_id, mysqld.ccc;
--echo --------------------------------------------------------------------
--exec grep server_id $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
--error 3015 # ER_INSTANCE_IS_ACTIVE
UNSET mysqld2.server_id, mysqld3.server_id, mysqld1.ccc;
--echo --------------------------------------------------------------------
--exec grep server_id $MYSQLTEST_VARDIR/im.cnf;
--echo --------------------------------------------------------------------
DROP INSTANCE mysqld3;
# - check that spaces are handled correctly;
SET mysqld2.server_id=222;
SET mysqld2.server_id = 222;
SET mysqld2.server_id = 222 ;
SET mysqld2 . server_id = 222 ;
SET mysqld2 . server_id = 222 , mysqld2 . aaa , mysqld2 . bbb ;
--echo --------------------------------------------------------------------
--exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
--echo --------------------------------------------------------------------
--exec grep aaa $MYSQLTEST_VARDIR/im.cnf ;
--echo --------------------------------------------------------------------
--exec grep bbb $MYSQLTEST_VARDIR/im.cnf ;
--echo --------------------------------------------------------------------
UNSET mysqld2 . aaa , mysqld2 . bbb ;
--echo --------------------------------------------------------------------
--exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
--echo --------------------------------------------------------------------
--exec grep aaa $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
--exec grep bbb $MYSQLTEST_VARDIR/im.cnf || true;
--echo --------------------------------------------------------------------
###########################################################################
#
# Check that SET/UNSET updates both the configuration cache in IM and
# the configuration file.
#
###########################################################################
# - check that the configuration file has been updated (i.e. contains
# server_id=SERVER_ID for mysqld2);
--echo --------------------------------------------------------------------
--exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
--echo --------------------------------------------------------------------
# - (for mysqld1) check that the running instance has not been affected:
# connect to the instance and check that 'SHOW VARIABLES LIKE 'server_id''
# returns zero;
--connection mysql1_con
SHOW VARIABLES LIKE 'server_id';
--connection default
# - check that internal cache of Instance Manager has been affected;
# TODO: we should check only server_id option here.
# SHOW INSTANCE OPTIONS mysqld2;
###########################################################################
#
# Check that FLUSH INSTANCES is allowed only when all instances are stopped.
#
###########################################################################
SHOW INSTANCES;
--error 3016 # ER_THERE_IS_ACTIVE_INSTACE
FLUSH INSTANCES;
STOP INSTANCE mysqld1;
# FIXME: STOP INSTANCE should be synchronous.
--sleep 3
# should be longer than monitoring interval and enough to stop instance.
SHOW INSTANCES;
FLUSH INSTANCES;

View File

@@ -1,142 +0,0 @@
###########################################################################
#
# This file contains test for (3) test suite.
#
# Consult WL#2789 for more information.
#
###########################################################################
#
# Check the options-management commands:
# - SET;
# - FLUSH INSTANCES;
#
# Let's test the commands on the option 'server_id'. It's expected that
# originally the instances have the following server ids:
# - mysqld1: 1
# - mysqld2: 2
#
# 1. SET <instance_id>.server_id= SERVER_ID); where SERVER_ID is 11 or 12.
# 1.1. check that the configuration file has been updated (i.e. contains
# server_id=SERVER_ID for the instance);
# 1.2. (for mysqld1) check that the running instance has not been affected:
# connect to the instance and check that 'SHOW VARIABLES LIKE 'server_id''
# returns zero;
# 1.3. check that internal cache of Instance Manager has not been affected
# (i.e. SHOW INSTANCE OPTIONS <instance> does not contain updated value).
#
# 2. FLUSH INSTANCES;
# 2.1. check that the configuration file has not been updated;
# 2.2. (for mysqld1) check that the running instance has not been affected:
# connect to the instance and check that 'SHOW VARIABLES LIKE 'server_id''
# returns zero value;
# 2.3. check that internal cache of Instance Manager has been updated (i.e.
# SHOW INSTANCE OPTIONS <instance> contains 'server_id=SERVER_ID' line).
#
# 3. Restore options.
#
###########################################################################
--source include/im_check_os.inc
###########################################################################
#
# 0. Check starting conditions.
#
###########################################################################
# - check the configuration file;
--exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
# - check the running instances.
--connect (mysql1_con,localhost,root,,mysql,$IM_MYSQLD1_PORT,$IM_MYSQLD1_SOCK)
--connection mysql1_con
SHOW VARIABLES LIKE 'server_id';
--connection default
# - check the internal cache.
# TODO: we should check only server_id option here.
# SHOW INSTANCE OPTIONS mysqld1;
# SHOW INSTANCE OPTIONS mysqld2;
###########################################################################
#
# 1. SET <instance_id>.server_id= SERVER_ID); where SERVER_ID is 11 or 12.
#
###########################################################################
# * mysqld1
SET mysqld1.server_id = 11;
# - check that the configuration file has been updated (i.e. contains
# server_id=SERVER_ID for the instance);
--exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
# - (for mysqld1) check that the running instance has not been affected:
# connect to the instance and check that 'SHOW VARIABLES LIKE 'server_id''
# returns zero;
--connection mysql1_con
SHOW VARIABLES LIKE 'server_id';
--connection default
# - check that internal cache of Instance Manager has not been affected
# (i.e. SHOW INSTANCE OPTIONS <instance> does not contain updated value).
# TODO: we should check only server_id option here.
# SHOW INSTANCE OPTIONS mysqld1;
# * mysqld2
SET mysqld2.server_id = 12;
# - check that the configuration file has been updated (i.e. contains
# server_id=SERVER_ID for the instance);
--exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
# - check that internal cache of Instance Manager has not been affected
# (i.e. SHOW INSTANCE OPTIONS <instance> does not contain updated value).
# TODO: we should check only server_id option here.
# SHOW INSTANCE OPTIONS mysqld2;
###########################################################################
#
# 2. FLUSH INSTANCES;
#
###########################################################################
FLUSH INSTANCES;
# - check that the configuration file has not been updated;
--exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
# - (for mysqld1) check that the running instance has not been affected:
# connect to the instance and check that 'SHOW VARIABLES LIKE 'server_id''
# returns zero value;
--connection mysql1_con
SHOW VARIABLES LIKE 'server_id';
--connection default
# - check that internal cache of Instance Manager has been updated (i.e.
# SHOW INSTANCE OPTIONS <instance> contains 'server_id=' line).
# TODO: we should check only server_id option here.
# SHOW INSTANCE OPTIONS mysqld1;
# SHOW INSTANCE OPTIONS mysqld2;

View File

@@ -1,150 +0,0 @@
###########################################################################
#
# This file contains test for (3) test suite.
#
# Consult WL#2789 for more information.
#
###########################################################################
#
# Check the options-management commands:
# - UNSET;
# - FLUSH INSTANCES;
#
# Let's test the commands on the option 'server_id'. It's expected that
# originally the instances have the following server ids:
# - mysqld1: 1
# - mysqld2: 2
#
# The test case:
#
# 1. UNSET <instance_id>.server_id;
#
# Do the step for both instances.
#
# 1.1. check that the configuration file has been updated (i.e. does not
# contain 'server_id=' line for the instance);
# 1.2. (for mysqld1) check that the running instance has not been affected:
# connect to the instance and check that 'SHOW VARIABLES LIKE 'server_id''
# returns non-zero value;
# 1.3. check that internal cache of Instance Manager is not affected (i.e.
# SHOW INSTANCE OPTIONS <instance> contains non-zero value for server_id);
#
# 2. FLUSH INSTANCES;
#
# Do the step for both instances.
#
# 2.1. check that the configuration file has not been updated (i.e. does not
# contain 'server_id=' for the instance);
# 2.2. (for mysqld1) check that the running instance has not been affected:
# connect to the instance and check that 'SHOW VARIABLES LIKE 'server_id''
# returns non-zero value;
# 2.3. check that internal cache of Instance Manager has been updated (i.e.
# SHOW INSTANCE OPTIONS <instance> does not contain 'server_id=' line).
#
###########################################################################
--source include/im_check_os.inc
###########################################################################
#
# 0. Check starting conditions.
#
###########################################################################
# - check the configuration file;
--exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
# - check the running instances.
--connect (mysql1_con,localhost,root,,mysql,$IM_MYSQLD1_PORT,$IM_MYSQLD1_SOCK)
--connection mysql1_con
SHOW VARIABLES LIKE 'server_id';
--connection default
# - check the internal cache.
# TODO: we should check only server_id option here.
# SHOW INSTANCE OPTIONS mysqld1;
# SHOW INSTANCE OPTIONS mysqld2;
###########################################################################
#
# 1. UNSET <instance_id>.server_id;
#
###########################################################################
# * mysqld1
UNSET mysqld1.server_id;
# - check that the configuration file has been updated (i.e. does not
# contain 'server_id=' line for the instance);
--exec grep server_id $MYSQLTEST_VARDIR/im.cnf ;
# - check that the running instance has not been affected: connect to the
# instance and check that 'SHOW VARIABLES LIKE 'server_id'' returns non-zero
# value;
--connection mysql1_con
SHOW VARIABLES LIKE 'server_id';
--connection default
# - check that internal cache of Instance Manager is not affected (i.e. SHOW
# INSTANCE OPTIONS <instance> contains non-zero value for server_id);
# TODO: we should check only server_id option here.
# SHOW INSTANCE OPTIONS mysqld1;
# * mysqld2
UNSET mysqld2.server_id;
# - check that the configuration file has been updated (i.e. does not
# contain 'server_id=' line for the instance);
--exec grep server_id $MYSQLTEST_VARDIR/im.cnf || true;
# - check that internal cache of Instance Manager is not affected (i.e. SHOW
# INSTANCE OPTIONS <instance> contains non-zero value for server_id);
# TODO: we should check only server_id option here.
# SHOW INSTANCE OPTIONS mysqld2;
###########################################################################
#
# 2. FLUSH INSTANCES;
#
###########################################################################
FLUSH INSTANCES;
# - check that the configuration file has not been updated (i.e. does not
# contain 'server_id=' for the instance);
--exec grep server_id $MYSQLTEST_VARDIR/im.cnf || true;
# - (for mysqld1) check that the running instance has not been affected:
# connect to the instance and check that 'SHOW VARIABLES LIKE 'server_id''
# returns non-zero value;
--connection mysql1_con
SHOW VARIABLES LIKE 'server_id';
--connection default
# - check that internal cache of Instance Manager has been updated (i.e.
# SHOW INSTANCE OPTIONS <instance> does not contain 'server_id=' line).
# TODO: we should check only server_id option here.
# SHOW INSTANCE OPTIONS mysqld1;
# SHOW INSTANCE OPTIONS mysqld2;

View File

@@ -0,0 +1 @@
--monitoring-interval=1

View File

@@ -17,6 +17,9 @@
# - the second instance is offline; # - the second instance is offline;
# #
--sleep 3
# should be longer than monitoring interval and enough to start instance.
SHOW INSTANCES; SHOW INSTANCES;
# #
@@ -41,8 +44,9 @@ SHOW INSTANCE OPTIONS mysqld2;
START INSTANCE mysqld2; START INSTANCE mysqld2;
# FIXME # FIXME: START INSTANCE should be synchronous.
-- sleep 3 --sleep 3
# should be longer than monitoring interval and enough to start instance.
STOP INSTANCE mysqld2; STOP INSTANCE mysqld2;

View File

@@ -16,7 +16,7 @@ use mysql;
# #
truncate table general_log; truncate table general_log;
--replace_column 1 TIMESTAMP --replace_column 1 TIMESTAMP 3 THREAD_ID
select * from general_log; select * from general_log;
truncate table slow_log; truncate table slow_log;
--replace_column 1 TIMESTAMP --replace_column 1 TIMESTAMP
@@ -31,7 +31,7 @@ select * from slow_log;
# #
truncate table general_log; truncate table general_log;
--replace_column 1 TIMESTAMP --replace_column 1 TIMESTAMP 3 THREAD_ID
select * from general_log where argument like '%general_log%'; select * from general_log where argument like '%general_log%';
@@ -156,7 +156,7 @@ truncate table mysql.general_log;
set names utf8; set names utf8;
create table bug16905 (s char(15) character set utf8 default 'пусто'); create table bug16905 (s char(15) character set utf8 default 'пусто');
insert into bug16905 values ('новое'); insert into bug16905 values ('новое');
--replace_column 1 TIMESTAMP --replace_column 1 TIMESTAMP 3 THREAD_ID
select * from mysql.general_log; select * from mysql.general_log;
drop table bug16905; drop table bug16905;

View File

@@ -244,7 +244,8 @@ err:
handle_option_ctx structure. handle_option_ctx structure.
group_name The name of the group the option belongs to. group_name The name of the group the option belongs to.
option The very option to be processed. It is already option The very option to be processed. It is already
prepared to be used in argv (has -- prefix) prepared to be used in argv (has -- prefix). If it
is NULL, we are handling a new group (section).
DESCRIPTION DESCRIPTION
This handler checks whether a group is one of the listed and adds an option This handler checks whether a group is one of the listed and adds an option
@@ -263,6 +264,9 @@ static int handle_default_option(void *in_ctx, const char *group_name,
char *tmp; char *tmp;
struct handle_option_ctx *ctx= (struct handle_option_ctx *) in_ctx; struct handle_option_ctx *ctx= (struct handle_option_ctx *) in_ctx;
if (!option)
return 0;
if (find_type((char *)group_name, ctx->group, 3)) if (find_type((char *)group_name, ctx->group, 3))
{ {
if (!(tmp= alloc_root(ctx->alloc, (uint) strlen(option) + 1))) if (!(tmp= alloc_root(ctx->alloc, (uint) strlen(option) + 1)))
@@ -719,6 +723,10 @@ static int search_default_file_with_ext(Process_option_func opt_handler,
end[0]=0; end[0]=0;
strnmov(curr_gr, ptr, min((uint) (end-ptr)+1, 4096)); strnmov(curr_gr, ptr, min((uint) (end-ptr)+1, 4096));
/* signal that a new group is found */
opt_handler(handler_ctx, curr_gr, NULL);
continue; continue;
} }
if (!found_group) if (!found_group)

View File

@@ -40,11 +40,13 @@ static char *add_option(char *dst, const char *option_value,
SYNOPSYS SYNOPSYS
modify_defaults_file() modify_defaults_file()
file_location The location of configuration file to edit file_location The location of configuration file to edit
option option to look for option The name of the option to look for (can be NULL)
option value The value of the option we would like to set option value The value of the option we would like to set (can be NULL)
section_name the name of the section section_name The name of the section (must be NOT NULL)
remove_option This is true if we want to remove the option. remove_option This defines what we want to remove:
False otherwise. - MY_REMOVE_NONE -- nothing to remove;
- MY_REMOVE_OPTION -- remove the specified option;
- MY_REMOVE_SECTION -- remove the specified section;
IMPLEMENTATION IMPLEMENTATION
We open the option file first, then read the file line-by-line, We open the option file first, then read the file line-by-line,
looking for the section we need. At the same time we put these lines looking for the section we need. At the same time we put these lines
@@ -67,7 +69,9 @@ int modify_defaults_file(const char *file_location, const char *option,
FILE *cnf_file; FILE *cnf_file;
MY_STAT file_stat; MY_STAT file_stat;
char linebuff[BUFF_SIZE], *src_ptr, *dst_ptr, *file_buffer; char linebuff[BUFF_SIZE], *src_ptr, *dst_ptr, *file_buffer;
uint opt_len, optval_len, sect_len, nr_newlines= 0, buffer_size; uint opt_len= 0;
uint optval_len= 0;
uint sect_len, nr_newlines= 0, buffer_size;
my_bool in_section= FALSE, opt_applied= 0; my_bool in_section= FALSE, opt_applied= 0;
uint reserve_extended; uint reserve_extended;
uint new_opt_len; uint new_opt_len;
@@ -81,8 +85,11 @@ int modify_defaults_file(const char *file_location, const char *option,
if (my_fstat(fileno(cnf_file), &file_stat, MYF(0))) if (my_fstat(fileno(cnf_file), &file_stat, MYF(0)))
goto malloc_err; goto malloc_err;
opt_len= (uint) strlen(option); if (option && option_value)
optval_len= (uint) strlen(option_value); {
opt_len= (uint) strlen(option);
optval_len= (uint) strlen(option_value);
}
new_opt_len= opt_len + 1 + optval_len + NEWLINE_LEN; new_opt_len= opt_len + 1 + optval_len + NEWLINE_LEN;
@@ -119,8 +126,8 @@ int modify_defaults_file(const char *file_location, const char *option,
continue; continue;
} }
/* correct the option */ /* correct the option (if requested) */
if (in_section && !strncmp(src_ptr, option, opt_len) && if (option && in_section && !strncmp(src_ptr, option, opt_len) &&
(*(src_ptr + opt_len) == '=' || (*(src_ptr + opt_len) == '=' ||
my_isspace(&my_charset_latin1, *(src_ptr + opt_len)) || my_isspace(&my_charset_latin1, *(src_ptr + opt_len)) ||
*(src_ptr + opt_len) == '\0')) *(src_ptr + opt_len) == '\0'))
@@ -143,7 +150,12 @@ int modify_defaults_file(const char *file_location, const char *option,
} }
else else
{ {
/* If going to new group and we have option to apply, do it now */ /*
If we are going to the new group and have an option to apply, do
it now. If we are removing a single option or the whole section
this will only trigger opt_applied flag.
*/
if (in_section && !opt_applied && *src_ptr == '[') if (in_section && !opt_applied && *src_ptr == '[')
{ {
dst_ptr= add_option(dst_ptr, option_value, option, remove_option); dst_ptr= add_option(dst_ptr, option_value, option, remove_option);
@@ -153,7 +165,10 @@ int modify_defaults_file(const char *file_location, const char *option,
for (; nr_newlines; nr_newlines--) for (; nr_newlines; nr_newlines--)
dst_ptr= strmov(dst_ptr, NEWLINE); dst_ptr= strmov(dst_ptr, NEWLINE);
dst_ptr= strmov(dst_ptr, linebuff);
/* Skip the section if MY_REMOVE_SECTION was given */
if (!in_section || remove_option != MY_REMOVE_SECTION)
dst_ptr= strmov(dst_ptr, linebuff);
} }
/* Look for a section */ /* Look for a section */
if (*src_ptr == '[') if (*src_ptr == '[')
@@ -167,18 +182,31 @@ int modify_defaults_file(const char *file_location, const char *option,
{} {}
if (*src_ptr != ']') if (*src_ptr != ']')
{
in_section= FALSE;
continue; /* Missing closing parenthesis. Assume this was no group */ continue; /* Missing closing parenthesis. Assume this was no group */
}
if (remove_option == MY_REMOVE_SECTION)
dst_ptr= dst_ptr - strlen(linebuff);
in_section= TRUE; in_section= TRUE;
} }
else else
in_section= FALSE; /* mark that this section is of no interest to us */ in_section= FALSE; /* mark that this section is of no interest to us */
} }
} }
/* File ended. */
if (!opt_applied && !remove_option && in_section) /*
File ended. Apply an option or set opt_applied flag (in case of
MY_REMOVE_SECTION) so that the changes are saved. Do not do anything
if we are removing non-existent option.
*/
if (!opt_applied && in_section && (remove_option != MY_REMOVE_OPTION))
{ {
/* New option still remains to apply at the end */ /* New option still remains to apply at the end */
if (*(dst_ptr - 1) != '\n') if (!remove_option && *(dst_ptr - 1) != '\n')
dst_ptr= strmov(dst_ptr, NEWLINE); dst_ptr= strmov(dst_ptr, NEWLINE);
dst_ptr= add_option(dst_ptr, option_value, option, remove_option); dst_ptr= add_option(dst_ptr, option_value, option, remove_option);
opt_applied= 1; opt_applied= 1;

View File

@@ -9,6 +9,7 @@ ADD_EXECUTABLE(mysqlmanager buffer.cc command.cc commands.cc guardian.cc instanc
instance_options.cc listener.cc log.cc manager.cc messages.cc mysql_connection.cc instance_options.cc listener.cc log.cc manager.cc messages.cc mysql_connection.cc
mysqlmanager.cc options.cc parse.cc parse_output.cc priv.cc protocol.cc mysqlmanager.cc options.cc parse.cc parse_output.cc priv.cc protocol.cc
thread_registry.cc user_map.cc imservice.cpp windowsservice.cpp thread_registry.cc user_map.cc imservice.cpp windowsservice.cpp
user_management_commands.cc
../../sql/net_serv.cc ../../sql-common/pack.c ../../sql/password.c ../../sql/net_serv.cc ../../sql-common/pack.c ../../sql/password.c
../../sql/sql_state.c ../../sql-common/client.c ../../libmysql/get_password.c ../../sql/sql_state.c ../../sql-common/client.c ../../libmysql/get_password.c
../../libmysql/errmsg.c) ../../libmysql/errmsg.c)

View File

@@ -20,7 +20,7 @@ IMService::~IMService(void)
void IMService::Stop() void IMService::Stop()
{ {
ReportStatus(SERVICE_STOP_PENDING); ReportStatus(SERVICE_STOP_PENDING);
// stop the IM work // stop the IM work
raise(SIGTERM); raise(SIGTERM);
} }
@@ -30,15 +30,14 @@ void IMService::Run(DWORD argc, LPTSTR *argv)
// report to the SCM that we're about to start // report to the SCM that we're about to start
ReportStatus((DWORD)SERVICE_START_PENDING); ReportStatus((DWORD)SERVICE_START_PENDING);
Options o; Options::load(argc, argv);
o.load(argc, argv);
// init goes here // init goes here
ReportStatus((DWORD)SERVICE_RUNNING); ReportStatus((DWORD)SERVICE_RUNNING);
// wait for main loop to terminate // wait for main loop to terminate
manager(o); manager();
o.cleanup(); Options::cleanup();
} }
void IMService::Log(const char *msg) void IMService::Log(const char *msg)
@@ -46,13 +45,13 @@ void IMService::Log(const char *msg)
log_info(msg); log_info(msg);
} }
int HandleServiceOptions(Options options) int HandleServiceOptions()
{ {
int ret_val= 0; int ret_val= 0;
IMService winService; IMService winService;
if (options.install_as_service) if (Options::Service::install_as_service)
{ {
if (winService.IsInstalled()) if (winService.IsInstalled())
log_info("Service is already installed"); log_info("Service is already installed");
@@ -64,7 +63,7 @@ int HandleServiceOptions(Options options)
ret_val= 1; ret_val= 1;
} }
} }
else if (options.remove_service) else if (Options::Service::remove_service)
{ {
if (! winService.IsInstalled()) if (! winService.IsInstalled())
log_info("Service is not installed"); log_info("Service is not installed");
@@ -77,6 +76,19 @@ int HandleServiceOptions(Options options)
} }
} }
else else
ret_val= !winService.Init(); {
log_info("Initializing Instance Manager service...");
if (!winService.Init())
{
log_info("Service failed to initialize.");
fprintf(stderr,
"The service should be started by Windows Service Manager.\n"
"The MySQL Manager should be started with '--standalone'\n"
"to run from command line.");
ret_val= 1;
}
}
return ret_val; return ret_val;
} }

View File

@@ -1,3 +1,21 @@
/*
Copyright (C) 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
*/
#pragma once #pragma once
#include "windowsservice.h" #include "windowsservice.h"
@@ -12,3 +30,5 @@ protected:
void Stop(); void Stop();
void Run(DWORD argc, LPTSTR *argv); void Run(DWORD argc, LPTSTR *argv);
}; };
extern int HandleServiceOptions();

View File

@@ -76,7 +76,10 @@ mysqlmanager_SOURCES= command.cc command.h mysqlmanager.cc \
guardian.cc guardian.h \ guardian.cc guardian.h \
parse_output.cc parse_output.h \ parse_output.cc parse_output.h \
mysql_manager_error.h \ mysql_manager_error.h \
portability.h portability.h \
exit_codes.h \
user_management_commands.h \
user_management_commands.cc
mysqlmanager_LDADD= @CLIENT_EXTRA_LDFLAGS@ \ mysqlmanager_LDADD= @CLIENT_EXTRA_LDFLAGS@ \
liboptions.la \ liboptions.la \

View File

@@ -7,9 +7,9 @@ static WindowsService *gService;
WindowsService::WindowsService(void) : WindowsService::WindowsService(void) :
statusCheckpoint(0), statusCheckpoint(0),
serviceName(NULL), serviceName(NULL),
inited(false), inited(FALSE),
dwAcceptedControls(SERVICE_ACCEPT_STOP), dwAcceptedControls(SERVICE_ACCEPT_STOP),
debugging(false) debugging(FALSE)
{ {
gService= this; gService= this;
status.dwServiceType= SERVICE_WIN32_OWN_PROCESS; status.dwServiceType= SERVICE_WIN32_OWN_PROCESS;
@@ -22,11 +22,12 @@ WindowsService::~WindowsService(void)
BOOL WindowsService::Install() BOOL WindowsService::Install()
{ {
bool ret_val= false; bool ret_val= FALSE;
SC_HANDLE newService; SC_HANDLE newService;
SC_HANDLE scm; SC_HANDLE scm;
if (IsInstalled()) return true; if (IsInstalled())
return TRUE;
// determine the name of the currently executing file // determine the name of the currently executing file
char szFilePath[_MAX_PATH]; char szFilePath[_MAX_PATH];
@@ -34,7 +35,7 @@ BOOL WindowsService::Install()
// open a connection to the SCM // open a connection to the SCM
if (!(scm= OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE))) if (!(scm= OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE)))
return false; return FALSE;
newService= CreateService(scm, serviceName, displayName, newService= CreateService(scm, serviceName, displayName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
@@ -45,7 +46,7 @@ BOOL WindowsService::Install()
if (newService) if (newService)
{ {
CloseServiceHandle(newService); CloseServiceHandle(newService);
ret_val= true; ret_val= TRUE;
} }
CloseServiceHandle(scm); CloseServiceHandle(scm);
@@ -56,34 +57,35 @@ BOOL WindowsService::Init()
{ {
assert(serviceName != NULL); assert(serviceName != NULL);
if (inited) return true; if (inited)
return TRUE;
SERVICE_TABLE_ENTRY stb[] = SERVICE_TABLE_ENTRY stb[] =
{ {
{ (LPSTR)serviceName, (LPSERVICE_MAIN_FUNCTION) ServiceMain}, { (LPSTR)serviceName, (LPSERVICE_MAIN_FUNCTION) ServiceMain},
{ NULL, NULL } { NULL, NULL }
}; };
inited= true; inited= TRUE;
return StartServiceCtrlDispatcher(stb); //register with the Service Manager return StartServiceCtrlDispatcher(stb); //register with the Service Manager
} }
BOOL WindowsService::Remove() BOOL WindowsService::Remove()
{ {
bool ret_val= false; bool ret_val= FALSE;
if (! IsInstalled()) if (!IsInstalled())
return true; return TRUE;
// open a connection to the SCM // open a connection to the SCM
SC_HANDLE scm= OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE); SC_HANDLE scm= OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE);
if (! scm) if (!scm)
return false; return FALSE;
SC_HANDLE service= OpenService(scm, serviceName, DELETE); SC_HANDLE service= OpenService(scm, serviceName, DELETE);
if (service) if (service)
{ {
if (DeleteService(service)) if (DeleteService(service))
ret_val= true; ret_val= TRUE;
DWORD dw= ::GetLastError(); DWORD dw= ::GetLastError();
CloseServiceHandle(service); CloseServiceHandle(service);
} }
@@ -116,7 +118,8 @@ void WindowsService::SetAcceptedControls(DWORD acceptedControls)
BOOL WindowsService::ReportStatus(DWORD currentState, DWORD waitHint, BOOL WindowsService::ReportStatus(DWORD currentState, DWORD waitHint,
DWORD dwError) DWORD dwError)
{ {
if(debugging) return TRUE; if (debugging)
return TRUE;
if(currentState == SERVICE_START_PENDING) if(currentState == SERVICE_START_PENDING)
status.dwControlsAccepted= 0; status.dwControlsAccepted= 0;

View File

@@ -1,3 +1,21 @@
/*
Copyright (C) 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
*/
#pragma once #pragma once
class WindowsService class WindowsService

View File

@@ -22,10 +22,12 @@
#pragma interface #pragma interface
#endif #endif
/* Class responsible for allocation of im commands. */ /* Class responsible for allocation of IM commands. */
class Instance_map; class Instance_map;
struct st_net;
/* /*
Command - entry point for any command. Command - entry point for any command.
GangOf4: 'Command' design pattern GangOf4: 'Command' design pattern
@@ -37,8 +39,18 @@ public:
Command(Instance_map *instance_map_arg= 0); Command(Instance_map *instance_map_arg= 0);
virtual ~Command(); virtual ~Command();
/* method of executing: */ /*
virtual int execute(struct st_net *net, ulong connection_id) = 0; This operation incapsulates behaviour of the command.
SYNOPSYS
net The network connection to the client.
connection_id Client connection ID
RETURN
0 On success
non 0 On error. Client error code is returned.
*/
virtual int execute(st_net *net, ulong connection_id) = 0;
protected: protected:
Instance_map *instance_map; Instance_map *instance_map;

File diff suppressed because it is too large Load Diff

View File

@@ -16,10 +16,20 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <my_global.h>
#include <my_sys.h>
#include <m_string.h>
#include <hash.h>
#include "command.h" #include "command.h"
#include "instance.h" #include "instance.h"
#include "parse.h" #include "parse.h"
#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
#pragma interface
#endif
/* /*
Print all instances of this instance manager. Print all instances of this instance manager.
Grammar: SHOW ISTANCES Grammar: SHOW ISTANCES
@@ -31,12 +41,16 @@ public:
Show_instances(Instance_map *instance_map_arg): Command(instance_map_arg) Show_instances(Instance_map *instance_map_arg): Command(instance_map_arg)
{} {}
int execute(struct st_net *net, ulong connection_id); int execute(st_net *net, ulong connection_id);
private:
int write_header(st_net *net);
int write_data(st_net *net);
}; };
/* /*
Reread configuration file and refresh instance map. Reread configuration file and refresh internal cache.
Grammar: FLUSH INSTANCES Grammar: FLUSH INSTANCES
*/ */
@@ -46,7 +60,43 @@ public:
Flush_instances(Instance_map *instance_map_arg): Command(instance_map_arg) Flush_instances(Instance_map *instance_map_arg): Command(instance_map_arg)
{} {}
int execute(struct st_net *net, ulong connection_id); int execute(st_net *net, ulong connection_id);
};
/*
Abstract class for Instance-specific commands.
*/
class Abstract_instance_cmd : public Command
{
public:
Abstract_instance_cmd(Instance_map *instance_map_arg,
const LEX_STRING *instance_name_arg);
public:
virtual int execute(st_net *net, ulong connection_id);
protected:
/* MT-NOTE: this operation is called under acquired Instance_map's lock. */
virtual int execute_impl(st_net *net, Instance *instance) = 0;
/*
This operation is invoked on successful return of execute_impl() and is
intended to send closing data.
MT-NOTE: this operation is called under released Instance_map's lock.
*/
virtual int send_ok_response(st_net *net, ulong connection_id) = 0;
protected:
inline const LEX_STRING *get_instance_name() const
{
return instance_name.get_str();
}
private:
Instance_name instance_name;
}; };
@@ -55,31 +105,40 @@ public:
Grammar: SHOW ISTANCE STATUS <instance_name> Grammar: SHOW ISTANCE STATUS <instance_name>
*/ */
class Show_instance_status : public Command class Show_instance_status : public Abstract_instance_cmd
{ {
public: public:
Show_instance_status(Instance_map *instance_map_arg, Show_instance_status(Instance_map *instance_map_arg,
const char *name, uint len); const LEX_STRING *instance_name_arg);
int execute(struct st_net *net, ulong connection_id);
const char *instance_name; protected:
virtual int execute_impl(st_net *net, Instance *instance);
virtual int send_ok_response(st_net *net, ulong connection_id);
private:
int write_header(st_net *net);
int write_data(st_net *net, Instance *instance);
}; };
/* /*
Print options if chosen instance. Print options of chosen instance.
Grammar: SHOW INSTANCE OPTIONS <instance_name> Grammar: SHOW INSTANCE OPTIONS <instance_name>
*/ */
class Show_instance_options : public Command class Show_instance_options : public Abstract_instance_cmd
{ {
public: public:
Show_instance_options(Instance_map *instance_map_arg, Show_instance_options(Instance_map *instance_map_arg,
const char *name, uint len); const LEX_STRING *instance_name_arg);
int execute(struct st_net *net, ulong connection_id); protected:
const char *instance_name; virtual int execute_impl(st_net *net, Instance *instance);
virtual int send_ok_response(st_net *net, ulong connection_id);
private:
int write_header(st_net *net);
int write_data(st_net *net, Instance *instance);
}; };
@@ -88,14 +147,15 @@ public:
Grammar: START INSTANCE <instance_name> Grammar: START INSTANCE <instance_name>
*/ */
class Start_instance : public Command class Start_instance : public Abstract_instance_cmd
{ {
public: public:
Start_instance(Instance_map *instance_map_arg, const char *name, uint len); Start_instance(Instance_map *instance_map_arg,
const LEX_STRING *instance_name_arg);
int execute(struct st_net *net, ulong connection_id); protected:
const char *instance_name; virtual int execute_impl(st_net *net, Instance *instance);
Instance *instance; virtual int send_ok_response(st_net *net, ulong connection_id);
}; };
@@ -104,33 +164,95 @@ public:
Grammar: STOP INSTANCE <instance_name> Grammar: STOP INSTANCE <instance_name>
*/ */
class Stop_instance : public Command class Stop_instance : public Abstract_instance_cmd
{ {
public: public:
Stop_instance(Instance_map *instance_map_arg, const char *name, uint len); Stop_instance(Instance_map *instance_map_arg,
const LEX_STRING *instance_name_arg);
Instance *instance; protected:
int execute(struct st_net *net, ulong connection_id); virtual int execute_impl(st_net *net, Instance *instance);
const char *instance_name; virtual int send_ok_response(st_net *net, ulong connection_id);
}; };
/* /*
Print requested part of the log Create an instance.
Grammar: Grammar: CREATE INSTANCE <instance_name> [<options>]
SHOW <instance_name> log {ERROR | SLOW | GENERAL} size[, offset_from_end]
*/ */
class Show_instance_log : public Command class Create_instance : public Command
{ {
public: public:
Create_instance(Instance_map *instance_map_arg,
const LEX_STRING *instance_name_arg);
Show_instance_log(Instance_map *instance_map_arg, const char *name, public:
uint len, Log_type log_type_arg, const char *size_arg, bool init(const char **text);
const char *offset_arg);
int execute(struct st_net *net, ulong connection_id); protected:
virtual int execute(st_net *net, ulong connection_id);
inline const LEX_STRING *get_instance_name() const
{
return instance_name.get_str();
}
private:
bool parse_args(const char **text);
private:
Instance_name instance_name;
Named_value_arr options;
};
/*
Drop an instance.
Grammar: DROP INSTANCE <instance_name>
Operation is permitted only if the instance is stopped. On successful
completion the instance section is removed from config file and the instance
is removed from the instance map.
*/
class Drop_instance : public Abstract_instance_cmd
{
public:
Drop_instance(Instance_map *instance_map_arg,
const LEX_STRING *instance_name_arg);
protected:
virtual int execute_impl(st_net *net, Instance *instance);
virtual int send_ok_response(st_net *net, ulong connection_id);
};
/*
Print requested part of the log.
Grammar:
SHOW <instance_name> LOG {ERROR | SLOW | GENERAL} size[, offset_from_end]
*/
class Show_instance_log : public Abstract_instance_cmd
{
public:
Show_instance_log(Instance_map *instance_map_arg,
const LEX_STRING *instance_name_arg,
Log_type log_type_arg, uint size_arg, uint offset_arg);
protected:
virtual int execute_impl(st_net *net, Instance *instance);
virtual int send_ok_response(st_net *net, ulong connection_id);
private:
int check_params(Instance *instance);
int write_header(st_net *net);
int write_data(st_net *net, Instance *instance);
private:
Log_type log_type; Log_type log_type;
const char *instance_name;
uint size; uint size;
uint offset; uint offset;
}; };
@@ -141,75 +263,112 @@ public:
Grammar: SHOW <instance_name> LOG FILES Grammar: SHOW <instance_name> LOG FILES
*/ */
class Show_instance_log_files : public Command class Show_instance_log_files : public Abstract_instance_cmd
{ {
public: public:
Show_instance_log_files(Instance_map *instance_map_arg, Show_instance_log_files(Instance_map *instance_map_arg,
const char *name, uint len); const LEX_STRING *instance_name_arg);
int execute(struct st_net *net, ulong connection_id);
const char *instance_name; protected:
const char *option; virtual int execute_impl(st_net *net, Instance *instance);
virtual int send_ok_response(st_net *net, ulong connection_id);
private:
int write_header(st_net *net);
int write_data(st_net *net, Instance *instance);
}; };
/* /*
Syntax error command. This command is issued if parser reported a syntax Abstract class for option-management commands.
error. We need it to distinguish the parse error and the situation when */
parser internal error occured. E.g. parsing failed because we hadn't had
enought memory. In the latter case parse_command() should return an error. class Instance_options_list;
class Abstract_option_cmd : public Command
{
public:
~Abstract_option_cmd();
public:
bool add_option(const LEX_STRING *instance_name, Named_value *option);
public:
bool init(const char **text);
virtual int execute(st_net *net, ulong connection_id);
protected:
Abstract_option_cmd(Instance_map *instance_map_arg);
int correct_file(Instance *instance, Named_value *option, bool skip);
protected:
virtual bool parse_args(const char **text) = 0;
virtual int process_option(Instance *instance, Named_value *option) = 0;
private:
Instance_options_list *
get_instance_options_list(const LEX_STRING *instance_name);
int execute_impl(st_net *net, ulong connection_id);
private:
HASH instance_options_map;
bool initialized;
};
/*
Set an option for the instance.
Grammar: SET instance_name.option[=option_value][, ...]
*/
class Set_option : public Abstract_option_cmd
{
public:
Set_option(Instance_map *instance_map_arg);
protected:
virtual bool parse_args(const char **text);
virtual int process_option(Instance *instance, Named_value *option);
};
/*
Remove option of the instance.
Grammar: UNSET instance_name.option[, ...]
*/
class Unset_option: public Abstract_option_cmd
{
public:
Unset_option(Instance_map *instance_map_arg);
protected:
virtual bool parse_args(const char **text);
virtual int process_option(Instance *instance, Named_value *option);
};
/*
Syntax error command.
This command is issued if parser reported a syntax error. We need it to
distinguish between syntax error and internal parser error. E.g. parsing
failed because we hadn't had enought memory. In the latter case the parser
just returns NULL.
*/ */
class Syntax_error : public Command class Syntax_error : public Command
{ {
public: public:
int execute(struct st_net *net, ulong connection_id); /* This is just to avoid compiler warning. */
}; Syntax_error() :Command(NULL)
{}
/*
Set an option for the instance.
Grammar: SET instance_name.option=option_value
*/
class Set_option : public Command
{
public: public:
Set_option(Instance_map *instance_map_arg, const char *name, uint len, int execute(st_net *net, ulong connection_id);
const char *option_arg, uint option_len,
const char *option_value_arg, uint option_value_len);
/*
the following function is virtual to let Unset_option to use
*/
virtual int do_command(struct st_net *net);
int execute(struct st_net *net, ulong connection_id);
protected:
int correct_file(int skip);
public:
const char *instance_name;
uint instance_name_len;
/* buffer for the option */
enum { MAX_OPTION_LEN= 1024 };
char option[MAX_OPTION_LEN];
char option_value[MAX_OPTION_LEN];
}; };
/*
Remove option of the instance from config file
Grammar: UNSET instance_name.option
*/
class Unset_option: public Set_option
{
public:
Unset_option(Instance_map *instance_map_arg, const char *name, uint len,
const char *option_arg, uint option_len,
const char *option_value_arg, uint option_value_len):
Set_option(instance_map_arg, name, len, option_arg, option_len,
option_value_arg, option_value_len)
{}
int do_command(struct st_net *net);
};
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_COMMANDS_H */ #endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_COMMANDS_H */

View File

@@ -0,0 +1,41 @@
#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_EXIT_CODES_H
#define INCLUDES_MYSQL_INSTANCE_MANAGER_EXIT_CODES_H
/*
Copyright (C) 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
*/
/*
This file contains a list of exit codes, which are used when Instance
Manager is working in user-management mode.
*/
const int ERR_OK = 0;
const int ERR_OUT_OF_MEMORY = 1;
const int ERR_INVALID_USAGE = 2;
const int ERR_INTERNAL_ERROR = 3;
const int ERR_IO_ERROR = 4;
const int ERR_PASSWORD_FILE_CORRUPTED = 5;
const int ERR_PASSWORD_FILE_DOES_NOT_EXIST = 6;
const int ERR_CAN_NOT_READ_USER_NAME = 10;
const int ERR_CAN_NOT_READ_PASSWORD = 11;
const int ERR_USER_ALREADY_EXISTS = 12;
const int ERR_USER_NOT_FOUND = 13;
#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_EXIT_CODES_H

View File

@@ -21,16 +21,14 @@
#include "guardian.h" #include "guardian.h"
#include "instance_map.h"
#include "instance.h"
#include "mysql_manager_error.h"
#include "log.h"
#include "portability.h"
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <signal.h> #include <signal.h>
#include "instance.h"
#include "instance_map.h"
#include "log.h"
#include "mysql_manager_error.h"
pthread_handler_t guardian(void *arg) pthread_handler_t guardian(void *arg)
@@ -40,6 +38,37 @@ pthread_handler_t guardian(void *arg)
return 0; return 0;
} }
const char *
Guardian_thread::get_instance_state_name(enum_instance_state state)
{
switch (state) {
case NOT_STARTED:
return "offline";
case STARTING:
return "starting";
case STARTED:
return "online";
case JUST_CRASHED:
return "failed";
case CRASHED:
return "crashed";
case CRASHED_AND_ABANDONED:
return "abandoned";
case STOPPING:
return "stopping";
}
return NULL; /* just to ignore compiler warning. */
}
Guardian_thread::Guardian_thread(Thread_registry &thread_registry_arg, Guardian_thread::Guardian_thread(Thread_registry &thread_registry_arg,
Instance_map *instance_map_arg, Instance_map *instance_map_arg,
uint monitoring_interval_arg) : uint monitoring_interval_arg) :
@@ -89,10 +118,17 @@ void Guardian_thread::process_instance(Instance *instance,
if (current_node->state == STOPPING) if (current_node->state == STOPPING)
{ {
/* this brach is executed during shutdown */ /* this brach is executed during shutdown */
if (instance->options.shutdown_delay_val) if (instance->options.shutdown_delay)
{
/*
NOTE: it is important to check shutdown_delay here, but use
shutdown_delay_val. The idea is that if the option is unset,
shutdown_delay will be NULL, but shutdown_delay_val will not be reset.
*/
waitchild= instance->options.shutdown_delay_val; waitchild= instance->options.shutdown_delay_val;
}
/* this returns true if and only if an instance was stopped for sure */ /* this returns TRUE if and only if an instance was stopped for sure */
if (instance->is_crashed()) if (instance->is_crashed())
*guarded_instances= list_delete(*guarded_instances, node); *guarded_instances= list_delete(*guarded_instances, node);
else if ( (uint) (current_time - current_node->last_checked) > waitchild) else if ( (uint) (current_time - current_node->last_checked) > waitchild)
@@ -159,7 +195,11 @@ void Guardian_thread::process_instance(Instance *instance,
instance->options.instance_name); instance->options.instance_name);
} }
else else
{
log_info("guardian: cannot start instance %s. Abandoning attempts "
"to (re)start it", instance->options.instance_name);
current_node->state= CRASHED_AND_ABANDONED; current_node->state= CRASHED_AND_ABANDONED;
}
} }
break; break;
case CRASHED_AND_ABANDONED: case CRASHED_AND_ABANDONED:
@@ -242,7 +282,9 @@ int Guardian_thread::is_stopped()
SYNOPSYS SYNOPSYS
Guardian_thread::init() Guardian_thread::init()
NOTE: One should always lock guardian before calling this routine. NOTE: The operation should be invoked with the following locks acquired:
- Guardian_thread;
- Instance_map;
RETURN RETURN
0 - ok 0 - ok
@@ -261,12 +303,11 @@ int Guardian_thread::init()
while ((instance= iterator.next())) while ((instance= iterator.next()))
{ {
if (!(instance->options.nonguarded)) if (instance->options.nonguarded)
if (guard(instance, TRUE)) /* do not lock guardian */ continue;
{
instance_map->unlock(); if (guard(instance, TRUE)) /* do not lock guardian */
return 1; return 1;
}
} }
return 0; return 0;
@@ -334,24 +375,14 @@ int Guardian_thread::stop_guard(Instance *instance)
LIST *node; LIST *node;
pthread_mutex_lock(&LOCK_guardian); pthread_mutex_lock(&LOCK_guardian);
node= guarded_instances;
while (node != NULL) node= find_instance_node(instance);
{
/* if (node != NULL)
We compare only pointers, as we always use pointers from the guarded_instances= list_delete(guarded_instances, node);
instance_map's MEM_ROOT.
*/
if (((GUARD_NODE *) node->data)->instance == instance)
{
guarded_instances= list_delete(guarded_instances, node);
pthread_mutex_unlock(&LOCK_guardian);
return 0;
}
else
node= node->next;
}
pthread_mutex_unlock(&LOCK_guardian); pthread_mutex_unlock(&LOCK_guardian);
/* if there is nothing to delete it is also fine */ /* if there is nothing to delete it is also fine */
return 0; return 0;
} }
@@ -420,7 +451,7 @@ int Guardian_thread::stop_instances(bool stop_instances_arg)
void Guardian_thread::lock() void Guardian_thread::lock()
{ {
pthread_mutex_lock(&LOCK_guardian); pthread_mutex_lock(&LOCK_guardian);
} }
@@ -428,3 +459,41 @@ void Guardian_thread::unlock()
{ {
pthread_mutex_unlock(&LOCK_guardian); pthread_mutex_unlock(&LOCK_guardian);
} }
LIST *Guardian_thread::find_instance_node(Instance *instance)
{
LIST *node= guarded_instances;
while (node != NULL)
{
/*
We compare only pointers, as we always use pointers from the
instance_map's MEM_ROOT.
*/
if (((GUARD_NODE *) node->data)->instance == instance)
return node;
node= node->next;
}
return NULL;
}
bool Guardian_thread::is_active(Instance *instance)
{
bool guarded;
lock();
guarded= find_instance_node(instance) != NULL;
/* is_running() can take a long time, so let's unlock mutex first. */
unlock();
if (guarded)
return true;
return instance->is_running();
}

View File

@@ -17,11 +17,11 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <my_global.h> #include <my_global.h>
#include "thread_registry.h"
#include <my_sys.h> #include <my_sys.h>
#include <my_list.h> #include <my_list.h>
#include "thread_registry.h"
#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE) #if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
#pragma interface #pragma interface
#endif #endif
@@ -79,6 +79,8 @@ public:
time_t last_checked; time_t last_checked;
}; };
/* Return client state name. */
static const char *get_instance_state_name(enum_instance_state state);
Guardian_thread(Thread_registry &thread_registry_arg, Guardian_thread(Thread_registry &thread_registry_arg,
Instance_map *instance_map_arg, Instance_map *instance_map_arg,
@@ -94,11 +96,28 @@ public:
int guard(Instance *instance, bool nolock= FALSE); int guard(Instance *instance, bool nolock= FALSE);
/* Stop instance protection */ /* Stop instance protection */
int stop_guard(Instance *instance); int stop_guard(Instance *instance);
/* Returns true if guardian thread is stopped */ /* Returns TRUE if guardian thread is stopped */
int is_stopped(); int is_stopped();
void lock(); void lock();
void unlock(); void unlock();
/*
Return an internal list node for the given instance if the instance is
managed by Guardian. Otherwise, return NULL.
MT-NOTE: must be called under acquired lock.
*/
LIST *find_instance_node(Instance *instance);
/* The operation is used to check if the instance is active or not. */
bool is_active(Instance *instance);
/*
Return state of the given instance list node. The pointer must specify
a valid list node.
*/
inline enum_instance_state get_instance_state(LIST *instance_node);
public: public:
pthread_cond_t COND_guardian; pthread_cond_t COND_guardian;
@@ -108,6 +127,7 @@ private:
/* check instance state and act accordingly */ /* check instance state and act accordingly */
void process_instance(Instance *instance, GUARD_NODE *current_node, void process_instance(Instance *instance, GUARD_NODE *current_node,
LIST **guarded_instances, LIST *elem); LIST **guarded_instances, LIST *elem);
int stopped; int stopped;
private: private:
@@ -115,9 +135,15 @@ private:
Thread_info thread_info; Thread_info thread_info;
LIST *guarded_instances; LIST *guarded_instances;
MEM_ROOT alloc; MEM_ROOT alloc;
enum { MEM_ROOT_BLOCK_SIZE= 512 };
/* this variable is set to TRUE when we want to stop Guardian thread */ /* this variable is set to TRUE when we want to stop Guardian thread */
bool shutdown_requested; bool shutdown_requested;
}; };
inline Guardian_thread::enum_instance_state
Guardian_thread::get_instance_state(LIST *instance_node)
{
return ((GUARD_NODE *) instance_node->data)->state;
}
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_GUARDIAN_H */ #endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_GUARDIAN_H */

View File

@@ -20,18 +20,27 @@
#include "instance.h" #include "instance.h"
#include "mysql_manager_error.h" #include <my_global.h>
#include "log.h" #include <mysql.h>
#include "instance_map.h"
#include "priv.h" #include <signal.h>
#include "portability.h"
#ifndef __WIN__ #ifndef __WIN__
#include <sys/wait.h> #include <sys/wait.h>
#endif #endif
#include <my_sys.h>
#include <signal.h> #include "guardian.h"
#include <m_string.h> #include "instance_map.h"
#include <mysql.h> #include "log.h"
#include "mysql_manager_error.h"
#include "portability.h"
#include "priv.h"
const LEX_STRING
Instance::DFLT_INSTANCE_NAME= { C_STRING_WITH_SIZE("mysqld") };
static const char * const INSTANCE_NAME_PREFIX= Instance::DFLT_INSTANCE_NAME.str;
static const int INSTANCE_NAME_PREFIX_LEN= Instance::DFLT_INSTANCE_NAME.length;
static void start_and_monitor_instance(Instance_options *old_instance_options, static void start_and_monitor_instance(Instance_options *old_instance_options,
@@ -152,7 +161,7 @@ static int start_process(Instance_options *instance_options,
switch (*pi) { switch (*pi) {
case 0: /* never happens on QNX */ case 0: /* never happens on QNX */
execv(instance_options->mysqld_path, instance_options->argv); execv(instance_options->mysqld_path.str, instance_options->argv);
/* exec never returns */ /* exec never returns */
exit(1); exit(1);
case -1: case -1:
@@ -180,7 +189,7 @@ static int start_process(Instance_options *instance_options,
char *cmdline= new char[cmdlen]; char *cmdline= new char[cmdlen];
if (cmdline == NULL) if (cmdline == NULL)
return 1; return 1;
cmdline[0]= 0; cmdline[0]= 0;
for (int i= 0; instance_options->argv[i] != 0; i++) for (int i= 0; instance_options->argv[i] != 0; i++)
{ {
@@ -232,9 +241,7 @@ static int start_process(Instance_options *instance_options,
static void start_and_monitor_instance(Instance_options *old_instance_options, static void start_and_monitor_instance(Instance_options *old_instance_options,
Instance_map *instance_map) Instance_map *instance_map)
{ {
enum { MAX_INSTANCE_NAME_LEN= 512 }; Instance_name instance_name(&old_instance_options->instance_name);
char instance_name_buff[MAX_INSTANCE_NAME_LEN];
uint instance_name_len;
Instance *current_instance; Instance *current_instance;
My_process_info process_info; My_process_info process_info;
@@ -248,11 +255,8 @@ static void start_and_monitor_instance(Instance_options *old_instance_options,
Save the instance name in the case if Instance object we Save the instance name in the case if Instance object we
are using is destroyed. (E.g. by "FLUSH INSTANCES") are using is destroyed. (E.g. by "FLUSH INSTANCES")
*/ */
strmake(instance_name_buff, old_instance_options->instance_name,
MAX_INSTANCE_NAME_LEN - 1);
instance_name_len= old_instance_options->instance_name_len;
log_info("starting instance %s", instance_name_buff); log_info("starting instance %s", (const char *) instance_name.get_c_str());
if (start_process(old_instance_options, &process_info)) if (start_process(old_instance_options, &process_info))
{ {
@@ -266,15 +270,36 @@ static void start_and_monitor_instance(Instance_options *old_instance_options,
/* don't check for return value */ /* don't check for return value */
wait_process(&process_info); wait_process(&process_info);
current_instance= instance_map->find(instance_name_buff, instance_name_len); instance_map->lock();
current_instance= instance_map->find(instance_name.get_str());
if (current_instance) if (current_instance)
current_instance->set_crash_flag_n_wake_all(); current_instance->set_crash_flag_n_wake_all();
instance_map->unlock();
return; return;
} }
bool Instance::is_name_valid(const LEX_STRING *name)
{
const char *name_suffix= name->str + INSTANCE_NAME_PREFIX_LEN;
if (strncmp(name->str, INSTANCE_NAME_PREFIX, INSTANCE_NAME_PREFIX_LEN) != 0)
return FALSE;
return *name_suffix == 0 || my_isdigit(default_charset_info, *name_suffix);
}
bool Instance::is_mysqld_compatible_name(const LEX_STRING *name)
{
return strcmp(name->str, INSTANCE_NAME_PREFIX) == 0;
}
Instance_map *Instance::get_map() Instance_map *Instance::get_map()
{ {
return instance_map; return instance_map;
@@ -309,11 +334,11 @@ int Instance::start()
{ {
/* clear crash flag */ /* clear crash flag */
pthread_mutex_lock(&LOCK_instance); pthread_mutex_lock(&LOCK_instance);
crashed= 0; crashed= FALSE;
pthread_mutex_unlock(&LOCK_instance); pthread_mutex_unlock(&LOCK_instance);
if (!is_running()) if (configured && !is_running())
{ {
remove_pid(); remove_pid();
@@ -339,8 +364,8 @@ int Instance::start()
return 0; return 0;
} }
/* the instance is started already */ /* The instance is started already or misconfigured. */
return ER_INSTANCE_ALREADY_STARTED; return configured ? ER_INSTANCE_ALREADY_STARTED : ER_INSTANCE_MISCONFIGURED;
} }
/* /*
@@ -363,7 +388,7 @@ void Instance::set_crash_flag_n_wake_all()
{ {
/* set instance state to crashed */ /* set instance state to crashed */
pthread_mutex_lock(&LOCK_instance); pthread_mutex_lock(&LOCK_instance);
crashed= 1; crashed= TRUE;
pthread_mutex_unlock(&LOCK_instance); pthread_mutex_unlock(&LOCK_instance);
/* /*
@@ -378,7 +403,7 @@ void Instance::set_crash_flag_n_wake_all()
Instance::Instance(): crashed(0) Instance::Instance(): crashed(FALSE), configured(FALSE)
{ {
pthread_mutex_init(&LOCK_instance, 0); pthread_mutex_init(&LOCK_instance, 0);
pthread_cond_init(&COND_instance_stopped, 0); pthread_cond_init(&COND_instance_stopped, 0);
@@ -392,9 +417,9 @@ Instance::~Instance()
} }
int Instance::is_crashed() bool Instance::is_crashed()
{ {
int val; bool val;
pthread_mutex_lock(&LOCK_instance); pthread_mutex_lock(&LOCK_instance);
val= crashed; val= crashed;
pthread_mutex_unlock(&LOCK_instance); pthread_mutex_unlock(&LOCK_instance);
@@ -413,10 +438,17 @@ bool Instance::is_running()
bool return_val; bool return_val;
if (options.mysqld_port) if (options.mysqld_port)
{
/*
NOTE: it is important to check mysqld_port here, but use
mysqld_port_val. The idea is that if the option is unset, mysqld_port
will be NULL, but mysqld_port_val will not be reset.
*/
port= options.mysqld_port_val; port= options.mysqld_port_val;
}
if (options.mysqld_socket) if (options.mysqld_socket)
socket= strchr(options.mysqld_socket, '=') + 1; socket= options.mysqld_socket;
/* no port was specified => instance falled back to default value */ /* no port was specified => instance falled back to default value */
if (!options.mysqld_port && !options.mysqld_socket) if (!options.mysqld_port && !options.mysqld_socket)
@@ -469,8 +501,15 @@ int Instance::stop()
struct timespec timeout; struct timespec timeout;
uint waitchild= (uint) DEFAULT_SHUTDOWN_DELAY; uint waitchild= (uint) DEFAULT_SHUTDOWN_DELAY;
if (options.shutdown_delay_val) if (options.shutdown_delay)
{
/*
NOTE: it is important to check shutdown_delay here, but use
shutdown_delay_val. The idea is that if the option is unset,
shutdown_delay will be NULL, but shutdown_delay_val will not be reset.
*/
waitchild= options.shutdown_delay_val; waitchild= options.shutdown_delay_val;
}
kill_instance(SIGTERM); kill_instance(SIGTERM);
/* sleep on condition to wait for SIGCHLD */ /* sleep on condition to wait for SIGCHLD */
@@ -588,20 +627,33 @@ void Instance::kill_instance(int signum)
} }
/* /*
We execute this function to initialize instance parameters. Initialize instance parameters.
Return value: 0 - ok. 1 - unable to init DYNAMIC_ARRAY.
SYNOPSYS
Instance::init()
name_arg name of the instance
RETURN:
0 ok
!0 error
*/ */
int Instance::init(const char *name_arg) int Instance::init(const LEX_STRING *name_arg)
{ {
mysqld_compatible= is_mysqld_compatible_name(name_arg);
return options.init(name_arg); return options.init(name_arg);
} }
int Instance::complete_initialization(Instance_map *instance_map_arg, int Instance::complete_initialization(Instance_map *instance_map_arg,
const char *mysqld_path, const char *mysqld_path)
uint instance_type)
{ {
instance_map= instance_map_arg; instance_map= instance_map_arg;
return options.complete_initialization(mysqld_path, instance_type); configured= !options.complete_initialization(mysqld_path);
return 0;
/*
TODO: return actual status (from
Instance_options::complete_initialization()) here.
*/
} }

View File

@@ -17,7 +17,10 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <my_global.h> #include <my_global.h>
#include <m_string.h>
#include "instance_options.h" #include "instance_options.h"
#include "priv.h"
#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE) #if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
#pragma interface #pragma interface
@@ -25,31 +28,120 @@
class Instance_map; class Instance_map;
/*
Instance_name -- the class represents instance name -- a string of length
less than MAX_INSTANCE_NAME_SIZE.
Generally, this is just a string with self-memory-management and should be
eliminated in the future.
*/
class Instance_name
{
public:
Instance_name(const LEX_STRING *name);
public:
inline const LEX_STRING *get_str() const
{
return &str;
}
inline const char *get_c_str() const
{
return str.str;
}
inline uint get_length() const
{
return str.length;
}
private:
LEX_STRING str;
char str_buffer[MAX_INSTANCE_NAME_SIZE];
};
class Instance class Instance
{ {
public:
/*
The following two constants defines name of the default mysqld-instance
("mysqld").
*/
static const LEX_STRING DFLT_INSTANCE_NAME;
public:
/*
The operation is intended to check whether string is a well-formed
instance name or not.
*/
static bool is_name_valid(const LEX_STRING *name);
/*
The operation is intended to check if the given instance name is
mysqld-compatible or not.
*/
static bool is_mysqld_compatible_name(const LEX_STRING *name);
public: public:
Instance(); Instance();
~Instance(); ~Instance();
int init(const char *name); int init(const LEX_STRING *name_arg);
int complete_initialization(Instance_map *instance_map_arg, int complete_initialization(Instance_map *instance_map_arg,
const char *mysqld_path, uint instance_type); const char *mysqld_path);
bool is_running(); bool is_running();
int start(); int start();
int stop(); int stop();
/* send a signal to the instance */ /* send a signal to the instance */
void kill_instance(int signo); void kill_instance(int signo);
int is_crashed(); bool is_crashed();
void set_crash_flag_n_wake_all(); void set_crash_flag_n_wake_all();
Instance_map *get_map(); Instance_map *get_map();
/*
The operation is intended to check if the instance is mysqld-compatible
or not.
*/
inline bool is_mysqld_compatible() const;
/*
The operation is intended to check if the instance is configured properly
or not. Misconfigured instances are not managed.
*/
inline bool is_configured() const;
inline const LEX_STRING *get_name() const;
public: public:
enum { DEFAULT_SHUTDOWN_DELAY= 35 }; enum { DEFAULT_SHUTDOWN_DELAY= 35 };
Instance_options options; Instance_options options;
private: private:
int crashed; /* This attributes is a flag, specifies if the instance has been crashed. */
bool crashed;
/*
This attribute specifies if the instance is configured properly or not.
Misconfigured instances are not managed.
*/
bool configured;
/*
This attribute specifies whether the instance is mysqld-compatible or not.
Mysqld-compatible instances can contain only mysqld-specific options.
At the moment an instance is mysqld-compatible if its name is "mysqld".
The idea is that [mysqld] section should contain only mysqld-specific
options (no Instance Manager-specific options) to be readable by mysqld
program.
*/
bool mysqld_compatible;
/* /*
Mutex protecting the instance. Currently we use it to avoid the Mutex protecting the instance. Currently we use it to avoid the
double start of the instance. This happens when the instance is starting double start of the instance. This happens when the instance is starting
@@ -66,4 +158,22 @@ private:
void remove_pid(); void remove_pid();
}; };
inline bool Instance::is_mysqld_compatible() const
{
return mysqld_compatible;
}
inline bool Instance::is_configured() const
{
return configured;
}
inline const LEX_STRING *Instance::get_name() const
{
return &options.instance_name;
}
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_H */ #endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_H */

View File

@@ -20,14 +20,19 @@
#include "instance_map.h" #include "instance_map.h"
#include "buffer.h" #include <my_global.h>
#include "instance.h"
#include "log.h"
#include "options.h"
#include <m_ctype.h> #include <m_ctype.h>
#include <mysql_com.h> #include <mysql_com.h>
#include <m_string.h>
#include "buffer.h"
#include "guardian.h"
#include "instance.h"
#include "log.h"
#include "manager.h"
#include "mysqld_error.h"
#include "mysql_manager_error.h"
#include "options.h"
#include "priv.h"
/* /*
Note: As we are going to suppost different types of connections, Note: As we are going to suppost different types of connections,
@@ -45,8 +50,8 @@ static byte* get_instance_key(const byte* u, uint* len,
my_bool __attribute__((unused)) t) my_bool __attribute__((unused)) t)
{ {
const Instance *instance= (const Instance *) u; const Instance *instance= (const Instance *) u;
*len= instance->options.instance_name_len; *len= instance->options.instance_name.length;
return (byte *) instance->options.instance_name; return (byte *) instance->options.instance_name.str;
} }
static void delete_instance(void *u) static void delete_instance(void *u)
@@ -79,15 +84,59 @@ static void delete_instance(void *u)
static int process_option(void *ctx, const char *group, const char *option) static int process_option(void *ctx, const char *group, const char *option)
{ {
Instance_map *map= NULL; Instance_map *map= (Instance_map*) ctx;
LEX_STRING group_str;
map = (Instance_map*) ctx; group_str.str= (char *) group;
return map->process_one_option(group, option); group_str.length= strlen(group);
return map->process_one_option(&group_str, option);
} }
C_MODE_END C_MODE_END
/*
Parse option string.
SYNOPSIS
parse_option()
option_str [IN] option string (e.g. "--name=value")
option_name_buf [OUT] parsed name of the option.
Must be of (MAX_OPTION_LEN + 1) size.
option_value_buf [OUT] parsed value of the option.
Must be of (MAX_OPTION_LEN + 1) size.
DESCRIPTION
This is an auxiliary function and should not be used externally. It is
intended to parse whole option string into option name and option value.
*/
static void parse_option(const char *option_str,
char *option_name_buf,
char *option_value_buf)
{
const char *eq_pos;
const char *ptr= option_str;
while (*ptr == '-')
++ptr;
strmake(option_name_buf, ptr, MAX_OPTION_LEN + 1);
eq_pos= strchr(ptr, '=');
if (eq_pos)
{
option_name_buf[eq_pos - ptr]= 0;
strmake(option_value_buf, eq_pos + 1, MAX_OPTION_LEN + 1);
}
else
{
option_value_buf[0]= 0;
}
}
/* /*
Process one option from the configuration file. Process one option from the configuration file.
@@ -103,34 +152,64 @@ C_MODE_END
of the instance map object. of the instance map object.
*/ */
int Instance_map::process_one_option(const char *group, const char *option) int Instance_map::process_one_option(const LEX_STRING *group,
const char *option)
{ {
Instance *instance= NULL; Instance *instance= NULL;
static const char prefix[]= { 'm', 'y', 's', 'q', 'l', 'd' };
if (strncmp(group, prefix, sizeof prefix) == 0 && if (!Instance::is_name_valid(group))
((my_isdigit(default_charset_info, group[sizeof prefix])) {
|| group[sizeof(prefix)] == '\0')) /*
Current section name is not a valid instance name.
We should skip it w/o error.
*/
return 0;
}
if (!(instance= (Instance *) hash_search(&hash, (byte *) group->str,
group->length)))
{
if (!(instance= new Instance()))
return 1;
if (instance->init(group) || add_instance(instance))
{ {
if (!(instance= (Instance *) hash_search(&hash, (byte *) group, delete instance;
strlen(group)))) return 1;
{
if (!(instance= new Instance))
goto err;
if (instance->init(group) || my_hash_insert(&hash, (byte *) instance))
goto err_instance;
}
if (instance->options.add_option(option))
goto err; /* the instance'll be deleted when we destroy the map */
} }
return 0; if (instance->is_mysqld_compatible())
log_info("Warning: instance name '%s' is mysqld-compatible.",
(const char *) group->str);
err_instance: log_info("mysqld instance '%s' has been added successfully.",
delete instance; (const char *) group->str);
err: }
return 1;
if (option)
{
char option_name[MAX_OPTION_LEN + 1];
char option_value[MAX_OPTION_LEN + 1];
parse_option(option, option_name, option_value);
if (instance->is_mysqld_compatible() &&
Instance_options::is_option_im_specific(option_name))
{
log_info("Warning: configuration of mysqld-compatible instance '%s' "
"contains IM-specific option '%s'. "
"This breaks backward compatibility for the configuration file.",
(const char *) group->str,
(const char *) option_name);
}
Named_value option(option_name, option_value);
if (instance->options.set_option(&option))
return 1; /* the instance'll be deleted when we destroy the map */
}
return 0;
} }
@@ -181,7 +260,7 @@ void Instance_map::unlock()
- pass on the new map to the guardian thread: it will start - pass on the new map to the guardian thread: it will start
all instances that are marked `guarded' and not yet started. all instances that are marked `guarded' and not yet started.
Note, as the check whether an instance is started is currently Note, as the check whether an instance is started is currently
very simple (returns true if there is a MySQL server running very simple (returns TRUE if there is a MySQL server running
at the given port), this function has some peculiar at the given port), this function has some peculiar
side-effects: side-effects:
* if the port number of a running instance was changed, the * if the port number of a running instance was changed, the
@@ -194,9 +273,9 @@ void Instance_map::unlock()
In order to avoid such side effects one should never call In order to avoid such side effects one should never call
FLUSH INSTANCES without prior stop of all running instances. FLUSH INSTANCES without prior stop of all running instances.
TODO NOTE: The operation should be invoked with the following locks acquired:
FLUSH INSTANCES should return an error if it's called - Guardian_thread;
while there is a running instance. - Instance_map;
*/ */
int Instance_map::flush_instances() int Instance_map::flush_instances()
@@ -209,67 +288,169 @@ int Instance_map::flush_instances()
guardian (2) reload the instance map (3) reinitialize the guardian guardian (2) reload the instance map (3) reinitialize the guardian
with new instances. with new instances.
*/ */
guardian->lock();
pthread_mutex_lock(&LOCK_instance_map);
hash_free(&hash); hash_free(&hash);
hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0, hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0,
get_instance_key, delete_instance, 0); get_instance_key, delete_instance, 0);
rc= load(); rc= load();
guardian->init(); guardian->init();
pthread_mutex_unlock(&LOCK_instance_map);
guardian->unlock();
return rc; return rc;
} }
Instance * bool Instance_map::is_there_active_instance()
Instance_map::find(const char *name, uint name_len)
{ {
Instance *instance; Instance *instance;
pthread_mutex_lock(&LOCK_instance_map); Iterator iterator(this);
instance= (Instance *) hash_search(&hash, (byte *) name, name_len);
pthread_mutex_unlock(&LOCK_instance_map); while ((instance= iterator.next()))
return instance; {
if (guardian->find_instance_node(instance) != NULL ||
instance->is_running())
{
return TRUE;
}
}
return FALSE;
} }
int Instance_map::complete_initialization() int Instance_map::add_instance(Instance *instance)
{ {
Instance *instance; return my_hash_insert(&hash, (byte *) instance);
uint i= 0; }
if (hash.records == 0) /* no instances found */ int Instance_map::remove_instance(Instance *instance)
{
return hash_delete(&hash, (byte *) instance);
}
int Instance_map::create_instance(const LEX_STRING *instance_name,
const Named_value_arr *options)
{
Instance *instance= new Instance();
if (!instance)
{ {
if ((instance= new Instance) == 0) log_error("Error: can not initialize (name: '%s').",
goto err; (const char *) instance_name->str);
return ER_OUT_OF_RESOURCES;
if (instance->init("mysqld") || my_hash_insert(&hash, (byte *) instance))
goto err_instance;
/*
After an instance have been added to the instance_map,
hash_free should handle it's deletion => goto err, not
err_instance.
*/
if (instance->complete_initialization(this, mysqld_path,
DEFAULT_SINGLE_INSTANCE))
goto err;
} }
else
while (i < hash.records) if (instance->init(instance_name))
{
log_error("Error: can not initialize (name: '%s').",
(const char *) instance_name->str);
delete instance;
return ER_OUT_OF_RESOURCES;
}
for (int i= 0; options && i < options->get_size(); ++i)
{
Named_value option= options->get_element(i);
if (instance->is_mysqld_compatible() &&
Instance_options::is_option_im_specific(option.get_name()))
{ {
instance= (Instance *) hash_element(&hash, i); log_error("Error: IM-option (%s) can not be used "
if (instance->complete_initialization(this, mysqld_path, USUAL_INSTANCE)) "in configuration of mysqld-compatible instance (%s).",
goto err; (const char *) option.get_name(),
i++; (const char *) instance_name->str);
delete instance;
return ER_INCOMPATIBLE_OPTION;
} }
instance->options.set_option(&option);
}
if (instance->is_mysqld_compatible())
log_info("Warning: instance name '%s' is mysqld-compatible.",
(const char *) instance_name->str);
if (instance->complete_initialization(this, mysqld_path))
{
log_error("Error: can not complete initialization of instance (name: '%s').",
(const char *) instance_name->str);
delete instance;
return ER_OUT_OF_RESOURCES;
/* TODO: return more appropriate error code in this case. */
}
if (add_instance(instance))
{
log_error("Error: can not register instance (name: '%s').",
(const char *) instance_name->str);
delete instance;
return ER_OUT_OF_RESOURCES;
}
return 0; return 0;
err_instance: }
delete instance;
err:
return 1; Instance * Instance_map::find(const LEX_STRING *name)
{
return (Instance *) hash_search(&hash, (byte *) name->str, name->length);
}
bool Instance_map::complete_initialization()
{
bool mysqld_found;
/* Complete initialization of all registered instances. */
for (uint i= 0; i < hash.records; ++i)
{
Instance *instance= (Instance *) hash_element(&hash, i);
if (instance->complete_initialization(this, mysqld_path))
return TRUE;
}
/* That's all if we are runnning in an ordinary mode. */
if (!Options::Main::mysqld_safe_compatible)
return FALSE;
/* In mysqld-compatible mode we must ensure that there 'mysqld' instance. */
mysqld_found= find(&Instance::DFLT_INSTANCE_NAME) != NULL;
if (mysqld_found)
return FALSE;
if (create_instance(&Instance::DFLT_INSTANCE_NAME, NULL))
{
log_error("Error: could not create default instance.");
return TRUE;
}
switch (create_instance_in_file(&Instance::DFLT_INSTANCE_NAME, NULL))
{
case 0:
case ER_CONF_FILE_DOES_NOT_EXIST:
/*
Continue if the instance has been added to the config file
successfully, or the config file just does not exist.
*/
break;
default:
log_error("Error: could not add default instance to the config file.");
Instance *instance= find(&Instance::DFLT_INSTANCE_NAME);
if (instance)
remove_instance(instance); /* instance is deleted here. */
return TRUE;
}
return FALSE;
} }
@@ -297,10 +478,10 @@ int Instance_map::load()
name and start looking for files named "my.cnf.cnf" in all name and start looking for files named "my.cnf.cnf" in all
default dirs. Which is not what we want. default dirs. Which is not what we want.
*/ */
if (Options::is_forced_default_file) if (Options::Main::is_forced_default_file)
{ {
snprintf(defaults_file_arg, FN_REFLEN, "--defaults-file=%s", snprintf(defaults_file_arg, FN_REFLEN, "--defaults-file=%s",
Options::config_file); Options::Main::config_file);
argv_options[1]= defaults_file_arg; argv_options[1]= defaults_file_arg;
argv_options[2]= '\0'; argv_options[2]= '\0';
@@ -314,15 +495,12 @@ int Instance_map::load()
If the routine failed, we'll simply fallback to defaults in If the routine failed, we'll simply fallback to defaults in
complete_initialization(). complete_initialization().
*/ */
if (my_search_option_files(Options::config_file, &argc, if (my_search_option_files(Options::Main::config_file, &argc,
(char ***) &argv, &args_used, (char ***) &argv, &args_used,
process_option, (void*) this)) process_option, (void*) this))
log_info("Falling back to compiled-in defaults"); log_info("Falling back to compiled-in defaults");
if (complete_initialization()) return complete_initialization();
return 1;
return 0;
} }
@@ -343,3 +521,105 @@ Instance *Instance_map::Iterator::next()
return NULL; return NULL;
} }
const char *Instance_map::get_instance_state_name(Instance *instance)
{
LIST *instance_node;
if (!instance->is_configured())
return "misconfigured";
if ((instance_node= guardian->find_instance_node(instance)) != NULL)
{
/* The instance is managed by Guardian: we can report precise state. */
return Guardian_thread::get_instance_state_name(
guardian->get_instance_state(instance_node));
}
/* The instance is not managed by Guardian: we can report status only. */
return instance->is_running() ? "online" : "offline";
}
/*
Create a new configuration section for mysqld-instance in the config file.
SYNOPSYS
create_instance_in_file()
instance_name mysqld-instance name
options options for the new mysqld-instance
RETURN
0 On success
ER_CONF_FILE_DOES_NOT_EXIST If config file does not exist
ER_ACCESS_OPTION_FILE If config file is not writable or some I/O
error ocurred during writing configuration
*/
int create_instance_in_file(const LEX_STRING *instance_name,
const Named_value_arr *options)
{
File cnf_file;
if (my_access(Options::Main::config_file, W_OK))
{
log_error("Error: configuration file (%s) does not exist.",
(const char *) Options::Main::config_file);
return ER_CONF_FILE_DOES_NOT_EXIST;
}
cnf_file= my_open(Options::Main::config_file, O_WRONLY | O_APPEND, MYF(0));
if (cnf_file <= 0)
{
log_error("Error: can not open configuration file (%s): %s.",
(const char *) Options::Main::config_file,
(const char *) strerror(errno));
return ER_ACCESS_OPTION_FILE;
}
if (my_write(cnf_file, (byte*)NEWLINE, NEWLINE_LEN, MYF(MY_NABP)) ||
my_write(cnf_file, (byte*)"[", 1, MYF(MY_NABP)) ||
my_write(cnf_file, (byte*)instance_name->str, instance_name->length,
MYF(MY_NABP)) ||
my_write(cnf_file, (byte*)"]", 1, MYF(MY_NABP)) ||
my_write(cnf_file, (byte*)NEWLINE, NEWLINE_LEN, MYF(MY_NABP)))
{
log_error("Error: can not write to configuration file (%s): %s.",
(const char *) Options::Main::config_file,
(const char *) strerror(errno));
my_close(cnf_file, MYF(0));
return ER_ACCESS_OPTION_FILE;
}
for (int i= 0; options && i < options->get_size(); ++i)
{
char option_str[MAX_OPTION_STR_LEN];
char *ptr;
int option_str_len;
Named_value option= options->get_element(i);
ptr= strxnmov(option_str, MAX_OPTION_LEN + 1, option.get_name(), NullS);
if (option.get_value()[0])
ptr= strxnmov(ptr, MAX_OPTION_LEN + 2, "=", option.get_value(), NullS);
option_str_len= ptr - option_str;
if (my_write(cnf_file, (byte*)option_str, option_str_len, MYF(MY_NABP)) ||
my_write(cnf_file, (byte*)NEWLINE, NEWLINE_LEN, MYF(MY_NABP)))
{
log_error("Error: can not write to configuration file (%s): %s.",
(const char *) Options::Main::config_file,
(const char *) strerror(errno));
my_close(cnf_file, MYF(0));
return ER_ACCESS_OPTION_FILE;
}
}
my_close(cnf_file, MYF(0));
return 0;
}

View File

@@ -17,21 +17,24 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <my_global.h> #include <my_global.h>
#include "protocol.h"
#include "guardian.h"
#include <my_sys.h> #include <my_sys.h>
#include <m_string.h>
#include <hash.h> #include <hash.h>
#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE) #if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
#pragma interface #pragma interface
#endif #endif
class Guardian_thread;
class Instance; class Instance;
class Named_value_arr;
extern int load_all_groups(char ***groups, const char *filename); extern int load_all_groups(char ***groups, const char *filename);
extern void free_groups(char **groups); extern void free_groups(char **groups);
extern int create_instance_in_file(const LEX_STRING *instance_name,
const Named_value_arr *options);
/* /*
Instance_map - stores all existing instances Instance_map - stores all existing instances
@@ -56,22 +59,64 @@ public:
}; };
friend class Iterator; friend class Iterator;
public: public:
/* returns a pointer to the instance or NULL, if there is no such instance */ /*
Instance *find(const char *name, uint name_len); Return a pointer to the instance or NULL, if there is no such instance.
MT-NOTE: must be called under acquired lock.
*/
Instance *find(const LEX_STRING *name);
/* Clear the configuration cache and reload the configuration file. */
int flush_instances(); int flush_instances();
/* The operation is used to check if there is an active instance or not. */
bool is_there_active_instance();
void lock(); void lock();
void unlock(); void unlock();
int init(); int init();
/* /*
Process a given option and assign it to appropricate instance. This is Process a given option and assign it to appropricate instance. This is
required for the option handler, passed to my_search_option_files(). required for the option handler, passed to my_search_option_files().
*/ */
int process_one_option(const char *group, const char *option); int process_one_option(const LEX_STRING *group, const char *option);
/*
Add an instance into the internal hash.
MT-NOTE: the operation must be called under acquired lock.
*/
int add_instance(Instance *instance);
/*
Remove instance from the internal hash.
MT-NOTE: the operation must be called under acquired lock.
*/
int remove_instance(Instance *instance);
/*
Create a new instance and register it in the internal hash.
MT-NOTE: the operation must be called under acquired lock.
*/
int create_instance(const LEX_STRING *instance_name,
const Named_value_arr *options);
Instance_map(const char *default_mysqld_path_arg); Instance_map(const char *default_mysqld_path_arg);
~Instance_map(); ~Instance_map();
/*
Retrieve client state name of the given instance.
MT-NOTE: the options must be called under acquired locks of the following
objects:
- Instance_map;
- Guardian_thread;
*/
const char *get_instance_state_name(Instance *instance);
public: public:
const char *mysqld_path; const char *mysqld_path;
Guardian_thread *guardian; Guardian_thread *guardian;
@@ -80,7 +125,7 @@ private:
/* loads options from config files */ /* loads options from config files */
int load(); int load();
/* inits instances argv's after all options have been loaded */ /* inits instances argv's after all options have been loaded */
int complete_initialization(); bool complete_initialization();
private: private:
enum { START_HASH_SIZE = 16 }; enum { START_HASH_SIZE = 16 };
pthread_mutex_t LOCK_instance_map; pthread_mutex_t LOCK_instance_map;

View File

@@ -20,28 +20,24 @@
#include "instance_options.h" #include "instance_options.h"
#include "parse_output.h" #include <my_global.h>
#include "buffer.h"
#include "log.h"
#include <my_sys.h> #include <my_sys.h>
#include <signal.h>
#include <m_string.h> #include <m_string.h>
#ifdef __WIN__ #include <signal.h>
#define NEWLINE_LEN 2
#else #include "buffer.h"
#define NEWLINE_LEN 1 #include "instance.h"
#endif #include "log.h"
#include "parse_output.h"
#include "priv.h"
/* Create "mysqld ..." command in the buffer */ /* Create "mysqld ..." command in the buffer */
static inline int create_mysqld_command(Buffer *buf, static inline int create_mysqld_command(Buffer *buf,
const char *mysqld_path_str, const LEX_STRING *mysqld_path,
uint mysqld_path_len, const LEX_STRING *option)
const char *option,
uint option_len)
{ {
int position= 0; int position= 0;
@@ -50,13 +46,13 @@ static inline int create_mysqld_command(Buffer *buf,
#ifdef __WIN__ #ifdef __WIN__
buf->append(position++, "\"", 1); buf->append(position++, "\"", 1);
#endif #endif
buf->append(position, mysqld_path_str, mysqld_path_len); buf->append(position, mysqld_path->str, mysqld_path->length);
position+= mysqld_path_len; position+= mysqld_path->length;
#ifdef __WIN__ #ifdef __WIN__
buf->append(position++, "\"", 1); buf->append(position++, "\"", 1);
#endif #endif
/* here the '\0' character is copied from the option string */ /* here the '\0' character is copied from the option string */
buf->append(position, option, option_len); buf->append(position, option->str, option->length + 1);
return buf->is_error(); return buf->is_error();
} }
@@ -64,6 +60,42 @@ static inline int create_mysqld_command(Buffer *buf,
} }
bool Instance_options::is_option_im_specific(const char *option_name)
{
static const char *IM_SPECIFIC_OPTIONS[] =
{
"nonguarded",
"mysqld-path",
"shutdown-delay",
NULL
};
for (int i= 0; IM_SPECIFIC_OPTIONS[i]; ++i)
{
if (!strcmp(option_name, IM_SPECIFIC_OPTIONS[i]))
return TRUE;
}
return FALSE;
}
Instance_options::Instance_options()
:mysqld_version(NULL), mysqld_socket(NULL), mysqld_datadir(NULL),
mysqld_pid_file(NULL), mysqld_port(NULL), mysqld_port_val(0),
nonguarded(NULL), shutdown_delay(NULL), shutdown_delay_val(0),
filled_default_options(0)
{
mysqld_path.str= NULL;
mysqld_path.length= 0;
mysqld_real_path.str= NULL;
mysqld_real_path.length= 0;
memset(logs, 0, sizeof(logs));
}
/* /*
Get compiled-in value of default_option Get compiled-in value of default_option
@@ -87,13 +119,13 @@ int Instance_options::get_default_option(char *result, size_t result_len,
const char *option_name) const char *option_name)
{ {
int rc= 1; int rc= 1;
char verbose_option[]= " --no-defaults --verbose --help"; LEX_STRING verbose_option=
{ C_STRING_WITH_SIZE(" --no-defaults --verbose --help") };
/* reserve space fot the path + option + final '\0' */ /* reserve space for the path + option + final '\0' */
Buffer cmd(mysqld_path_len + sizeof(verbose_option)); Buffer cmd(mysqld_path.length + verbose_option.length + 1);
if (create_mysqld_command(&cmd, mysqld_path, mysqld_path_len, if (create_mysqld_command(&cmd, &mysqld_path, &verbose_option))
verbose_option, sizeof(verbose_option)))
goto err; goto err;
/* +2 eats first "--" from the option string (E.g. "--datadir") */ /* +2 eats first "--" from the option string (E.g. "--datadir") */
@@ -121,21 +153,19 @@ err:
int Instance_options::fill_instance_version() int Instance_options::fill_instance_version()
{ {
enum { MAX_VERSION_STRING_LENGTH= 160 }; char result[MAX_VERSION_LENGTH];
char result[MAX_VERSION_STRING_LENGTH]; LEX_STRING version_option=
char version_option[]= " --no-defaults --version"; { C_STRING_WITH_SIZE(" --no-defaults --version") };
int rc= 1; int rc= 1;
Buffer cmd(mysqld_path_len + sizeof(version_option)); Buffer cmd(mysqld_path.length + version_option.length + 1);
if (create_mysqld_command(&cmd, mysqld_path, mysqld_path_len, if (create_mysqld_command(&cmd, &mysqld_path, &version_option))
version_option, sizeof(version_option)))
goto err; goto err;
bzero(result, MAX_VERSION_STRING_LENGTH); bzero(result, MAX_VERSION_LENGTH);
rc= parse_output_and_get_value(cmd.buffer, "Ver", rc= parse_output_and_get_value(cmd.buffer, "Ver", result,
result, MAX_VERSION_STRING_LENGTH, MAX_VERSION_LENGTH, GET_LINE);
GET_LINE);
if (*result != '\0') if (*result != '\0')
{ {
@@ -146,6 +176,7 @@ int Instance_options::fill_instance_version()
start= result; start= result;
while (my_isspace(default_charset_info, *start)) while (my_isspace(default_charset_info, *start))
++start; ++start;
mysqld_version= strdup_root(&alloc, start); mysqld_version= strdup_root(&alloc, start);
} }
err: err:
@@ -178,12 +209,12 @@ err:
int Instance_options::fill_mysqld_real_path() int Instance_options::fill_mysqld_real_path()
{ {
char result[FN_REFLEN]; char result[FN_REFLEN];
char help_option[]= " --no-defaults --help"; LEX_STRING help_option=
{ C_STRING_WITH_SIZE(" --no-defaults --help") };
int rc= 1; int rc= 1;
Buffer cmd(mysqld_path_len + sizeof(help_option)); Buffer cmd(mysqld_path.length + help_option.length);
if (create_mysqld_command(&cmd, mysqld_path, mysqld_path_len, if (create_mysqld_command(&cmd, &mysqld_path, &help_option))
help_option, sizeof(help_option)))
goto err; goto err;
bzero(result, FN_REFLEN); bzero(result, FN_REFLEN);
@@ -198,7 +229,8 @@ int Instance_options::fill_mysqld_real_path()
/* chop the path of at [OPTIONS] */ /* chop the path of at [OPTIONS] */
if ((options_str= strstr(result, "[OPTIONS]"))) if ((options_str= strstr(result, "[OPTIONS]")))
*options_str= '\0'; *options_str= '\0';
mysqld_real_path= strdup_root(&alloc, result); mysqld_real_path.str= strdup_root(&alloc, result);
mysqld_real_path.length= strlen(mysqld_real_path.str);
} }
err: err:
if (rc) if (rc)
@@ -255,8 +287,7 @@ int Instance_options::fill_log_options()
else else
{ {
/* below is safe, as --datadir always has a value */ /* below is safe, as --datadir always has a value */
strmake(datadir, strmake(datadir, mysqld_datadir, MAX_LOG_OPTION_LENGTH - 1);
strchr(mysqld_datadir, '=') + 1, MAX_LOG_OPTION_LENGTH - 1);
} }
if (gethostname(hostname,sizeof(hostname)-1) < 0) if (gethostname(hostname,sizeof(hostname)-1) < 0)
@@ -342,7 +373,6 @@ err:
int Instance_options::get_pid_filename(char *result) int Instance_options::get_pid_filename(char *result)
{ {
const char *pid_file= mysqld_pid_file;
char datadir[MAX_PATH_LEN]; char datadir[MAX_PATH_LEN];
if (mysqld_datadir == NULL) if (mysqld_datadir == NULL)
@@ -352,14 +382,10 @@ int Instance_options::get_pid_filename(char *result)
return 1; return 1;
} }
else else
strxnmov(datadir, MAX_PATH_LEN - 1, strchr(mysqld_datadir, '=') + 1, strxnmov(datadir, MAX_PATH_LEN - 1, mysqld_datadir, "/", NullS);
"/", NullS);
DBUG_ASSERT(mysqld_pid_file);
pid_file= strchr(pid_file, '=') + 1;
/* get the full path to the pidfile */ /* get the full path to the pidfile */
my_load_path(result, pid_file, datadir); my_load_path(result, mysqld_pid_file, datadir);
return 0; return 0;
} }
@@ -388,23 +414,23 @@ pid_t Instance_options::get_pid()
} }
int Instance_options::complete_initialization(const char *default_path, int Instance_options::complete_initialization(const char *default_path)
uint instance_type)
{ {
int arg_idx;
const char *tmp; const char *tmp;
char *end; char *end;
if (!mysqld_path && !(mysqld_path= strdup_root(&alloc, default_path))) if (!mysqld_path.str && !(mysqld_path.str= strdup_root(&alloc, default_path)))
goto err; goto err;
// it's safe to cast this to char* since this is a buffer we are allocating // it's safe to cast this to char* since this is a buffer we are allocating
end= convert_dirname((char*)mysqld_path, mysqld_path, NullS); end= convert_dirname((char*)mysqld_path.str, mysqld_path.str, NullS);
end[-1]= 0; end[-1]= 0;
mysqld_path_len= strlen(mysqld_path); mysqld_path.length= strlen(mysqld_path.str);
if (mysqld_port) if (mysqld_port)
mysqld_port_val= atoi(strchr(mysqld_port, '=') + 1); mysqld_port_val= atoi(mysqld_port);
if (shutdown_delay) if (shutdown_delay)
shutdown_delay_val= atoi(shutdown_delay); shutdown_delay_val= atoi(shutdown_delay);
@@ -412,7 +438,7 @@ int Instance_options::complete_initialization(const char *default_path,
if (!(tmp= strdup_root(&alloc, "--no-defaults"))) if (!(tmp= strdup_root(&alloc, "--no-defaults")))
goto err; goto err;
if (!(mysqld_pid_file)) if (!mysqld_pid_file)
{ {
char pidfilename[MAX_PATH_LEN]; char pidfilename[MAX_PATH_LEN];
char hostname[MAX_PATH_LEN]; char hostname[MAX_PATH_LEN];
@@ -421,26 +447,27 @@ int Instance_options::complete_initialization(const char *default_path,
If we created only one istance [mysqld], because no config. files were If we created only one istance [mysqld], because no config. files were
found, we would like to model mysqld pid file values. found, we would like to model mysqld pid file values.
*/ */
if (!gethostname(hostname, sizeof(hostname) - 1)) if (!gethostname(hostname, sizeof(hostname) - 1))
{ {
if (instance_type & DEFAULT_SINGLE_INSTANCE) if (Instance::is_mysqld_compatible_name(&instance_name))
strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", hostname, strxnmov(pidfilename, MAX_PATH_LEN - 1, hostname, ".pid", NullS);
".pid", NullS);
else else
strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", instance_name, strxnmov(pidfilename, MAX_PATH_LEN - 1, instance_name.str, "-",
"-", hostname, ".pid", NullS); hostname, ".pid", NullS);
} }
else else
{ {
if (instance_type & DEFAULT_SINGLE_INSTANCE) if (Instance::is_mysqld_compatible_name(&instance_name))
strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", "mysql", strxnmov(pidfilename, MAX_PATH_LEN - 1, "mysql", ".pid", NullS);
".pid", NullS);
else else
strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", instance_name, strxnmov(pidfilename, MAX_PATH_LEN - 1, instance_name.str, ".pid",
".pid", NullS); NullS);
} }
add_option(pidfilename); Named_value option((char *) "pid-file", pidfilename);
set_option(&option);
} }
if (get_pid_filename(pid_file_with_path)) if (get_pid_filename(pid_file_with_path))
@@ -448,20 +475,37 @@ int Instance_options::complete_initialization(const char *default_path,
/* we need to reserve space for the final zero + possible default options */ /* we need to reserve space for the final zero + possible default options */
if (!(argv= (char**) if (!(argv= (char**)
alloc_root(&alloc, (options_array.elements + 1 alloc_root(&alloc, (get_num_options() + 1
+ MAX_NUMBER_OF_DEFAULT_OPTIONS) * sizeof(char*)))) + MAX_NUMBER_OF_DEFAULT_OPTIONS) * sizeof(char*))))
goto err; goto err;
filled_default_options= 0;
/* the path must be first in the argv */ /* the path must be first in the argv */
if (add_to_argv(mysqld_path)) if (add_to_argv(mysqld_path.str))
goto err; goto err;
if (add_to_argv(tmp)) if (add_to_argv(tmp))
goto err; goto err;
memcpy((gptr) (argv + filled_default_options), options_array.buffer, arg_idx= filled_default_options;
options_array.elements*sizeof(char*)); for (int opt_idx= 0; opt_idx < get_num_options(); ++opt_idx)
argv[filled_default_options + options_array.elements]= 0; {
char option_str[MAX_OPTION_STR_LEN];
Named_value option= get_option(opt_idx);
if (is_option_im_specific(option.get_name()))
continue;
char *ptr= strxnmov(option_str, MAX_OPTION_LEN + 3, "--", option.get_name(),
NullS);
if (option.get_value()[0])
strxnmov(ptr, MAX_OPTION_LEN + 2, "=", option.get_value(), NullS);
argv[arg_idx++]= strdup_root(&alloc, option_str);
}
argv[arg_idx]= 0;
if (fill_log_options() || fill_mysqld_real_path() || fill_instance_version()) if (fill_log_options() || fill_mysqld_real_path() || fill_instance_version())
goto err; goto err;
@@ -473,75 +517,91 @@ err:
} }
/* bool Instance_options::set_option(Named_value *option)
Assigns given value to the appropriate option from the class.
SYNOPSYS
add_option()
option string with the option prefixed by --
DESCRIPTION
The method is called from the option handling routine.
RETURN
0 - ok
1 - error occured
*/
int Instance_options::add_option(const char* option)
{ {
char *tmp; bool err_status;
enum { SAVE_VALUE= 1, SAVE_WHOLE, SAVE_WHOLE_AND_ADD }; int idx= find_option(option->get_name());
struct selected_options_st char *option_name_str;
char *option_value_str;
if (!(option_name_str= Named_value::alloc_str(option->get_name())))
return TRUE;
if (!(option_value_str= Named_value::alloc_str(option->get_value())))
{
Named_value::free_str(&option_name_str);
return TRUE;
}
Named_value option_copy(option_name_str, option_value_str);
if (idx < 0)
err_status= options.add_element(&option_copy);
else
err_status= options.replace_element(idx, &option_copy);
if (!err_status)
update_var(option_copy.get_name(), option_copy.get_value());
else
option_copy.free();
return err_status;
}
void Instance_options::unset_option(const char *option_name)
{
int idx= find_option(option_name);
if (idx < 0)
return; /* the option has not been set. */
options.remove_element(idx);
update_var(option_name, NULL);
}
void Instance_options::update_var(const char *option_name,
const char *option_value)
{
struct options_st
{ {
const char *name; const char *name;
uint length; uint name_len;
const char **value; const char **var;
uint type; } options_def[]=
} options[]=
{ {
{"--socket=", 9, &mysqld_socket, SAVE_WHOLE_AND_ADD}, {"socket", 6, &mysqld_socket},
{"--port=", 7, &mysqld_port, SAVE_WHOLE_AND_ADD}, {"port", 4, &mysqld_port},
{"--datadir=", 10, &mysqld_datadir, SAVE_WHOLE_AND_ADD}, {"datadir", 7, &mysqld_datadir},
{"--bind-address=", 15, &mysqld_bind_address, SAVE_WHOLE_AND_ADD}, {"pid-file", 8, &mysqld_pid_file},
{"--pid-file=", 11, &mysqld_pid_file, SAVE_WHOLE_AND_ADD}, {"nonguarded", 10, &nonguarded},
{"--mysqld-path=", 14, &mysqld_path, SAVE_VALUE}, {"mysqld-path", 11, (const char **) &mysqld_path.str},
{"--nonguarded", 9, &nonguarded, SAVE_WHOLE}, {"shutdown-delay", 14, &shutdown_delay},
{"--shutdown_delay", 9, &shutdown_delay, SAVE_VALUE}, {NULL, 0, NULL}
{NULL, 0, NULL, 0}
}; };
struct selected_options_st *selected_options;
if (!(tmp= strdup_root(&alloc, option))) for (options_st *opt= options_def; opt->name; ++opt)
goto err; {
if (!strncmp(opt->name, option_name, opt->name_len))
{
*(opt->var)= option_value;
break;
}
}
}
for (selected_options= options; selected_options->name; selected_options++)
{
if (strncmp(tmp, selected_options->name, selected_options->length) == 0)
switch (selected_options->type) {
case SAVE_WHOLE_AND_ADD:
*(selected_options->value)= tmp;
insert_dynamic(&options_array,(gptr) &tmp);
return 0;
case SAVE_VALUE:
*(selected_options->value)= strchr(tmp, '=') + 1;
return 0;
case SAVE_WHOLE:
*(selected_options->value)= tmp;
return 0;
default:
break;
}
}
/* if we haven't returned earlier we should just save the option */ int Instance_options::find_option(const char *option_name)
insert_dynamic(&options_array,(gptr) &tmp); {
for (int i= 0; i < get_num_options(); i++)
{
if (!strcmp(get_option(i).get_name(), option_name))
return i;
}
return 0; return -1;
err:
return 1;
} }
@@ -559,7 +619,10 @@ int Instance_options::add_to_argv(const char* option)
void Instance_options::print_argv() void Instance_options::print_argv()
{ {
int i; int i;
printf("printing out an instance %s argv:\n", instance_name);
printf("printing out an instance %s argv:\n",
(const char *) instance_name.str);
for (i=0; argv[i] != NULL; i++) for (i=0; argv[i] != NULL; i++)
printf("argv: %s\n", argv[i]); printf("argv: %s\n", argv[i]);
} }
@@ -570,17 +633,17 @@ void Instance_options::print_argv()
Return value: 0 - ok. 1 - unable to allocate memory. Return value: 0 - ok. 1 - unable to allocate memory.
*/ */
int Instance_options::init(const char *instance_name_arg) int Instance_options::init(const LEX_STRING *instance_name_arg)
{ {
instance_name_len= strlen(instance_name_arg); instance_name.length= instance_name_arg->length;
init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0); init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0);
if (my_init_dynamic_array(&options_array, sizeof(char*), 0, 32)) if (options.init())
goto err; goto err;
if (!(instance_name= strmake_root(&alloc, (char*) instance_name_arg, if (!(instance_name.str= strmake_root(&alloc, instance_name_arg->str,
instance_name_len))) instance_name_arg->length)))
goto err; goto err;
return 0; return 0;
@@ -593,6 +656,4 @@ err:
Instance_options::~Instance_options() Instance_options::~Instance_options()
{ {
free_root(&alloc, MYF(0)); free_root(&alloc, MYF(0));
delete_dynamic(&options_array);
} }

View File

@@ -18,8 +18,9 @@
#include <my_global.h> #include <my_global.h>
#include <my_sys.h> #include <my_sys.h>
#include "parse.h" #include "parse.h"
#include "portability.h" #include "portability.h" /* for pid_t on Win32 */
#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE) #if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
#pragma interface #pragma interface
@@ -35,25 +36,26 @@
don't have to synchronize between threads. don't have to synchronize between threads.
*/ */
#define USUAL_INSTANCE 0
#define DEFAULT_SINGLE_INSTANCE 1
class Instance_options class Instance_options
{ {
public: public:
Instance_options() : /* The operation is used to check if the option is IM-specific or not. */
mysqld_version(0), mysqld_socket(0), mysqld_datadir(0), static bool is_option_im_specific(const char *option_name);
mysqld_bind_address(0), mysqld_pid_file(0), mysqld_port(0),
mysqld_port_val(0), mysqld_path(0), mysqld_real_path(0), public:
nonguarded(0), shutdown_delay(0), Instance_options();
shutdown_delay_val(0), filled_default_options(0)
{}
~Instance_options(); ~Instance_options();
/* fills in argv */ /* fills in argv */
int complete_initialization(const char *default_path, uint instance_type); int complete_initialization(const char *default_path);
int add_option(const char* option); bool set_option(Named_value *option);
int init(const char *instance_name_arg); void unset_option(const char *option_name);
inline int get_num_options() const;
inline Named_value get_option(int idx) const;
public:
int init(const LEX_STRING *instance_name_arg);
pid_t get_pid(); pid_t get_pid();
int get_pid_filename(char *result); int get_pid_filename(char *result);
int unlink_pidfile(); int unlink_pidfile();
@@ -66,7 +68,6 @@ public:
*/ */
enum { MAX_PATH_LEN= 512 }; enum { MAX_PATH_LEN= 512 };
enum { MAX_NUMBER_OF_DEFAULT_OPTIONS= 2 }; enum { MAX_NUMBER_OF_DEFAULT_OPTIONS= 2 };
enum { MEM_ROOT_BLOCK_SIZE= 512 };
char pid_file_with_path[MAX_PATH_LEN]; char pid_file_with_path[MAX_PATH_LEN];
char **argv; char **argv;
/* /*
@@ -77,23 +78,18 @@ public:
/* We need the some options, so we store them as a separate pointers */ /* We need the some options, so we store them as a separate pointers */
const char *mysqld_socket; const char *mysqld_socket;
const char *mysqld_datadir; const char *mysqld_datadir;
const char *mysqld_bind_address;
const char *mysqld_pid_file; const char *mysqld_pid_file;
const char *mysqld_port; const char *mysqld_port;
uint mysqld_port_val; uint mysqld_port_val;
const char *instance_name; LEX_STRING instance_name;
uint instance_name_len; LEX_STRING mysqld_path;
const char *mysqld_path; LEX_STRING mysqld_real_path;
uint mysqld_path_len;
const char *mysqld_real_path;
const char *nonguarded; const char *nonguarded;
const char *shutdown_delay; const char *shutdown_delay;
uint shutdown_delay_val; uint shutdown_delay_val;
/* log enums are defined in parse.h */ /* log enums are defined in parse.h */
char *logs[3]; char *logs[3];
/* this value is computed and cashed here */
DYNAMIC_ARRAY options_array;
private: private:
int fill_log_options(); int fill_log_options();
int fill_instance_version(); int fill_instance_version();
@@ -101,9 +97,27 @@ private:
int add_to_argv(const char *option); int add_to_argv(const char *option);
int get_default_option(char *result, size_t result_len, int get_default_option(char *result, size_t result_len,
const char *option_name); const char *option_name);
void update_var(const char *option_name, const char *option_value);
int find_option(const char *option_name);
private: private:
uint filled_default_options; uint filled_default_options;
MEM_ROOT alloc; MEM_ROOT alloc;
Named_value_arr options;
}; };
inline int Instance_options::get_num_options() const
{
return options.get_size();
}
inline Named_value Instance_options::get_option(int idx) const
{
return options.get_element(idx);
}
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_OPTIONS_H */ #endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_OPTIONS_H */

View File

@@ -19,21 +19,23 @@
#endif #endif
#include "listener.h" #include "listener.h"
#include "priv.h"
#include <m_string.h> #include <my_global.h>
#include <mysql.h> #include <mysql.h>
#include <violite.h> #include <violite.h>
#include <sys/stat.h>
#ifndef __WIN__ #ifndef __WIN__
#include <sys/un.h> #include <sys/un.h>
#endif #endif
#include <sys/stat.h>
#include "thread_registry.h"
#include "options.h"
#include "instance_map.h" #include "instance_map.h"
#include "log.h" #include "log.h"
#include "mysql_connection.h" #include "mysql_connection.h"
#include "options.h"
#include "portability.h" #include "portability.h"
#include "priv.h"
#include "thread_registry.h"
/* /*
@@ -62,8 +64,7 @@ private:
Listener_thread::Listener_thread(const Listener_thread_args &args) : Listener_thread::Listener_thread(const Listener_thread_args &args) :
Listener_thread_args(args.thread_registry, args.options, args.user_map, Listener_thread_args(args.thread_registry, args.user_map, args.instance_map)
args.instance_map)
,total_connection_count(0) ,total_connection_count(0)
,thread_info(pthread_self()) ,thread_info(pthread_self())
,num_sockets(0) ,num_sockets(0)
@@ -234,14 +235,16 @@ int Listener_thread::create_tcp_socket()
bzero(&ip_socket_address, sizeof(ip_socket_address)); bzero(&ip_socket_address, sizeof(ip_socket_address));
ulong im_bind_addr; ulong im_bind_addr;
if (options.bind_address != 0) if (Options::Main::bind_address != 0)
{ {
if ((im_bind_addr= (ulong) inet_addr(options.bind_address)) == INADDR_NONE) im_bind_addr= (ulong) inet_addr(Options::Main::bind_address);
if (im_bind_addr == INADDR_NONE)
im_bind_addr= htonl(INADDR_ANY); im_bind_addr= htonl(INADDR_ANY);
} }
else else
im_bind_addr= htonl(INADDR_ANY); im_bind_addr= htonl(INADDR_ANY);
uint im_port= options.port_number; uint im_port= Options::Main::port_number;
ip_socket_address.sin_family= AF_INET; ip_socket_address.sin_family= AF_INET;
ip_socket_address.sin_addr.s_addr= im_bind_addr; ip_socket_address.sin_addr.s_addr= im_bind_addr;
@@ -295,7 +298,7 @@ create_unix_socket(struct sockaddr_un &unix_socket_address)
bzero(&unix_socket_address, sizeof(unix_socket_address)); bzero(&unix_socket_address, sizeof(unix_socket_address));
unix_socket_address.sun_family= AF_UNIX; unix_socket_address.sun_family= AF_UNIX;
strmake(unix_socket_address.sun_path, options.socket_file_name, strmake(unix_socket_address.sun_path, Options::Main::socket_file_name,
sizeof(unix_socket_address.sun_path)); sizeof(unix_socket_address.sun_path));
unlink(unix_socket_address.sun_path); // in case we have stale socket file unlink(unix_socket_address.sun_path); // in case we have stale socket file

View File

@@ -27,23 +27,19 @@
pthread_handler_t listener(void *arg); pthread_handler_t listener(void *arg);
class Thread_registry; class Thread_registry;
struct Options;
class User_map; class User_map;
class Instance_map; class Instance_map;
struct Listener_thread_args struct Listener_thread_args
{ {
Thread_registry &thread_registry; Thread_registry &thread_registry;
const Options &options;
const User_map &user_map; const User_map &user_map;
Instance_map &instance_map; Instance_map &instance_map;
Listener_thread_args(Thread_registry &thread_registry_arg, Listener_thread_args(Thread_registry &thread_registry_arg,
const Options &options_arg,
const User_map &user_map_arg, const User_map &user_map_arg,
Instance_map &instance_map_arg) : Instance_map &instance_map_arg) :
thread_registry(thread_registry_arg) thread_registry(thread_registry_arg)
,options(options_arg)
,user_map(user_map_arg) ,user_map(user_map_arg)
,instance_map(instance_map_arg) ,instance_map(instance_map_arg)
{} {}

View File

@@ -14,14 +14,16 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <my_global.h>
#include "log.h" #include "log.h"
#include "portability.h"
#include <stdarg.h> #include <my_global.h>
#include <m_string.h> #include <m_string.h>
#include <my_sys.h> #include <my_sys.h>
#include <stdarg.h>
#include "portability.h" /* for vsnprintf() on Windows. */
/* /*
TODO: TODO:
- add flexible header support - add flexible header support
@@ -71,7 +73,7 @@ static inline void log(FILE *file, const char *format, va_list args)
{ {
int size= sizeof(buff_stack) * 2; int size= sizeof(buff_stack) * 2;
buff_msg= (char*) my_malloc(size, MYF(0)); buff_msg= (char*) my_malloc(size, MYF(0));
while (true) while (TRUE)
{ {
if (buff_msg == 0) if (buff_msg == 0)
{ {

View File

@@ -14,39 +14,55 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <my_global.h>
#include "manager.h" #include "manager.h"
#include "priv.h" #include <my_global.h>
#include "thread_registry.h"
#include "listener.h"
#include "instance_map.h"
#include "options.h"
#include "user_map.h"
#include "log.h"
#include "guardian.h"
#include <my_sys.h>
#include <m_string.h> #include <m_string.h>
#include <signal.h> #include <my_sys.h>
#include <thr_alarm.h> #include <thr_alarm.h>
#include <signal.h>
#ifndef __WIN__ #ifndef __WIN__
#include <sys/wait.h> #include <sys/wait.h>
#endif #endif
#include "exit_codes.h"
#include "guardian.h"
#include "instance_map.h"
#include "listener.h"
#include "log.h"
#include "options.h"
#include "priv.h"
#include "thread_registry.h"
#include "user_map.h"
int create_pid_file(const char *pid_file_name, int pid) int create_pid_file(const char *pid_file_name, int pid)
{ {
if (FILE *pid_file= my_fopen(pid_file_name, FILE *pid_file;
O_WRONLY | O_CREAT | O_BINARY, MYF(0)))
if (!(pid_file= my_fopen(pid_file_name, O_WRONLY | O_CREAT | O_BINARY,
MYF(0))))
{ {
fprintf(pid_file, "%d\n", (int) pid); log_error("Error: can not create pid file '%s': %s (errno: %d)",
my_fclose(pid_file, MYF(0)); (const char *) pid_file_name,
return 0; (const char *) strerror(errno),
(int) errno);
return 1;
} }
log_error("can't create pid file %s: errno=%d, %s",
pid_file_name, errno, strerror(errno)); if (fprintf(pid_file, "%d\n", (int) pid) <= 0)
return 1; {
log_error("Error: can not write to pid file '%s': %s (errno: %d)",
(const char *) pid_file_name,
(const char *) strerror(errno),
(int) errno);
return 1;
}
my_fclose(pid_file, MYF(0));
return 0;
} }
#ifndef __WIN__ #ifndef __WIN__
@@ -82,14 +98,14 @@ bool have_signal;
void onsignal(int signo) void onsignal(int signo)
{ {
have_signal= true; have_signal= TRUE;
} }
void set_signals(sigset_t *set) void set_signals(sigset_t *set)
{ {
signal(SIGINT, onsignal); signal(SIGINT, onsignal);
signal(SIGTERM, onsignal); signal(SIGTERM, onsignal);
have_signal= false; have_signal= FALSE;
} }
int my_sigwait(const sigset_t *set, int *sig) int my_sigwait(const sigset_t *set, int *sig)
@@ -109,10 +125,16 @@ int my_sigwait(const sigset_t *set, int *sig)
listener thread, write pid file and enter into signal handling. listener thread, write pid file and enter into signal handling.
See also comments in mysqlmanager.cc to picture general Instance Manager See also comments in mysqlmanager.cc to picture general Instance Manager
architecture. architecture.
TODO: how about returning error status.
*/ */
void manager(const Options &options) void manager()
{ {
int err_code;
const char *err_msg;
bool shutdown_complete= FALSE;
Thread_registry thread_registry; Thread_registry thread_registry;
/* /*
All objects created in the manager() function live as long as All objects created in the manager() function live as long as
@@ -121,31 +143,60 @@ void manager(const Options &options)
*/ */
User_map user_map; User_map user_map;
Instance_map instance_map(options.default_mysqld_path); Instance_map instance_map(Options::Main::default_mysqld_path);
Guardian_thread guardian_thread(thread_registry, Guardian_thread guardian_thread(thread_registry,
&instance_map, &instance_map,
options.monitoring_interval); Options::Main::monitoring_interval);
Listener_thread_args listener_args(thread_registry, options, user_map, Listener_thread_args listener_args(thread_registry, user_map, instance_map);
instance_map);
manager_pid= getpid(); manager_pid= getpid();
instance_map.guardian= &guardian_thread; instance_map.guardian= &guardian_thread;
if (instance_map.init() || user_map.init()) /* Initialize instance map. */
return;
if (user_map.load(options.password_file_name)) if (instance_map.init())
{
log_error("Error: can not initialize instance list: out of memory.");
return; return;
}
/* Initialize user map and load password file. */
if (user_map.init())
{
log_error("Error: can not initialize user list: out of memory.");
return;
}
if ((err_code= user_map.load(Options::Main::password_file_name, &err_msg)))
{
if (err_code == ERR_PASSWORD_FILE_DOES_NOT_EXIST &&
Options::Main::mysqld_safe_compatible)
{
/*
The password file does not exist, but we are running in
mysqld_safe-compatible mode. Continue, but complain in log.
*/
log_error("Warning: password file does not exist, "
"nobody will be able to connect to Instance Manager.");
}
else
{
log_error("Error: %s.", (const char *) err_msg);
return;
}
}
/* write Instance Manager pid file */ /* write Instance Manager pid file */
log_info("IM pid file: '%s'; PID: %d.", log_info("IM pid file: '%s'; PID: %d.",
(const char *) options.pid_file_name, (const char *) Options::Main::pid_file_name,
(int) manager_pid); (int) manager_pid);
if (create_pid_file(options.pid_file_name, manager_pid)) if (create_pid_file(Options::Main::pid_file_name, manager_pid))
return; return; /* necessary logging has been already done. */
sigset_t mask; sigset_t mask;
set_signals(&mask); set_signals(&mask);
@@ -198,17 +249,23 @@ void manager(const Options &options)
To work nicely with LinuxThreads, the signal thread is the first thread To work nicely with LinuxThreads, the signal thread is the first thread
in the process. in the process.
*/ */
int signo;
bool shutdown_complete;
shutdown_complete= FALSE;
if (instance_map.flush_instances())
{ {
log_error("Cannot init instances repository. This might be caused by " instance_map.guardian->lock();
"the wrong config file options. For instance, missing mysqld " instance_map.lock();
"binary. Aborting.");
return; int flush_instances_status= instance_map.flush_instances();
instance_map.unlock();
instance_map.guardian->unlock();
if (flush_instances_status)
{
log_error("Cannot init instances repository. This might be caused by "
"the wrong config file options. For instance, missing mysqld "
"binary. Aborting.");
return;
}
} }
/* /*
@@ -219,6 +276,7 @@ void manager(const Options &options)
while (!shutdown_complete) while (!shutdown_complete)
{ {
int signo;
int status= 0; int status= 0;
if ((status= my_sigwait(&mask, &signo)) != 0) if ((status= my_sigwait(&mask, &signo)) != 0)
@@ -245,7 +303,7 @@ void manager(const Options &options)
{ {
if (!guardian_thread.is_stopped()) if (!guardian_thread.is_stopped())
{ {
bool stop_instances= true; bool stop_instances= TRUE;
guardian_thread.request_shutdown(stop_instances); guardian_thread.request_shutdown(stop_instances);
pthread_cond_signal(&guardian_thread.COND_guardian); pthread_cond_signal(&guardian_thread.COND_guardian);
} }
@@ -259,7 +317,7 @@ void manager(const Options &options)
err: err:
/* delete the pid file */ /* delete the pid file */
my_delete(options.pid_file_name, MYF(0)); my_delete(Options::Main::pid_file_name, MYF(0));
#ifndef __WIN__ #ifndef __WIN__
/* free alarm structures */ /* free alarm structures */
@@ -267,4 +325,3 @@ err:
/* don't pthread_exit to kill all threads who did not shut down in time */ /* don't pthread_exit to kill all threads who did not shut down in time */
#endif #endif
} }

View File

@@ -16,9 +16,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
struct Options; void manager();
void manager(const Options &options);
int create_pid_file(const char *pid_file_name, int pid); int create_pid_file(const char *pid_file_name, int pid);

View File

@@ -14,15 +14,14 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <my_global.h>
#include "messages.h" #include "messages.h"
#include <my_global.h>
#include <mysql_com.h>
#include "mysqld_error.h" #include "mysqld_error.h"
#include "mysql_manager_error.h" #include "mysql_manager_error.h"
#include <mysql_com.h>
#include <assert.h>
static const char *mysqld_error_message(unsigned sql_errno) static const char *mysqld_error_message(unsigned sql_errno)
{ {
@@ -70,6 +69,23 @@ static const char *mysqld_error_message(unsigned sql_errno)
"in the instance options"; "in the instance options";
case ER_ACCESS_OPTION_FILE: case ER_ACCESS_OPTION_FILE:
return "Cannot open the option file to edit. Check permissions"; return "Cannot open the option file to edit. Check permissions";
case ER_DROP_ACTIVE_INSTANCE:
return "Cannot drop an active instance. You should stop it first";
case ER_CREATE_EXISTING_INSTANCE:
return "Instance already exists";
case ER_INSTANCE_MISCONFIGURED:
return "Instance is misconfigured. Cannot start it";
case ER_MALFORMED_INSTANCE_NAME:
return "Malformed instance name.";
case ER_INSTANCE_IS_ACTIVE:
return "The instance is active. Stop the instance first";
case ER_THERE_IS_ACTIVE_INSTACE:
return "At least one instance is active. Stop all instances first";
case ER_INCOMPATIBLE_OPTION:
return "Instance Manager-specific options are prohibited from being used "
"in the configuration of mysqld-compatible instances";
case ER_CONF_FILE_DOES_NOT_EXIST:
return "Configuration file does not exist";
default: default:
DBUG_ASSERT(0); DBUG_ASSERT(0);
return 0; return 0;

View File

@@ -20,22 +20,24 @@
#include "mysql_connection.h" #include "mysql_connection.h"
#include "priv.h"
#include "mysql_manager_error.h"
#include "mysqld_error.h"
#include "thread_registry.h"
#include "log.h"
#include "user_map.h"
#include "protocol.h"
#include "messages.h"
#include "command.h"
#include "parse.h"
#include <mysql.h>
#include <violite.h>
#include <mysql_com.h>
#include <m_string.h> #include <m_string.h>
#include <m_string.h>
#include <my_global.h>
#include <mysql_com.h>
#include <mysql.h>
#include <my_sys.h> #include <my_sys.h>
#include <violite.h>
#include "command.h"
#include "log.h"
#include "messages.h"
#include "mysqld_error.h"
#include "mysql_manager_error.h"
#include "parse.h"
#include "priv.h"
#include "protocol.h"
#include "thread_registry.h"
#include "user_map.h"
Mysql_connection_thread_args::Mysql_connection_thread_args( Mysql_connection_thread_args::Mysql_connection_thread_args(
@@ -56,7 +58,7 @@ Mysql_connection_thread_args::Mysql_connection_thread_args(
See also comments in mysqlmanager.cc to picture general Instance Manager See also comments in mysqlmanager.cc to picture general Instance Manager
architecture. architecture.
We use conventional technique to work with classes without exceptions: We use conventional technique to work with classes without exceptions:
class acquires all vital resource in init(); Thus if init() succeed, class acquires all vital resource in init(); Thus if init() succeed,
a user must call cleanup(). All other methods are valid only between a user must call cleanup(). All other methods are valid only between
init() and cleanup(). init() and cleanup().
*/ */
@@ -190,8 +192,6 @@ void Mysql_connection_thread::run()
int Mysql_connection_thread::check_connection() int Mysql_connection_thread::check_connection()
{ {
ulong pkt_len=0; // to hold client reply length ulong pkt_len=0; // to hold client reply length
/* maximum size of the version string */
enum { MAX_VERSION_LENGTH= 80 };
/* buffer for the first packet */ /* packet contains: */ /* buffer for the first packet */ /* packet contains: */
char buff[MAX_VERSION_LENGTH + 1 + // server version, 0-ended char buff[MAX_VERSION_LENGTH + 1 + // server version, 0-ended
@@ -202,8 +202,8 @@ int Mysql_connection_thread::check_connection()
char *pos= buff; char *pos= buff;
ulong server_flags; ulong server_flags;
memcpy(pos, mysqlmanager_version, mysqlmanager_version_length + 1); memcpy(pos, mysqlmanager_version.str, mysqlmanager_version.length + 1);
pos+= mysqlmanager_version_length + 1; pos+= mysqlmanager_version.length + 1;
int4store((uchar*) pos, connection_id); int4store((uchar*) pos, connection_id);
pos+= 4; pos+= 4;
@@ -271,12 +271,14 @@ int Mysql_connection_thread::check_connection()
const char *user= pos; const char *user= pos;
const char *password= strend(user)+1; const char *password= strend(user)+1;
ulong password_len= *password++; ulong password_len= *password++;
LEX_STRING user_name= { (char *) user, password - user - 2 };
if (password_len != SCRAMBLE_LENGTH) if (password_len != SCRAMBLE_LENGTH)
{ {
net_send_error(&net, ER_ACCESS_DENIED_ERROR); net_send_error(&net, ER_ACCESS_DENIED_ERROR);
return 1; return 1;
} }
if (user_map.authenticate(user, password-user-2, password, scramble)) if (user_map.authenticate(&user_name, password, scramble))
{ {
net_send_error(&net, ER_ACCESS_DENIED_ERROR); net_send_error(&net, ER_ACCESS_DENIED_ERROR);
return 1; return 1;
@@ -312,7 +314,7 @@ int Mysql_connection_thread::do_command()
packet= (char*) net.read_pos; packet= (char*) net.read_pos;
enum enum_server_command command= (enum enum_server_command) enum enum_server_command command= (enum enum_server_command)
(uchar) *packet; (uchar) *packet;
log_info("connection %d: packet_length=%d, command=%d", log_info("connection %d: packet_length=%d, command=%d",
connection_id, packet_length, command); connection_id, packet_length, command);
return dispatch_command(command, packet + 1, packet_length - 1); return dispatch_command(command, packet + 1, packet_length - 1);
} }
@@ -336,7 +338,7 @@ int Mysql_connection_thread::dispatch_command(enum enum_server_command command,
if (Command *command= parse_command(&instance_map, packet)) if (Command *command= parse_command(&instance_map, packet))
{ {
int res= 0; int res= 0;
log_info("query for connection %d successefully parsed",connection_id); log_info("query for connection %d successfully parsed",connection_id);
res= command->execute(&net, connection_id); res= command->execute(&net, connection_id);
delete command; delete command;
if (!res) if (!res)
@@ -380,5 +382,5 @@ pthread_handler_t mysql_connection(void *arg)
} }
/* /*
vim: fdm=marker vim: fdm=marker
*/ */

View File

@@ -29,5 +29,13 @@
#define ER_ACCESS_OPTION_FILE 3008 #define ER_ACCESS_OPTION_FILE 3008
#define ER_OFFSET_ERROR 3009 #define ER_OFFSET_ERROR 3009
#define ER_READ_FILE 3010 #define ER_READ_FILE 3010
#define ER_DROP_ACTIVE_INSTANCE 3011
#define ER_CREATE_EXISTING_INSTANCE 3012
#define ER_INSTANCE_MISCONFIGURED 3013
#define ER_MALFORMED_INSTANCE_NAME 3014
#define ER_INSTANCE_IS_ACTIVE 3015
#define ER_THERE_IS_ACTIVE_INSTACE 3016
#define ER_INCOMPATIBLE_OPTION 3017
#define ER_CONF_FILE_DOES_NOT_EXIST 3018
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_MYSQL_MANAGER_ERROR_H */ #endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_MYSQL_MANAGER_ERROR_H */

View File

@@ -15,25 +15,30 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <my_global.h> #include <my_global.h>
#include "manager.h"
#include "options.h"
#include "log.h"
#include <my_sys.h> #include <my_sys.h>
#include <string.h> #include <string.h>
#include <signal.h> #include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifndef __WIN__ #ifndef __WIN__
#include <pwd.h> #include <pwd.h>
#include <grp.h> #include <grp.h>
#include <sys/wait.h> #include <sys/wait.h>
#endif #endif
#include <sys/types.h>
#include <sys/stat.h> #include "log.h"
#include "manager.h"
#include "options.h"
#include "user_management_commands.h"
#ifdef __WIN__ #ifdef __WIN__
#include "windowsservice.h" #include "IMService.h"
#include "WindowsService.h"
#endif #endif
/* /*
Few notes about Instance Manager architecture: Few notes about Instance Manager architecture:
Instance Manager consisits of two processes: the angel process, and the Instance Manager consisits of two processes: the angel process, and the
@@ -59,13 +64,12 @@
*/ */
static void init_environment(char *progname); static void init_environment(char *progname);
#ifndef __WIN__ #ifndef __WIN__
static void daemonize(const char *log_file_name); static void daemonize(const char *log_file_name);
static void angel(const Options &options); static void angel();
static struct passwd *check_user(const char *user); static struct passwd *check_user(const char *user);
static int set_user(const char *user, struct passwd *user_info); static int set_user(const char *user, struct passwd *user_info);
#else
int HandleServiceOptions(Options options);
#endif #endif
@@ -81,41 +85,61 @@ int main(int argc, char *argv[])
{ {
int return_value= 1; int return_value= 1;
init_environment(argv[0]); init_environment(argv[0]);
Options options;
if (options.load(argc, argv)) if ((return_value= Options::load(argc, argv)))
goto err; goto main_end;
if (Options::User_management::cmd)
{
return_value= Options::User_management::cmd->execute();
goto main_end;
}
#ifndef __WIN__ #ifndef __WIN__
struct passwd *user_info; struct passwd *user_info;
if ((user_info= check_user(options.user))) if ((user_info= check_user(Options::Daemon::user)))
{ {
if (set_user(options.user, user_info)) if (set_user(Options::Daemon::user, user_info))
goto err; {
return_value= 1;
goto main_end;
}
} }
if (options.run_as_service) if (Options::Daemon::run_as_service)
{ {
/* forks, and returns only in child */ /* forks, and returns only in child */
daemonize(options.log_file_name); daemonize(Options::Daemon::log_file_name);
/* forks again, and returns only in child: parent becomes angel */ /* forks again, and returns only in child: parent becomes angel */
angel(options); angel();
} }
manager();
#else #else
if (!options.stand_alone)
if (!Options::Service::stand_alone)
{ {
if (HandleServiceOptions(options)) if (HandleServiceOptions())
goto err; {
return_value= 1;
goto main_end;
}
} }
else else
{
manager();
}
#endif #endif
manager(options);
return_value= 0; return_value= 0;
err: main_end:
options.cleanup(); Options::cleanup();
my_end(0); my_end(0);
return return_value; return return_value;
} }
@@ -200,7 +224,7 @@ static void init_environment(char *progname)
MY_INIT(progname); MY_INIT(progname);
log_init(); log_init();
umask(0117); umask(0117);
srand(time(0)); srand((unsigned int) time(0));
} }
@@ -298,7 +322,7 @@ void terminate(int signo)
Angel process will exit silently if mysqlmanager exits normally. Angel process will exit silently if mysqlmanager exits normally.
*/ */
static void angel(const Options &options) static void angel()
{ {
/* install signal handlers */ /* install signal handlers */
sigset_t zeromask; // to sigsuspend in parent sigset_t zeromask; // to sigsuspend in parent
@@ -341,10 +365,10 @@ spawn:
pid= getpid(); /* Get our pid. */ pid= getpid(); /* Get our pid. */
log_info("Angel pid file: '%s'; PID: %d.", log_info("Angel pid file: '%s'; PID: %d.",
(const char *) options.angel_pid_file_name, (const char *) Options::Daemon::angel_pid_file_name,
(int) pid); (int) pid);
create_pid_file(Options::angel_pid_file_name, pid); create_pid_file(Options::Daemon::angel_pid_file_name, pid);
while (child_status == CHILD_OK && is_terminated == 0) while (child_status == CHILD_OK && is_terminated == 0)
sigsuspend(&zeromask); sigsuspend(&zeromask);

Some files were not shown because too many files have changed in this diff Show More