1 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 86 87 public void checkNoActive(String 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 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 clid = createClidFromClassName(classMetaDescription.getClassName()); 131 writePersistentClassMetaDescription(clid, (ClassDescriptionImpl) classMetaDescription); 132 } catch (SchemaException fse) { 133 } 135 session.currentTransaction().commit(); 136 } 137 138 public ClassDescription getMetaData(String className) { 139 Object clid = getClidFromClassName(className); 140 return getPersistentClassMetaDescription(clid); 141 } 142 143 public void removeClass(Session session, String className) { 144 checkNoActive(MODIFY_DURING_TRANSACTION_MESSAGE); 145 146 Object sessionId = session.getInternalSession().getSessionId(); 147 Object 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 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 className, FieldDescription fieldDescription) { 184 checkNoActive(MODIFY_DURING_TRANSACTION_MESSAGE); 185 186 session.currentTransaction().begin(); 187 short index = fieldDescription.getIndex(); 188 Object 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 oid = oids.next(); 200 Object [] o = session.readObjectByOid(oid); 201 Object [] oo = new Object [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 [] getFieldNames(String className) { 219 return getMetaData(className).getFieldNames(); 220 } 221 222 public void renameField(Session session, String className, String oldFieldName, String newFieldName) { 223 checkNoActive(MODIFY_DURING_TRANSACTION_MESSAGE); 224 225 session.currentTransaction().begin(); 226 Object 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 [] fieldNames = meta.getFieldNames(); 238 fieldNames[index] = newFieldName; 239 writePersistentClassMetaDescription(clid, meta); 240 session.currentTransaction().commit(); 241 } 242 243 public void removeField(Session session, String className, String fieldName) { 244 checkNoActive(MODIFY_DURING_TRANSACTION_MESSAGE); 245 246 session.currentTransaction().begin(); 247 Object 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 oid = oids.next(); 261 Object [] o = session.readObjectByOid(oid); 262 Object [] oo = new Object [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 className, String fieldName) { 279 String [] 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 297 298 public ClassDescription getPersistentClassMetaDescription(Object 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 public void writePersistentClassMetaDescription(Object clid, ClassDescription metaDescription) { 309 tracer.println(Trace.LOGICAL, "MetaRepositoryImpl : writePersistentClassMetaDescription({0}, {1})", clid, 310 metaDescription); 311 ((ClassDescriptionImpl)metaDescription).setRepository(this); 312 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 public void writePersistentClassMetaDescription(ClassDescriptionImpl metaDescription) { 322 Object clid = getClidFromClassName(metaDescription.getClassName()); 323 writePersistentClassMetaDescription(clid, metaDescription); 324 } 325 326 private void allocateNewClidIfa(Object 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 clid) { 342 tracer.println(Trace.LOGICAL, "MetaRepositoryImpl : getPersistentClassMetaDescription({0})", clid); 343 InFileAddress classIfa = (InFileAddress) clidIndex.get(clid); 345 ClassPage classPage = (ClassPage) physicalAccess.readFileObjectAt(classIfa); 346 ClassDescriptionImpl classMetaDescription = (ClassDescriptionImpl) classPage.getDataAt(classIfa); 348 classMetaDescription.setRepository(this); 349 return classMetaDescription; 350 } 351 352 355 356 public String getClassNameFromClid(Object clid) { 357 Iterator keys = classTable.keySet().iterator(); 358 while (keys.hasNext()) { 359 Object key = keys.next(); 360 if (classTable.get(key).equals(clid)) { 361 return (String ) key; 362 } 363 } 364 return null; 365 } 366 367 public Object getClidFromClassName(String fullClassName) { 368 Object 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 getNewClassPageAddress() { 376 return "cp" + (classPageIndex++); 377 } 378 379 private Object createClidFromClassName(String fullClassName) { 380 if (!classTable.containsKey(fullClassName)) { 381 Object 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 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 [] datas = (Object []) physicalAccess.readFileObjectAt(MR_STATE_IFA).getData(); 419 currentAvalaibleClassPage = (InFileAddress) datas[0]; 420 classPageIndex = ((Integer ) datas[1]).intValue(); 421 422 classMetas = new HashMap(); 423 Iterator clids = classTable.values().iterator(); 424 while (clids.hasNext()) { 425 Object 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 [] datas = new Object [2]; 433 datas[0] = currentAvalaibleClassPage; 434 datas[1] = new Integer (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 repository.getStateFromBase(); 443 } catch (Exception 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; private Map classTable; private Map clidIndex; 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 MODIFY_DURING_TRANSACTION_MESSAGE = "Try to modify schema during active transaction : "; 471 } 472 | Popular Tags |