MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ConfigValues.cpp
1 /*
2  Copyright (C) 2004-2007 MySQL AB, 2008 Sun Microsystems, Inc.
3  All rights reserved. Use is subject to license terms.
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; version 2 of the License.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 #include <ndb_global.h>
20 #include <ConfigValues.hpp>
21 #include <NdbOut.hpp>
22 #include <NdbTCP.h>
23 
24 static bool findKey(const Uint32 * vals, Uint32 sz, Uint32 key, Uint32 * pos);
25 
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)
44 
45 static const Uint32 CFV_KEY_PARENT = (KP_KEYVAL_MASK - 1);
46 static const Uint32 CFV_KEY_FREE = ~0;
47 
48 static const char Magic[] = { 'N', 'D', 'B', 'C', 'O', 'N', 'F', 'V' };
49 
50 //#define DEBUG_CV
51 #ifdef DEBUG_CV
52 #define DEBUG if(getenv("CV_DEBUG"))
53 #else
54 #define DEBUG if(0)
55 #endif
56 
57 inline
58 ConfigValues::ValueType
59 getTypeOf(Uint32 k) {
60  return (ConfigValues::ValueType)((k >> KP_TYPE_SHIFT) & KP_TYPE_MASK);
61 }
62 
63 ConfigValues::ConfigValues(Uint32 sz, Uint32 dsz){
64  m_size = sz;
65  m_dataSize = dsz;
66  m_stringCount = 0;
67  m_int64Count = 0;
68  for(Uint32 i = 0; i<m_size; i++){
69  m_values[i << 1] = CFV_KEY_FREE;
70  }
71 }
72 
73 ConfigValues::~ConfigValues(){
74  for(Uint32 i = 0; i<m_stringCount; i++){
75  free(* getString(i));
76  }
77 }
78 
79 bool
80 ConfigValues::ConstIterator::get(Uint32 key, Entry * result) const {
81  Uint32 pos;
82  if(!findKey(m_cfg.m_values, m_cfg.m_size, key | m_currentSection, &pos)){
83  return false;
84  }
85 
86  result->m_key = key;
87  return m_cfg.getByPos(pos, result);
88 }
89 
90 bool
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];
95 
96  switch(::getTypeOf(keypart)){
97  case IntType:
98  case SectionType:
99  result->m_int = val2;
100  break;
101  case StringType:
102  result->m_string = * getString(val2);
103  break;
104  case Int64Type:
105  result->m_int64 = * get64(val2);
106  break;
107  case InvalidType:
108  default:
109  return false;
110  }
111 
112  result->m_type = ::getTypeOf(keypart);
113 
114  return true;
115 }
116 
117 Uint64 *
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;
122  ptr += index;
123  return ptr;
124 }
125 
126 char **
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;
131  ptr += m_dataSize;
132  ptr -= (index * sizeof(char *));
133  return (char**)ptr;
134 }
135 
136 bool
138  Uint32 curr = m_currentSection;
139 
140  Entry tmp;
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)){
149  return true;
150  }
151  }
152  }
153 
154  m_currentSection = curr;
155  return false;
156 }
157 
158 bool
159 ConfigValues::ConstIterator::closeSection() {
160 
161  Entry tmp;
162  if(get(CFV_KEY_PARENT, &tmp) && tmp.m_type == IntType){
163  m_currentSection = tmp.m_int;
164  return true;
165  }
166 
167  return false;
168 }
169 
170 bool
171 ConfigValues::Iterator::set(Uint32 key, Uint32 value){
172  Uint32 pos;
173  if(!findKey(m_cfg.m_values, m_cfg.m_size, key | m_currentSection, &pos)){
174  return false;
175  }
176 
177  if(::getTypeOf(m_cfg.m_values[pos]) != IntType){
178  return false;
179  }
180 
181  m_cfg.m_values[pos+1] = value;
182  return true;
183 }
184 
185 bool
186 ConfigValues::Iterator::set(Uint32 key, Uint64 value){
187  Uint32 pos;
188  if(!findKey(m_cfg.m_values, m_cfg.m_size, key | m_currentSection, &pos)){
189  return false;
190  }
191 
192  if(::getTypeOf(m_cfg.m_values[pos]) != Int64Type){
193  return false;
194  }
195 
196  * m_cfg.get64(m_cfg.m_values[pos+1]) = value;
197  return true;
198 }
199 
200 bool
201 ConfigValues::Iterator::set(Uint32 key, const char * value){
202  Uint32 pos;
203  if(!findKey(m_cfg.m_values, m_cfg.m_size, key | m_currentSection, &pos)){
204  return false;
205  }
206 
207  if(::getTypeOf(m_cfg.m_values[pos]) != StringType){
208  return false;
209  }
210 
211  char ** str = m_cfg.getString(m_cfg.m_values[pos+1]);
212  free(* str);
213  * str = strdup(value ? value : "");
214  return true;
215 }
216 
217 static
218 bool
219 findKey(const Uint32 * values, Uint32 sz, Uint32 key, Uint32 * _pos){
220  Uint32 lo = 0;
221  Uint32 hi = sz;
222  Uint32 pos = (hi + lo) >> 1;
223 
224  DEBUG printf("findKey(H'%.8x %d)", key, sz);
225 
226  if (sz == 0)
227  {
228  DEBUG ndbout_c(" -> false, 0");
229  * _pos = 0;
230  return false;
231  }
232 
233  Uint32 val = 0;
234  Uint32 oldpos = pos + 1;
235  while (pos != oldpos)
236  {
237  DEBUG printf(" [ %d %d %d ] ", lo, pos, hi);
238  assert(pos < hi);
239  assert(pos >= lo);
240  val = values[2*pos] & KP_MASK;
241  if (key > val)
242  {
243  lo = pos;
244  }
245  else if (key < val)
246  {
247  hi = pos;
248  }
249  else
250  {
251  * _pos = 2*pos;
252  DEBUG ndbout_c(" -> true, %d", pos);
253  return true;
254  }
255  oldpos = pos;
256  pos = (hi + lo) >> 1;
257  }
258 
259  DEBUG printf(" pos: %d (key %.8x val: %.8x values[pos]: %x) key>val: %d ",
260  pos, key, val, values[2*pos] & KP_MASK,
261  key > val);
262 
263  pos += (key > val) ? 1 : 0;
264 
265  * _pos = 2*pos;
266  DEBUG ndbout_c(" -> false, %d", pos);
267  return false;
268 }
269 
270 
271 ConfigValuesFactory::ConfigValuesFactory(Uint32 keys, Uint32 data){
272  m_sectionCounter = (1 << KP_SECTION_SHIFT);
273  m_freeKeys = keys;
274  m_freeData = (data + 7) & ~7;
275  m_currentSection = 0;
276  m_cfg = create(m_freeKeys, m_freeData);
277 }
278 
279 ConfigValuesFactory::ConfigValuesFactory(ConfigValues * cfg){
280  m_cfg = cfg;
281  m_freeKeys = 0;
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){
289  m_freeKeys++;
290  } else {
291  switch(::getTypeOf(key)){
292  case ConfigValues::IntType:
293  case ConfigValues::SectionType:
294  break;
295  case ConfigValues::Int64Type:
296  m_freeData -= sizeof(Uint64);
297  break;
298  case ConfigValues::StringType:
299  m_freeData -= sizeof(char *);
300  break;
301  case ConfigValues::InvalidType:
302  abort();
303  }
304  Uint32 sec = key & (KP_SECTION_MASK << KP_SECTION_SHIFT);
305  m_sectionCounter = (sec > m_sectionCounter ? sec : m_sectionCounter);
306  }
307  }
308 }
309 
310 ConfigValuesFactory::~ConfigValuesFactory()
311 {
312  if(m_cfg)
313  {
314  m_cfg->~ConfigValues();
315  free(m_cfg);
316  }
317 }
318 
319 ConfigValues *
320 ConfigValuesFactory::create(Uint32 keys, Uint32 data){
321  Uint32 sz = sizeof(ConfigValues);
322  sz += (2 * keys * sizeof(Uint32));
323  sz += data;
324 
325  void * tmp = malloc(sz);
326  return new (tmp) ConfigValues(keys, data);
327 }
328 
329 void
330 ConfigValuesFactory::expand(Uint32 fk, Uint32 fs){
331  if(m_freeKeys >= fk && m_freeData >= fs){
332  return ;
333  }
334 
335  DEBUG printf("[ fk fd ] : [ %d %d ]", m_freeKeys, m_freeData);
336 
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;
340 
341  DEBUG ndbout_c(" [ %d %d ]", m_freeKeys, m_freeData);
342 
343  ConfigValues * m_tmp = m_cfg;
344  m_cfg = create(m_freeKeys, m_freeData);
345  put(* m_tmp);
346  m_tmp->~ConfigValues();
347  free(m_tmp);
348 }
349 
350 void
351 ConfigValuesFactory::shrink(){
352  if(m_freeKeys == 0 && m_freeData == 0){
353  return ;
354  }
355 
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;
359 
360  ConfigValues * m_tmp = m_cfg;
361  m_cfg = create(m_freeKeys, m_freeData);
362  put(* m_tmp);
363  m_tmp->~ConfigValues();
364  free(m_tmp);
365 }
366 
367 bool
368 ConfigValuesFactory::openSection(Uint32 key, Uint32 no){
370  const Uint32 parent = m_currentSection;
371 
372  ConfigValues::ConstIterator iter(* m_cfg);
373  iter.m_currentSection = m_currentSection;
374  if(!iter.get(key, &tmp)){
375 
376  tmp.m_key = key;
377  tmp.m_type = ConfigValues::SectionType;
378  tmp.m_int = m_sectionCounter;
379  m_sectionCounter += (1 << KP_SECTION_SHIFT);
380 
381  if(!put(tmp)){
382  return false;
383  }
384  }
385 
386  if(tmp.m_type != ConfigValues::SectionType){
387  return false;
388  }
389 
390  m_currentSection = tmp.m_int;
391 
392  tmp.m_key = no;
393  tmp.m_type = ConfigValues::IntType;
394  tmp.m_int = m_sectionCounter;
395  if(!put(tmp)){
396  m_currentSection = parent;
397  return false;
398  }
399  m_sectionCounter += (1 << KP_SECTION_SHIFT);
400 
401  m_currentSection = tmp.m_int;
402  tmp.m_type = ConfigValues::IntType;
403  tmp.m_key = CFV_KEY_PARENT;
404  tmp.m_int = parent;
405  if(!put(tmp)){
406  m_currentSection = parent;
407  return false;
408  }
409 
410  return true;
411 }
412 
413 bool
414 ConfigValuesFactory::closeSection(){
415  ConfigValues::ConstIterator iter(* m_cfg);
416  iter.m_currentSection = m_currentSection;
417  const bool b = iter.closeSection();
418  m_currentSection = iter.m_currentSection;
419  return b;
420 }
421 
422 bool
423 ConfigValuesFactory::put(const ConfigValues::Entry & entry){
424 
425  if(m_freeKeys == 0 ||
426  (entry.m_type == ConfigValues::StringType && m_freeData < sizeof(char *))
427  || (entry.m_type == ConfigValues::Int64Type && m_freeData < 8 )){
428 
429  DEBUG ndbout_c("m_freeKeys = %d, m_freeData = %d -> expand",
430  m_freeKeys, m_freeData);
431 
432  expand(31, 20);
433  }
434 
435  const Uint32 tmp = entry.m_key | m_currentSection;
436  const Uint32 sz = m_cfg->m_size - m_freeKeys;
437 
438  Uint32 pos;
439  if (findKey(m_cfg->m_values, sz, tmp, &pos))
440  {
441  DEBUG ndbout_c("key %x already found at pos: %d", tmp, pos);
442  return false;
443  }
444 
445  DEBUG {
446  printf("H'before ");
447  Uint32 prev = 0;
448  for (Uint32 i = 0; i<sz; i++)
449  {
450  Uint32 val = m_cfg->m_values[2*i] & KP_MASK;
451  ndbout_c("%.8x", val);
452  assert(val >= prev);
453  prev = val;
454  }
455  }
456 
457  if (pos != 2*sz)
458  {
459  DEBUG ndbout_c("pos: %d sz: %d", pos, sz);
460  memmove(m_cfg->m_values + pos + 2, m_cfg->m_values + pos,
461  4 * (2*sz - pos));
462  }
463 
464 
465  Uint32 key = tmp;
466  key |= (entry.m_type << KP_TYPE_SHIFT);
467  m_cfg->m_values[pos] = key;
468 
469  DEBUG {
470  printf("H'after ");
471  Uint32 prev = 0;
472  for (Uint32 i = 0; i<=sz; i++)
473  {
474  Uint32 val = m_cfg->m_values[2*i] & KP_MASK;
475  ndbout_c("%.8x", val);
476  assert(val >= prev);
477  prev = val;
478  }
479  }
480 
481  switch(entry.m_type){
482  case ConfigValues::IntType:
483  case ConfigValues::SectionType:
484  m_cfg->m_values[pos+1] = entry.m_int;
485  m_freeKeys--;
486  DEBUG printf("Putting at: %d(%d) (loop = %d) key: %d value: %d\n",
487  pos, sz, 0,
488  (key >> KP_KEYVAL_SHIFT) & KP_KEYVAL_MASK,
489  entry.m_int);
490  return true;
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 : "");
496  m_freeKeys--;
497  m_freeData -= sizeof(char *);
498  DEBUG printf("Putting at: %d(%d) (loop = %d) key: %d value(%d): %s\n",
499  pos, sz, 0,
500  (key >> KP_KEYVAL_SHIFT) & KP_KEYVAL_MASK,
501  index,
502  entry.m_string);
503  return true;
504  }
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;
509  m_freeKeys--;
510  m_freeData -= 8;
511  DEBUG printf("Putting at: %d(%d) (loop = %d) key: %d value64(%d): %lld\n",
512  pos, sz, 0,
513  (key >> KP_KEYVAL_SHIFT) & KP_KEYVAL_MASK,
514  index,
515  entry.m_int64);
516  return true;
517  }
518  case ConfigValues::InvalidType:
519  default:
520  return false;
521  }
522  return false;
523 }
524 
525 void
526 ConfigValuesFactory::put(const ConfigValues & cfg){
527 
528  Uint32 curr = m_currentSection;
529  m_currentSection = 0;
530 
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);
536  put(tmp);
537  }
538  }
539 
540  m_currentSection = curr;
541 }
542 
543 ConfigValues *
544 ConfigValuesFactory::extractCurrentSection(const ConfigValues::ConstIterator & cfg){
545  ConfigValuesFactory * fac = new ConfigValuesFactory(20, 20);
546  Uint32 curr = cfg.m_currentSection;
547 
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);
556  tmp.m_key = key;
557  fac->put(tmp);
558  }
559  }
560 
561  ConfigValues * ret = fac->getConfigValues();
562  delete fac;
563  return ret;
564 }
565 
566 ConfigValues *
567 ConfigValuesFactory::getConfigValues(){
568  ConfigValues * ret = m_cfg;
569  m_cfg = create(10, 10);
570  return ret;
571 }
572 
573 static int
574 mod4(unsigned int i){
575  int res = i + (4 - (i % 4));
576  return res;
577 }
578 
579 Uint32
580 ConfigValues::getPackedSize() const {
581 
582  Uint32 size = 0;
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)){
587  case IntType:
588  case SectionType:
589  size += 8;
590  break;
591  case Int64Type:
592  size += 12;
593  break;
594  case StringType:
595  size += 8; // key + len
596  size += mod4(strlen(* getString(m_values[i+1])) + 1);
597  break;
598  case InvalidType:
599  default:
600  abort();
601  }
602  }
603  }
604 
605  return size + sizeof(Magic) + 4; // checksum also
606 }
607 
608 Uint32
609 ConfigValues::pack(void * _dst, Uint32 _len) const {
610  Uint32 i;
611  char * dst = (char*)_dst;
612  memcpy(dst, Magic, sizeof(Magic)); dst += sizeof(Magic);
613 
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)){
619  case IntType:
620  case SectionType:
621  * (Uint32*)dst = htonl(key); dst += 4;
622  * (Uint32*)dst = htonl(val); dst += 4;
623  break;
624  case Int64Type:{
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;
631  }
632  break;
633  case StringType:{
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);
640  dst += mod4(len);
641  }
642  break;
643  case InvalidType:
644  default:
645  abort();
646  }
647  }
648  }
649 
650  const Uint32 * sum = (Uint32*)_dst;
651  const Uint32 len = Uint32(((Uint32*)dst) - sum);
652  Uint32 chk = 0;
653  for(i = 0; i<len; i++){
654  chk ^= htonl(sum[i]);
655  }
656 
657  * (Uint32*)dst = htonl(chk); dst += 4;
658  return 4 * (len + 1);
659 }
660 
661 bool
662 ConfigValuesFactory::unpack(const void * _src, Uint32 len){
663 
664  if(len < sizeof(Magic) + 4){
665  DEBUG abort();
666  return false;
667  }
668 
669  if(memcmp(_src, Magic, sizeof(Magic)) != 0){
670  DEBUG abort();
671  return false;
672  }
673 
674  const char * src = (const char *)_src;
675  const char * end = src + len - 4;
676  src += sizeof(Magic);
677 
678  {
679  Uint32 len32 = (len >> 2);
680  const Uint32 * tmp = (const Uint32*)_src;
681  Uint32 chk = 0;
682  for(Uint32 i = 0; (i+1)<len32; i++){
683  chk ^= ntohl(tmp[i]);
684  }
685 
686  if(chk != ntohl(tmp[len32-1])){
687  DEBUG abort();
688  return false;
689  }
690  }
691 
692  const char * save = src;
693 
694  {
695  Uint32 keys = 0;
696  Uint32 data = 0;
697  while(end - src > 4){
698  Uint32 tmp = ntohl(* (const Uint32 *)src); src += 4;
699  keys++;
700  switch(::getTypeOf(tmp)){
701  case ConfigValues::IntType:
702  case ConfigValues::SectionType:
703  src += 4;
704  break;
705  case ConfigValues::Int64Type:
706  src += 8;
707  data += 8;
708  break;
709  case ConfigValues::StringType:{
710  Uint32 s_len = ntohl(* (const Uint32 *)src);
711  src += 4 + mod4(s_len);
712  data += sizeof(char*);
713  break;
714  }
715  default:
716  break;
717  }
718  }
719  expand(keys, data);
720  }
721 
722  src = save;
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;
732  break;
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;
737  }
738  break;
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){
743  DEBUG abort();
744  return false;
745  }
746 
747  entry.m_string = (const char*)src; src+= mod4(s_len);
748  }
749  break;
750  case ConfigValues::InvalidType:
751  default:
752  DEBUG abort();
753  return false;
754  }
755  if(!put(entry)){
756  DEBUG abort();
757  return false;
758  }
759  }
760  if(src != end){
761  DEBUG abort();
762  return false;
763  }
764  return true;
765 }
766 
767 #ifdef __TEST_CV_HASH_HPP
768 
769 int
770 main(void){
771  srand(time(0));
772  for(int t = 0; t<100; t++){
773  const size_t len = directory(rand() % 1000);
774 
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++){
780  buf[j] = p;
781  p = nextHash(key, len, p, j+1);
782  }
783 
784  for(size_t j = 0; j<len; j++){
785  Uint32 pos = buf[j];
786  int unique = 0;
787  for(size_t k = j + 1; k<len; k++){
788  if(pos == buf[k]){
789  if(unique > 0)
790  printf("size=%d key=%d pos(%d)=%d buf[%d]=%d\n", len, key, j, pos, k, buf[k]);
791  unique ++;
792  }
793  }
794  if(unique > 1){
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]);
798  }
799  printf("\n");
800  }
801  }
802  }
803  delete[] buf;
804  }
805  return 0;
806 }
807 
808 #endif