/*
 *    PROJECT:      DVS
 *    SUBSYSTEM:    vl
 *    MODULE:       vl.h
 *
 *    File:         $RCSfile: vl.h,v $
 *    Revision:     $Revision: 1.23 $
 *    Date:         $Date: 1995/05/18 09:43:47 $
 *    Author:       $Author: jeff $
 *    RCS Ident:    $Id: vl.h,v 1.23 1995/05/18 09:43:47 jeff beta $
 *
 *    FUNCTION:
 *
 *      This file contains all the external definitions needed to use
 *       the vl library.
 *
 * Copyright (c) 1994 Division Ltd.
 *
 * All Rights Reserved.
 *
 * This Document may not, in whole or in part, be copied,
 * photocopied, reproduced, translated, or reduced to any
 * electronic medium or machine readable form without prior
 * written consent from Division Ltd.
 */
#ifndef _VL_H
#define _VL_H

#include <stdio.h>

#ifndef _VLTYPES_H
#include <dvs/vltypes.h>
#endif

/*
 * type for return of event info
 */
typedef union  VLEventData           VLEventData;
typedef struct VLInstanceEvent       VLInstanceEvent;

typedef struct VLSignalEvent         VLSignalEvent;
typedef struct VLStreamEvent         VLStreamEvent;
typedef struct VLInstInterestEvent   VLInstInterestEvent;
typedef struct VLElemInterestEvent   VLElemInterestEvent;
typedef struct VLElementConfirmEvent VLElementConfirmEvent;
typedef struct VLElemCreateEvent     VLElemCreateEvent;
typedef struct VLTimeServiceEvent    VLTimeServiceEvent;
typedef struct VLPeerEvent           VLPeerEvent;
typedef struct VLBadEvent            VLBadEvent;


struct VLInstanceEvent{
    ElementHandle handle;
    InstanceNo    ino;
    int32         repCount;
};

struct VLSignalEvent{
    uint32        signal;
};

struct VLStreamEvent {
    void         *buf;
    VLStreamId    id;
    int32         type;
};

struct VLInstInterestEvent{
    InstanceNo    ino;
    uint32        type;
    ActorId       actor;
    EventQ        queue;
};
    
struct VLElemInterestEvent{
    ElementHandle handle;
    uint32        type;
    ActorId       actor;
    EventQ        queue;
};

struct VLElementConfirmEvent{
    ElementHandle reference;
    ElementHandle confirmed;
};

struct VLElemCreateEvent{
    ElementHandle handle;
    uint32        descSize;
};

struct VLTimeServiceEvent{
    VLTime time;
    ActorId who;
};

struct  VLPeerEvent{
    ActorId peer;
};

struct VLBadEvent {
    VLStatus stat;
};

union VLEventData {
    VLInstanceEvent       instanceEvent;
    VLSignalEvent         signalEvent;
    VLStreamEvent         streamEvent;
    VLInstInterestEvent   instInterestEvent;
    VLElemInterestEvent   elemInterestEvent;
    VLElementConfirmEvent elementConfirmEvent;
    VLElemCreateEvent     elemCreateEvent;
    VLTimeServiceEvent    timeServiceEvent;
    VLPeerEvent           peerEvent;
    VLBadEvent            badEvent;
};

/*
 * fundemenatal element handles, always around.
 */
extern const ElementHandle el_char8;
extern const ElementHandle el_int8;
extern const ElementHandle el_uint8;
extern const ElementHandle el_int16;
extern const ElementHandle el_uint16;
extern const ElementHandle el_int32;
extern const ElementHandle el_uint32;
extern const ElementHandle el_float32;
extern const ElementHandle el_float64;

/*
 * get the version
 */
extern void          vlVersion(FILE *fp);

/*
 * Connecting to a  database, finding out name etc.
 */
extern ActorId   VLAttachActor(const char8 *agentName);
extern VLStatus  VLDetachActor(VLExitMode);
extern uint32     VLDomainName(char8 *name, uint32 maxNameLen);
extern AgentId      VLDomainId(void);


/*
 * Creating elements
 */
extern VLStatus VLCreateElement(int32 (*efunc)(void));


/*  how epp generated code defines elements..
 * For error free code..
 *
 * THIS ROUTINE IS FOR USE BY EPP-GENERATED CODE
 *                 ONLY!
 * That is why its name is prefixed with 'vl' not 'VL'.
 */
extern ElementHandle   vlCreateElement(char8 *name,
                                       int32 size,
                                       int32 alignment,
                                       int32 atomic,
                                       int32 dynamic,
                                       int32 subelems, ...);

/*
 * extract an element description into a buffer
 * that could be transmited to a remote data base and 
 * used to recreate the element there. Used by agents
 * to exchange element information.
 */
extern VLStatus      VLExtractElemDesc(ElementHandle h,
                                       ElementDesc *d);


/*
 * take an element description, probably transmitted from a remote
 * machine, and create an element from it. Such an element cannot be
 * properly used on the local database, without a 'vlCreateElement()'
 * being performed, as offset and alignment information (which is machine
 * dependant) is not available here, but the form will be created here
 * with a valid element handle. This will speed up future
 * vlCreateElement(), or ' VLCreateElemFromDesc()' calls at this database.
 *
 *                THIS CREATE IS ASYNCHRONOUS. 
 *
 * If the element creation needs to be further negotiated with a peer
 * database, then a potential for deadlock in the database coms exists.
 * To avoid this, VLCreateElemFromDesc() always returns imediately, with
 * no status. All return info is put onto the event queue for async handling.
 */
extern VLStatus VLPeerElement(ElementDesc *d, EventQ q);

/*
 * Setting the database peer.
 */
extern VLStatus VLSetPeerActor(EventQ q);

/*
 * Arrange to get an event when the peer attatches to the database, 
 * error status if there will be no peer.
 */
extern VLStatus VLGetPeerActor(void);

/*
 * check to see if tha database is a master or not.
 */
extern int VLIsMasterP(void);

/*
 * Define the data format (alignment, endianess etc) of a remote
 * database to this database. Return value is used to identify
 * the source type of remote machines for updates with reformating.
 * returns negative if there is any form of error.
 */
extern VLFormat VLDefineFormat(dpTypeSpec *s);


/*
 * The following calls are needed to find out when a time keeper has
 * connected, and to set up the timekeeper, used on those systems that
 * use a timekeeper. on systems that have a local timer, these calls will
 * always fail.
 */
extern VLStatus VLGetTimeKeeper(void);
extern VLStatus VLSetTimeKeeper(EventQ q);

/*
 * used by a timekeeper to wakeup actors waiting on alarms, on systems
 * without a timekeeper this funcion will still work. returns
 * VL_ERR_BAD_AGENT if the actor id is not recognised.
 */
extern VLStatus VLWakeUpActor(ActorId actor);

/*
 * change the state of an element to confirmed. This may involve a change
 * of element handle , from 'oldh' to 'newh'. To delete an element awaiting
 * confirmation set the 'newh' element handle to 0. Will return
 * VL_ERR_BAD_ELEM if 'oldh' is not waiting for confirmation or is not an
 * element. else returns VL_ERR_OK.
 */
extern VLStatus      VLConfirmElement(ElementHandle oldh, ElementHandle newh);


/*
 * requesting info about other actors interest at this database.
 */
#define   VLRegisterElementInterest()   VLQRegisterElementInterest(0)
#define VLDeRegisterElementInterest() VLQDeRegisterElementInterest(0)

extern VLStatus   (VLRegisterElementInterest)(void);
extern VLStatus (VLDeRegisterElementInterest)(void);
extern VLStatus    VLQRegisterElementInterest(EventQ q);
extern VLStatus  VLQDeRegisterElementInterest(EventQ q);
extern VLStatus      VLRequestElementInterest(EventQ q, ElementHandle h);

#define   VLRegisterInstanceInterest(x)   VLQRegisterInstanceInterest(0,x)
#define VLDeRegisterInstanceInterest(x) VLQDeRegisterInstanceInterest(0,x)

extern VLStatus   (VLRegisterInstanceInterest)(AgentId id);
extern VLStatus (VLDeRegisterInstanceInterest)(AgentId id);
extern VLStatus    VLQRegisterInstanceInterest(EventQ q, AgentId);
extern VLStatus  VLQDeRegisterInstanceInterest(EventQ q, AgentId);


/*
 * Low-level routines  to create/delete/update/extract
 * instances from the database.
 *
 * THESE  ROUTINES SHOULD BE CALLED FROM EPP-GENERATED CODE ONLY
 *
 * Epp will write type-safe access routines for you,
 *
 *                          USE THEM.
 */
#define vlCreateInstance(e,i,d,t,m)             vlQCreateDynamicFormattedInstance(  0,(e),(i),(d),(t),(m),-1, -1 ) 
#define vlCreateDynamicInstance(e,i,d,t,m,c)    vlQCreateDynamicFormattedInstance(  0,(e),(i),(d),(t),(m),-1, (c))
#define vlQCreateInstance(q,e,i,d,t,m)          vlQCreateDynamicFormattedInstance((q),(e),(i),(d),(t),(m),-1, -1 )
#define vlQCreateDynamicInstance(q,e,i,d,t,m,c) vlQCreateDynamicFormattedInstance((q),(e),(i),(d),(t),(m),-1, (c))

extern InstanceNo                 (vlCreateInstance)(ElementHandle elem,
                                                     InstanceNo    ino,
                                                     void         *data,
                                                     VLTime       *vtime,
                                                     VLUpdateMode  mode);
extern InstanceNo                (vlQCreateInstance)(EventQ     qid,
                                                     ElementHandle elem,
                                                     InstanceNo    ino,
                                                     void         *data,
                                                     VLTime       *vtime,
                                                     VLUpdateMode  mode);

extern InstanceNo          (vlCreateDynamicInstance)(ElementHandle elem,
                                                     InstanceNo    ino,
                                                     void         *data,
                                                     VLTime       *vtime,
                                                     VLUpdateMode  mode,
                                                     int32        count);

extern InstanceNo         (vlQCreateDynamicInstance)(EventQ        qid,
                                                     ElementHandle elem,
                                                     InstanceNo    ino,
                                                     void         *data,
                                                     VLTime       *vtime,
                                                     VLUpdateMode  mode,
                                                     int32        count);

extern InstanceNo  vlQCreateDynamicFormattedInstance(EventQ        qid,
                                                     ElementHandle elem,
                                                     InstanceNo    ino,
                                                     void         *data,
                                                     VLTime       *vtime,
                                                     VLUpdateMode  mode,
                                                     VLFormat      format,
                                                     int32        count);

#define vlDeleteInstance(i,m)            vlQDeleteInstance(0,(i),(m))

extern VLStatus          (vlDeleteInstance)(InstanceNo   ino,
                                            VLUpdateMode mode);
extern VLStatus           vlQDeleteInstance(EventQ     qid,
                                            InstanceNo   ino,
                                            VLUpdateMode mode);

extern VLStatus            vlUpdateInstance(InstanceNo   ino,
                                            void        *data,
                                            VLTime      *vtime,
                                            VLUpdateMode mode);

extern VLStatus           vlQUpdateInstance(EventQ     qid,
                                            InstanceNo   ino,
                                            void        *data,
                                            VLTime      *vtime,
                                            VLUpdateMode mode);

extern VLStatus     vlUpdateDynamicInstance(InstanceNo    ino,
                                            void         *data,
                                            VLTime       *vtime,
                                            VLUpdateMode  mode,
                                            int32        count);

extern VLStatus    vlQUpdateDynamicInstance(EventQ        qid,
                                            InstanceNo    ino,
                                            void         *data,
                                            VLTime       *vtime,
                                            VLUpdateMode  mode,
                                            int32        count);

extern VLStatus     vlQUpdateInstanceFormat(EventQ        qid,
                                            VLFormat      format,
                                            InstanceNo    ino,
                                            void         *data,
                                            VLTime       *vtime,
                                            VLUpdateMode  mode,
                                            int32        count);


extern VLStatus           vlExtractInstance(InstanceNo ino,
                                            void *data,
                                            VLTime *vtime);




/*
 * Miscellaneous instance routines
 */
extern ElementHandle      VLInstanceType(InstanceNo ino);
extern uint32             VLInstanceSize(InstanceNo ino, uint32 *icount);
extern int32         VLInstanceOwnership(InstanceNo ino);
extern void           *VLInstanceAddress(InstanceNo ino,
                                         VLStatus    *status, 
                                         VLTime      *time,
                                         VLUpdateMode mode,
                                         uint32       count);
extern VLStatus         VLInstanceUpdate(InstanceNo   ino,
                                         VLTime      *vtime,
                                         VLUpdateMode mode);


/*
 * (de)registering of interest in elements and instances.
 */
#define    VLRegisterElement(e, t)    VLQRegisterElement(0,(e),(t))
#define  VLDeRegisterElement(e, t)  VLQDeRegisterElement(0,(e),(t))
#define   VLRegisterInstance(i, t)   VLQRegisterInstance(0,(i),(t))
#define VLDeRegisterInstance(i, t) VLQDeRegisterInstance(0,(i),(t))

extern VLStatus    (VLRegisterElement)(ElementHandle e, uint32 type);
extern VLStatus  (VLDeRegisterElement)(ElementHandle e, uint32 type);
extern VLStatus   (VLRegisterInstance)(InstanceNo ino,  uint32 type);
extern VLStatus (VLDeRegisterInstance)(InstanceNo ino,  uint32 type);

extern VLStatus    VLQRegisterElement(EventQ q,
                                      ElementHandle e,
                                      uint32 type);
extern VLStatus  VLQDeRegisterElement(EventQ q,
                                      ElementHandle e,
                                      uint32 type);
extern VLStatus   VLQRegisterInstance(EventQ q,
                                      InstanceNo ino,
                                      uint32 type);
extern VLStatus VLQDeRegisterInstance(EventQ q,
                                      InstanceNo ino,
                                      uint32 type);


/*
 * Events, and their queues.
 */
#define VLAwaitEvent(e,w) VLQAwaitEvent((e),NULL,(w))

extern VLAction     (VLAwaitEvent)(VLEventData *ev,
                                   VLWaitMode   wait);
extern VLAction      VLQAwaitEvent(VLEventData *ev,
                                   EventQ      *q,
                                   VLWaitMode   wait);
extern VLAction       VLSnoopEvent(EventQ qid,VLEventData *ev);

extern EventQ      VLNewEventQueue(void);
extern VLStatus VLDeleteEventQueue(EventQ q);
extern VLStatus  VLBlockEventQueue(EventQ q);
extern VLStatus  VLClearEventQueue(EventQ q);


/*
 * signals
 */
extern void   VLSigSet(int32 sig);
extern void VLSigUnset(int32 sig);

/*
 * Stream operations
 */
extern VLStreamId  VLStreamOpen(char8   *name,
                                int32    buflen,
                                void    *buffer,
                                char8   *format ); 
extern VLStatus   VLStreamWrite(VLStreamId  streamId,
                                int32       type,
                                uint32      length,
                                void       *data );
extern VLStatus   VLStreamClose(VLStreamId streamId );

/*
 * Locking and groups
 */
extern VLStatus     VLLock(void);
extern VLStatus   VLUnlock(void);
extern int32  VLLockStatus(void);

extern int32       VLGroup(void);
extern int32     VLUnGroup(void);
extern int32 VLGroupStatus(void);

/*
 * Virtual time and timers
 */
extern VLStatus        VLVirtualTime(VLTime *t);
extern VLStatus VLSetVirtualTimeSkew(VLTime *t);
extern VLStatus VLGetVirtualTimeSkew(VLTime *t);

#define VLAddVtimes(r,a,b)       dpAddVtimes(r,a,b)
#define VLSubVtimes(r,a,b)       dpSubVtimes(r,a,b)

extern void (VLAddVtimes)(VLTime *r, VLTime *a, VLTime *b);
extern void (VLSubVtimes)(VLTime *r, VLTime *a, VLTime *b);

extern VLStatus VLTimer(VLTime *period, VLTimerMode mode);

/*
 * converting status numbers, element handles  to meaningful messages
 */
extern const char *VLErrorString(VLStatus s);
extern const char *VLElementName(ElementHandle h);

#endif /* _VL_H */
