/*
* 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.nifi.provenance.store.iterator;
import static org.junit.Assert.assertEquals;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.nifi.provenance.EventIdFirstSchemaRecordWriter;
import org.apache.nifi.provenance.IdentifierLookup;
import org.apache.nifi.provenance.ProvenanceEventRecord;
import org.apache.nifi.provenance.TestUtil;
import org.apache.nifi.provenance.serialization.RecordReaders;
import org.apache.nifi.provenance.serialization.RecordWriter;
import org.apache.nifi.provenance.store.RecordReaderFactory;
import org.apache.nifi.provenance.toc.StandardTocWriter;
import org.apache.nifi.provenance.toc.TocUtil;
import org.apache.nifi.provenance.toc.TocWriter;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
public class TestSelectiveRecordReaderEventIterator {
private RecordWriter createWriter(final File file, final TocWriter tocWriter, final boolean compressed, final int uncompressedBlockSize) throws IOException {
return new EventIdFirstSchemaRecordWriter(file, new AtomicLong(0L), tocWriter, compressed, uncompressedBlockSize, IdentifierLookup.EMPTY);
}
@Test
public void testFilterUnneededFiles() {
final File file1 = new File("1.prov");
final File file1000 = new File("1000.prov");
final File file2000 = new File("2000.prov");
final File file3000 = new File("3000.prov");
// Filter out the first file.
final List<File> files = new ArrayList<>();
files.add(file1);
files.add(file1000);
files.add(file2000);
files.add(file3000);
List<Long> eventIds = new ArrayList<>();
eventIds.add(1048L);
eventIds.add(2048L);
eventIds.add(3048L);
List<File> filteredFiles = SelectiveRecordReaderEventIterator.filterUnneededFiles(files, eventIds);
assertEquals(Arrays.asList(new File[] {file1000, file2000, file3000}), filteredFiles);
// Filter out file at end
eventIds.clear();
eventIds.add(1L);
eventIds.add(1048L);
filteredFiles = SelectiveRecordReaderEventIterator.filterUnneededFiles(files, eventIds);
assertEquals(Arrays.asList(new File[] {file1, file1000}), filteredFiles);
}
@Test
@Ignore("For local testing only. Runs indefinitely")
public void testPerformanceOfRandomAccessReads() throws Exception {
final File dir = new File("target/storage/" + UUID.randomUUID().toString());
final File journalFile = new File(dir, "/4.prov.gz");
final File tocFile = TocUtil.getTocFile(journalFile);
final int blockSize = 1024 * 32;
try (final RecordWriter writer = createWriter(journalFile, new StandardTocWriter(tocFile, true, false), true, blockSize)) {
writer.writeHeader(0L);
for (int i = 0; i < 100_000; i++) {
writer.writeRecord(TestUtil.createEvent());
}
}
final Long[] eventIds = new Long[] {
4L, 80L, 1024L, 1025L, 1026L, 1027L, 1028L, 1029L, 1030L, 40_000L, 80_000L, 99_000L
};
final RecordReaderFactory readerFactory = (file, logs, maxChars) -> RecordReaders.newRecordReader(file, logs, maxChars);
final List<File> files = new ArrayList<>();
files.add(new File(dir, "0.prov"));
files.add(new File(dir, "0.prov"));
files.add(new File(dir, "1.prov"));
files.add(new File(dir, "2.prov"));
files.add(new File(dir, "3.prov"));
files.add(journalFile);
files.add(new File(dir, "100000000.prov"));
boolean loopForever = true;
while (loopForever) {
final long start = System.nanoTime();
for (int i = 0; i < 1000; i++) {
final SelectiveRecordReaderEventIterator iterator = new SelectiveRecordReaderEventIterator(
Collections.singletonList(journalFile), readerFactory, Arrays.asList(eventIds), 32 * 1024);
for (final long id : eventIds) {
time(() -> {
return iterator.nextEvent().orElse(null);
}, id);
}
}
final long ms = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
System.out.println(ms + " ms total");
}
}
private void time(final Callable<ProvenanceEventRecord> task, final long id) throws Exception {
final long start = System.nanoTime();
final ProvenanceEventRecord event = task.call();
Assert.assertNotNull(event);
Assert.assertEquals(id, event.getEventId());
// System.out.println(event);
final long nanos = System.nanoTime() - start;
final long millis = TimeUnit.NANOSECONDS.toMillis(nanos);
// System.out.println("Took " + millis + " ms to " + taskDescription);
}
}