/* Copyright (C) 1999 Monty Program KB

   This software is distributed with NO WARRANTY OF ANY KIND.  No author or
   distributor accepts any responsibility for the consequences of using it, or
   for whether it serves any particular purpose or works at all, unless he or
   she says so in writing.  Refer to the Free Public License (the "License")
   for full details.

   Every copy of this file must include a copy of the License, normally in a
   plain ASCII text file named PUBLIC.  The License grants you the right to
   copy, modify and redistribute this file, but only under certain conditions
   described in the License.  Among other things, the License requires that
   the copyright notice and this notice be preserved on all copies. */

#if defined(USE_RAID)

#ifdef __GNUC__
#pragma interface			/* gcc class implementation */
#endif

/* Trap all occurences of my_...() in source and use our wrapper around this function */

#ifdef MAP_TO_USE_RAID
#define my_read(A,B,C,D)     my_raid_read(A,B,C,D)
#define my_write(A,B,C,D)    my_raid_write(A,B,C,D)
#define my_pwrite(A,B,C,D,E) my_raid_pwrite(A,B,C,D,E)
#define my_pread(A,B,C,D,E)  my_raid_pread(A,B,C,D,E)
#define my_chsize(A,B,C)     my_raid_chsize(A,B,C)
#define my_close(A,B)        my_raid_close(A,B)
#define my_tell(A,B)         my_raid_tell(A,B)
#define my_seek(A,B,C,D)     my_raid_seek(A,B,C,D)
#define my_lock(A,B,C,D,E)     my_raid_lock(A,B,C,D,E)
#endif /* MAP_TO_USE_RAID */

#define RAID_TYPE_0 1       // Striping
#define RAID_TYPE_x 2       // Some new modes
#define RAID_TYPE_y 3       // 

#ifdef __cplusplus
extern "C" {
#endif
  void init_raid(void);
  void end_raid(void);

  bool is_raid(File fd);
  File my_raid_create(const char *FileName, int CreateFlags, int access_flags,
		      uint raid_type, uint raid_chunks, ulong raid_chunksize,
		      myf MyFlags);
  File my_raid_open(const char *FileName, int Flags,
		    uint raid_type, uint raid_chunks, ulong raid_chunksize,
		    myf MyFlags);
  int my_raid_rename(const char *from, const char *to, uint raid_chunks,
		     myf MyFlags);
  int my_raid_delete(const char *from, uint raid_chunks, myf MyFlags);
  my_off_t my_raid_seek(File fd, my_off_t pos, int whence, myf MyFlags);
  my_off_t my_raid_tell(File fd, myf MyFlags);

  uint my_raid_write(File,const byte *Buffer, uint Count, myf MyFlags);
  uint my_raid_read(File Filedes, byte *Buffer, uint Count, myf MyFlags);

  uint my_raid_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset,
		     myf MyFlags);
  uint my_raid_pwrite(int Filedes, const byte *Buffer, uint Count,
		      my_off_t offset, myf MyFlags);

  int my_raid_lock(File,int locktype, my_off_t start, my_off_t length,
		   myf MyFlags);
  int my_raid_chsize(File fd, my_off_t newlength, myf MyFlags);
  int my_raid_close(File, myf MyFlags);

#ifdef __cplusplus
}

class RaidName {
  public:
    RaidName(const char *FileName);
    ~RaidName();
    bool IsRaid();
    int Rename(const char * from, const char * to, myf MyFlags);
  private:
    uint _raid_type;       // RAID_TYPE_0 or RAID_TYPE_1 or RAID_TYPE_5
    uint _raid_chunks;     // 1..n
    ulong _raid_chunksize; // 1..n in bytes
};

class RaidFd {
  public:
    RaidFd(uint raid_type, uint raid_chunks , ulong raid_chunksize);
    ~RaidFd();
    File Create(const char *FileName, int CreateFlags, int access_flags,
		myf MyFlags);
    File Open(const char *FileName, int Flags, myf MyFlags);
    my_off_t Seek(my_off_t pos,int whence,myf MyFlags);
    my_off_t Tell(myf MyFlags);
    int Write(const byte *Buffer, uint Count, myf MyFlags);
    int Read(const byte *Buffer, uint Count, myf MyFlags);
    int Lock(int locktype, my_off_t start, my_off_t length, myf MyFlags);
    int Chsize(File fd, my_off_t newlength, myf MyFlags);
    int Close(myf MyFlags);
    static bool IsRaid(File fd);
    static DYNAMIC_ARRAY _raid_map;		/* Map of RaidFD* */
  private:

    uint _raid_type;       // RAID_TYPE_0 or RAID_TYPE_1 or RAID_TYPE_5
    uint _raid_chunks;     // 1..n
    ulong _raid_chunksize; // 1..n in bytes

    ulong _total_block;    // We are operating with block no x (can be 0..many).
    uint _this_block;      // can be 0.._raid_chunks
    uint _remaining_bytes; // Maximum bytes that can be written in this block

    my_off_t _position;
    File _fd;
    File *_fd_vector;		/* Array of File */

    void _Calculate();
};

#endif /* __cplusplus */
#endif /* USE_RAID */
