1 /* 2 Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License, version 2.0, 6 as published by the Free Software Foundation. 7 8 This program is also distributed with certain software (including 9 but not limited to OpenSSL) that is licensed under separate terms, 10 as designated in a particular file or component or in included license 11 documentation. The authors of MySQL hereby grant you an additional 12 permission to link the program and your derivative works with the 13 separately licensed software that they have included with MySQL. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License, version 2.0, for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software 22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 */ 24 25 #ifndef SOCKET_SERVER_HPP 26 #define SOCKET_SERVER_HPP 27 28 #include <NdbTCP.h> 29 #include <NdbMutex.h> 30 #include <NdbThread.h> 31 #include <Vector.hpp> 32 33 extern "C" void* sessionThread_C(void*); 34 extern "C" void* socketServerThread_C(void*); 35 36 /** 37 * Socket Server 38 */ 39 class SocketServer { 40 public: 41 /** 42 * A Session 43 */ 44 class Session { 45 public: ~Session()46 virtual ~Session() {} runSession()47 virtual void runSession(){} stopSession()48 virtual void stopSession(){ m_stop = true; } 49 protected: 50 friend class SocketServer; 51 friend void* sessionThread_C(void*); Session(NDB_SOCKET_TYPE sock)52 Session(NDB_SOCKET_TYPE sock) : 53 m_stop(false), 54 m_socket(sock), 55 m_refCount(0), 56 m_thread_stopped(false) 57 { 58 DBUG_ENTER("SocketServer::Session"); 59 DBUG_PRINT("enter",("NDB_SOCKET: " MY_SOCKET_FORMAT, 60 MY_SOCKET_FORMAT_VALUE(m_socket))); 61 DBUG_VOID_RETURN; 62 } 63 bool m_stop; // Has the session been ordered to stop? 64 NDB_SOCKET_TYPE m_socket; 65 unsigned m_refCount; 66 private: 67 bool m_thread_stopped; // Has the session thread stopped? 68 }; 69 70 /** 71 * A service i.e. a session factory 72 */ 73 class Service { 74 public: Service()75 Service() {} ~Service()76 virtual ~Service(){} 77 78 /** 79 * Returned Session will be ran in own thread 80 * 81 * To manage threads self, just return NULL 82 */ 83 virtual Session * newSession(NDB_SOCKET_TYPE theSock) = 0; stopSessions()84 virtual void stopSessions(){} 85 }; 86 87 /** 88 * Constructor / Destructor 89 */ 90 SocketServer(unsigned maxSessions = ~(unsigned)0); 91 ~SocketServer(); 92 93 /** 94 * Setup socket and bind it 95 * then close the socket 96 * Returns true if succeding in binding 97 */ 98 static bool tryBind(unsigned short port, const char * intface = 0); 99 100 /** 101 * Setup socket 102 * bind & listen 103 * Returns false if no success 104 */ 105 bool setup(Service *, unsigned short *port, const char * pinterface = 0); 106 107 /** 108 * start/stop the server 109 */ 110 struct NdbThread* startServer(); 111 void stopServer(); 112 113 /** 114 * stop sessions 115 * 116 * Note: Implies previous stopServer 117 * 118 * wait, wait until all sessions has stopped if true 119 * wait_timeout - wait, but abort wait after this 120 * time(in milliseconds) 121 * 0 = infinite 122 * 123 * returns false if wait was abandoned 124 * 125 */ 126 bool stopSessions(bool wait = false, unsigned wait_timeout = 0); 127 128 void foreachSession(void (*f)(Session*, void*), void *data); 129 void checkSessions(); 130 131 private: 132 struct SessionInstance { 133 Service * m_service; 134 Session * m_session; 135 NdbThread * m_thread; 136 }; 137 struct ServiceInstance { 138 Service * m_service; 139 NDB_SOCKET_TYPE m_socket; 140 }; 141 NdbLockable m_session_mutex; 142 Vector<SessionInstance> m_sessions; 143 MutexVector<ServiceInstance> m_services; 144 ndb_socket_poller m_services_poller; 145 unsigned m_maxSessions; 146 147 bool doAccept(); 148 void checkSessionsImpl(); 149 void startSession(SessionInstance &); 150 151 /** 152 * Note, this thread is only used when running interactive 153 * 154 */ 155 bool m_stopThread; 156 struct NdbThread * m_thread; 157 NdbLockable m_threadLock; 158 void doRun(); 159 friend void* socketServerThread_C(void*); 160 friend void* sessionThread_C(void*); 161 }; 162 163 #endif 164