e1a455fac1263030e2180c32c8d1dfd82aeacf4b
[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.log.LoggerWrapper;
54 import mir.misc.StringUtil;
55
56 public class StoreContainer {
57   private final static int DEFAULT_SIZE = 10;
58   private static int uniqueCounter = 10000;
59
60   private LinkedList container;
61   private StoreContainerType stocType;
62   private int maxSize = DEFAULT_SIZE, uniqueId;
63   private int addCount = 0, removeCount = 0, storeOutCount;
64   private int hitCount = 0, missCount = 0;
65   private static ObjectStore o_store = ObjectStore.getInstance();
66
67   protected LoggerWrapper logger = new LoggerWrapper("Database.ObjectStore");
68
69   // avoid construction without parameters
70   private StoreContainer() {}
71
72
73   public StoreContainer(StoreContainerType stoc_type) {
74     this.uniqueId = ++uniqueCounter;
75     this.stocType = stoc_type;
76     this.container = new LinkedList();
77     int defaultSize = stoc_type.getDefaultSize();
78     String confProperty = stoc_type.getConfPrefix() + ".DefaultSize";
79     String confedSize = o_store.getConfProperty(confProperty);
80     if (confedSize != null) {
81       this.maxSize = StringUtil.parseInt(confedSize, defaultSize);
82     }
83   }
84
85   public StoreContainer(StoreContainerType stoc_type, int maxSize) {
86     this();
87     this.maxSize = maxSize;
88   }
89
90   public synchronized StorableObject use(StoreIdentifier sid) {
91     int hit = container.indexOf(sid);
92     if (hit >= 0) {
93       StoreIdentifier hitSid = (StoreIdentifier) container.get(hit);
94       if (hitSid != null) {
95         hitCount++;
96         return hitSid.use();
97       }
98     }
99     missCount++;
100     return null;
101   }
102
103   public boolean has(StoreIdentifier sid) {
104     return container.contains(sid);
105   }
106
107   public void add(StoreIdentifier sid) {
108     if (sid != null && sid.hasReference()) {
109       if (has(sid)) {
110         moveToHead(sid);
111         logger.debug("OBJECTStore: tried to add sid " + sid.toString() + " that was already in store.");
112       }
113       else {
114         container.addFirst(sid);
115         shrinkIfNecessary();
116         addCount++;
117       }
118     }
119   }
120
121   /**
122    *  Method:       invalidate(StorableObject sto)
123    *  Description:  finds @see StorableObject, propagates invalidation to
124    *                @see StoreIdentifier and removes StoreIdentifier from
125    *                list.
126    */
127   public synchronized void invalidate(StoreIdentifier search_sid) {
128     if (search_sid != null) {
129       int hit = container.indexOf(search_sid);
130       if (hit >= 0) {
131         StoreIdentifier sid = (StoreIdentifier) container.get(hit);
132         container.remove(sid);
133         sid.invalidate();
134         removeCount++;
135       }
136     }
137   }
138
139   public synchronized void invalidate() {
140     StoreIdentifier sid;
141     while (container.size() > 0) {
142       sid = (StoreIdentifier) container.getLast();
143       container.removeLast();
144       sid.invalidate();
145     }
146   }
147
148   /**
149    *  Method:       setSize
150    *  Description:  readjusts StoreContainer size to value.
151    *
152    */
153   public void setSize(int size) {
154     if (size < 0)
155       return;
156     shrinkToSize(size);
157     this.maxSize = size;
158   }
159
160   private void shrinkIfNecessary() {
161     shrinkToSize(maxSize);
162   }
163
164   private void shrinkToSize(int size) {
165     if (size < container.size()) {
166       // shrink
167       while (size < container.size()) {
168         StoreIdentifier sid = (StoreIdentifier) container.getLast();
169         container.remove(sid);
170         sid.release();
171         storeOutCount++;
172       }
173     }
174   }
175
176   private synchronized void moveToHead(StoreIdentifier sid) {
177     if (sid != null) {
178       container.remove(sid);
179       container.addFirst(sid);
180     }
181   }
182
183   /**
184    *  Method:       toString()
185    *  Description:  gives out statistical Information, viewable via
186    *                @see ServletStoreInfo
187    *
188    *  @return       String
189    */
190   public String toString() {
191     return toHtml(null);
192   }
193
194   public String toHtml(HttpServletRequest req) {
195     boolean showingContent = false;
196     float hitRatio = 0;
197     long divisor = hitCount + missCount;
198     if (divisor > 0)
199       hitRatio = (float) hitCount / (float) divisor;
200     hitRatio *= 100;
201
202     StringBuffer sb = new StringBuffer("StoreContainer id: ");
203     sb.append(uniqueId).append(" for ");
204     sb.append(stocType.toString());
205     if (req != null) {
206       String show = req.getParameter("stoc_show");
207       if (show != null && show.equals("" + uniqueId)) {
208         // show all entries in container
209         sb.append(" [<b>showing</b>]");
210         showingContent = true;
211       }
212       else
213         sb.append(" [<a href=\"?stoc_show=" + uniqueId + "\">show</a>]");
214     }
215     sb.append("\n  [current/maximum size: ");
216     sb.append(container.size()).append("/").append(maxSize);
217     sb.append("]\n  [added/stored out/removed: ").append(addCount).append("/");
218     sb.append(storeOutCount).append("/").append(removeCount).append(
219         "]\n  [hit/miss/ratio: ");
220     sb.append(hitCount).append("/").append(missCount).append("/");
221     sb.append(hitRatio).append("%]\n");
222
223     if (showingContent) {
224       sb.append("  <b>Container contains following references:</b>\n  ");
225       ListIterator it = container.listIterator();
226       while (it.hasNext()) {
227         StoreIdentifier sid = (StoreIdentifier) it.next();
228         sb.append(sid.toString()).append("\n  ");
229       }
230       sb.append("<b>End of List</b>\n\n");
231
232     }
233
234     return sb.toString();
235   }
236
237 }