/** * Copyright 2007 The Apache Software Foundation * * 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 cn.ac.ncic.mastiff.io.coding; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.IntBuffer; import cn.ac.ncic.mastiff.Chunk; import cn.ac.ncic.mastiff.ValPair; import cn.ac.ncic.mastiff.io.RLEChunk; import cn.ac.ncic.mastiff.io.RLETriple; import cn.ac.ncic.mastiff.utils.Bytes; /** * <p> * Decode the <i>RLEChunk</i>s from a encode page. * An encoded page will produce multi <i>RLEChunk</i>s. * </p> * * @see RLEChunk */ public class GuoSiJieRLEDecoder implements Decoder { ValPair pair = new ValPair(); int valueLen; /** RLE related structures */ RLEChunk rleBlock; RLETriple rleTriple; ValPair pairInTriple; RLEChunk shadowChunk; RLETriple shadowTriple; ValPair shadowVP; /** Encoded page data */ byte[] page = null; int offset; int length; /** statistics of page data */ int numPairs; int startPos; /** used for iteration */ int curIdx = -1; int curTripleOffset; int curTripleLength; int tripleOffsetInPage; int curStartPos = -1; int curNumReps = 0; /** used for var-length cluster */ ByteBuffer bb; IntBuffer index = null; int indexOffset; public GuoSiJieRLEDecoder(int sortedCol, int valueLen_) { System.out.println("77 RLE Decoder "); System.out.println("sortedCol= "+sortedCol+" valueLen_ "+valueLen_); pairInTriple = new ValPair(); rleTriple = new RLETriple(pairInTriple, 0, 0); rleBlock = new RLEChunk(rleTriple, sortedCol); shadowVP = new ValPair(); shadowTriple = new RLETriple(shadowVP, 0, 0); shadowChunk = new RLEChunk(shadowTriple, sortedCol); valueLen = valueLen_; } @Override public ValPair begin() { System.out.println("92 begin "); pair.data = page; pair.offset = offset + 3 * Bytes.SIZEOF_INT; if (valueLen > 0) pair.length = valueLen; else { pair.length = index.get(0) - 3 * Bytes.SIZEOF_INT - 2 * Bytes.SIZEOF_INT; } pair.pos = startPos; return pair; } @Override public int beginPos() { return startPos; } @Override public ValPair end() { System.out.println("111 end()"); pair.data = page; if (valueLen > 0) { pair.offset = offset + 3 * Bytes.SIZEOF_INT + (numPairs - 1) * (valueLen + 2 * Bytes.SIZEOF_INT); pair.length = valueLen; } else { int prevOffset = numPairs == 1 ? 3 * Bytes.SIZEOF_INT : index.get(numPairs-2); pair.length = index.get(numPairs-1) - prevOffset - 2 * Bytes.SIZEOF_INT; pair.offset = offset + prevOffset; } int startPosInLastTriple = Bytes.toInt(page, pair.offset + pair.length); int numRepsInLastTriple = Bytes.toInt(page, pair.offset + pair.length + Bytes.SIZEOF_INT); pair.pos = startPosInLastTriple + numRepsInLastTriple - 1; return pair; } @Override public int endPos() { return end().pos; } @Override public byte[] getBuffer() { return page; } @Override public int getBufferLen() { return length; } @Override public int getNumPairs() { return endPos() - beginPos() + 1; } @Override public boolean hashNextChunk() { if (curIdx < 0 || curIdx >= numPairs) return false; else return true; } @Override public Chunk nextChunk() throws IOException { System.out.println("158 nextChunk()"); if (curIdx < 0 || curIdx >= numPairs) return null; curTripleLength = valueLen > 0 ? valueLen : index.get(curIdx) - tripleOffsetInPage - 2 * Bytes.SIZEOF_INT; pairInTriple.data = page; pairInTriple.offset = curTripleOffset; pairInTriple.length = curTripleLength; curStartPos = pairInTriple.pos = Bytes.toInt(page, curTripleOffset + curTripleLength, Bytes.SIZEOF_INT); curNumReps = Bytes.toInt(page, curTripleOffset + curTripleLength + Bytes.SIZEOF_INT, Bytes.SIZEOF_INT); rleTriple.setTriple(pairInTriple, pairInTriple.pos, curNumReps); curTripleOffset += curTripleLength + 2 * Bytes.SIZEOF_INT; tripleOffsetInPage += curTripleLength + 2 * Bytes.SIZEOF_INT; curIdx++; rleBlock.reset(); return rleBlock; } @Override public Chunk getChunkByPosition(int position) throws IOException { System.out.println("184 getchunkByPosition"); int begin = 0, end = numPairs - 1, mid, mid_pos, num_reps; int tripleOffset = -1, tripleLength = valueLen; // var length cluster while (begin <= end) { mid = (begin + end) / 2; if (valueLen < 0) { tripleOffset = mid == 0 ? 3 * Bytes.SIZEOF_INT : index.get(mid - 1); tripleLength = index.get(mid) - tripleOffset - 2 * Bytes.SIZEOF_INT; } else { tripleOffset = 3 * Bytes.SIZEOF_INT + mid * (valueLen + 2 * Bytes.SIZEOF_INT); } mid_pos = Bytes.toInt(page, offset + tripleOffset + tripleLength); num_reps = Bytes.toInt(page, offset + tripleOffset + tripleLength + Bytes.SIZEOF_INT); if (mid_pos <= position && position < mid_pos + num_reps) { shadowVP.data = page; shadowVP.offset = offset + tripleOffset; shadowVP.length = tripleLength; shadowTriple.setTriple(shadowVP, mid_pos, num_reps); shadowChunk.reset(); return shadowChunk; } else if (position < mid_pos) { end = mid - 1; } else { begin = mid + 1; } } return null; } @Override public void reset() { curIdx = -1; } @Override public void reset(byte[] buffer, int offset, int length) throws IOException { System.out.println("214 RLEDecoder reset "); this.page = buffer; this.offset = offset; this.length = length; numPairs = Bytes.toInt(page, offset + Bytes.SIZEOF_INT, Bytes.SIZEOF_INT); curIdx = 0; curStartPos = -1; curTripleOffset = offset + 3 * Bytes.SIZEOF_INT; tripleOffsetInPage = 3 * Bytes.SIZEOF_INT; if (valueLen < 0) { indexOffset = this.length - numPairs * Bytes.SIZEOF_INT; // System.out.println("Index offset in Page is " + indexOffset); bb = ByteBuffer.wrap(page, offset + indexOffset, numPairs * Bytes.SIZEOF_INT); index = bb.asIntBuffer(); } int tmpTripleLength = valueLen > 0 ? valueLen : index.get(0) - tripleOffsetInPage - 2 * Bytes.SIZEOF_INT; startPos = Bytes.toInt(page, curTripleOffset + tmpTripleLength, Bytes.SIZEOF_INT); } @Override public boolean skipToPos(int pos) { if (curStartPos == -1) { curTripleLength = valueLen > 0 ? valueLen : index.get(curIdx) - tripleOffsetInPage - 2 * Bytes.SIZEOF_INT; curStartPos = Bytes.toInt(page, curTripleOffset + curTripleLength, Bytes.SIZEOF_INT); curNumReps = Bytes.toInt(page, curTripleOffset + curTripleLength + Bytes.SIZEOF_INT, Bytes.SIZEOF_INT); } while(curStartPos + curNumReps < pos && curIdx < numPairs) { curTripleOffset += (curTripleLength + 2 * Bytes.SIZEOF_INT); tripleOffsetInPage += (curTripleLength + 2 * Bytes.SIZEOF_INT); curTripleLength = valueLen > 0 ? valueLen : index.get(curIdx) - tripleOffsetInPage - 2 * Bytes.SIZEOF_INT; curStartPos = Bytes.toInt(page, curTripleOffset + curTripleLength, Bytes.SIZEOF_INT); curNumReps = Bytes.toInt(page, curTripleOffset + curTripleLength + Bytes.SIZEOF_INT, Bytes.SIZEOF_INT); curIdx++; } if (curIdx >= numPairs) return false; else return true; } @Override public byte[] ensureDecompressed() throws IOException { // TODO Auto-generated method stub return null; } }