View Javadoc

1   package org.sourceforge.jemm.database.components;
2   
3   import java.util.HashMap;
4   import java.util.Map;
5   
6   import org.apache.log4j.Logger;
7   import org.sourceforge.jemm.collections.JemmAtomicInteger;
8   import org.sourceforge.jemm.collections.JemmList;
9   import org.sourceforge.jemm.collections.JemmMap;
10  import org.sourceforge.jemm.collections.JemmSet;
11  import org.sourceforge.jemm.database.ClassId;
12  import org.sourceforge.jemm.database.ClassInfo;
13  import org.sourceforge.jemm.database.ClientId;
14  import org.sourceforge.jemm.database.ClientThreadId;
15  import org.sourceforge.jemm.database.Database;
16  import org.sourceforge.jemm.database.DatabaseDebugIF;
17  import org.sourceforge.jemm.database.EnumId;
18  import org.sourceforge.jemm.database.EnumInfo;
19  import org.sourceforge.jemm.database.FieldInfo;
20  import org.sourceforge.jemm.database.GetObjectResp;
21  import org.sourceforge.jemm.database.LockAcquiredListener;
22  import org.sourceforge.jemm.database.ObjectSyncData;
23  import org.sourceforge.jemm.database.ObjectSyncResp;
24  import org.sourceforge.jemm.database.StructureModifiedException;
25  import org.sourceforge.jemm.database.components.interfaces.DBClassHandler;
26  import org.sourceforge.jemm.database.components.interfaces.DBClientRefHandler;
27  import org.sourceforge.jemm.database.components.interfaces.DBEnumHandler;
28  import org.sourceforge.jemm.database.components.interfaces.DBGarbageSweeper;
29  import org.sourceforge.jemm.database.components.interfaces.DBObjectHandler;
30  import org.sourceforge.jemm.database.components.interfaces.DBRootHandler;
31  import org.sourceforge.jemm.database.components.interfaces.DBUserLockHandler;
32  import org.sourceforge.jemm.database.components.types.StoredObject;
33  import org.sourceforge.jemm.lifecycle.TypeRequest;
34  import org.sourceforge.jemm.lifecycle.TypeResponse;
35  import org.sourceforge.jemm.types.ID;
36  import org.sourceforge.jemm.util.JEMMType;
37  
38  public abstract class BaseDatabase implements Database {
39  	
40  	private static final Logger LOG = Logger.getLogger(BaseDatabase.class);
41  	
42      protected final DBClassHandler classHandler;
43      protected final DBEnumHandler enumHandler;
44      protected final DBObjectHandler objectHandler;
45      protected final DBUserLockHandler userLockHandler;
46      protected final DBRootHandler rootHandler;
47      protected final DatabaseDebugIF debugHandler;
48      protected final DBClientRefHandler clientRefHandler;
49      protected final DBGarbageSweeper gcHandler;
50  
51      protected DefaultDBListTypeHandler listHandler;
52      protected DefaultDBSetTypeHandler setHandler;
53      protected DefaultDBMapTypeHandler mapHandler;
54      protected DefaultDBAtomicIntTypeHandler atomicIntHandler;
55      
56      protected final ObjectStatusListener objectStatusListener;
57      
58  	protected StorageEngine storageEngine;
59  	
60  	protected Map<ClassId,TypeHandler> typeHandlers = new HashMap<ClassId, TypeHandler>();
61  	
62  	public BaseDatabase(StorageEngine storageEngine,GCMode gcMode) {
63  		this.storageEngine = storageEngine;
64  		storageEngine.initialise();
65          classHandler = new DefaultDBClassHandler(storageEngine);
66          enumHandler = new DefaultDBEnumHandler(storageEngine);
67          clientRefHandler = new DefaultDBClientRefHandler(storageEngine);
68          objectHandler = new DefaultDBObjectHandler(storageEngine,classHandler,clientRefHandler);
69          userLockHandler = new DefaultDBUserLockHandler(storageEngine,objectHandler);
70          rootHandler = new DefaultDBRootHandler(storageEngine);
71          gcHandler  = new DefaultDBGarbageSweeper(storageEngine,objectHandler,gcMode);
72          debugHandler = new DefaultDBDebugHandler(objectHandler,clientRefHandler,gcHandler);
73      
74          objectStatusListener = gcHandler.getObjectStatusListener();
75          
76          rootHandler.setObjectStatusListener(objectStatusListener);
77          clientRefHandler.setObjectStatusListener(objectStatusListener);
78          objectHandler.setObjectStatusListener(objectStatusListener);
79          
80          // register the core types
81          ClassId setClassId = registerTypeClass(JemmSet.class);
82          ClassId mapClassId = registerTypeClass(JemmMap.class);
83          ClassId listClassId = registerTypeClass(JemmList.class);
84          ClassId atomicIntClassId = registerTypeClass(JemmAtomicInteger.class);
85          
86          listHandler = new DefaultDBListTypeHandler(listClassId,objectHandler,clientRefHandler);
87          setHandler = new DefaultDBSetTypeHandler(setClassId,objectHandler,clientRefHandler);
88          mapHandler = new DefaultDBMapTypeHandler(mapClassId,objectHandler,clientRefHandler,setClassId,listClassId);
89          atomicIntHandler = new DefaultDBAtomicIntTypeHandler(atomicIntClassId,objectHandler,clientRefHandler);
90          
91          registerTypeHandler(setClassId,setHandler);
92          registerTypeHandler(mapClassId,mapHandler);
93          registerTypeHandler(listClassId,listHandler);
94          registerTypeHandler(atomicIntClassId,atomicIntHandler);
95  	}
96  
97  	private ClassId registerTypeClass(Class<? extends JEMMType> typeClass) {
98  		ClassId classId;
99  		try {
100 			classId = this.registerClass(null, 
101 					new ClassInfo(typeClass));			
102 		} catch (StructureModifiedException e) {
103 			LOG.error("Unable to register type class " + typeClass,e);
104 			throw new RuntimeException(e);
105 		}
106 		return classId;
107 	}
108 
109 	private void registerTypeHandler(ClassId classId,TypeHandler handler) {
110 		typeHandlers.put(classId, handler);
111 		objectHandler.registerType(classId,handler);
112 	}
113 
114     @Override
115     public void setClientLockAcquiredListener(ClientId clientId,LockAcquiredListener listener) {
116         userLockHandler.setClientListener(clientId,listener);
117     }
118 
119     @Override
120     public void acquireLock(ClientThreadId threadId, ID jemmId) {
121         userLockHandler.acquire(threadId,jemmId);
122     }
123 
124     @Override
125     public ClassInfo getClassInfo(ClientId clientId,ClassId classId) {
126         return classHandler.get(classId);
127     }
128 
129     @Override
130     public EnumInfo getEnumInfo(ClientId clientId,EnumId enumId) {
131         if(clientId == null)
132             throw new IllegalArgumentException("clientId may not be null");
133         
134         return enumHandler.get(enumId);
135     }
136 
137     @Override
138     public GetObjectResp getObject(ClientId clientId,ID jemmId) {
139     	GetObjectResp resp;
140     	StoredObject so = objectHandler.getObject(jemmId);
141     	try {
142             resp = so.getObjectData();
143     	} finally {
144     		objectHandler.release(so);
145     	}    	
146         
147         for (Map.Entry<FieldInfo, Object> fieldValue : resp.fieldValues.entrySet()) {
148             switch(fieldValue.getKey().fieldType) {
149             case OBJECT:
150                 ID referenceId = (ID) fieldValue.getValue();
151                 if(referenceId != null)
152                     clientRefHandler.recordReference(clientId, referenceId);
153                 break;
154             default:
155                 // do nothing
156                 break;
157             }
158         }
159         
160         return resp;
161     }
162 
163     @Override
164     public ID getRoot(ClientId clientId,String rootName) {
165         ID id = rootHandler.getRoot(rootName);
166         if(id != null)
167             clientRefHandler.recordReference(clientId, id);
168         return id;
169     }
170 
171     @Override
172     public ID newObject(ClientId clientId,ClassId classId) {
173     	
174         if(clientId == null)
175             throw new IllegalArgumentException("clientId most not be null");
176         if(classId == null)
177             throw new IllegalArgumentException("classId must not be null");
178         
179         ID id = objectHandler.createObject(clientId,classId);
180         return id;        	
181     }
182 
183     @Override
184     public void referenceCleared(ClientId clientId,ID... ids) {
185     	for(ID id: ids)
186     		clientRefHandler.clearReference(clientId, id);
187     }
188 
189     @Override
190     public ClassId registerClass(ClientId clientId,ClassInfo classInfo) throws StructureModifiedException {
191         return classHandler.register(classInfo);
192     }
193 
194     @Override
195     public EnumId registerEnum(ClientId clientId,EnumInfo enumInfo) throws StructureModifiedException {
196         return enumHandler.register(enumInfo);
197     }
198 
199     @Override
200     public void releaseLock(ClientThreadId threadId, ID jemmId) {
201         userLockHandler.release(threadId,jemmId);
202     }
203 
204     @Override
205     public void removeLockAcquiredListener(ClientId clientId) {
206         userLockHandler.removeClientListener(clientId);
207     }
208 
209     @Override
210     public void setRoot(ClientId clientId,String rootName, ID newValue) {
211         rootHandler.setRoot(rootName,newValue);
212     }
213 
214     @Override
215     public ID setRootIfNull(ClientId clientId,String rootName, ID newValue) {
216         return rootHandler.setRootIfNull(rootName,newValue);
217     }
218 
219     @Override
220     public ObjectSyncResp synchroniseObject(ClientId clientId,ID objectId, ObjectSyncData syncData) {
221         return objectHandler.synchroniseObject(objectId,syncData);
222     }
223 
224     @Override
225     public DatabaseDebugIF getDebugInterface() {
226         return debugHandler;
227     }
228 
229 	public void shutdown() {
230 		gcHandler.shutdown();
231 		userLockHandler.shutdown();
232 		storageEngine.shutdown();
233 		storageEngine = null;
234 		System.gc();
235 	}
236 
237 	@Override
238 	public void clientDisconnect(ClientId clientId) {
239 		userLockHandler.clientDisconnect(clientId);
240 		clientRefHandler.clientDisconnect(clientId);
241 	}
242 
243 	@Override
244 	public TypeResponse<?> processTypeRequest(ClientId clientId,
245 			ClassId classId, ID objId, TypeRequest<?> request) {
246 		TypeHandler handler = typeHandlers.get(classId);
247 		if(handler != null)
248 			return handler.processRequest(clientId, classId, objId, request);
249 		else
250 			throw new IllegalArgumentException("No type handler defined for class type");
251 	}
252 }