KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jalisto > se > impl > meta > InternalMetaRepositoryImpl


1 /*
2  * Jalisto - JAva LIght STOrage
3  * Copyright (C) 2000-2005 Xcalia http://www.xcalia.com
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
18  *
19  * Xcalia
20  * 71, rue Desnouettes
21  * 75014 Paris - France
22  * http://www.xcalia.com
23  */

24 package org.objectweb.jalisto.se.impl.meta;
25
26 import org.objectweb.jalisto.se.api.Session;
27 import org.objectweb.jalisto.se.api.query.FieldDescription;
28 import org.objectweb.jalisto.se.api.*;
29 import org.objectweb.jalisto.se.api.internal.InternalPhysicalFileAccess;
30 import org.objectweb.jalisto.se.api.internal.SessionInternal;
31 import org.objectweb.jalisto.se.api.internal.InternalMetaRepository;
32 import org.objectweb.jalisto.se.api.internal.InternalFactory;
33 import org.objectweb.jalisto.se.exception.JalistoException;
34 import org.objectweb.jalisto.se.exception.SchemaException;
35 import org.objectweb.jalisto.se.impl.server.IdentityProvider;
36 import org.objectweb.jalisto.se.impl.InFileAddress;
37 import org.objectweb.jalisto.se.impl.server.page.ClassPage;
38 import org.objectweb.jalisto.se.impl.trace.Trace;
39 import org.objectweb.jalisto.se.JalistoFactory;
40
41 import java.util.*;
42
43 public class InternalMetaRepositoryImpl implements InternalMetaRepository {
44
45     private InternalMetaRepositoryImpl(JalistoProperties properties) {
46         InternalFactory internalFactory = JalistoFactory.getInternalFactory();
47         tracer = internalFactory.getTracer(properties);
48         tracer.println(Trace.LOGICAL, "MetaRepositoryImpl : create new instance");
49
50         sessions = new ArrayList();
51
52         isMono = properties.isMonoImplementation();
53
54         oidProvider = internalFactory.getIdentityProvider(properties);
55         physicalAccess = internalFactory.getInternalPhysicalAccess(properties);
56         classPageSize = properties.getClassPageSize();
57     }
58
59     public void addSession(SessionInternal session) {
60         synchronized (sessions) {
61             if (isMono) {
62                 sessions.clear();
63             }
64             if (!sessions.contains(session)) {
65                 sessions.add(session);
66             }
67         }
68     }
69
70     public void removeSession(SessionInternal session) {
71         sessions.remove(session);
72     }
73
74
75     public Map getClassMetas() {
76         return classMetas;
77     }
78
79     public Map getClassTable() {
80         return classTable;
81     }
82
83     /**
84      * *************************** methods from MetaRepository ********************************
85      */

86
87     public void checkNoActive(String JavaDoc message) {
88         for (short i = 0; i < sessions.size(); i++) {
89             if (((SessionInternal) sessions.get(i)).currentTransaction().isActive()) {
90                 throw new SchemaException(message+((SessionInternal) sessions.get(i)).getSessionId());
91             }
92         }
93     }
94
95     public void checkNoSessions(String JavaDoc message) {
96         if (!sessions.isEmpty()) {
97             throw new JalistoException(message);
98         }
99     }
100
101     public void closeAllSessions() {
102         ArrayList checkedSessions = new ArrayList();
103         checkedSessions.addAll(sessions);
104         for (short i = 0; i < checkedSessions.size(); i++) {
105             SessionInternal s = (SessionInternal) sessions.get(i);
106             if (s.currentTransaction().isActive()) {
107                 s.currentTransaction().rollback();
108             }
109             if (s.isOpen()) {
110                 s.closeSession();
111             }
112         }
113     }
114
115     public void defineClass(Session session, ClassDescription classMetaDescription) {
116         try {
117             ClassDescription oldMeta = getMetaData(classMetaDescription.getClassName());
118             if (!oldMeta.equals(classMetaDescription)) {
119                 throw new SchemaException(
120                         "Class " + classMetaDescription.getClassName() + " is already define in base with other metadescription");
121             }
122             return;
123         } catch (SchemaException e) {
124             if (!e.getMessage().endsWith("is not define in base")) {
125                 throw e;
126             }
127         }
128         session.currentTransaction().begin();
129         try {
130             Object JavaDoc clid = createClidFromClassName(classMetaDescription.getClassName());
131             writePersistentClassMetaDescription(clid, (ClassDescriptionImpl) classMetaDescription);
132         } catch (SchemaException fse) {
133             // class already define
134
}
135         session.currentTransaction().commit();
136     }
137
138     public ClassDescription getMetaData(String JavaDoc className) {
139         Object JavaDoc clid = getClidFromClassName(className);
140         return getPersistentClassMetaDescription(clid);
141     }
142
143     public void removeClass(Session session, String JavaDoc className) {
144         checkNoActive(MODIFY_DURING_TRANSACTION_MESSAGE);
145
146         Object JavaDoc sessionId = session.getInternalSession().getSessionId();
147         Object JavaDoc clid = classTable.get(className);
148
149         if (clid == null) {
150             throw new SchemaException("Class "+className+" is not define in base");
151         }
152
153         session.currentTransaction().begin();
154         Iterator extent =
155                 session.getInternalSession().getOidTable().getFloidsFromClid(sessionId, clid, true).iterator();
156         while (extent.hasNext()) {
157             try {
158                 session.deleteObjectByOid(extent.next());
159             } catch (Exception JavaDoc e) {
160                 System.out.println("PROBLEM DURING CLEANING OF PERSISTENT INSTANCES");
161                 e.printStackTrace();
162             }
163         }
164
165         classTable.remove(className);
166         InFileAddress ifa = (InFileAddress) clidIndex.remove(clid);
167         ClassDescriptionImpl meta = (ClassDescriptionImpl) classMetas.remove(clid);
168         physicalAccess.writeObjectInBase(META_REPOSITORY_IFA, classTable, true);
169         physicalAccess.writeObjectInBase(OID_IFA_CLID_INDEX_IFA, clidIndex, true);
170
171         ClassPage classPage = (ClassPage) physicalAccess.readFileObjectAt(ifa);
172         classPage.setDataAt(ifa, null);
173         physicalAccess.updateFileObject(classPage);
174
175         if (session.getQueryManager() != null) {
176             session.getQueryManager().getIndexManager().deleteIndexesOnClass(meta);
177         }
178
179         session.currentTransaction().commit();
180     }
181
182
183     public void addField(Session session, String JavaDoc className, FieldDescription fieldDescription) {
184         checkNoActive(MODIFY_DURING_TRANSACTION_MESSAGE);
185
186         session.currentTransaction().begin();
187         short index = fieldDescription.getIndex();
188         Object JavaDoc clid = getClidFromClassName(className);
189         ClassDescription meta = getPersistentClassMetaDescription(clid);
190         if (meta == null) {
191             throw new SchemaException("meta data of class " + className + " null in base");
192         }
193         if ((index < 0) || (index > meta.getNbrFields())) {
194             throw new SchemaException("index " + index + " out of range from 0 to " + meta.getNbrFields());
195         }
196
197         Iterator oids = session.getExtent(className).readFully().iterator();
198         while (oids.hasNext()) {
199             Object JavaDoc oid = oids.next();
200             Object JavaDoc[] o = session.readObjectByOid(oid);
201             Object JavaDoc[] oo = new Object JavaDoc[o.length + 1];
202             for (int i = 0; i < oo.length; i++) {
203                 if (i < index) {
204                     oo[i] = o[i];
205                 } else if (i == index) {
206                     oo[i] = null;
207                 } else {
208                     oo[i] = o[i - 1];
209                 }
210             }
211             session.updateObjectByOid(oid, oo);
212         }
213         meta.addField(fieldDescription);
214         writePersistentClassMetaDescription(clid, meta);
215         session.currentTransaction().commit();
216     }
217
218     public String JavaDoc[] getFieldNames(String JavaDoc className) {
219         return getMetaData(className).getFieldNames();
220     }
221
222     public void renameField(Session session, String JavaDoc className, String JavaDoc oldFieldName, String JavaDoc newFieldName) {
223         checkNoActive(MODIFY_DURING_TRANSACTION_MESSAGE);
224
225         session.currentTransaction().begin();
226         Object JavaDoc clid = getClidFromClassName(className);
227         int index = getIndex(className, oldFieldName);
228         ClassDescription meta = getPersistentClassMetaDescription(clid);
229
230         if (meta == null) {
231             throw new SchemaException("meta data of class " + className + " null in base");
232         }
233         if ((index < 0) || (index > (meta.getNbrFields() - 1))) {
234             throw new SchemaException("index " + index + " out of range from 0 to " + (meta.getNbrFields() - 1));
235         }
236
237         String JavaDoc[] fieldNames = meta.getFieldNames();
238         fieldNames[index] = newFieldName;
239         writePersistentClassMetaDescription(clid, meta);
240         session.currentTransaction().commit();
241     }
242
243     public void removeField(Session session, String JavaDoc className, String JavaDoc fieldName) {
244         checkNoActive(MODIFY_DURING_TRANSACTION_MESSAGE);
245
246         session.currentTransaction().begin();
247         Object JavaDoc clid = getClidFromClassName(className);
248         int index = getIndex(className, fieldName);
249         ClassDescription meta = getPersistentClassMetaDescription(clid);
250
251         if (meta == null) {
252             throw new SchemaException("meta data of class " + className + " null in base");
253         }
254         if ((index < 0) || (index > (meta.getNbrFields() - 1))) {
255             throw new SchemaException("index " + index + " out of range from 0 to " + (meta.getNbrFields() - 1));
256         }
257
258         Iterator oids = session.getExtent(className).readFully().iterator();
259         while (oids.hasNext()) {
260             Object JavaDoc oid = oids.next();
261             Object JavaDoc[] o = session.readObjectByOid(oid);
262             Object JavaDoc[] oo = new Object JavaDoc[o.length - 1];
263             for (int i = 0; i < oo.length; i++) {
264                 if (i < index) {
265                     oo[i] = o[i];
266                 } else {
267                     oo[i] = o[i + 1];
268                 }
269             }
270             session.updateObjectByOid(oid, oo);
271         }
272         meta.removeField(index);
273         writePersistentClassMetaDescription(clid, meta);
274         session.currentTransaction().commit();
275     }
276
277
278     public int getIndex(String JavaDoc className, String JavaDoc fieldName) {
279         String JavaDoc[] fieldNames = getMetaData(className).getFieldNames();
280         for (int i = 0; i < fieldNames.length; i++) {
281             if (fieldNames[i].equalsIgnoreCase(fieldName)) {
282                 return i;
283             }
284         }
285         return -1;
286     }
287
288
289     public Collection getAllClassNames() {
290         return classTable.keySet();
291     }
292
293
294     /**
295      * ***************************** Page access methods ****************************************
296      */

297
298     public ClassDescription getPersistentClassMetaDescription(Object JavaDoc clid) {
299         ClassDescriptionImpl meta = (ClassDescriptionImpl) classMetas.get(clid);
300         if (meta == null) {
301             meta = internalGetPersistentClassMetaDescription(clid);
302             classMetas.put(clid, meta);
303         }
304         return meta;
305     }
306
307     // allocation is done
308
public void writePersistentClassMetaDescription(Object JavaDoc clid, ClassDescription metaDescription) {
309         tracer.println(Trace.LOGICAL, "MetaRepositoryImpl : writePersistentClassMetaDescription({0}, {1})", clid,
310                        metaDescription);
311         ((ClassDescriptionImpl)metaDescription).setRepository(this);
312         // get ifa of the page where instance is stored
313
InFileAddress classIfa = (InFileAddress) clidIndex.get(clid);
314         ClassPage classPage = (ClassPage) physicalAccess.readFileObjectAt(classIfa);
315         classPage.setDataAt(classIfa, metaDescription);
316         physicalAccess.updateFileObject(classPage);
317         classMetas.put(clid, metaDescription);
318     }
319
320     // allocation is done
321
public void writePersistentClassMetaDescription(ClassDescriptionImpl metaDescription) {
322         Object JavaDoc clid = getClidFromClassName(metaDescription.getClassName());
323         writePersistentClassMetaDescription(clid, metaDescription);
324     }
325
326     private void allocateNewClidIfa(Object JavaDoc clid) {
327         tracer.println(Trace.LOGICAL, "MetaRepositoryImpl : allocateNewClidIfa({0})", clid);
328         if (currentAvalaibleClassPage.getIndex() == (classPageSize - 1)) {
329             currentAvalaibleClassPage = new InFileAddress(getNewClassPageAddress());
330             ClassPage classPage = new ClassPage(classPageSize);
331             classPage.setIfa(currentAvalaibleClassPage);
332             physicalAccess.insertFileObject(classPage);
333         } else {
334             currentAvalaibleClassPage.incrementeFileIndex();
335         }
336         clidIndex.put(clid, currentAvalaibleClassPage.getClone());
337         updateStateInBase(true);
338         physicalAccess.writeObjectInBase(OID_IFA_CLID_INDEX_IFA, clidIndex, true);
339     }
340
341     private ClassDescriptionImpl internalGetPersistentClassMetaDescription(Object JavaDoc clid) {
342         tracer.println(Trace.LOGICAL, "MetaRepositoryImpl : getPersistentClassMetaDescription({0})", clid);
343         // get ifa of the system page
344
InFileAddress classIfa = (InFileAddress) clidIndex.get(clid);
345         ClassPage classPage = (ClassPage) physicalAccess.readFileObjectAt(classIfa);
346         // get and return the page info
347
ClassDescriptionImpl classMetaDescription = (ClassDescriptionImpl) classPage.getDataAt(classIfa);
348         classMetaDescription.setRepository(this);
349         return classMetaDescription;
350     }
351
352     /**
353      * ************************************* CLID METHODS ********************************************
354      */

355
356     public String JavaDoc getClassNameFromClid(Object JavaDoc clid) {
357         Iterator keys = classTable.keySet().iterator();
358         while (keys.hasNext()) {
359             Object JavaDoc key = keys.next();
360             if (classTable.get(key).equals(clid)) {
361                 return (String JavaDoc) key;
362             }
363         }
364         return null;
365     }
366
367     public Object JavaDoc getClidFromClassName(String JavaDoc fullClassName) {
368         Object JavaDoc result = classTable.get(fullClassName);
369         if (result == null) {
370             throw new SchemaException("Class " + fullClassName + " is not define in base");
371         }
372         return result;
373     }
374
375     private String JavaDoc getNewClassPageAddress() {
376         return "cp" + (classPageIndex++);
377     }
378
379     private Object JavaDoc createClidFromClassName(String JavaDoc fullClassName) {
380         if (!classTable.containsKey(fullClassName)) {
381             Object JavaDoc newClid = oidProvider.getNewClid();
382             classTable.put(fullClassName, newClid);
383             allocateNewClidIfa(newClid);
384             updateStateInBase(true);
385             physicalAccess.writeObjectInBase(META_REPOSITORY_IFA, classTable, true);
386             return newClid;
387         }
388         throw new SchemaException("class " + fullClassName + " is already defined in base");
389     }
390
391     /**
392      * ******************************* INITIALIZATION ***************************************
393      */

394
395     private void init(short classPageSize) {
396         classTable = new HashMap();
397         clidIndex = new Hashtable();
398         classPageIndex = 0;
399         currentAvalaibleClassPage = new InFileAddress(getNewClassPageAddress());
400         currentAvalaibleClassPage.setIndex(-1);
401
402         ClassPage firstClassPage = new ClassPage(classPageSize);
403         firstClassPage.setIfa(currentAvalaibleClassPage);
404         physicalAccess.insertFileObject(firstClassPage);
405
406         updateStateInBase(false);
407         physicalAccess.writeObjectInBase(META_REPOSITORY_IFA, classTable, false);
408         physicalAccess.writeObjectInBase(OID_IFA_CLID_INDEX_IFA, clidIndex, false);
409
410         classMetas = new HashMap();
411     }
412
413     private void getStateFromBase() {
414         classTable = (Map) physicalAccess.readFileObjectAt(META_REPOSITORY_IFA).getData();
415
416         clidIndex = (Map) physicalAccess.readFileObjectAt(OID_IFA_CLID_INDEX_IFA).getData();
417
418         Object JavaDoc[] datas = (Object JavaDoc[]) physicalAccess.readFileObjectAt(MR_STATE_IFA).getData();
419         currentAvalaibleClassPage = (InFileAddress) datas[0];
420         classPageIndex = ((Integer JavaDoc) datas[1]).intValue();
421
422         classMetas = new HashMap();
423         Iterator clids = classTable.values().iterator();
424         while (clids.hasNext()) {
425             Object JavaDoc clid = clids.next();
426             ClassDescription meta = getPersistentClassMetaDescription(clid);
427             classMetas.put(clid, meta);
428         }
429     }
430
431     public synchronized void updateStateInBase(boolean isUpdate) {
432         Object JavaDoc[] datas = new Object JavaDoc[2];
433         datas[0] = currentAvalaibleClassPage;
434         datas[1] = new Integer JavaDoc(classPageIndex);
435         physicalAccess.writeObjectInBase(MR_STATE_IFA, datas, isUpdate);
436     }
437
438     public static InternalMetaRepositoryImpl getAnMetaRepository(JalistoProperties properties) {
439         InternalMetaRepositoryImpl repository = new InternalMetaRepositoryImpl(properties);
440         try {
441             // load it from base
442
repository.getStateFromBase();
443         } catch (Exception JavaDoc e) {
444             repository.init(properties.getClassPageSize());
445         }
446         return repository;
447     }
448
449     private ArrayList sessions;
450     private IdentityProvider oidProvider;
451     private InternalPhysicalFileAccess physicalAccess;
452
453     private Map classMetas; // clid -> classMeta
454
private Map classTable; // classname -> clid
455
private Map clidIndex; // clid -> class meta's ifa
456

457     private InFileAddress currentAvalaibleClassPage;
458     private int classPageIndex;
459     private int classPageSize;
460
461     private boolean isMono;
462     private Trace tracer;
463
464
465     private static final InFileAddress META_REPOSITORY_IFA = new InFileAddress("metarep");
466     private static final InFileAddress OID_IFA_CLID_INDEX_IFA = new InFileAddress("clid");
467     private static final InFileAddress MR_STATE_IFA = new InFileAddress("mrstate");
468
469
470     public static final String JavaDoc MODIFY_DURING_TRANSACTION_MESSAGE = "Try to modify schema during active transaction : ";
471 }
472
Popular Tags