core/index.c

Go to the documentation of this file.
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     /* reversal forces adjustment when first item is received */
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) /* grow on bottom end */
00071     {
00073         /* (this is very unusual and shouldn't happen the way things are now) */
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) /* grow on to end */
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;   /* double until it fits */
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) /* new list at ordinal */
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 

GridLAB-DTM Version 1.0
An open-source project initiated by the US Department of Energy