/** * Get the IOEngine from the IO engine name * @param ioEngineName * @param capacity * @param persistencePath * @return the IOEngine * @throws IOException */ private IOEngine getIOEngineFromName(String ioEngineName, long capacity, String persistencePath) throws IOException { if (ioEngineName.startsWith("file:") || ioEngineName.startsWith("files:")) { // In order to make the usage simple, we only need the prefix 'files:' in // document whether one or multiple file(s), but also support 'file:' for // the compatibility String[] filePaths = ioEngineName.substring(ioEngineName.indexOf(":") + 1) .split(FileIOEngine.FILE_DELIMITER); return new FileIOEngine(capacity, persistencePath != null, filePaths); } else if (ioEngineName.startsWith("offheap")) { return new ByteBufferIOEngine(capacity); } else if (ioEngineName.startsWith("mmap:")) { return new FileMmapEngine(ioEngineName.substring(5), capacity); } else { throw new IllegalArgumentException( "Don't understand io engine name for cache- prefix with file:, files:, mmap: or offheap"); } }
public FileMmapEngine(String filePath, long capacity) throws IOException { this.path = filePath; this.size = capacity; long fileSize = 0; try { raf = new RandomAccessFile(filePath, "rw"); fileSize = roundUp(capacity, ByteBufferArray.DEFAULT_BUFFER_SIZE); raf.setLength(fileSize); fileChannel = raf.getChannel(); LOG.info("Allocating " + StringUtils.byteDesc(fileSize) + ", on the path:" + filePath); } catch (java.io.FileNotFoundException fex) { LOG.error("Can't create bucket cache file " + filePath, fex); throw fex; } catch (IOException ioex) { LOG.error("Can't extend bucket cache file; insufficient space for " + StringUtils.byteDesc(fileSize), ioex); shutdown(); throw ioex; } ByteBufferAllocator allocator = new ByteBufferAllocator() { AtomicInteger pos = new AtomicInteger(0); @Override public ByteBuffer allocate(long size) throws IOException { ByteBuffer buffer = fileChannel.map(java.nio.channels.FileChannel.MapMode.READ_WRITE, pos.getAndIncrement() * size, size); return buffer; } }; bufferArray = new ByteBufferArray(fileSize, allocator); }
@Test public void testFileMmapEngine() throws IOException { int size = 2 * 1024 * 1024; // 2 MB String filePath = "testFileMmapEngine"; try { FileMmapEngine fileMmapEngine = new FileMmapEngine(filePath, size); for (int i = 0; i < 50; i++) { int len = (int) Math.floor(Math.random() * 100); long offset = (long) Math.floor(Math.random() * size % (size - len)); byte[] data1 = new byte[len]; for (int j = 0; j < data1.length; ++j) { data1[j] = (byte) (Math.random() * 255); } fileMmapEngine.write(ByteBuffer.wrap(data1), offset); BufferGrabbingDeserializer deserializer = new BufferGrabbingDeserializer(); fileMmapEngine.read(offset, len, deserializer); ByteBuff data2 = deserializer.getDeserializedByteBuff(); for (int j = 0; j < data1.length; ++j) { assertTrue(data1[j] == data2.get(j)); } } } finally { File file = new File(filePath); if (file.exists()) { file.delete(); } } } }
@Test public void testFileMmapEngine() throws IOException { int size = 2 * 1024 * 1024; // 2 MB String filePath = "testFileMmapEngine"; try { FileMmapEngine fileMmapEngine = new FileMmapEngine(filePath, size); for (int i = 0; i < 50; i++) { int len = (int) Math.floor(Math.random() * 100); long offset = (long) Math.floor(Math.random() * size % (size - len)); byte[] data1 = new byte[len]; for (int j = 0; j < data1.length; ++j) { data1[j] = (byte) (Math.random() * 255); } fileMmapEngine.write(ByteBuffer.wrap(data1), offset); BufferGrabbingDeserializer deserializer = new BufferGrabbingDeserializer(); fileMmapEngine.read(offset, len, deserializer); ByteBuff data2 = deserializer.getDeserializedByteBuff(); for (int j = 0; j < data1.length; ++j) { assertTrue(data1[j] == data2.get(j)); } } } finally { File file = new File(filePath); if (file.exists()) { file.delete(); } } } }