blob: 8c6a2c1529ab5141285fa7aae1faad29adf9ca5a [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.jackrabbit.oak.index.indexer.document.flatfile;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import com.google.common.base.Stopwatch;
import org.apache.commons.io.FileUtils;
import org.apache.jackrabbit.oak.index.indexer.document.NodeStateEntry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static com.google.common.base.StandardSystemProperty.LINE_SEPARATOR;
import static org.apache.jackrabbit.oak.commons.IOUtils.humanReadableByteCount;
import static org.apache.jackrabbit.oak.index.indexer.document.flatfile.FlatFileNodeStoreBuilder.OAK_INDEXER_MAX_SORT_MEMORY_IN_GB;
import static org.apache.jackrabbit.oak.index.indexer.document.flatfile.FlatFileNodeStoreBuilder.OAK_INDEXER_MAX_SORT_MEMORY_IN_GB_DEFAULT;
import static org.apache.jackrabbit.oak.index.indexer.document.flatfile.FlatFileStoreUtils.getSortedStoreFileName;
class StoreAndSortStrategy implements SortStrategy {
private static final String OAK_INDEXER_DELETE_ORIGINAL = "oak.indexer.deleteOriginal";
private static final int LINE_SEP_LENGTH = LINE_SEPARATOR.value().length();
private final Logger log = LoggerFactory.getLogger(getClass());
private final Iterable<NodeStateEntry> nodeStates;
private final PathElementComparator comparator;
private final NodeStateEntryWriter entryWriter;
private final File storeDir;
private final boolean compressionEnabled;
private long entryCount;
private boolean deleteOriginal = Boolean.parseBoolean(System.getProperty(OAK_INDEXER_DELETE_ORIGINAL, "true"));
private int maxMemory = Integer.getInteger(OAK_INDEXER_MAX_SORT_MEMORY_IN_GB, OAK_INDEXER_MAX_SORT_MEMORY_IN_GB_DEFAULT);
private long textSize;
public StoreAndSortStrategy(Iterable<NodeStateEntry> nodeStates, PathElementComparator comparator,
NodeStateEntryWriter entryWriter, File storeDir, boolean compressionEnabled) {
this.nodeStates = nodeStates;
this.comparator = comparator;
this.entryWriter = entryWriter;
this.storeDir = storeDir;
this.compressionEnabled = compressionEnabled;
}
@Override
public File createSortedStoreFile() throws IOException {
File storeFile = writeToStore(storeDir, getStoreFileName());
return sortStoreFile(storeFile);
}
@Override
public long getEntryCount() {
return entryCount;
}
private File sortStoreFile(File storeFile) throws IOException {
File sortWorkDir = new File(storeFile.getParent(), "sort-work-dir");
FileUtils.forceMkdir(sortWorkDir);
File sortedFile = new File(storeFile.getParentFile(), getSortedStoreFileName(compressionEnabled));
NodeStateEntrySorter sorter =
new NodeStateEntrySorter(comparator, storeFile, sortWorkDir, sortedFile);
logFlags();
sorter.setUseZip(compressionEnabled);
sorter.setMaxMemoryInGB(maxMemory);
sorter.setDeleteOriginal(deleteOriginal);
sorter.setActualFileSize(textSize);
sorter.sort();
return sorter.getSortedFile();
}
private File writeToStore(File dir, String fileName) throws IOException {
entryCount = 0;
File file = new File(dir, fileName);
Stopwatch sw = Stopwatch.createStarted();
try (BufferedWriter w = FlatFileStoreUtils.createWriter(file, compressionEnabled)) {
for (NodeStateEntry e : nodeStates) {
String line = entryWriter.toString(e);
w.append(line);
w.newLine();
textSize += line.length() + LINE_SEP_LENGTH;
entryCount++;
}
}
String sizeStr = compressionEnabled ? String.format("compressed/%s actual size", humanReadableByteCount(textSize)) : "";
log.info("Dumped {} nodestates in json format in {} ({} {})",entryCount, sw, humanReadableByteCount(file.length()), sizeStr);
return file;
}
private void logFlags() {
log.info("Delete original dump from traversal : {} ({})", deleteOriginal, OAK_INDEXER_DELETE_ORIGINAL);
log.info("Max heap memory (GB) to be used for merge sort : {} ({})", maxMemory, OAK_INDEXER_MAX_SORT_MEMORY_IN_GB);
}
private String getStoreFileName() {
return compressionEnabled ? "store.json.gz" : "store.json";
}
}