blob: 9c7d113a67e3198eee297cf930c1d8ef952d7c39 [file] [log] [blame]
/*
* Copyright (c) 2016 Audi AG
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.mdm.mdfsorter.mdf4;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.LinkedList;
import java.util.NoSuchElementException;
import java.util.logging.Level;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
import org.eclipse.mdm.mdfsorter.MDFSorter;
public class ZippedDataCache {
// private TreeMap<DZBLOCK, byte[]> cache;
private LinkedList<DZBLOCK> cacheblocks;
private LinkedList<byte[]> cachedata;
private FileChannel reader;
private static final int MAXENTRIES = 3;
public ZippedDataCache(FileChannel reader) {
cacheblocks = new LinkedList<DZBLOCK>();
cachedata = new LinkedList<byte[]>();
this.reader = reader;
}
public boolean isAvailable(DZBLOCK dzblk) {
return cacheblocks.contains(dzblk);
}
public byte[] getData(DZBLOCK dzblk) {
if (cacheblocks.contains(dzblk)) {
return cachedata.get(cacheblocks.indexOf(dzblk));
}
throw new NoSuchElementException("Element not found in Data Cache.");
}
/**
* Load an DZBLOCK into Cache
*
* @param dzblk
* The dzblock to load.
* @throws DataFormatException
* If zipped data is in an invalid format.
* @throws IOException
* If an I/O error occurs.
*/
public void load(DZBLOCK dzblk) throws DataFormatException, IOException {
byte[] uncompressedData;
Inflater decompresser = new Inflater();
uncompressedData = new byte[(int) dzblk.getOrg_data_length()];
ByteBuffer compressedData = ByteBuffer.allocate((int) dzblk.getData_length());
// Skip header section of DZ Block
reader.position(dzblk.getPos() + 48L);
reader.read(compressedData);
decompresser.setInput(compressedData.array(), 0, (int) dzblk.getData_length());
int resultLength = decompresser.inflate(uncompressedData);
decompresser.end();
if (dzblk.transposeNeeded()) {
int columnsize = (int) dzblk.getZip_parameters();
uncompressedData = MDF4Util.transposeArray(uncompressedData, columnsize, false);
MDFSorter.log.log(Level.FINER, "Transposing data with columnsize " + columnsize + ".");
}
if (resultLength != dzblk.getOrg_data_length()) {
throw new RuntimeException("Data gain or loss detected while unziping. Expected "
+ dzblk.getOrg_data_length() + " bytes, got " + resultLength);
}
MDFSorter.log.log(Level.FINER, "Unzipped block of size " + resultLength + ".");
// Store Data in Cache
if (cacheblocks.size() == MAXENTRIES) {
cacheblocks.removeFirst();
cachedata.removeFirst();
System.out.println("Cache full. Removing");
}
cachedata.add(uncompressedData);
cacheblocks.add(dzblk);
System.out.println("Cache size:" + cacheblocks.size());
}
/**
* Reads buf.capacity bytes from the spezified DZBLOCK.
*
* @param dzblk
* The DZBLOCK we want to read from-
* @param offset
* The offset in the unzipped data of the DZBLOCK
* @param buf
* The ByteBuffer data will be stored in.
* @throws DataFormatException
* If Zipped-Data is in an invalid format
* @throws IOException
* If an input error occurs.
*/
public void read(DZBLOCK dzblk, long offset, ByteBuffer buf) throws DataFormatException, IOException {
// Load block if not available
if (!isAvailable(dzblk)) {
load(dzblk);
}
int readsize = buf.limit();
byte[] dt = getData(dzblk);
buf.put(dt, (int) offset, readsize);
}
}