X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fextra%2Fm_sqlv2.h;h=c7f6edbb97b51b64f295809fc01a1b388e94ffb3;hb=d556a4f8740b65e635ff7d2b976faaedbdac51d4;hp=ba74fa57f7fb8c3f7fa8fed5e7efb377a00faa6f;hpb=9ab4ee2ea02372ffc1790a14124328e9b4c00ccc;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modules/extra/m_sqlv2.h b/src/modules/extra/m_sqlv2.h index ba74fa57f..c7f6edbb9 100644 --- a/src/modules/extra/m_sqlv2.h +++ b/src/modules/extra/m_sqlv2.h @@ -6,7 +6,7 @@ * See: http://www.inspircd.org/wiki/index.php/Credits * * This program is free but copyrighted software; see - * the file COPYING for details. + * the file COPYING for details. * * --------------------------------------------------- */ @@ -82,16 +82,16 @@ public: */ SQLerror(SQLerrorNum i = NO_ERROR, const std::string &s = "") : id(i), str(s) - { + { } - + /** Return the ID of the error */ SQLerrorNum Id() { return id; } - + /** Set the ID of an error * @param i The new error ID to set * @return the ID which was set @@ -101,7 +101,7 @@ public: id = i; return id; } - + /** Set the error string for an error * @param s The new error string to set */ @@ -109,14 +109,14 @@ public: { str = s; } - + /** Return the error string for an error */ const char* Str() { if(str.length()) return str.c_str(); - + switch(id) { case NO_ERROR: @@ -130,7 +130,7 @@ public: case QREPLY_FAIL: return "Getting query result failed"; default: - return "Unknown error"; + return "Unknown error"; } } }; @@ -155,7 +155,7 @@ public: * * SQLrequest foo = SQLrequest(this, target, "databaseid", (SQLquery("SELECT.. ?"), parameter, parameter)); */ -class SQLquery +class SQLquery : public classbase { public: /** The query 'format string' @@ -181,8 +181,8 @@ public: SQLquery(const std::string &query, const ParamL ¶ms) : q(query), p(params) { - } - + } + /** An overloaded operator for pushing parameters onto the parameter list */ template SQLquery& operator,(const T &foo) @@ -190,7 +190,7 @@ public: p.push_back(ConvToStr(foo)); return *this; } - + /** An overloaded operator for pushing parameters onto the parameter list. * This has higher precedence than 'operator,' and can save on parenthesis. */ @@ -229,7 +229,7 @@ public: /** If an error occured, error.id will be any other value than NO_ERROR. */ SQLerror error; - + /** Initialize an SQLrequest. * For example: * @@ -245,14 +245,14 @@ public: : Request(s, d, SQLREQID), query(q), dbid(databaseid), pri(false), id(0) { } - + /** Set the priority of a request. */ void Priority(bool p = true) { pri = p; } - + /** Set the source of a request. You should not need to use this method. */ void SetSource(Module* mod) @@ -283,7 +283,7 @@ public: SQLfield(const std::string &data = "", bool n = false) : d(data), null(n) { - + } }; @@ -318,7 +318,7 @@ public: * If an error occured the value of error.id will be any * other value than NO_ERROR. */ - SQLerror error; + SQLerror error; /** * This will match query ID you were given when sending * the request at an earlier time. @@ -331,7 +331,7 @@ public: : Request(s, d, SQLRESID), id(i) { } - + /** * Return the number of rows in the result * Note that if you have perfomed an INSERT @@ -343,7 +343,7 @@ public: * @returns Number of rows in the result set. */ virtual int Rows() = 0; - + /** * Return the number of columns in the result. * If you performed an UPDATE or INSERT which @@ -352,14 +352,14 @@ public: * @returns Number of columns in the result set. */ virtual int Cols() = 0; - + /** * Get a string name of the column by an index number * @param column The id number of a column * @returns The column name associated with the given ID */ virtual std::string ColName(int column) = 0; - + /** * Get an index number for a column from a string name. * An exception of type SQLbadColName will be thrown if @@ -368,14 +368,14 @@ public: * @returns The ID number of the column provided */ virtual int ColNum(const std::string &column) = 0; - + /** * Get a string value in a given row and column * This does not effect the internal cursor. * @returns The value stored at [row,column] in the table */ virtual SQLfield GetValue(int row, int column) = 0; - + /** * Return a list of values in a row, this should * increment an internal counter so you can repeatedly @@ -389,14 +389,14 @@ public: * @returns A reference to the current row's SQLfieldList */ virtual SQLfieldList& GetRow() = 0; - + /** * As above, but return a map indexed by key name. * The internal cursor (row counter) is incremented by one. * @returns A reference to the current row's SQLfieldMap */ virtual SQLfieldMap& GetRowMap() = 0; - + /** * Like GetRow(), but returns a pointer to a dynamically * allocated object which must be explicitly freed. For @@ -405,14 +405,14 @@ public: * @returns A newly-allocated SQLfieldList */ virtual SQLfieldList* GetRowPtr() = 0; - + /** * As above, but return a map indexed by key name * The internal cursor (row counter) is incremented by one. * @returns A newly-allocated SQLfieldMap */ virtual SQLfieldMap* GetRowMapPtr() = 0; - + /** * Overloaded function for freeing the lists and maps * returned by GetRowPtr or GetRowMapPtr. @@ -428,4 +428,178 @@ public: virtual void Free(SQLfieldList* fl) = 0; }; + +/** SQLHost represents a config line and is useful + * for storing in a map and iterating on rehash to see which + * tags was added/removed/unchanged. + */ +class SQLhost +{ + public: + std::string id; /* Database handle id */ + std::string host; /* Database server hostname */ + std::string ip; /* resolved IP, needed for at least pgsql.so */ + unsigned int port; /* Database server port */ + std::string name; /* Database name */ + std::string user; /* Database username */ + std::string pass; /* Database password */ + bool ssl; /* If we should require SSL */ + + SQLhost() + { + } + + SQLhost(const std::string& i, const std::string& h, unsigned int p, const std::string& n, const std::string& u, const std::string& pa, bool s) + : id(i), host(h), port(p), name(n), user(u), pass(pa), ssl(s) + { + } + + /** Overload this to return a correct Data source Name (DSN) for + * the current SQL module. + */ + std::string GetDSN(); +}; + +/** Overload operator== for two SQLhost objects for easy comparison. + */ +bool operator== (const SQLhost& l, const SQLhost& r) +{ + return (l.id == r.id && l.host == r.host && l.port == r.port && l.name == r.name && l.user == l.user && l.pass == r.pass && l.ssl == r.ssl); +} + + +/** QueryQueue, a queue of queries waiting to be executed. + * This maintains two queues internally, one for 'priority' + * queries and one for less important ones. Each queue has + * new queries appended to it and ones to execute are popped + * off the front. This keeps them flowing round nicely and no + * query should ever get 'stuck' for too long. If there are + * queries in the priority queue they will be executed first, + * 'unimportant' queries will only be executed when the + * priority queue is empty. + * + * We store lists of SQLrequest's here, by value as we want to avoid storing + * any data allocated inside the client module (in case that module is unloaded + * while the query is in progress). + * + * Because we want to work on the current SQLrequest in-situ, we need a way + * of accessing the request we are currently processing, QueryQueue::front(), + * but that call needs to always return the same request until that request + * is removed from the queue, this is what the 'which' variable is. New queries are + * always added to the back of one of the two queues, but if when front() + * is first called then the priority queue is empty then front() will return + * a query from the normal queue, but if a query is then added to the priority + * queue then front() must continue to return the front of the *normal* queue + * until pop() is called. + */ + +class QueryQueue : public classbase +{ +private: + typedef std::deque ReqDeque; + + ReqDeque priority; /* The priority queue */ + ReqDeque normal; /* The 'normal' queue */ + enum { PRI, NOR, NON } which; /* Which queue the currently active element is at the front of */ + +public: + QueryQueue() + : which(NON) + { + } + + void push(const SQLrequest &q) + { + if(q.pri) + priority.push_back(q); + else + normal.push_back(q); + } + + void pop() + { + if((which == PRI) && priority.size()) + { + priority.pop_front(); + } + else if((which == NOR) && normal.size()) + { + normal.pop_front(); + } + + /* Reset this */ + which = NON; + + /* Silently do nothing if there was no element to pop() */ + } + + SQLrequest& front() + { + switch(which) + { + case PRI: + return priority.front(); + case NOR: + return normal.front(); + default: + if(priority.size()) + { + which = PRI; + return priority.front(); + } + + if(normal.size()) + { + which = NOR; + return normal.front(); + } + + /* This will probably result in a segfault, + * but the caller should have checked totalsize() + * first so..meh - moron :p + */ + + return priority.front(); + } + } + + std::pair size() + { + return std::make_pair(priority.size(), normal.size()); + } + + int totalsize() + { + return priority.size() + normal.size(); + } + + void PurgeModule(Module* mod) + { + DoPurgeModule(mod, priority); + DoPurgeModule(mod, normal); + } + +private: + void DoPurgeModule(Module* mod, ReqDeque& q) + { + for(ReqDeque::iterator iter = q.begin(); iter != q.end(); iter++) + { + if(iter->GetSource() == mod) + { + if(iter->id == front().id) + { + /* It's the currently active query.. :x */ + iter->SetSource(NULL); + } + else + { + /* It hasn't been executed yet..just remove it */ + iter = q.erase(iter); + } + } + } + } +}; + + #endif