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