diff --git common/src/java/org/apache/hadoop/hive/common/ValidTxnList.java common/src/java/org/apache/hadoop/hive/common/ValidTxnList.java new file mode 100644 index 0000000..bcb3276 --- /dev/null +++ common/src/java/org/apache/hadoop/hive/common/ValidTxnList.java @@ -0,0 +1,82 @@ +/** + * 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 org.apache.hadoop.hive.common; + +/** + * Models the list of transactions that should be included in a snapshot. + * It is modelled as a high water mark, which is the largest transaction id that + * has been committed and a list of transactions that are not included. + */ +public interface ValidTxnList { + + /** + * Key used to store valid txn list in a + * {@link org.apache.hadoop.conf.Configuration} object. + */ + public static final String VALID_TXNS_KEY = "hive.txn.valid.txns"; + + /** + * The response to a range query. NONE means no values in this range match, + * SOME mean that some do, and ALL means that every value does. + */ + public enum RangeResponse {NONE, SOME, ALL}; + + /** + * Indicates whether a given transaction has been committed and should be + * viewed as valid for read. + * @param txnid id for the transaction + * @return true if committed, false otherwise + */ + public boolean isTxnCommitted(long txnid); + + /** + * Find out if a range of transaction ids have been committed. + * @param minTxnId minimum txnid to look for, inclusive + * @param maxTxnId maximum txnid to look for, inclusive + * @return Indicate whether none, some, or all of these transactions have been + * committed. + */ + public RangeResponse isTxnRangeCommitted(long minTxnId, long maxTxnId); + + /** + * Write this validTxnList into a string. This should produce a string that + * can be used by {@link #readFromString(String)} to populate a validTxnsList. + */ + public String writeToString(); + + /** + * Populate this validTxnList from the string. It is assumed that the string + * was created via {@link #writeToString()}. + * @param src source string. + */ + public void readFromString(String src); + + /** + * Get the largest committed transaction id. + * @return largest committed transaction id + */ + public long getHighWatermark(); + + /** + * Get the list of transactions under the high water mark that are still + * open. + * @return a list of open transaction ids + */ + public long[] getOpenTransactions(); +} diff --git common/src/java/org/apache/hadoop/hive/common/ValidTxnListImpl.java common/src/java/org/apache/hadoop/hive/common/ValidTxnListImpl.java new file mode 100644 index 0000000..26528f9 --- /dev/null +++ common/src/java/org/apache/hadoop/hive/common/ValidTxnListImpl.java @@ -0,0 +1,126 @@ +/** + * 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 org.apache.hadoop.hive.common; + +import java.util.Arrays; + +public class ValidTxnListImpl implements ValidTxnList { + + private long[] exceptions; + private long highWatermark; + + public ValidTxnListImpl() { + this(new long[0], Long.MAX_VALUE); + } + + public ValidTxnListImpl(long[] exceptions, long highWatermark) { + if (exceptions.length == 0) { + this.exceptions = exceptions; + } else { + this.exceptions = exceptions.clone(); + Arrays.sort(this.exceptions); + } + this.highWatermark = highWatermark; + } + + public ValidTxnListImpl(String value) { + readFromString(value); + } + + @Override + public boolean isTxnCommitted(long txnid) { + if (highWatermark < txnid) { + return false; + } + return Arrays.binarySearch(exceptions, txnid) < 0; + } + + @Override + public RangeResponse isTxnRangeCommitted(long minTxnId, long maxTxnId) { + // check the easy cases first + if (highWatermark < minTxnId) { + return RangeResponse.NONE; + } else if (exceptions.length > 0 && exceptions[0] > maxTxnId) { + return RangeResponse.ALL; + } + + // since the exceptions and the range in question overlap, count the + // exceptions in the range + long count = Math.max(0, maxTxnId - highWatermark); + for(long txn: exceptions) { + if (minTxnId <= txn && txn <= maxTxnId) { + count += 1; + } + } + + if (count == 0) { + return RangeResponse.ALL; + } else if (count == (maxTxnId - minTxnId + 1)) { + return RangeResponse.NONE; + } else { + return RangeResponse.SOME; + } + } + + @Override + public String toString() { + return writeToString(); + } + + @Override + public String writeToString() { + StringBuilder buf = new StringBuilder(); + buf.append(highWatermark); + if (exceptions.length == 0) { + buf.append(':'); + } else { + for(long except: exceptions) { + buf.append(':'); + buf.append(except); + } + } + return buf.toString(); + } + + @Override + public void readFromString(String src) { + if (src == null) { + highWatermark = Long.MAX_VALUE; + exceptions = new long[0]; + } else { + String[] values = src.split(":"); + highWatermark = Long.parseLong(values[0]); + exceptions = new long[values.length - 1]; + for(int i = 1; i < values.length; ++i) { + exceptions[i-1] = Long.parseLong(values[i]); + } + } + } + + @Override + public long getHighWatermark() { + return highWatermark; + } + + @Override + public long[] getOpenTransactions() { + return exceptions; + } +} + diff --git itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/TestHiveMetaStoreTxns.java itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/TestHiveMetaStoreTxns.java index 76b9c76..aa64863 100644 --- itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/TestHiveMetaStoreTxns.java +++ itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/TestHiveMetaStoreTxns.java @@ -18,12 +18,13 @@ package org.apache.hadoop.hive.metastore; import junit.framework.Assert; +import org.apache.hadoop.hive.common.ValidTxnList; +import org.apache.hadoop.hive.common.ValidTxnListImpl; import org.apache.hadoop.hive.conf.HiveConf; import org.apache.hadoop.hive.metastore.HiveMetaStoreClient; import org.apache.hadoop.hive.metastore.IMetaStoreClient; import org.apache.hadoop.hive.metastore.LockComponentBuilder; import org.apache.hadoop.hive.metastore.LockRequestBuilder; -import org.apache.hadoop.hive.metastore.api.GetOpenTxnsResponse; import org.apache.hadoop.hive.metastore.api.LockResponse; import org.apache.hadoop.hive.metastore.api.LockState; import org.apache.hadoop.hive.metastore.txn.TxnDbUtil; @@ -33,9 +34,7 @@ import org.junit.Before; import org.junit.Test; -import java.util.HashSet; import java.util.List; -import java.util.Set; /** * Unit tests for {@link org.apache.hadoop.hive.metastore.HiveMetaStoreClient}. For now this just has @@ -68,7 +67,7 @@ public void testTxns() throws Exception { Assert.assertEquals(3L, (long) tids.get(2)); client.rollbackTxn(1); client.commitTxn(2); - IMetaStoreClient.ValidTxnList validTxns = client.getValidTxns(); + ValidTxnList validTxns = client.getValidTxns(); Assert.assertFalse(validTxns.isTxnCommitted(1)); Assert.assertTrue(validTxns.isTxnCommitted(2)); Assert.assertFalse(validTxns.isTxnCommitted(3)); @@ -77,39 +76,55 @@ public void testTxns() throws Exception { @Test public void testTxnRange() throws Exception { - IMetaStoreClient.ValidTxnList validTxns = client.getValidTxns(); - Assert.assertEquals(IMetaStoreClient.ValidTxnList.RangeResponse.NONE, + ValidTxnList validTxns = client.getValidTxns(); + Assert.assertEquals(ValidTxnList.RangeResponse.NONE, validTxns.isTxnRangeCommitted(1L, 3L)); - List tids = client.openTxns("me", 5).getTxn_ids(); + client.rollbackTxn(1L); client.commitTxn(2L); client.commitTxn(3L); client.commitTxn(4L); validTxns = client.getValidTxns(); - Assert.assertEquals(IMetaStoreClient.ValidTxnList.RangeResponse.ALL, + System.out.println("validTxns = " + validTxns); + Assert.assertEquals(ValidTxnList.RangeResponse.ALL, validTxns.isTxnRangeCommitted(2L, 2L)); - Assert.assertEquals(IMetaStoreClient.ValidTxnList.RangeResponse.ALL, + Assert.assertEquals(ValidTxnList.RangeResponse.ALL, validTxns.isTxnRangeCommitted(2L, 3L)); - Assert.assertEquals(IMetaStoreClient.ValidTxnList.RangeResponse.ALL, + Assert.assertEquals(ValidTxnList.RangeResponse.ALL, validTxns.isTxnRangeCommitted(2L, 4L)); - Assert.assertEquals(IMetaStoreClient.ValidTxnList.RangeResponse.ALL, + Assert.assertEquals(ValidTxnList.RangeResponse.ALL, validTxns.isTxnRangeCommitted(3L, 4L)); - Assert.assertEquals(IMetaStoreClient.ValidTxnList.RangeResponse.SOME, + Assert.assertEquals(ValidTxnList.RangeResponse.SOME, validTxns.isTxnRangeCommitted(1L, 4L)); - Assert.assertEquals(IMetaStoreClient.ValidTxnList.RangeResponse.SOME, + Assert.assertEquals(ValidTxnList.RangeResponse.SOME, validTxns.isTxnRangeCommitted(2L, 5L)); - Assert.assertEquals(IMetaStoreClient.ValidTxnList.RangeResponse.SOME, + Assert.assertEquals(ValidTxnList.RangeResponse.SOME, validTxns.isTxnRangeCommitted(1L, 2L)); - Assert.assertEquals(IMetaStoreClient.ValidTxnList.RangeResponse.SOME, + Assert.assertEquals(ValidTxnList.RangeResponse.SOME, validTxns.isTxnRangeCommitted(4L, 5L)); - Assert.assertEquals(IMetaStoreClient.ValidTxnList.RangeResponse.NONE, + Assert.assertEquals(ValidTxnList.RangeResponse.NONE, validTxns.isTxnRangeCommitted(1L, 1L)); - Assert.assertEquals(IMetaStoreClient.ValidTxnList.RangeResponse.NONE, + Assert.assertEquals(ValidTxnList.RangeResponse.NONE, validTxns.isTxnRangeCommitted(5L, 10L)); + validTxns = new ValidTxnListImpl("10:4:5:6"); + Assert.assertEquals(ValidTxnList.RangeResponse.NONE, + validTxns.isTxnRangeCommitted(4,6)); + Assert.assertEquals(ValidTxnList.RangeResponse.ALL, + validTxns.isTxnRangeCommitted(7, 10)); + Assert.assertEquals(ValidTxnList.RangeResponse.SOME, + validTxns.isTxnRangeCommitted(7, 11)); + Assert.assertEquals(ValidTxnList.RangeResponse.SOME, + validTxns.isTxnRangeCommitted(3, 6)); + Assert.assertEquals(ValidTxnList.RangeResponse.SOME, + validTxns.isTxnRangeCommitted(4, 7)); + Assert.assertEquals(ValidTxnList.RangeResponse.SOME, + validTxns.isTxnRangeCommitted(1, 12)); + Assert.assertEquals(ValidTxnList.RangeResponse.ALL, + validTxns.isTxnRangeCommitted(1, 3)); } @Test @@ -184,43 +199,32 @@ public void testLocksWithTxn() throws Exception { @Test public void stringifyValidTxns() throws Exception { // Test with just high water mark - GetOpenTxnsResponse rsp = new GetOpenTxnsResponse(); - rsp.setTxn_high_water_mark(1); - IMetaStoreClient.ValidTxnList validTxns = new HiveMetaStoreClient.ValidTxnListImpl(rsp); + ValidTxnList validTxns = new ValidTxnListImpl("1:"); String asString = validTxns.toString(); Assert.assertEquals("1:", asString); - validTxns = new HiveMetaStoreClient.ValidTxnListImpl(); - validTxns.fromString(asString); - Assert.assertEquals(1, validTxns.getOpenTxns().getTxn_high_water_mark()); - Assert.assertNotNull(validTxns.getOpenTxns().getOpen_txns()); - Assert.assertEquals(0, validTxns.getOpenTxns().getOpen_txnsSize()); + validTxns = new ValidTxnListImpl(asString); + Assert.assertEquals(1, validTxns.getHighWatermark()); + Assert.assertNotNull(validTxns.getOpenTransactions()); + Assert.assertEquals(0, validTxns.getOpenTransactions().length); asString = validTxns.toString(); Assert.assertEquals("1:", asString); - validTxns = new HiveMetaStoreClient.ValidTxnListImpl(); - validTxns.fromString(asString); - Assert.assertEquals(1, validTxns.getOpenTxns().getTxn_high_water_mark()); - Assert.assertNotNull(validTxns.getOpenTxns().getOpen_txns()); - Assert.assertEquals(0, validTxns.getOpenTxns().getOpen_txnsSize()); + validTxns = new ValidTxnListImpl(asString); + Assert.assertEquals(1, validTxns.getHighWatermark()); + Assert.assertNotNull(validTxns.getOpenTransactions()); + Assert.assertEquals(0, validTxns.getOpenTransactions().length); // Test with open transactions - rsp = new GetOpenTxnsResponse(); - rsp.setTxn_high_water_mark(10); - Set openTxns = new HashSet(2); - openTxns.add(3L); - openTxns.add(5L); - rsp.setOpen_txns(openTxns); - validTxns = new HiveMetaStoreClient.ValidTxnListImpl(rsp); + validTxns = new ValidTxnListImpl("10:5:3"); asString = validTxns.toString(); if (!asString.equals("10:3:5") && !asString.equals("10:5:3")) { Assert.fail("Unexpected string value " + asString); } - validTxns = new HiveMetaStoreClient.ValidTxnListImpl(); - validTxns.fromString(asString); - Assert.assertEquals(10, validTxns.getOpenTxns().getTxn_high_water_mark()); - Assert.assertNotNull(validTxns.getOpenTxns().getOpen_txns()); - Assert.assertEquals(2, validTxns.getOpenTxns().getOpen_txnsSize()); + validTxns = new ValidTxnListImpl(asString); + Assert.assertEquals(10, validTxns.getHighWatermark()); + Assert.assertNotNull(validTxns.getOpenTransactions()); + Assert.assertEquals(2, validTxns.getOpenTransactions().length); boolean sawThree = false, sawFive = false; - for (long tid : validTxns.getOpenTxns().getOpen_txns()) { + for (long tid : validTxns.getOpenTransactions()) { if (tid == 3) sawThree = true; else if (tid == 5) sawFive = true; else Assert.fail("Unexpected value " + tid); diff --git metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStoreClient.java metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStoreClient.java index 529e538..0550589 100644 --- metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStoreClient.java +++ metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStoreClient.java @@ -46,6 +46,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.hive.common.ObjectPair; +import org.apache.hadoop.hive.common.ValidTxnList; +import org.apache.hadoop.hive.common.ValidTxnListImpl; import org.apache.hadoop.hive.conf.HiveConf; import org.apache.hadoop.hive.conf.HiveConf.ConfVars; import org.apache.hadoop.hive.metastore.api.AbortTxnRequest; @@ -103,12 +105,14 @@ import org.apache.hadoop.hive.metastore.api.TableStatsRequest; import org.apache.hadoop.hive.metastore.api.ThriftHiveMetastore; import org.apache.hadoop.hive.metastore.api.TxnAbortedException; +import org.apache.hadoop.hive.metastore.api.TxnInfo; import org.apache.hadoop.hive.metastore.api.TxnOpenException; import org.apache.hadoop.hive.metastore.api.Type; import org.apache.hadoop.hive.metastore.api.UnknownDBException; import org.apache.hadoop.hive.metastore.api.UnknownPartitionException; import org.apache.hadoop.hive.metastore.api.UnknownTableException; import org.apache.hadoop.hive.metastore.api.UnlockRequest; +import org.apache.hadoop.hive.metastore.txn.TxnHandler; import org.apache.hadoop.hive.shims.HadoopShims; import org.apache.hadoop.hive.shims.ShimLoader; import org.apache.hadoop.hive.thrift.HadoopThriftAuthBridge; @@ -1526,80 +1530,9 @@ public void cancelDelegationToken(String tokenStrForm) throws MetaException, TEx client.cancel_delegation_token(tokenStrForm); } - public static class ValidTxnListImpl implements ValidTxnList { - - private GetOpenTxnsResponse txns; - - public ValidTxnListImpl() { - } - - public ValidTxnListImpl(GetOpenTxnsResponse t) { - txns = t; - } - - @Override - public boolean isTxnCommitted(long txnid) { - if (txns.getTxn_high_water_mark() < txnid) return false; - return !txns.getOpen_txns().contains(txnid); - } - - @Override - public RangeResponse isTxnRangeCommitted(long minTxnId, long maxTxnId) { - if (txns.getTxn_high_water_mark() < minTxnId) return RangeResponse.NONE; - - RangeResponse rc = RangeResponse.ALL; - boolean foundCommitted = false; - for (long id = minTxnId; id <= maxTxnId; id++) { - if (isTxnCommitted(id)) foundCommitted = true; - else rc = RangeResponse.SOME; - } - if (!foundCommitted) rc = RangeResponse.NONE; - return rc; - } - - @Override - public GetOpenTxnsResponse getOpenTxns() { - return txns; - } - - @Override - public String toString() { - StringBuffer buf = new StringBuffer(); - buf.append(getOpenTxns().getTxn_high_water_mark()); - Set openTxns = getOpenTxns().getOpen_txns(); - if (openTxns != null && openTxns.size() > 0) { - for (long txn : openTxns) { - buf.append(':'); - buf.append(txn); - } - } else { - buf.append(':'); - } - return buf.toString(); - } - - @Override - public void fromString(String src) { - // Make sure we have a non-null value in txns so that any future calls to this don't NPE. - txns = new GetOpenTxnsResponse(); - if (src == null) { - txns.setTxn_high_water_mark(Long.MAX_VALUE); - txns.setOpen_txns(new HashSet()); - return; - } - - String[] tString = src.split(":"); - txns.setTxn_high_water_mark(Long.valueOf(tString[0])); - Set openTxns = new HashSet(); - for (int i = 1; i < tString.length; i++) openTxns.add(Long.valueOf(tString[i])); - txns.setOpen_txns(openTxns); - } - } - @Override public ValidTxnList getValidTxns() throws TException { - GetOpenTxnsResponse txns = client.get_open_txns(); - return new ValidTxnListImpl(txns); + return TxnHandler.createValidTxnList(client.get_open_txns()); } @Override diff --git metastore/src/java/org/apache/hadoop/hive/metastore/IMetaStoreClient.java metastore/src/java/org/apache/hadoop/hive/metastore/IMetaStoreClient.java index 0f8dd54..47c49aa 100644 --- metastore/src/java/org/apache/hadoop/hive/metastore/IMetaStoreClient.java +++ metastore/src/java/org/apache/hadoop/hive/metastore/IMetaStoreClient.java @@ -18,6 +18,21 @@ package org.apache.hadoop.hive.metastore; +import org.apache.hadoop.hive.common.ValidTxnList; +import org.apache.hadoop.hive.metastore.api.CompactionType; +import org.apache.hadoop.hive.metastore.api.GetOpenTxnsInfoResponse; +import org.apache.hadoop.hive.metastore.api.GetOpenTxnsResponse; +import org.apache.hadoop.hive.metastore.api.LockRequest; +import org.apache.hadoop.hive.metastore.api.LockResponse; +import org.apache.hadoop.hive.metastore.api.NoSuchLockException; +import org.apache.hadoop.hive.metastore.api.NoSuchTxnException; +import org.apache.hadoop.hive.metastore.api.OpenTxnsResponse; +import org.apache.hadoop.hive.metastore.api.ShowCompactResponse; +import org.apache.hadoop.hive.metastore.api.ShowLocksResponse; +import org.apache.hadoop.hive.metastore.api.TxnAbortedException; +import org.apache.hadoop.hive.metastore.api.TxnOpenException; +import org.apache.thrift.TException; + import java.util.List; import java.util.Map; @@ -1035,61 +1050,6 @@ public Function getFunction(String dbName, String funcName) public List getFunctions(String dbName, String pattern) throws MetaException, TException; - // Transaction and locking methods - public interface ValidTxnList { - - /** - * Key used to store valid txn list in a {@link org.apache.hadoop.conf.Configuration} object. - */ - public static final String VALID_TXNS_KEY = "hive.txn.valid.txns"; - - /** - * The response to a range query. NONE means no values in this range match, - * SOME mean that some do, and ALL means that every value does. - */ - public enum RangeResponse {NONE, SOME, ALL}; - - /** - * Indicates whether a given transaction has been committed and should be - * viewed as valid for read. - * @param txnid id for the transaction - * @return true if committed, false otherwise - */ - public boolean isTxnCommitted(long txnid); - - /** - * Find out if a range of transaction ids have been committed. - * @param minTxnId minimum txnid to look for, inclusive - * @param maxTxnId maximum txnid to look for, inclusive - * @return Indicate whether none, some, or all of these transactions have been committed. - */ - public RangeResponse isTxnRangeCommitted(long minTxnId, long maxTxnId); - - /** - * Get at the underlying OpenTxn structure. This is useful if the user - * wishes to get a list of all open transactions for more efficient - * filtering. - * @return open transactions - */ - public GetOpenTxnsResponse getOpenTxns(); - - /** - * Write this validTxnList into a string. Obviously all implementations will already - * implement this, but it is being called out specifically here to make clear that the - * implementation needs to override the default implementation. This should produce a string - * that can be used by {@link #fromString(String)} to populate a validTxnsList. - */ - @Override - public String toString(); - - /** - * Populate this validTxnList from the string. It is assumed that the string was created via - * {@link #toString()}. - * @param src source string. - */ - public void fromString(String src); - } - /** * Get a structure that details valid transactions. * @return list of valid transactions diff --git metastore/src/java/org/apache/hadoop/hive/metastore/txn/TxnHandler.java metastore/src/java/org/apache/hadoop/hive/metastore/txn/TxnHandler.java index 4441c2f..714865d 100644 --- metastore/src/java/org/apache/hadoop/hive/metastore/txn/TxnHandler.java +++ metastore/src/java/org/apache/hadoop/hive/metastore/txn/TxnHandler.java @@ -22,6 +22,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.hive.common.ValidTxnList; +import org.apache.hadoop.hive.common.ValidTxnListImpl; import org.apache.hadoop.hive.conf.HiveConf; import org.apache.hadoop.hive.metastore.api.*; import org.apache.hadoop.util.StringUtils; @@ -194,6 +196,17 @@ public GetOpenTxnsResponse getOpenTxns() throws MetaException{ } } + public static ValidTxnList createValidTxnList(GetOpenTxnsResponse txns) { + long highWater = txns.getTxn_high_water_mark(); + Set open = txns.getOpen_txns(); + long[] exceptions = new long[open.size()]; + int i = 0; + for(long txn: open) { + exceptions[i++] = txn; + } + return new ValidTxnListImpl(exceptions, highWater); + } + public OpenTxnsResponse openTxns(OpenTxnRequest rqst) throws MetaException { int numTxns = rqst.getNum_txns(); Connection dbConn = getDbConn(); diff --git pom.xml pom.xml index 27effb5..30e786a 100644 --- pom.xml +++ pom.xml @@ -126,7 +126,7 @@ 0.9.0 0.9.0 1.2.16 - 1.8.2 + 1.9.5 2.0.0-M5