/*
 * messages.h:
 * This file defines the message types for the
 * trace messages. Also defines the constants for
 * file system operations.
 */

#ifndef __MESSAGES_H
#define __MESSAGES_H


typedef unsigned short msg_len_t; /* length field in trace message */
typedef unsigned short field_len_t; /* length field in argument */


typedef unsigned short field_t;   /* field type */
#define FIELD_LENGTH_MASK (1 << (sizeof(field_t) * 8 - 2))
typedef unsigned short op_t;      /* operation type */

#define AGSOP_BASE		0
/*NFSv2 ops*/
#define AGSOP_NULL		(AGSOP_BASE + 0)
#define AGSOP_GETATTR		(AGSOP_BASE + 1)
#define AGSOP_SETATTR		(AGSOP_BASE + 2)
#define AGSOP_LOOKUP		(AGSOP_BASE + 3)
#define AGSOP_READLINK		(AGSOP_BASE + 4)
#define AGSOP_READ		(AGSOP_BASE + 5)
#define AGSOP_WRITE		(AGSOP_BASE + 6)
#define AGSOP_CREATE		(AGSOP_BASE + 7)
#define AGSOP_REMOVE		(AGSOP_BASE + 8)
#define AGSOP_RENAME		(AGSOP_BASE + 9)
#define AGSOP_LINK		(AGSOP_BASE + 10)
#define AGSOP_SYMLINK		(AGSOP_BASE + 11)
#define AGSOP_MKDIR		(AGSOP_BASE + 12)
#define AGSOP_RMDIR		(AGSOP_BASE + 12)
#define AGSOP_READDIR		(AGSOP_BASE + 13)
#define AGSOP_STATFS		(AGSOP_BASE + 14)
/*NFSv3 ops*/
#define AGSOP_ACCESS		(AGSOP_BASE + 15)
#define AGSOP_MKNOD		(AGSOP_BASE + 16)
#define AGSOP_READDIRPLUS	(AGSOP_BASE + 17)
#define AGSOP_FSSTAT		(AGSOP_BASE + 18)
#define AGSOP_FSINFO		(AGSOP_BASE + 19)
#define AGSOP_PATHCONF		(AGSOP_BASE + 20)
#define AGSOP_COMMIT		(AGSOP_BASE + 21)
/*other*/
#define AGSOP_OPEN		(AGSOP_BASE + 22)
#define AGSOP_RELEASE		(AGSOP_BASE + 23)
#define AGSOP_LLSEEK		(AGSOP_BASE + 24)
#define AGSOP_MAX		25

/* all pre ops have same value as the AGSOP_ value */
#define POST_AGSOP_BIT (1 << (8 * sizeof(op_t) - 1))
static inline op_t pre_op(op_t op) { return op; }
static inline op_t post_op(op_t op) { return (op |= POST_AGSOP_BIT); }
#define IS_POST_OP(op) ((op) & POST_AGSOP_BIT)
#define GET_OP(op) (IS_POST_OP((op)) ? ((op) & ~POST_AGSOP_BIT) : (op))
/* base value for non file op messages */
#define MSG_META_BASE   (1 << (8 * sizeof(op_t) - 2))
#define MSG_START                (MSG_META_BASE + 0)
#define MSG_STOP                 (MSG_META_BASE + 1)
#define MSG_PNAME                (MSG_META_BASE + 2)
#define MSG_SYSCALL              (MSG_META_BASE + 3)

/* common arguments */
/* all type length value type arguments are encoded with last but one bit
 * set enabled. Since we're using short, this would mean an OR operation with
 * 0x4000. Make sure that the values of arguments are all < 0x4000, that is,
 * with the range of 0 - 16383 inclusive
 */

#define ARG_INVAL	    0                                                                                                                          
#define ARG_PATHNAME        1
#define ARG_TIMESTAMP       2
#define ARG_UTIMESTAMP      3
#define ARG_INUM            4
#define ARG_INT_FLAGS       5
#define ARG_LOFFSET         6
#define ARG_IATTR           7
#define ARG_REQUESTED_SIZE  8
#define ARG_DATA            9
#define ARG_FD              10
#define ARG_UID             11
#define ARG_GID             12
#define ARG_RET             13
#define ARG_MSG_DESC        14
#define ARG_MSG_ID          15
#define ARG_CHILD_INUM      16
#define ARG_PID             17
#define ARG_FIELD_ID        18
#define ARG_FIELD_LEN       19
#define ARG_FIELD_DESC      20
#define ARG_PNAME           21
// uname(2) fields
#define ARG_SYSNAME         22
#define ARG_RELEASE         23
#define ARG_VERSION         24
#define ARG_MACHINE         25
// for link
#define ARG_NEW_PATHNAME    26
#define ARG_DIR_INUM        27
// system call ID
#define ARG_SYSCALL         28
#define ARG_SYSCALL_NAME    29
// for calls with two inodes, dentries
#define ARG_NEW_INUM        30
// general string
#define ARG_STR             31
// general unsigned long (size_t)
#define ARG_ULONG           32
// for checksum
#define ARG_CKSUM           33
// These are for replaying, will not be in the original trace file
#define ARG_INODE           34
#define ARG_DENTRY          35
#define ARG_FILE            36
#define ARG_VFSMNT          37
// more fields
#define ARG_DENTRY_PTR      38
#define ARG_INODE_PTR       39
#define ARG_FILE_PTR        40
#define ARG_FILE_FLAGS      41
// needed with ops where we need to have more than one object of a type.
#define ARG_NEW_DENTRY_PTR  42
#define ARG_NEW_INODE_PTR   43

// page-based ops
#define ARG_PAGE_INDEX      44
#define ARG_WRITE_FROM      45
#define ARG_WRITE_TO        46
//
#define ARG_UULONG	    47

/* Non kernel stuff, used by the user level trace parsing library */
//#ifndef __KERNEL__
#define MSG_ENTRY(M) { M, #M }
struct msg_desc_t {
	op_t msg_type;
	char *str_type;
};

struct arg_desc_t {
	field_t         arg_type;
	char*           str_type;
	field_len_t     size;
};

#ifdef NEED_DESCRIPTIVE_MESSAGES

struct msg_desc_t msg_desc[] = {
	MSG_ENTRY(AGSOP_NULL),
	MSG_ENTRY(AGSOP_GETATTR),
	MSG_ENTRY(AGSOP_SETATTR),
	MSG_ENTRY(AGSOP_LOOKUP),
	MSG_ENTRY(AGSOP_READLINK),
	MSG_ENTRY(AGSOP_READ),
	MSG_ENTRY(AGSOP_WRITE),
	MSG_ENTRY(AGSOP_CREATE),
	MSG_ENTRY(AGSOP_REMOVE),
	MSG_ENTRY(AGSOP_RENAME),
	MSG_ENTRY(AGSOP_LINK),
	MSG_ENTRY(AGSOP_SYMLINK),
	MSG_ENTRY(AGSOP_MKDIR),
	MSG_ENTRY(AGSOP_RMDIR),
	MSG_ENTRY(AGSOP_READDIR),
	MSG_ENTRY(AGSOP_STATFS),
	MSG_ENTRY(AGSOP_ACCESS),
	MSG_ENTRY(AGSOP_MKNOD),
	MSG_ENTRY(AGSOP_READDIRPLUS),
	MSG_ENTRY(AGSOP_FSSTAT),
	MSG_ENTRY(AGSOP_FSINFO),
	MSG_ENTRY(AGSOP_PATHCONF),
	MSG_ENTRY(AGSOP_COMMIT),
	MSG_ENTRY(AGSOP_OPEN),
	MSG_ENTRY(AGSOP_RELEASE),
	MSG_ENTRY(AGSOP_LLSEEK),
	{ -1, NULL }
};

/* 
 * variable length args are put in this structure with zero length
 * because we don't look into this array for the length field
 */
   
#define ARG_ENTRY(M, S) { M, #M, S }
struct arg_desc_t arg_desc[] = {
	ARG_ENTRY(ARG_PATHNAME, 0),
	ARG_ENTRY(ARG_TIMESTAMP, sizeof(int)),
	ARG_ENTRY(ARG_UTIMESTAMP, 2 * sizeof(int)),
	ARG_ENTRY(ARG_INUM, sizeof(int)),
	ARG_ENTRY(ARG_INT_FLAGS, sizeof(int)),
	ARG_ENTRY(ARG_LOFFSET, sizeof(loff_t)),
	ARG_ENTRY(ARG_IATTR, 0),
	ARG_ENTRY(ARG_REQUESTED_SIZE, sizeof(int)),
	ARG_ENTRY(ARG_DATA, 0),
	ARG_ENTRY(ARG_FD, sizeof(int)),
	ARG_ENTRY(ARG_UID, sizeof(uid_t)),
	ARG_ENTRY(ARG_GID, sizeof(uid_t)),
	ARG_ENTRY(ARG_RET, sizeof(int)),
	ARG_ENTRY(ARG_MSG_DESC, 0),
	ARG_ENTRY(ARG_MSG_ID, sizeof(op_t)),
        ARG_ENTRY(ARG_CHILD_INUM, sizeof(int)),
	ARG_ENTRY(ARG_PID, sizeof(pid_t)),
	ARG_ENTRY(ARG_FIELD_ID, sizeof(field_t)),
	ARG_ENTRY(ARG_FIELD_LEN, sizeof(field_len_t)),
	ARG_ENTRY(ARG_FIELD_DESC, 0),
	ARG_ENTRY(ARG_PNAME, 0),
	ARG_ENTRY(ARG_SYSNAME, 0),
        ARG_ENTRY(ARG_RELEASE, 0),
	ARG_ENTRY(ARG_VERSION, 0),
	ARG_ENTRY(ARG_MACHINE, 0),
	ARG_ENTRY(ARG_NEW_PATHNAME, 0),
	ARG_ENTRY(ARG_DIR_INUM, 0),
	ARG_ENTRY(ARG_SYSCALL, sizeof(unsigned short)),
	ARG_ENTRY(ARG_SYSCALL_NAME, 0),
	ARG_ENTRY(ARG_NEW_INUM, sizeof(int)),
	ARG_ENTRY(ARG_STR, 0),
	ARG_ENTRY(ARG_ULONG, sizeof(unsigned long)),
	ARG_ENTRY(ARG_CKSUM, 0),
	ARG_ENTRY(ARG_DENTRY_PTR, sizeof(int)),
	ARG_ENTRY(ARG_NEW_DENTRY_PTR, sizeof(int)),
	ARG_ENTRY(ARG_FILE_PTR, sizeof(int)),
	ARG_ENTRY(ARG_INODE_PTR, sizeof(int)),
	ARG_ENTRY(ARG_NEW_INODE_PTR, sizeof(int)),
	ARG_ENTRY(ARG_FILE_FLAGS, sizeof(int)),
	ARG_ENTRY(ARG_PAGE_INDEX, sizeof(int)),
	ARG_ENTRY(ARG_WRITE_FROM, sizeof(int)),
	ARG_ENTRY(ARG_WRITE_TO, sizeof(int)),
	ARG_ENTRY(ARG_UULONG, sizeof(unsigned long long)),
	{ -1, NULL, 0}
};

#else
extern struct msg_desc_t msg_desc[];
extern struct arg_desc_t arg_desc[];

#endif 
//#endif /* !__ KERNEL__ */

#endif /* __MESSAGES_H */
