#ifndef __SFS_INTERFACE_H__
#define __SFS_INTERFACE_H__
/******************************************************************************/
/*                                                                            */
/*                    X r d S f s I n t e r f a c e . h h                     */
/*                                                                            */
/* (c) 2010 by the Board of Trustees of the Leland Stanford, Jr., University  */
/*       All Rights Reserved. See XrdInfo.cc for complete License Terms       */
/*   Produced by Andrew Hanushevsky for Stanford University under contract    */
/*              DE-AC02-76-SFO0515 with the Department of Energy              */
/******************************************************************************/

#include <string.h>      // For strlcpy()
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>  // for sockaddr

#include "XrdOuc/XrdOucErrInfo.hh"

/******************************************************************************/
/*                            O p e n   M o d e s                             */
/******************************************************************************/

#define SFS_O_RDONLY           0         // open read/only
#define SFS_O_WRONLY           1         // open write/only
#define SFS_O_RDWR             2         // open read/write
#define SFS_O_CREAT        0x100         // used for file creation
#define SFS_O_TRUNC        0x200         // used for file truncation
#define SFS_O_POSC     0x0100000         // persist on successful close
#define SFS_O_NOWAIT  0x01000000         // do not impose operational delays
#define SFS_O_RAWIO   0x02000000         // allow client-side decompression
#define SFS_O_RESET   0x04000000         // Reset any cached information
#define SFS_O_REPLICA 0x08000000         // Open for replication

// The following flag may be set in the access mode arg for open() & mkdir()
// Note that on some systems mode_t is 16-bits so we use a careful value!
//
#define SFS_O_MKPTH   0x00004000         // Make directory path if missing

// The following options are here to provide a uniform clustering interface.
// They may be passed through open/locate/stat, as applicable.
//
#define SFS_O_LOCATE  0x10000000         // This request generated by locate()
#define SFS_O_STAT    0x20000000         // This request generated by stat()
#define SFS_O_META    0x40000000         // This request generated by metaop

/******************************************************************************/
/*                               D e f i n e s                                */
/******************************************************************************/

// Common fctl  command values (0 to 255)
//
#define SFS_FCTL_GETFD    1 // Return file descriptor if possible
#define SFS_FCTL_STATV    2 // Return visa information

// Common fsctl command values (0 to 255)
//
#define SFS_FSCTL_CMD   255

#define SFS_FSCTL_LOCATE  1 // Locate a file
#define SFS_FSCTL_STATFS  2 // Return FS data
#define SFS_FSCTL_STATLS  3 // Return LS data
#define SFS_FSCTL_STATXA  4 // Return XA data
#define SFS_FSCTL_PLUGIN  8 // Return Implementation Dependent Data
#define SFS_FSCTL_PLUGIO 16 // Return Implementation Dependent Data

// Return Values for Integer Returning XrdSfs Interface
//
#define SFS_STALL         1 // ErrInfo code -> Seconds to stall client
#define SFS_OK            0 // ErrInfo code -> All is well
#define SFS_ERROR        -1 // ErrInfo code -> Error occurred
#define SFS_REDIRECT   -256 // ErrInfo code -> Port number to redirect to
#define SFS_STARTED    -512 // ErrInfo code -> Estimated seconds to completion
#define SFS_DATA      -1024 // ErrInfo code -> Length of data

/******************************************************************************/
/*                 S t r u c t u r e s   &   T y p e d e f s                  */
/******************************************************************************/

typedef long long     XrdSfsFileOffset;
typedef int           XrdSfsFileOpenMode;
typedef int           XrdSfsMode;
typedef int           XrdSfsXferSize;

enum XrdSfsFileExistence 
{
     XrdSfsFileExistNo,
     XrdSfsFileExistIsFile,
     XrdSfsFileExistIsDirectory
};
//------------------------------------------------

#define Prep_PRTY0 0
#define Prep_PRTY1 1
#define Prep_PRTY2 2
#define Prep_PRTY3 3
#define Prep_PMASK 3
#define Prep_SENDAOK 4
#define Prep_SENDERR 8
#define Prep_SENDACK 12
#define Prep_WMODE   16
#define Prep_STAGE   32
#define Prep_COLOC   64
#define Prep_FRESH  128

class XrdOucTList;

struct XrdSfsFSctl // SFS_FSCTL_PLUGIN/PLUGIO parameters
{
 const char            *Arg1;      // PLUGIO & PLUGIN
       int              Arg1Len;
       int              Arg2Len;
 const char            *Arg2;      // PLUGIN opaque string
};

struct XrdSfsPrep  // Prepare parameters
{
       char            *reqid;     // Request ID
       char            *notify;    // Notification path or 0
       int              opts;      // Prep_xxx
       XrdOucTList     *paths;     // List of paths
       XrdOucTList     *oinfo;     // 1-to-1 correspondence of opaque info
};

/******************************************************************************/
/*                      A b s t r a c t   C l a s s e s                       */
/******************************************************************************/

class  XrdSfsFile;
class  XrdSfsDirectory;
class  XrdOucTList;
class  XrdSecEntity;

/******************************************************************************/
/*                      X r d S f s F i l e S y s t e m                       */
/******************************************************************************/
  
class XrdSfsFileSystem
{
public:

// The following two methods allocate a directory or file object
//
virtual XrdSfsDirectory *newDir(char *user=0)  = 0;

virtual XrdSfsFile      *newFile(char *user=0) = 0;

// The following are filesystem related methods
//
virtual int            chmod(const char             *Name,
                                   XrdSfsMode        Mode,
                                   XrdOucErrInfo    &out_error,
                             const XrdSecEntity     *client = 0,
                             const char             *opaque = 0) = 0;

virtual int            FSctl(const int               cmd,
                                   XrdSfsFSctl      &args,
                                   XrdOucErrInfo    &out_error,
                             const XrdSecEntity     *client = 0) {return SFS_OK;}

virtual int            fsctl(const int               cmd,
                             const char             *args,
                                   XrdOucErrInfo    &out_error,
                             const XrdSecEntity     *client = 0) = 0;

virtual int            getStats(char *buff, int blen) = 0;

virtual const char    *getVersion() = 0;

virtual int            exists(const char                *fileName,
                                    XrdSfsFileExistence &exists_flag,
                                    XrdOucErrInfo       &out_error,
                              const XrdSecEntity        *client = 0,
                              const char                *opaque = 0) = 0;

virtual int            mkdir(const char             *dirName,
                                   XrdSfsMode         Mode,
                                   XrdOucErrInfo     &out_error,
                             const XrdSecEntity      *client = 0,
                             const char              *opaque = 0) = 0;

virtual int            prepare(      XrdSfsPrep      &pargs,
                                     XrdOucErrInfo   &out_error,
                               const XrdSecEntity    *client = 0) = 0;

virtual int            rem(const char                *path,
                                 XrdOucErrInfo       &out_error,
                           const XrdSecEntity        *client = 0,
                           const char                *opaque = 0) = 0;

virtual int            remdir(const char             *dirName,
                                    XrdOucErrInfo    &out_error,
                              const XrdSecEntity     *client = 0,
                              const char             *opaque = 0) = 0;

virtual int            rename(const char             *oldFileName,
                              const char             *newFileName,
                                    XrdOucErrInfo    &out_error,
                              const XrdSecEntity     *client = 0,
                              const char             *opaqueO = 0,
                              const char             *opaqueN = 0) = 0;

virtual int            stat(const char               *Name,
                                  struct stat        *buf,
                                  XrdOucErrInfo      &out_error,
                            const XrdSecEntity       *client = 0,
                            const char               *opaque = 0) = 0;

virtual int            stat(const char               *Name,
                                  mode_t             &mode,
                                  XrdOucErrInfo      &out_error,
                            const XrdSecEntity       *client = 0,
                            const char               *opaque = 0) = 0;

virtual int            truncate(const char             *Name,
                                      XrdSfsFileOffset fileOffset,
                                      XrdOucErrInfo    &out_error,
                                const XrdSecEntity     *client = 0,
                                const char             *opaque = 0) = 0;

                       XrdSfsFileSystem() {}
virtual               ~XrdSfsFileSystem() {}

protected:
};

/******************************************************************************/
/*              F i l e   S y s t e m   I n s t a n t i a t o r               */
/******************************************************************************/

/* When building a shared library plugin, the following "C" entry point must
   exist in the library:

   extern "C"
         {XrdSfsFileSystem *XrdSfsGetFileSystem(XrdSfsFileSystem *nativeFS,
                                                XrdSysLogger     *Logger,
                                                const char       *configFn);
         }

   This entry is called to get an instance of the file system. Return 0 if upon
   failure to properly create such an object. For statically linked file systems
   the non-extern C XrdSfsGetDefaultFileSystem() is used instead.
*/

/******************************************************************************/
/*                            X r d S f s F i l e                             */
/******************************************************************************/

class XrdSfsAio;
  
class XrdSfsFile
{
public:
        XrdOucErrInfo  error;

virtual int            open(const char                *fileName,
                                  XrdSfsFileOpenMode   openMode,
                                  mode_t               createMode,
                            const XrdSecEntity        *client = 0,
                            const char                *opaque = 0) = 0;

virtual int            close() = 0;

virtual int            fctl(const int               cmd,
                            const char             *args,
                                  XrdOucErrInfo    &out_error) = 0;

virtual const char    *FName() = 0;

virtual int            getMmap(void **Addr, off_t &Size) = 0;

virtual int            read(XrdSfsFileOffset   fileOffset,
                            XrdSfsXferSize     preread_sz) = 0;

virtual XrdSfsXferSize read(XrdSfsFileOffset   fileOffset,
                            char              *buffer,
                            XrdSfsXferSize     buffer_size) = 0;

virtual int            read(XrdSfsAio *aioparm) = 0;

virtual XrdSfsXferSize write(XrdSfsFileOffset  fileOffset,
                             const char       *buffer,
                             XrdSfsXferSize    buffer_size) = 0;

virtual int            write(XrdSfsAio *aioparm) = 0;

virtual int            stat(struct stat *buf) = 0;

virtual int            sync() = 0;

virtual int            sync(XrdSfsAio *aiop) = 0;

virtual int            truncate(XrdSfsFileOffset fileOffset) = 0;

virtual int            getCXinfo(char cxtype[4], int &cxrsz) = 0;

                       XrdSfsFile(const char *user=0) {error.setErrUser(user);}
virtual               ~XrdSfsFile() {}

}; // class XrdSfsFile

/******************************************************************************/
/*                       X r d S f s D i r e c t o r y                        */
/******************************************************************************/
  
class XrdSfsDirectory
{
public:
        XrdOucErrInfo error;

virtual int         open(const char              *dirName,
                         const XrdSecEntity      *client = 0,
                         const char              *opaque = 0) = 0;

virtual const char *nextEntry() = 0;

virtual int         close() = 0;

virtual const char *FName() = 0;

                    XrdSfsDirectory(const char *user=0) {error.setErrUser(user);}
virtual            ~XrdSfsDirectory() {}

}; // class XrdSfsDirectory
#endif
