blob: 662839c6f99f19690a8859248b2f6e3f1133cb8d [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.binary;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.concurrent.ConcurrentMap;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteLogger;
import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.binary.BinaryMetadata;
import org.apache.ignite.internal.binary.BinaryUtils;
import org.apache.ignite.internal.util.typedef.internal.CU;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.jetbrains.annotations.Nullable;
/**
* Class handles saving/restoring binary metadata to/from disk.
*
* Current implementation needs to be rewritten as it issues IO operations from discovery thread
* which may lead to segmentation of nodes from cluster.
*/
class BinaryMetadataFileStore {
/** Link to resolved binary metadata directory. Null for non persistent mode */
private File workDir;
/** */
private final ConcurrentMap<Integer, BinaryMetadataHolder> metadataLocCache;
/** */
private final GridKernalContext ctx;
/** */
private final IgniteLogger log;
/**
* @param metadataLocCache Metadata locale cache.
* @param ctx Context.
* @param log Logger.
* @param binaryMetadataFileStoreDir Path to binary metadata store configured by user, should include binary_meta and consistentId
*/
BinaryMetadataFileStore(
final ConcurrentMap<Integer, BinaryMetadataHolder> metadataLocCache,
final GridKernalContext ctx,
final IgniteLogger log,
@Nullable final File binaryMetadataFileStoreDir
) throws IgniteCheckedException {
this.metadataLocCache = metadataLocCache;
this.ctx = ctx;
this.log = log;
if (!CU.isPersistenceEnabled(ctx.config()))
return;
if (binaryMetadataFileStoreDir != null)
workDir = binaryMetadataFileStoreDir;
else {
final String subFolder = ctx.pdsFolderResolver().resolveFolders().folderName();
workDir = new File(U.resolveWorkDirectory(
ctx.config().getWorkDirectory(),
"binary_meta",
false
),
subFolder);
}
U.ensureDirectory(workDir, "directory for serialized binary metadata", log);
}
/**
* @param binMeta Binary metadata to be written to disk.
*/
void writeMetadata(BinaryMetadata binMeta) {
if (!CU.isPersistenceEnabled(ctx.config()))
return;
try {
File file = new File(workDir, Integer.toString(binMeta.typeId()) + ".bin");
try(FileOutputStream out = new FileOutputStream(file, false)) {
byte[] marshalled = U.marshal(ctx, binMeta);
out.write(marshalled);
}
}
catch (Exception e) {
U.warn(log, "Failed to save metadata for typeId: " + binMeta.typeId() +
"; exception was thrown: " + e.getMessage());
}
}
/**
* Restores metadata on startup of {@link CacheObjectBinaryProcessorImpl} but before starting discovery.
*/
void restoreMetadata() {
if (!CU.isPersistenceEnabled(ctx.config()))
return;
for (File file : workDir.listFiles()) {
try (FileInputStream in = new FileInputStream(file)) {
BinaryMetadata meta = U.unmarshal(ctx.config().getMarshaller(), in, U.resolveClassLoader(ctx.config()));
metadataLocCache.put(meta.typeId(), new BinaryMetadataHolder(meta, 0, 0));
}
catch (Exception e) {
U.warn(log, "Failed to restore metadata from file: " + file.getName() +
"; exception was thrown: " + e.getMessage());
}
}
}
/**
* Checks if binary metadata for the same typeId is already presented on disk.
* If so merges it with new metadata and stores the result.
* Otherwise just writes new metadata.
*
* @param binMeta new binary metadata to write to disk.
*/
void mergeAndWriteMetadata(BinaryMetadata binMeta) {
BinaryMetadata existingMeta = readMetadata(binMeta.typeId());
if (existingMeta != null) {
BinaryMetadata mergedMeta = BinaryUtils.mergeMetadata(existingMeta, binMeta);
writeMetadata(mergedMeta);
} else
writeMetadata(binMeta);
}
/**
* Reads binary metadata for given typeId.
*
* @param typeId typeId of BinaryMetadata to be read.
*/
private BinaryMetadata readMetadata(int typeId) {
File file = new File(workDir, Integer.toString(typeId) + ".bin");
if (!file.exists())
return null;
try (FileInputStream in = new FileInputStream(file)) {
return U.unmarshal(ctx.config().getMarshaller(), in, U.resolveClassLoader(ctx.config()));
}
catch (Exception e) {
U.warn(log, "Failed to restore metadata from file: " + file.getName() +
"; exception was thrown: " + e.getMessage());
}
return null;
}
}