package org.wonderdb.cache.impl; /******************************************************************************* * 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.IOException; import java.nio.ByteBuffer; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.jboss.netty.buffer.ChannelBuffer; import org.wonderdb.cache.Cacheable; import org.wonderdb.cache.InflightReads; import org.wonderdb.file.FilePointerFactory; import org.wonderdb.file.StorageUtils; import org.wonderdb.seralizers.block.SerializedBlockImpl; import org.wonderdb.types.BlockPtr; public class InflightFileReader implements InflightReads<BlockPtr, ChannelBuffer> { ConcurrentMap<BlockPtr, BlockPtr> inflightPtrMap = new ConcurrentHashMap<BlockPtr, BlockPtr>(); private static InflightFileReader instance = new InflightFileReader(); private static CacheHandler<BlockPtr, ChannelBuffer> secondaryCacheHandler = SecondaryCacheHandlerFactory.getInstance().getCacheHandler(); private static SecondaryCacheResourceProvider secondaryResourceProvider = SecondaryCacheResourceProviderFactory.getInstance().getResourceProvider(); private InflightFileReader() { } public static InflightFileReader getInstance() { return instance; } @Override public Cacheable<BlockPtr, ChannelBuffer> getBlock(BlockPtr ptr) { BlockPtr p = inflightPtrMap.putIfAbsent(ptr, ptr); Cacheable<BlockPtr, ChannelBuffer> block = null; if (p == null) { block = readFromFile(ptr); secondaryCacheHandler.addIfAbsent(block); inflightPtrMap.remove(ptr); synchronized (ptr) { ptr.notifyAll(); } } else { block = secondaryCacheHandler.getFromCache(p); synchronized (p) { while (block == null) { try { p.wait(10); // break; } catch (InterruptedException e) { } block = secondaryCacheHandler.getFromCache(p); } } } return block; } private Cacheable<BlockPtr, ChannelBuffer> readFromFile(BlockPtr p) { ByteBuffer buffer = null; SerializedBlockImpl block = (SerializedBlockImpl) secondaryResourceProvider.getResource(p, StorageUtils.getInstance().getSmallestBlockCount(p)); block.getFullBuffer().clear(); block.getFullBuffer().writerIndex(block.getFullBuffer().capacity()); buffer = ByteBuffer.allocate(block.getFullBuffer().capacity()); try { FilePointerFactory.getInstance().readChannel(p.getFileId(), p.getBlockPosn(), buffer); } catch (IOException e) { throw new RuntimeException(e); } block.getFullBuffer().clear(); buffer.flip(); block.getFullBuffer().writeBytes(buffer); return block; } }