// ImpactStore.h -- Storing impacts on disk


#ifndef IMPACT_STORE_H
#define IMPACT_STORE_H

#include <stdio.h>
#include <stdlib.h>

#include "Impact.h"
#include "DynamicVector.h"

class ImpactStoreWindow;

class ImpactFile
{
public:
  ImpactFile();
  ~ImpactFile();

  int initialise(const int);

  FILE                   *file;              // Underlying file.
  long                   *fb;                // First block position.
};


// ImpactStore is a class used to store Impact objects.
// All impacts are assumed to take the same space on disk.
// You can assign an id (positive integer number) to an Impact.
// The impacts are sorted by id.
// You have to specify a maximum id when constructing an instance of this class.
// Ids are assumed to begin at 0. 

class ImpactStore
{
public:
  // Constructor.
  // IN:  maximumid    is the maximum id you will be able to assign to an impact. 
  // PRE: maximumid>0.
  // OUT: A pointer to an ImpactStore (NULL if memory allocation failed).
  ImpactStore(const int numsurf);

  // Destructor.
  // POST: Ressources taken by ImpactStore are freed.
  ~ImpactStore();


  // Record an Impact.
  // IN:  id     is an id (integer inside [0,maximumid]).
  //      impact is the Impact to be stored.
  // OUT: 0      if the operation failed,
  //      non 0  otherwise.
  int recordImpact(const int id,const Impact& impact);


  // Flush all Impacts to disk.
  // POST: You are able to iterate through the Impacts for an id.
  void flush();


  // Get the number of Impact recorded for an identifier.
  // IN:  id  is an identifier.    
  // OUT: the number of impacts for id.
  int getNumberOfImpacts(const int id);


  // Create an ImpactStoreWindow
  // IN:  id is an identifier
  // OUT: an ImpactStoreWindow that can be used to read impact stored for id.
  ImpactStoreWindow* newImpactStoreWindow(const int id);

  friend class ImpactStoreWindow;

private:

  static const int       buffersz=200000;  // Buffer size (in number of impacts).
  static const long      bsz=512;          // Block size on disk
  static const long      maxfilesz=1024*1024*512; // Maximum size for a file (512 Mb)
  static const int       maxfile=50;       // Maximum number of impact file (50) --> (25 Gb limit)


  int                    maxid;            // Maximum id number + 1.
  long                   sizeofimpact;     // Size (in bytes) needed to store an impact on disk.
  long                   impactperblock;   // Number of impacts per block.



  ImpactFile             pf[maxfile];      // Array of impact files

  long                   *lb;              // Last block array.
  int                    *lf;              // Last impact file number array.

  long                   cb;               // Current block position.
  int                    cf;               // Current impact file number.
  



  long                   *numonid;         // A per id counter.
  DynamicVector          **ids;            // One dynamic vector per id for buffering.


  long                   numinmemory;      // A general counter.
  Impact                 *buffer;          // Array of impact for buffering

};




// ImpactStoreWindow is a class used to iterate through Impact stored in a ImpactStore.
// An ImpactStoreWindow is associated to an id of ImpactStore.
// The only way to construct an ImpactStoreWindow is to call the newImpactStoreWindow of
// the ImpactStore class.
class ImpactStoreWindow
{
public:
  // Read the next impact.
  // IN:   An impact who will contain the next impact
  // OUT:  0:      There are no more impacts (no impact read)
  //       non 0:  The next impact was read.
  int readNext(Impact &);

  friend class ImpactStore;

private:
  ImpactStore *is;
  int         id;
  long        curblock;  // current block
  int         curfile;   // current file
  int         curnum;
  int         maxnum;
};


#endif














