transactd 3.4.1 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/CMakeLists.txt +2 -2
  3. data/bin/common/tdclc_32_3_5.dll +0 -0
  4. data/bin/common/tdclc_64_3_5.dll +0 -0
  5. data/build/common/options.cmake +12 -0
  6. data/build/common/transactd_cl_common.cmake +1 -0
  7. data/build/common/transactd_required.cmake +5 -0
  8. data/build/swig/ruby/tdclrb_wrap.cpp +1029 -130
  9. data/build/swig/tdcl.i +60 -5
  10. data/build/tdclc/CMakeLists.txt +30 -32
  11. data/build/tdclc/libtdclcm.map +1 -1
  12. data/build/tdclc/tdclc.cbproj +1 -1
  13. data/build/tdclc/tdclc.rc +4 -4
  14. data/build/tdclcpp/CMakeLists.txt +39 -48
  15. data/build/tdclcpp/tdclcpp.rc +4 -4
  16. data/build/tdclcpp/tdclcpp_bc.cbproj +4 -1
  17. data/build/tdclrb/CMakeLists.txt +5 -4
  18. data/build/tdclrb/tdclrb.rc +4 -4
  19. data/source/bzs/db/engine/mysql/database.cpp +45 -35
  20. data/source/bzs/db/engine/mysql/database.h +6 -8
  21. data/source/bzs/db/engine/mysql/dbManager.cpp +11 -0
  22. data/source/bzs/db/engine/mysql/dbManager.h +1 -0
  23. data/source/bzs/db/engine/mysql/ha.cpp +174 -0
  24. data/source/bzs/db/engine/mysql/ha.h +50 -0
  25. data/source/bzs/db/engine/mysql/mysqlInternal.h +18 -1
  26. data/source/bzs/db/engine/mysql/mysqlProtocol.cpp +222 -9
  27. data/source/bzs/db/engine/mysql/mysqlProtocol.h +5 -0
  28. data/source/bzs/db/protocol/tdap/client/client.cpp +23 -9
  29. data/source/bzs/db/protocol/tdap/client/client.h +125 -94
  30. data/source/bzs/db/protocol/tdap/client/connMgr.cpp +139 -30
  31. data/source/bzs/db/protocol/tdap/client/connMgr.h +40 -8
  32. data/source/bzs/db/protocol/tdap/client/database.cpp +17 -17
  33. data/source/bzs/db/protocol/tdap/client/database.h +15 -0
  34. data/source/bzs/db/protocol/tdap/client/dllmain.cpp +10 -4
  35. data/source/bzs/db/protocol/tdap/client/haNameResolver.cpp +486 -0
  36. data/source/bzs/db/protocol/tdap/client/haNameResolver.h +74 -0
  37. data/source/bzs/db/protocol/tdap/client/nsDatabase.cpp +102 -71
  38. data/source/bzs/db/protocol/tdap/client/nsDatabase.h +15 -3
  39. data/source/bzs/db/protocol/tdap/client/nsTable.cpp +2 -5
  40. data/source/bzs/db/protocol/tdap/client/nsTable.h +2 -1
  41. data/source/bzs/db/protocol/tdap/client/sqlBuilder.cpp +2 -2
  42. data/source/bzs/db/protocol/tdap/client/table.cpp +1 -2
  43. data/source/bzs/db/protocol/tdap/client/trdboostapi.h +13 -0
  44. data/source/bzs/db/protocol/tdap/client/trnsctcl.def +1 -0
  45. data/source/bzs/db/protocol/tdap/mysql/databaseSchema.cpp +9 -7
  46. data/source/bzs/db/protocol/tdap/mysql/recordsetReader.h +2 -2
  47. data/source/bzs/db/protocol/tdap/mysql/tdapCommandExecuter.cpp +328 -117
  48. data/source/bzs/db/protocol/tdap/mysql/tdapCommandExecuter.h +7 -8
  49. data/source/bzs/db/protocol/tdap/tdapcapi.h +81 -41
  50. data/source/bzs/db/transactd/connManager.cpp +118 -93
  51. data/source/bzs/db/transactd/connManager.h +6 -1
  52. data/source/bzs/db/transactd/connectionRecord.h +27 -7
  53. data/source/bzs/db/transactd/transactd.cpp +24 -13
  54. data/source/bzs/env/crosscompile.h +2 -0
  55. data/source/bzs/netsvc/client/iconnection.h +2 -0
  56. data/source/bzs/netsvc/client/tcpClient.cpp +45 -14
  57. data/source/bzs/netsvc/client/tcpClient.h +21 -4
  58. data/source/bzs/netsvc/server/IAppModule.h +1 -0
  59. data/source/bzs/netsvc/server/serverCpt.cpp +1 -1
  60. data/source/bzs/netsvc/server/serverPipe.cpp +2 -0
  61. data/source/bzs/netsvc/server/serverTpool.cpp +3 -5
  62. data/source/bzs/test/tdclatl/test_v3.js +91 -3
  63. data/source/bzs/test/tdclphp/transactd_v3_Test.php +89 -3
  64. data/source/bzs/test/tdclrb/transactd_v3_spec.rb +69 -2
  65. data/source/bzs/test/trdclengn/testField.h +19 -1
  66. data/source/bzs/test/trdclengn/test_tdclcpp_ha.cpp +388 -0
  67. data/source/bzs/test/trdclengn/test_tdclcpp_v3.cpp +6 -1
  68. data/source/bzs/test/trdclengn/test_trdclengn.cpp +1 -0
  69. data/source/bzs/test/trdclengn/testbase.h +7 -1
  70. data/source/global/replication/haCommand.cpp +843 -0
  71. data/source/global/replication/haCommand.h +78 -0
  72. data/source/global/replication/haMgr.cpp +321 -0
  73. data/source/global/replication/replCommand.cpp +696 -0
  74. data/source/global/replication/replCommand.h +161 -0
  75. data/source/global/tdclatl/BinlogPos.cpp +10 -0
  76. data/source/global/tdclatl/BinlogPos.h +1 -0
  77. data/source/global/tdclatl/ConnMgr.cpp +89 -2
  78. data/source/global/tdclatl/ConnMgr.h +13 -1
  79. data/source/global/tdclatl/ConnRecord.cpp +8 -2
  80. data/source/global/tdclatl/ConnRecord.h +4 -3
  81. data/source/global/tdclatl/Database.cpp +13 -0
  82. data/source/global/tdclatl/Database.h +2 -0
  83. data/source/global/tdclatl/HaNameREsolver.cpp +54 -0
  84. data/source/global/tdclatl/HaNameREsolver.h +68 -0
  85. data/source/global/tdclatl/resource.h +0 -0
  86. data/source/global/tdclatl/tdclatl.idl +76 -5
  87. metadata +16 -6
  88. data/bin/common/tdclc_32_3_4.dll +0 -0
  89. data/bin/common/tdclc_64_3_4.dll +0 -0
  90. data/source/bzs/db/protocol/tdap/mysql/debuglog.cpp +0 -423
  91. data/source/bzs/db/protocol/tdap/mysql/debuglog.h +0 -116
@@ -53,14 +53,33 @@ public:
53
53
  connRecords();
54
54
  connRecords(const connRecords& r);
55
55
  connRecords& operator=(const connRecords& r);
56
- const record& operator[] (int index) const;
57
- record& operator[] (int index);
56
+ const record& operator[] (size_t index) const;
57
+ record& operator[] (size_t index);
58
58
  size_t size() const;
59
59
  void clear();
60
60
  void release();
61
61
  static connRecords* create();
62
+ static connRecords* create(const connRecords& r);
62
63
  };
63
64
 
65
+ typedef boost::shared_ptr<connRecords> connRecords_ptr;
66
+
67
+ inline void releaseConnRecords(connRecords* p)
68
+ {
69
+ if (p) p->release();
70
+ }
71
+
72
+ inline connRecords_ptr createConnRecords(const connRecords& r)
73
+ {
74
+ return connRecords_ptr(connRecords::create(r), releaseConnRecords);
75
+ }
76
+
77
+ inline connRecords_ptr createConnRecords()
78
+ {
79
+ return connRecords_ptr(connRecords::create(), releaseConnRecords);
80
+ }
81
+
82
+
64
83
  class DLLLIB connMgr : private nstable // no copyable
65
84
  {
66
85
 
@@ -85,7 +104,7 @@ private:
85
104
  const connMgr::records& doDefinedTables(const _TCHAR* dbname, int type);
86
105
  void setBlobFieldPointer(const bzs::db::blobHeader* bd);
87
106
  explicit connMgr(database* db);
88
-
107
+ const records& blobOperation(int op);
89
108
  public:
90
109
 
91
110
  bool connect(const _TCHAR* uri);
@@ -94,22 +113,35 @@ public:
94
113
  const records& tables(const _TCHAR* dbname);
95
114
  const records& views(const _TCHAR* dbname);
96
115
  const records& schemaTables(const _TCHAR* dbname);
97
- const records& slaveStatus();
116
+ const records& slaveStatus(const char* channel=0);
117
+ #ifdef _UNICODE
118
+ const records& slaveStatus(const wchar_t* channel);
119
+ #endif
120
+ const records& channels(bool withLock = false);
121
+ const records& slaveHosts();
98
122
  const records& sysvars();
123
+ const records& extendedvars();
99
124
  const records& statusvars();
100
125
  const records& connections();
101
126
  const records& inUseDatabases(__int64 connid);
102
127
  const records& inUseTables(__int64 connid, int dbid);
103
128
  void postDisconnectOne(__int64 connid);
104
129
  void postDisconnectAll();
105
- short_td stat();
130
+ bool haLock();
131
+ void haUnlock();
132
+ bool setRole(int v);
133
+ bool setTrxBlock(bool v);
134
+ bool setEnableFailover(bool v);
106
135
  database* db() const;
107
- const _TCHAR* slaveStatusName(uint_td index) const;
136
+ const _TCHAR* slaveStatusName(uint_td id) const;
137
+ using nstable::stat;
108
138
  using nstable::tdapErr;
109
139
  using nstable::release;
140
+ using nstable::isOpen;
110
141
  static void removeSystemDb(records& recs);
111
- static const _TCHAR* sysvarName(uint_td index);
112
- static const _TCHAR* statusvarName(uint_td index);
142
+ static const _TCHAR* sysvarName(uint_td id);
143
+ static const _TCHAR* statusvarName(uint_td id);
144
+ static const _TCHAR* extendedVarName(uint_td id);
113
145
  static connMgr* create(database* db);
114
146
  };
115
147
 
@@ -258,8 +258,8 @@ void database::create(const _TCHAR* uri, short type)
258
258
  _TCHAR posblk[128] = { 0x00 };
259
259
  const char* p = toServerUri((char*)buf, MAX_PATH, uri_tmp, true);
260
260
  uint_td len = 0;
261
- stat = m_btrcallid(TD_CREATETABLE, posblk, NULL, &len,
262
- (void*)p, (uchar_td)strlen(p), CR_SUBOP_CREATE_DBONLY , clientID());
261
+ stat = tdapEx(TD_CREATETABLE, posblk, NULL, &len,
262
+ (void*)p, (uchar_td)strlen(p), CR_SUBOP_CREATE_DBONLY);
263
263
  }
264
264
  }
265
265
  else
@@ -440,6 +440,12 @@ void database::doOpen(const _TCHAR* uri, short type, short mode,
440
440
  m_impl->isOpened = (m_stat == STATUS_SUCCESS); // important
441
441
  }
442
442
 
443
+ bool isConnected(const uchar_td* cid)
444
+ {
445
+ const void* p = *((void**)cid);
446
+ return p != 0;
447
+ }
448
+
443
449
  bool database::open(const _TCHAR* _uri, short type, short mode,
444
450
  const _TCHAR* dir, const _TCHAR* ownername)
445
451
  {
@@ -492,7 +498,7 @@ bool database::open(const _TCHAR* _uri, short type, short mode,
492
498
  {
493
499
  if ((compatibleMode() & CMP_MODE_MYSQL_NULL) == 0)
494
500
  m_stat = STATUS_INVALID_NULLMODE;
495
- else if (isAssociate() || connect(_uri))
501
+ else if (isAssociate() || isConnected(clientID()) || connect(_uri))
496
502
  {
497
503
  m_impl->dbDef->allocDatabuffer();
498
504
  m_stat = m_impl->dbDef->stat();
@@ -554,8 +560,7 @@ short database::aclReload()
554
560
  return m_stat = STATUS_DB_YET_OPEN;
555
561
  _TCHAR posblk[128] = { 0x00 };
556
562
  uint_td buflen = 0;
557
- return m_stat =
558
- m_btrcallid(TD_ACL_RELOAD, posblk, NULL, &buflen, 0, 0, 0, clientID());
563
+ return m_stat = tdapEx(TD_ACL_RELOAD, posblk, NULL, &buflen, 0, 0, 0);
559
564
  }
560
565
 
561
566
  char* database::getContinuousList(int option)
@@ -594,8 +599,7 @@ short database::continuous(char_td IsEnd, bool inclideRepfile)
594
599
  char tmp[128] = { 0x00 };
595
600
  char* buf = getContinuousList(inclideRepfile);
596
601
  uint_td buflen = (uint_td)strlen(buf) + 1;
597
- m_stat =
598
- m_btrcallid(TD_BACKUPMODE, tmp, buf, &buflen, 0, 0, IsEnd, clientID());
602
+ m_stat = tdap(TD_BACKUPMODE, tmp, buf, &buflen, 0, 0, IsEnd);
599
603
  free(buf);
600
604
  return m_stat;
601
605
  }
@@ -994,10 +998,8 @@ char* database::getSqlStringForCreateTable(const _TCHAR* tableName, char* retbuf
994
998
 
995
999
  const char* p = toServerUri(buf2, MAX_PATH, uri, isUseTransactd());
996
1000
 
997
- m_stat = m_btrcallid(
998
- TD_TABLE_INFO, posblk, td,
999
- size, (void*)p, (uchar_td)strlen(p),
1000
- ST_SUB_GETSQL_BY_TABLEDEF, clientID());
1001
+ m_stat = tdap(TD_TABLE_INFO, posblk, td, size, (void*)p,
1002
+ (uchar_td)strlen(p), ST_SUB_GETSQL_BY_TABLEDEF);
1001
1003
  return retbuf;
1002
1004
  }
1003
1005
 
@@ -1014,10 +1016,10 @@ bool database::createTable(const char* utf8Sql)
1014
1016
  _TCHAR posblk[128] = { 0x00 };
1015
1017
  const char* p = toServerUri(buf2, MAX_PATH, rootDir(), true);
1016
1018
  uint_td len = (uint_td)strlen(utf8Sql);
1017
- m_stat = m_btrcallid(TD_CREATETABLE, posblk, (void*)utf8Sql, &len,
1019
+ m_stat = tdapEx(TD_CREATETABLE, posblk, (void*)utf8Sql, &len,
1018
1020
  (void*)p, (uchar_td)strlen(p),
1019
1021
  (m_impl->createExistNoCheck) ?
1020
- CR_SUBOP_BY_SQL : CR_SUBOP_BY_SQL_NOCKECK, clientID());
1022
+ CR_SUBOP_BY_SQL : CR_SUBOP_BY_SQL_NOCKECK);
1021
1023
  }
1022
1024
  }
1023
1025
  else
@@ -1044,12 +1046,10 @@ bool database::createTable(short fileNum, const _TCHAR* uri)
1044
1046
 
1045
1047
  const char* p = toServerUri(buf2, MAX_PATH, uri, isUseTransactd());
1046
1048
 
1047
- m_stat = m_btrcallid(
1048
- TD_CREATETABLE, posblk, td,
1049
+ m_stat = tdapEx(TD_CREATETABLE, posblk, td,
1049
1050
  &m_impl->dbDef->m_datalen, (void*)p, (uchar_td)strlen(p),
1050
1051
  (m_impl->createExistNoCheck) ?
1051
- CR_SUBOP_BY_TABLEDEF : CR_SUBOP_BY_TABLEDEF_NOCKECK,
1052
- clientID());
1052
+ CR_SUBOP_BY_TABLEDEF : CR_SUBOP_BY_TABLEDEF_NOCKECK);
1053
1053
  }
1054
1054
  else
1055
1055
  {
@@ -149,6 +149,21 @@ public:
149
149
  static const int CMP_MODE_OLD_NULL = 0;
150
150
  };
151
151
 
152
+ class overrideCompatibleMode
153
+ {
154
+ int mode;
155
+ public:
156
+ inline overrideCompatibleMode(int v)
157
+ {
158
+ mode = database::compatibleMode();
159
+ database::setCompatibleMode(v);
160
+ }
161
+ inline ~overrideCompatibleMode()
162
+ {
163
+ database::setCompatibleMode(mode);
164
+ }
165
+ };
166
+
152
167
  } // namespace client
153
168
  } // namespace tdap
154
169
  } // namespace protocol
@@ -350,7 +350,7 @@ extern "C" PACKAGE_OSX short_td __STDCALL
350
350
  else
351
351
  {
352
352
  client_t->cleanup();
353
- return 1;
353
+ return client_t->result();
354
354
  }
355
355
  }
356
356
  else if (op == TD_OPENTABLE)
@@ -358,7 +358,7 @@ extern "C" PACKAGE_OSX short_td __STDCALL
358
358
  if (!client_t->buildDualChasetKeybuf())
359
359
  {
360
360
  client_t->cleanup();
361
- return SERVER_CLIENT_NOT_COMPATIBLE;
361
+ return client_t->result();
362
362
  }
363
363
  }
364
364
  break;
@@ -461,7 +461,7 @@ const char* dateTimeStr(char* buf, unsigned int bufsize)
461
461
  date = &tmp;
462
462
  localtime_x(date, &now);
463
463
  #endif // NOT __MINGW32__
464
- sprintf_s(buf, bufsize, "%04d/%02d/%02d %02d:%02d:%02d",
464
+ sprintf_s(buf, bufsize, "%04d-%02d-%02dT%02d:%02d:%02d",
465
465
  date->tm_year + 1900, date->tm_mon + 1, date->tm_mday,
466
466
  date->tm_hour, date->tm_min, date->tm_sec);
467
467
  return buf;
@@ -482,7 +482,7 @@ void writeErrorLog(int err, const char* msg)
482
482
  strcpy_s(buf, MAX_PATH, "/var/log");
483
483
  #endif
484
484
 
485
- strcat_s(buf, MAX_PATH, PSEPARATOR "trnsctcl_error.log");
485
+ strcat_s(buf, MAX_PATH, PSEPARATOR TD_CLINET_LOGNAME);
486
486
  FILE* fp = fileOpen(buf, "a+");
487
487
  if (fp)
488
488
  {
@@ -561,3 +561,9 @@ extern "C" PACKAGE_OSX void __STDCALL BeginWinThreadPoolShutdown()
561
561
  {
562
562
  win_thread_pool_shutdown = true;
563
563
  }
564
+
565
+
566
+ extern "C" PACKAGE_OSX void __STDCALL RegisterHaNameResolver(HANAME_RESOLVER_PTR func)
567
+ {
568
+ m_cons->registHaNameResolver(func);
569
+ }
@@ -0,0 +1,486 @@
1
+ /* =================================================================
2
+ Copyright (C) 2016 BizStation Corp All rights reserved.
3
+
4
+ This program is free software; you can redistribute it and/or
5
+ modify it under the terms of the GNU General Public License
6
+ as published by the Free Software Foundation; either version 2
7
+ of the License, or (at your option) any later version.
8
+
9
+ This program is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ GNU General Public License for more details.
13
+
14
+ You should have received a copy of the GNU General Public License
15
+ along with this program; if not, write to the Free Software
16
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17
+ 02111-1307, USA.
18
+ ================================================================= */
19
+ #if defined(__BORLANDC__) && defined(__clang__)
20
+ #define BOOST_THREAD_BUILD_DLL
21
+ #endif
22
+ #include <boost/thread.hpp>
23
+ #include <boost/scoped_ptr.hpp>
24
+ #include "haNameResolver.h"
25
+ #include <bzs/env/compiler.h>
26
+ #include <vector>
27
+ #include <string>
28
+ #include <algorithm>
29
+ #include "nsDatabase.h"
30
+ #include "database.h"
31
+ #include "connMgr.h"
32
+ #ifdef _WIN32
33
+ #include <Shlobj.h>
34
+ #include <direct.h>
35
+ #endif
36
+
37
+ #ifdef __BCPLUSPLUS__
38
+ # pragma package(smart_init)
39
+ # define BZS_LINK_BOOST_THREAD
40
+ # define BZS_LINK_BOOST_FILESYSTEM
41
+ # define BZS_LINK_BOOST_SYSTEM
42
+ # ifdef _WIN64
43
+ # define BZS_LINK_BOOST_CHRONO
44
+ namespace boost { void tss_cleanup_implemented(){} }
45
+ # else
46
+ namespace boost { extern "C" void tss_cleanup_implemented() {} }
47
+ # endif //_WIN64
48
+ # include <bzs/env/boost_bcb_link.h>
49
+ #endif // __BCPLUSPLUS__
50
+
51
+
52
+
53
+ using namespace std;
54
+ boost::mutex g_nr_mutex;
55
+ static string masterRoleName;
56
+ static vector<string> slaveRoleNames;
57
+ static vector<string> slaveHosts;
58
+
59
+ static string user;
60
+ static string passwd;
61
+
62
+ namespace bzs
63
+ {
64
+ namespace db
65
+ {
66
+ namespace protocol
67
+ {
68
+ namespace tdap
69
+ {
70
+ namespace client
71
+ {
72
+
73
+ const char* __STDCALL hostNameResolver(const char* vhost, const char* port, char* buf, unsigned int& opt);
74
+ struct portMap
75
+ {
76
+ short myPort;
77
+ short tdPort;
78
+ portMap(short m, short td) : myPort(m), tdPort(td){}
79
+ };
80
+
81
+ static database* g_db=NULL;
82
+ static connMgr* g_mgr = NULL;
83
+ static connMgr::records g_recs;
84
+ static vector<portMap> g_portMap;
85
+ static string cache_master;
86
+ static string cache_slave;
87
+ static int g_slaveIndex = 0;
88
+ static short g_stat = 0;
89
+ static short g_slaveNum = 0;
90
+ static bool g_failover = false;
91
+ static bool g_failoverError = false;
92
+ static bool g_callFailover = true;
93
+ static bool g_readonly_control = false;
94
+
95
+ void split(vector<string>& ss, const char* s)
96
+ {
97
+ const char* p = s;
98
+ const char* pp = strchr(p, _T(','));
99
+ while (pp)
100
+ {
101
+ string s = string(p, pp);
102
+ ss.push_back(s);
103
+ p = pp + 1;
104
+ pp = strchr(p, _T(','));
105
+ }
106
+ size_t len = strlen(p);
107
+ if (len)
108
+ ss.push_back(string(p, p + len));
109
+ }
110
+
111
+ void disconnect()
112
+ {
113
+ if (g_mgr)
114
+ g_mgr->release();
115
+ if (g_db)
116
+ database::destroy(g_db);
117
+ g_mgr = NULL;
118
+ g_db = NULL;
119
+ }
120
+
121
+ bool connect(const string& host)
122
+ {
123
+ char buf[1024];
124
+ const char* up="@";
125
+ const char* pp="?pwd=";
126
+ if (user == "") { up = ""; pp = "";}
127
+
128
+ sprintf_s(buf, 1024, "tdap://%s%s%s/%s%s", user.c_str(), up,
129
+ host.c_str(), pp, passwd.c_str());
130
+ #ifdef _UNICODE
131
+ _TCHAR bufw[1024];
132
+ MultiByteToWideChar(CP_UTF8, 0, buf, -1, bufw, 1024);
133
+ const _TCHAR* uri = bufw;
134
+ #else
135
+ const _TCHAR* uri = buf;
136
+ #endif
137
+ if (g_mgr->connect(uri))
138
+ return true;
139
+ return false;
140
+ }
141
+
142
+ inline const char* slaveHost()
143
+ {
144
+ return cache_slave.c_str();
145
+ }
146
+
147
+ inline const char* masterHost()
148
+ {
149
+ return cache_master.c_str();
150
+ }
151
+
152
+ inline bool registerHaNameResolver(HANAME_RESOLVER_PTR func)
153
+ {
154
+ return nsdatabase::registerHaNameResolver(func);
155
+ }
156
+
157
+ bool checkSlaveStatus(const char* chnnel)
158
+ {
159
+ g_recs = g_mgr->slaveStatus(chnnel);
160
+ if (g_recs.size() > SLAVE_STATUS_SLAVE_SQL_RUNNING)
161
+ return (strcmp(g_recs[SLAVE_STATUS_SLAVE_SQL_RUNNING].name, "Yes") == 0) &&
162
+ (strcmp(g_recs[SLAVE_STATUS_SLAVE_IO_RUNNING].name, "Yes") == 0);
163
+ return false;
164
+ }
165
+
166
+ bool readReplMaster(const string& host)
167
+ {
168
+ if (connect(host))
169
+ {
170
+ /* read channel with wait lock in the server 60 second max */
171
+ g_recs = g_mgr->channels(true /*withLock*/);
172
+ if (g_recs.size())
173
+ {
174
+ char channle[MAX_PATH];
175
+ g_recs[0].value(channle, MAX_PATH);
176
+ g_recs = g_mgr->statusvars();
177
+ int ha = HA_ROLE_SLAVE;
178
+ if (g_recs.size() > TD_SVAR_HA)
179
+ ha = (int)g_recs[TD_SVAR_HA].longValue;
180
+ if ((ha & (HA_ROLE_MASTER | HA_ROLE_NONE)) == HA_ROLE_SLAVE)
181
+ {
182
+ if (checkSlaveStatus(channle))
183
+ return true;
184
+ }
185
+ }else
186
+ {
187
+ g_recs = g_mgr->statusvars();
188
+ int ha = HA_ROLE_MASTER;
189
+ if (g_recs.size() > TD_SVAR_HA)
190
+ ha = (int)g_recs[TD_SVAR_HA].longValue;
191
+ if ((ha & HA_ROLE_MASTER) == HA_ROLE_MASTER)
192
+ cache_master = host;
193
+ }
194
+ }
195
+ if (g_mgr)
196
+ {
197
+ g_mgr->release();
198
+ g_db->close();
199
+ g_mgr = connMgr::create(g_db);
200
+ }
201
+ return false;
202
+ }
203
+
204
+ bool selectSlave()
205
+ {
206
+ // First try, specified slave server
207
+ g_slaveIndex = g_slaveNum;
208
+ if (g_slaveNum < (short)slaveHosts.size() && readReplMaster(slaveHosts[g_slaveNum]))
209
+ return true;
210
+ // After, each slave of slave list
211
+ for (size_t i=0;i < slaveHosts.size(); ++i)
212
+ {
213
+ if ((short)i != g_slaveNum)
214
+ {
215
+ g_slaveIndex = (int)i;
216
+ if (readReplMaster(slaveHosts[i]))
217
+ return true;
218
+ }
219
+ }
220
+ g_mgr->release();
221
+ g_mgr = NULL;
222
+ return false;
223
+ }
224
+
225
+ char* getHostName(char* str)
226
+ {
227
+ char* p = strchr(str, '\t');
228
+ if (p)
229
+ *p = 0x00;
230
+ return str;
231
+ }
232
+
233
+ int setSlaveHosts()
234
+ {
235
+ if (g_slaveIndex < (short)slaveHosts.size())
236
+ {
237
+ cache_slave = slaveHosts[g_slaveIndex];
238
+ return 0;
239
+ }
240
+ return THNR_SLAVE_HOSTS_NOT_FOUND;
241
+ }
242
+
243
+ void addPort(short port)
244
+ {
245
+ for (size_t i=0;i<g_portMap.size();++i)
246
+ {
247
+ if (g_portMap[i].myPort == port)
248
+ {
249
+ char tmp[24];
250
+ _ltoa_s(g_portMap[i].tdPort, tmp, 24, 10);
251
+ cache_master += ":" + string(tmp);
252
+ return;
253
+ }
254
+ }
255
+ }
256
+
257
+ void setMasterHost()
258
+ {
259
+ char tmp[MAX_PATH];
260
+ cache_master = g_recs[SLAVE_STATUS_MASTER_HOST].value(tmp, MAX_PATH);
261
+ g_recs[SLAVE_STATUS_MASTER_PORT].value(tmp, MAX_PATH);
262
+ addPort((short)atol(tmp));
263
+ }
264
+
265
+ const char* logPath(char* buf)
266
+ {
267
+ #ifdef _WIN32
268
+ SHGetFolderPathA(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, buf);
269
+ strcat_s(buf, MAX_PATH, PSEPARATOR_A "BizStation");
270
+ _mkdir(buf);
271
+ strcat_s(buf, MAX_PATH, PSEPARATOR_A "Transactd");
272
+ _mkdir(buf);
273
+ #else
274
+ strcpy_s(buf, MAX_PATH, "/var/log");
275
+ #endif
276
+ strcat_s(buf, MAX_PATH, PSEPARATOR_A TD_CLINET_LOGNAME);
277
+ return buf;
278
+ }
279
+
280
+ int callFailover()
281
+ {
282
+ const char* fmt = "haMgr%d -c failover -s %s -u %s -p %s %s %s >> %s";
283
+ char tmp[4096];
284
+ int cpu = sizeof(char*) == 8 ? 64 :32;
285
+ string slaves;
286
+ for (size_t i = 0; i < slaveHosts.size(); ++i)
287
+ slaves += slaveHosts[i] + ",";
288
+ if (slaves.size())
289
+ slaves.erase(slaves.end() - 1);
290
+
291
+ string portmap;
292
+ for (size_t i = 0; i < g_portMap.size(); ++i)
293
+ {
294
+ if (i == 0) portmap = "-a ";
295
+ sprintf_s(tmp, 4096, "%d:%d,", g_portMap[i].tdPort, g_portMap[i].myPort);
296
+ portmap += tmp;
297
+ }
298
+ if (portmap.size())
299
+ portmap.erase(portmap.end() - 1);
300
+
301
+ char buf[MAX_PATH];
302
+ logPath(buf);
303
+
304
+ sprintf_s(tmp, 4096, fmt, cpu, slaves.c_str(), user.c_str(), passwd.c_str(),
305
+ portmap.size() ? portmap.c_str() : "",
306
+ g_readonly_control ? "-R1": "", buf);
307
+ return system(tmp);
308
+ }
309
+
310
+ /* Read from the slave server's master */
311
+ int setHosts()
312
+ {
313
+ g_db = database::create();
314
+ g_mgr = connMgr::create(g_db);
315
+ cache_master = "-";
316
+ cache_slave = "-";
317
+ int ret = THNR_INVALID_HOSTS;
318
+ if (selectSlave())
319
+ {
320
+ setMasterHost();
321
+ disconnect();
322
+ ret = setSlaveHosts();
323
+ }else if (cache_master != "-")
324
+ ret = THNR_SLAVE_HOSTS_NOT_FOUND;
325
+ disconnect();
326
+ if (g_failover && !g_failoverError)
327
+ {
328
+ g_failover = false;
329
+ bool fa = cache_master == "-";
330
+ if(!fa)
331
+ {
332
+ g_db = database::create();
333
+ g_mgr = connMgr::create(g_db);
334
+ bool ret = connect(cache_master);
335
+ short stat = g_mgr->stat();
336
+ disconnect();
337
+ fa = (ret == false &&
338
+ stat >= ERROR_TD_HOSTNAME_NOT_FOUND &&
339
+ stat < ERROR_TD_NET_REMOTE_DISCONNECT);
340
+
341
+ }
342
+ if (fa)
343
+ {
344
+ g_failoverError = callFailover() != 0;
345
+ if (!g_failoverError)
346
+ return setHosts();
347
+ }
348
+ }
349
+ return ret;
350
+ }
351
+
352
+ const char* masterHostInternal()
353
+ {
354
+ if (cache_master == "")
355
+ setHosts();
356
+ return cache_master.c_str();
357
+ }
358
+
359
+ const char* slaveHostInternal()
360
+ {
361
+ if (cache_slave == "")
362
+ setHosts();
363
+ return cache_slave.c_str();
364
+ }
365
+
366
+ void updateRsolver()
367
+ {
368
+ boost::mutex::scoped_lock lck(g_nr_mutex);
369
+ if (g_failoverError) return;
370
+ nsdatabase::registerHaNameResolver(NULL);
371
+ g_failover = g_callFailover;
372
+ {
373
+ boost::scoped_ptr<boost::thread> t(new boost::thread(setHosts));
374
+ t->join();
375
+ }
376
+ g_failover = false;
377
+ registerHaNameResolver(hostNameResolver);
378
+ }
379
+
380
+ /* During the startResolver,resolver dose not work. */
381
+ int haNameResolver::start(const char* master, const char* slaves,
382
+ const char* slvHosts, short slaveNum,const char* userName,
383
+ const char* password, int option)
384
+ {
385
+ boost::mutex::scoped_lock lck(g_nr_mutex);
386
+ g_callFailover = (option & THNR_OPT_DISABLE_CALL_FAILOVER) == 0;
387
+ g_readonly_control = (option & THNR_OPT_FO_READONLY_CONTROL) == 0;
388
+ registerHaNameResolver(NULL);
389
+ masterRoleName = master;
390
+ split(slaveRoleNames, slaves);
391
+ split(slaveHosts, slvHosts);
392
+ g_slaveNum = slaveNum;
393
+ user = userName;
394
+ passwd = password;
395
+ int ret = setHosts();
396
+ if (ret <= THNR_SLAVE_HOSTS_NOT_FOUND)
397
+ {
398
+ if (!registerHaNameResolver(hostNameResolver))
399
+ ret = THNR_REGISTER_FUNC_ERROR;
400
+ if (ret != THNR_REGISTER_FUNC_ERROR &&
401
+ cache_slave == "-" &&
402
+ option & THNR_OPT_MASTER_CAN_CONCUR_SLAVE)
403
+ cache_slave = cache_master;
404
+ }
405
+ return ret;
406
+ }
407
+
408
+ void haNameResolver::stop()
409
+ {
410
+ boost::mutex::scoped_lock lck(g_nr_mutex);
411
+ registerHaNameResolver(NULL);
412
+ }
413
+
414
+ void haNameResolver::addPortMap(short mysqlPort, short transactdPort)
415
+ {
416
+ boost::mutex::scoped_lock lck(g_nr_mutex);
417
+ g_portMap.push_back(portMap(mysqlPort, transactdPort));
418
+ }
419
+
420
+ void haNameResolver::clearPortMap()
421
+ {
422
+ boost::mutex::scoped_lock lck(g_nr_mutex);
423
+ g_portMap.clear();
424
+ }
425
+
426
+ const char* haNameResolver::master()
427
+ {
428
+ boost::mutex::scoped_lock lck(g_nr_mutex);
429
+ return masterHost();
430
+ }
431
+
432
+ const char* haNameResolver::slave()
433
+ {
434
+ boost::mutex::scoped_lock lck(g_nr_mutex);
435
+ return slaveHost();
436
+ }
437
+
438
+ const char* __STDCALL hostNameResolver(const char* vhost, const char* port, char* buf, unsigned int& opt)
439
+ {
440
+ if (opt & HST_OPTION_CLEAR_CACHE)
441
+ updateRsolver();
442
+
443
+ // Resolve a host name from a role name.
444
+ boost::mutex::scoped_lock lck(g_nr_mutex);
445
+
446
+ if (masterRoleName == vhost)
447
+ {
448
+ const char* p = masterHostInternal();
449
+ if (*p && (*p != '-'))
450
+ {
451
+ strcpy_s(buf, MAX_PATH, p);
452
+ opt |= HST_OPTION_ROLE_MASTER | CL_OPTION_CHECK_ROLE;
453
+ opt &= ~HST_OPTION_ROLE_SLAVE;
454
+ return buf;
455
+ }
456
+ }
457
+ else
458
+ {
459
+ vector<string>::iterator it =
460
+ find(slaveRoleNames.begin(), slaveRoleNames.end(), vhost);
461
+ if (it != slaveRoleNames.end())
462
+ {
463
+ const char* p = slaveHostInternal();
464
+ if (*p && (*p != '-'))
465
+ {
466
+ strcpy_s(buf, MAX_PATH, p);
467
+ opt |= HST_OPTION_ROLE_SLAVE | CL_OPTION_CHECK_ROLE;
468
+ opt &= ~HST_OPTION_ROLE_MASTER;
469
+ return buf;
470
+ }
471
+ }
472
+ }
473
+ strcpy_s(buf, MAX_PATH, vhost);
474
+ if (port[0])
475
+ {
476
+ strcat_s(buf, MAX_PATH, ":");
477
+ strcat_s(buf, MAX_PATH, port);
478
+ }
479
+ return buf;
480
+ }
481
+ } // namespace client
482
+ } // namespace tdap
483
+ } // namespace protocol
484
+ } // namespace db
485
+ } // namespace bzs
486
+