org.iq80.leveldb.memenv.MemFs Maven / Gradle / Ivy
The newest version!
/*
* Copyright (C) 2011 the original author or authors.
* See the notice.md file distributed with this work for additional
* information regarding copyright ownership.
*
* 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 org.iq80.leveldb.memenv;
import org.iq80.leveldb.env.DbLock;
import org.iq80.leveldb.env.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
class MemFs
{
public static final char SEPARATOR_CHAR = '/';
public static final String SEPARATOR = "/";
private final Object lock = new Object();
private final Set dirs = new HashSet<>();
private final Map maps = new HashMap<>();
public File createTempDir(String prefix)
{
synchronized (lock) {
MemFile e;
do {
String baseName = "/";
if (prefix != null) {
baseName += prefix + "-";
}
baseName += System.currentTimeMillis() + "-";
e = MemFile.createMemFile(this, baseName);
} while (maps.containsKey(e) || !dirs.add(e));
e.mkdirs();
return e;
}
}
public FileState requireFile(MemFile file) throws FileNotFoundException
{
FileState fileState;
synchronized (lock) {
fileState = maps.get(file);
if (fileState == null) {
throw new FileNotFoundException(file.getPath());
}
}
return fileState;
}
public FileState getOrCreateFile(MemFile file) throws IOException
{
FileState fileState;
synchronized (lock) {
if (dirs.contains(file)) {
throw new IOException(file + " is a directory");
}
if (!dirs.contains(file.getParentFile())) {
throw new IOException("Unable to create file " + file + ", parent directory does not exist");
}
fileState = maps.computeIfAbsent(file, memFile -> new FileState());
}
return fileState;
}
public boolean mkdirs(MemFile memFile)
{
synchronized (lock) {
if (maps.containsKey(memFile)) {
return false;
}
dirs.add(memFile);
return true;
}
}
public boolean canRead(MemFile memFile)
{
synchronized (lock) {
return maps.containsKey(memFile);
}
}
public boolean isFile(MemFile memFile)
{
return canRead(memFile);
}
public boolean isDirectory(MemFile memFile)
{
synchronized (lock) {
return dirs.contains(memFile);
}
}
public Optional getFileState(MemFile file)
{
synchronized (lock) {
return Optional.ofNullable(maps.get(file));
}
}
public boolean delete(MemFile memFile)
{
synchronized (lock) {
return maps.remove(memFile) != null || dirs.remove(memFile);
}
}
public List listFiles(MemFile memFile)
{
synchronized (lock) {
return children(memFile).collect(Collectors.toList());
}
}
private Stream children(MemFile memFile)
{
String s = memFile.getPath() + SEPARATOR;
return Stream.concat(maps.keySet().stream(), dirs.stream())
.filter(e -> e.getPath().startsWith(s))
.map(e -> {
int i = e.getPath().indexOf(SEPARATOR, s.length());
return i >= 0 ? MemFile.createMemFile(this, e.getPath().substring(0, i)) : e;
})
.distinct();
}
public boolean renameTo(MemFile from, MemFile dest)
{
synchronized (lock) {
if (isDirectory(from)) {
//not supported, not required by DB
return false;
}
if (maps.containsKey(from) && !maps.containsKey(dest)) {
maps.put(dest, maps.get(from));
maps.remove(from);
return true;
}
}
return false;
}
public boolean deleteRecursively(MemFile memFile)
{
String prefix = memFile.getPath() + SEPARATOR;
synchronized (lock) {
boolean r = false;
for (Iterator iterator = dirs.iterator(); iterator.hasNext(); ) {
MemFile dir = iterator.next();
if (dir.equals(memFile) || dir.getPath().startsWith(prefix)) {
iterator.remove();
r = true;
}
}
for (Iterator> iterator = maps.entrySet().iterator(); iterator.hasNext(); ) {
Map.Entry entry = iterator.next();
if (entry.getKey().equals(memFile) || entry.getKey().getPath().startsWith(prefix)) {
iterator.remove();
r = true;
}
}
return r;
}
}
public boolean exists(MemFile memFile)
{
synchronized (lock) {
return dirs.contains(memFile) || maps.containsKey(memFile);
}
}
public DbLock doLock(MemFile file) throws IOException
{
final FileState orCreateFile;
synchronized (lock) {
orCreateFile = getOrCreateFile(file);
if (orCreateFile.isLocked()) {
throw new IOException("lock on " + file + " already owned");
}
orCreateFile.setLocked(true);
}
return new MemDbLock(orCreateFile);
}
private class MemDbLock implements DbLock
{
private final FileState file;
private boolean released;
public MemDbLock(FileState file)
{
this.file = file;
}
@Override
public boolean isValid()
{
synchronized (lock) {
return !released;
}
}
@Override
public void release()
{
synchronized (lock) {
if (!released) {
released = true;
file.setLocked(false);
}
}
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy