9ad70f70421d0888270ee2fb5e300d409a336536
[mir.git] / source / mir / storage / store / StoreContainer.java
1 /*
2  * Copyright (C) 2001, 2002 The Mir-coders group
3  *
4  * This file is part of Mir.
5  *
6  * Mir is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Mir is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Mir; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * In addition, as a special exception, The Mir-coders gives permission to link
21  * the code of this program with  any library licensed under the Apache Software License, 
22  * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library 
23  * (or with modified versions of the above that use the same license as the above), 
24  * and distribute linked combinations including the two.  You must obey the 
25  * GNU General Public License in all respects for all of the code used other than 
26  * the above mentioned libraries.  If you modify this file, you may extend this 
27  * exception to your version of the file, but you are not obligated to do so.  
28  * If you do not wish to do so, delete this exception statement from your version.
29  */
30
31 package mir.storage.store;
32
33 /**
34  * Title:         StoreContainer
35  *
36  * Description:   This is the bucket object for one type of StorableObjects,
37  *                mainy a linked list of StoreIdenfiers. On use or creation
38  *                an object stored in StoreIdentifier is put to head of the
39  *                list. if maximum size of the list is reached, the
40  *                StoreIdentifier at the end of the list is released.
41  *
42  * Copyright:     Copyright (c) 2002
43  * Company:       indy
44  * @author        //rk
45  * @version 1.0
46  */
47
48 import java.util.LinkedList;
49 import java.util.ListIterator;
50
51 import javax.servlet.http.HttpServletRequest;
52
53 import mir.config.MirPropertiesConfiguration;
54 import mir.config.MirPropertiesConfiguration.PropertiesConfigExc;
55 import mir.log.LoggerWrapper;
56 import mir.misc.StringUtil;
57
58 public class StoreContainer {
59   private final static int DEFAULT_SIZE = 10;
60   private static int uniqueCounter = 10000;
61
62   private LinkedList container;
63   private StoreContainerType stocType;
64   private int maxSize = DEFAULT_SIZE, uniqueId;
65   private int addCount = 0, removeCount = 0, storeOutCount;
66   private int hitCount = 0, missCount = 0;
67   private static ObjectStore o_store = ObjectStore.getInstance();
68
69   protected LoggerWrapper logger = new LoggerWrapper("Database");
70   private MirPropertiesConfiguration configuration;
71
72   // avoid construction without parameters
73   private StoreContainer() {};
74
75
76   public StoreContainer(StoreContainerType stoc_type) {
77     this.uniqueId = ++uniqueCounter;
78     this.stocType = stoc_type;
79     this.container = new LinkedList();
80     try {
81                         configuration = MirPropertiesConfiguration.instance();
82                 } catch (PropertiesConfigExc e) {
83                         e.printStackTrace(logger.asPrintWriter(LoggerWrapper.ERROR_MESSAGE));
84                 }
85     int defaultSize = stoc_type.getDefaultSize();
86     String confProperty = stoc_type.getConfPrefix() + ".DefaultSize";
87     String confedSize = configuration.getString(confProperty);
88     if (confedSize != null) {
89       this.maxSize = StringUtil.parseInt(confedSize, defaultSize);
90     }
91   }
92
93   public StoreContainer(StoreContainerType stoc_type, int maxSize) {
94     this();
95     this.maxSize = maxSize;
96   }
97
98   public synchronized StorableObject use(StoreIdentifier sid) {
99     int hit = container.indexOf(sid);
100     if (hit >= 0) {
101       StoreIdentifier hitSid = (StoreIdentifier) container.get(hit);
102       if (hitSid != null) {
103         hitCount++;
104         return hitSid.use();
105       }
106     }
107     missCount++;
108     return null;
109   }
110
111   public boolean has(StoreIdentifier sid) {
112     return container.contains(sid);
113   }
114
115   public void add(StoreIdentifier sid) {
116     if (sid != null && sid.hasReference()) {
117       if (has(sid)) {
118         moveToHead(sid);
119         logger.debug("OBJECTStore: tried to add sid " + sid.toString() + " that was already in store.");
120       }
121       else {
122         container.addFirst(sid);
123         shrinkIfNecessary();
124         addCount++;
125       }
126     }
127   }
128
129   /**
130    *  Method:       invalidate(StorableObject sto)
131    *  Description:  finds @see StorableObject, propagates invalidation to
132    *                @see StoreIdentifier and removes StoreIdentifier from
133    *                list.
134    */
135   public synchronized void invalidate(StoreIdentifier search_sid) {
136     if (search_sid != null) {
137       int hit = container.indexOf(search_sid);
138       if (hit >= 0) {
139         StoreIdentifier sid = (StoreIdentifier) container.get(hit);
140         container.remove(sid);
141         sid.invalidate();
142         removeCount++;
143       }
144     }
145   }
146
147   public synchronized void invalidate() {
148     StoreIdentifier sid;
149     while (container.size() > 0) {
150       sid = (StoreIdentifier) container.getLast();
151       container.removeLast();
152       sid.invalidate();
153     }
154   }
155
156   /**
157    *  Method:       setSize
158    *  Description:  readjusts StoreContainer size to value.
159    *
160    */
161   public void setSize(int size) {
162     if (size < 0)
163       return;
164     shrinkToSize(size);
165     this.maxSize = size;
166   }
167
168   private void shrinkIfNecessary() {
169     shrinkToSize(maxSize);
170   }
171
172   private void shrinkToSize(int size) {
173     if (size < container.size()) {
174       // shrink
175       while (size < container.size()) {
176         StoreIdentifier sid = (StoreIdentifier) container.getLast();
177         container.remove(sid);
178         sid.release();
179         storeOutCount++;
180       }
181     }
182   }
183
184   private synchronized void moveToHead(StoreIdentifier sid) {
185     if (sid != null) {
186       container.remove(sid);
187       container.addFirst(sid);
188     }
189   }
190
191   /**
192    *  Method:       toString()
193    *  Description:  gives out statistical Information, viewable via
194    *                @see ServletStoreInfo.
195    *
196    *  @return       String
197    */
198   public String toString() {
199     return toHtml(null);
200   }
201
202   public String toHtml(HttpServletRequest req) {
203     boolean showingContent = false;
204     float hitRatio = 0;
205     long divisor = hitCount + missCount;
206     if (divisor > 0)
207       hitRatio = (float) hitCount / (float) divisor;
208     hitRatio *= 100;
209
210     StringBuffer sb = new StringBuffer("StoreContainer id: ");
211     sb.append(uniqueId).append(" for ");
212     sb.append(stocType.toString());
213     if (req != null) {
214       String show = req.getParameter("stoc_show");
215       if (show != null && show.equals("" + uniqueId)) {
216         // show all entries in container
217         sb.append(" [<b>showing</b>]");
218         showingContent = true;
219       }
220       else
221         sb.append(" [<a href=\"?stoc_show=" + uniqueId + "\">show</a>]");
222     }
223     sb.append("\n  [current/maximum size: ");
224     sb.append(container.size()).append("/").append(maxSize);
225     sb.append("]\n  [added/stored out/removed: ").append(addCount).append("/");
226     sb.append(storeOutCount).append("/").append(removeCount).append(
227         "]\n  [hit/miss/ratio: ");
228     sb.append(hitCount).append("/").append(missCount).append("/");
229     sb.append(hitRatio).append("%]\n");
230
231     if (showingContent) {
232       sb.append("  <b>Container contains following references:</b>\n  ");
233       ListIterator it = container.listIterator();
234       while (it.hasNext()) {
235         StoreIdentifier sid = (StoreIdentifier) it.next();
236         sb.append(sid.toString()).append("\n  ");
237       }
238       sb.append("<b>End of List</b>\n\n");
239
240     }
241
242     return sb.toString();
243   }
244
245 }