Logo Search packages:      
Sourcecode: ras version File versions  Download package

applysum.c

/*
    ras - Redundant Archive System
    Copyright (C) 1999  Nick Cleaton

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

    Nick Cleaton <nick@cleaton.net>
*/


#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stddef.h>

#include "common.h"
#include "utils.h"
#include "field.h"
#include "applysum.h"


struct input_file
{  FILE *f;
   char *name;
   unsigned char *buf;
   int want_trailing_1;
   int at_eof;
};

struct output_file
{  FILE *f;
   char *name;
   unsigned char *buf;
   int strip_trailing_1;
   int found_trailing_1;
   long zero_count;
   field_t *genvec;
};

static size_t flush10_blocksize;
static uchar *flush10_1base;
static uchar *flush10_0base;

/*************************************************************************/

size_t read_blocks(size_t count, struct input_file *infiles, size_t blocksize);
void write_block(struct output_file *outfile, size_t len);

void process_data(size_t incount,  struct inblkstream *inblks, 
                  size_t outcount, struct outblkstream *outblks,
              size_t blocksize, int footer)
{
   size_t i, n, len;
   int *gotvec;
   struct input_file *infiles;
   struct output_file *outfiles;
   unsigned char *buffer_storage;
   unsigned char *inbuf_base;
   unsigned char *p;

   /*
   ** Sort out storage used for writing out 100000..... sequences that
   ** have been held back because they might be the trailing 1000... on
   ** an output segfile, but have turned out not to be.
   */
   flush10_blocksize = blocksize;
   flush10_1base = Malloc( blocksize + 1 );
   flush10_0base = flush10_1base + 1;

   flush10_1base[0] = (uchar) 1;
   n=blocksize; p=flush10_0base;
   while(n--)
      *p++ = (uchar) 0;

   /*
   ** Build a vector of the available x values.
   */
   gotvec = Malloc( incount * sizeof(*gotvec) );
   for( i=0 ; i<incount ; i++ )
      gotvec[i] = inblks[i].x_val;
    
   /*
   ** Allocate storage and initialise the arrays of structs representing
   ** input and output files.
   */
   infiles = Malloc( incount * sizeof(*infiles) );
   outfiles = Malloc( outcount * sizeof(*outfiles) );
   buffer_storage = Malloc( (incount + outcount) * blocksize );
   inbuf_base = buffer_storage;
   for( i=0 ; i<incount ; i++ )
   {  infiles[i].f = inblks[i].f;
      infiles[i].name = inblks[i].name;
      infiles[i].buf = buffer_storage + blocksize * i;
      infiles[i].want_trailing_1 = (!inblks[i].is_sum) && footer;
      infiles[i].at_eof = 0;
   }
   for( i=0 ;i<outcount ; i++ )
   {  outfiles[i].f = outblks[i].f;
      outfiles[i].name = outblks[i].name;
      outfiles[i].buf = buffer_storage + blocksize * (incount + i);
      outfiles[i].strip_trailing_1 = (!outblks[i].is_sum) && footer;
      outfiles[i].found_trailing_1 = 0;
      outfiles[i].zero_count = 0;
      outfiles[i].genvec = Makevector(incount, gotvec, outblks[i].x_val);
   }
   free( gotvec );


   /*
   ** Main loop: read data from each input file, compute the sums and
   ** write the output files until all the input files are at EOF. 
   */
   while( (len = read_blocks(incount, infiles, blocksize)) )
   {  
      for( i=0 ; i<outcount ; i++ )
      {  dotproduct( incount, inbuf_base, blocksize, outfiles[i].buf,
                                                 outfiles[i].genvec, len );
                                              
       write_block( outfiles+i, len );
      }
   }


   for( i=0 ; i<outcount ; i++ )
      free( outfiles[i].genvec );
   free( outfiles );
   free( infiles );
   free( buffer_storage );
   free( flush10_1base );
}

/*************************************************************************/

size_t read_block(struct input_file *infile, size_t blocksize);

size_t read_blocks(size_t count, struct input_file *infiles, size_t blocksize)
{
   size_t maxlen, i, j;
   size_t *lens;

   lens = Malloc( count * sizeof(*lens) ); 

   maxlen = 0;
   for( i=0 ; i<count ; i++ )
   {  lens[i] = read_block( infiles+i, blocksize );
      maxlen = (lens[i] > maxlen) ? lens[i] : maxlen;
   }

   if( maxlen )
   {  /* some data read from at least 1 input file, pad to length */
      for( i=0 ; i<count ; i++ )
      {  for( j=lens[i] ; j<maxlen ; j++ )
            infiles[i].buf[j] = '\0';
      }         
   }

   free( lens );
   return maxlen;
}

/*************************************************************************/

size_t read_block(struct input_file *infile, size_t blocksize)
{ 
   size_t bytes_read;
 
   if( infile->at_eof ) return 0;

   bytes_read = fread(infile->buf, 1, blocksize, infile->f);
   if( bytes_read != blocksize )
   {  if( ferror(infile->f) )
      {  fprintf(stderr,PROGNAME ": error reading file %s: %s\n",
                                        infile->name, strerror(errno));
         exit_because_of_error(EXTERNAL_FAILURE);
      }
      else
      {  /*  Underlength read, end of file  */
         infile->at_eof = 1;
       if( infile->want_trailing_1 )
       {  infile->buf[bytes_read++] = 1;
          infile->want_trailing_1 = 0;
       }
      }
   }

   return bytes_read;
}

/*************************************************************************/

void flush_1_and_0s(struct output_file *outfile);
int all_zero(unsigned char *buffer, size_t len);
size_t count_trailing_0s(uchar *buf, size_t len);

void write_block(struct output_file *outfile, size_t len)
{
   size_t zeros;

   if( outfile->strip_trailing_1 )
   {  if( outfile->found_trailing_1 )
      {  /*  We're in the middle of a 1 followed by some 0s.  */
         if( all_zero(outfile->buf, len) )
       {  outfile->zero_count += len;
          return;
       }
       else
       {  flush_1_and_0s( outfile );
       }
      }

      zeros = count_trailing_0s( outfile->buf, len );
      if( zeros < len && outfile->buf[len - zeros - 1] == 1 )
      {  /*  Start of a 100... block  */
         outfile->found_trailing_1 = 1;
       outfile->zero_count = zeros;
       len -= (zeros + 1);
      }
   }
         
   if( len == 0 ) return;

   if( fwrite(outfile->buf, 1, len, outfile->f) != len )
   {      
      fprintf(stderr,PROGNAME ": error writing to file %s: %s\n",
                                         outfile->name, strerror(errno));
      exit_because_of_error(EXTERNAL_FAILURE);
   }

}

/*************************************************************************/
      
void flush_1_and_0s(struct output_file *outfile)
{
   size_t rest, whole;
   
   if( ! outfile->found_trailing_1 ) 
      return;

   whole = outfile->zero_count / flush10_blocksize;
   rest = outfile->zero_count % flush10_blocksize;

   if( fwrite(flush10_1base, 1, rest+1, outfile->f) != rest+1 )
   {      
      fprintf(stderr,PROGNAME ": error writing to file %s: %s\n",
                                         outfile->name, strerror(errno));
      exit_because_of_error(EXTERNAL_FAILURE);
   }
      
   while(whole--)
   {  if( fwrite(flush10_0base, 1, flush10_blocksize, outfile->f) !=
                                                       flush10_blocksize )
      {      
       fprintf(stderr,PROGNAME ": error writing to file %s: %s\n",
                                  outfile->name, strerror(errno));
       exit_because_of_error(EXTERNAL_FAILURE);
      }
   }

   outfile->found_trailing_1 = 0;
   outfile->zero_count = 0;
}

/*************************************************************************/

int all_zero(unsigned char *buffer, size_t len)
{
   while( len-- )
   {  if( *buffer++ )
         return 0;
   }
   return 1;
}

/*************************************************************************/

size_t count_trailing_0s(uchar *buf, size_t len)
{
   size_t found;
   uchar *end;

   found = 0;
   end = buf + (len-1);
   while( len-- && !*end-- )
      found++;

   return found;
}

/*************************************************************************/


Generated by  Doxygen 1.6.0   Back to index