transactd 3.4.1 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+