/*
 * Copyright (c) 2003-2016
 * Distributed Systems Software.  All rights reserved.
 * See the file LICENSE for redistribution information.
 *
 * $Id: vfs.h 2910 2016-10-18 19:46:38Z brachman $
 */

/*****************************************************************************
 * COPYRIGHT AND PERMISSION NOTICE
 * 
 * Copyright (c) 2001-2003 The Queen in Right of Canada
 * 
 * All rights reserved.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation 
 * the rights to use, copy, modify, merge, publish, distribute, and/or sell
 * copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, provided that the above copyright notice(s) and this
 * permission notice appear in all copies of the Software and that both the
 * above copyright notice(s) and this permission notice appear in supporting
 * documentation.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE 
 * BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
 * SOFTWARE.
 * 
 * Except as contained in this notice, the name of a copyright holder shall not
 * be used in advertising or otherwise to promote the sale, use or other
 * dealings in this Software without prior written authorization of the
 * copyright holder.
 ***************************************************************************/

#ifndef _VFS_H_
#define _VFS_H_

#include <stdarg.h>

#include "kwv.h"

#ifndef DEFAULT_FIELD_SEP_CHAR
#define DEFAULT_FIELD_SEP_CHAR		":"
#endif

typedef enum {
  VFS_OPEN       =  0,
  VFS_CLOSE      =  1,
  VFS_CONTROL    =  2,
  VFS_GET        =  3,
  VFS_GETSIZE    =  4,
  VFS_PUT        =  5,
  VFS_DELETE     =  6,
  VFS_EXISTS     =  7,
  VFS_RENAME     =  8,
  VFS_LIST       =  9,
  VFS_ENABLED    = 10,
  VFS_DEFINED    = 11,
  VFS_URI        = 12,
  VFS_UNKNOWN    = 13
} Vfs_op;

typedef enum {
  VFS_FLUSH_DATA        = 0,
  VFS_SET_FIELD_SEP     = 1,
  VFS_SET_COOKIES       = 2,
  VFS_SET_LOCK          = 3,
  VFS_GET_CONTAINER     = 4,
  VFS_GET_FIELD_SEP     = 5
} Vfs_control_op;

typedef enum {
  VFS_NOLOCK        = 0,
  VFS_SHLOCK        = 1,
  VFS_EXLOCK        = 2
} Vfs_lock_type;

typedef struct Vfs_op_tab {
  Vfs_op op;
  char *opname;
} Vfs_op_tab;

typedef struct Vfs_switch Vfs_switch;

typedef struct Vfs_conf {
  unsigned int null_flag;
  unsigned int create_flag;
  unsigned int append_flag;
  unsigned int delete_flag;
  unsigned int lock_flag;
  mode_t mode;
} Vfs_conf;

typedef struct Vfs_directive {
  Uri *uri;
  char *uri_str;
  char *store_name;
  char *item_type;
  char *naming_context;
  char *option_str;
  char *path;
  Kwv *options;
} Vfs_directive;

typedef struct Vfs_handle {
  Vfs_directive *sd;
  Vfs_switch *sw;
  char *error_msg;				/* Most recent error message */
  int error_num;				/* For most recent error */
  int (*get_filter)(struct Vfs_handle *, void *inbuf, size_t inbuf_length,
					void **outbuf, size_t *outbuf_length);
  int (*put_filter)(struct Vfs_handle *, void *inbuf, size_t inbuf_length,
					void **outbuf, size_t *outbuf_length);
  void (*list_sort)(void *base, size_t nmemb, size_t size,
					int (*compar)(const void *, const void *));
  Kwv *kwv;
  unsigned int append_flag : 1;	/* Append to object, if possible */
  unsigned int create_flag : 1;	/* If it doesn't exist, create it */
  unsigned int delete_flag : 1;	/* If it already exists, delete it */
  unsigned int lock_flag   : 2;	/* A VFS_LOCK_TYPE value */
  unsigned int null_flag   : 1;	/* Set if keys include null character */
  mode_t mode;					/* If non-zero, mode bits for creation */
  void *h;
} Vfs_handle;

/*
 * Callbacks for the store-dependent layer.
 * All are required.
 */
struct Vfs_switch {
  char *store_name;
  int (*open)(Vfs_handle *, char *naming_context);
  int (*close)(Vfs_handle *);
  int (*control)(Vfs_handle *, Vfs_control_op op, va_list ap);
  int (*get)(Vfs_handle *, char *key, void **buffer, size_t *length);
  int (*getsize)(Vfs_handle *, char *key, size_t *length);
  int (*put)(Vfs_handle *, char *key, void *buffer, size_t length);
  int (*delete)(Vfs_handle *, char *key);
  int (*exists)(Vfs_handle *, char *key);
  int (*rename)(Vfs_handle *, char *oldkey, char *newkey);
  int (*list)(Vfs_handle *,
			  int (*is_valid)(char *),
			  int (*compar)(const void *, const void *),
			  int (*add)(char *, char *, void ***), void ***names);
};

typedef struct Vfs_def {
	char *store_name;
	Vfs_switch *(*vfs_init)(char *store_name);
    void (*vfs_term)(char *store_name);
} Vfs_def;

#ifdef __cplusplus
extern "C" {
#endif

extern void vfs_init(void);
extern void vfs_term(void *bogus);
extern Vfs_directive *vfs_init_directive(Vfs_directive *ovd);
extern Vfs_directive *vfs_lookup_item_type(char *item_type);
extern Dsvec *vfs_list_item_types(Dsvec *odsv);
extern Vfs_op vfs_lookup_op(char *opname);
extern int vfs_enabled(char *store_name);
extern Dsvec *vfs_enabled_list(void);
extern int vfs_open(Vfs_directive *sd, Vfs_handle **handle);
extern Vfs_handle *vfs_open_item_type(char *item_type);
extern Vfs_handle *vfs_open_uri(char *vfs_uri);
extern Vfs_handle *vfs_open_any(char *any);
extern int vfs_close(Vfs_handle *handle);
extern int vfs_control(Vfs_handle *handle, Vfs_control_op op, ...);
extern int vfs_get(Vfs_handle *handle, char *key, void **buffer,
					 size_t *length);
extern int vfs_get_any(char *any, char *key, void **buffer, size_t *length);
extern int vfs_getsize(Vfs_handle *handle, char *key, size_t *length);
extern int vfs_put(Vfs_handle *handle, char *key, void *buffer,
					 size_t length);
extern int vfs_delete(Vfs_handle *handle, char *key);
extern int vfs_exists(Vfs_handle *handle, char *key);
extern int vfs_rename(Vfs_handle *handle, char *oldkey, char *newkey);
extern int vfs_list(Vfs_handle *handle,
					  int (*is_valid)(char *),
					  int (*compar)(const void *, const void *),
					  int (*add)(char *, char *, void ***), void ***names);
extern Vfs_directive *vfs_uri_parse(char *uri_str, Vfs_directive *);
extern Vfs_conf *vfs_conf(Vfs_conf *conf);
extern int vfs_is_valid_item_type(char *item_type);

#ifdef __cplusplus
}
#endif

#endif
