/*
** SellaNMS
** $Id: module.h,v 2.46 2005/05/15 05:21:17 sella Exp $
** Copyright (c) 2001-2005 Digital Genesis Software, LLC. All Rights Reserved.
** Released under the GPL Version 2 License.
** http://www.digitalgenesis.com
*/

#ifndef __DGS_MODULE_H
#define __DGS_MODULE_H

#ifdef HAVE_CONFIG_H
	#include "config.h"
#endif

#include "defaults.h"
#include "confignode.h"
#include "storagedata.h"
#include <pwd.h>
#include <grp.h>
#include <stdio.h>
#include <unistd.h> 
#include <stdarg.h>
#include <pthread.h>
#include <sys/sem.h>
#include <stl/list>
#include <stl/hash_map>

#define THREAD_STATUS							(0x20000000)
#define THREAD_UNKNOWN							(THREAD_STATUS | 0x00000000)
#define THREAD_STARTING							(THREAD_STATUS | 0x00000001)
#define THREAD_RUNNING							(THREAD_STATUS | 0x00000002)
#define THREAD_KILLED							(THREAD_STATUS | 0x00000003)
#define THREAD_COMPLETED						(THREAD_STATUS | 0x00000004)

#define MODULE_SCHEDULER_SLIP_THRESHOLD	5 /* Only notify of slips longer than 5 sec. */

#define DEFAULT_MODULE_TIMEOUT				30
#define DEFAULT_MODULE_DELAY					0
#define DEFAULT_MODULE_ORDER					0

class Module;

typedef struct module_t {
	Module* instance;
	void* handle;
} _module;

typedef struct mod_attr_t {
	string name;
	string dso;
	Module* ptr;
	pthread_t execute_id;
	pthread_t scheduler_id;
	bool thread;
	bool block;
	bool resident;
	bool startup;
	long order;
	long timeout;
	long delay;
	string cron;
	time_t next_start;
	time_t last_start;
} _mod_attr;

typedef struct {
	bool config;
	bool sql;
	bool policy_in;
	bool policy_out;
	bool policy_sql;
	bool thread;
	bool internal;
	bool timer;
	bool debug;
} traceoptions_t;

class Module {
	public:
		Module();
		virtual ~Module();

		/* External API - General */
		RESULT start(pthread_t &scheduler_id, pthread_t &execute_id);
		RESULT setConfig(ConfigNode *node);
		RESULT setUid(uid_t uid);
		RESULT setGid(gid_t gid);
		RESULT setStatFile(string stat_file);

		/* Internal API - Main [FIXME: Daemon uses this for Storage] */
		virtual RESULT readConfig();
		virtual RESULT readTraceOptions();
		virtual RESULT handleTraceOptions();
		virtual RESULT printConfig();

	protected:
		/* Internal API - Main */
		virtual RESULT scheduler();
		virtual RESULT execute();
		virtual RESULT grantPriv();
		virtual RESULT dropPriv();

		/* Internal API - Thread */
		RESULT getThreadResult(pthread_t thread_id, RESULT &thread_result);
		RESULT getThreadStatus(pthread_t thread_id, STATUS &thread_result);
		RESULT setThreadStatus(pthread_t thread_id, STATUS thread_result);
		RESULT createThread(pthread_t& thread_id, void* (*thread_func)(void*), void* args);
		RESULT killThread(pthread_t thread_id);
		RESULT killThreadAll();
		bool schedulerRunning();

		/* Internal API - Module */
		RESULT getModuleInstance(Module *&instance, string &module);
		RESULT loadModule(string &module, string &dso, bool resident = false);
		RESULT unloadModule(string &module, bool resident = false);

		/* Internal API - Hooks. */
		virtual RESULT childStart(Module *child_module);
		virtual RESULT childStop(Module *child_module);

		/* Variable */
		ConfigNode *config;
		string name;
		traceoptions_t trace;
		bool interrupt;
		bool has_scheduler;
		bool has_execute;

	private:
		RESULT buildModuleList(list<mod_attr_t> &mod_list);
		RESULT startModule(mod_attr_t &mod_attr);
		RESULT stopModule(mod_attr_t &mod_attr);
		RESULT setNextStart(mod_attr_t &mod_attr);
		long cronAdj(long val, long val_max, char *str);

		static RESULT scheduler_thread(void *args);
		static RESULT execute_thread(void *args);

		hash_map<string, module_t>		modules;
		pthread_mutex_t 					modules_mutex;

		hash_map<pthread_t, RESULT> 	threads;
		pthread_mutex_t 					threads_mutex;

		bool scheduler_running;
		long 	threadCount;
		uid_t uid;
		gid_t gid;
		string stat_file;
};

#endif

/*
** Local Variables:
** c-basic-offset: 3
** tab-width: 3
** End:
** vim600: fdm=marker
** vim: noet ts=3 sw=3
*/
