1 /*
2 Copyright (c) 2003, 2021, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #include "Config.hpp"
26
27 #include <mgmapi.h>
28 #include <NdbOut.hpp>
29 #include "ConfigInfo.hpp"
30
31 #include <HashMap.hpp>
32
Config(struct ndb_mgm_configuration * config_values)33 Config::Config(struct ndb_mgm_configuration *config_values) :
34 m_configValues(config_values)
35 {
36 }
37
38
Config(ConfigValues * config_values)39 Config::Config(ConfigValues *config_values) :
40 m_configValues((struct ndb_mgm_configuration*)config_values)
41 {
42 }
43
Config(const Config * conf)44 Config::Config(const Config* conf)
45 {
46 // TODO Magnus, improve copy constructor
47 // to not use pack/unpack
48 assert(conf);
49 UtilBuffer buf;
50 conf->pack(buf);
51 ConfigValuesFactory cvf;
52 cvf.unpack(buf);
53 m_configValues= (struct ndb_mgm_configuration*)cvf.getConfigValues();
54 }
55
56
~Config()57 Config::~Config() {
58 ndb_mgm_destroy_configuration(m_configValues);
59 }
60
61 unsigned sections[]=
62 {
63 CFG_SECTION_SYSTEM,
64 CFG_SECTION_NODE,
65 CFG_SECTION_CONNECTION
66 };
67 const size_t num_sections= sizeof(sections)/sizeof(unsigned);
68
69 static const ConfigInfo g_info;
70
71 void
print(const char * section_filter,NodeId nodeid_filter,const char * param_filter,NdbOut & out) const72 Config::print(const char* section_filter, NodeId nodeid_filter,
73 const char* param_filter,
74 NdbOut& out) const {
75
76 for(unsigned i= 0; i < num_sections; i++) {
77 unsigned section= sections[i];
78 ConfigIter it(this, section);
79
80 if (it.first())
81 continue;
82
83 for(;it.valid();it.next()) {
84
85 Uint32 section_type;
86 if(it.get(CFG_TYPE_OF_SECTION, §ion_type) != 0)
87 continue;
88
89 const ConfigInfo::ParamInfo* pinfo= NULL;
90 ConfigInfo::ParamInfoIter param_iter(g_info,
91 section,
92 section_type);
93
94 const char* section_name= g_info.sectionName(section, section_type);
95
96 // Section name filter
97 if (section_filter && // Filter is on
98 strcmp(section_filter, section_name)) // Value is different
99 continue;
100
101 // NodeId filter
102 Uint32 nodeid = 0;
103 it.get(CFG_NODE_ID, &nodeid);
104 if (nodeid_filter && // Filter is on
105 nodeid_filter != nodeid) // Value is different
106 continue;
107
108 /* Loop through the section and print those values that exist */
109 Uint32 val;
110 Uint64 val64;
111 const char* val_str;
112 while((pinfo= param_iter.next())){
113
114 // Param name filter
115 if (param_filter && // Filter is on
116 strcmp(param_filter, pinfo->_fname)) // Value is different
117 continue;
118
119 if (section_name) // Print section name only first time
120 {
121 out << "[" << section_name << "]" << endl;
122 section_name= NULL;
123 }
124
125 if (!it.get(pinfo->_paramId, &val))
126 out << pinfo->_fname << "=" << val << endl;
127 else if (!it.get(pinfo->_paramId, &val64))
128 out << pinfo->_fname << "=" << val64 << endl;
129 else if (!it.get(pinfo->_paramId, &val_str))
130 out << pinfo->_fname << "=" << val_str << endl;
131 }
132 }
133 }
134 }
135
136
137
138 Uint32
getGeneration() const139 Config::getGeneration() const
140 {
141 Uint32 generation;
142 ConfigIter iter(this, CFG_SECTION_SYSTEM);
143
144 if (iter.get(CFG_SYS_CONFIG_GENERATION, &generation))
145 return 0;
146
147 return generation;
148 }
149
150
151 Uint32
getPrimaryMgmNode() const152 Config::getPrimaryMgmNode() const
153 {
154 Uint32 primaryMgmNode;
155 ConfigIter iter(this, CFG_SECTION_SYSTEM);
156
157 if (iter.get(CFG_SYS_PRIMARY_MGM_NODE, &primaryMgmNode))
158 return 0;
159
160 return primaryMgmNode;
161 }
162
163
164 const char*
getName() const165 Config::getName() const
166 {
167 const char* name;
168 ConfigIter iter(this, CFG_SECTION_SYSTEM);
169
170 if (iter.get(CFG_SYS_NAME, &name))
171 return 0;
172
173 return name;
174 }
175
176
177 bool
setValue(Uint32 section,Uint32 section_no,Uint32 id,Uint32 new_val)178 Config::setValue(Uint32 section, Uint32 section_no,
179 Uint32 id, Uint32 new_val)
180 {
181 ConfigValues::Iterator iter(m_configValues->m_config);
182 if (!iter.openSection(section, section_no))
183 return false;
184
185 if (!iter.set(id, new_val))
186 return false;
187
188 return true;
189 }
190
191
192 bool
setValue(Uint32 section,Uint32 section_no,Uint32 id,const char * new_val)193 Config::setValue(Uint32 section, Uint32 section_no,
194 Uint32 id, const char* new_val)
195 {
196 ConfigValues::Iterator iter(m_configValues->m_config);
197 if (!iter.openSection(section, section_no))
198 return false;
199
200 if (!iter.set(id, new_val))
201 return false;
202
203 return true;
204 }
205
206
207 bool
setGeneration(Uint32 new_gen)208 Config::setGeneration(Uint32 new_gen)
209 {
210 return setValue(CFG_SECTION_SYSTEM, 0,
211 CFG_SYS_CONFIG_GENERATION,
212 new_gen);
213 }
214
215
216 bool
setPrimaryMgmNode(Uint32 new_primary)217 Config::setPrimaryMgmNode(Uint32 new_primary)
218 {
219 return setValue(CFG_SECTION_SYSTEM, 0,
220 CFG_SYS_PRIMARY_MGM_NODE,
221 new_primary);
222 }
223
224
225 bool
setName(const char * new_name)226 Config::setName(const char* new_name)
227 {
228 return setValue(CFG_SECTION_SYSTEM, 0,
229 CFG_SYS_NAME,
230 new_name);
231 }
232
233
234 Uint32
pack(UtilBuffer & buf) const235 Config::pack(UtilBuffer& buf) const
236 {
237 return m_configValues->m_config.pack(buf);
238 }
239
240
241 #include <ndb_base64.h>
242
243 bool
pack64(BaseString & encoded) const244 Config::pack64(BaseString& encoded) const
245 {
246 UtilBuffer buf;
247 if (m_configValues->m_config.pack(buf) == 0)
248 return false;
249
250 /*
251 Expand the string to correct length by filling with Z.
252 The base64 encoded data of UtilBuffer can be of max length (1024*1024)/3*4
253 hence using int to store the length.
254 */
255 encoded.assfmt("%*s",
256 (int)base64_needed_encoded_length(buf.length()),
257 "Z");
258
259 if (base64_encode(buf.get_data(),
260 buf.length(),
261 (char*)encoded.c_str()))
262 return false;
263 return true;
264 }
265
266
267 enum diff_types {
268 DT_DIFF, // Value differed
269 DT_MISSING_VALUE, // Value didn't exist
270 DT_MISSING_SECTION, // Section missing
271 DT_ILLEGAL_CHANGE // Illegal change detected
272 };
273
274
275 static void
add_diff(const char * name,const char * key,Properties & diff,const char * value_name,Properties * value)276 add_diff(const char* name, const char* key,
277 Properties& diff,
278 const char* value_name, Properties* value)
279 {
280 Properties *section;
281 // Create a new section if it did not exist
282 if (!diff.getCopy(key, §ion)){
283 Properties new_section(true);
284 new_section.put("Key", key);
285 new_section.put("Name", name);
286
287 require(diff.put(key, &new_section));
288
289 // Get copy of section
290 require(diff.getCopy(key, §ion));
291 }
292
293 // Make sure type of diff has been set
294 Uint32 type;
295 require(value->get("Type", &type));
296
297 require(value->put("Name", value_name));
298
299 // Add the value to the section if not already added
300 // (a changed value will be detected twice)
301 if (!section->put(value_name, value))
302 require(section->getPropertiesErrno() ==
303 E_PROPERTIES_ELEMENT_ALREADY_EXISTS);
304
305 // Put the updated section into the diff
306 require(diff.put(key, section, true));
307
308 delete section;
309 }
310
311
312 static void
compare_value(const char * name,const char * key,const ConfigInfo::ParamInfo * pinfo,ConfigValues::ConstIterator & it,ConfigValues::ConstIterator & it2,Properties & diff)313 compare_value(const char* name, const char* key,
314 const ConfigInfo::ParamInfo* pinfo,
315 ConfigValues::ConstIterator& it,
316 ConfigValues::ConstIterator& it2,
317 Properties& diff)
318 {
319 Uint32 pid= pinfo->_paramId;
320 {
321 Uint32 val;
322 if (it.get(pid, &val) == true) {
323 Uint32 val2;
324 if (it2.get(pid, &val2) == true) {
325 if (val != val2){
326 Properties info(true);
327 info.put("Type", DT_DIFF);
328 info.put("New", val2);
329 info.put("Old", val);
330 add_diff(name, key,
331 diff,
332 pinfo->_fname, &info);
333 }
334 }
335 else
336 {
337 Properties info(true);
338 info.put("Type", DT_MISSING_VALUE);
339 info.put("Old", val);
340 add_diff(name, key,
341 diff,
342 pinfo->_fname, &info);
343 }
344 return;
345 }
346 }
347
348 {
349 Uint64 val;
350 if (it.get(pid, &val) == true) {
351 Uint64 val2;
352 if (it2.get(pid, &val2) == true) {
353 if (val != val2) {
354 Properties info(true);
355 info.put("Type", DT_DIFF);
356 info.put64("New", Uint64(val2));
357 info.put64("Old", Uint64(val));
358 add_diff(name, key,
359 diff,
360 pinfo->_fname, &info);
361 }
362 }
363 else
364 {
365 Properties info(true);
366 info.put("Type", DT_MISSING_VALUE);
367 info.put64("Old", Uint64(val));
368 add_diff(name, key,
369 diff,
370 pinfo->_fname, &info);
371 }
372 return;
373 }
374 }
375
376 {
377 const char* val;
378 if (it.get(pid, &val) == true) {
379 const char* val2;
380 if (it2.get(pid, &val2) == true) {
381 if (strcmp(val, val2)) {
382 Properties info(true);
383 info.put("Type", DT_DIFF);
384 info.put("New", val2);
385 info.put("Old", val);
386 add_diff(name, key,
387 diff,
388 pinfo->_fname, &info);
389 }
390 }
391 else
392 {
393 Properties info(true);
394 info.put("Type", DT_MISSING_VALUE);
395 info.put("Old", val);
396 add_diff(name, key,
397 diff,
398 pinfo->_fname, &info);
399 }
400 return;
401 }
402 }
403 }
404
405
406 static void
diff_system(const Config * a,const Config * b,Properties & diff)407 diff_system(const Config* a, const Config* b, Properties& diff)
408 {
409 ConfigIter itA(a, CFG_SECTION_SYSTEM);
410 ConfigIter itB(b, CFG_SECTION_SYSTEM);
411
412 // Check each possible configuration value
413 const ConfigInfo::ParamInfo* pinfo= NULL;
414 ConfigInfo::ParamInfoIter param_iter(g_info,
415 CFG_SECTION_SYSTEM,
416 CFG_SECTION_SYSTEM);
417 while((pinfo= param_iter.next())) {
418 /* Loop through the section and compare values */
419 compare_value("SYSTEM", "", pinfo, itA.m_config, itB.m_config, diff);
420 }
421 }
422
423
424 static void
diff_nodes(const Config * a,const Config * b,Properties & diff)425 diff_nodes(const Config* a, const Config* b, Properties& diff)
426 {
427 ConfigIter itA(a, CFG_SECTION_NODE);
428
429 for(;itA.valid(); itA.next())
430 {
431
432 /* Get typ of Node */
433 Uint32 nodeType;
434 require(itA.get(CFG_TYPE_OF_SECTION, &nodeType) == 0);
435
436 BaseString name(g_info.sectionName(CFG_SECTION_NODE, nodeType));
437
438 /* Get NodeId which is "primary key" */
439 Uint32 nodeId;
440 require(itA.get(CFG_NODE_ID, &nodeId) == 0);
441
442 BaseString key;
443 key.assfmt("NodeId=%d", nodeId);
444
445 /* Position itB in the section with same NodeId */
446 ConfigIter itB(b, CFG_SECTION_NODE);
447 if (itB.find(CFG_NODE_ID, nodeId) != 0)
448 {
449 // A whole node has been removed
450 Properties info(true);
451 info.put("Type", DT_MISSING_SECTION);
452 info.put("Why", "Node removed");
453 add_diff(name.c_str(), key.c_str(),
454 diff,
455 "Node removed", &info);
456
457 continue;
458 }
459
460 /* Make sure it has the same node type */
461 Uint32 nodeType2;
462 require(itB.get(CFG_TYPE_OF_SECTION, &nodeType2) == 0);
463 if ((nodeType == NODE_TYPE_DB || nodeType == NODE_TYPE_MGM) &&
464 nodeType != nodeType2)
465 {
466 // DB or MGM node has changed type -> not allowed change
467 Properties info(true);
468 info.put("Type", DT_ILLEGAL_CHANGE);
469 info.put("Why", "Node has changed type");
470 add_diff(name.c_str(), key.c_str(),
471 diff,
472 "Node type changed", &info);
473 continue;
474 }
475
476 // Check each possible configuration value
477 const ConfigInfo::ParamInfo* pinfo= NULL;
478 ConfigInfo::ParamInfoIter param_iter(g_info, CFG_SECTION_NODE, nodeType);
479 while((pinfo= param_iter.next())) {
480 /* Loop through the section and compare values */
481 compare_value(name.c_str(), key.c_str(), pinfo,
482 itA.m_config, itB.m_config, diff);
483 }
484 }
485 }
486
487
488 struct NodePair {
489 Uint32 nodeId1;
490 Uint32 nodeId2;
NodePairNodePair491 NodePair(Uint32 n1, Uint32 n2) : nodeId1(n1), nodeId2(n2) {};
492 };
493
494 static void
diff_connections(const Config * a,const Config * b,Properties & diff)495 diff_connections(const Config* a, const Config* b, Properties& diff)
496 {
497 // Build lookup table to make it a quick operation to check
498 // if a given connection(with "primary key" NodeId1+NodeId2)
499 // exists in other config, in such case return the section number
500 // so that the section can be retrieved quickly
501 HashMap<NodePair, Uint32> lookup;
502 {
503 Uint32 nodeId1, nodeId2;
504 ConfigIter itB(b, CFG_SECTION_CONNECTION);
505 for(; itB.valid(); itB.next())
506 {
507 require(itB.get(CFG_CONNECTION_NODE_1, &nodeId1) == 0);
508 require(itB.get(CFG_CONNECTION_NODE_2, &nodeId2) == 0);
509
510 require(lookup.insert(NodePair(nodeId1, nodeId2), itB.m_sectionNo));
511 }
512 }
513
514 ConfigIter itA(a, CFG_SECTION_CONNECTION);
515
516 for(;itA.valid(); itA.next())
517 {
518 /* Get typ of connection */
519 Uint32 connectionType;
520 require(itA.get(CFG_TYPE_OF_SECTION, &connectionType) == 0);
521
522 BaseString name(g_info.sectionName(CFG_SECTION_CONNECTION, connectionType));
523
524 /* Get NodeId1 and NodeId2 which is "primary key" */
525 Uint32 nodeId1_A, nodeId2_A;
526 require(itA.get(CFG_CONNECTION_NODE_1, &nodeId1_A) == 0);
527 require(itA.get(CFG_CONNECTION_NODE_2, &nodeId2_A) == 0);
528
529 BaseString key;
530 key.assfmt("NodeId1=%d;NodeId2=%d", nodeId1_A, nodeId2_A);
531
532 /* Lookup connection and get section no if it exists */
533 Uint32 sectionNo;
534 if (!lookup.search(NodePair(nodeId1_A, nodeId2_A), sectionNo))
535 {
536 // A connection has been removed
537 Properties info(true);
538 info.put("Type", DT_MISSING_SECTION);
539 info.put("Why", "Connection removed");
540 add_diff(name.c_str(), key.c_str(),
541 diff,
542 "Connection removed", &info);
543
544 continue;
545 }
546
547 /* Open the connection section in other config */
548 ConfigValues::ConstIterator itB(b->m_configValues->m_config);
549 require(itB.openSection(CFG_SECTION_CONNECTION, sectionNo) == true);
550
551 Uint32 nodeId1_B = 0; /* Silence compiler warning */
552 Uint32 nodeId2_B = 0; /* Silence compiler warning */
553 require(itB.get(CFG_CONNECTION_NODE_1, &nodeId1_B) == true);
554 require(itB.get(CFG_CONNECTION_NODE_2, &nodeId2_B) == true);
555 require(nodeId1_A == nodeId1_B && nodeId2_A == nodeId2_B);
556
557 // Check each possible configuration value
558 const ConfigInfo::ParamInfo* pinfo= NULL;
559 ConfigInfo::ParamInfoIter param_iter(g_info,
560 CFG_SECTION_CONNECTION,
561 connectionType);
562 while((pinfo= param_iter.next())) {
563 /* Loop through the section and compare values */
564 compare_value(name.c_str(), key.c_str(), pinfo, itA.m_config, itB, diff);
565 }
566 }
567 }
568
569
570 static bool
include_section(const unsigned * exclude,unsigned section)571 include_section(const unsigned* exclude, unsigned section){
572 if (exclude == NULL)
573 return true;
574
575 while(*exclude){
576 if (*exclude == section)
577 return false;
578 exclude++;
579 }
580 return true;
581 }
582
583
584 /**
585 Generate a diff list
586 */
587
diff(const Config * other,Properties & diff,const unsigned * exclude) const588 void Config::diff(const Config* other, Properties& diff,
589 const unsigned* exclude) const {
590
591 if (include_section(exclude, CFG_SECTION_SYSTEM)) {
592 diff_system(this, other, diff);
593 diff_system(other, this, diff);
594 }
595 if (include_section(exclude, CFG_SECTION_NODE)) {
596 diff_nodes(this, other, diff);
597 diff_nodes(other, this, diff);
598 }
599 if (include_section(exclude, CFG_SECTION_CONNECTION)) {
600 diff_connections(this, other, diff);
601 diff_connections(other, this, diff);
602 }
603 }
604
605
606 static const char*
p2s(const Properties * prop,const char * name,BaseString & buf)607 p2s(const Properties* prop, const char* name, BaseString& buf){
608 PropertiesType type;
609 require(prop->getTypeOf(name, &type));
610 switch(type){
611 case PropertiesType_Uint32:
612 {
613 Uint32 val;
614 require(prop->get(name, &val));
615 buf.assfmt("%u", val);
616 break;
617 }
618 case PropertiesType_Uint64:
619 {
620 Uint64 val;
621 require(prop->get(name, &val));
622 buf.assfmt("%llu", val);
623 break;
624 }
625 case PropertiesType_char:
626 {
627 require(prop->get(name, buf));
628 break;
629 }
630 default:
631 require(false);
632 break;
633 }
634 return buf.c_str();
635 }
636
637
638 const char*
diff2str(const Properties & diff_list,BaseString & str) const639 Config::diff2str(const Properties& diff_list, BaseString& str) const
640 {
641 const char* name;
642 Properties::Iterator prop_it(&diff_list);
643 while ((name= prop_it.next())){
644
645 const Properties *node;
646 require(diff_list.get(name, &node));
647
648 require(node->get("Name", &name));
649 str.appfmt("[%s]\n", name);
650
651 BaseString key;
652 require(node->get("Key", key));
653 if (key.length() > 0){
654 Vector<BaseString> keys;
655 key.split(keys, ";");
656 for (unsigned i= 0; i < keys.size(); i++)
657 str.appfmt("%s\n", keys[i].c_str());
658 }
659
660 BaseString buf;
661 Properties::Iterator prop_it2(node);
662 while ((name= prop_it2.next())){
663
664 const Properties *what;
665 if (!node->get(name, &what))
666 continue;
667
668 Uint32 type;
669 require(what->get("Type", &type));
670 require(what->get("Name", &name));
671 switch (type) {
672 case DT_DIFF:
673 {
674 str.appfmt("-%s=%s\n", name, p2s(what, "Old", buf));
675 str.appfmt("+%s=%s\n", name, p2s(what, "New", buf));
676 break;
677 }
678
679 case DT_MISSING_VALUE:
680 {
681 str.appfmt("-%s=%s\n", name, p2s(what, "Old", buf));
682 break;
683 }
684
685 case DT_MISSING_SECTION:
686 {
687 const char* why;
688 if (what->get("Why", &why))
689 str.appfmt("%s\n", why);
690 break;
691 }
692
693 case DT_ILLEGAL_CHANGE:
694 {
695 const char* why;
696 str.appfmt("Illegal change\n");
697 if (what->get("Why", &why))
698 str.appfmt("%s\n", why);
699 break;
700 }
701
702 default:
703 str.appfmt("Illegal 'type' found in diff_list\n");
704 require(false);
705 break;
706 }
707 }
708 str.appfmt("\n");
709 }
710 return str.c_str();
711 }
712
713
print_diff(const Config * other) const714 void Config::print_diff(const Config* other) const {
715 Properties diff_list;
716 diff(other, diff_list);
717 BaseString str;
718 ndbout_c("%s", diff2str(diff_list, str));
719 }
720
721
722 const char*
diff2str(const Config * other,BaseString & str,const unsigned * exclude) const723 Config::diff2str(const Config* other, BaseString& str, const unsigned * exclude) const {
724 Properties diff_list;
725 diff(other, diff_list, exclude);
726 return diff2str(diff_list, str);
727 }
728
729
equal(const Properties & diff_list) const730 bool Config::equal(const Properties& diff_list) const {
731 int count= 0;
732 Properties::Iterator prop_it(&diff_list);
733 while ((prop_it.next()))
734 count++;
735 return (count == 0);
736 }
737
738
equal(const Config * other,const unsigned * exclude) const739 bool Config::equal(const Config* other, const unsigned * exclude) const {
740 Properties diff_list;
741 diff(other, diff_list, exclude);
742 return equal(diff_list);
743 }
744
745
746
illegal_change(const Properties & diff_list) const747 bool Config::illegal_change(const Properties& diff_list) const {
748 bool illegal= false;
749 const char* name;
750 Properties::Iterator prop_it(&diff_list);
751 while ((name= prop_it.next())){
752
753 const Properties *node;
754 require(diff_list.get(name, &node));
755
756 Properties::Iterator prop_it2(node);
757 while ((name= prop_it2.next())){
758
759 const Properties *what;
760 if (!node->get(name, &what))
761 continue;
762
763 Uint32 type;
764 require(what->get("Type", &type));
765 if (type == DT_ILLEGAL_CHANGE)
766 {
767 illegal= true;
768 break;
769 }
770 }
771 }
772 return illegal;
773 }
774
775
illegal_change(const Config * other) const776 bool Config::illegal_change(const Config* other) const {
777 Properties diff_list;
778 diff(other, diff_list);
779 return illegal_change(diff_list);
780 }
781
782
getConnectString(BaseString & connectstring,const BaseString & separator) const783 void Config::getConnectString(BaseString& connectstring,
784 const BaseString& separator) const
785 {
786 bool first= true;
787 ConfigIter it(this, CFG_SECTION_NODE);
788
789 for(;it.valid(); it.next())
790 {
791 /* Get type of Node */
792 Uint32 nodeType;
793 require(it.get(CFG_TYPE_OF_SECTION, &nodeType) == 0);
794
795 if (nodeType != NODE_TYPE_MGM)
796 continue;
797
798 Uint32 port;
799 const char* hostname;
800 require(it.get(CFG_NODE_HOST, &hostname) == 0);
801 require(it.get(CFG_MGM_PORT, &port) == 0);
802
803 if (!first)
804 connectstring.append(separator);
805 first= false;
806
807 connectstring.appfmt("%s:%d", hostname, port);
808
809 }
810 ndbout << connectstring << endl;
811 }
812
813
814 void
get_nodemask(NodeBitmask & mask,ndb_mgm_node_type type) const815 Config::get_nodemask(NodeBitmask& mask,
816 ndb_mgm_node_type type) const
817 {
818 mask.clear();
819 ConfigIter it(this, CFG_SECTION_NODE);
820 for (; it.valid(); it.next())
821 {
822 Uint32 node_type;
823 require(it.get(CFG_TYPE_OF_SECTION, &node_type) == 0);
824
825 if (type == NDB_MGM_NODE_TYPE_UNKNOWN || // UNKOWN -> add all nodes to mask
826 type == (ndb_mgm_node_type)node_type)
827 {
828 Uint32 nodeid;
829 require(it.get(CFG_NODE_ID, &nodeid) == 0);
830 mask.set(nodeid);
831 }
832 }
833 }
834
835
836 Uint32
checksum(void) const837 Config::checksum(void) const {
838 Uint32 chk;
839
840 UtilBuffer buf;
841 pack(buf);
842
843 // Checksum is the last 4 bytes in buffer
844 const char* chk_ptr = (const char*)buf.get_data();
845 chk_ptr += buf.length() - sizeof(Uint32);
846 chk = *(Uint32*) chk_ptr;
847
848 return chk;
849 }
850
851