[vcs-log] get rid of VcsRootsRegistry

Since hash map stores data in a file for a specific set of roots, we do not need root indexes to be consistent in a project, only in a specific set of roots. This means we do not need to store roots on disk at all. This solves various issues with having another PE.
This commit is contained in:
Julia Beliaeva
2016-06-25 20:48:33 +03:00
parent cc0368eab1
commit 87145fa71c
5 changed files with 26 additions and 129 deletions
@@ -19,8 +19,6 @@
serviceImplementation="com.intellij.vcs.log.data.VcsLogTabsProperties"/>
<projectService serviceInterface="com.intellij.vcs.log.VcsUserRegistry"
serviceImplementation="com.intellij.vcs.log.data.VcsUserRegistryImpl"/>
<projectService serviceInterface="com.intellij.vcs.log.impl.VcsRootsRegistry"
serviceImplementation="com.intellij.vcs.log.impl.VcsRootsRegistryImpl"/>
<statistics.usagesCollector implementation="com.intellij.vcs.log.statistics.VcsLogRepoSizeCollector"/>
<statistics.usagesCollector implementation="com.intellij.vcs.log.statistics.VcsLogFeaturesCollector"/>
@@ -16,7 +16,6 @@
package com.intellij.vcs.log.data;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
@@ -32,15 +31,17 @@ import com.intellij.vcs.log.Hash;
import com.intellij.vcs.log.VcsLogHashMap;
import com.intellij.vcs.log.VcsLogProvider;
import com.intellij.vcs.log.impl.HashImpl;
import com.intellij.vcs.log.impl.VcsRootsRegistry;
import com.intellij.vcs.log.util.PersistentUtil;
import gnu.trove.TObjectIntHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Supports the int <-> Hash persistent mapping.
@@ -72,17 +73,24 @@ public class VcsLogHashMapImpl implements Disposable, VcsLogHashMap {
@NotNull private static final Logger LOG = Logger.getInstance(VcsLogHashMap.class);
@NotNull private static final String LOG_KIND = "hashes";
private static final int VERSION = 2;
private static final int VERSION = 3;
private static final int NO_INDEX = -1;
@NotNull private final PersistentEnumerator<CommitId> myPersistentEnumerator;
@NotNull private final Consumer<Exception> myExceptionReporter;
public VcsLogHashMapImpl(@NotNull final Project project, @NotNull Map<VirtualFile, VcsLogProvider> logProviders, @NotNull Consumer<Exception> exceptionReporter, @NotNull Disposable parent) throws IOException {
public VcsLogHashMapImpl(@NotNull Project project,
@NotNull Map<VirtualFile, VcsLogProvider> logProviders,
@NotNull Consumer<Exception> exceptionReporter,
@NotNull Disposable parent) throws IOException {
myExceptionReporter = exceptionReporter;
myPersistentEnumerator =
PersistentUtil.createPersistentEnumerator(new MyCommitIdKeyDescriptor(project), LOG_KIND,
PersistentUtil.calcLogId(project, logProviders), VERSION);
List<VirtualFile> roots =
logProviders.keySet().stream().sorted((o1, o2) -> o1.getPath().compareTo(o2.getPath())).collect(Collectors.toList());
myPersistentEnumerator = PersistentUtil.createPersistentEnumerator(new MyCommitIdKeyDescriptor(roots), LOG_KIND,
PersistentUtil.calcLogId(project, logProviders), VERSION);
Disposer.register(parent, this);
}
@@ -160,22 +168,28 @@ public class VcsLogHashMapImpl implements Disposable, VcsLogHashMap {
}
private static class MyCommitIdKeyDescriptor implements KeyDescriptor<CommitId> {
@NotNull private final VcsRootsRegistry myRootsRegistry;
@NotNull private final List<VirtualFile> myRoots;
@NotNull private final TObjectIntHashMap<VirtualFile> myRootsReversed;
public MyCommitIdKeyDescriptor(@NotNull Project project) {
myRootsRegistry = ServiceManager.getService(project, VcsRootsRegistry.class);
public MyCommitIdKeyDescriptor(@NotNull List<VirtualFile> roots) {
myRoots = roots;
myRootsReversed = new TObjectIntHashMap<>();
for (int i = 0; i < roots.size(); i++) {
myRootsReversed.put(roots.get(i), i);
}
}
@Override
public void save(@NotNull DataOutput out, CommitId value) throws IOException {
((HashImpl)value.getHash()).write(out);
out.writeInt(myRootsRegistry.getId(value.getRoot()));
out.writeInt(myRootsReversed.get(value.getRoot()));
}
@Override
public CommitId read(@NotNull DataInput in) throws IOException {
Hash hash = HashImpl.read(in);
VirtualFile root = myRootsRegistry.getRootById(in.readInt());
VirtualFile root = myRoots.get(in.readInt());
if (root == null) return null;
return new CommitId(hash, root);
}
@@ -1,29 +0,0 @@
/*
* Copyright 2000-2015 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.vcs.log.impl;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
public interface VcsRootsRegistry {
int getId(@NotNull VirtualFile root) throws IOException;
@Nullable
VirtualFile getRootById(int id) throws IOException;
}
@@ -1,78 +0,0 @@
/*
* Copyright 2000-2016 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.vcs.log.impl;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.io.PersistentStringEnumerator;
import com.intellij.vcs.log.util.PersistentUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
public class VcsRootsRegistryImpl implements VcsRootsRegistry, Disposable {
@NotNull private static final Logger LOG = Logger.getInstance(VcsRootsRegistry.class);
@NotNull private static final String LOG_KIND = "roots";
@NotNull private final PersistentStringEnumerator myEnumerator;
private static final int VERSION = 0;
public VcsRootsRegistryImpl(@NotNull final Project project) {
myEnumerator = createEnumerator(project);
}
@NotNull
private static PersistentStringEnumerator createEnumerator(@NotNull Project project) {
try {
return PersistentUtil
.createPersistentStringEnumerator(LOG_KIND, project.getName() + "." + project.getBaseDir().getPath().hashCode(), VERSION);
}
catch (IOException e) {
throw new RuntimeException("Can not create persistent storage for vcs roots.", e);
}
}
@Override
public void dispose() {
try {
myEnumerator.close();
}
catch (IOException e) {
LOG.error(e);
}
}
@Override
public int getId(@NotNull VirtualFile root) throws IOException {
return myEnumerator.enumerate(root.getPath());
}
@Override
@Nullable
public VirtualFile getRootById(int id) throws IOException {
String path = myEnumerator.valueOf(id);
if (path == null) throw new RuntimeException("Can not find path by id " + id);
VirtualFile file = LocalFileSystem.getInstance().findFileByPath(path);
if (file == null) {
LOG.info("Can not find file by path " + path);
return null;
}
return file;
}
}
@@ -64,12 +64,4 @@ public class PersistentUtil {
return IOUtil.openCleanOrResetBroken(() -> new PersistentEnumerator<>(storageFile, keyDescriptor, Page.PAGE_SIZE), storageFile);
}
@NotNull
public static PersistentStringEnumerator createPersistentStringEnumerator(@NotNull String logKind, @NotNull String logId, int version)
throws IOException {
final File storageFile = getStorageFile(logId, logKind, version);
return IOUtil.openCleanOrResetBroken(() -> new PersistentStringEnumerator(storageFile), storageFile);
}
}