1 /*
2 Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
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, nodeId2_B;
552 require(itB.get(CFG_CONNECTION_NODE_1, &nodeId1_B) == true);
553 require(itB.get(CFG_CONNECTION_NODE_2, &nodeId2_B) == true);
554 require(nodeId1_A == nodeId1_B && nodeId2_A == nodeId2_B);
555
556 // Check each possible configuration value
557 const ConfigInfo::ParamInfo* pinfo= NULL;
558 ConfigInfo::ParamInfoIter param_iter(g_info,
559 CFG_SECTION_CONNECTION,
560 connectionType);
561 while((pinfo= param_iter.next())) {
562 /* Loop through the section and compare values */
563 compare_value(name.c_str(), key.c_str(), pinfo, itA.m_config, itB, diff);
564 }
565 }
566 }
567
568
569 static bool
include_section(const unsigned * exclude,unsigned section)570 include_section(const unsigned* exclude, unsigned section){
571 if (exclude == NULL)
572 return true;
573
574 while(*exclude){
575 if (*exclude == section)
576 return false;
577 exclude++;
578 }
579 return true;
580 }
581
582
583 /**
584 Generate a diff list
585 */
586
diff(const Config * other,Properties & diff,const unsigned * exclude) const587 void Config::diff(const Config* other, Properties& diff,
588 const unsigned* exclude) const {
589
590 if (include_section(exclude, CFG_SECTION_SYSTEM)) {
591 diff_system(this, other, diff);
592 diff_system(other, this, diff);
593 }
594 if (include_section(exclude, CFG_SECTION_NODE)) {
595 diff_nodes(this, other, diff);
596 diff_nodes(other, this, diff);
597 }
598 if (include_section(exclude, CFG_SECTION_CONNECTION)) {
599 diff_connections(this, other, diff);
600 diff_connections(other, this, diff);
601 }
602 }
603
604
605 static const char*
p2s(const Properties * prop,const char * name,BaseString & buf)606 p2s(const Properties* prop, const char* name, BaseString& buf){
607 PropertiesType type;
608 require(prop->getTypeOf(name, &type));
609 switch(type){
610 case PropertiesType_Uint32:
611 {
612 Uint32 val;
613 require(prop->get(name, &val));
614 buf.assfmt("%u", val);
615 break;
616 }
617 case PropertiesType_Uint64:
618 {
619 Uint64 val;
620 require(prop->get(name, &val));
621 buf.assfmt("%llu", val);
622 break;
623 }
624 case PropertiesType_char:
625 {
626 require(prop->get(name, buf));
627 break;
628 }
629 default:
630 require(false);
631 break;
632 }
633 return buf.c_str();
634 }
635
636
637 const char*
diff2str(const Properties & diff_list,BaseString & str) const638 Config::diff2str(const Properties& diff_list, BaseString& str) const
639 {
640 const char* name;
641 Properties::Iterator prop_it(&diff_list);
642 while ((name= prop_it.next())){
643
644 const Properties *node;
645 require(diff_list.get(name, &node));
646
647 require(node->get("Name", &name));
648 str.appfmt("[%s]\n", name);
649
650 BaseString key;
651 require(node->get("Key", key));
652 if (key.length() > 0){
653 Vector<BaseString> keys;
654 key.split(keys, ";");
655 for (unsigned i= 0; i < keys.size(); i++)
656 str.appfmt("%s\n", keys[i].c_str());
657 }
658
659 BaseString buf;
660 Properties::Iterator prop_it2(node);
661 while ((name= prop_it2.next())){
662
663 const Properties *what;
664 if (!node->get(name, &what))
665 continue;
666
667 Uint32 type;
668 require(what->get("Type", &type));
669 require(what->get("Name", &name));
670 switch (type) {
671 case DT_DIFF:
672 {
673 str.appfmt("-%s=%s\n", name, p2s(what, "Old", buf));
674 str.appfmt("+%s=%s\n", name, p2s(what, "New", buf));
675 break;
676 }
677
678 case DT_MISSING_VALUE:
679 {
680 str.appfmt("-%s=%s\n", name, p2s(what, "Old", buf));
681 break;
682 }
683
684 case DT_MISSING_SECTION:
685 {
686 const char* why;
687 if (what->get("Why", &why))
688 str.appfmt("%s\n", why);
689 break;
690 }
691
692 case DT_ILLEGAL_CHANGE:
693 {
694 const char* why;
695 str.appfmt("Illegal change\n");
696 if (what->get("Why", &why))
697 str.appfmt("%s\n", why);
698 break;
699 }
700
701 default:
702 str.appfmt("Illegal 'type' found in diff_list\n");
703 require(false);
704 break;
705 }
706 }
707 str.appfmt("\n");
708 }
709 return str.c_str();
710 }
711
712
print_diff(const Config * other) const713 void Config::print_diff(const Config* other) const {
714 Properties diff_list;
715 diff(other, diff_list);
716 BaseString str;
717 ndbout_c("%s", diff2str(diff_list, str));
718 }
719
720
721 const char*
diff2str(const Config * other,BaseString & str,const unsigned * exclude) const722 Config::diff2str(const Config* other, BaseString& str, const unsigned * exclude) const {
723 Properties diff_list;
724 diff(other, diff_list, exclude);
725 return diff2str(diff_list, str);
726 }
727
728
equal(const Properties & diff_list) const729 bool Config::equal(const Properties& diff_list) const {
730 int count= 0;
731 Properties::Iterator prop_it(&diff_list);
732 while ((prop_it.next()))
733 count++;
734 return (count == 0);
735 }
736
737
equal(const Config * other,const unsigned * exclude) const738 bool Config::equal(const Config* other, const unsigned * exclude) const {
739 Properties diff_list;
740 diff(other, diff_list, exclude);
741 return equal(diff_list);
742 }
743
744
745
illegal_change(const Properties & diff_list) const746 bool Config::illegal_change(const Properties& diff_list) const {
747 bool illegal= false;
748 const char* name;
749 Properties::Iterator prop_it(&diff_list);
750 while ((name= prop_it.next())){
751
752 const Properties *node;
753 require(diff_list.get(name, &node));
754
755 Properties::Iterator prop_it2(node);
756 while ((name= prop_it2.next())){
757
758 const Properties *what;
759 if (!node->get(name, &what))
760 continue;
761
762 Uint32 type;
763 require(what->get("Type", &type));
764 if (type == DT_ILLEGAL_CHANGE)
765 illegal= true;
766 }
767 }
768 return illegal;
769 }
770
771
illegal_change(const Config * other) const772 bool Config::illegal_change(const Config* other) const {
773 Properties diff_list;
774 diff(other, diff_list);
775 return illegal_change(diff_list);
776 }
777
778
getConnectString(BaseString & connectstring,const BaseString & separator) const779 void Config::getConnectString(BaseString& connectstring,
780 const BaseString& separator) const
781 {
782 bool first= true;
783 ConfigIter it(this, CFG_SECTION_NODE);
784
785 for(;it.valid(); it.next())
786 {
787 /* Get type of Node */
788 Uint32 nodeType;
789 require(it.get(CFG_TYPE_OF_SECTION, &nodeType) == 0);
790
791 if (nodeType != NODE_TYPE_MGM)
792 continue;
793
794 Uint32 port;
795 const char* hostname;
796 require(it.get(CFG_NODE_HOST, &hostname) == 0);
797 require(it.get(CFG_MGM_PORT, &port) == 0);
798
799 if (!first)
800 connectstring.append(separator);
801 first= false;
802
803 connectstring.appfmt("%s:%d", hostname, port);
804
805 }
806 ndbout << connectstring << endl;
807 }
808
809
810 void
get_nodemask(NodeBitmask & mask,ndb_mgm_node_type type) const811 Config::get_nodemask(NodeBitmask& mask,
812 ndb_mgm_node_type type) const
813 {
814 mask.clear();
815 ConfigIter it(this, CFG_SECTION_NODE);
816 for (; it.valid(); it.next())
817 {
818 Uint32 node_type;
819 require(it.get(CFG_TYPE_OF_SECTION, &node_type) == 0);
820
821 if (type == NDB_MGM_NODE_TYPE_UNKNOWN || // UNKOWN -> add all nodes to mask
822 type == (ndb_mgm_node_type)node_type)
823 {
824 Uint32 nodeid;
825 require(it.get(CFG_NODE_ID, &nodeid) == 0);
826 mask.set(nodeid);
827 }
828 }
829 }
830
831
832 Uint32
checksum(void) const833 Config::checksum(void) const {
834 Uint32 chk;
835
836 UtilBuffer buf;
837 pack(buf);
838
839 // Checksum is the last 4 bytes in buffer
840 const char* chk_ptr = (const char*)buf.get_data();
841 chk_ptr += buf.length() - sizeof(Uint32);
842 chk = *(Uint32*) chk_ptr;
843
844 return chk;
845 }
846
847