blob: 3a79f4983dd9a7ca03a2020b22c0b24ee7b607e3 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.ignite.internal.processors.cache.persistence.file;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.function.IntSupplier;
import java.util.function.LongConsumer;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.internal.pagemem.store.PageStore;
import org.apache.ignite.lang.IgniteOutClosure;
/**
* Checks version in files if it's present on the disk, creates store with latest version otherwise.
*/
public class FileVersionCheckingFactory {
/** Property to override latest version. Should be used only in tests. */
public static final String LATEST_VERSION_OVERRIDE_PROPERTY = "file.page.store.latest.version.override";
/** Latest page store version. */
public static final int LATEST_VERSION = 2;
/** Factory to provide I/O interfaces for read/write operations with files. */
private final FileIOFactory fileIOFactory;
/**
* Factory to provide I/O interfaces for read/write operations with files.
* This is backup factory for V1 page store.
*/
private final FileIOFactory fileIOFactoryStoreV1;
/** Memory configuration. */
private final IntSupplier pageSize;
/**
* @param fileIOFactory File IO factory.
* @param fileIOFactoryStoreV1 File IO factory for V1 page store and for version checking.
* @param pageSize Page size supplier.
*/
public FileVersionCheckingFactory(
FileIOFactory fileIOFactory,
FileIOFactory fileIOFactoryStoreV1,
IntSupplier pageSize
) {
this.fileIOFactory = fileIOFactory;
this.fileIOFactoryStoreV1 = fileIOFactoryStoreV1;
this.pageSize = pageSize;
}
/**
* Creates instance of PageStore based on given file.
*
* @param type Data type, can be {@link PageStore#TYPE_IDX} or {@link PageStore#TYPE_DATA}.
* @param file File Page store file.
* @param allocatedTracker metrics updater.
* @return page store
* @throws IgniteCheckedException if failed.
*/
public PageStore createPageStore(byte type, File file, LongConsumer allocatedTracker) throws IgniteCheckedException {
return createPageStore(type, file::toPath, allocatedTracker);
}
/**
* Creates instance of PageStore based on file path provider.
*
* @param type Data type, can be {@link PageStore#TYPE_IDX} or {@link PageStore#TYPE_DATA}
* @param pathProvider File Page store path provider.
* @param allocatedTracker metrics updater
* @return page store
* @throws IgniteCheckedException if failed
*/
public PageStore createPageStore(
byte type,
IgniteOutClosure<Path> pathProvider,
LongConsumer allocatedTracker
) throws IgniteCheckedException {
Path filePath = pathProvider.apply();
if (!Files.exists(filePath))
return createPageStore(type, pathProvider, pageSize.getAsInt(), latestVersion(), allocatedTracker);
try (FileIO fileIO = fileIOFactoryStoreV1.create(filePath.toFile())) {
int minHdr = FilePageStore.HEADER_SIZE;
if (fileIO.size() < minHdr)
return createPageStore(type, pathProvider, pageSize.getAsInt(), latestVersion(), allocatedTracker);
ByteBuffer hdr = ByteBuffer.allocate(minHdr).order(ByteOrder.nativeOrder());
fileIO.readFully(hdr);
hdr.rewind();
hdr.getLong(); // Read signature
int ver = hdr.getInt();
return createPageStore(type, pathProvider, pageSize.getAsInt(), ver, allocatedTracker);
}
catch (IOException e) {
throw new IgniteCheckedException("Error while creating file page store [file=" + filePath.toAbsolutePath() + "]:", e);
}
}
/**
* Resolves latest page store version.
*/
public int latestVersion() {
int latestVer = LATEST_VERSION;
try {
latestVer = Integer.parseInt(System.getProperty(LATEST_VERSION_OVERRIDE_PROPERTY));
} catch (NumberFormatException ignore) {
// No override.
}
return latestVer;
}
/**
* Instantiates specific version of FilePageStore.
*
* @param type Type.
* @param ver Version.
* @param pageSize Page size.
* @param allocatedTracker Metrics updater
*/
private FilePageStore createPageStore(
byte type,
IgniteOutClosure<Path> pathProvider,
int pageSize,
int ver,
LongConsumer allocatedTracker
) {
switch (ver) {
case FilePageStore.VERSION:
return new FilePageStore(type, pathProvider, fileIOFactoryStoreV1, pageSize, allocatedTracker);
case FilePageStoreV2.VERSION:
return new FilePageStoreV2(type, pathProvider, fileIOFactory, pageSize, allocatedTracker);
default:
throw new IllegalArgumentException(
"Unknown version of file page store: " + ver + " for file [" + pathProvider.apply().toAbsolutePath() + "]"
);
}
}
/**
* @param ver Version.
* @return Header size.
*/
public int headerSize(int ver) {
switch (ver) {
case FilePageStore.VERSION:
return FilePageStore.HEADER_SIZE;
case FilePageStoreV2.VERSION:
return pageSize.getAsInt();
default:
throw new IllegalArgumentException("Unknown version of file page store.");
}
}
}