#define SUBSYSTEM APPLICATION_EXEC "_worker_inotify: "

#if ! defined(PROG_DISABLE_INOTIFY) && defined(HAVE_INOTIFY_INIT)
#define INOTIFY_DESC_TIMEOUT 1000000 / 100					/* Time interval in milliseconds
										   to check for inotify descriptor */
#define INOTIFY_EVENTS_READ 1024						/* Buffer size for reading events */
#define INOTIFY_BUFFER_SIZE (sizeof(struct inotify_event) + CONFIG_PATH_LENGTH) * INOTIFY_EVENTS_READ

/* REMEMBER to keep these in sync with build/ano predefined macros */
enum inotify_flags {
	INOTIFY_ACCESS = 0x1,
	INOTIFY_MODIFY = 0x2,
	INOTIFY_ATTRIB = 0x4,
	INOTIFY_CLOSE_WRITE = 0x8,
	INOTIFY_CLOSE_NOWRITE = 0x10,
	INOTIFY_CLOSE = 0x20,
	INOTIFY_OPEN = 0x40,
	INOTIFY_MOVED_FROM = 0x80,
	INOTIFY_MOVED_TO = 0x100,
	INOTIFY_MOVE = 0x200,
	INOTIFY_CREATE = 0x400,
	INOTIFY_DELETE = 0x800,
	INOTIFY_DELETE_SELF = 0x1000,
	INOTIFY_MOVE_SELF = 0x2000
};

struct t_str {
	void (*cb_notify)(struct d_par *);					/* Callback functions */

	struct d_par par_notify;						/* Callback subroutine parameters */

	struct inotify_ctx *ta;

	char *event;								/* Buffer for events */
};

struct a_not {
	char *s;								/* Inotify watch path */

	int d;									/* Inotify watch descriptor */
};

static int a_hnd = -1;								/* Inotify handle */

static D_LOCK t_sem_p = D_LOCK_INIT;						/* Semaphores for reader and writer */

static unsigned int c_set = 0;							/* Containers created */

static struct a_not **a_set = NULL;						/* Container structures */

static void worker_inotify(void *);
static void worker_inotify_cancel(void *);
static void worker_inotify_cancel_local(struct t_ctx *, struct t_str *);
static void worker_inotify_finalize(struct t_ctx *);
static int worker_inotify_init(struct t_ctx *);
static char *worker_inotify_init_op(char *);
static int worker_inotify_init_local(struct t_ctx *, struct t_str *);

static void worker_inotify_run(struct t_str *);
static void worker_inotify_run_op(struct t_str *, struct inotify_event *);
static void worker_inotify_run_at(struct t_str *, D_HANDLE, unsigned int, unsigned int, char *, char *, size_t);
static void worker_inotify_run_cb(struct d_par *, D_HANDLE, unsigned int, unsigned int, char *, char *, size_t);
static void worker_inotify_cb_notify(struct d_par *);

static D_HANDLE worker_inotify_get_struct(char *);
static struct a_not *worker_inotify_get_struct_by_handle(D_HANDLE);

/* dsl_cb.c */
void dsl_cb_inotify_notify(struct d_par *);

void dsl_cb_param_uint_add(struct d_par *, unsigned int, unsigned int);
void dsl_cb_param_string_add(struct d_par *, char *, size_t, unsigned int);
void dsl_cb_param_handle_add(struct d_par *, D_HANDLE, unsigned int, unsigned int);
#endif
