mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-10-01 09:03:31 +07:00
local history: storage bug fixed (hopefully) + some logging and storage checking in internal mode
IO: storage classes cleanup
This commit is contained in:
@@ -21,9 +21,7 @@ import com.intellij.history.core.changes.Change;
|
||||
import com.intellij.history.core.changes.ChangeSet;
|
||||
import com.intellij.history.core.changes.ChangeVisitor;
|
||||
import com.intellij.history.core.changes.ContentChange;
|
||||
import com.intellij.history.core.storage.Content;
|
||||
import com.intellij.history.core.tree.Entry;
|
||||
import com.intellij.history.core.tree.RootEntry;
|
||||
import com.intellij.history.integration.IdeaGateway;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.intellij.history.Clock;
|
||||
import com.intellij.history.core.changes.Change;
|
||||
import com.intellij.history.core.changes.ChangeSet;
|
||||
import com.intellij.history.core.changes.ChangeVisitor;
|
||||
import com.intellij.history.core.storage.Content;
|
||||
import com.intellij.history.utils.LocalHistoryLog;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.util.Consumer;
|
||||
@@ -36,13 +35,13 @@ public class ChangeList {
|
||||
private int myChangeSetDepth;
|
||||
private ChangeSet myCurrentChangeSet;
|
||||
|
||||
private int myIntervalBetweenActivities = 12 * 60 * 60 * 1000; // one day
|
||||
private int myIntervalBetweenActivities = 12 * 60 * 60 * 1000; // 12 hours
|
||||
|
||||
public ChangeList(ChangeListStorage storage) {
|
||||
myStorage = storage;
|
||||
}
|
||||
|
||||
public synchronized void save() {
|
||||
public synchronized void flush() {
|
||||
myStorage.flush();
|
||||
}
|
||||
|
||||
|
||||
@@ -27,12 +27,13 @@ import com.intellij.util.io.storage.AbstractStorage;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
public class ChangeListStorageImpl implements ChangeListStorage {
|
||||
private static final int VERSION = 4;
|
||||
private static final int VERSION = 5;
|
||||
private static final String STORAGE_FILE = "changes";
|
||||
|
||||
private final LinkedStorage myStorage;
|
||||
|
||||
private final LocalHistoryStorage myStorage;
|
||||
|
||||
public ChangeListStorageImpl(File storageDir) {
|
||||
try {
|
||||
@@ -43,22 +44,26 @@ public class ChangeListStorageImpl implements ChangeListStorage {
|
||||
}
|
||||
}
|
||||
|
||||
private static LinkedStorage createStorage(File storageDir) throws IOException {
|
||||
private static LocalHistoryStorage createStorage(File storageDir) throws IOException {
|
||||
String path = storageDir.getPath() + "/" + STORAGE_FILE;
|
||||
LinkedStorage result = new LinkedStorage(path);
|
||||
LocalHistoryStorage result = new LocalHistoryStorage(path);
|
||||
|
||||
long fsTimestamp = ((PersistentFS)ManagingFS.getInstance()).getCreationTimestamp();
|
||||
|
||||
boolean versionMismatch = result.getVersion() != VERSION;
|
||||
int storedVersion = result.getVersion();
|
||||
boolean versionMismatch = storedVersion != VERSION;
|
||||
boolean timestampMismatch = result.getFSTimestamp() != fsTimestamp;
|
||||
if (versionMismatch || timestampMismatch) {
|
||||
if (versionMismatch) LocalHistoryLog.LOG.info("local history version mismatch, rebuilding...");
|
||||
if (timestampMismatch) LocalHistoryLog.LOG.info("FS has been rebuild, rebuilding clearing local history...");
|
||||
if (versionMismatch) {
|
||||
LocalHistoryLog.LOG.info(MessageFormat.format(
|
||||
"local history version mismatch (was: {0}, expected: {1}), rebuilding...", storedVersion, VERSION));
|
||||
}
|
||||
if (timestampMismatch) LocalHistoryLog.LOG.info("FS has been rebuild, rebuilding local history...");
|
||||
result.dispose();
|
||||
if (!FileUtil.delete(storageDir)) {
|
||||
throw new IOException("cannot clear storage dir: " + storageDir);
|
||||
}
|
||||
result = new LinkedStorage(path);
|
||||
result = new LocalHistoryStorage(path);
|
||||
result.setVersion(VERSION);
|
||||
result.setFSTimestamp(fsTimestamp);
|
||||
}
|
||||
@@ -74,7 +79,7 @@ public class ChangeListStorageImpl implements ChangeListStorage {
|
||||
catch (Throwable ex) {
|
||||
LocalHistoryLog.LOG.error("cannot mark storage as broken", ex);
|
||||
}
|
||||
throw new RuntimeException(e);
|
||||
throw new RuntimeException("Local history is broken and will be rebuilt after restart (storage version: " + VERSION + ")", e);
|
||||
}
|
||||
|
||||
public synchronized void close() {
|
||||
@@ -128,8 +133,9 @@ public class ChangeListStorageImpl implements ChangeListStorage {
|
||||
try {
|
||||
while (eachBlockId != 0) {
|
||||
processor.consume(doReadBlock(eachBlockId).changeSet);
|
||||
myStorage.deleteRecord(eachBlockId);
|
||||
int toDelete = eachBlockId;
|
||||
eachBlockId = myStorage.getPrevRecord(eachBlockId);
|
||||
myStorage.deleteRecord(toDelete);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
@@ -149,6 +155,7 @@ public class ChangeListStorageImpl implements ChangeListStorage {
|
||||
long delta = prevTimestamp - t;
|
||||
prevTimestamp = t;
|
||||
|
||||
// we sum only intervals between changes during one 'day' (intervalBetweenActivities) and add '1' between two 'days'
|
||||
length += delta < intervalBetweenActivities ? delta : 1;
|
||||
|
||||
if (length >= period) return last;
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.history.core.storage;
|
||||
package com.intellij.history.core;
|
||||
|
||||
import com.intellij.history.core.tree.Entry;
|
||||
import com.intellij.history.integration.IdeaGateway;
|
||||
@@ -18,10 +18,9 @@ package com.intellij.history.core;
|
||||
|
||||
import com.intellij.history.ByteContent;
|
||||
import com.intellij.history.core.changes.*;
|
||||
import com.intellij.history.core.revisions.ChangeRevision;
|
||||
import com.intellij.history.core.revisions.RecentChange;
|
||||
import com.intellij.history.core.revisions.Revision;
|
||||
import com.intellij.history.core.revisions.ChangeRevision;
|
||||
import com.intellij.history.core.storage.Content;
|
||||
import com.intellij.history.core.tree.Entry;
|
||||
import com.intellij.history.core.tree.RootEntry;
|
||||
import com.intellij.openapi.Disposable;
|
||||
|
||||
+7
-15
@@ -15,14 +15,13 @@
|
||||
*/
|
||||
package com.intellij.history.core;
|
||||
|
||||
import com.intellij.openapi.components.impl.stores.StorageUtil;
|
||||
import com.intellij.util.io.PagePool;
|
||||
import com.intellij.util.io.storage.AbstractRecordsTable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public class LinkedRecordsTable extends AbstractRecordsTable {
|
||||
public class LocalHistoryRecordsTable extends AbstractRecordsTable {
|
||||
private static final int VERSION = 4;
|
||||
|
||||
private static final int ID_COUNTER_OFFSET = DEFAULT_HEADER_SIZE;
|
||||
@@ -38,7 +37,7 @@ public class LinkedRecordsTable extends AbstractRecordsTable {
|
||||
private static final int RECORD_SIZE = TIMESTAMP_OFFSET + 8;
|
||||
private static final byte[] ZEROS = new byte[RECORD_SIZE];
|
||||
|
||||
public LinkedRecordsTable(final File storageFilePath, final PagePool pool) throws IOException {
|
||||
public LocalHistoryRecordsTable(final File storageFilePath, final PagePool pool) throws IOException {
|
||||
super(storageFilePath, pool);
|
||||
}
|
||||
|
||||
@@ -62,11 +61,11 @@ public class LinkedRecordsTable extends AbstractRecordsTable {
|
||||
return ZEROS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clearDeletedRecord(int record) {
|
||||
setTimestamp(record, 0);
|
||||
setNextRecord(record, 0);
|
||||
setPrevRecord(record, 0);
|
||||
public long nextId() {
|
||||
markDirty();
|
||||
long result = myStorage.getLong(ID_COUNTER_OFFSET);
|
||||
myStorage.putLong(ID_COUNTER_OFFSET, result + 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setFSTimestamp(long timestamp) {
|
||||
@@ -122,12 +121,5 @@ public class LinkedRecordsTable extends AbstractRecordsTable {
|
||||
public long getTimestamp(int record) {
|
||||
return myStorage.getLong(getOffset(record, TIMESTAMP_OFFSET));
|
||||
}
|
||||
|
||||
public long nextId() {
|
||||
markDirty();
|
||||
long result = myStorage.getLong(ID_COUNTER_OFFSET);
|
||||
myStorage.putLong(ID_COUNTER_OFFSET, result + 1);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
+14
-14
@@ -23,71 +23,71 @@ import com.intellij.util.io.storage.AbstractStorage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public class LinkedStorage extends AbstractStorage {
|
||||
public LinkedStorage(String storageFilePath) throws IOException {
|
||||
public class LocalHistoryStorage extends AbstractStorage {
|
||||
public LocalHistoryStorage(String storageFilePath) throws IOException {
|
||||
super(storageFilePath);
|
||||
}
|
||||
|
||||
public LinkedStorage(String storageFilePath, PagePool pool) throws IOException {
|
||||
public LocalHistoryStorage(String storageFilePath, PagePool pool) throws IOException {
|
||||
super(storageFilePath, pool);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractRecordsTable createRecordsTable(PagePool pool, File recordsFile) throws IOException {
|
||||
return new LinkedRecordsTable(recordsFile, pool);
|
||||
return new LocalHistoryRecordsTable(recordsFile, pool);
|
||||
}
|
||||
|
||||
public long getFSTimestamp() {
|
||||
synchronized (myLock) {
|
||||
return ((LinkedRecordsTable)myRecordsTable).getFSTimestamp();
|
||||
return ((LocalHistoryRecordsTable)myRecordsTable).getFSTimestamp();
|
||||
}
|
||||
}
|
||||
|
||||
public void setFSTimestamp(long timestamp) {
|
||||
synchronized (myLock) {
|
||||
((LinkedRecordsTable)myRecordsTable).setFSTimestamp(timestamp);
|
||||
((LocalHistoryRecordsTable)myRecordsTable).setFSTimestamp(timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
public long nextId() {
|
||||
synchronized (myLock) {
|
||||
return ((LinkedRecordsTable)myRecordsTable).nextId();
|
||||
return ((LocalHistoryRecordsTable)myRecordsTable).nextId();
|
||||
}
|
||||
}
|
||||
|
||||
public int getFirstRecord() {
|
||||
synchronized (myLock) {
|
||||
return ((LinkedRecordsTable)myRecordsTable).getFirstRecord();
|
||||
return ((LocalHistoryRecordsTable)myRecordsTable).getFirstRecord();
|
||||
}
|
||||
}
|
||||
|
||||
public int getLastRecord() {
|
||||
synchronized (myLock) {
|
||||
return ((LinkedRecordsTable)myRecordsTable).getLastRecord();
|
||||
return ((LocalHistoryRecordsTable)myRecordsTable).getLastRecord();
|
||||
}
|
||||
}
|
||||
|
||||
public int getPrevRecord(int record) {
|
||||
synchronized (myLock) {
|
||||
return ((LinkedRecordsTable)myRecordsTable).getPrevRecord(record);
|
||||
return ((LocalHistoryRecordsTable)myRecordsTable).getPrevRecord(record);
|
||||
}
|
||||
}
|
||||
|
||||
public int getNextRecord(int record) {
|
||||
synchronized (myLock) {
|
||||
return ((LinkedRecordsTable)myRecordsTable).getNextRecord(record);
|
||||
return ((LocalHistoryRecordsTable)myRecordsTable).getNextRecord(record);
|
||||
}
|
||||
}
|
||||
|
||||
public long getTimestamp(int record) {
|
||||
synchronized (myLock) {
|
||||
return ((LinkedRecordsTable)myRecordsTable).getTimestamp(record);
|
||||
return ((LocalHistoryRecordsTable)myRecordsTable).getTimestamp(record);
|
||||
}
|
||||
}
|
||||
|
||||
public int createNextRecord() throws IOException {
|
||||
synchronized (myLock) {
|
||||
LinkedRecordsTable table = (LinkedRecordsTable)myRecordsTable;
|
||||
LocalHistoryRecordsTable table = (LocalHistoryRecordsTable)myRecordsTable;
|
||||
int id = table.createNewRecord();
|
||||
int prev = table.getLastRecord();
|
||||
|
||||
@@ -108,7 +108,7 @@ public class LinkedStorage extends AbstractStorage {
|
||||
|
||||
public void deleteRecord(int id) throws IOException {
|
||||
synchronized (myLock) {
|
||||
LinkedRecordsTable table = (LinkedRecordsTable)myRecordsTable;
|
||||
LocalHistoryRecordsTable table = (LocalHistoryRecordsTable)myRecordsTable;
|
||||
|
||||
int prev = table.getPrevRecord(id);
|
||||
int next = table.getNextRecord(id);
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.history.core.storage;
|
||||
package com.intellij.history.core;
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
|
||||
+7
-3
@@ -14,12 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.history.core.storage;
|
||||
package com.intellij.history.core;
|
||||
|
||||
import com.intellij.history.core.changes.*;
|
||||
import com.intellij.history.core.tree.DirectoryEntry;
|
||||
import com.intellij.history.core.tree.Entry;
|
||||
import com.intellij.history.core.tree.FileEntry;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
@@ -95,20 +97,22 @@ public class StreamUtil {
|
||||
change.write(out);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String readString(DataInput in) throws IOException {
|
||||
return in.readUTF();
|
||||
}
|
||||
|
||||
public static void writeString(DataOutput out, String s) throws IOException {
|
||||
public static void writeString(DataOutput out, @NotNull String s) throws IOException {
|
||||
out.writeUTF(s);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String readStringOrNull(DataInput in) throws IOException {
|
||||
if (!in.readBoolean()) return null;
|
||||
return readString(in);
|
||||
}
|
||||
|
||||
public static void writeStringOrNull(DataOutput out, String s) throws IOException {
|
||||
public static void writeStringOrNull(DataOutput out, @Nullable String s) throws IOException {
|
||||
out.writeBoolean(s != null);
|
||||
if (s != null) writeString(out, s);
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package com.intellij.history.core.changes;
|
||||
|
||||
import com.intellij.history.core.storage.Content;
|
||||
import com.intellij.history.core.Content;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
package com.intellij.history.core.changes;
|
||||
|
||||
import com.intellij.history.core.storage.Content;
|
||||
import com.intellij.history.core.storage.StreamUtil;
|
||||
import com.intellij.history.core.Content;
|
||||
import com.intellij.history.core.StreamUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -30,7 +30,7 @@ import java.util.List;
|
||||
|
||||
public class ChangeSet {
|
||||
private final long myId;
|
||||
private String myName;
|
||||
@Nullable private String myName;
|
||||
private final long myTimestamp;
|
||||
private final List<Change> myChanges;
|
||||
|
||||
@@ -63,10 +63,11 @@ public class ChangeSet {
|
||||
}
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
public void setName(@Nullable String name) {
|
||||
myName = name;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
package com.intellij.history.core.changes;
|
||||
|
||||
import com.intellij.history.core.storage.Content;
|
||||
import com.intellij.history.core.storage.StoredContent;
|
||||
import com.intellij.history.core.Content;
|
||||
import com.intellij.history.core.StoredContent;
|
||||
import com.intellij.history.core.tree.Entry;
|
||||
import com.intellij.history.core.tree.RootEntry;
|
||||
|
||||
@@ -39,7 +39,7 @@ public class ContentChange extends StructuralChange {
|
||||
|
||||
public ContentChange(DataInput in) throws IOException {
|
||||
super(in);
|
||||
myOldContent = new StoredContent(in.readInt());
|
||||
myOldContent = new StoredContent(in);
|
||||
myOldTimestamp = in.readLong();
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.intellij.history.core.changes;
|
||||
|
||||
import com.intellij.history.core.storage.StreamUtil;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.intellij.history.core.changes;
|
||||
|
||||
import com.intellij.history.core.storage.StreamUtil;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
|
||||
package com.intellij.history.core.changes;
|
||||
|
||||
import com.intellij.history.core.Content;
|
||||
import com.intellij.history.core.Paths;
|
||||
import com.intellij.history.core.storage.Content;
|
||||
import com.intellij.history.core.storage.StreamUtil;
|
||||
import com.intellij.history.core.StreamUtil;
|
||||
import com.intellij.history.core.tree.Entry;
|
||||
import com.intellij.history.core.tree.RootEntry;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package com.intellij.history.core.changes;
|
||||
|
||||
import com.intellij.history.core.Paths;
|
||||
import com.intellij.history.core.storage.StreamUtil;
|
||||
import com.intellij.history.core.StreamUtil;
|
||||
import com.intellij.history.core.tree.Entry;
|
||||
import com.intellij.history.core.tree.RootEntry;
|
||||
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
package com.intellij.history.core.changes;
|
||||
|
||||
import com.intellij.history.core.storage.Content;
|
||||
import com.intellij.history.core.storage.StreamUtil;
|
||||
import com.intellij.history.core.Content;
|
||||
import com.intellij.history.core.StreamUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.DataInput;
|
||||
@@ -28,8 +28,8 @@ import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class PutLabelChange extends Change {
|
||||
private final String myName;
|
||||
private final String myProjectId;
|
||||
@NotNull private final String myName;
|
||||
@NotNull private final String myProjectId;
|
||||
|
||||
public PutLabelChange(long id, @NotNull String name, @NotNull String projectId) {
|
||||
super(id);
|
||||
@@ -50,10 +50,12 @@ public class PutLabelChange extends Change {
|
||||
StreamUtil.writeString(out, myProjectId);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getProjectId() {
|
||||
return myProjectId;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package com.intellij.history.core.changes;
|
||||
|
||||
import com.intellij.history.core.Paths;
|
||||
import com.intellij.history.core.storage.StreamUtil;
|
||||
import com.intellij.history.core.StreamUtil;
|
||||
import com.intellij.history.core.tree.Entry;
|
||||
import com.intellij.history.core.tree.RootEntry;
|
||||
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
|
||||
package com.intellij.history.core.changes;
|
||||
|
||||
import com.intellij.history.core.Content;
|
||||
import com.intellij.history.core.Paths;
|
||||
import com.intellij.history.core.storage.Content;
|
||||
import com.intellij.history.core.storage.StreamUtil;
|
||||
import com.intellij.history.core.StreamUtil;
|
||||
import com.intellij.history.core.tree.Entry;
|
||||
import com.intellij.history.core.tree.RootEntry;
|
||||
import com.intellij.history.utils.LocalHistoryLog;
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.history.core.storage;
|
||||
|
||||
// todo this class is needed only becase we cannot create IOException with cause - it will be possible in java 1.6
|
||||
public class BrokenStorageException extends Exception {
|
||||
public BrokenStorageException() {
|
||||
}
|
||||
|
||||
public BrokenStorageException(Throwable e) {
|
||||
super(e);
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
package com.intellij.history.core.tree;
|
||||
|
||||
import com.intellij.history.core.StreamUtil;
|
||||
import com.intellij.history.core.revisions.Difference;
|
||||
import com.intellij.history.core.storage.StreamUtil;
|
||||
import com.intellij.history.utils.LocalHistoryLog;
|
||||
|
||||
import java.io.DataInput;
|
||||
@@ -26,8 +26,6 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
public class DirectoryEntry extends Entry {
|
||||
private final ArrayList<Entry> myChildren;
|
||||
|
||||
@@ -36,7 +34,7 @@ public class DirectoryEntry extends Entry {
|
||||
myChildren = new ArrayList<Entry>(3);
|
||||
}
|
||||
|
||||
public DirectoryEntry(DataInput in, boolean dummy /* to distinguish from general contructor*/) throws IOException {
|
||||
public DirectoryEntry(DataInput in, boolean dummy /* to distinguish from general constructor*/) throws IOException {
|
||||
super(in);
|
||||
int count = in.readInt();
|
||||
myChildren = new ArrayList<Entry>(count);
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
|
||||
package com.intellij.history.core.tree;
|
||||
|
||||
import com.intellij.history.core.Content;
|
||||
import com.intellij.history.core.Paths;
|
||||
import com.intellij.history.core.StreamUtil;
|
||||
import com.intellij.history.core.revisions.Difference;
|
||||
import com.intellij.history.core.storage.Content;
|
||||
import com.intellij.history.core.storage.StreamUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
|
||||
import java.io.DataInput;
|
||||
@@ -37,7 +37,6 @@ public abstract class Entry {
|
||||
|
||||
public Entry(String name) {
|
||||
myName = name;
|
||||
//assert name == null || !name.contains("/");
|
||||
}
|
||||
|
||||
public Entry(DataInput in) throws IOException {
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
|
||||
package com.intellij.history.core.tree;
|
||||
|
||||
import com.intellij.history.core.Content;
|
||||
import com.intellij.history.core.StoredContent;
|
||||
import com.intellij.history.core.revisions.Difference;
|
||||
import com.intellij.history.core.storage.Content;
|
||||
import com.intellij.history.core.storage.StoredContent;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
@@ -37,7 +37,7 @@ public class FileEntry extends Entry {
|
||||
myContent = content;
|
||||
}
|
||||
|
||||
public FileEntry(DataInput in, boolean dummy /* to distinguish from general contructor*/) throws IOException {
|
||||
public FileEntry(DataInput in, boolean dummy /* to distinguish from general constructor*/) throws IOException {
|
||||
super(in);
|
||||
myTimestamp = in.readLong();
|
||||
isReadOnly = in.readBoolean();
|
||||
|
||||
@@ -17,13 +17,10 @@
|
||||
package com.intellij.history.core.tree;
|
||||
|
||||
import com.intellij.history.core.Paths;
|
||||
import com.intellij.history.core.storage.StreamUtil;
|
||||
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
public class RootEntry extends DirectoryEntry {
|
||||
public RootEntry() {
|
||||
super("");
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
package com.intellij.history.integration;
|
||||
|
||||
import com.intellij.history.Clock;
|
||||
import com.intellij.history.core.Content;
|
||||
import com.intellij.history.core.LocalHistoryFacade;
|
||||
import com.intellij.history.core.Paths;
|
||||
import com.intellij.history.core.storage.Content;
|
||||
import com.intellij.history.core.storage.StoredContent;
|
||||
import com.intellij.history.core.StoredContent;
|
||||
import com.intellij.history.core.tree.DirectoryEntry;
|
||||
import com.intellij.history.core.tree.Entry;
|
||||
import com.intellij.history.core.tree.FileEntry;
|
||||
|
||||
+1
-1
@@ -16,8 +16,8 @@
|
||||
|
||||
package com.intellij.history.integration;
|
||||
|
||||
import com.intellij.history.core.Content;
|
||||
import com.intellij.history.core.LocalHistoryFacade;
|
||||
import com.intellij.history.core.storage.Content;
|
||||
import com.intellij.history.core.tree.Entry;
|
||||
import com.intellij.openapi.command.CommandEvent;
|
||||
import com.intellij.openapi.command.CommandListener;
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.intellij.history.integration;
|
||||
import com.intellij.concurrency.JobScheduler;
|
||||
import com.intellij.history.*;
|
||||
import com.intellij.history.core.*;
|
||||
import com.intellij.history.utils.LocalHistoryLog;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.application.ex.ApplicationManagerEx;
|
||||
@@ -60,7 +61,7 @@ public class LocalHistoryImpl extends LocalHistory implements ApplicationCompone
|
||||
|
||||
public void initComponent() {
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode() && ApplicationManager.getApplication().isHeadlessEnvironment()) return;
|
||||
|
||||
|
||||
myShutdownTask = new Runnable() {
|
||||
public void run() {
|
||||
disposeComponent();
|
||||
@@ -86,6 +87,21 @@ public class LocalHistoryImpl extends LocalHistory implements ApplicationCompone
|
||||
VirtualFileManager fm = VirtualFileManagerEx.getInstance();
|
||||
fm.addVirtualFileListener(myEventDispatcher);
|
||||
fm.addVirtualFileManagerListener(myEventDispatcher);
|
||||
|
||||
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
validateStorage();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void validateStorage() {
|
||||
if (ApplicationManagerEx.getApplicationEx().isInternal() && !ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
LocalHistoryLog.LOG.info("Checking local history storage...");
|
||||
myVcs.getChangeListInTests().getChangesInTests();
|
||||
LocalHistoryLog.LOG.info("Local history storage seems to be ok");
|
||||
}
|
||||
}
|
||||
|
||||
public File getStorageDir() {
|
||||
@@ -100,7 +116,7 @@ public class LocalHistoryImpl extends LocalHistory implements ApplicationCompone
|
||||
if (ApplicationManagerEx.getApplication().isHeadlessEnvironment()) return;
|
||||
myAutoSaveFuture = JobScheduler.getScheduler().scheduleAtFixedRate(new Runnable() {
|
||||
public void run() {
|
||||
if (!HeavyProcessLatch.INSTANCE.isRunning()) myChangeList.save();
|
||||
if (!HeavyProcessLatch.INSTANCE.isRunning()) myChangeList.flush();
|
||||
}
|
||||
}, 15000, 15000, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
@@ -118,7 +134,9 @@ public class LocalHistoryImpl extends LocalHistory implements ApplicationCompone
|
||||
CommandProcessor.getInstance().removeCommandListener(myEventDispatcher);
|
||||
|
||||
myChangeList.purgeObsolete(period);
|
||||
validateStorage();
|
||||
myChangeList.close();
|
||||
LocalHistoryLog.LOG.info("Local history storage successfully closed.");
|
||||
|
||||
ShutDownTracker.getInstance().unregisterShutdownTask(myShutdownTask);
|
||||
}
|
||||
|
||||
+1
-1
@@ -17,9 +17,9 @@
|
||||
package com.intellij.history.integration.revertion;
|
||||
|
||||
import com.intellij.history.LocalHistory;
|
||||
import com.intellij.history.core.Content;
|
||||
import com.intellij.history.core.Paths;
|
||||
import com.intellij.history.core.changes.*;
|
||||
import com.intellij.history.core.storage.Content;
|
||||
import com.intellij.history.core.tree.Entry;
|
||||
import com.intellij.history.integration.IdeaGateway;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
|
||||
+1
-1
@@ -16,11 +16,11 @@
|
||||
|
||||
package com.intellij.history.integration.revertion;
|
||||
|
||||
import com.intellij.history.core.Content;
|
||||
import com.intellij.history.core.LocalHistoryFacade;
|
||||
import com.intellij.history.core.Paths;
|
||||
import com.intellij.history.core.revisions.Difference;
|
||||
import com.intellij.history.core.revisions.Revision;
|
||||
import com.intellij.history.core.storage.Content;
|
||||
import com.intellij.history.core.tree.Entry;
|
||||
import com.intellij.history.integration.FormatUtil;
|
||||
import com.intellij.history.integration.IdeaGateway;
|
||||
|
||||
+1
-1
@@ -18,8 +18,8 @@ package com.intellij.history.integration.ui.models;
|
||||
|
||||
import com.intellij.diff.Block;
|
||||
import com.intellij.diff.FindBlock;
|
||||
import com.intellij.history.core.Content;
|
||||
import com.intellij.history.core.revisions.Revision;
|
||||
import com.intellij.history.core.storage.Content;
|
||||
import com.intellij.history.core.tree.Entry;
|
||||
import com.intellij.history.integration.IdeaGateway;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -19,7 +19,6 @@ package com.intellij.history.core;
|
||||
import com.intellij.history.Clock;
|
||||
import com.intellij.history.core.changes.*;
|
||||
import com.intellij.history.core.revisions.Revision;
|
||||
import com.intellij.history.core.storage.Content;
|
||||
import com.intellij.history.core.storage.TestContent;
|
||||
import com.intellij.history.core.tree.Entry;
|
||||
import com.intellij.history.core.tree.FileEntry;
|
||||
|
||||
@@ -175,7 +175,7 @@ public class ChangeListTest extends ChangeListTestCase {
|
||||
@Test
|
||||
public void testSavingDuringChangeSet() throws Exception {
|
||||
facade.beginChangeSet();
|
||||
facade.getChangeListInTests().save();
|
||||
facade.getChangeListInTests().flush();
|
||||
facade.endChangeSet(null); // should not throw exception.
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -16,8 +16,8 @@
|
||||
|
||||
package com.intellij.history.core.changes;
|
||||
|
||||
import com.intellij.history.core.Content;
|
||||
import com.intellij.history.core.LocalHistoryTestCase;
|
||||
import com.intellij.history.core.storage.Content;
|
||||
import com.intellij.history.core.tree.RootEntry;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package com.intellij.history.core.storage;
|
||||
|
||||
import com.intellij.history.core.LocalHistoryTestCase;
|
||||
import com.intellij.history.core.StoredContent;
|
||||
import com.intellij.history.core.StreamUtil;
|
||||
import com.intellij.history.core.changes.*;
|
||||
import com.intellij.history.core.tree.DirectoryEntry;
|
||||
import com.intellij.history.core.tree.Entry;
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.intellij.history.core.storage;
|
||||
|
||||
import com.intellij.history.core.Content;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class TestContent extends Content {
|
||||
|
||||
@@ -18,13 +18,13 @@ package com.intellij.history.core.tree;
|
||||
|
||||
import com.intellij.history.core.LocalHistoryTestCase;
|
||||
import com.intellij.history.core.Paths;
|
||||
import com.intellij.history.core.StoredContent;
|
||||
import com.intellij.history.core.revisions.Difference;
|
||||
import com.intellij.history.core.storage.StoredContent;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DirectoryEntryTest extends LocalHistoryTestCase {
|
||||
@Test
|
||||
|
||||
@@ -18,13 +18,12 @@ package com.intellij.history.core.tree;
|
||||
|
||||
import com.intellij.history.core.LocalHistoryTestCase;
|
||||
import com.intellij.history.core.Paths;
|
||||
import com.intellij.history.core.StoredContent;
|
||||
import com.intellij.history.core.revisions.Difference;
|
||||
import com.intellij.history.core.storage.StoredContent;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class FileEntryTest extends LocalHistoryTestCase {
|
||||
@Test
|
||||
|
||||
+4
-4
@@ -49,14 +49,14 @@ public class GettingContentAtDateTest extends IntegrationTestCase {
|
||||
}
|
||||
|
||||
public void testGettingFirstAvailableContentAfterPurge() throws Exception {
|
||||
Clock.setCurrentTimestamp(10);
|
||||
Clock.setCurrentTimestamp(1);
|
||||
setContent(f, "1", TIMESTAMP_INCREMENT);
|
||||
Clock.setCurrentTimestamp(20);
|
||||
Clock.setCurrentTimestamp(2);
|
||||
setContent(f, "2", TIMESTAMP_INCREMENT * 2);
|
||||
Clock.setCurrentTimestamp(30);
|
||||
Clock.setCurrentTimestamp(3);
|
||||
setContent(f, "3", TIMESTAMP_INCREMENT * 3);
|
||||
|
||||
getVcs().getChangeListInTests().purgeObsolete(5);
|
||||
getVcs().getChangeListInTests().purgeObsolete(2);
|
||||
|
||||
assertContentAt(TIMESTAMP_INCREMENT, null);
|
||||
assertContentAt(TIMESTAMP_INCREMENT * 2, "2");
|
||||
|
||||
+7
-7
@@ -15,19 +15,19 @@
|
||||
*/
|
||||
package com.intellij.historyIntegrTests;
|
||||
|
||||
import com.intellij.history.core.LinkedStorage;
|
||||
import com.intellij.history.core.LocalHistoryStorage;
|
||||
import com.intellij.util.io.storage.AbstractStorage;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class LinkedStorageTest extends IntegrationTestCase {
|
||||
private LinkedStorage myStorage;
|
||||
public class LocalHistoryStorageTest extends IntegrationTestCase {
|
||||
private LocalHistoryStorage myStorage;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
myStorage = new LinkedStorage(myRoot.getPath() + "/storage");
|
||||
myStorage = new LocalHistoryStorage(myRoot.getPath() + "/storage");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -105,7 +105,7 @@ public class LinkedStorageTest extends IntegrationTestCase {
|
||||
myStorage.deleteRecord(r2);
|
||||
|
||||
myStorage.dispose();
|
||||
myStorage = new LinkedStorage(myRoot.getPath() + "/storage");
|
||||
myStorage = new LocalHistoryStorage(myRoot.getPath() + "/storage");
|
||||
|
||||
assertFirstAndLast(r1, r3);
|
||||
assertRecord(r3, r1, 0);
|
||||
@@ -114,7 +114,7 @@ public class LinkedStorageTest extends IntegrationTestCase {
|
||||
myStorage.deleteRecord(r1);
|
||||
|
||||
myStorage.dispose();
|
||||
myStorage = new LinkedStorage(myRoot.getPath() + "/storage");
|
||||
myStorage = new LocalHistoryStorage(myRoot.getPath() + "/storage");
|
||||
|
||||
assertFirstAndLast(r3, r3);
|
||||
assertRecord(r3, 0, 0);
|
||||
@@ -122,7 +122,7 @@ public class LinkedStorageTest extends IntegrationTestCase {
|
||||
int r4 = createRecord();
|
||||
|
||||
myStorage.dispose();
|
||||
myStorage = new LinkedStorage(myRoot.getPath() + "/storage");
|
||||
myStorage = new LocalHistoryStorage(myRoot.getPath() + "/storage");
|
||||
|
||||
assertFirstAndLast(r3, r4);
|
||||
assertRecord(r4, r3, 0);
|
||||
@@ -40,6 +40,13 @@ public class PurgingTest extends IntegrationTestCase {
|
||||
assertRemainedChangesTimestamps(3, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPurgeSeveral() {
|
||||
createChangesWithTimestamps(1, 2, 3);
|
||||
getVcs().getChangeListInTests().purgeObsolete(1);
|
||||
assertRemainedChangesTimestamps(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPurgeNothing() {
|
||||
createChangesWithTimestamps(1, 2, 3);
|
||||
|
||||
@@ -35,7 +35,7 @@ public abstract class AbstractRecordsTable implements Disposable, Forceable {
|
||||
protected static final int DEFAULT_HEADER_SIZE = 8;
|
||||
|
||||
private static final int VERSION = 5;
|
||||
private static final int CONNECTED_MAGIC = 0x12ad34e4;
|
||||
private static final int DIRTY_MAGIC = 0x12ad34e4;
|
||||
private static final int SAFELY_CLOSED_MAGIC = 0x1f2f3f4f + VERSION;
|
||||
|
||||
private static final int ADDRESS_OFFSET = 0;
|
||||
@@ -53,7 +53,7 @@ public abstract class AbstractRecordsTable implements Disposable, Forceable {
|
||||
myStorage = new RandomAccessDataFile(storageFilePath, pool);
|
||||
if (myStorage.length() == 0) {
|
||||
myStorage.put(0, new byte[getHeaderSize()], 0, getHeaderSize());
|
||||
myIsDirty = true;
|
||||
markDirty();
|
||||
}
|
||||
else {
|
||||
if (myStorage.getInt(HEADER_MAGIC_OFFSET) != getSafelyClosedMagic()) {
|
||||
@@ -77,13 +77,6 @@ public abstract class AbstractRecordsTable implements Disposable, Forceable {
|
||||
|
||||
protected abstract byte[] getZeros();
|
||||
|
||||
public void markDirty() {
|
||||
if (!myIsDirty) {
|
||||
myIsDirty = true;
|
||||
myStorage.putInt(HEADER_MAGIC_OFFSET, CONNECTED_MAGIC);
|
||||
}
|
||||
}
|
||||
|
||||
public int createNewRecord() throws IOException {
|
||||
markDirty();
|
||||
ensureFreeRecordsScanned();
|
||||
@@ -164,13 +157,11 @@ public abstract class AbstractRecordsTable implements Disposable, Forceable {
|
||||
|
||||
public void deleteRecord(final int record) throws IOException {
|
||||
ensureFreeRecordsScanned();
|
||||
cleanRecord(record);
|
||||
setSize(record, -1);
|
||||
clearDeletedRecord(record);
|
||||
myFreeRecordsList.add(record);
|
||||
}
|
||||
|
||||
protected abstract void clearDeletedRecord(int record);
|
||||
|
||||
public int getVersion() {
|
||||
return myStorage.getInt(HEADER_VERSION_OFFSET);
|
||||
}
|
||||
@@ -202,7 +193,14 @@ public abstract class AbstractRecordsTable implements Disposable, Forceable {
|
||||
}
|
||||
|
||||
public boolean isDirty() {
|
||||
return myIsDirty;
|
||||
return myIsDirty || myStorage.isDirty();
|
||||
}
|
||||
|
||||
public void markDirty() {
|
||||
if (!myIsDirty) {
|
||||
myIsDirty = true;
|
||||
myStorage.putInt(HEADER_MAGIC_OFFSET, DIRTY_MAGIC);
|
||||
}
|
||||
}
|
||||
|
||||
private void markClean() {
|
||||
|
||||
@@ -30,7 +30,7 @@ import java.io.IOException;
|
||||
|
||||
class DataTable implements Disposable, Forceable {
|
||||
private static final int HEADER_SIZE = 32;
|
||||
private static final int CONNECTED_MAGIC = 0x12ad34e4;
|
||||
private static final int DIRTY_MAGIC = 0x12ad34e4;
|
||||
private static final int SAFELY_CLOSED_MAGIC = 0x1f2f3f4f;
|
||||
|
||||
private final RandomAccessDataFile myFile;
|
||||
@@ -43,8 +43,7 @@ class DataTable implements Disposable, Forceable {
|
||||
public DataTable(final File filePath, final PagePool pool) throws IOException {
|
||||
myFile = new RandomAccessDataFile(filePath, pool);
|
||||
if (myFile.length() == 0) {
|
||||
fillInHeader(CONNECTED_MAGIC, 0);
|
||||
myIsDirty = true;
|
||||
markDirty();
|
||||
}
|
||||
else {
|
||||
readInHeader(filePath);
|
||||
@@ -125,7 +124,7 @@ class DataTable implements Disposable, Forceable {
|
||||
private void markDirty() {
|
||||
if (!myIsDirty) {
|
||||
myIsDirty = true;
|
||||
fillInHeader(CONNECTED_MAGIC, 0);
|
||||
fillInHeader(DIRTY_MAGIC, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,4 @@ class RecordsTable extends AbstractRecordsTable {
|
||||
return ZEROES;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clearDeletedRecord(int record) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,11 +47,6 @@ class RefCountingRecordsTable extends AbstractRecordsTable {
|
||||
return ZEROES;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clearDeletedRecord(int record) {
|
||||
myStorage.putInt(getOffset(record, REF_COUNT_OFFSET), 0);
|
||||
}
|
||||
|
||||
public void incRefCount(int record) {
|
||||
markDirty();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user