
/*-------------------------------------------------------------------------*
 *                                                                         *
 * Attempts to rebuild both the Data and Index file, eliminating deleted   *
 * blocks.  The current Index file MUST reflect the contents of the data   *
 * data file.  All index information is retained, including alternates.    *
 *                                                                         *
 * Compiles under Manx C 5.0d                                              *
 *   cc -hi allprecomp -pp -wnuq -o reloadrmfdata.o reloadrmfdata.c        *
 *   ln -o reloadrmfdata reloadrmfdata.o -lc                               *
 *                                                                         *
 * Compile/link for Lattice 5.10                                           *
 *     LC -L -Hinclude:allprecomp.q reloadrmfdata                          *
 *           (pre-compiled header file)                                    *
 *                                                                         *
 *-------------------------------------------------------------------------*/
 

#include "avl.structs.h"

int reload_data_index( char *ifile, char *dfile, char *nindex, char *ndata);

main( int argc, char *argv[] )
{
    char *oldi,*oldd,*newi,*newd;
    long oldnamelen;
    int  noerr;
    
    if( argc < 2 ) {
        printf("\n Syntax is %s 'name of rmf file'\n",argv[0]);
        exit( 10 );
    }
        
    oldnamelen = strlen(argv[1]) + 50;
    
    oldi = AllocMem( oldnamelen, MEMF_CLEAR );
    oldd = AllocMem( oldnamelen, MEMF_CLEAR );
    newi = AllocMem( oldnamelen, MEMF_CLEAR );
    newd = AllocMem( oldnamelen, MEMF_CLEAR );
    
    strcpy(oldd,argv[1]);
    strcpy(oldi,argv[1]);
    strcpy(newi,argv[1]);
    strcpy(newd,argv[1]);
    
    strcat(oldi,".rmfindex");
    strcat(newi,".NEW.RMFINDEX");
    strcat(newd,".NEW");
    
    noerr = reload_data_index( oldi, oldd, newi, newd );
    if( noerr ) {
        printf("\n\n   DataFile %s rebuilt as %s\n",oldd,newd);
        printf("\n   IndexFile %s rebuilt as %s\n\n",oldi,newi);
    }
    else 
       printf("\n\n  Error Occured during rebuild \n\n");
    
    FreeMem( oldi, oldnamelen);
    FreeMem( oldd, oldnamelen);
    FreeMem( newi, oldnamelen);
    FreeMem( newd, oldnamelen);
    
}

 
int reload_data_index( char *indexfile, char *datafile, char *newindex, char *newdata)
{


   struct IndexFile      *ix;
   struct DiskIndex      *dtnode; 
   struct DataFileHeader *dfh;
   struct RecordHeader   *rh;
   char                  *datablock; 
   ULONG                 blocklen;
   ULONG                 recaddr,rba;
   ULONG                 ifd,dfd,nifd,ndfd;
   long                  err,total_keylen;
   int                   ok,i;

   
   ifd = Open(indexfile,MODE_OLDFILE);
   if( !ifd ) {
       printf(" COULD NOT OPEN INDEX file %s\n",indexfile);
       return( FALSE );
   }
   
   dfd = Open(datafile,MODE_OLDFILE);
   if( !ifd ) {
       printf(" COULD NOT OPEN DATA file %s\n",datafile);
       Close( ifd );
       return( FALSE );
   }
   
   ndfd = Open(newdata,MODE_NEWFILE);
   if( !ifd ) {
       printf(" COULD NOT CREATE DATA file %s\n",newdata);
       Close( dfd );
       Close( ifd );
       return( FALSE );
   }
   
   nifd = Open(newindex,MODE_NEWFILE);
   if( !nifd ) {
       printf(" COULD NOT CREATE file %s\n",newindex);
       Close( ndfd );
       Close( dfd );
       Close( ifd );
       return( FALSE );
   }
   

   ix     = AllocMem( sizeof(struct IndexFile), MEMF_CLEAR );
   dtnode = AllocMem( sizeof(struct DiskIndex), MEMF_CLEAR );
   dfh    = AllocMem( sizeof(struct DataFileHeader), MEMF_CLEAR );
   rh     = AllocMem( sizeof(struct RecordHeader), MEMF_CLEAR );
   if( !rh || !ix || !dtnode || !dfh ) {
       printf("\nUnable to allocate memory\n\n");
       if( ix )
           FreeMem( ix, sizeof(struct IndexFile) );
       if( dtnode ) 
           FreeMem( dtnode, sizeof(struct DiskIndex) );
       if( dfh ) 
           FreeMem( dfh, sizeof(struct DataFileHeader) );
       if( rh ) 
           FreeMem( rh, sizeof(struct RecordHeader) );
       Close( ndfd );
       Close( nifd );
       Close( dfd );
       Close( ifd );
       return( FALSE );    
   }
   
   ok = Read(ifd,ix,sizeof(struct IndexFile));
   ok = Write(nifd,ix,sizeof(struct IndexFile));
   
   ok = Read(dfd,dfh,sizeof(struct DataFileHeader));
   ok = Write(ndfd,dfh,sizeof(struct DataFileHeader));
   
   ok = TRUE;
   while( ok ) {
   
      /* fixed portion */
      err = Read(ifd,dtnode,sizeof(struct DI_Info));
      if( err <= 0 ) 
           break;
      
      total_keylen = 0;
      for( i=0; i < MAXINDICES; i++ )
           total_keylen = total_keylen + dtnode->di_info.keylen[i]; 
           
      /* read variable key portion */
      err = Read(ifd,&dtnode->keydata[0],total_keylen);
      
      if( err <= 0 )
          break;

      if( dtnode->di_info.recstatus == 'D' )  /* a deleted block */
          continue;                           /* causing it to be removed */

      recaddr = dtnode->di_info.recaddr;      /* else gonna assume its 'A' */
      
      Seek(dfd,recaddr,OFFSET_BEGINNING);
      err = Read( dfd, rh, sizeof(struct RecordHeader));
      if( err <= 0 )
          break;
          
      blocklen  = rh->blocklength;
      datablock = AllocMem( blocklen, MEMF_CLEAR );    
      
      err = Read( dfd, datablock, (blocklen));
      if( err <= 0 )
          break;
          
      rba = Seek( ndfd, 0L, OFFSET_END);    
      rba = Seek( ndfd, 0L, OFFSET_CURRENT);    
      
      err = Write( ndfd, rh, sizeof(struct RecordHeader));
      err = Write( ndfd, datablock, (blocklen));
      
      dtnode->di_info.recaddr = rba; /* index record gets a new RBA here */
      
      err = Write( nifd, dtnode, sizeof(struct DI_Info)+total_keylen);
      
      FreeMem( datablock,blocklen);
   }   
   
   
   Close( ndfd );
   Close( nifd );
   Close( dfd );
   Close( ifd );
   
   FreeMem( ix, sizeof(struct IndexFile) );
   FreeMem( dtnode, sizeof(struct DiskIndex) );
   FreeMem( dfh, sizeof(struct DataFileHeader) );
   FreeMem( rh, sizeof(struct RecordHeader) );
   
   return( !err );
   
}

