Main Page | Class Hierarchy | Data Structures | Directories | File List | Data Fields | Related Pages

Server.java

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 2001-2005
00005  *      Sleepycat Software.  All rights reserved.
00006  *
00007  * $Id: Server.java,v 12.2 2005/08/02 06:57:10 mjc Exp $
00008  */
00009 
00010 package com.sleepycat.db.rpcserver;
00011 
00012 import com.sleepycat.db.*;
00013 import com.sleepycat.db.internal.DbConstants;
00014 import java.io.*;
00015 import java.util.*;
00016 import org.acplt.oncrpc.OncRpcException;
00017 import org.acplt.oncrpc.server.OncRpcCallInformation;
00018 
00022 public class Server extends Dispatcher {
00023     public static long idleto = 10 * 60 * 1000; // 5 minutes
00024     public static long defto = 5 * 60 * 1000;   // 5 minutes
00025     public static long maxto = 60 * 60 * 1000;  // 1 hour
00026     public static String passwd = null;
00027     public static OutputStream errstream;
00028     public static PrintWriter err;
00029 
00030     long now, hint; // updated each operation
00031     FreeList env_list = new FreeList();
00032     FreeList db_list = new FreeList();
00033     FreeList txn_list = new FreeList();
00034     FreeList cursor_list = new FreeList();
00035 
00036     public Server() throws IOException, OncRpcException {
00037         super();
00038         init_lists();
00039     }
00040 
00041     public void dispatchOncRpcCall(OncRpcCallInformation call, int program,
00042                                    int version, int procedure) throws OncRpcException, IOException {
00043         long newnow = System.currentTimeMillis();
00044         // Server.err.println("Dispatching RPC call " + procedure + " after delay of " + (newnow - now));
00045         now = newnow;
00046         try {
00047             super.dispatchOncRpcCall(call, program, version, procedure);
00048             doTimeouts();
00049         } catch (Throwable t) {
00050             System.err.println("Caught " + t + " while dispatching RPC call " + procedure);
00051             t.printStackTrace(Server.err);
00052         } finally {
00053             Server.err.flush();
00054         }
00055     }
00056 
00057     // Internal methods to track context
00058     private void init_lists() {
00059         // We do this so that getEnv/Database/etc(0) == null
00060         env_list.add(null);
00061         db_list.add(null);
00062         txn_list.add(null);
00063         cursor_list.add(null);
00064     }
00065 
00066     int addEnv(RpcDbEnv rdbenv) {
00067         rdbenv.timer.last_access = now;
00068         int id = env_list.add(rdbenv);
00069         return id;
00070     }
00071 
00072     int addDatabase(RpcDb rdb) {
00073         int id = db_list.add(rdb);
00074         return id;
00075     }
00076 
00077     int addTxn(RpcDbTxn rtxn) {
00078         rtxn.timer.last_access = now;
00079         int id = txn_list.add(rtxn);
00080         return id;
00081     }
00082 
00083     int addCursor(RpcDbc rdbc) {
00084         rdbc.timer.last_access = now;
00085         int id = cursor_list.add(rdbc);
00086         return id;
00087     }
00088 
00089     void delEnv(RpcDbEnv rdbenv, boolean dispose) {
00090         env_list.del(rdbenv);
00091 
00092         // cursors and transactions will already have been cleaned up
00093         for (LocalIterator i = db_list.iterator(); i.hasNext();) {
00094             RpcDb rdb = (RpcDb)i.next();
00095             if (rdb != null && rdb.rdbenv == rdbenv)
00096                 delDatabase(rdb, true);
00097         }
00098 
00099         if (dispose)
00100             rdbenv.dispose();
00101     }
00102 
00103     void delDatabase(RpcDb rdb, boolean dispose) {
00104         db_list.del(rdb);
00105 
00106         for (LocalIterator i = cursor_list.iterator(); i.hasNext();) {
00107             RpcDbc rdbc = (RpcDbc)i.next();
00108             if (rdbc != null && rdbc.timer == rdb) {
00109                 i.remove();
00110                 rdbc.dispose();
00111             }
00112         }
00113 
00114         if (dispose)
00115             rdb.dispose();
00116     }
00117 
00118     void delTxn(RpcDbTxn rtxn, boolean dispose) {
00119         txn_list.del(rtxn);
00120 
00121         for (LocalIterator i = cursor_list.iterator(); i.hasNext();) {
00122             RpcDbc rdbc = (RpcDbc)i.next();
00123             if (rdbc != null && rdbc.timer == rtxn) {
00124                 i.remove();
00125                 rdbc.dispose();
00126             }
00127         }
00128 
00129         for (LocalIterator i = txn_list.iterator(); i.hasNext();) {
00130             RpcDbTxn rtxn_child = (RpcDbTxn)i.next();
00131             if (rtxn_child != null && rtxn_child.timer == rtxn) {
00132                 i.remove();
00133                 rtxn_child.dispose();
00134             }
00135         }
00136 
00137         if (dispose)
00138             rtxn.dispose();
00139     }
00140 
00141     void delCursor(RpcDbc rdbc, boolean dispose) {
00142         cursor_list.del(rdbc);
00143         if (dispose)
00144             rdbc.dispose();
00145     }
00146 
00147     RpcDbEnv getEnv(int envid) {
00148         RpcDbEnv rdbenv = (RpcDbEnv)env_list.get(envid);
00149         if (rdbenv != null)
00150             rdbenv.timer.last_access = now;
00151         return rdbenv;
00152     }
00153 
00154     RpcDb getDatabase(int dbid) {
00155         RpcDb rdb = (RpcDb)db_list.get(dbid);
00156         if (rdb != null)
00157             rdb.rdbenv.timer.last_access = now;
00158         return rdb;
00159     }
00160 
00161     RpcDbTxn getTxn(int txnid) {
00162         RpcDbTxn rtxn = (RpcDbTxn)txn_list.get(txnid);
00163         if (rtxn != null)
00164             rtxn.timer.last_access = rtxn.rdbenv.timer.last_access = now;
00165         return rtxn;
00166     }
00167 
00168     RpcDbc getCursor(int dbcid) {
00169         RpcDbc rdbc = (RpcDbc)cursor_list.get(dbcid);
00170         if (rdbc != null)
00171             rdbc.last_access = rdbc.timer.last_access = rdbc.rdbenv.timer.last_access = now;
00172         return rdbc;
00173     }
00174 
00175     void doTimeouts() {
00176         if (now < hint) {
00177             // Server.err.println("Skipping cleaner sweep - now = " + now + ", hint = " + hint);
00178             return;
00179         }
00180 
00181         // Server.err.println("Starting a cleaner sweep");
00182         hint = now + Server.maxto;
00183 
00184         for (LocalIterator i = cursor_list.iterator(); i.hasNext();) {
00185             RpcDbc rdbc = (RpcDbc)i.next();
00186             if (rdbc == null)
00187                 continue;
00188 
00189             long end_time = rdbc.timer.last_access + rdbc.rdbenv.timeout;
00190             // Server.err.println("Examining " + rdbc + ", time left = " + (end_time - now));
00191             if (end_time < now) {
00192                 Server.err.println("Cleaning up " + rdbc);
00193                 delCursor(rdbc, true);
00194             } else if (end_time < hint)
00195                 hint = end_time;
00196         }
00197 
00198         for (LocalIterator i = txn_list.iterator(); i.hasNext();) {
00199             RpcDbTxn rtxn = (RpcDbTxn)i.next();
00200             if (rtxn == null)
00201                 continue;
00202 
00203             long end_time = rtxn.timer.last_access + rtxn.rdbenv.timeout;
00204             // Server.err.println("Examining " + rtxn + ", time left = " + (end_time - now));
00205             if (end_time < now) {
00206                 Server.err.println("Cleaning up " + rtxn);
00207                 delTxn(rtxn, true);
00208             } else if (end_time < hint)
00209                 hint = end_time;
00210         }
00211 
00212         for (LocalIterator i = env_list.iterator(); i.hasNext();) {
00213             RpcDbEnv rdbenv = (RpcDbEnv)i.next();
00214             if (rdbenv == null)
00215                 continue;
00216 
00217             long end_time = rdbenv.timer.last_access + rdbenv.idletime;
00218             // Server.err.println("Examining " + rdbenv + ", time left = " + (end_time - now));
00219             if (end_time < now) {
00220                 Server.err.println("Cleaning up " + rdbenv);
00221                 delEnv(rdbenv, true);
00222             }
00223         }
00224 
00225         // if we didn't find anything, reset the hint
00226         if (hint == now + Server.maxto)
00227             hint = 0;
00228 
00229         // Server.err.println("Finishing a cleaner sweep");
00230     }
00231 
00232     // Some constants that aren't available elsewhere
00233     static final int ENOENT = 2;
00234     static final int EACCES = 13;
00235     static final int EEXIST = 17;
00236     static final int EINVAL = 22;
00237     static final int DB_SERVER_FLAGMASK = DbConstants.DB_LOCKDOWN |
00238         DbConstants.DB_PRIVATE | DbConstants.DB_RECOVER | DbConstants.DB_RECOVER_FATAL |
00239         DbConstants.DB_SYSTEM_MEM | DbConstants.DB_USE_ENVIRON |
00240         DbConstants.DB_USE_ENVIRON_ROOT;
00241     static final int DB_SERVER_ENVFLAGS = DbConstants.DB_INIT_CDB |
00242         DbConstants.DB_INIT_LOCK | DbConstants.DB_INIT_LOG | DbConstants.DB_INIT_MPOOL |
00243         DbConstants.DB_INIT_TXN | DbConstants.DB_JOINENV;
00244     static final int DB_SERVER_DBFLAGS = DbConstants.DB_READ_UNCOMMITTED |
00245         DbConstants.DB_NOMMAP | DbConstants.DB_RDONLY;
00246     static final int DB_SERVER_DBNOSHARE = DbConstants.DB_EXCL | DbConstants.DB_TRUNCATE;
00247     static final int DB_MODIFIER_MASK = 0xff000000;
00248 
00249     static Vector homes = new Vector();
00250 
00251     static void add_home(String home) {
00252         File f = new File(home);
00253         try {
00254             home = f.getCanonicalPath();
00255         } catch (IOException e) {
00256             // ignored
00257         }
00258         homes.addElement(home);
00259     }
00260 
00261     static boolean check_home(String home) {
00262         if (home == null)
00263             return false;
00264         File f = new File(home);
00265         try {
00266             home = f.getCanonicalPath();
00267         } catch (IOException e) {
00268             // ignored
00269         }
00270         return homes.contains(home);
00271     }
00272 
00273     public static void main(String[] args) {
00274         System.out.println("Starting Server...");
00275         for (int i = 0; i < args.length; i++) {
00276             if (args[i].charAt(0) != '-')
00277                 usage();
00278 
00279             switch (args[i].charAt(1)) {
00280             case 'h':
00281                 add_home(args[++i]);
00282                 break;
00283             case 'I':
00284                 idleto = Long.parseLong(args[++i]) * 1000L;
00285                 break;
00286             case 'P':
00287                 passwd = args[++i];
00288                 break;
00289             case 't':
00290                 defto = Long.parseLong(args[++i]) * 1000L;
00291                 break;
00292             case 'T':
00293                 maxto = Long.parseLong(args[++i]) * 1000L;
00294                 break;
00295             case 'V':
00296                 // version;
00297                 break;
00298             case 'v':
00299                 // verbose
00300                 break;
00301             default:
00302                 usage();
00303             }
00304         }
00305 
00306         try {
00307             // Server.errstream = System.err;
00308             Server.errstream = new FileOutputStream("JavaRPCServer.trace", true);
00309             Server.err = new PrintWriter(Server.errstream);
00310             Server server = new Server();
00311             server.run();
00312         } catch (Throwable e) {
00313             System.err.println("Server exception:");
00314             e.printStackTrace(Server.err);
00315         } finally {
00316             if (Server.err != null)
00317                 Server.err.close();
00318         }
00319 
00320         System.out.println("Server stopped.");
00321     }
00322 
00323     static void usage() {
00324         System.err.println("usage: java com.sleepycat.db.rpcserver.Server \\");
00325         System.err.println("[-Vv] [-h home] [-P passwd] [-I idletimeout] [-L logfile] [-t def_timeout] [-T maxtimeout]");
00326         System.exit(1);
00327     }
00328 }

Generated on Sun Dec 25 12:14:49 2005 for Berkeley DB 4.4.16 by  doxygen 1.4.2