📄 storedclasscatalog.java
字号:
* Not found in the database, write class info and class * format. */ classInfo = putClassInfo(new ClassInfo(), className, key, classFormat); } else { /* * Read class info to get the class format key, then read class * format. */ classInfo = new ClassInfo(data); DatabaseEntry formatData = new DatabaseEntry(); ObjectStreamClass storedClassFormat = getClassFormat(classInfo.getClassID(), formatData); /* * Compare the stored class format to the current class format, * and if they are different then generate a new class ID. */ if (!areClassFormatsEqual(storedClassFormat, getBytes(formatData), classFormat)) { classInfo = putClassInfo(classInfo, className, key, classFormat); } /* Update the class info map. */ classInfo.setClassFormat(classFormat); classMap.put(className, classInfo); } } return classInfo; } /** * Assign a new class ID (increment the current ID record), write the * ObjectStreamClass record for this new ID, and update the ClassInfo * record with the new ID also. The ClassInfo passed as an argument is the * one to be updated. */ private ClassInfo putClassInfo(ClassInfo classInfo, String className, DatabaseEntry classKey, ObjectStreamClass classFormat) throws DatabaseException, ClassNotFoundException { /* An intent-to-write cursor is needed for CDB. */ CursorConfig cursorConfig = null; if (cdbMode) { cursorConfig = new CursorConfig(); DbCompat.setWriteCursor(cursorConfig, true); } Cursor cursor = null; Transaction txn = null; try { if (txnMode) { txn = db.getEnvironment().beginTransaction(null, null); } cursor = db.openCursor(txn, cursorConfig); /* Get the current class ID. */ DatabaseEntry key = new DatabaseEntry(LAST_CLASS_ID_KEY); DatabaseEntry data = new DatabaseEntry(); OperationStatus status = cursor.getSearchKey(key, data, writeLockMode); if (status != OperationStatus.SUCCESS) { throw new IllegalStateException("Class ID not initialized"); } byte[] idBytes = getBytes(data); /* Increment the ID by one and write the updated record. */ idBytes = incrementID(idBytes); data.setData(idBytes); cursor.put(key, data); /* * Write the new class format record whose key is the ID just * assigned. */ byte[] keyBytes = new byte[1 + idBytes.length]; keyBytes[0] = REC_CLASS_FORMAT; System.arraycopy(idBytes, 0, keyBytes, 1, idBytes.length); key.setData(keyBytes); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos; try { oos = new ObjectOutputStream(baos); oos.writeObject(classFormat); } catch (IOException e) { throw new RuntimeExceptionWrapper(e); } data.setData(baos.toByteArray()); cursor.put(key, data); /* * Write the new class info record, using the key passed in; this * is done last so that a reader who gets the class info record * first will always find the corresponding class format record. */ classInfo.setClassID(idBytes); classInfo.toDbt(data); cursor.put(classKey, data); /* * Update the maps before closing the cursor, so that the cursor * lock prevents other writers from duplicating this entry. */ classInfo.setClassFormat(classFormat); classMap.put(className, classInfo); formatMap.put(new BigInteger(idBytes), classFormat); return classInfo; } finally { if (cursor != null) { cursor.close(); } if (txn != null) { txn.commit(); } } } private static byte[] incrementID(byte[] key) { BigInteger id = new BigInteger(key); id = id.add(BigInteger.valueOf(1)); return id.toByteArray(); } /** * Holds the class format key for a class, maintains a reference to the * ObjectStreamClass. Other fields can be added when we need to store more * information per class. */ private static class ClassInfo implements Serializable { private byte[] classID; private transient ObjectStreamClass classFormat; ClassInfo() { } ClassInfo(DatabaseEntry dbt) { byte[] data = dbt.getData(); int len = data[0]; classID = new byte[len]; System.arraycopy(data, 1, classID, 0, len); } void toDbt(DatabaseEntry dbt) { byte[] data = new byte[1 + classID.length]; data[0] = (byte) classID.length; System.arraycopy(classID, 0, data, 1, classID.length); dbt.setData(data); } void setClassID(byte[] classID) { this.classID = classID; } byte[] getClassID() { return classID; } ObjectStreamClass getClassFormat() { return classFormat; } void setClassFormat(ObjectStreamClass classFormat) { this.classFormat = classFormat; } } /** * Return whether two class formats are equal. This determines whether a * new class format is needed for an object being serialized. Formats must * be identical in all respects, or a new format is needed. */ private static boolean areClassFormatsEqual(ObjectStreamClass format1, byte[] format1Bytes, ObjectStreamClass format2) { try { if (format1Bytes == null) { // using cached format1 object format1Bytes = getObjectBytes(format1); } byte[] format2Bytes = getObjectBytes(format2); return java.util.Arrays.equals(format2Bytes, format1Bytes); } catch (IOException e) { return false; } } /* * We can return the same byte[] for 0 length arrays. */ private static byte[] ZERO_LENGTH_BYTE_ARRAY = new byte[0]; private static byte[] getBytes(DatabaseEntry dbt) { byte[] b = dbt.getData(); if (b == null) { return null; } if (dbt.getOffset() == 0 && b.length == dbt.getSize()) { return b; } int len = dbt.getSize(); if (len == 0) { return ZERO_LENGTH_BYTE_ARRAY; } else { byte[] t = new byte[len]; System.arraycopy(b, dbt.getOffset(), t, 0, t.length); return t; } } private static byte[] getObjectBytes(Object o) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(o); return baos.toByteArray(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -