package io.eguan.nrs; /* * #%L * Project eguan * %% * Copyright (C) 2012 - 2017 Oodrive * %% * 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. * #L% */ import io.eguan.configuration.MetaConfiguration; import io.eguan.nrs.NrsAbstractFile; import io.eguan.nrs.NrsException; import io.eguan.nrs.NrsFileFlag; import io.eguan.nrs.NrsFileHeader; import io.eguan.nrs.NrsMsgPostOffice; import io.eguan.nrs.NrsStorageConfigKey; import io.eguan.utils.SimpleIdentifierProvider; import io.eguan.utils.UuidT; import io.eguan.utils.mapper.FileMapper; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.OverlappingFileLockException; import java.nio.file.AccessDeniedException; import java.nio.file.NoSuchFileException; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; import java.util.Random; import java.util.Set; import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicBoolean; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Test class for {@link NrsAbstractFile}. * * @author oodrive * @author llambert * */ public abstract class TestNrsAbstractFiles<T, U> extends AbstractNrsTestFixture { private static final Logger LOGGER = LoggerFactory.getLogger(TestNrsAbstractFiles.class); /** Base dir */ private File tempBaseDir; protected FileMapper fileMapper; /** * Factory of {@link NrsAbstractFile}. * * @return a new {@link NrsAbstractFile}. */ abstract NrsAbstractFile<T, U> newNrsAbstractFile(final FileMapper fileMapper, final NrsFileHeader<U> header, final NrsMsgPostOffice postOffice); abstract int getWriteSize(int hashSize, int blockSize); abstract T getTrimElement(); abstract T newRandomElement(int size); abstract void nextRandomElement(T e, Random random); abstract T newEmptyElement(int size); abstract void releaseElement(T e); abstract void assertEqualsElements(T e1, T e2); @Before public void setUp() { final MetaConfiguration config = getConfiguration(); tempBaseDir = NrsStorageConfigKey.getInstance().getTypedValue(config); Assert.assertTrue(tempBaseDir.isDirectory()); fileMapper = FileMapper.Type.FLAT.newInstance(tempBaseDir, 32, config); } /** * Create and delete a NrsAbstractFile. * * @throws IOException */ @Test public void testCreateNrsAbstractFile() throws IOException { testCreateNrsAbstractFile(false, false); } @Test public void testCreateNrsAbstractFileRoot() throws IOException { testCreateNrsAbstractFile(true, false); } @Test public void testCreateNrsAbstractFilePartial() throws IOException { testCreateNrsAbstractFile(false, true); } @Test public void testCreateNrsAbstractFileRootPartial() throws IOException { testCreateNrsAbstractFile(true, true); } /** * Creating of an empty {@link NrsAbstractFile}. * * @throws IOException */ @Test public void testNrsAbstractFileEmpty() throws IOException { testCreateNrsAbstractFile(true, false, true, false, false); } @Test public void testNrsAbstractFileSmallCluster() throws IOException { testCreateNrsAbstractFile(true, false, false, true, false); } @Test public void testNrsAbstractFileRounded() throws IOException { testCreateNrsAbstractFile(false, true, false, false, true); } @Test public void testNrsAbstractFileSmallClusterRounded() throws IOException { testCreateNrsAbstractFile(true, false, false, true, true); } @Test public void testNrsAbstractFileSmallClusterEmpty() throws IOException { testCreateNrsAbstractFile(true, false, true, true, false); } private void testCreateNrsAbstractFile(final boolean root, final boolean partial) throws IOException { testCreateNrsAbstractFile(root, partial, false, false, false); } private void testCreateNrsAbstractFile(final boolean root, final boolean partial, final boolean empty, final boolean smallCluster, final boolean roundedBlockCount) throws IOException { final int blockSize = 3510; final int hashSize = smallCluster ? 4 : 150; // Must put 2 elements in a cluster (for test purpose, small cluster size) final int clusterSize = getWriteSize(hashSize, blockSize) * (smallCluster ? 4 : 123); final int writeSize = getWriteSize(hashSize, blockSize); final int size = empty ? 0 : blockSize * (roundedBlockCount ? (smallCluster ? (5 * clusterSize) : 15) * (hashSize + 1) : 56370); final NrsFileHeader.Builder<U> headerBuilder = new NrsFileHeader.Builder<>(); final UuidT<U> parent = SimpleIdentifierProvider.newId(); headerBuilder.parent(parent); final UUID device = UUID.randomUUID(); headerBuilder.device(device); final UUID node = UUID.randomUUID(); headerBuilder.node(node); final UuidT<U> fileId = SimpleIdentifierProvider.newId(); headerBuilder.file(fileId); headerBuilder.size(size); headerBuilder.blockSize(blockSize); headerBuilder.hashSize(hashSize); headerBuilder.clusterSize(clusterSize); final long now = System.currentTimeMillis(); headerBuilder.timestamp(now); if (root) { headerBuilder.addFlags(NrsFileFlag.ROOT); } if (partial) { headerBuilder.addFlags(NrsFileFlag.PARTIAL); } final NrsAbstractFile<T, U> nrsFile; { final NrsFileHeader<U> header = headerBuilder.build(); LOGGER.info("Header " + header); nrsFile = newNrsAbstractFile(fileMapper, header, null); } // Not created yet Assert.assertEquals(parent, nrsFile.getDescriptor().getParentId()); Assert.assertEquals(device, nrsFile.getDescriptor().getDeviceId()); Assert.assertEquals(node, nrsFile.getDescriptor().getNodeId()); Assert.assertEquals(fileId, nrsFile.getDescriptor().getFileId()); Assert.assertEquals(size, nrsFile.getDescriptor().getSize()); Assert.assertEquals(blockSize, nrsFile.getDescriptor().getBlockSize()); Assert.assertEquals(hashSize, nrsFile.getDescriptor().getHashSize()); Assert.assertEquals(clusterSize, nrsFile.getDescriptor().getClusterSize()); Assert.assertEquals(now, nrsFile.getDescriptor().getTimestamp()); Assert.assertTrue(root == nrsFile.getDescriptor().isRoot()); Assert.assertTrue(partial == nrsFile.getDescriptor().isPartial()); Assert.assertFalse(nrsFile.isOpened()); Assert.assertFalse(nrsFile.isWriteable()); Assert.assertEquals(0, nrsFile.getFile().toFile().length()); Assert.assertFalse(nrsFile.getFile().toFile().exists()); if (empty) { Assert.assertEquals(0, nrsFile.getVersion()); } else { try { nrsFile.getVersion(); throw new AssertionError("Not reachable"); } catch (final NoSuchFileException e) { // ok } } // Create file nrsFile.create(); LOGGER.info("Create " + nrsFile); // Try to create twice try { nrsFile.create(); throw new AssertionError("Not reachable"); } catch (final NrsException e) { // ok } Assert.assertEquals(parent, nrsFile.getDescriptor().getParentId()); Assert.assertEquals(device, nrsFile.getDescriptor().getDeviceId()); Assert.assertEquals(node, nrsFile.getDescriptor().getNodeId()); Assert.assertEquals(fileId, nrsFile.getDescriptor().getFileId()); Assert.assertEquals(size, nrsFile.getDescriptor().getSize()); Assert.assertEquals(blockSize, nrsFile.getDescriptor().getBlockSize()); Assert.assertEquals(hashSize, nrsFile.getDescriptor().getHashSize()); Assert.assertEquals(clusterSize, nrsFile.getDescriptor().getClusterSize()); Assert.assertEquals(now, nrsFile.getDescriptor().getTimestamp()); Assert.assertTrue(root == nrsFile.getDescriptor().isRoot()); Assert.assertTrue(partial == nrsFile.getDescriptor().isPartial()); Assert.assertFalse(nrsFile.isOpened()); Assert.assertTrue(nrsFile.isWriteable()); Assert.assertTrue(nrsFile.getFile().toFile().isFile()); Assert.assertEquals(0L, nrsFile.getVersion()); if (empty) { Assert.assertEquals(NrsFileHeader.HEADER_LENGTH, nrsFile.getFile().toFile().length()); } else if (smallCluster) { Assert.assertEquals(0, nrsFile.getDescriptor().getH1Address() % clusterSize); Assert.assertEquals(0, nrsFile.getFile().toFile().length() % clusterSize); } else { Assert.assertEquals(clusterSize, nrsFile.getDescriptor().getH1Address()); Assert.assertEquals(0, nrsFile.getFile().toFile().length() % clusterSize); } // Init block for read/write with random data final T block = newRandomElement(writeSize); // Version reached after IOs final long version; // Open RW nrsFile.open(false); try { Assert.assertTrue(nrsFile.isOpened()); Assert.assertTrue(nrsFile.isWriteable()); // Try to open twice try { nrsFile.open(false); throw new AssertionError("Not reachable"); } catch (final IllegalStateException e) { // ok } // Try to delete try { nrsFile.delete(); throw new AssertionError("Not reachable"); } catch (final IllegalStateException e) { // ok } // Try to set not writable try { nrsFile.setNotWritable(); throw new AssertionError("Not reachable"); } catch (final IllegalStateException e) { // ok } // Read/write blocks // ----------------- final int blockCount = size / blockSize; try { nrsFile.read(-1); throw new AssertionError("Not reachable"); } catch (final IndexOutOfBoundsException e) { // ok } try { nrsFile.write(-1, block); throw new AssertionError("Not reachable"); } catch (final IndexOutOfBoundsException e) { // ok } try { nrsFile.read(blockCount); throw new AssertionError("Not reachable"); } catch (final IndexOutOfBoundsException e) { // ok } try { nrsFile.write(blockCount, block); throw new AssertionError("Not reachable"); } catch (final IndexOutOfBoundsException e) { // ok } try { nrsFile.read(blockCount + 1); throw new AssertionError("Not reachable"); } catch (final IndexOutOfBoundsException e) { // ok } try { nrsFile.write(blockCount + 1, block); throw new AssertionError("Not reachable"); } catch (final IndexOutOfBoundsException e) { // ok } // Version should not have changed yet Assert.assertEquals(0L, nrsFile.getVersion()); if (empty) { // Check we can not read/write anything from empty file (prev tests) Assert.assertEquals(0, blockCount); version = 0L; } else { // Write invalid element size {// reduce scope of variable final T elem = newEmptyElement(writeSize - 1); try { nrsFile.write(0, elem); throw new AssertionError("Not reachable"); } catch (final IllegalArgumentException e) { // ok } finally { releaseElement(elem); } } { final T elem = newEmptyElement(writeSize + 1); try { nrsFile.write(0, elem); throw new AssertionError("Not reachable"); } catch (final IllegalArgumentException e) { // ok } finally { releaseElement(elem); } } { final T elem = newEmptyElement(0); try { nrsFile.write(0, elem); throw new AssertionError("Not reachable"); } catch (final IllegalArgumentException e) { // ok } finally { releaseElement(elem); } } // Version should not have changed yet Assert.assertEquals(0L, nrsFile.getVersion()); final long fileSize = nrsFile.getFile().toFile().length(); Assert.assertEquals(0, fileSize % clusterSize); // Read at the beginning (no write yet) Assert.assertNull(nrsFile.read(0)); // Write a block at the beginning nrsFile.write(0, block); final T read0 = nrsFile.read(0); assertEqualsElements(block, read0); releaseElement(read0); Assert.assertNull(nrsFile.read(1)); Assert.assertEquals(1L, nrsFile.getVersion()); // New cluster allocated Assert.assertEquals(fileSize + clusterSize, nrsFile.getFile().toFile().length()); // New block, same cluster nrsFile.write(2, block); final T read2 = nrsFile.read(2); assertEqualsElements(block, read2); releaseElement(read2); Assert.assertNull(nrsFile.read(1)); Assert.assertEquals(fileSize + clusterSize, nrsFile.getFile().toFile().length()); Assert.assertEquals(2L, nrsFile.getVersion()); // New block, new cluster final int newClusterBlock = nrsFile.computeL2Capacity() + 1; nrsFile.write(newClusterBlock, block); final T readNew = nrsFile.read(newClusterBlock); assertEqualsElements(block, readNew); releaseElement(readNew); Assert.assertNull(nrsFile.read(1)); Assert.assertEquals(fileSize + 2 * clusterSize, nrsFile.getFile().toFile().length()); Assert.assertEquals(3L, nrsFile.getVersion()); // Revert last block nrsFile.reset(newClusterBlock); Assert.assertNull(nrsFile.read(newClusterBlock)); Assert.assertNull(nrsFile.read(1)); Assert.assertEquals(fileSize + 2 * clusterSize, nrsFile.getFile().toFile().length()); Assert.assertEquals(4L, nrsFile.getVersion()); version = 4L; } } finally { nrsFile.close(); } // close() does nothing if the file is close nrsFile.close(); // Can get the version if the file is closed Assert.assertEquals(version, nrsFile.getVersion()); // Can not read or write if closed try { nrsFile.read(0); throw new AssertionError("Not reachable"); } catch (final IllegalStateException e) { // ok } {// reduce scope of variable final T elem = newEmptyElement(writeSize); try { nrsFile.write(0, elem); throw new AssertionError("Not reachable"); } catch (final IllegalStateException e) { // ok } finally { releaseElement(elem); } } Assert.assertFalse(nrsFile.isOpened()); Assert.assertTrue(nrsFile.isWriteable()); // Open RO nrsFile.open(true); try { Assert.assertTrue(nrsFile.isOpened()); Assert.assertTrue(nrsFile.isWriteable()); // Can get the version if the file is opened Assert.assertEquals(version, nrsFile.getVersion()); } finally { nrsFile.close(); } Assert.assertFalse(nrsFile.isOpened()); Assert.assertTrue(nrsFile.isWriteable()); // File not more writable nrsFile.setNotWritable(); Assert.assertFalse(nrsFile.isWriteable()); // Can get the version if the file is closed, not writable Assert.assertEquals(version, nrsFile.getVersion()); // Open RW try { nrsFile.open(false); throw new AssertionError("Not reachable"); } catch (final AccessDeniedException e) { // ok } Assert.assertFalse(nrsFile.isOpened()); Assert.assertFalse(nrsFile.isWriteable()); // Open RO nrsFile.open(true); try { Assert.assertTrue(nrsFile.isOpened()); Assert.assertFalse(nrsFile.isWriteable()); // Can get the version if the file is opened, not writable Assert.assertEquals(version, nrsFile.getVersion()); // Can not write if (empty) { final T elem = newEmptyElement(writeSize); try { nrsFile.write(0, elem); throw new AssertionError("Not reachable"); } catch (final IndexOutOfBoundsException e) { // ok } finally { releaseElement(elem); } } else { final T elem = newEmptyElement(writeSize); try { nrsFile.write(0, elem); throw new AssertionError("Not reachable"); } catch (final IllegalStateException e) { // ok } finally { releaseElement(elem); } final T read0 = nrsFile.read(0); assertEqualsElements(block, read0); releaseElement(read0); Assert.assertNull(nrsFile.read(1)); } } finally { nrsFile.close(); } Assert.assertFalse(nrsFile.isOpened()); Assert.assertFalse(nrsFile.isWriteable()); // Read file header final File file = nrsFile.getFile().toFile(); { final byte[] contents = new byte[(int) file.length()]; try (FileInputStream fis = new FileInputStream(file)) { fis.read(contents); } final ByteBuffer buffer = ByteBuffer.wrap(contents); final NrsFileHeader<U> headerRead = NrsFileHeader.readFromBuffer(buffer); Assert.assertEquals(parent, headerRead.getParentId()); Assert.assertEquals(device, headerRead.getDeviceId()); Assert.assertEquals(node, headerRead.getNodeId()); Assert.assertEquals(fileId, headerRead.getFileId()); Assert.assertEquals(size, headerRead.getSize()); Assert.assertEquals(blockSize, headerRead.getBlockSize()); Assert.assertEquals(hashSize, headerRead.getHashSize()); Assert.assertEquals(clusterSize, headerRead.getClusterSize()); Assert.assertEquals(now, headerRead.getTimestamp()); Assert.assertTrue(root == headerRead.isRoot()); Assert.assertTrue(partial == headerRead.isPartial()); if (empty) { Assert.assertEquals(NrsFileHeader.HEADER_LENGTH, nrsFile.getFile().toFile().length()); } // New NrsAbstractFile instance { final NrsAbstractFile<T, U> nrsFileNew = newNrsAbstractFile(fileMapper, headerRead, null); Assert.assertEquals(parent, nrsFileNew.getDescriptor().getParentId()); Assert.assertEquals(device, nrsFileNew.getDescriptor().getDeviceId()); Assert.assertEquals(node, nrsFileNew.getDescriptor().getNodeId()); Assert.assertEquals(fileId, nrsFileNew.getDescriptor().getFileId()); Assert.assertEquals(size, nrsFileNew.getDescriptor().getSize()); Assert.assertEquals(blockSize, nrsFileNew.getDescriptor().getBlockSize()); Assert.assertEquals(hashSize, nrsFileNew.getDescriptor().getHashSize()); Assert.assertEquals(clusterSize, nrsFileNew.getDescriptor().getClusterSize()); Assert.assertEquals(now, nrsFileNew.getDescriptor().getTimestamp()); Assert.assertTrue(root == nrsFileNew.getDescriptor().isRoot()); Assert.assertTrue(partial == nrsFileNew.getDescriptor().isPartial()); Assert.assertFalse(nrsFileNew.isOpened()); Assert.assertFalse(nrsFileNew.isWriteable()); if (empty) { Assert.assertEquals(NrsFileHeader.HEADER_LENGTH, nrsFileNew.getFile().toFile().length()); } Assert.assertTrue(nrsFileNew.getFile().toFile().exists()); Assert.assertEquals(version, nrsFileNew.getVersion()); } } // Release block releaseElement(block); // Delete file nrsFile.delete(); Assert.assertEquals(parent, nrsFile.getDescriptor().getParentId()); Assert.assertEquals(device, nrsFile.getDescriptor().getDeviceId()); Assert.assertEquals(node, nrsFile.getDescriptor().getNodeId()); Assert.assertEquals(fileId, nrsFile.getDescriptor().getFileId()); Assert.assertEquals(size, nrsFile.getDescriptor().getSize()); Assert.assertEquals(blockSize, nrsFile.getDescriptor().getBlockSize()); Assert.assertEquals(hashSize, nrsFile.getDescriptor().getHashSize()); Assert.assertEquals(clusterSize, nrsFile.getDescriptor().getClusterSize()); Assert.assertEquals(now, nrsFile.getDescriptor().getTimestamp()); Assert.assertTrue(root == nrsFile.getDescriptor().isRoot()); Assert.assertTrue(partial == nrsFile.getDescriptor().isPartial()); Assert.assertFalse(nrsFile.isOpened()); Assert.assertFalse(nrsFile.isWriteable()); Assert.assertEquals(0, nrsFile.getFile().toFile().length()); Assert.assertFalse(nrsFile.getFile().toFile().exists()); } /** * Test access to the file from 2 instances. * * @throws IOException */ @Test public void testConcurrentFileAccess() throws IOException { final int blockSize = 6541; final int size = 56370 * blockSize; final int hashSize = 664; final int clusterSize = (int) (getWriteSize(hashSize, blockSize) * 2.33); final Set<NrsFileFlag> flags = EnumSet.noneOf(NrsFileFlag.class); flags.add(NrsFileFlag.ROOT); final NrsFileHeader.Builder<U> headerBuilder = newHeaderBuilder(size, blockSize, hashSize, clusterSize, flags); final NrsFileHeader<U> header = headerBuilder.build(); Assert.assertTrue(header.isRoot()); Assert.assertFalse(header.isPartial()); // Create file1 final NrsAbstractFile<T, U> file1 = newNrsAbstractFile(fileMapper, header, null); file1.create(); try { // Create file2 final NrsAbstractFile<T, U> file2 = newNrsAbstractFile(fileMapper, header, null); // Open file1 RW file1.open(false); try { try { file2.open(true); throw new AssertionError("Not reachable"); } catch (final OverlappingFileLockException e) { // ok } try { file2.open(false); throw new AssertionError("Not reachable"); } catch (final OverlappingFileLockException e) { // ok } } finally { file1.close(); } // Open file2 RO file2.open(true); try { try { // Can not get two shared lock from the same JVM (yet?) file1.open(true); throw new AssertionError("Not reachable"); } catch (final OverlappingFileLockException e) { // ok } try { file1.open(false); throw new AssertionError("Not reachable"); } catch (final OverlappingFileLockException e) { // ok } } finally { file2.close(); } } finally { file1.delete(); } } /** * Read, write and reset some elements in a NrsAbstractFile. * */ final class NrsAbstractFilePartReadWrite implements Callable<Void> { private final NrsAbstractFile<T, U> file; private final T element; private final int blockCount; private final int firstBlockIndex; final AtomicBoolean goOn = new AtomicBoolean(true); NrsAbstractFilePartReadWrite(final NrsAbstractFile<T, U> file, final int writeSize, final int blockCount, final int firstBlockIndex) { super(); this.file = file; this.element = newEmptyElement(writeSize); this.blockCount = blockCount; this.firstBlockIndex = firstBlockIndex; } @Override public final Void call() throws Exception { int blockIndex = firstBlockIndex; final int blockIndexMax = firstBlockIndex + blockCount; final Random rand = new Random(); while (goOn.get()) { Assert.assertNull(file.read(blockIndex)); nextRandomElement(element, rand); file.write(blockIndex, element); final T hashRead = file.read(blockIndex); assertEqualsElements(element, hashRead); releaseElement(hashRead); file.trim(blockIndex); Assert.assertSame(getTrimElement(), file.read(blockIndex)); file.reset(blockIndex); Assert.assertNull(file.read(blockIndex)); blockIndex++; if (blockIndex >= blockIndexMax) { blockIndex = firstBlockIndex; } } releaseElement(element); return null; } } /** * Multi threaded read/write access to a {@link NrsAbstractFile}. * * @throws Exception */ @Test public void testMultiThreadAccess() throws Exception { final int threadCount = Runtime.getRuntime().availableProcessors(); final int blockSize = 4 * 1024; final int blockCount = 512; // per thread final long size = threadCount * blockSize * blockCount; final int hashSize = 20; final int writeSize = getWriteSize(hashSize, blockSize); final int clusterSize = writeSize * 11; final Set<NrsFileFlag> flags = EnumSet.noneOf(NrsFileFlag.class); // Create NrsAbstractFile final NrsFileHeader.Builder<U> headerBuilder = newHeaderBuilder(size, blockSize, hashSize, clusterSize, flags); final NrsFileHeader<U> header = headerBuilder.build(); final NrsAbstractFile<T, U> nrsFile = newNrsAbstractFile(fileMapper, header, null); nrsFile.create(); nrsFile.open(false); try { final ExecutorService exec = Executors.newFixedThreadPool(threadCount); final List<NrsAbstractFilePartReadWrite> tasks = new ArrayList<>(threadCount); for (int i = 0; i < threadCount; i++) { tasks.add(new NrsAbstractFilePartReadWrite(nrsFile, writeSize, blockCount, i * blockCount)); } // Start tasks final List<Future<Void>> threads = new ArrayList<>(threadCount); for (final NrsAbstractFilePartReadWrite task : tasks) { threads.add(exec.submit(task)); } Thread.sleep(8 * 1000); // Shutdown tasks for (final NrsAbstractFilePartReadWrite task : tasks) { task.goOn.set(false); } // Check tasks run. Make sure all the threads are done before closing the file Exception testException = null; for (final Future<Void> thread : threads) { try { thread.get(); } catch (final Exception e) { testException = e; } } if (testException != null) { throw testException; } } finally { nrsFile.close(); } } protected final NrsFileHeader.Builder<U> newHeaderBuilder(final long size, final int blockSize, final int hashSize, final int clusterSize, final Set<NrsFileFlag> flags) { final NrsFileHeader.Builder<U> headerBuilder = new NrsFileHeader.Builder<>(); final UuidT<U> parent = SimpleIdentifierProvider.newId(); headerBuilder.parent(parent); final UUID device = UUID.randomUUID(); headerBuilder.device(device); final UUID node = UUID.randomUUID(); headerBuilder.node(node); final UuidT<U> fileId = SimpleIdentifierProvider.newId(); headerBuilder.file(fileId); headerBuilder.size(size); headerBuilder.blockSize(blockSize); headerBuilder.hashSize(hashSize); headerBuilder.clusterSize(clusterSize); final long now = System.currentTimeMillis(); headerBuilder.timestamp(now); headerBuilder.flags(flags); return headerBuilder; } }