package org.wonderdb.file; /******************************************************************************* * Copyright 2013 Vilas Athavale * * 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. *******************************************************************************/ import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.AsynchronousFileChannel; import java.nio.channels.FileChannel; import java.nio.file.OpenOption; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.wonderdb.server.WonderDBPropertyManager; import org.wonderdb.thread.WonderDBThreadFactory; import org.wonderdb.types.FileBlockEntry; public class FilePointerFactory { private Map<Byte, AsynchronousFileChannel> asyncChannelMap = new ConcurrentHashMap<Byte, AsynchronousFileChannel>(); private Map<Byte, BlockingQueue<FileChannel>> syncChannelMap = new ConcurrentHashMap<Byte, BlockingQueue<FileChannel>>(); private Map<Byte, RandomAccessFile> fileMap = new ConcurrentHashMap<Byte, RandomAccessFile>(); ExecutorService executor = null; private static FilePointerFactory pool = new FilePointerFactory(); private FilePointerFactory() { int asyncCoreSize = WonderDBPropertyManager.getInstance().getDiskAsyncWriterThreadPoolSize(); WonderDBThreadFactory t = new WonderDBThreadFactory("diskAsyncWriter"); executor = new ThreadPoolExecutor (asyncCoreSize, asyncCoreSize, 5, TimeUnit.MINUTES, new ArrayBlockingQueue<Runnable>(20), t); } public static FilePointerFactory getInstance() { return pool; } public void shutdown() { // executor.shutdown(); } public void create(FileBlockEntry entry) { Path path = Paths.get(entry.getFileName()); AsynchronousFileChannel afc = null; try { Set<OpenOption> set = new HashSet<OpenOption>(); set.add(StandardOpenOption.READ); set.add(StandardOpenOption.WRITE); set.add(StandardOpenOption.CREATE); // afc = AsynchronousFileChannel.open(path, StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE); afc = AsynchronousFileChannel.open(path, set, executor); asyncChannelMap.put(entry.getFileId(), afc); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } BlockingQueue<FileChannel> q1 = new ArrayBlockingQueue<FileChannel>(5); syncChannelMap.put(entry.getFileId(), q1); for (int i = 0; i < 5; i++) { path = Paths.get(entry.getFileName()); FileChannel fc = null; try { fc = FileChannel.open(path, StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } q1.add(fc); } try { RandomAccessFile raf = new RandomAccessFile(entry.getFileName(), "rw"); if (raf.length() < entry.getBlockSize()*10000) { raf.setLength(entry.getBlockSize()*10000); } fileMap.put(entry.getFileId(), raf); } catch (FileNotFoundException e) { } catch (IOException e1) { } } public synchronized void closAll() { executor.shutdownNow(); Iterator<BlockingQueue<FileChannel>> syncIter = syncChannelMap.values().iterator(); while (syncIter.hasNext()) { BlockingQueue<FileChannel> syncChannels = syncIter.next(); for (int closed = 0; closed < 5; closed++) { FileChannel fc = null;; try { fc = syncChannels.take(); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } try { fc.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } public void writeChannel(byte fileId, long posn, ByteBuffer buffer) throws IOException { BlockingQueue<FileChannel> q = syncChannelMap.get(fileId); FileChannel fc; try { fc = q.take(); fc.write(buffer, posn); q.add(fc); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void readChannel(byte fileId, long posn, ByteBuffer buffer) throws IOException { readChannel(fileId, posn, 0, buffer); } public void readChannel(byte fileId, long posn, long sleep, ByteBuffer buffer) throws IOException { if (sleep > 0) { try { Thread.sleep(sleep); } catch (InterruptedException e) { } } BlockingQueue<FileChannel> q = syncChannelMap.get(fileId); FileChannel fc; try { fc = q.take(); fc.read(buffer, posn); q.add(fc); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } AsynchronousFileChannel getAsyncChannel(byte fileId) { return asyncChannelMap.get(fileId); } public long increaseSizeBy(byte fileId, long size) { RandomAccessFile raf = fileMap.get(fileId); long currentSize = -1; synchronized (raf) { try { currentSize = raf.length(); raf.setLength(currentSize+size); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return currentSize; } }