Date: Friday, March 10, 2006 @ 13:37:00
Author: zsolt
Path: /cvsroot/carob/libmysequoia
Added: include/HostTokenizer.hpp (1.1) src/HostTokenizer.cpp (1.1)
Modified: src/CarobMySQL.cpp (1.63 -> 1.64) src/Makefile.am (1.9 -> 1.10)
- implemented HostTokenizer
- removed default port 3306
- integrated HostTokenizer
---------------------------+
include/HostTokenizer.hpp | 75 ++++++++++++++++++++
src/CarobMySQL.cpp | 60 +++++++---------
src/HostTokenizer.cpp | 158 ++++++++++++++++++++++++++++++++++++++++++++
src/Makefile.am | 3
4 files changed, 262 insertions(+), 34 deletions(-)
Index: libmysequoia/include/HostTokenizer.hpp
diff -u /dev/null libmysequoia/include/HostTokenizer.hpp:1.1
--- /dev/null Fri Mar 10 13:37:00 2006
+++ libmysequoia/include/HostTokenizer.hpp Fri Mar 10 13:37:00 2006
@@ -0,0 +1,75 @@
+/*
+ * Sequoia: Database clustering technology.
+ * Copyright (C) 2005-2006 Continuent, Inc.
+ * Contact: [EMAIL PROTECTED]
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Initial developer(s): Zsolt Simon, Csaba Simon
+ * Contributor(s):
+ */
+
+#ifndef _HOSTTOKENIZER_HPP
+#define _HOSTTOKENIZER_HPP
+
+#include <string>
+#include <vector>
+
+//Carob includes
+#include <ConnectionParameters.hpp>
+
+typedef struct {
+ std::string host;
+ unsigned int port;
+} HOSTPORT;
+
+class HostTokenizerException
+{
+public:
+ /**
+ * Constructor.
+ * @param s The error message.
+ */
+ HostTokenizerException(std::string s) : message(s) {};
+
+ /**
+ * Return the error message.
+ * @return a string containing the error message
+ */
+ const std::string& description() const { return message; }
+
+private:
+ std::string message;
+};
+
+class HostTokenizer
+{
+public:
+ typedef std::vector<HOSTPORT>::const_iterator const_iterator;
+
+ HostTokenizer(const char *str, const char *defaultpolicy = 0);
+ ~HostTokenizer() {}
+
+ const_iterator begin() { return hosts.begin(); }
+ const_iterator end() { return hosts.end(); }
+
+ CarobNS::ConnectPolicy getPolicy() { return policy; }
+private:
+ std::vector<HOSTPORT> hosts;
+ CarobNS::ConnectPolicy policy;
+
+ bool validChar(const char *p, const char *first, int state);
+ CarobNS::ConnectPolicy HostTokenizer::findPolicy(const char *pol, int len =
0);
+};
+
+#endif /*_HOSTTOKENIZER_HPP*/
Index: libmysequoia/src/CarobMySQL.cpp
diff -u libmysequoia/src/CarobMySQL.cpp:1.63
libmysequoia/src/CarobMySQL.cpp:1.64
--- libmysequoia/src/CarobMySQL.cpp:1.63 Wed Mar 8 08:25:23 2006
+++ libmysequoia/src/CarobMySQL.cpp Fri Mar 10 13:37:00 2006
@@ -23,6 +23,7 @@
#include <CarobStmt.hpp>
#include <IniParser.hpp>
#include <Utils.hpp>
+#include <HostTokenizer.hpp>
/* MySQL include */
#include <errmsg.h>
@@ -107,8 +108,6 @@
{
LOG4CXX_DEBUG(logger, "Entering connect: host=" << host << " user=" << user
<< " passwd=" << passwd << " db=" << db << " port=" << port);
- bool defaultport = false;
-
if (mysqlPtr->status != MYSQL_STATUS_READY)
{
set_error(CR_COMMANDS_OUT_OF_SYNC, SQLT_UNKNOWN);
@@ -163,15 +162,6 @@
port = 25322;
}
- //check if the port contains the hardcoded mysql port (3306)
- //if so, then first try to connect to the default sequoia port (25322)
- //and if is unsuccessful, then to the 3306 port.
- if (port == 3306)
- {
- port = 25322;
- defaultport = true;
- }
-
/* set the default character set if not set */
if (!mysqlPtr->options.charset_name || !*mysqlPtr->options.charset_name)
{
@@ -197,28 +187,23 @@
try
{
- ConnectionParameters connectionParameters(to_wstring(host), port,
- to_wstring(db), to_wstring(user), to_wstring(passwd), DEBUG_LEVEL_OFF,
DEFAULT_POLICY, DEFAULT_RETRY_INTERVAL, true);
+ HostTokenizer ht(host);
+ HostTokenizer::const_iterator hti = ht.begin();
- Connection *newConnectionPtr;
+ LOG4CXX_DEBUG(logger, "Connect (first host): host=" << hti->host << "
port=" << hti->port);
+ port = hti->port;
+ ConnectionParameters connectionParameters(to_wstring(hti->host),
hti->port,
+ to_wstring(db), to_wstring(user), to_wstring(passwd), DEBUG_LEVEL_OFF,
ht.getPolicy(), DEFAULT_RETRY_INTERVAL, true);
+ hti++;
- try {
- newConnectionPtr = new Connection(connectionParameters);
- }
- catch (CarobException &e)
+ for (; hti != ht.end(); hti++)
{
- //if the default port was given and the connection to port 25322
- //failed we try the 3306 port
- if (defaultport && (port == 25322))
- {
- ConnectionParameters connectionParameters2(to_wstring(host), 3306,
- to_wstring(db), to_wstring(user), to_wstring(passwd),
DEBUG_LEVEL_OFF, DEFAULT_POLICY, DEFAULT_RETRY_INTERVAL, true);
- newConnectionPtr = new Connection(connectionParameters2);
- }
- else
- throw;
+ connectionParameters.addController(to_wstring(hti->host), hti->port);
+ LOG4CXX_DEBUG(logger, "Connect (adding host): host=" << hti->host << "
port=" << hti->port);
}
+ Connection *newConnectionPtr = new Connection(connectionParameters);
+
if (newConnectionPtr)
{
//TODO handle not enough memory
@@ -247,6 +232,13 @@
LOG4CXX_DEBUG(logger, "Leaving connect.");
return false;
}
+ catch (HostTokenizerException &e)
+ {
+ set_error(0, e.description().c_str(), error_sqlstate[SQLT_UNKNOWN]);
+ //TODO error handling
+ LOG4CXX_DEBUG(logger, "Leaving connect.");
+ return false;
+ }
}
bool
@@ -905,11 +897,13 @@
break;
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_DATETIME:
- SQLTimeStamp ts = drsPtr->getTimeStamp(i+1);
- getFromDateTime(&b,fPtr,&ts);
- result += buffer;
- field_len = *b.length;
- break;
+ {
+ SQLTimeStamp ts = drsPtr->getTimeStamp(i+1);
+ getFromDateTime(&b,fPtr,&ts);
+ result += buffer;
+ field_len = *b.length;
+ break;
+ }
default:
if (fPtr->flags & BINARY_FLAG)
{
Index: libmysequoia/src/HostTokenizer.cpp
diff -u /dev/null libmysequoia/src/HostTokenizer.cpp:1.1
--- /dev/null Fri Mar 10 13:37:00 2006
+++ libmysequoia/src/HostTokenizer.cpp Fri Mar 10 13:37:00 2006
@@ -0,0 +1,158 @@
+/*
+ * Sequoia: Database clustering technology.
+ * Copyright (C) 2005-2006 Continuent, Inc.
+ * Contact: [EMAIL PROTECTED]
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Initial developer(s): Zsolt Simon, Csaba Simon
+ * Contributor(s):
+ */
+
+#include <HostTokenizer.hpp>
+
+#include <ctype.h>
+
+using namespace std;
+using namespace CarobNS;
+
+const char *policy_list[] = {"roundrobin", 0};
+const int MAXDIGITLEN = 5;
+const int MAXBUFFERSIZE = 1024;
+
+HostTokenizer::HostTokenizer(const char *str, const char *defaultpolicy)
+{
+ /* parse a string of format "[host:port] [host2:port2] [policy=xy]" */
+ const char *pl = str, *pf;
+ bool space;
+ HOSTPORT last;
+ //state showing the internal state of the parsing
+ //0 - host or policy expecting
+ //1 - :, host or policy expecting
+ //2 - port expecting
+ //3 - = expecting
+ //4 - selected policy expecting
+ int state = 0;
+
+ if (defaultpolicy)
+ policy = findPolicy(defaultpolicy);
+ else
+ policy = ROUND_ROBIN;
+
+ if (pl)
+ {
+ while (*pl)
+ {
+ pf = pl;
+ //skip white spaces from the begining
+ while (*pf && isspace(*pf)) ++pf;
+ space = pf != pl || pf == str;
+ pl = pf;
+ while (*pl && validChar(pl, pf, state)) ++pl;
+
+ //if we found a token
+ if (pf != pl && ((!state && space) || state))
+ {
+ int len = pl - pf;
+ switch (state)
+ {
+ case 0:
+ case 1:
+ if (state == 1 && *pf == ':')
+ state++;
+ else
+ {
+ if (state == 1)
+ {
+ //we don't have a port so we add the default one
+ last.port = 25322;
+ hosts.push_back(last);
+ }
+
+ if (!strncasecmp(pf,"policy",len))
+ state = 3;
+ else
+ {
+ last.host = string(pf,len);
+ state = 1;
+ }
+ }
+ break;
+ case 2:
+ last.port = 0;
+ while (pf < pl)
+ last.port = last.port*10 + (*pf++ - '0');
+ hosts.push_back(last);
+ state = 0;
+ break;
+ case 3:
+ state++;
+ break;
+ case 4:
+ policy = findPolicy(pf, len);
+ state = 0;
+ break;
+ }
+ }
+ else
+ if (*pf)
+ {
+ char buffer[MAXBUFFERSIZE];
+ snprintf(buffer, sizeof(buffer), "Invalid or unexpected character
occured '%c' at position: %d", *pf, pf - str);
+ throw HostTokenizerException(buffer);
+ }
+ }
+
+ //if we are in state == 1, it means, there was given a host without port,
so add it to the list
+ if (state == 1)
+ {
+ last.port = 25322;
+ hosts.push_back(last);
+ }
+ }
+}
+
+bool HostTokenizer::validChar(const char *p, const char *first, int state)
+{
+ switch (state)
+ {
+ case 1:
+ if (*first == ':')
+ return first == p;
+ case 0:
+ return isalnum(*p) || ((first != p) && ((*p == '.') || (*p == '-')));
+ case 2:
+ return isdigit(*p) && (p - first <= MAXDIGITLEN);
+ case 3:
+ if (*first == '=')
+ return first == p;
+ case 4:
+ return isalpha(*p) || (*p == '-');
+ }
+
+ return false;
+}
+
+ConnectPolicy HostTokenizer::findPolicy(const char *pol, int len)
+{
+ if (!len)
+ len = strlen(pol);
+
+ const char **p;
+
+ for (p = policy_list; *p && (strncasecmp(pol,*p,len) != 0); p++) ;
+ if (*p)
+ return (ConnectPolicy) (p-policy_list);
+ else
+ throw HostTokenizerException("Invalid connect policy: " + string(pol,len));
+}
Index: libmysequoia/src/Makefile.am
diff -u libmysequoia/src/Makefile.am:1.9 libmysequoia/src/Makefile.am:1.10
--- libmysequoia/src/Makefile.am:1.9 Thu Mar 2 17:23:24 2006
+++ libmysequoia/src/Makefile.am Fri Mar 10 13:37:00 2006
@@ -28,7 +28,8 @@
MySQLAPI.cpp \
Utils.cpp \
IniParser.cpp \
- Converter.cpp
+ Converter.cpp \
+ HostTokenizer.cpp
libmysequoia_la_CXXFLAGS = @MYSQL_CFLAGS@ @GCOV_CFLAGS@
libmysequoia_la_LDFLAGS = -version-info 0:0:0 @GCOV_LDADD@ @LOG4CXX_LDADD@
_______________________________________________
Carob-commits mailing list
[email protected]
https://forge.continuent.org/mailman/listinfo/carob-commits