mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
refactor FSRecords storage (next attempt)
GitOrigin-RevId: edde88ae63ec3fd76ba185cf344736a4150928b6
This commit is contained in:
committed by
intellij-monorepo-bot
parent
fbbda80ec3
commit
f99a286b5e
+36
-44
@@ -85,16 +85,18 @@ public final class FSRecords {
|
||||
w = lock.writeLock();
|
||||
}
|
||||
|
||||
// return nameId>0
|
||||
static int writeAttributesToRecord(int id, int parentId, @NotNull FileAttributes attributes, @NotNull String name) {
|
||||
/**
|
||||
* @return nameId > 0
|
||||
*/
|
||||
static int writeAttributesToRecord(int fileId, int parentId, @NotNull FileAttributes attributes, @NotNull String name) {
|
||||
return writeAndHandleErrors(() -> {
|
||||
int nameId = setName(id, name);
|
||||
int nameId = setName(fileId, name);
|
||||
|
||||
setTimestamp(id, attributes.lastModified);
|
||||
setLength(id, attributes.isDirectory() ? -1L : attributes.length);
|
||||
setTimestamp(fileId, attributes.lastModified);
|
||||
setLength(fileId, attributes.isDirectory() ? -1L : attributes.length);
|
||||
setFlags(fileId, PersistentFSImpl.fileAttributesToFlags(attributes));
|
||||
setParent(fileId, parentId);
|
||||
|
||||
setFlags(id, PersistentFSImpl.fileAttributesToFlags(attributes));
|
||||
setParent(id, parentId);
|
||||
return nameId;
|
||||
});
|
||||
}
|
||||
@@ -105,10 +107,13 @@ public final class FSRecords {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String diagnosticsForAlreadyCreatedFile(int id, int nameId, @NotNull Object existingData) {
|
||||
public static String diagnosticsForAlreadyCreatedFile(int fileId, int nameId, @NotNull Object existingData) {
|
||||
invalidateCaches();
|
||||
int parentId = getParent(id);
|
||||
String msg = "File already created: id="+id + "; nameId="+nameId + "("+getNameByNameId(nameId)+"); parentId=" + parentId+ "; existingData=" + existingData;
|
||||
int parentId = getParent(fileId);
|
||||
String msg = "File already created: fileId=" + fileId +
|
||||
"; nameId=" + nameId + "(" + getNameByNameId(nameId) + ")" +
|
||||
"; parentId=" + parentId +
|
||||
"; existingData=" + existingData;
|
||||
if (parentId > 0) {
|
||||
msg += "; parent.name=" + getName(parentId);
|
||||
msg += "; parent.children=" + list(parentId);
|
||||
@@ -163,7 +168,7 @@ public final class FSRecords {
|
||||
markAsDeletedRecursively(subRecord);
|
||||
}
|
||||
|
||||
writeAndHandleErrors(() -> ourRecordAccessor.addToFreeRecordsList(id, ourConnection));
|
||||
ourRecordAccessor.addToFreeRecordsList(id, ourConnection);
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
@@ -190,22 +195,22 @@ public final class FSRecords {
|
||||
return writeAndHandleErrors(() -> ourTreeAccessor.findOrCreateRootRecord(rootUrl, ourConnection, () -> createRecord()));
|
||||
}
|
||||
|
||||
static void deleteRootRecord(int id) {
|
||||
writeAndHandleErrors(() -> ourTreeAccessor.deleteRootRecord(id, ourConnection));
|
||||
static void deleteRootRecord(int fileId) {
|
||||
writeAndHandleErrors(() -> ourTreeAccessor.deleteRootRecord(fileId, ourConnection));
|
||||
}
|
||||
|
||||
static int @NotNull [] listIds(int id) {
|
||||
return readAndHandleErrors(() -> ourTreeAccessor.listIds(id, ourConnection));
|
||||
static int @NotNull [] listIds(int fileId) {
|
||||
return readAndHandleErrors(() -> ourTreeAccessor.listIds(fileId, ourConnection));
|
||||
}
|
||||
|
||||
static boolean mayHaveChildren(int id) {
|
||||
return readAndHandleErrors(() -> ourTreeAccessor.mayHaveChildren(id, ourConnection));
|
||||
static boolean mayHaveChildren(int fileId) {
|
||||
return readAndHandleErrors(() -> ourTreeAccessor.mayHaveChildren(fileId, ourConnection));
|
||||
}
|
||||
|
||||
// returns child infos (sorted by id) without (potentially expensive) name (or without even nameId if `loadNameId` is false)
|
||||
@NotNull
|
||||
static ListResult list(int parentId) {
|
||||
return readAndHandleErrors(() -> doLoadChildren(parentId));
|
||||
return readAndHandleErrors(() -> ourTreeAccessor.doLoadChildren(parentId, ourConnection));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -213,14 +218,7 @@ public final class FSRecords {
|
||||
return ContainerUtil.map(list(parentId).children, c -> c.getName());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static ListResult doLoadChildren(int parentId) throws IOException {
|
||||
checkFileIsValid(parentId);
|
||||
return ourTreeAccessor.doLoadChildren(parentId, ourConnection);
|
||||
}
|
||||
|
||||
static boolean wereChildrenAccessed(int id) {
|
||||
checkFileIsValid(id);
|
||||
return readAndHandleErrors(() -> ourTreeAccessor.wereChildrenAccessed(id, ourConnection));
|
||||
}
|
||||
|
||||
@@ -289,12 +287,12 @@ public final class FSRecords {
|
||||
ListResult children = list(parentId);
|
||||
ListResult result = childrenConvertor.apply(children);
|
||||
|
||||
w.lock();
|
||||
try {
|
||||
w.lock();
|
||||
ListResult toSave;
|
||||
// optimization: if the children were never changed after list(), do not check for duplicates again
|
||||
if (result.childrenWereChangedSinceLastList()) {
|
||||
children = doLoadChildren(parentId);
|
||||
children = list(parentId);
|
||||
toSave = childrenConvertor.apply(children);
|
||||
}
|
||||
else {
|
||||
@@ -373,13 +371,12 @@ public final class FSRecords {
|
||||
return ourConnection.getLocalModificationCount(); // This is volatile, only modified under Application.runWriteAction() lock.
|
||||
}
|
||||
|
||||
static int getModCount() {
|
||||
return readAndHandleErrors(ourConnection::getGlobalModCount);
|
||||
static int getPersistentModCount() {
|
||||
return readAndHandleErrors(ourConnection::getPersistentModCount);
|
||||
}
|
||||
|
||||
private static void incModCount(int id) {
|
||||
int count = ourConnection.incGlobalModCount();
|
||||
ourConnection.getRecords().setModCount(id, count);
|
||||
ourConnection.incModCount(id);
|
||||
}
|
||||
|
||||
public static int getParent(int id) {
|
||||
@@ -426,6 +423,7 @@ public final class FSRecords {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private VirtualFileSystemEntry findDescendantByIdPath() {
|
||||
VirtualFileSystemEntry parent = foundParent;
|
||||
if (path != null) {
|
||||
@@ -437,6 +435,7 @@ public final class FSRecords {
|
||||
return findChild(parent, id);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private VirtualFileSystemEntry findChild(VirtualFileSystemEntry parent, int childId) {
|
||||
if (!(parent instanceof VirtualDirectoryImpl)) {
|
||||
return null;
|
||||
@@ -507,13 +506,14 @@ public final class FSRecords {
|
||||
return nameId == 0 ? "" : ourConnection.getNames().valueOf(nameId);
|
||||
}
|
||||
|
||||
// return nameId>0
|
||||
static int setName(int id, @NotNull String name) {
|
||||
/**
|
||||
* @return nameId
|
||||
*/
|
||||
static int setName(int fileId, @NotNull String name) {
|
||||
return writeAndHandleErrors(() -> {
|
||||
incModCount(id);
|
||||
incModCount(fileId);
|
||||
int nameId = ourConnection.getNames().enumerate(name);
|
||||
assert nameId > 0 : nameId;
|
||||
ourConnection.getRecords().setNameId(id, nameId);
|
||||
ourConnection.getRecords().setNameId(fileId, nameId);
|
||||
return nameId;
|
||||
});
|
||||
}
|
||||
@@ -558,7 +558,6 @@ public final class FSRecords {
|
||||
@Nullable
|
||||
static DataInputStream readContent(int fileId) {
|
||||
ThrowableComputable<DataInputStream, IOException> computable = readAndHandleErrors(() -> {
|
||||
checkFileIsValid(fileId);
|
||||
return ourContentAccessor.readContent(fileId, ourConnection);
|
||||
});
|
||||
if (computable == null) return null;
|
||||
@@ -608,15 +607,10 @@ public final class FSRecords {
|
||||
// must be called under r or w lock
|
||||
@Nullable
|
||||
private static DataInputStream readAttribute(int fileId, @NotNull FileAttribute attribute) throws IOException {
|
||||
checkFileIsValid(fileId);
|
||||
|
||||
return ourAttributeAccessor.readAttribute(fileId, attribute, ourConnection);
|
||||
}
|
||||
|
||||
private static void checkFileIsValid(int fileId) {
|
||||
assert fileId > 0 : fileId;
|
||||
}
|
||||
|
||||
static int acquireFileContent(int fileId) {
|
||||
return writeAndHandleErrors(() -> ourContentAccessor.acquireContentRecord(fileId, ourConnection));
|
||||
}
|
||||
@@ -636,7 +630,6 @@ public final class FSRecords {
|
||||
|
||||
@NotNull
|
||||
static DataOutputStream writeContent(int fileId, boolean readOnly) {
|
||||
checkFileIsValid(fileId);
|
||||
return new DataOutputStream(ourContentAccessor.new ContentOutputStream(fileId, readOnly, ourConnection)) {
|
||||
@Override
|
||||
public void close() {
|
||||
@@ -651,7 +644,6 @@ public final class FSRecords {
|
||||
}
|
||||
|
||||
static void writeContent(int fileId, @NotNull ByteArraySequence bytes, boolean readOnly) {
|
||||
checkFileIsValid(fileId);
|
||||
writeAndHandleErrors(() -> {
|
||||
if (ourContentAccessor.writeContent(fileId, bytes, readOnly, ourConnection)) {
|
||||
incModCount(fileId);
|
||||
|
||||
+4
@@ -33,6 +33,8 @@ class PersistentFSAttributeAccessor {
|
||||
DataInputStream readAttribute(int fileId,
|
||||
@NotNull FileAttribute attribute,
|
||||
@NotNull PersistentFSConnection connection) throws IOException {
|
||||
PersistentFSConnection.ensureIdIsValid(fileId);
|
||||
|
||||
int recordId = connection.getRecords().getAttributeRecordId(fileId);
|
||||
if (recordId == 0) return null;
|
||||
int encodedAttrId = connection.getAttributeId(attribute.getId());
|
||||
@@ -83,6 +85,8 @@ class PersistentFSAttributeAccessor {
|
||||
@NotNull FileAttribute attr,
|
||||
boolean toWrite,
|
||||
@NotNull PersistentFSConnection connection) throws IOException {
|
||||
PersistentFSConnection.ensureIdIsValid(fileId);
|
||||
|
||||
int recordId = connection.getRecords().getAttributeRecordId(fileId);
|
||||
int encodedAttrId = connection.getAttributeId(attr.getId());
|
||||
boolean directoryRecord = false;
|
||||
|
||||
+13
-2
@@ -146,13 +146,12 @@ final class PersistentFSConnection {
|
||||
} // No luck.
|
||||
}
|
||||
|
||||
int getGlobalModCount() {
|
||||
int getPersistentModCount() {
|
||||
return myRecords.getGlobalModCount();
|
||||
}
|
||||
|
||||
int incGlobalModCount() {
|
||||
incLocalModCount();
|
||||
|
||||
return myRecords.incGlobalModCount();
|
||||
}
|
||||
|
||||
@@ -219,6 +218,11 @@ final class PersistentFSConnection {
|
||||
return myPersistentFSPaths;
|
||||
}
|
||||
|
||||
public void incModCount(int fileId) {
|
||||
int count = incGlobalModCount();
|
||||
getRecords().setModCount(fileId, count);
|
||||
}
|
||||
|
||||
static void closeStorages(@Nullable PersistentFSRecordsStorage records,
|
||||
@Nullable PersistentStringEnumerator names,
|
||||
@Nullable Storage attributes,
|
||||
@@ -286,4 +290,11 @@ final class PersistentFSConnection {
|
||||
return Math.max(myAttrPageRequested ? 8 : 32, Math.min((int)(requiredLength * 1.2), (requiredLength / 1024 + 1) * 1024));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id - file id, name id, any other positive id
|
||||
*/
|
||||
static void ensureIdIsValid(int id) {
|
||||
assert id > 0 : id;
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -31,6 +31,7 @@ public class PersistentFSContentAccessor {
|
||||
|
||||
@Nullable
|
||||
ThrowableComputable<DataInputStream, IOException> readContent(int fileId, @NotNull PersistentFSConnection connection) {
|
||||
PersistentFSConnection.ensureIdIsValid(fileId);
|
||||
int page = connection.getRecords().getContentRecordId(fileId);
|
||||
if (page == 0) return null;
|
||||
return () -> {
|
||||
@@ -60,6 +61,8 @@ public class PersistentFSContentAccessor {
|
||||
}
|
||||
|
||||
boolean writeContent(int fileId, @NotNull ByteArraySequence bytes, boolean fixedSize, @NotNull PersistentFSConnection connection) throws IOException {
|
||||
PersistentFSConnection.ensureIdIsValid(fileId);
|
||||
|
||||
boolean modified = false;
|
||||
RefCountingStorage contentStorage = connection.getContents();
|
||||
|
||||
@@ -206,6 +209,7 @@ public class PersistentFSContentAccessor {
|
||||
|
||||
ContentOutputStream(int fileId, boolean readOnly, @NotNull PersistentFSConnection connection) {
|
||||
super(new BufferExposingByteArrayOutputStream());
|
||||
PersistentFSConnection.ensureIdIsValid(fileId);
|
||||
myFileId = fileId;
|
||||
myFixedSize = readOnly;
|
||||
myConnection = connection;
|
||||
|
||||
+1
-1
@@ -290,7 +290,7 @@ public final class PersistentFSImpl extends PersistentFS implements Disposable {
|
||||
|
||||
@Override
|
||||
public int getFilesystemModificationCount() {
|
||||
return FSRecords.getModCount();
|
||||
return FSRecords.getPersistentModCount();
|
||||
}
|
||||
|
||||
// return nameId>0 if write successful, -1 if not
|
||||
|
||||
+1
@@ -70,6 +70,7 @@ public class PersistentFSRecordsStorage {
|
||||
}
|
||||
|
||||
void setNameId(int id, int nameId) {
|
||||
PersistentFSConnection.ensureIdIsValid(nameId);
|
||||
putRecordInt(id, NAME_OFFSET, nameId);
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -65,6 +65,8 @@ class PersistentFSTreeAccessor {
|
||||
|
||||
@NotNull
|
||||
ListResult doLoadChildren(int parentId, @NotNull PersistentFSConnection connection) throws IOException {
|
||||
PersistentFSConnection.ensureIdIsValid(parentId);
|
||||
|
||||
try (DataInputStream input = myAttributeAccessor.readAttribute(parentId, ourChildrenAttr, connection)) {
|
||||
int count = input == null ? 0 : DataInputOutputUtil.readINT(input);
|
||||
List<ChildInfo> result = count == 0 ? Collections.emptyList() : new ArrayList<>(count);
|
||||
|
||||
Reference in New Issue
Block a user