19 #include <ndb_global.h>
20 #include <ConfigValues.hpp>
24 static bool findKey(
const Uint32 * vals, Uint32 sz, Uint32 key, Uint32 * pos);
37 #define KP_TYPE_MASK (15)
38 #define KP_TYPE_SHIFT (28)
39 #define KP_SECTION_MASK (0x3FFF)
40 #define KP_SECTION_SHIFT (14)
41 #define KP_KEYVAL_MASK (0x3FFF)
42 #define KP_KEYVAL_SHIFT (0)
43 #define KP_MASK (0x0FFFFFFF)
45 static const Uint32 CFV_KEY_PARENT = (KP_KEYVAL_MASK - 1);
46 static const Uint32 CFV_KEY_FREE = ~0;
48 static const char Magic[] = {
'N',
'D',
'B',
'C',
'O',
'N',
'F',
'V' };
52 #define DEBUG if(getenv("CV_DEBUG"))
58 ConfigValues::ValueType
60 return (ConfigValues::ValueType)((k >> KP_TYPE_SHIFT) & KP_TYPE_MASK);
63 ConfigValues::ConfigValues(Uint32 sz, Uint32 dsz){
68 for(Uint32
i = 0;
i<m_size;
i++){
69 m_values[
i << 1] = CFV_KEY_FREE;
73 ConfigValues::~ConfigValues(){
74 for(Uint32
i = 0;
i<m_stringCount;
i++){
80 ConfigValues::ConstIterator::get(Uint32 key, Entry * result)
const {
82 if(!findKey(m_cfg.m_values, m_cfg.m_size, key | m_currentSection, &pos)){
87 return m_cfg.getByPos(pos, result);
91 ConfigValues::getByPos(Uint32 pos, Entry * result)
const {
92 assert(pos < (2 * m_size));
93 Uint32 keypart = m_values[pos];
94 Uint32 val2 = m_values[pos+1];
96 switch(::getTypeOf(keypart)){
102 result->m_string = * getString(val2);
105 result->m_int64 = * get64(val2);
112 result->m_type = ::getTypeOf(keypart);
118 ConfigValues::get64(Uint32
index)
const {
119 assert(index < m_int64Count);
120 const Uint32 * data = m_values + (m_size << 1);
121 Uint64 * ptr = (Uint64*)data;
127 ConfigValues::getString(Uint32
index)
const {
128 assert(index < m_stringCount);
129 const Uint32 * data = m_values + (m_size << 1);
130 char * ptr = (
char*)data;
132 ptr -= (index *
sizeof(
char *));
138 Uint32 curr = m_currentSection;
141 if(
get(key, &tmp) && tmp.m_type == SectionType){
142 m_currentSection = tmp.m_int;
143 if(
get(no, &tmp) && tmp.m_type == IntType){
144 m_currentSection = tmp.m_int;
148 if(
get(CFV_KEY_PARENT, &tmp)){
154 m_currentSection = curr;
159 ConfigValues::ConstIterator::closeSection() {
162 if(
get(CFV_KEY_PARENT, &tmp) && tmp.m_type == IntType){
163 m_currentSection = tmp.m_int;
171 ConfigValues::Iterator::set(Uint32 key, Uint32 value){
173 if(!findKey(m_cfg.m_values, m_cfg.m_size, key | m_currentSection, &pos)){
177 if(::getTypeOf(m_cfg.m_values[pos]) != IntType){
181 m_cfg.m_values[pos+1] = value;
186 ConfigValues::Iterator::set(Uint32 key, Uint64 value){
188 if(!findKey(m_cfg.m_values, m_cfg.m_size, key | m_currentSection, &pos)){
192 if(::getTypeOf(m_cfg.m_values[pos]) != Int64Type){
196 * m_cfg.get64(m_cfg.m_values[pos+1]) = value;
201 ConfigValues::Iterator::set(Uint32 key,
const char * value){
203 if(!findKey(m_cfg.m_values, m_cfg.m_size, key | m_currentSection, &pos)){
207 if(::getTypeOf(m_cfg.m_values[pos]) != StringType){
211 char ** str = m_cfg.getString(m_cfg.m_values[pos+1]);
213 * str = strdup(value ? value :
"");
219 findKey(
const Uint32 * values, Uint32 sz, Uint32 key, Uint32 * _pos){
222 Uint32 pos = (hi + lo) >> 1;
224 DEBUG printf(
"findKey(H'%.8x %d)", key, sz);
228 DEBUG ndbout_c(
" -> false, 0");
234 Uint32 oldpos = pos + 1;
235 while (pos != oldpos)
237 DEBUG printf(
" [ %d %d %d ] ", lo, pos, hi);
240 val = values[2*pos] & KP_MASK;
252 DEBUG ndbout_c(
" -> true, %d", pos);
256 pos = (hi + lo) >> 1;
259 DEBUG printf(
" pos: %d (key %.8x val: %.8x values[pos]: %x) key>val: %d ",
260 pos, key, val, values[2*pos] & KP_MASK,
263 pos += (key > val) ? 1 : 0;
266 DEBUG ndbout_c(
" -> false, %d", pos);
271 ConfigValuesFactory::ConfigValuesFactory(Uint32 keys, Uint32 data){
272 m_sectionCounter = (1 << KP_SECTION_SHIFT);
274 m_freeData = (data + 7) & ~7;
275 m_currentSection = 0;
276 m_cfg = create(m_freeKeys, m_freeData);
279 ConfigValuesFactory::ConfigValuesFactory(
ConfigValues * cfg){
282 m_freeData = m_cfg->m_dataSize;
283 m_sectionCounter = (1 << KP_SECTION_SHIFT);
284 m_currentSection = 0;
285 const Uint32 sz = 2 * m_cfg->m_size;
286 for(Uint32
i = 0;
i<sz;
i += 2){
287 const Uint32 key = m_cfg->m_values[
i];
288 if(key == CFV_KEY_FREE){
291 switch(::getTypeOf(key)){
292 case ConfigValues::IntType:
293 case ConfigValues::SectionType:
295 case ConfigValues::Int64Type:
296 m_freeData -=
sizeof(Uint64);
298 case ConfigValues::StringType:
299 m_freeData -=
sizeof(
char *);
301 case ConfigValues::InvalidType:
304 Uint32 sec = key & (KP_SECTION_MASK << KP_SECTION_SHIFT);
305 m_sectionCounter = (sec > m_sectionCounter ? sec : m_sectionCounter);
310 ConfigValuesFactory::~ConfigValuesFactory()
314 m_cfg->~ConfigValues();
320 ConfigValuesFactory::create(Uint32 keys, Uint32 data){
322 sz += (2 * keys *
sizeof(Uint32));
325 void * tmp = malloc(sz);
330 ConfigValuesFactory::expand(Uint32 fk, Uint32 fs){
331 if(m_freeKeys >= fk && m_freeData >= fs){
335 DEBUG printf(
"[ fk fd ] : [ %d %d ]", m_freeKeys, m_freeData);
337 m_freeKeys = (m_freeKeys >= fk ? m_cfg->m_size : fk + m_cfg->m_size);
338 m_freeData = (m_freeData >= fs ? m_cfg->m_dataSize : fs + m_cfg->m_dataSize);
339 m_freeData = (m_freeData + 7) & ~7;
341 DEBUG ndbout_c(
" [ %d %d ]", m_freeKeys, m_freeData);
344 m_cfg = create(m_freeKeys, m_freeData);
346 m_tmp->~ConfigValues();
351 ConfigValuesFactory::shrink(){
352 if(m_freeKeys == 0 && m_freeData == 0){
356 m_freeKeys = m_cfg->m_size - m_freeKeys;
357 m_freeData = m_cfg->m_dataSize - m_freeData;
358 m_freeData = (m_freeData + 7) & ~7;
361 m_cfg = create(m_freeKeys, m_freeData);
363 m_tmp->~ConfigValues();
368 ConfigValuesFactory::openSection(Uint32 key, Uint32 no){
370 const Uint32 parent = m_currentSection;
373 iter.m_currentSection = m_currentSection;
374 if(!iter.get(key, &tmp)){
377 tmp.m_type = ConfigValues::SectionType;
378 tmp.m_int = m_sectionCounter;
379 m_sectionCounter += (1 << KP_SECTION_SHIFT);
386 if(tmp.m_type != ConfigValues::SectionType){
390 m_currentSection = tmp.m_int;
393 tmp.m_type = ConfigValues::IntType;
394 tmp.m_int = m_sectionCounter;
396 m_currentSection = parent;
399 m_sectionCounter += (1 << KP_SECTION_SHIFT);
401 m_currentSection = tmp.m_int;
402 tmp.m_type = ConfigValues::IntType;
403 tmp.m_key = CFV_KEY_PARENT;
406 m_currentSection = parent;
414 ConfigValuesFactory::closeSection(){
416 iter.m_currentSection = m_currentSection;
417 const bool b = iter.closeSection();
418 m_currentSection = iter.m_currentSection;
425 if(m_freeKeys == 0 ||
426 (entry.m_type == ConfigValues::StringType && m_freeData <
sizeof(
char *))
427 || (entry.m_type == ConfigValues::Int64Type && m_freeData < 8 )){
429 DEBUG ndbout_c(
"m_freeKeys = %d, m_freeData = %d -> expand",
430 m_freeKeys, m_freeData);
435 const Uint32 tmp = entry.m_key | m_currentSection;
436 const Uint32 sz = m_cfg->m_size - m_freeKeys;
439 if (findKey(m_cfg->m_values, sz, tmp, &pos))
441 DEBUG ndbout_c(
"key %x already found at pos: %d", tmp, pos);
448 for (Uint32
i = 0;
i<sz;
i++)
450 Uint32 val = m_cfg->m_values[2*
i] & KP_MASK;
451 ndbout_c(
"%.8x", val);
459 DEBUG ndbout_c(
"pos: %d sz: %d", pos, sz);
460 memmove(m_cfg->m_values + pos + 2, m_cfg->m_values + pos,
466 key |= (entry.m_type << KP_TYPE_SHIFT);
467 m_cfg->m_values[pos] = key;
472 for (Uint32
i = 0;
i<=sz;
i++)
474 Uint32 val = m_cfg->m_values[2*
i] & KP_MASK;
475 ndbout_c(
"%.8x", val);
481 switch(entry.m_type){
482 case ConfigValues::IntType:
483 case ConfigValues::SectionType:
484 m_cfg->m_values[pos+1] = entry.m_int;
486 DEBUG printf(
"Putting at: %d(%d) (loop = %d) key: %d value: %d\n",
488 (key >> KP_KEYVAL_SHIFT) & KP_KEYVAL_MASK,
491 case ConfigValues::StringType:{
492 Uint32 index = m_cfg->m_stringCount++;
493 m_cfg->m_values[pos+1] =
index;
494 char ** ref = m_cfg->getString(index);
495 * ref = strdup(entry.m_string ? entry.m_string :
"");
497 m_freeData -=
sizeof(
char *);
498 DEBUG printf(
"Putting at: %d(%d) (loop = %d) key: %d value(%d): %s\n",
500 (key >> KP_KEYVAL_SHIFT) & KP_KEYVAL_MASK,
505 case ConfigValues::Int64Type:{
506 Uint32 index = m_cfg->m_int64Count++;
507 m_cfg->m_values[pos+1] =
index;
508 * m_cfg->get64(index) = entry.m_int64;
511 DEBUG printf(
"Putting at: %d(%d) (loop = %d) key: %d value64(%d): %lld\n",
513 (key >> KP_KEYVAL_SHIFT) & KP_KEYVAL_MASK,
518 case ConfigValues::InvalidType:
528 Uint32 curr = m_currentSection;
529 m_currentSection = 0;
532 for(Uint32
i = 0;
i < 2 * cfg.m_size;
i += 2){
533 if(cfg.m_values[
i] != CFV_KEY_FREE){
534 tmp.m_key = cfg.m_values[
i];
535 cfg.getByPos(
i, &tmp);
540 m_currentSection = curr;
546 Uint32 curr = cfg.m_currentSection;
549 for(Uint32
i = 0;
i < 2 * cfg.m_cfg.m_size;
i += 2){
550 Uint32 keypart = cfg.m_cfg.m_values[
i];
551 const Uint32 sec = keypart & (KP_SECTION_MASK << KP_SECTION_SHIFT);
552 const Uint32 key = keypart & KP_KEYVAL_MASK;
553 if(sec == curr && key != CFV_KEY_PARENT){
554 tmp.m_key = cfg.m_cfg.m_values[
i];
555 cfg.m_cfg.getByPos(
i, &tmp);
567 ConfigValuesFactory::getConfigValues(){
569 m_cfg = create(10, 10);
574 mod4(
unsigned int i){
575 int res = i + (4 - (i % 4));
580 ConfigValues::getPackedSize()
const {
583 for(Uint32
i = 0;
i < 2 * m_size;
i += 2){
584 Uint32 key = m_values[
i];
585 if(key != CFV_KEY_FREE){
586 switch(::getTypeOf(key)){
596 size += mod4(strlen(* getString(m_values[
i+1])) + 1);
605 return size +
sizeof(Magic) + 4;
609 ConfigValues::pack(
void * _dst, Uint32 _len)
const {
611 char * dst = (
char*)_dst;
612 memcpy(dst, Magic,
sizeof(Magic)); dst +=
sizeof(Magic);
614 for(i = 0; i < 2 * m_size; i += 2){
615 Uint32 key = m_values[
i];
616 Uint32 val = m_values[i+1];
617 if(key != CFV_KEY_FREE){
618 switch(::getTypeOf(key)){
621 * (Uint32*)dst = htonl(key); dst += 4;
622 * (Uint32*)dst = htonl(val); dst += 4;
625 Uint64 i64 = * get64(val);
626 Uint32 hi = (Uint32)(i64 >> 32);
627 Uint32 lo = (Uint32)(i64 & 0xFFFFFFFF);
628 * (Uint32*)dst = htonl(key); dst += 4;
629 * (Uint32*)dst = htonl(hi); dst += 4;
630 * (Uint32*)dst = htonl(lo); dst += 4;
634 const char * str = * getString(val);
635 Uint32 len = Uint32(strlen(str) + 1);
636 * (Uint32*)dst = htonl(key); dst += 4;
637 * (Uint32*)dst = htonl(len); dst += 4;
638 memcpy(dst, str, len);
639 memset(dst+len, 0, mod4(len) - len);
650 const Uint32 * sum = (Uint32*)_dst;
651 const Uint32 len = Uint32(((Uint32*)dst) - sum);
653 for(i = 0; i<len; i++){
654 chk ^= htonl(sum[i]);
657 * (Uint32*)dst = htonl(chk); dst += 4;
658 return 4 * (len + 1);
662 ConfigValuesFactory::unpack(
const void * _src, Uint32 len){
664 if(len <
sizeof(Magic) + 4){
669 if(memcmp(_src, Magic,
sizeof(Magic)) != 0){
674 const char * src = (
const char *)_src;
675 const char * end = src + len - 4;
676 src +=
sizeof(Magic);
679 Uint32 len32 = (len >> 2);
680 const Uint32 * tmp = (
const Uint32*)_src;
682 for(Uint32 i = 0; (i+1)<len32; i++){
683 chk ^= ntohl(tmp[i]);
686 if(chk != ntohl(tmp[len32-1])){
692 const char * save = src;
697 while(end - src > 4){
698 Uint32 tmp = ntohl(* (
const Uint32 *)src); src += 4;
700 switch(::getTypeOf(tmp)){
701 case ConfigValues::IntType:
702 case ConfigValues::SectionType:
705 case ConfigValues::Int64Type:
709 case ConfigValues::StringType:{
710 Uint32 s_len = ntohl(* (
const Uint32 *)src);
711 src += 4 + mod4(s_len);
712 data +=
sizeof(
char*);
724 while(end - src > 4){
725 Uint32 tmp = ntohl(* (
const Uint32 *)src); src += 4;
726 entry.m_key = tmp & KP_MASK;
727 entry.m_type = ::getTypeOf(tmp);
728 switch(entry.m_type){
729 case ConfigValues::IntType:
730 case ConfigValues::SectionType:
731 entry.m_int = ntohl(* (
const Uint32 *)src); src += 4;
733 case ConfigValues::Int64Type:{
734 Uint64 hi = ntohl(* (
const Uint32 *)src); src += 4;
735 Uint64 lo = ntohl(* (
const Uint32 *)src); src += 4;
736 entry.m_int64 = (hi <<32) | lo;
739 case ConfigValues::StringType:{
740 Uint32 s_len = ntohl(* (
const Uint32 *)src); src += 4;
741 size_t s_len2 = strlen((
const char*)src);
742 if(s_len2 + 1 != s_len){
747 entry.m_string = (
const char*)src; src+= mod4(s_len);
750 case ConfigValues::InvalidType:
767 #ifdef __TEST_CV_HASH_HPP
772 for(
int t = 0; t<100; t++){
773 const size_t len = directory(rand() % 1000);
775 printf(
"size = %d\n", len);
776 unsigned *
buf =
new unsigned[len];
777 for(
size_t key = 0; key<len; key++){
778 Uint32 p = hash(key, len);
779 for(
size_t j = 0; j<len; j++){
781 p = nextHash(key, len, p, j+1);
784 for(
size_t j = 0; j<len; j++){
787 for(
size_t k = j + 1; k<len; k++){
790 printf(
"size=%d key=%d pos(%d)=%d buf[%d]=%d\n", len, key, j, pos, k, buf[k]);
795 printf(
"key = %d size = %d not uniqe!!\n", key, len);
796 for(
size_t k = 0; k<len; k++){
797 printf(
"%d ", buf[k]);