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