/**
* 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 io.horizondb.db.databases;
import io.horizondb.db.Configuration;
import io.horizondb.db.HorizonDBFiles;
import io.horizondb.db.btree.AbstractNodeReader;
import io.horizondb.db.btree.AbstractNodeWriter;
import io.horizondb.db.btree.NodeManager;
import io.horizondb.db.btree.NodeReader;
import io.horizondb.db.btree.NodeReaderFactory;
import io.horizondb.db.btree.NodeWriter;
import io.horizondb.db.btree.NodeWriterFactory;
import io.horizondb.db.btree.OnDiskNodeManager;
import io.horizondb.db.series.TimeSeriesManager;
import io.horizondb.io.ByteReader;
import io.horizondb.io.ByteWriter;
import io.horizondb.io.encoding.VarInts;
import io.horizondb.io.files.FileDataOutput;
import io.horizondb.io.files.FileUtils;
import io.horizondb.io.files.SeekableFileDataInput;
import io.horizondb.model.schema.DatabaseDefinition;
import java.io.IOException;
import java.nio.file.Path;
import com.codahale.metrics.MetricRegistry;
import static io.horizondb.io.files.FileUtils.createDirectoriesIfNeeded;
/**
* <code>DatabaseManager</code> that store all data on disk.
*/
public final class OnDiskDatabaseManager extends AbstractDatabaseManager {
/**
* Creates a new <code>InMemoryDatabaseManager</code> that will used the specified configuration.
*
* @param configuration the database configuration
* @param timeSeriesManager the time series manager
*/
public OnDiskDatabaseManager(Configuration configuration, TimeSeriesManager timeSeriesManager) {
super(configuration, timeSeriesManager);
}
/**
* {@inheritDoc}
*/
@Override
protected NodeManager<String, DatabaseDefinition> createNodeManager(Configuration configuration,
String name)
throws IOException {
createDirectoriesIfNeeded(HorizonDBFiles.getSystemDirectory(configuration));
Path databasesFile = HorizonDBFiles.getDatabasesFile(configuration);
return new OnDiskNodeManager<>(MetricRegistry.name(name, "bTree"),
databasesFile,
DatabaseDefinitionNodeWriter.FACTORY,
DatabaseDefinitionNodeReader.FACTORY);
}
/**
* {@inheritDoc}
*/
@Override
protected void afterCreate(DatabaseDefinition definition) throws IOException {
Path directory = HorizonDBFiles.getDatabaseDirectory(this.configuration, definition);
FileUtils.createDirectoriesIfNeeded(directory);
}
/**
* <code>NodeWriter</code> for the <code>DatabaseDefinition</code>.
*
*/
private static class DatabaseDefinitionNodeWriter extends AbstractNodeWriter<String, DatabaseDefinition> {
/**
* The <code>NodeWriter</code> factory.
*/
public static final NodeWriterFactory<String, DatabaseDefinition> FACTORY = new NodeWriterFactory<String, DatabaseDefinition>() {
/**
* {@inheritDoc}
*/
@Override
public NodeWriter<String, DatabaseDefinition> newWriter(FileDataOutput output) throws IOException {
return new DatabaseDefinitionNodeWriter(output);
}
};
/**
* Creates a new <code>DatabaseDefinitionNodeWriter</code> that write to the specified output.
*
* @param output the output used by the writer.
* @throws IOException if an I/O problem occurs.
*/
public DatabaseDefinitionNodeWriter(FileDataOutput output) throws IOException {
super(output);
}
/**
* {@inheritDoc}
*/
@Override
protected int computeKeySize(String name) {
return VarInts.computeStringSize(name);
}
/**
* {@inheritDoc}
*/
@Override
protected int computeValueSize(DatabaseDefinition definition) {
return definition.computeSerializedSize();
}
/**
* {@inheritDoc}
*/
@Override
protected void writeKey(ByteWriter writer, String name) throws IOException {
VarInts.writeString(writer, name);
}
/**
* {@inheritDoc}
*/
@Override
protected void writeValue(ByteWriter writer, DatabaseDefinition definition) throws IOException {
writer.writeObject(definition);
}
}
/**
* <code>NodeReader</code> for the <code>DatabaseDefinition</code>.
*
*/
private static final class DatabaseDefinitionNodeReader extends AbstractNodeReader<String, DatabaseDefinition> {
/**
* The <code>NodeReader</code> factory.
*/
public static final NodeReaderFactory<String, DatabaseDefinition> FACTORY = new NodeReaderFactory<String, DatabaseDefinition>() {
/**
* {@inheritDoc}
*/
@Override
public NodeReader<String, DatabaseDefinition> newReader(SeekableFileDataInput input) throws IOException {
return new DatabaseDefinitionNodeReader(input);
}
};
/**
* Creates a new <code>DatabaseDefinitionNodeReader</code> that read from the specified input.
*
* @param input the input used by the reader.
* @throws IOException if an I/O problem occurs.
*/
public DatabaseDefinitionNodeReader(SeekableFileDataInput input) throws IOException {
super(input);
}
/**
* {@inheritDoc}
*/
@Override
protected DatabaseDefinition readValue(ByteReader reader) throws IOException {
return DatabaseDefinition.parseFrom(reader);
}
/**
* {@inheritDoc}
*/
@Override
protected String readKey(ByteReader reader) throws IOException {
return VarInts.readString(reader);
}
}
}