~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/hash.cc

  • Committer: Padraig O'Sullivan
  • Date: 2009-09-13 01:03:01 UTC
  • mto: (1126.9.2 captain-20090915-01)
  • mto: This revision was merged to the branch mainline in revision 1133.
  • Revision ID: osullivan.padraig@gmail.com-20090913010301-tcvvezipx1124acy
Added calls to the dtrace delete begin/end probes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
/* One of key_length or key_length_offset must be given */
22
22
/* Key length of 0 isn't allowed */
23
23
 
24
 
#include "config.h"
25
 
#include "drizzled/my_hash.h"
26
 
#include "drizzled/charset.h"
27
 
#include "drizzled/charset_info.h"
28
 
 
29
 
namespace drizzled
30
 
{
 
24
#include <drizzled/global.h>
 
25
#include CSTDINT_H
 
26
#include <mysys/hash.h>
31
27
 
32
28
const uint32_t NO_RECORD= UINT32_MAX;
33
29
 
125
121
  return;
126
122
}
127
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
 
128
142
/* some helper functions */
129
143
 
130
144
/*
319
333
  data=dynamic_element(&info->array,0,HASH_LINK*);
320
334
  halfbuff= info->blength >> 1;
321
335
 
322
 
  idx= first_index= info->records-halfbuff;
 
336
  idx=first_index=info->records-halfbuff;
323
337
  /* If some records */
324
338
  if (idx != info->records)
325
339
  {
527
541
  return(0);
528
542
}
529
543
 
 
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=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
 
530
650
unsigned char *hash_element(HASH *hash,uint32_t idx)
531
651
{
532
652
  if (idx < hash->records)
534
654
  return 0;
535
655
}
536
656
 
537
 
} /* namespace drizzled */
 
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
}