/**C*
 *
 * Vaisala software source code file
 *
 * Copyright (c) Vaisala Oyj 2003, 2005, 2008, 2011, 2012.
 * All rights reserved.
 *
 **C*/

/** @file
 *
 * Time Series Archive Library 
 *
 * $URL: https://subversion.vaisala.com/svn/repos/sigmet/wr_iris_rda/branches/release8.13.5/rda/ts/archlib/tsarchive_lib.h $
 *
 * $Id: tsarchive_lib.h 28576 2012-10-16 20:39:30Z jho $
 *
 */

#ifndef SIGMET_TSARCHIVE_LIB_H
#define SIGMET_TSARCHIVE_LIB_H 1

/* Messages supported within the driver.
 */
#define TSARCHLIB_BAD_INDEX        (TSARCHLIB_FACILITY + 1)
#define TSARCHLIB_CLIENT_CHANGED   (TSARCHLIB_FACILITY + 2)
#define TSARCHLIB_CLIENT_INVALID   (TSARCHLIB_FACILITY + 4)
#define TSARCHLIB_STARTFIRST       (TSARCHLIB_FACILITY + 6)
#define TSARCHLIB_SETUP_CHANGED    (TSARCHLIB_FACILITY + 8)
#define TSARCHLIB_SETUP_FILE       (TSARCHLIB_FACILITY + 10)
#define TSARCHLIB_TWO_EXECUTIVE    (TSARCHLIB_FACILITY + 14)
#define TSARCHLIB_TWO_WATCHDOG     (TSARCHLIB_FACILITY + 15)


/* ***************************
 * *                         *
 * *  TS Archive Structures  *
 * *    and Definitions      *
 * *                         *
 * ***************************
 */

/* Filter used to define what files are supposed to be processed */
struct tsarchlib_filter
{
    char sSiteName16[20];   /* * for don't care */
    char sTaskName[16];     /* * for don't care */
    int  iYear;             /* -1 for don't care */
    int  iMonth;            /* -1 for don't care */
    int  iDay;              /* -1 for don't care */
    int  iStartTime;        /* Time span, -1 for don't care */
    int  iEndTime;
    int  iMaxListSize;      /* Maximum number of files to list */
};

/* The number of pre canned directories available */
#define TSARCH_DIRECTORY_COUNT (8)
struct tsarchlib_setup
{
    char  sVersion[8];
    UINT1 lPlaybackRepeat;    /* repeat data when playing back */
    char  ipad9x1[1];
#define TSARCH_PB_VERSION_MAX (99)
    SINT2 iPlaybackVersion;   /* Playback version number */
    FLT4  fPlaybackSpeed;     /* Playback speed, 1=original speed */
    FLT4  fPlaybackPause;     /* Playback loop pause in seconds */
    SINT4 iInventorySize;
    char  sDirectory[DIRECTORY_SIZE];
    char  sDirectoryList[TSARCH_DIRECTORY_COUNT][DIRECTORY_SIZE];

};

#define TSARCH_FILENAME_SIZE (68)  /* Should be a multiple of 4 */
struct one_ts_file
{
    SINT4 ibytes;                           /*Size in bytes*/
    UINT2 iFlags;                           /*File Status*/
#define TSARCH_OTF_DELETE    (0x0001)      /* Delete this file */
#define TSARCH_OTF_PLAYBACK  (0x0002)      /* Playback this file */
#define TSARCH_OTF_NOT_TS    (0x0004)      /* File is not TS */
#define TSARCH_OTF_LONG_NAME (0x0008)      /* Filename is to long */
#define TSARCH_OTF_TITLE     (0x0010)      /* File is title file */
#define TSARCH_OTF_ACTIVE    (0x0020)      /* File is "Active" */
    SINT2 iMaxRange;                        /* Max range in km */
    UINT2 iSweepNumber;
    char  sSiteName[17];                    /* Null term. */
    char  sTaskName[17];                    /* Null term. */
    struct ymds_time ing_time;              /* Data time */
    char  sPolarization[4];                 /* Polarization, null term */
    char sFileName[TSARCH_FILENAME_SIZE];   /*File name on disk, zero term */
};

#define TSARCH_TITLE_SIZE (64)
struct tsarchlib_dirinfo
{
    char sDirectory[DIRECTORY_SIZE];     /* Ignore if CHANGING set */

    int  iStateFlags;
#define TSARCH_DIR_MISSING    (0x001)   /* Directory is missing */
#define TSARCH_DIR_BUSY       (0x008)   /* Mount or init in progress */
#define TSARCH_DIR_ROOT_FS    (0x010)   /* Directory is on the root filesystem */
#define TSARCH_DIR_NOT_OWNER  (0x020)   /* Directory owner is not operator */
#define TSARCH_DIR_CHANGING   (0x040)   /* Directory is changing */
#define TSARCH_DIR_READ_ONLY  (0x080)   /* Directory is read only */
    int  iTotalMBytes;              /* Total space on partition in MB */
    int  iFreeMBytes;               /* Free space on partition in MB */
    int  iUsedMBytes;               /* Used space on partition in MB, calc from total&Free */
};

void tsarch_lib_nls_init(void);
#define TSARCH_LIB_INIT tsarch_lib_nls_init()

#define TSARCH_SITE_COUNT (8)  /* Must be a multiple of 4 */
#define TSARCH_TASK_COUNT (16)  /* Must be a multiple of 4 */
struct tsarchlib_name_list
{
    char  sName[17]; /* List of all sites found in the inventory */
};

struct tsarchlib_inventory_header
{
    UINT1 lValid;                   // Non-zero if information is valid
    UINT1 lPartial;                 // Non-zero if Inventory is not complete
    UINT1 lDelete;                  // File is flagged for delete
    UINT1 lNonTS;                   // Inventory contains non-time series files
    char sTitle[TSARCH_TITLE_SIZE]; // Title of directory, blank if none

    struct linear_list_header lhead;// List header
    struct kilo_count num_bytes;    // # bytes for all products
    struct tsarchlib_name_list SiteList[TSARCH_SITE_COUNT];
    struct tsarchlib_name_list TaskList[TSARCH_TASK_COUNT];

    UINT4 iChangedBTime;            // Time of the last change
    UINT4 iActiveBTime;             // Time of the last change to the active file only
    UINT4 iDfBTime;                 // Time of the last df command
    SINT4 iActiveFileIndex2;        // Index2 of the last active file, -1 if none
};
/* Results of filter listing */
struct tsarchlib_results
{
    UINT4 lPartial;              /* List was clipped by the maximum size */
    struct kilo_count Count;     /* Number of bytes found in the list */
};


/* Semaphore related definitions */
#define TSARCH_SEMAPHORE_NUM  (4)
#define TSARCH_EF_NUM         (0)

/* Locks must be done in numerical order, lowest first */
/* Lock shared memory holding setup information */
#define TSARCH_SETUP_SEM      (LIBS_TSARCHIVE_CLUSTER + 0)
/* Lock when making significant state transitions. */
#define TSARCH_ACTION_SEM     (LIBS_TSARCHIVE_CLUSTER + 1)
/* Lock the disk inventory */
#define TSARCH_INVENTORY_SEM  (LIBS_TSARCHIVE_CLUSTER + 2)
/* Lock the message list */
#define TSARCH_MESSAGE_SEM    (LIBS_TSARCHIVE_CLUSTER + 3)

/* Most attempts to change this or to read this require locking the
 * TSARCHIVE_ACTION_SEM.  It is OK for the executive to read without
 * locking to see if the command has changed from the current mode.
 */
#define TSARCH_ACTION_STATUS_SIZE (32)
struct tsarchlib_action
{
    /* The executive will attempt to obey the command ASAP.  In the case
     * of INIT or MOUNT, it will automatically switch to STOP mode when
     * it is finised.
     * In the case of RECORD or PLAYBACK, it will stay in that mode until
     * the user requests a different mode.
     */

    /* Some state transitions are not allowed:
     *           ------------------ New command ---------------------
     * Old Mode    Stop    Record  Playback   Init    Mount    Exit
     * ---------+--------+--------+--------+--------+--------+-------+
     * Stop     |   OK   |   OK   |   OK   |   OK   |   OK   |  OK
     * Record   |   OK   |   OK   |   OK   |   No   |   No   |  OK
     * Playback |   OK   |   OK   |   OK   |   No   |   No   |  OK
     * Init     |   OK   |   No   |   No   |   No   |   No   |  OK
     * Mount    |   OK   |   No   |   No   |   No   |   No   |  OK
     */

#define TSARCH_MODE_STOP     (0)  /* Stopped */
#define TSARCH_MODE_RECORD   (1)  /* Record data to disk */
#define TSARCH_MODE_PLAYBACK (2)  /* Playback data from disk */
#define TSARCH_MODE_INIT     (3)  /* Initialize a directory */
#define TSARCH_MODE_MOUNT    (4)  /* Mount a new directory */
#define TSARCH_MODE_EXIT     (5)  /* Time to exit */
    UINT4 iCommand;     /* Command requested by the user */
    UINT4 iMode;        /* Mode that the executive is in, set by exec only */
    char  sMountDirectory[DIRECTORY_SIZE];    /* Directory to mount/init */
    char  sInitTitle[TSARCH_TITLE_SIZE];      /* Title to init to */
    char  sStatus[TSARCH_ACTION_STATUS_SIZE]; /* Action status string */
};

/* ------------------------------
 * The information structure itself.
 */
struct tsarchlib_pinfo
{
    UINT4 iPid;
};


struct tsarchlib_state
{
    struct tsarchlib_action Action;

    UINT2 lShuttingDown ;               /* Driver attempting to shutdown */

    struct tsarchlib_pinfo Executive;

    /* Directory state related values */
    int  iStateFlags;
    int  iTotalMBytes;                  /* Total space on partition in MB */
    int  iFreeMBytes;                   /* Free space on partition in MB */
    //  char sTitle[TSARCH_TITLE_SIZE];     /* Title of directory */

};


#define TSARCH_MESSAGE_TEXT_SIZE (80)
struct tsarchlib_message
{
    UINT4 iIndex;
    char sText[TSARCH_MESSAGE_TEXT_SIZE];
};

#define TSARCH_MESSAGE_COUNT (100)
struct tsarchlib_message_list
{
    struct tsarchlib_message  List[TSARCH_MESSAGE_COUNT];
    SINT4 iCount;
};

/* ------------------------------
 * The actual shared global antenna structure.
 */
struct tsarchlib_info
{
    /* Current information for the tsarchlib
     */
    struct tsarchlib_state State;

    /* Setup information for the tsarchlib
     */
    struct tsarchlib_setup Setup;

    /* List of errors */
    struct tsarchlib_message_list Messages;
  
} ;
/* The TS archive inventory actually consists of an array of linear list 
 * numbers followed by an array of the one_ts_file structures. 
 * The dimensions are determined from setup questions.
 */
/* 0x186a0==100000 decimal */
#define TSARCH_INVENTORY_MAX    (0x0186a0)  /* Max value for inventory depth */
#define TSARCH_INVENTORY_SEARCH (0x010000)  /* Must be GE half of max */
struct tsarchlib_inventory
{
    UINT4  isize;           /* Full size of the inventory structure  */
    UINT4  iOffsetToOtf;  /* Offset to the array of OTF structures */
    struct tsarchlib_info Info;
    struct tsarchlib_inventory_header InvHead;
    SINT4  iLList[1];
    /* struct one_ts_file file[1]; */
};

/* ********************************************
 * *                                          *
 * * Function Prototypes for Library Routines *
 * *                                          *
 * ********************************************
 */

class TsArchLib
{
public:
    /* Get current action status for screen updates.  
     * Does not need lock.
     */
    void GetAction
        ( struct tsarchlib_action *pAction_a );

    /* Get information about the current active directory.
     * Does ot need a lock.
     */
    void GetDirectory
        ( struct tsarchlib_dirinfo *pDirectory_a );
  
    /* Insert a new error message into the list.
     */
    void InsertMessage
        ( const char *sMessage_a );

    /* UnMap the shared memory, and disconnect this process from the
     * antenna driver.  Use this when you no longer need the antenna
     * driver.  For multi-threaded programs, call this after all threads
     * are closed, for example in the exit handler.
     */
    MESSAGE Close( void );

    /* Look up a file in the inventory */
    SINT4 InventoryFileLookup
        (const struct one_ts_file *pFile_a );

    /* Set the usage numbers about the directory */
    void SetDirectoryUse
        ( void );

    /* Convert ts index1 into pointer to the file.  It will return
     * a null pointer if the index is out of the valid used range
     * of the list.  Note that index1's are not constant if the inventory
     * is not locked.  Index1's cannot be stored after unlocking
     * the inventory.  Output is cast non-volatile because of the
     * lock.
     */
    struct one_ts_file *pTsFileFromIndex1
        ( SINT4 index1_a ); /* Origin 1 index1 */

    /* Get the playback repeat flag */
    UINT1 lGetPlaybackRepeat(void);

    /* Get the playback version number. */
    SINT2 iGetPlaybackVersion(void);
  
    /* Get the playback speed (1.0 means recorded speed) */
    FLT4  fGetPlaybackSpeed(void);
  
    /* Get the playback pause in seconds */
    FLT4  fGetPlaybackPause(void);

    /* Tag a specified list of files */
#define TSARCH_TAG_DELETE    (0)  /* Delete the file */
#define TSARCH_TAG_PLAYBACK  (1)  /* Playback file */
#define TSARCH_TAG_ACTIVE    (2)  /* File is active */
#define TSARCH_TAG_INACTIVE  (3)  /* File is not active */
#define TSARCH_TAG_CLEAR     (9)  /* Erase all tags */
    void TagInventoryList
        ( struct one_ts_file List_a[],  /* List of files to tag */
          UINT4 iCommand_a,             /* Tag command to perform */
          SINT4 iCount_a );             /* Number of entries in the list */

protected:
    TsArchLib(void);    /* Constructor */
    /* ---------------------------------------------------------------
     * ----------------- Open/Close/Powerup Routines -----------------
     * ---------------------------------------------------------------
     */
  
    /* TsArchOpen() initializes internal shared memory for subsequent
     * calls to the library.  Any additional processes needed to
     * run the ts archive are also created by this function. 
     */
  
#define TSARCH_IAM_CLIENT    (0)   /* Normal client, such as a GUI */
#define TSARCH_IAM_EXECUTIVE (1)   /* The executive process */
#define TSARCH_IAM_WATCHDOG  (3)   /* The watchdog process */
  
    MESSAGE Open
        ( int32_t iClientType_a );

    bool GetFirstFlag(void);

    /* Set the action command.  Does not handle mount or init.
     * Locks handled internally. */
    void ActionCommandSet
        ( UINT4 iCommand_a );
  
    /* Save the current state for future powerup */
    MESSAGE SaveState( void);
  
    /* -------------------------------------------------------------
     * --------------------- Message Functions ---------------------
     * -------------------------------------------------------------
     */
    /* Get the index of the last message in the message log */
    UINT4 GetLastMessageIndex
        ( void );
  
    /* Get the specified message text.  Returns NULL if the index
     * is invalid.  Caller must free the pointer.
     */
    char *GetMessageByIndex
        ( UINT4 iIndex_a );

    struct one_ts_file *pTsFileFromIndex2
        ( SINT4 index2_a ); /* Origin 0 index2 */
    SINT4 iTsIndex2FromIndex1
        ( SINT4 index1_a ); /* Origin 1 index1 */

  
    /* Get the pointer to archive inventory file list
     */
    volatile struct one_ts_file *InventoryGetPointer(void);
    
    /* Pointer to global section for the TS Archive Lib to use. */
    volatile struct tsarchlib_inventory *pTsInventory_c ;
    volatile struct tsarchlib_info      *pTsGlobal_c ;

private:
    MESSAGE GlobalInit
        ( const struct tsarchlib_setup *pSetup_a,
          UINT1 *lcreated_a );
    void InitFirst( void );
    MESSAGE ProcessClientType
        (int32_t iClientType_a, uint8_t lCreated_a);
    MESSAGE ForkRequiredProcesses
        (int32_t iClientType_a, bool *did_start_a);
    MESSAGE LoadSetup
        ( volatile struct tsarchlib_setup *pTsSetup_a );
    MESSAGE SaveSetup
        ( volatile const struct tsarchlib_setup *pTsSetup_a );

  
    bool  did_start_daemon;     // We forked the daemon
    bool  lPoweredUp_c;         // This library is opened already
    SINT4 iTsInventorySize_c;
    SINT4 iTsInventoryId_c;

};


class TsArchClient: public TsArchLib
{
private:
  
public:
    MESSAGE Open(void);
    /* -------------------------------------------------------------
     * --------------------- Directory Functions -------------------
     * -------------------------------------------------------------
     */
    /* Set the active directory */
    void SetDirectory
        ( const char *sDirectory_a );
  
    /* Initialize the current active directory.  Note that the specified
     * directory is just a cross check to prevent inits when the directory
     * was just switched.  If the current active directory does not match,
     * it will not init. */
    void InitDirectory
        ( const char *sDirectory_a,
          const char *sTitle_a );   /* Set to this title */
  
    /* Get the current list of possible directories */
    void GetDirectoryList
        ( char pDirectory_a[TSARCH_DIRECTORY_COUNT][DIRECTORY_SIZE] );
  
    /* Set the list of possible directories */
    void SetDirectoryList
        ( const char pDirectory_a[TSARCH_DIRECTORY_COUNT][DIRECTORY_SIZE] );
  
    MESSAGE SaveState(void);

    /* Set the action command.  Does not handle mount or init.
     * Locks handled internally. */
    void ActionCommandSet
        ( UINT4 iCommand_a );

    UINT4  GetLastMessageIndex(void);
    char   *GetMessageByIndex(UINT4 iMsgIdx_a);
    /* -------------------- Inventory Functions --------------------
     */
    UINT4 GetInventoryChangedTime( void );
    UINT4 GetInventoryActiveTime( void );
  
    /* Get the inventory list.  Returns the number of entries found.
     * The list is allocated in the caller's routine, and the
     * filter specifies the maximum number of slots to use.
     */
    SINT4 GetInventoryList
        ( struct tsarchlib_inventory_header *pInvHeader_a,
          const struct tsarchlib_filter *pFilter_a,
          struct tsarchlib_results *pResults_a,
          struct one_ts_file pList_a[] );

    /* Get the active inventory file */
    SINT4 GetInventoryActiveFile
        ( UINT4 *iActiveBTime_a,
          struct one_ts_file *pFile_a );

    /* Tag all files which match the filter, tag options are the same as
     * TagInventoryList minus the ACTIVE options. */
    void TagInventoryFilter
        ( const struct tsarchlib_filter *pFilter_a,
          UINT4 iCommand_a );           /* Tag command to perform */
    /* Set the playback repeat flag */
    void SetPlaybackRepeat(UINT1 lPlaybackRepeat_a);

    /* Set the playback version number */
    void SetPlaybackVersion(SINT2 iPlaybackVersion_a);
    
    /* Set the playback speed (1.0 means recorded speed) */
    void SetPlaybackSpeed(FLT4 fPlaybackSpeed_a);
    
    /* Set the playback pause in seconds */
    void SetPlaybackPause(FLT4 fPlaybackPause_a);
  
};

class TsArchExec: public TsArchLib
{
private:
    SINT4 InventorySiteLookup
        (const char *sSitename_a );
    SINT4 InventorySiteInsert
        (SINT4 iIndex_a,    /* Location to put the new sitename in */
         const char *sSitename_a );
    SINT4 InventoryTaskLookup
        (const char *sName_a );
    SINT4 InventoryTaskInsert
        (SINT4 iIndex_a,    /* Location to put the new sitename in */
         const char *sName_a );

public:

    MESSAGE Open(void);
    MESSAGE Close(void);
    /* Set the action mode.  */
    void SetActionMode
        ( UINT4 iMode_a,
          const char *sStatus_a );   /* The status string */

    /* Set the action command back to STOP after a command has completed.
     * Does not require a lock. */
    void ActionCommandClear
        ( void );
    /* Set the action command to playback */
    void ActionCommandPlayback
        ( void );
    void ActionCommandMount
        ( void );
    void ActionCommandExit
        ( void );

    UINT4 GetActionCommand( void );
    /* Move the new directory into effect. */
    void SwitchDirectoryName
        ( const char* sDirectory_a );   /* New directory name to use */
    /* Set the directory state. */
    void SetDirectoryState
        ( UINT4 iStateFlags_a );   /* New state flags */
    /* Set and clear directory state bits */
    void SetClrDirectoryState
        ( UINT4 iSetBits_a,
          UINT4 iClrBits_a ); 
    /* Set the inventory title */
    void SetInventoryTitle
        ( const char *sTitle_a );
    /* Set the inventory valid flag */
    void SetInventoryValid
        ( UINT1 lValid_a );
    /* Set the inventory partial flag */
    void SetInventoryPartial
        ( UINT1 lPartial_a );
    /* Set the inventory non-TS flag */
    void SetInventoryNonTs
        ( UINT1 lNonTs_a );
    /* Clear the inventory. */
    void ClearInventory(void);
    /* Add a file to the inventory */
    MESSAGE InventoryFileAdd
        (const struct one_ts_file *pFile_a,
         SINT4 *iIndex1_a );
    /* Get the current list of files tagged for playback.  Returns the 
     * number of entries found. The list is allocated in the caller's routine, 
     * and the MaxListSize the maximum number of file to return.  File are
     * in inventory order, the most recent first.
     */
    SINT4 GetInventoryPlayList
        (SINT4  iMaxListSize_a,  // Maximum number of files to show in the list
         struct one_ts_file pList_a[]);

    /* Get just the header of the inventory */
    void GetInventoryHeader
        ( struct tsarchlib_inventory_header *pInvHeader_a );

    /* Add an active file to the inventory */
    MESSAGE InventoryActiveAdd
        (const struct one_ts_file *pFile_a);
    /* Update the size of the active entry. */
    void InventoryActiveUpdateSize
        (SINT4 iSize_a);
    /* Mark the active file as done. */
    void InventoryActiveDone
        (void);

    void EntryFromFileName
        ( struct one_ts_file *pFile_a,
          const char *sFile_a );

};
      
class TsArchWatch: public TsArchLib
{
private:

public:
    MESSAGE Open(void);

    MESSAGE Close(void) ;

    void  SetWatchdogMode( UINT4 iMode_a );

    UINT4 GetActionCommand( void );

    volatile UINT1 *GetInventoryDeletePointer( void );

    MESSAGE InventoryFileDelete
        (SINT4 index1_a,                    /* Index of product, origin 1 */
         UINT4 isem_a );
};

#endif /* #ifndef SIGMET_TSARCHIVE_LIB_H */
