1 /*
   2  * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.corba.se.impl.interceptors;
  27 
  28 import org.omg.CORBA.CompletionStatus;
  29 import org.omg.CORBA.INTERNAL;
  30 import org.omg.PortableInterceptor.Current;
  31 import org.omg.PortableInterceptor.InvalidSlot;
  32 
  33 import com.sun.corba.se.impl.corba.AnyImpl;
  34 
  35 import com.sun.corba.se.impl.logging.InterceptorsSystemException;
  36 import com.sun.corba.se.spi.logging.CORBALogDomains;
  37 
  38 import com.sun.corba.se.spi.orb.ORB;
  39 
  40 /**
  41  * SlotTableStack is the container of SlotTable instances for each thread
  42  */
  43 public class SlotTableStack
  44 {
  45     // SlotTablePool is the container for reusable SlotTables'
  46     private class SlotTablePool {
  47 
  48         // Contains a list of reusable SlotTable
  49         private SlotTable[] pool;
  50 
  51         // High water mark for the pool
  52         // If the pool size reaches this limit then putSlotTable will
  53         // not put SlotTable to the pool.
  54         private final int  HIGH_WATER_MARK = 5;
  55 
  56         // currentIndex points to the last SlotTable in the list
  57         private int currentIndex;
  58 
  59         SlotTablePool( ) {
  60             pool = new SlotTable[HIGH_WATER_MARK];
  61             currentIndex = 0;
  62         }
  63 
  64         /**
  65          * Puts SlotTable to the re-usable pool.
  66          */
  67         void putSlotTable( SlotTable table ) {
  68             // If there are enough SlotTables in the pool, then don't add
  69             // this table to the pool.
  70             if( currentIndex >= HIGH_WATER_MARK ) {
  71                 // Let the garbage collector collect it.
  72                 return;
  73             }
  74             pool[currentIndex] = table;
  75             currentIndex++;
  76         }
  77 
  78         /**
  79          * Gets SlotTable from the re-usable pool.
  80          */
  81         SlotTable getSlotTable( ) {
  82             // If there are no entries in the pool then return null
  83             if( currentIndex == 0 ) {
  84                 return null;
  85             }
  86             // Works like a stack, Gets the last one added first
  87             currentIndex--;
  88             return pool[currentIndex];
  89         }
  90     }
  91 
  92     // Contains all the active SlotTables for each thread.
  93     // The List is made to behave like a stack.
  94     private java.util.List tableContainer;
  95 
  96     // Keeps track of number of PICurrents in the stack.
  97     private int currentIndex;
  98 
  99     // For Every Thread there will be a pool of re-usable SlotTables'
 100     // stored in SlotTablePool
 101     private SlotTablePool tablePool;
 102 
 103     // The ORB associated with this slot table stack
 104     private ORB orb;
 105 
 106     private InterceptorsSystemException wrapper ;
 107 
 108     /**
 109      * Constructs the stack and and SlotTablePool
 110      */
 111     SlotTableStack( ORB orb, SlotTable table ) {
 112        this.orb = orb;
 113        wrapper = InterceptorsSystemException.get( orb, CORBALogDomains.RPC_PROTOCOL ) ;
 114 
 115        currentIndex = 0;
 116        tableContainer = new java.util.ArrayList( );
 117        tablePool = new SlotTablePool( );
 118        // SlotTableStack will be created with one SlotTable on the stack.
 119        // This table is used as the reference to query for number of
 120        // allocated slots to create other slottables.
 121        tableContainer.add( currentIndex, table );
 122        currentIndex++;
 123     }
 124 
 125 
 126     /**
 127      * pushSlotTable  pushes a fresh Slot Table on to the stack by doing the
 128      * following,
 129      * 1: Checks to see if there is any SlotTable in SlotTablePool
 130      *    If present then use that instance to push into the SlotTableStack
 131      *
 132      * 2: If there is no SlotTable in the pool, then creates a new one and
 133      *    pushes that into the SlotTableStack
 134      */
 135     void pushSlotTable( ) {
 136         SlotTable table = tablePool.getSlotTable( );
 137         if( table == null ) {
 138             // get an existing PICurrent to get the slotSize
 139             SlotTable tableTemp = peekSlotTable();
 140             table = new SlotTable( orb, tableTemp.getSize( ));
 141         }
 142         // NOTE: Very important not to always "add" - otherwise a memory leak.
 143         if (currentIndex == tableContainer.size()) {
 144             // Add will cause the table to grow.
 145             tableContainer.add( currentIndex, table );
 146         } else if (currentIndex > tableContainer.size()) {
 147             throw wrapper.slotTableInvariant( new Integer( currentIndex ),
 148                 new Integer( tableContainer.size() ) ) ;
 149         } else {
 150             // Set will override unused slots.
 151             tableContainer.set( currentIndex, table );
 152         }
 153         currentIndex++;
 154     }
 155 
 156     /**
 157      * popSlotTable does the following
 158      * 1: pops the top SlotTable in the SlotTableStack
 159      *
 160      * 2: resets the slots in the SlotTable which resets the slotvalues to
 161      *    null if there are any previous sets.
 162      *
 163      * 3: puts the reset SlotTable into the SlotTablePool to reuse
 164      */
 165     void  popSlotTable( ) {
 166         if( currentIndex <= 1 ) {
 167             // Do not pop the SlotTable, If there is only one.
 168             // This should not happen, But an extra check for safety.
 169             throw wrapper.cantPopOnlyPicurrent() ;
 170         }
 171         currentIndex--;
 172         SlotTable table = (SlotTable)tableContainer.get( currentIndex );
 173         tableContainer.set( currentIndex, null ); // Do not leak memory.
 174         table.resetSlots( );
 175         tablePool.putSlotTable( table );
 176     }
 177 
 178     /**
 179      * peekSlotTable gets the top SlotTable from the SlotTableStack without
 180      * popping.
 181      */
 182     SlotTable peekSlotTable( ) {
 183        return (SlotTable) tableContainer.get( currentIndex - 1);
 184     }
 185 
 186 }
 187 
 188 // End of file.