00001
00010 #include <stdlib.h>
00011 #include <memory.h>
00012 #include <string.h>
00013 #include <errno.h>
00014 #include "output.h"
00015 #include "index.h"
00016
00017 static unsigned int next_index_id = 0;
00018
00022 INDEX *index_create(int first_ordinal,
00023 int last_ordinal)
00024 {
00025 int size = (unsigned int)(last_ordinal - first_ordinal + 1);
00026 INDEX *index = malloc(sizeof(INDEX));
00027 if (index!=NULL)
00028 {
00029 if (size<1)
00030 {
00031 errno = EINVAL;
00032 goto Undo;
00033 }
00034 index->ordinal = malloc(sizeof(LIST*)*size);
00035 if (index->ordinal==NULL)
00036 {
00037 errno = ENOMEM;
00038 goto Undo;
00039 }
00040 index->id = next_index_id++;
00041 index->first_ordinal = first_ordinal;
00042 index->last_ordinal = last_ordinal;
00043 memset(index->ordinal,0,sizeof(LIST*)*size);
00044 output_verbose("creating index %d", index->id);
00045 }
00046 else
00047 {
00048 errno = ENOMEM;
00049 return NULL;
00050 }
00051
00052
00053 index->first_used=last_ordinal;
00054 index->last_used=first_ordinal;
00055 return index;
00056 Undo:
00057 free(index);
00058 return NULL;
00059 }
00060
00064 STATUS index_insert(INDEX *index,
00065 void *data,
00066 int ordinal)
00067 {
00068 int pos = ordinal - index->first_ordinal;
00069
00070 if (ordinal<index->first_ordinal)
00071 {
00073
00074 output_fatal("ordinal %d is too small (first is %d)",ordinal, index->first_ordinal);
00075 errno = EINVAL;
00076 return FAILED;
00077 }
00078 else if (ordinal>=index->last_ordinal)
00079 {
00080 int oldsize = index->last_ordinal - index->first_ordinal;
00081 int newsize = oldsize;
00082 LIST **newblock = NULL;
00083 while (ordinal >= index->first_ordinal + newsize)
00084 newsize *= 2;
00085 newblock = malloc(sizeof(LIST*)*newsize);
00086 if (newblock==NULL)
00087 {
00088 output_fatal("unable to grow index %d: %s",index->id, strerror(errno));
00089 return FAILED;
00090 }
00091 output_verbose("growing index %d to %d ordinals", index->id, newsize);
00092 memset(newblock,0,sizeof(LIST*)*newsize);
00093 memcpy(newblock,index->ordinal,sizeof(LIST*)*oldsize);
00094 free(index->ordinal);
00095 index->ordinal = newblock;
00096 index->last_ordinal = index->first_ordinal + newsize;
00097
00098 }
00099 if (index->ordinal[pos]==NULL)
00100 {
00101 index->ordinal[pos] = list_create();
00102 if (index->ordinal[pos]==NULL)
00103 return FAILED;
00104 }
00105 if (list_append(index->ordinal[pos],data)==NULL)
00106 return FAILED;
00107 if (ordinal<index->first_used) index->first_used=ordinal;
00108 if (ordinal>index->last_used) index->last_used=ordinal;
00109 return SUCCESS;
00110 }
00111
00115 void index_shuffle(INDEX *index)
00116 {
00117 int i, size = index->last_used - index->first_used;
00118 for (i=0; i<size; i++)
00119 list_shuffle(index->ordinal[i]);
00120 output_verbose("shuffled %d lists in index %d", size, index->id);
00121 }
00122