/** Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved. Contact: SYSTAP, LLC DBA Blazegraph 2501 Calvert ST NW #106 Washington, DC 20008 licenses@blazegraph.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Created on Mar 21, 2011 */ package com.bigdata.btree.keys; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import com.bigdata.journal.Name2Addr; import com.ibm.icu.util.VersionInfo; /** * Persistent record in which we store the version metadata for the ICU * dependency in use when the journal was created. bigdata uses Unicode sort * keys for various indices, including {@link Name2Addr}. A change in the ICU * version can result in sort keys which are NOT compatible. Binary * compatibility for Unicode sort keys is an absolute requirement for bigdata. * The purpose of this persistence capable data record is to note the version of * ICU against which bigdata was linked with the associated binary store file * was created. * <p> * Note: This can result in data which apparently becomes "lost", such as this * <a href="http://sourceforge.net/apps/trac/bigdata/ticket/193>trac issue</a>. * The underlying problem was substituting a newer version of ICU for the one * included in the bigdata distribution. Such errors are now caught by detecting * a change in the ICU runtime environment. * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> * @version $Id$ */ public class ICUVersionRecord implements Externalizable { /** * */ private static final long serialVersionUID = 1L; private VersionInfo icuVersion; private VersionInfo ucolRuntimeVersion; private VersionInfo ucolBuilderVersion; private VersionInfo ucolTailoringsVersion; /** * The ICU software version number. * * @see VersionInfo#ICU_VERSION */ public VersionInfo getICUVersion() { return icuVersion; } /** * If this version number changes, then the sort keys for the same Unicode * string could be different. * * @see VersionInfo#UCOL_RUNTIME_VERSION */ public VersionInfo getUColRuntimeVersion() { return ucolRuntimeVersion; } /** * If this version number changes, then the same tailoring might result in * assigning different collation elements to code points (which could break * binary compatibility on sort keys). * * @see VersionInfo#UCOL_BUILDER_VERSION */ public VersionInfo getUColBuilderVersion() { return ucolBuilderVersion; } /** * The version of the collation tailorings. * * @see VersionInfo#UCOL_TAILORINGS_VERSION */ public VersionInfo getUColTailoringsVersion() { return ucolTailoringsVersion; } /** * Factory returns a record reporting on the ICU dependency as currently * linked with the code base. */ public static ICUVersionRecord newInstance() { final ICUVersionRecord r = new ICUVersionRecord(// VersionInfo.ICU_VERSION,// VersionInfo.UCOL_RUNTIME_VERSION,// VersionInfo.UCOL_BUILDER_VERSION,// VersionInfo.UCOL_TAILORINGS_VERSION// ); return r; } ICUVersionRecord(// VersionInfo icuVersion,// VersionInfo ucolRuntimeVesion,// VersionInfo ucolBuilderVersion,// VersionInfo ucolTailoringsVersion// ) { this.icuVersion = icuVersion; this.ucolRuntimeVersion = ucolRuntimeVesion; this.ucolBuilderVersion = ucolBuilderVersion; this.ucolTailoringsVersion = ucolTailoringsVersion; } /** * De-serialization contructor <strong>only</strong>. */ public ICUVersionRecord() { } /** The initial version of this data record. */ private static final transient int VERSION0 = 0; private static final transient int CURRENT_VERSION = VERSION0; public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { final int version = in.readInt(); switch (version) { case VERSION0: break; default: throw new IOException("Unknown version: " + version); } icuVersion = readVersionInfo(in); ucolRuntimeVersion = readVersionInfo(in); ucolBuilderVersion = readVersionInfo(in); ucolTailoringsVersion = readVersionInfo(in); } public void writeExternal(ObjectOutput out) throws IOException { out.writeInt(CURRENT_VERSION); writeVersionInfo(icuVersion, out); writeVersionInfo(ucolRuntimeVersion, out); writeVersionInfo(ucolBuilderVersion, out); writeVersionInfo(ucolTailoringsVersion, out); } private VersionInfo readVersionInfo(final ObjectInput in) throws IOException { final int major = in.readInt(); final int minor = in.readInt(); final int micro = in.readInt(); final int milli = in.readInt(); return VersionInfo.getInstance(major, minor, milli, micro); } private void writeVersionInfo(final VersionInfo v, final ObjectOutput out) throws IOException { out.writeInt(v.getMajor()); out.writeInt(v.getMinor()); out.writeInt(v.getMicro()); out.writeInt(v.getMilli()); } /** * A human readable representation of the data record. */ public String toString() { final StringBuilder sb = new StringBuilder(); sb.append(getClass().getName()); sb.append("{icuVersion=" + icuVersion); sb.append(",ucolRuntimeVersion=" + ucolRuntimeVersion); sb.append(",ucolBuilderVersion=" + ucolBuilderVersion); sb.append(",ucolTailoringsVersion=" + ucolTailoringsVersion); sb.append("}"); return sb.toString(); } public int hashCode() { return super.hashCode(); } public boolean equals(final Object o) { if (this == o) return true; if (!(o instanceof ICUVersionRecord)) return false; final ICUVersionRecord r = (ICUVersionRecord) o; if (!icuVersion.equals(r.icuVersion)) return false; if (!ucolRuntimeVersion.equals(r.ucolRuntimeVersion)) return false; if (!ucolBuilderVersion.equals(r.ucolBuilderVersion)) return false; if (!ucolTailoringsVersion.equals(r.ucolTailoringsVersion)) return false; return true; } /** * Writes out the {@link ICUVersionRecord} for the current classpath. * * @param args * Ignored. */ static public void main(String[] args) { System.out.println(ICUVersionRecord.newInstance().toString()); final ICUVersionRecord a = ICUVersionRecord.newInstance(); final ICUVersionRecord b = ICUVersionRecord.newInstance(); if(!a.equals(b)) throw new AssertionError(); if(!b.equals(a)) throw new AssertionError(); } }