//----------------------------------------------------------------------------
// Pismo Technic Inc. Copyright 2003-2024 Joe Lowe
//
// Permission is granted to any person obtaining a copy of this Software,
// to deal in the Software without restriction, including the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and sell copies of
// the Software.
//
// The above copyright and permission notice must be left intact in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS WITHOUT WARRANTY.
//----------------------------------------------------------------------------
// file name:  fsrformatter.h
// created:    2020.09.04
//----------------------------------------------------------------------------
#ifndef FSRFORMATTER_H
#define FSRFORMATTER_H
#ifdef __cplusplus
#include "fsrformatter.hxx"
#else
#include "fsrapi.h"
#include "ptiobuf.h"
PT_C_ASSERT_STRUCT_PACKING(FSRSERVER_H);

/*interface FsrFile*/ typedef struct FsrFile_vtbl_t FsrFile_vtbl_t, * FsrFile;

typedef struct FsrOpenAttribs FsrOpenAttribs; struct FsrOpenAttribs
{
   PT_INT8 accessLevel;
   PT_UINT8 controlFlags;
   PT_UINT32 touch;
   PT_UINT64 sequence;
   FsrAttribs attribs;
};

enum {
   fsrOpTypeOpen = 3,
   fsrOpTypeReplace = 4,
   fsrOpTypeMove = 5,
   fsrOpTypeMoveReplace = 6,
   fsrOpTypeDelete = 7,
   fsrOpTypeFlush = 9,
   fsrOpTypeList = 10,
   fsrOpTypeRead = 12,
   fsrOpTypeWrite = 13,
   fsrOpTypeSetSize = 14,
   fsrOpTypeCapacity = 15,
   fsrOpTypeFlushMedia = 16,
   fsrOpTypeControl = 17,
   fsrOpTypeMediaInfo = 18,
   fsrOpTypeAccess = 19,
   fsrOpTypeReadXattr = 20,
   fsrOpTypeWriteXattr = 21,
   fsrOpTypeReadTouchMap = 23,
};

typedef struct FsrOp FsrOp; struct FsrOp
{
   void (PT_CCALL*complete)( FsrOp*, int perr);
   void* context;
   pin_i* cancelPin;
};

struct FsrControlOpResult
{
   PT_SIZE_T outputSize;
};
typedef struct FsrControlOp FsrControlOp; struct FsrControlOp
{
      union { FsrOp base; struct {
   void (PT_CCALL*complete)( FsrControlOp*, int perr);
   void* context;
   pin_i* cancelPin;
      };};
   struct FsrControlOpResult result;
      //
   PT_INT8 accessLevel;
   PT_UINT8 controlScope;
   PT_SZC_T interfaceId;
   int controlCode;
   const void* input;
   PT_SIZE_T inputSize;
   void* output;
   PT_SIZE_T maxOutputSize;
};

struct FsrMediaInfoOpResult
{
   PT_UUID mediaUuid;
   PT_UINT64 mediaId64;
   PT_UINT32 mediaId32;
   PT_UINT8 mediaFlags;
   PT_INT64 createTime;
   PT_SZC_T mediaLabel;
};
typedef struct FsrMediaInfoOp FsrMediaInfoOp; struct FsrMediaInfoOp
{
      union { FsrOp base; struct {
   void (PT_CCALL*complete)( FsrMediaInfoOp*, int perr);
   void* context;
   pin_i* cancelPin;
      };};
   struct FsrMediaInfoOpResult result;
      //
};

struct FsrCapacityOpResult
{
   PT_UINT64 totalCapacity;
   PT_UINT64 availableCapacity;
};
typedef struct FsrCapacityOp FsrCapacityOp; struct FsrCapacityOp
{
      union { FsrOp base; struct {
   void (PT_CCALL*complete)( FsrCapacityOp*, int perr);
   void* context;
   pin_i* cancelPin;
      };};
   struct FsrCapacityOpResult result;
      //
};

struct FsrFlushMediaOpResult
{
   int msecFlushDelay;
};
typedef struct FsrFlushMediaOp FsrFlushMediaOp; struct FsrFlushMediaOp
{
      union { FsrOp base; struct {
   void (PT_CCALL*complete)( FsrFlushMediaOp*, int perr);
   void* context;
   pin_i* cancelPin;
      };};
   struct FsrFlushMediaOpResult result;
      //
};

struct FsrListOpResult
{
   PT_BOOL noMore;
};
typedef struct FsrListOp FsrListOp; struct FsrListOp
{
      union { FsrOp base; struct {
   void (PT_CCALL*complete)( FsrListOp*, int perr);
   void* context;
   pin_i* cancelPin;
      };};
   struct FsrListOpResult result;
      //
PT_BOOL /*ok*/ (PT_CCALL* add)( FsrListOp* op, const FsrAttribs* attribs, PT_SZC_T name);
};

struct FsrFlushOpResult
{
   FsrOpenAttribs openAttribs;
};
typedef struct FsrFlushOp FsrFlushOp; struct FsrFlushOp
{
      union { FsrOp base; struct {
   void (PT_CCALL*complete)( FsrFlushOp*, int perr);
   void* context;
   pin_i* cancelPin;
      };};
   struct FsrFlushOpResult result;
      //
   PT_UINT8 flushFlags;
   PT_UINT8 fileFlags;
   PT_UINT8 color;
   PT_INT64 createTime;
   PT_INT64 accessTime;
   PT_INT64 writeTime;
   PT_INT64 changeTime;
   const void* linkData;
   PT_SIZE_T linkDataSize;
};

struct FsrOpenOpResult
{
   FsrFile* existedFile;
   FsrOpenAttribs openAttribs;
   PT_INT64 parentFileId;
   PT_SZC_T endName;
   PT_SIZE_T linkNamePartCount;
   const void* linkData;
   PT_SIZE_T linkDataSize;
};
typedef struct FsrOpenOp FsrOpenOp; struct FsrOpenOp
{
      union { FsrOp base; struct {
   void (PT_CCALL*complete)( FsrOpenOp*, int perr);
   void* context;
   pin_i* cancelPin;
      };};
   struct FsrOpenOpResult result;
      //
   PT_SZC_T* nameParts;
   PT_SIZE_T namePartCount;
   FsrFile* newCreatedFile;
   PT_INT8 createFileType;
   PT_UINT8 createFileFlags;
   PT_INT64 writeTime;
   PT_INT8 existingAccessLevel;
};

struct FsrReplaceOpResult
{
   FsrOpenAttribs openAttribs;
};
typedef struct FsrReplaceOp FsrReplaceOp; struct FsrReplaceOp
{
      union { FsrOp base; struct {
   void (PT_CCALL*complete)( FsrReplaceOp*, int perr);
   void* context;
   pin_i* cancelPin;
      };};
   struct FsrReplaceOpResult result;
      //
   FsrFile* newCreatedFile;
   PT_INT64 targetParentFileId;
   PT_SZC_T targetEndName;
   PT_UINT8 createFileFlags;
   PT_INT64 writeTime;
};

struct FsrAccessOpResult
{
   FsrOpenAttribs openAttribs;
};
typedef struct FsrAccessOp FsrAccessOp; struct FsrAccessOp
{
      union { FsrOp base; struct {
   void (PT_CCALL*complete)( FsrAccessOp*, int perr);
   void* context;
   pin_i* cancelPin;
      };};
   struct FsrAccessOpResult result;
      //
   PT_INT8 accessLevel;
};

struct FsrMoveOpResult
{
   FsrFile* targetExistedFile;
   FsrOpenAttribs openAttribs;
   PT_INT64 parentFileId;
   PT_SZC_T endName;
   PT_SIZE_T linkNamePartCount;
   const void* linkData;
   PT_SIZE_T linkDataSize;
};
typedef struct FsrMoveOp FsrMoveOp; struct FsrMoveOp
{
      union { FsrOp base; struct {
   void (PT_CCALL*complete)( FsrMoveOp*, int perr);
   void* context;
   pin_i* cancelPin;
      };};
   struct FsrMoveOpResult result;
      //
   PT_INT64 sourceParentFileId;
   PT_SZC_T sourceEndName;
   PT_SZC_T* targetNameParts;
   PT_SIZE_T targetNamePartCount;
   PT_BOOL deleteSource;
   PT_INT64 writeTime;
   PT_INT8 existingAccessLevel;
};

typedef struct FsrMoveReplaceOp FsrMoveReplaceOp; struct FsrMoveReplaceOp
{
      union { FsrOp base; struct {
   void (PT_CCALL*complete)( FsrMoveReplaceOp*, int perr);
   void* context;
   pin_i* cancelPin;
      };};
   PT_INT64 sourceParentFileId;
   PT_SZC_T sourceEndName;
   FsrFile* targetFile;
   PT_INT64 targetParentFileId;
   PT_SZC_T targetEndName;
   PT_BOOL deleteSource;
   PT_INT64 writeTime;
};

typedef struct FsrDeleteOp FsrDeleteOp; struct FsrDeleteOp
{
      union { FsrOp base; struct {
   void (PT_CCALL*complete)( FsrDeleteOp*, int perr);
   void* context;
   pin_i* cancelPin;
      };};
   PT_INT64 parentFileId;
   PT_SZC_T endName;
   PT_INT64 writeTime;
};

struct FsrReadOpResult
{
   PT_SIZE_T actualSize;
};
typedef struct FsrReadOp FsrReadOp; struct FsrReadOp
{
      union { FsrOp base; struct {
   void (PT_CCALL*complete)( FsrReadOp*, int perr);
   void* context;
   pin_i* cancelPin;
      };};
   struct FsrReadOpResult result;
      //
   PT_UINT64 fileOffset;
   pt_iobufv_t* buf;
   PT_SIZE_T bufOff;
   PT_BOOL bufUnstable;
   PT_SIZE_T requestedSize;
};

struct FsrWriteOpResult
{
   PT_SIZE_T actualSize;
};
typedef struct FsrWriteOp FsrWriteOp; struct FsrWriteOp
{
      union { FsrOp base; struct {
   void (PT_CCALL*complete)( FsrWriteOp*, int perr);
   void* context;
   pin_i* cancelPin;
      };};
   struct FsrWriteOpResult result;
      //
   PT_UINT64 fileOffset;
   pt_iobufv_t* buf;
   PT_SIZE_T bufOff;
   PT_BOOL bufUnstable;
   PT_SIZE_T requestedSize;
};

typedef struct FsrSetSizeOp FsrSetSizeOp; struct FsrSetSizeOp
{
      union { FsrOp base; struct {
   void (PT_CCALL*complete)( FsrSetSizeOp*, int perr);
   void* context;
   pin_i* cancelPin;
      };};
   PT_UINT64 fileSize;
};

struct FsrReadXattrOpResult
{
   PT_SIZE_T xattrSize;
   PT_SIZE_T actualSize;
};
typedef struct FsrReadXattrOp FsrReadXattrOp; struct FsrReadXattrOp
{
      union { FsrOp base; struct {
   void (PT_CCALL*complete)( FsrReadXattrOp*, int perr);
   void* context;
   pin_i* cancelPin;
      };};
   struct FsrReadXattrOpResult result;
      //
   PT_SZC_T name;
   PT_UINT32 offset;
   pt_iobufv_t* buf;
   PT_SIZE_T bufOff;
   PT_BOOL bufUnstable;
   PT_SIZE_T requestedSize;
};

struct FsrWriteXattrOpResult
{
   PT_SIZE_T actualSize;
};
typedef struct FsrWriteXattrOp FsrWriteXattrOp; struct FsrWriteXattrOp
{
      union { FsrOp base; struct {
   void (PT_CCALL*complete)( FsrWriteXattrOp*, int perr);
   void* context;
   pin_i* cancelPin;
      };};
   struct FsrWriteXattrOpResult result;
      //
   PT_SZC_T name;
   PT_SIZE_T xattrSize;
   PT_SIZE_T offset;
   pt_iobufv_t* buf;
   PT_SIZE_T bufOff;
   PT_BOOL bufUnstable;
   PT_SIZE_T requestedSize;
};

typedef struct FsrReadTouchMapOp FsrReadTouchMapOp; struct FsrReadTouchMapOp
{
      union { FsrOp base; struct {
   void (PT_CCALL*complete)( FsrReadTouchMapOp*, int perr);
   void* context;
   pin_i* cancelPin;
      };};
   pt_iobufv_t* buf;
};

/*interface FsrList*/ typedef struct FsrList_vtbl_t FsrList_vtbl_t, * FsrList; struct FsrList_vtbl_t
{
   void (PT_CCALL* DynaCast)( FsrList*, void* v, PT_SZC_T typeId);
   void (PT_CCALL* Release)( FsrList*);
   void (PT_CCALL* List)( FsrList*, FsrListOp* op, void* mem);
};

/*interface FsrFile*/ struct FsrFile_vtbl_t
{
   void (PT_CCALL* DynaCast)( FsrFile*, void* v, PT_SZC_T typeId);
   void (PT_CCALL* Release)( FsrFile*);
   FsrList* /*list*/ (PT_CCALL* ListFactory)( FsrFile*);
   void (PT_CCALL* Replace)( FsrFile*, FsrReplaceOp* op, void* mem);
   void (PT_CCALL* Move)( FsrFile*, FsrMoveOp* op, void* mem);
   void (PT_CCALL* MoveReplace)( FsrFile*, FsrMoveReplaceOp* op, void* mem);
   void (PT_CCALL* Delete)( FsrFile*, FsrDeleteOp* op, void* mem);
   void (PT_CCALL* Access)( FsrFile*, FsrAccessOp* op, void* mem);
   void (PT_CCALL* Flush)( FsrFile*, FsrFlushOp* op, void* mem);
   void (PT_CCALL* Control)( FsrFile*, FsrControlOp* op, void* mem);
   void (PT_CCALL* MediaInfo)( FsrFile*, FsrMediaInfoOp* op, void* mem);
   void (PT_CCALL* Capacity)( FsrFile*, FsrCapacityOp* op, void* mem);
   void (PT_CCALL* Read)( FsrFile*, FsrReadOp* op, void* mem);
   void (PT_CCALL* Write)( FsrFile*, FsrWriteOp* op, void* mem);
   void (PT_CCALL* SetSize)( FsrFile*, FsrSetSizeOp* op, void* mem);
   void (PT_CCALL* ReadXattr)( FsrFile*, FsrReadXattrOp* op, void* mem);
   void (PT_CCALL* WriteXattr)( FsrFile*, FsrWriteXattrOp* op, void* mem);
};

typedef struct FsrFormatterWork FsrFormatterWork; struct FsrFormatterWork
{
   void (PT_CCALL*handler)( FsrFormatterWork*);
   FsrFormatterWork* next;
};

/*interface FsrFormatterOwner*/ typedef struct FsrFormatterOwner_vtbl_t FsrFormatterOwner_vtbl_t, * FsrFormatterOwner; struct FsrFormatterOwner_vtbl_t
{
   void (PT_CCALL* Retain)( FsrFormatterOwner*);
   void (PT_CCALL* Release)( FsrFormatterOwner*);
   void (PT_CCALL* Cancel)( FsrFormatterOwner*);
   void (PT_CCALL* QueueWork)( FsrFormatterOwner*, FsrFormatterWork* work);
};

typedef struct FsrFormatterConfig FsrFormatterConfig; struct FsrFormatterConfig
{
   FsrFormatterOwner* owner;
   PT_SIZE_T fileExtensionSize;
   PT_SIZE_T listExtensionSize;
   PT_SIZE_T touchMapSize;
   PT_SIZE_T maxIoSize;
   PT_SIZE_T dataAlign;
   PT_SIZE_T reserved2[2];
   PT_SIZE_T opContextSize[32];
};

/*interface FsrFormatter*/ struct FsrFormatter_vtbl_t
{
   void (PT_CCALL* DynaCast)( FsrFormatter*, void* v, PT_SZC_T typeId);
   void (PT_CCALL* Release)( FsrFormatter*);
   void (PT_CCALL* Cancel)( FsrFormatter*);
   void (PT_CCALL* Configure)( FsrFormatter*, FsrFormatterConfig* config);
   int /*perr*/ (PT_CCALL* FileFactory)( FsrFormatter*, FsrFile** file);
   void (PT_CCALL* Control)( FsrFormatter*, FsrControlOp* op, void* mem);
   void (PT_CCALL* MediaInfo)( FsrFormatter*, FsrMediaInfoOp* op, void* mem);
   void (PT_CCALL* Capacity)( FsrFormatter*, FsrCapacityOp* op, void* mem);
   void (PT_CCALL* FlushMedia)( FsrFormatter*, FsrFlushMediaOp* op, void* mem);
   void (PT_CCALL* ReadTouchMap)( FsrFormatter*, FsrReadTouchMapOp* op, void* mem);
   void (PT_CCALL* Open)( FsrFormatter*, FsrOpenOp* op, void* mem);
};


#define FsrTouchMapFileName ".$touch_map_v1"
   // Larger touch maps reduce collisions so namespace caching
   // on client is more effective. Smaller touch maps reduce
   // latency and bandwidth overhead when clients read touch map.
PT_STATIC_CONST( PT_SIZE_T, FsrTouchMapMinSize,   0x1000);
PT_STATIC_CONST( PT_SIZE_T, FsrTouchMapDefaultSize,  0x10000);
PT_STATIC_CONST( PT_SIZE_T, FsrTouchMapMaxSize, 0x100000);
   // File id hash function based on Bob Jenkins lookup3.c,
   // for use in converting file id to touch map index.
#ifdef BITOPS_H
#define FSR_ROL_(v,c) bits_rol(v,c)
#else
#define FSR_ROL_(v,c) (((v)<<(c))|((v)>>(32U-(c))))
#endif
PT_INLINE unsigned FsrTouchMapIndex( PT_INT64 fileId, PT_SIZE_T mapMask)
{
   unsigned a = PT_SCAST( unsigned, fileId & 0xFFFFFFFFu);
   unsigned b = PT_SCAST( unsigned, PT_SCAST( PT_UINT64, fileId) >> 32);
   unsigned c = 0;
   c ^= b; c -= FSR_ROL_( b, 14);
   a ^= c; a -= FSR_ROL_( c, 11);
   b ^= a; b -= FSR_ROL_( a, 25);
   c ^= b; c -= FSR_ROL_( b, 16);
   a ^= c; a -= FSR_ROL_( c, 4);
   b ^= a; b -= FSR_ROL_( a, 14);
   c ^= b; c -= FSR_ROL_( b, 24);
   return c & PT_SCAST( unsigned, mapMask);
}
#undef FSR_ROL_

/*interface FsrFlowMonitor*/ struct FsrFlowMonitor_vtbl_t
{
   void (PT_CCALL* FlowRecvStart)( FsrFlowMonitor*);
   void (PT_CCALL* FlowRecvComplete)( FsrFlowMonitor*);
   void (PT_CCALL* FlowSendStart)( FsrFlowMonitor*);
   void (PT_CCALL* FlowSendComplete)( FsrFlowMonitor*);
};

/*interface FsrClient*/ struct FsrClient_vtbl_t
{
   void (PT_CCALL* Retain)( FsrClient*);
   void (PT_CCALL* Release)( FsrClient*);
   void (PT_CCALL* Cancel)( FsrClient*);
   int /*perr*/ (PT_CCALL* Connect)( FsrClient*, malloc_i* ma, pin_i* cancelPin, FsrFormatter** formatter, int* serverVersion, int* volumeFlags, PT_SZ_T* formatterName);
   int /*perr*/ (PT_CCALL* MsgFlushMedia)( FsrClient*, pin_i* cancelPin, PT_BOOL async);
};

/*interface FsrServer*/ struct FsrServer_vtbl_t
{
   void (PT_CCALL* Release)( FsrServer*);
   void (PT_CCALL* Cancel)( FsrServer*);
   int /*err*/ (PT_CCALL* Connect)( FsrServer*, pin_i* cancelPin, int* clientVersion, int* clientFlags, int* clientFileNameType, FsrFormatter* formatter);
   void (PT_CCALL* Serve)( FsrServer*, pin_i* cancelPin, FsrFlowMonitor* flow, FsrFormatter* formatter);
};

enum {
   fsrPolicyFlagRead = 0x00000001,
   fsrPolicyFlagWrite = 0x00000002,
   fsrPolicyFlagCreate = 0x00000004,
   fsrPolicyFlagDelete = 0x00000008,
   fsrPolicyFlagTraverse = 0x00000010,
   fsrPolicyFlagUndelete = 0x00000020,
   fsrPolicyFlagTemp = 0x00000040,
   fsrPolicyFlagTrash = 0x00000080,
   fsrPolicyFlagAuditRead = 0x00000100,
   fsrPolicyFlagAuditWrite = 0x00000200,
   fsrPolicyFlagAuditCreate = 0x00000400,
   fsrPolicyFlagAuditDelete = 0x00000800,
   fsrPolicyFlagReserved9 = 0x00400000,
   fsrPolicyFlagReserved8 = 0x00800000,
   fsrPolicyFlagReserved7 = 0x01000000,
   fsrPolicyFlagReserved6 = 0x02000000,
   fsrPolicyFlagReserved5 = 0x04000000,
   fsrPolicyFlagReserved4 = 0x08000000,
   fsrPolicyFlagReserved3 = 0x10000000,
   fsrPolicyFlagReserved2 = 0x20000000,
   fsrPolicyFlagReserved1 = 0x40000000,
};

#define fsrDeletedFilesFolderName "_Deleted_Files_"

/*interface FsrPolicyFormatterOwner*/ struct FsrPolicyFormatterOwner_vtbl_t
{
   void (PT_CCALL* FsrPolicyFormatterOwner_Retain)( FsrPolicyFormatterOwner*);
   void (PT_CCALL* FsrPolicyFormatterOwner_Release)( FsrPolicyFormatterOwner*);
   PT_INT64 /*inst*/ (PT_CCALL* GetNamePolicyInstance)( FsrPolicyFormatterOwner*);
   int /*flags*/ (PT_CCALL* GetNamePolicy)( FsrPolicyFormatterOwner*, PT_SZC_T* nameParts, PT_SIZE_T namePartCount, int fileType);
   void (PT_CCALL* AuditPolicy)( FsrPolicyFormatterOwner*, int flags, PT_SZC_T* nameParts, PT_SIZE_T namePartCount, int fileType);
};

#endif
#endif
