001: /*
002: * Copyright 2001 Sun Microsystems, Inc. All rights reserved.
003: * PROPRIETARY/CONFIDENTIAL. Use of this product is subject to license terms.
004: */
005:
006: package com.sun.portal.search.rdmserver;
007:
008: import com.sun.portal.search.util.*;
009: import com.sun.portal.search.db.*;
010: import com.sun.portal.log.common.PortalLogger;
011:
012: import java.util.*;
013: import java.util.logging.Logger;
014: import java.util.logging.Level;
015:
016: /**
017: * Support for RDM database requests - maps database names to objects.
018: */
019: public class DbAccess {
020:
021: // This class does name to db mapping in support of multiple dbs.
022: // It could be used to control concurrency, etc.
023:
024: /** maps db name to db handle */
025: static Map dbMap = new HashMap();
026:
027: static final int defaultDbConcurrent = 8; // XXX global - want per database?
028: Semaphore dbsem;
029:
030: // hide
031: private DbAccess() {
032: int poolsize = defaultDbConcurrent;
033: String s;
034: if ((s = SearchConfig.getValue(SearchConfig.DBMAX)) != null) {
035: int i = Integer.parseInt(s);
036: if (i > 0)
037: poolsize = i;
038: }
039: dbsem = new Semaphore(poolsize);
040: }
041:
042: static DbAccess dbaccess; // singleton
043:
044: synchronized static DbAccess getInstance() {
045: if (dbaccess == null)
046: dbaccess = new DbAccess();
047: return dbaccess;
048: }
049:
050: // Restart is called in a single-threaded mode
051: public synchronized void shutdown(SToken st) throws Exception {
052: for (Iterator dbit = dbMap.entrySet().iterator(); dbit
053: .hasNext();) {
054: Map.Entry me = (Map.Entry) dbit.next();
055: SearchLogger.getLogger().log(Level.FINE,
056: "PSSH_CSPSRDMS0021", (String) me.getKey());
057: RDMDb db = (RDMDb) me.getValue();
058: db.close(st);
059: }
060: dbMap.clear();
061: }
062:
063: // XXX do we need multiple handles per db? More efficient? Less contention?
064: public RDMDb readStart(SToken st, String dbname) throws Exception {
065: return writeStart(st, dbname);
066: }
067:
068: public void readFinish(SToken st, RDMDb db) throws Exception {
069: writeFinish(st, db);
070: }
071:
072: public RDMDb writeStart(SToken st, String dbname) throws Exception {
073: SearchLogger.getLogger().log(Level.FINE, "PSSH_CSPSRDMS0022",
074: dbname);
075: String pdbname = st.getPhysicalDBName();
076: //request might not contain database parameter, system use the default but not yet in SToken
077: if (pdbname == null) {
078: st.setDatabaseName(dbname);
079: pdbname = st.getPhysicalDBName();
080: }
081: dbsem.acquire();
082: RDMDb db = null;
083: synchronized (dbMap) {
084: db = (RDMDb) dbMap.get(pdbname);
085: if (db != null) {
086: SearchLogger.getLogger().log(Level.FINE,
087: "PSSH_CSPSRDMS0023", pdbname);
088: // NB: Sleepycat says it's okay to share a single connection, but we might
089: // want to check this for performance versus a multiple connection implementation.
090: // Multiple connections could be used as a semaphore too.
091: return db;
092: }
093: // Open a db connection
094: db = DbManager.dbOpen(st, pdbname, RDMDb.WRCREAT);
095: dbMap.put(pdbname, db);
096: }
097: SearchLogger.getLogger().log(Level.FINE, "PSSH_CSPSRDMS0024",
098: dbname);
099: return db;
100: }
101:
102: public void writeFinish(SToken st, RDMDb db) throws Exception {
103: dbsem.release();
104: }
105:
106: }
|