/*-
 * See the file LICENSE for redistribution information.
 *
 * Copyright (c) 2001-2002
 *      Sleepycat Software.  All rights reserved.
 *
 * $Id: RpcDbEnv.java,v 1.1 2002/01/03 02:59:39 mjc Exp $
 */

package com.sleepycat.db.rpcserver;

import com.sleepycat.db.*;
import java.io.IOException;
import java.io.*;
import java.util.*;

/**
 * RPC wrapper around a dbenv for the Java RPC server.
 */
public class RpcDbEnv extends Timer
{
	DbEnv dbenv;
	long idletime, timeout;
	
	void dispose()
	{
		if (dbenv != null) {
			try {
				dbenv.close(0);
			} catch(DbException e) {
				e.printStackTrace(DbServer.err);
			}
			dbenv = null;
		}
	}
	
	public  void close(DbDispatcher server,
		__env_close_msg args, __env_close_reply reply)
	{
		try {
			dbenv.close(args.flags);
			dbenv = null;
			reply.status = 0;
		} catch(DbException e) {
			e.printStackTrace(DbServer.err);
			reply.status = e.get_errno();
		} finally {
			server.delEnv(this);
		}
	}
	
	public  void create(DbDispatcher server,
		__env_create_msg args, __env_create_reply reply)
	{
		this.idletime = (args.timeout != 0) ? args.timeout : DbServer.idleto;
		this.timeout = DbServer.defto;
		dbenv = new DbEnv(0);
		reply.envcl_id = server.addEnv(this);
		reply.status = 0;
	}
	
	public  void open(DbDispatcher server,
		__env_open_msg args, __env_open_reply reply)
	{
		try {
			args.home = (args.home.length() > 0) ? args.home : null;
			// TODO: check home?

			/*
			 * If they are using locking do deadlock detection for them,
			 * internally.
			 */
			if ((args.flags & Db.DB_INIT_LOCK) != 0)
				dbenv.set_lk_detect(Db.DB_LOCK_DEFAULT);
				
			// adjust flags for RPC
			args.flags &= ~DbServer.DB_SERVER_FLAGMASK;
			dbenv.open(args.home, args.flags, args.mode);
			reply.status = 0;
		} catch(DbException e) {
			e.printStackTrace(DbServer.err);
			reply.status = e.get_errno();
		} catch(FileNotFoundException e) {
			reply.status = Db.DB_NOTFOUND;
		}
	}
	
	public  void remove(DbDispatcher server,
		__env_remove_msg args, __env_remove_reply reply)
	{
		try {
			args.home = (args.home.length() > 0) ? args.home : null;
			// TODO: check home?

			dbenv.remove(args.home, args.flags);
			dbenv = null;
			reply.status = 0;
		} catch(DbException e) {
			e.printStackTrace(DbServer.err);
			reply.status = e.get_errno();
		} catch(FileNotFoundException e) {
			reply.status = Db.DB_NOTFOUND;
		} finally {
			server.delEnv(this);
		}
	}
	
	public  void set_cachesize(DbDispatcher server,
		__env_cachesize_msg args, __env_cachesize_reply reply)
	{
		try {
			dbenv.set_cachesize(args.gbytes, args.bytes, args.ncache);
			reply.status = 0;
		} catch(DbException e) {
			e.printStackTrace(DbServer.err);
			reply.status = e.get_errno();
		}
	}
	
	public  void set_flags(DbDispatcher server,
		__env_flags_msg args, __env_flags_reply reply)
	{
		try {
			dbenv.set_flags(args.flags, args.onoff != 0);
			reply.status = 0;
		} catch(DbException e) {
			e.printStackTrace(DbServer.err);
			reply.status = e.get_errno();
		}
	}
	
	// txn_recover implementation
	public  void txn_recover(DbDispatcher server,
		__txn_recover_msg args, __txn_recover_reply reply)
	{
		try {
			DbPreplist[] prep_list = dbenv.txn_recover(args.count, args.flags);
			if (prep_list != null && prep_list.length > 0) {
				int count = prep_list.length;
				reply.retcount = count;
				reply.txn = new int[count];
				reply.gid = new byte[count * Db.DB_XIDDATASIZE];
				
				for(int i = 0; i < count; i++) {
					reply.txn[i] = server.addTxn(new RpcDbTxn(this, prep_list[i].txn));
					System.arraycopy(prep_list[i].gid, 0, reply.gid, i * Db.DB_XIDDATASIZE, Db.DB_XIDDATASIZE);
				}
			}
			
			reply.status = 0;
		} catch(DbException e) {
			e.printStackTrace(DbServer.err);
			reply.status = e.get_errno();
		}
	}
}