/** * Convert an MVD to a string * * @param mvd the MVD to convert * @param rb database properties file * @param folderId id of the folder to contain it in * @throws Exception raised if an error occurred */ public static String externalise(MVD mvd) throws Exception { int size = mvd.dataSize(); byte[] data = new byte[size]; int nBytes = mvd.serialise(data); assert nBytes == size : "MVD shorter than predicted"; return Base64.encodeBytes(data, Base64.GZIP); }
/** * Save an MVD to a file * * @param mvd the MVD to save * @param dst the file to save it to * @param rb database properties file * @param folderId id of the folder to contain it in * @throws Exception raised if an error occurred */ public static void externalise(MVD mvd, File dst, int folderId, Properties rb) throws Exception { long start = System.nanoTime() / 1000; System.gc(); long startMem = Runtime.getRuntime().freeMemory(); int size = mvd.dataSize(); byte[] data = new byte[size]; int nBytes = mvd.serialise(data); assert nBytes == size : "MVD shorter than predicted"; String str = Base64.encodeBytes(data, Base64.GZIP); if (rb == null) writeToFile(dst, str); else writeToDatabase(dst.getName(), str, mvd.description, folderId, rb); long end = System.nanoTime() / 1000; long endMem = Runtime.getRuntime().freeMemory(); System.out.println("internalise took " + (end - start) + " microseconds"); System.out.println("Memory used " + (startMem - endMem) + " bytes"); }
/** * Read the version table for an MVD from a byte array * * @param data the byte array containing the version definitions * @param p the start offset of the versions within data * @param mvd an mvd to add the version definitions to */ private static void readVersionTable(byte[] data, int p, MVD mvd) throws Exception { short nVersions = readShort(data, p); p += 2; if (nVersions < 0) throw new MVDException("Invalid number of versions: " + nVersions); short setSize = readShort(data, p); p += 2; mvd.setVersionSetSize(setSize); for (short i = 0; i < nVersions; i++) { short group = readShort(data, p); p += 2; short backup = readShort(data, p); p += 2; short len = readShort(data, p); String shortName = readUtf8String(data, p); p += 2 + len; len = readShort(data, p); String longName = readUtf8String(data, p); p += 2 + len; mvd.addVersion(new Version(group, backup, shortName, longName)); } }
/** * Read the group table for an MVD from a byte array * * @param data the byte array containing the group definitions * @param p the start offset of the groups within data * @param mvd an mvd to add the group definitions to */ private static void readGroupTable(byte[] data, int p, MVD mvd) throws Exception { short nGroups = readShort(data, p); p += 2; if (nGroups < 0) throw new MVDException("Invalid number of groups: " + nGroups); for (short i = 0; i < nGroups; i++) { short parent = readShort(data, p); p += 2; short len = readShort(data, p); String name = readUtf8String(data, p); p += 2 + len; mvd.addGroup(new Group(parent, name)); } }
/** * Read the pairs table for an MVD from a byte array * * @param data the byte array containing the version definitions * @param p the start offset of the versions within data * @param dataTableOffset offset within data of the pairs data * @param mvd an mvd to add the version definitions to */ private static void readPairsTable(byte[] data, int p, int dataTableOffset, MVD mvd) throws Exception { // record any pairs declaring themselves as parents HashMap<Integer, Pair> parents = new HashMap<Integer, Pair>(); HashMap<Integer, LinkedList<Pair>> orphans = new HashMap<Integer, LinkedList<Pair>>(); int nPairs = readInt(data, p); p += 4; if (nPairs < 0) throw new MVDException("Invalid number of pairs: " + nPairs); for (int i = 0; i < nPairs; i++) { byte[] copy; Pair pair; BitSet versions = readVersionSet(mvd.versionSetSize, data, p); p += mvd.versionSetSize; int offset = readInt(data, p); p += 4; int len = readInt(data, p); int flag = len & Pair.TRANSPOSE_MASK; // clear top two bits len &= Pair.INVERSE_MASK; p += 4; if (flag == Pair.PARENT_FLAG) { // read special parent id field int pId = readInt(data, p); p += 4; // transpose parent copy = copyData(len, dataTableOffset + offset, data); pair = new Pair(versions, toChars(copy, mvd.encoding)); Integer key = new Integer(pId); // check for orphans of this parent LinkedList<Pair> children = orphans.get(key); if (children != null) { ListIterator<Pair> iter = children.listIterator(); // match them up with this parent while (iter.hasNext()) { Pair child = iter.next(); child.setParent(pair); pair.addChild(child); } // now they're not orphans any more orphans.remove(key); } // always do this in case more children turn up parents.put(key, pair); } else if (flag == Pair.CHILD_FLAG) { // read special parent id field int pId = readInt(data, p); p += 4; // transpose child Integer key = new Integer(pId); Pair parent = parents.get(key); if (parent == null) { LinkedList<Pair> children = orphans.get(key); if (children == null) { children = new LinkedList<Pair>(); orphans.put(key, children); } pair = new Pair(versions, null); children.add(pair); } else // parent available { pair = new Pair(versions, null); pair.setParent(parent); parent.addChild(pair); } } else { // no transposition copy = copyData(len, dataTableOffset + offset, data); pair = new Pair(versions, toChars(copy, mvd.encoding)); } mvd.addPair(pair); } }