scripts/mir-setup/README: update with link to new doc on wiki
[mir.git] / source / mir / storage / store / ObjectStore.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:         ObjectStore for StorableObjects
32  * Description:   ObjectStore holds a Map of @see StoreContainer for all possible
33  *                @see StoreIdentifier.
34  *
35  *                @see StorageIdentifier - identitfies one object in the ObjectStore
36  *                      i.e. in its apropriate bucket. It holds a unique identifier
37  *                      of a StorableObject and a reference on the StorableObject.
38  *
39  *                @see StoreContainer - "Buckets" to store different types of Objects
40  *                      in one Container. These buckets are cofigurable via
41  *                      config.properties.
42  *
43  *                @see StoreContainerType - is a signature for all StoreContainer
44  *                      and StoreIdentifier.
45  *
46  *                @see StorableObjects - Interface Object have to implement to
47  *                      be handled by the ObjectStore
48  *
49  *                @see ServletStoreInfo - Maintenance Servlet for ObjectStore.
50  *                      Displays information about current content of the
51  *                      ObjectStore.
52  *
53  *
54  * Copyright:     Copyright (c) 2002
55  * Company:       indy
56  * @author        rk
57  * @version 1.0
58  */
59
60 import java.util.HashMap;
61 import java.util.Iterator;
62 import java.util.Map;
63 import java.util.MissingResourceException;
64
65 import javax.servlet.http.HttpServletRequest;
66
67 import mir.config.MirPropertiesConfiguration;
68 import mir.log.LoggerWrapper;
69
70 public class ObjectStore {
71
72   private final static ObjectStore INSTANCE = new ObjectStore();
73   private final static Map containerMap = new HashMap(); // StoreContainerType/StoreContainer
74   private static long storeHit = 0, storeMiss = 0;
75   private MirPropertiesConfiguration configuration;
76   private LoggerWrapper logger;
77
78   private ObjectStore() {
79     logger = new LoggerWrapper("Database.ObjectStore");
80     configuration = MirPropertiesConfiguration.instance();
81   }
82
83   public static ObjectStore getInstance() {
84     return INSTANCE;
85   }
86
87   /**
88    *  Method:       use
89    *  Description:  The ObjectStore tries to find the @see StoreIdentifier sid
90    *                and returns the stored Object.
91    *
92    *  @return       StorableObject is null when no StorableObject for the
93    *                StoreIdentifier sid is found.
94    */
95   public StorableObject use(StoreIdentifier sid) {
96     if (sid != null) {
97       StorableObject storeObject = null;
98       StoreContainer stoc = getStoreContainerForSid(sid);
99       if (stoc != null)
100         storeObject = stoc.use(sid);
101       else
102         logger.warn("container not found for: " + sid.toString());
103       if (storeObject != null) {
104         storeHit++;
105         return storeObject;
106       }
107     }
108     storeMiss++;
109     return null;
110
111   }
112
113   /**
114    *  Method:       add
115    *  Description:  A StoreIdentifier is added to the ObjectStore, if it
116    *                contains a reference to a @see StorableObject.
117    */
118   public void add(StoreIdentifier sid) {
119     if (sid != null && sid.hasReference()) {
120       // find the right StoreContainer for sid
121       StoreContainer stoc = getStoreContainerForSid(sid);
122       if (stoc == null) {
123         // we have to make new StoreContainer
124         StoreContainerType stocType = sid.getStoreContainerType();
125         stoc = new StoreContainer(stocType);
126         containerMap.put(stocType, stoc);
127       }
128       stoc.add(sid);
129     }
130   }
131
132   /**
133    *  Method:       invalidate(StorableObject sto)
134    *  Description:  ObjectStore is notified of change of a @see StorableObject
135    *                sto and invalidates all relevant cache entries.
136    */
137
138   public void invalidate(StoreIdentifier sid) {
139     // propagate invalidation to StoreContainer
140     if (sid != null) {
141       StoreContainer stoc = getStoreContainerForSid(sid);
142       stoc.invalidate(sid);
143     }
144   }
145
146   /**
147    * serves to invalidate a whole StoreContainer
148    */
149   public void invalidate(StoreContainerType stoc_type) {
150     if (stoc_type != null) {
151       StoreContainer stoc = getStoreContainerForStocType(stoc_type);
152       if (stoc != null)
153         stoc.invalidate();
154     }
155
156   }
157
158   // internal methods for StoreContainer managment
159
160   /**
161    *  Method:       getStoreContainerForSid
162    *  Description:  private method to find the right @see StoreContainer for
163    *                the @see StoreIdentifier sid.
164    *
165    *  @return       StoreContainer is null when no Container is found.
166    */
167   private StoreContainer getStoreContainerForSid(StoreIdentifier sid) {
168     // find apropriate container for a specific sid
169     if (sid != null) {
170       StoreContainerType stoc_type = sid.getStoreContainerType();
171       return getStoreContainerForStocType(stoc_type);
172     }
173
174     return null;
175   }
176
177   private StoreContainer getStoreContainerForStocType(StoreContainerType
178       stoc_type) {
179     if (stoc_type != null && containerMap.containsKey(stoc_type))
180       return (StoreContainer) containerMap.get(stoc_type);
181     return null;
182   }
183
184   private boolean has(StoreIdentifier sid) {
185     StoreContainer stoc = getStoreContainerForSid(sid);
186     return (stoc != null && stoc.has(sid)) ? true : false;
187   }
188
189   public String getConfProperty(String name) {
190     if (name != null) {
191       try {
192         return configuration.getString(name);
193       }
194       catch (MissingResourceException e) {
195         logger.error("getConfProperty: " + e.toString());
196       }
197     }
198     return null;
199   }
200
201   /**
202    *  Method:       toString()
203    *  Description:  Displays statistical information about the ObjectStore.
204        *                Further information is gathered from all @see StoreContainer
205    *
206    *  @return       String
207    */
208   public String toString() {
209     return toHtml(null);
210   }
211
212   public String toHtml(HttpServletRequest req) {
213     float hitRatio = 0;
214     long divisor = storeHit + storeMiss;
215     if (divisor > 0)
216       hitRatio = (float) storeHit / (float) divisor;
217     hitRatio *= 100;
218
219     StringBuffer sb = new StringBuffer("Mir-ObjectStore ");
220     sb.append( ( (req != null) ? html_version() : version())).append("\n");
221     sb.append("ObjectStore overall hits/misses/ratio: ").append(storeHit);
222     sb.append("/").append(storeMiss).append("/").append(hitRatio);
223     sb.append("%\nCurrently ").append(containerMap.size());
224     sb.append(" StoreContainer in use - listing information:\n");
225
226     // ask container for information
227     StoreContainer currentStoc;
228     for (Iterator it = containerMap.keySet().iterator(); it.hasNext(); ) {
229       currentStoc = (StoreContainer) containerMap.get(it.next());
230       sb.append(currentStoc.toHtml(req));
231     }
232
233     return sb.toString();
234   }
235
236   /**
237    *  Method:       html_version()
238        *  Description:  returns ObjectStore version as String for HTML representation
239    *
240    *  @return       String
241    */
242   private String html_version() {
243     return "<i>" + version() + "</i>";
244   }
245
246   /**
247    *  Method:       version()
248    *  Description:  returns ObjectStore version as String
249    *
250    *  @return       String
251    */
252   private String version() {
253     return "v_sstart3__1.0";
254   }
255
256 }