1 /// \file 2 /// \brief Contains code to call sqlite3_exec over a network that does not support shared file handles. 3 /// 4 /// This file is part of RakNet Copyright 2003 Jenkins Software LLC 5 /// 6 /// Raknet is available under the terms of the GPLv3 license, see /usr/local/share/licenses/raknet-3.9.2_10,1/GPLv3. 7 8 9 #ifndef ___SQLITE_3_SERVER_PLUGIN_H 10 #define ___SQLITE_3_SERVER_PLUGIN_H 11 12 /// \brief Control if SQLite3 statements execute in a thread 13 /// \details sqlite3_exec is blocking and will therefore block other operations in the same program<BR> 14 /// If defined, sqlite3_exec executes in a thread so that doesn't happen<BR> 15 /// If the only thing this system is doing is running SQLite, then you'll get marginally better performance by commenting it out. 16 /// \ingroup SQL_LITE_3_PLUGIN 17 #define SQLite3_STATEMENT_EXECUTE_THREADED 18 19 #include "RakNetTypes.h" 20 #include "Export.h" 21 #include "PluginInterface2.h" 22 #include "PacketPriority.h" 23 #include "SocketIncludes.h" 24 #include "DS_Multilist.h" 25 #include "RakString.h" 26 #include "sqlite3.h" 27 #include "SQLite3PluginCommon.h" 28 29 #ifdef SQLite3_STATEMENT_EXECUTE_THREADED 30 #include "ThreadPool.h" 31 #endif 32 33 class RakPeerInterface; 34 35 namespace RakNet 36 { 37 38 /// \brief Exec SQLLite commands over the network 39 /// \details SQLite version 3 supports remote calls via networked file handles, but not over the regular internet<BR> 40 /// This plugin will serialize calls to and results from sqlite3_exec<BR> 41 /// That's all it does - any remote system can execute SQL queries.<BR> 42 /// Intended as a starting platform to derive from for more advanced functionality (security over who can query, etc).<BR> 43 /// Compatible as a plugin with both RakPeerInterface and PacketizedTCP 44 /// \ingroup SQL_LITE_3_PLUGIN 45 class RAK_DLL_EXPORT SQLite3ServerPlugin : public PluginInterface2 46 { 47 public: 48 SQLite3ServerPlugin(); 49 virtual ~SQLite3ServerPlugin(); 50 51 /// Associate identifier with dbHandle, so when we get calls to operate on identifier, we use dbhandle 52 /// If SQLite3_STATEMENT_EXECUTE_THREADED is defined, will start the execution thread the first time a dbHandle is added. 53 /// \return true on success, false on dbIdentifier empty, or already in use 54 virtual bool AddDBHandle(RakNet::RakString dbIdentifier, sqlite3 *dbHandle, bool dbAutoCreated=false); 55 56 /// Stop using a dbHandle, lookup either by identifier or by pointer. 57 /// If SQLite3_STATEMENT_EXECUTE_THREADED is defined, do not call this while processing commands, since the commands run in a thread and might be using the dbHandle 58 /// Call before closing the handle or else SQLite3Plugin won't know that it was closed, and will continue using it 59 void RemoveDBHandle(RakNet::RakString dbIdentifier, bool alsoCloseConnection=false); 60 void RemoveDBHandle(sqlite3 *dbHandle, bool alsoCloseConnection=false); 61 62 /// \internal For plugin handling 63 virtual PluginReceiveResult OnReceive(Packet *packet); 64 virtual void OnAttach(void); 65 virtual void OnDetach(void); 66 67 /// \internal 68 struct NamedDBHandle 69 { 70 RakNet::RakString dbIdentifier; 71 sqlite3 *dbHandle; 72 bool dbAutoCreated; 73 RakNetTimeMS whenCreated; 74 }; 75 76 #ifdef SQLite3_STATEMENT_EXECUTE_THREADED 77 virtual void Update(void); 78 /// \internal 79 struct SQLExecThreadInput 80 { SQLExecThreadInputSQLExecThreadInput81 SQLExecThreadInput() {data=0; packet=0;} 82 char *data; 83 unsigned int length; 84 SystemAddress sender; 85 RakNetTimeMS whenMessageArrived; 86 sqlite3 *dbHandle; 87 Packet *packet; 88 }; 89 90 /// \internal 91 struct SQLExecThreadOutput 92 { SQLExecThreadOutputSQLExecThreadOutput93 SQLExecThreadOutput() {data=0; packet=0;} 94 char *data; 95 unsigned int length; 96 SystemAddress sender; 97 Packet *packet; 98 }; 99 #endif // SQLite3_STATEMENT_EXECUTE_THREADED 100 101 protected: 102 virtual void StopThreads(void); 103 104 // List of databases added with AddDBHandle() 105 DataStructures::Multilist<ML_ORDERED_LIST, NamedDBHandle, RakNet::RakString> dbHandles; 106 107 #ifdef SQLite3_STATEMENT_EXECUTE_THREADED 108 // The point of the sqlThreadPool is so that SQL queries, which are blocking, happen in the thread and don't slow down the rest of the application 109 // The sqlThreadPool has a queue for incoming processing requests. As systems disconnect their pending requests are removed from the list. 110 ThreadPool<SQLExecThreadInput, SQLExecThreadOutput> sqlThreadPool; 111 #endif 112 }; 113 114 }; 115 116 extern bool operator<( const DataStructures::MLKeyRef<RakNet::RakString> &inputKey, const RakNet::SQLite3ServerPlugin::NamedDBHandle &cls ); 117 extern bool operator>( const DataStructures::MLKeyRef<RakNet::RakString> &inputKey, const RakNet::SQLite3ServerPlugin::NamedDBHandle &cls ); 118 extern bool operator==( const DataStructures::MLKeyRef<RakNet::RakString> &inputKey, const RakNet::SQLite3ServerPlugin::NamedDBHandle &cls ); 119 120 #endif 121