1 2 24 25 package com.lutris.appserver.server.sessionEnhydra; 26 27 import java.util.Enumeration ; 28 import java.util.Hashtable ; 29 import java.util.Vector ; 30 31 import com.lutris.appserver.server.Enhydra; 32 import com.lutris.appserver.server.session.SessionException; 33 import com.lutris.logging.Logger; 34 import com.lutris.util.Config; 35 import com.lutris.util.ConfigException; 36 37 105 public abstract class PagedSessionHome implements StandardSessionHome { 106 107 111 private Hashtable activeCache = new Hashtable (); 112 113 118 private Hashtable activeThreadCache = new Hashtable (); 119 120 124 private Hashtable passiveCache = new Hashtable (); 125 126 129 private Config config; 130 131 134 private long maxSessions = -1; 135 136 139 private long pageThreshold = -1; 140 141 145 private long pageTimeThreshold = -1; 146 147 150 private PagedSessionThresholdTimer thresholdTimer; 151 152 159 private long pageWait = 60000; 161 164 private final String MAX_SESSIONS_KEY = "MaxSessions"; 165 private final String PAGE_THRESHOLD_KEY = "PageThreshold"; 166 private final String PAGE_TIME_THRESHOLD_KEY = "PageTimeThreshold"; 167 private final String PAGE_WAIT_KEY = "PageWait"; 168 private final long UNDEFINED_MAX_SESSIONS = -1; 169 170 173 protected ClassLoader loader; 174 175 178 protected StandardSessionManager sessionMgr; 179 180 193 public PagedSessionHome(StandardSessionManager sessionMgr, 194 Config config, ClassLoader loader) 195 throws SessionException, ConfigException { 196 this.config = config; 197 this.loader = loader; 198 this.sessionMgr = sessionMgr; 199 if (config.containsKey(MAX_SESSIONS_KEY)) { 200 maxSessions = config.getLong(MAX_SESSIONS_KEY); 201 } 202 if (maxSessions <= 0) { 203 maxSessions = UNDEFINED_MAX_SESSIONS; 204 } 205 debug(MAX_SESSIONS_KEY + " = " + maxSessions); 206 pageThreshold = config.getLong(PAGE_THRESHOLD_KEY); 207 debug(PAGE_THRESHOLD_KEY + " = " + pageThreshold); 208 if (config.containsKey(PAGE_WAIT_KEY)) { 209 pageWait = config.getLong(PAGE_WAIT_KEY); 210 if (pageWait <= 0) { 211 throw new ConfigException("PagedSessionHome: " 212 + "PageWait cannot be <= 0."); 213 } 214 } 215 if (config.containsKey(PAGE_TIME_THRESHOLD_KEY)) { 216 pageTimeThreshold = config.getLong(PAGE_TIME_THRESHOLD_KEY) * 1000; 217 if (!isWriteThroughCache() && (pageTimeThreshold > 0)) { 218 thresholdTimer = new PagedSessionThresholdTimer(this, sessionMgr.app); 219 thresholdTimer.start(); 220 } 221 } 222 debug(PAGE_TIME_THRESHOLD_KEY + " = " + pageTimeThreshold); 223 } 224 225 240 public synchronized StandardSession createSession(String sessionKey) 241 throws CreateSessionException, DuplicateKeyException, SessionException { 242 if (containsKey(sessionKey)) { 243 throw new DuplicateKeyException("Session key " 244 + sessionKey + " is already in use."); 245 } 246 if ((maxSessions != UNDEFINED_MAX_SESSIONS) && 247 (maxSessions <= size())) { 248 cleanupNewSession(); 249 if (maxSessions <= size()) { 250 throw new CreateSessionException("Maximum session limit of " 251 + maxSessions 252 + " sessions has been reached."); 253 } 254 } 255 ensureNewSession(); 256 PagedSession session = newSession(sessionMgr, sessionKey); 257 SessionThread activeKey = new SessionThread(Thread.currentThread(), 258 sessionKey); 259 session.incrementRefCount(); activeThreadCache.put(activeKey, session); 261 activeCache.put(sessionKey, session); 262 debug("createSession: " + activeKey); 264 return (StandardSession)session; 265 } 266 267 274 protected abstract PagedSession newSession(StandardSessionManager mgr, 275 String sessionKey) 276 throws SessionException; 277 278 279 286 protected abstract void deleteSession(String sessionKey) 287 throws SessionException; 288 289 300 public synchronized StandardSession getSession(String sessionKey) 301 throws SessionException { 302 debug("get session: key = " + sessionKey); 304 SessionThread activeKey = new SessionThread(Thread.currentThread(), 305 sessionKey); 306 PagedSession s = (PagedSession)activeThreadCache.get(activeKey); 307 return s; 308 } 309 310 324 public synchronized StandardSession getSession(Thread thread, String sessionKey) 325 throws SessionException { 326 debug("getSession: " + sessionKey); 328 SessionThread activeKey = new SessionThread(thread, sessionKey); 329 PagedSession s = (PagedSession)activeThreadCache.get(activeKey); 330 if (s == null) { 331 s = (PagedSession)activeCache.get(sessionKey); 332 if (s == null) { 333 s = activateSession(sessionKey); 334 } 335 if (s != null) { 336 activeThreadCache.put(activeKey, s); 337 s.incrementRefCount(); 339 } 340 } 341 return s; 342 } 343 344 353 public synchronized void removeSession(String sessionKey) throws SessionException { 354 debug("removeSession: " + sessionKey); 356 Enumeration e = activeThreadCache.keys(); 357 while (e.hasMoreElements()) { 358 SessionThread key = (SessionThread)e.nextElement(); 359 if (key.sessionKey.equals(sessionKey)) { 360 activeThreadCache.remove(key); 361 } 362 } 363 activeCache.remove(sessionKey); 364 passiveCache.remove(sessionKey); 365 deleteSession(sessionKey); 366 notify(); 367 } 368 369 378 public synchronized void passivateSession(Thread thread, String sessionKey) 379 throws SessionException { 380 SessionThread activeKey = new SessionThread(thread, sessionKey); 381 try { 382 debug("passivateSession: " + activeKey); 384 if (activeThreadCache.containsKey(activeKey)) { 385 PagedSession s = (PagedSession)activeThreadCache.remove(activeKey); 386 s.decrementRefCount(); 387 if (s.getRefCount() == 0) { 389 if (isWriteThroughCache()) { 390 pageOut(s); 391 } else if ((pageThreshold < 0) 392 || ((activeCache.size() + passiveCache.size()) < pageThreshold)) { 393 debug("active -> passive: " + sessionKey); 395 passiveCache.put(sessionKey, s); 396 } else { 397 pageOut(s); 398 } 399 activeCache.remove(sessionKey); 400 } 401 } else { 402 debug("passivateSession called but active session " 404 + " doesn't exist: " + sessionKey); 405 } 406 } catch (Exception e) { 407 throw new SessionException(e); 408 } finally { 409 notify(); 410 } 411 } 412 413 420 protected abstract void pageOut(PagedSession s) throws SessionException; 421 422 432 protected abstract PagedSession pageIn(String sessionKey) throws SessionException; 433 434 437 protected abstract int getPagedSessionCount() throws SessionException; 438 439 448 private synchronized PagedSession activateSession(String sessionKey) 449 throws SessionException { 450 PagedSession session = null; 451 boolean isPaged = !activeCache.containsKey(sessionKey) 452 && !passiveCache.containsKey(sessionKey); 453 debug("activateSession: " + sessionKey); 455 if (isPaged) { 456 ensureNewSession(); 457 session = pageIn(sessionKey); 458 } else if (passiveCache.containsKey(sessionKey)) { 459 debug("passive -> active : " + sessionKey); 461 session = (PagedSession)passiveCache.remove(sessionKey); 462 } else if (activeCache.containsKey(sessionKey)) { 463 debug("session is active : " + sessionKey); 465 session = (PagedSession)activeCache.get(sessionKey); 466 } 467 if (session != null) { 468 activeCache.put(sessionKey, session); 469 } 470 return session; 471 } 472 473 480 public boolean containsKey(String sessionKey) throws SessionException { 481 if (activeCache.containsKey(sessionKey) 482 || passiveCache.containsKey(sessionKey) 483 || pagedSessionKeyExists(sessionKey)) { 484 return true; 485 } 486 return false; 487 } 488 489 497 protected abstract boolean pagedSessionKeyExists(String sessionKey) 498 throws SessionException; 499 500 506 public int size() throws SessionException { 507 return activeCache.size() + passiveCache.size() 508 + getPagedSessionCount(); 509 } 510 511 520 public int pagedSize() throws SessionException { 521 return getPagedSessionCount(); 522 } 523 524 530 public synchronized Enumeration keys() throws SessionException { 531 try { 532 Vector v = new Vector (); 533 String sessionKey; 534 Enumeration e; 535 e = activeCache.keys(); 536 while (e.hasMoreElements()) { 537 sessionKey = (String )e.nextElement(); 538 if (!v.contains(sessionKey)) { 539 v.addElement(sessionKey); 540 } 541 } 542 e = passiveCache.keys(); 543 while (e.hasMoreElements()) { 544 sessionKey = (String )e.nextElement(); 545 if (!v.contains(sessionKey)) { 546 v.addElement(sessionKey); 547 } 548 } 549 e = getPagedSessionKeys(); 550 while (e.hasMoreElements()) { 551 sessionKey = (String )e.nextElement(); 552 if (!v.contains(sessionKey)) { 553 v.addElement(sessionKey); 554 } 555 } 556 return v.elements(); 557 } catch (Exception e) { 558 throw new SessionException(e); 559 } 560 } 561 562 569 protected abstract Enumeration getPagedSessionKeys() throws SessionException; 570 571 577 private void cleanupNewSession() throws SessionException { 578 if (!cleanupNewPagedSession()) { 579 Enumeration e; 580 String key = null; 581 long oldestTime = -1; 582 e = passiveCache.keys(); 583 while (e.hasMoreElements()) { 584 PagedSession s = (PagedSession)passiveCache.get(e.nextElement()); 585 if (s.isNew()) { 586 if ((oldestTime < 0) 587 || (s.getTimeCreated() < oldestTime)) { 588 oldestTime = s.getTimeCreated(); 589 key = s.getSessionKey(); 590 } 591 } 592 } 593 if (key != null) { 594 removeSession(key); 595 } 596 } 597 } 598 599 606 long checkPassiveSessions() throws SessionException { 607 return checkPassiveSessions(pageTimeThreshold); 608 } 609 610 619 private synchronized long checkPassiveSessions(long threshold) 620 throws SessionException { 621 long nextCheck = threshold; 622 Enumeration e = passiveCache.elements(); 623 long now = System.currentTimeMillis(); 624 while (e.hasMoreElements()) { 625 PagedSession s = (PagedSession) e.nextElement(); 626 long passiveTime = now - s.getTimeLastUsed(); 627 if (passiveTime >= threshold) { 628 pageOut(s); 629 passiveCache.remove(s.getSessionKey()); 630 } else if (nextCheck > (threshold - passiveTime)) { 631 nextCheck = threshold - passiveTime; 632 } 633 } 634 return nextCheck; 635 } 636 637 643 protected abstract boolean cleanupNewPagedSession() throws SessionException; 644 645 646 654 private void ensureNewSession() throws SessionException { 655 if (pageThreshold > 0) { while ((activeCache.size() + passiveCache.size()) > pageThreshold) { 657 if (passiveCache.size() == 0) { 658 try { 659 debug("waiting for a passive session that can be paged..."); 661 wait(pageWait); 662 if (passiveCache.size() <= 0) { 663 throw new SessionException("Unable to activate session: " 664 + "no sessions are ready to be paged."); 665 } 666 } catch (InterruptedException e) { 667 } 669 } else { 670 debug("a passive session ready to be paged"); 672 Enumeration keys = passiveCache.keys(); 673 PagedSession s = (PagedSession)passiveCache.get((String )keys.nextElement()); 674 pageOut(s); 675 passiveCache.remove(s.getSessionKey()); 676 } 677 } 678 } 679 } 680 681 684 public synchronized void shutdown() { 685 try { 686 if (thresholdTimer != null) { 687 thresholdTimer.shutdown(); 688 thresholdTimer = null; 689 } 690 Enumeration e=activeThreadCache.keys(); 692 while (e.hasMoreElements()){ 693 SessionThread s=(SessionThread)e.nextElement(); 694 passivateSession(s.thread, s.sessionKey); 695 } 696 checkPassiveSessions(0); 698 } catch (Exception e) { 699 Enhydra.getLogChannel().write(Logger.ERROR, 700 "PagedSessionHome: " 701 + "failed to page out active and passive sessions.", 702 e); 703 } 704 } 705 706 707 713 private boolean isWriteThroughCache() { 714 return (pageThreshold == 0); 715 } 716 717 722 protected void debug(String msg) { 723 debug(0, msg); 724 } 725 726 732 protected void debug(int level, String msg) { 733 int dbg = Logger.DEBUG; 734 switch (level) { 735 case 1: 736 dbg = Logger.DEBUG1; 737 break; 738 case 2: 739 dbg = Logger.DEBUG2; 740 break; 741 case 3: 742 dbg = Logger.DEBUG3; 743 break; 744 case 4: 745 dbg = Logger.DEBUG4; 746 break; 747 case 5: 748 dbg = Logger.DEBUG5; 749 break; 750 case 6: 751 dbg = Logger.DEBUG6; 752 break; 753 case 7: 754 dbg = Logger.DEBUG7; 755 break; 756 case 8: 757 dbg = Logger.DEBUG8; 758 break; 759 case 9: 760 dbg = Logger.DEBUG9; 761 break; 762 default: 763 dbg = Logger.DEBUG; 764 break; 765 } 766 Enhydra.getLogChannel().write(dbg, "PersistentSessionHome(" 767 + Thread.currentThread().getName() 768 + "): " + msg); 769 } 770 } 771 772 773 | Popular Tags |