~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/hash.cc

  • Committer: Monty Taylor
  • Date: 2009-10-13 06:22:10 UTC
  • mfrom: (1182 staging)
  • mto: This revision was merged to the branch mainline in revision 1184.
  • Revision ID: mordred@inaugust.com-20091013062210-iwnwwcdamjdvlx1m
Merged up with build.

Show diffs side-by-side

added added

removed removed

Lines of Context:
121
121
  return;
122
122
}
123
123
 
124
 
 
125
 
/*
126
 
  Delete all elements from the hash (the hash itself is to be reused).
127
 
 
128
 
  SYNOPSIS
129
 
  my_hash_reset()
130
 
  hash   the hash to delete elements of
131
 
*/
132
 
 
133
 
void my_hash_reset(HASH *hash)
134
 
{
135
 
  hash_free_elements(hash);
136
 
  reset_dynamic(&hash->array);
137
 
  /* Set row pointers so that the hash can be reused at once */
138
 
  hash->blength= 1;
139
 
  return;
140
 
}
141
 
 
142
124
/* some helper functions */
143
125
 
144
126
/*
541
523
  return(0);
542
524
}
543
525
 
544
 
/*
545
 
  Update keys when record has changed.
546
 
  This is much more efficent than using a delete & insert.
547
 
*/
548
 
 
549
 
bool hash_update(HASH *hash, unsigned char *record, unsigned char *old_key,
550
 
                 size_t old_key_length)
551
 
{
552
 
  uint32_t new_index,new_pos_index,blength,records,empty;
553
 
  size_t idx;
554
 
  HASH_LINK org_link,*data,*previous,*pos;
555
 
 
556
 
  if (HASH_UNIQUE & hash->flags)
557
 
  {
558
 
    HASH_SEARCH_STATE state;
559
 
    unsigned char *found,
560
 
      *new_key= (unsigned char*) hash_key(hash, record, &idx, 1);
561
 
 
562
 
    if ((found= hash_first(hash, new_key, idx, &state)))
563
 
    {
564
 
      do
565
 
      {
566
 
        if (found != record)
567
 
          return(1);            /* Duplicate entry */
568
 
      }
569
 
      while ((found= hash_next(hash, new_key, idx, &state)));
570
 
    }
571
 
  }
572
 
 
573
 
  data=dynamic_element(&hash->array,0,HASH_LINK*);
574
 
  blength=hash->blength; records=hash->records;
575
 
 
576
 
  /* Search after record with key */
577
 
 
578
 
  idx=hash_mask(calc_hash(hash, old_key,(old_key_length ?
579
 
                                         old_key_length :
580
 
                                         hash->key_length)),
581
 
                blength,records);
582
 
  new_index=hash_mask(rec_hashnr(hash,record),blength,records);
583
 
  if (idx == new_index)
584
 
    return(0);                  /* Nothing to do (No record check) */
585
 
  previous=0;
586
 
  for (;;)
587
 
  {
588
 
 
589
 
    if ((pos= data+idx)->data == record)
590
 
      break;
591
 
    previous=pos;
592
 
    if ((idx=pos->next) == NO_RECORD)
593
 
      return(1);                        /* Not found in links */
594
 
  }
595
 
  org_link= *pos;
596
 
  empty= static_cast<uint32_t>(idx);
597
 
 
598
 
  /* Relink record from current chain */
599
 
 
600
 
  if (!previous)
601
 
  {
602
 
    if (pos->next != NO_RECORD)
603
 
    {
604
 
      empty= pos->next;
605
 
      *pos= data[pos->next];
606
 
    }
607
 
  }
608
 
  else
609
 
    previous->next=pos->next;           /* unlink pos */
610
 
 
611
 
  /* Move data to correct position */
612
 
  if (new_index == empty)
613
 
  {
614
 
    /*
615
 
      At this point record is unlinked from the old chain, thus it holds
616
 
      random position. By the chance this position is equal to position
617
 
      for the first element in the new chain. That means updated record
618
 
      is the only record in the new chain.
619
 
    */
620
 
    if (empty != idx)
621
 
    {
622
 
      /*
623
 
        Record was moved while unlinking it from the old chain.
624
 
        Copy data to a new position.
625
 
      */
626
 
      data[empty]= org_link;
627
 
    }
628
 
    data[empty].next= NO_RECORD;
629
 
    return(0);
630
 
  }
631
 
  pos=data+new_index;
632
 
  new_pos_index=hash_rec_mask(hash,pos,blength,records);
633
 
  if (new_index != new_pos_index)
634
 
  {                                     /* Other record in wrong position */
635
 
    data[empty] = *pos;
636
 
    movelink(data,new_index,new_pos_index,empty);
637
 
    org_link.next=NO_RECORD;
638
 
    data[new_index]= org_link;
639
 
  }
640
 
  else
641
 
  {                                     /* Link in chain at right position */
642
 
    org_link.next=data[new_index].next;
643
 
    data[empty]=org_link;
644
 
    data[new_index].next=empty;
645
 
  }
646
 
  return(0);
647
 
}
648
 
 
649
 
 
650
526
unsigned char *hash_element(HASH *hash,uint32_t idx)
651
527
{
652
528
  if (idx < hash->records)
654
530
  return 0;
655
531
}
656
532
 
657
 
 
658
 
/*
659
 
  Replace old row with new row.  This should only be used when key
660
 
  isn't changed
661
 
*/
662
 
 
663
 
void hash_replace(HASH *hash, HASH_SEARCH_STATE *current_record,
664
 
                  unsigned char *new_row)
665
 
{
666
 
  if (*current_record != NO_RECORD)            /* Safety */
667
 
    dynamic_element(&hash->array, *current_record, HASH_LINK*)->data= new_row;
668
 
}