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