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