[jira] [Updated] (HBASE-17300) Concurrently calling checkAndPut with expected value as null returns true unexpectedly

2016-12-13 Thread Andrew Purtell (JIRA)

 [ 
https://issues.apache.org/jira/browse/HBASE-17300?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Andrew Purtell updated HBASE-17300:
---
Attachment: HBASE-17300.patch

Refactored test for master. I move the table creation out of the callables 
because we should be testing for concurrent checkAndPut failure not if 
operations are racing with table creation. Check your code otherwise 
[~samarthjain] . Test passes on master. Will come back to this soon to see if 
it flaps on master, and will port back to branch-1 and 0.98 to check those too. 

> Concurrently calling checkAndPut with expected value as null returns true 
> unexpectedly
> --
>
> Key: HBASE-17300
> URL: https://issues.apache.org/jira/browse/HBASE-17300
> Project: HBase
>  Issue Type: Bug
>Affects Versions: 0.98.23, 1.2.4
>Reporter: Samarth Jain
> Attachments: HBASE-17300.patch
>
>
> Attached is the test case. I have added some comments so hopefully the test 
> makes sense. It actually is causing test failures on the Phoenix branches.
> The test fails consistently using HBase-0.98.23. It exhibits flappy behavior 
> with the 1.2 branch (failed twice in 5 tries). 
> {code}
> @Test
> public void testNullCheckAndPut() throws Exception {
> try (HBaseAdmin admin = TEST_UTIL.getHBaseAdmin()) {
> Callable c1 = new CheckAndPutCallable();
> Callable c2 = new CheckAndPutCallable();
> ExecutorService e = Executors.newFixedThreadPool(5);
> Future f1 = e.submit(c1);
> Future f2 = e.submit(c2);
> assertTrue(f1.get() || f2.get());
> assertFalse(f1.get() && f2.get());
> }
> }
> }
> 
> 
> private static final class CheckAndPutCallable implements 
> Callable {
> @Override
> public Boolean call() throws Exception {
> byte[] rowToLock = "ROW".getBytes();
> byte[] colFamily = "COLUMN_FAMILY".getBytes();
> byte[] column = "COLUMN".getBytes();
> byte[] newValue = "NEW_VALUE".getBytes();
> byte[] oldValue = "OLD_VALUE".getBytes();
> byte[] tableName = "table".getBytes();
> boolean acquired = false;
> try (HBaseAdmin admin = TEST_UTIL.getHBaseAdmin()) {
> HTableDescriptor tableDesc = new 
> HTableDescriptor(TableName.valueOf(tableName));
> HColumnDescriptor columnDesc = new 
> HColumnDescriptor(colFamily);
> columnDesc.setTimeToLive(600);
> tableDesc.addFamily(columnDesc);
> try {
> admin.createTable(tableDesc);
> } catch (TableExistsException e) {
> // ignore
> }
> try (HTableInterface table = 
> admin.getConnection().getTable(tableName)) {
> Put put = new Put(rowToLock);
> put.add(colFamily, column, oldValue); // add a row 
> with column set to oldValue
> table.put(put);
> put = new Put(rowToLock);
> put.add(colFamily, column, newValue);
> // only one of the threads should be able to get 
> return value of true for the expected value of oldValue
> acquired = table.checkAndPut(rowToLock, colFamily, 
> column, oldValue, put); 
> if (!acquired) {
>// if a thread didn't get true before, then it 
> shouldn't get true this time either
>// because the column DOES exist
>acquired = table.checkAndPut(rowToLock, colFamily, 
> column, null, put);
> }
> }
> }
> }  
> return acquired;
> }
> }
> {code}
> cc [~apurtell], [~jamestaylor], [~lhofhansl]. 



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)


[jira] [Updated] (HBASE-17300) Concurrently calling checkAndPut with expected value as null returns true unexpectedly

2016-12-12 Thread Samarth Jain (JIRA)

 [ 
https://issues.apache.org/jira/browse/HBASE-17300?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Samarth Jain updated HBASE-17300:
-
Description: 
Attached is the test case. I have added some comments so hopefully the test 
makes sense. It actually is causing test failures on the Phoenix branches.

The test fails consistently using HBase-0.98.23. It exhibits flappy behavior 
with the 1.2 branch (failed twice in 5 tries). 

{code}
@Test
public void testNullCheckAndPut() throws Exception {
try (HBaseAdmin admin = TEST_UTIL.getHBaseAdmin()) {
Callable c1 = new CheckAndPutCallable();
Callable c2 = new CheckAndPutCallable();
ExecutorService e = Executors.newFixedThreadPool(5);
Future f1 = e.submit(c1);
Future f2 = e.submit(c2);
assertTrue(f1.get() || f2.get());
assertFalse(f1.get() && f2.get());
}
}
}


private static final class CheckAndPutCallable implements Callable 
{
@Override
public Boolean call() throws Exception {
byte[] rowToLock = "ROW".getBytes();
byte[] colFamily = "COLUMN_FAMILY".getBytes();
byte[] column = "COLUMN".getBytes();
byte[] newValue = "NEW_VALUE".getBytes();
byte[] oldValue = "OLD_VALUE".getBytes();
byte[] tableName = "table".getBytes();
boolean acquired = false;
try (HBaseAdmin admin = TEST_UTIL.getHBaseAdmin()) {
HTableDescriptor tableDesc = new 
HTableDescriptor(TableName.valueOf(tableName));
HColumnDescriptor columnDesc = new 
HColumnDescriptor(colFamily);
columnDesc.setTimeToLive(600);
tableDesc.addFamily(columnDesc);
try {
admin.createTable(tableDesc);
} catch (TableExistsException e) {
// ignore
}
try (HTableInterface table = 
admin.getConnection().getTable(tableName)) {
Put put = new Put(rowToLock);
put.add(colFamily, column, oldValue); // add a row with 
column set to oldValue
table.put(put);
put = new Put(rowToLock);
put.add(colFamily, column, newValue);
// only one of the threads should be able to get return 
value of true for the expected value of oldValue
acquired = table.checkAndPut(rowToLock, colFamily, 
column, oldValue, put); 
if (!acquired) {
   // if a thread didn't get true before, then it 
shouldn't get true this time either
   // because the column DOES exist
   acquired = table.checkAndPut(rowToLock, colFamily, 
column, null, put);
}
}
}
}  
return acquired;
}
}
{code}


cc [~apurtell], [~jamestaylor], [~lhofhansl]. 


  was:
Attached is the test case. I have added some comments so hopefully the test 
makes sense. It actually is causing test failures on the Phoenix branches.
PS - I am using a bit of Phoenix API to get hold of HBaseAdmin. But it should 
be fairly straightforward to adopt it for HBase IT tests. 

The test fails consistently using HBase-0.98.23. It exhibits flappy behavior 
with the 1.2 branch (failed twice in 5 tries). 

{code}
@Test
public void testNullCheckAndPut() throws Exception {
 try (Connection conn = DriverManager.getConnection(getUrl())) {
try (HBaseAdmin admin = 
conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
Callable c1 = new CheckAndPutCallable();
Callable c2 = new CheckAndPutCallable();
ExecutorService e = Executors.newFixedThreadPool(5);
Future f1 = e.submit(c1);
Future f2 = e.submit(c2);
assertTrue(f1.get() || f2.get());
assertFalse(f1.get() && f2.get());
}
}
}


private static final class CheckAndPutCallable implements Callable 
{
@Override
public Boolean call() throws Exception {
byte[] rowToLock = "ROW".getBytes();
byte[] colFamily = "COLUMN_FAMILY".getBytes();
byte[] column = "COLUMN".getBytes();
byte[] newValue = "NEW_VALUE".getBytes();
byte[] oldValue = "OLD_VALUE".getBytes();
byte[] tableName = "table".getBytes();
boolean acquired = false;
try (Connection conn = DriverManager.getConnection(getUrl())) {
try (HBaseAdmin admin = 
conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
 

[jira] [Updated] (HBASE-17300) Concurrently calling checkAndPut with expected value as null returns true unexpectedly

2016-12-12 Thread Andrew Purtell (JIRA)

 [ 
https://issues.apache.org/jira/browse/HBASE-17300?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Andrew Purtell updated HBASE-17300:
---
Affects Version/s: 0.98.23
   1.2.4

Set fix versions as reported. Let me see as part of 0.98.24 work if a port of 
this to HBase API only will repro the issue. If so, if an earlier version 
worked correctly (0.98.17 perhaps?). If so, what commit broke things.

> Concurrently calling checkAndPut with expected value as null returns true 
> unexpectedly
> --
>
> Key: HBASE-17300
> URL: https://issues.apache.org/jira/browse/HBASE-17300
> Project: HBase
>  Issue Type: Bug
>Affects Versions: 0.98.23, 1.2.4
>Reporter: Samarth Jain
>
> Attached is the test case. I have added some comments so hopefully the test 
> makes sense. It actually is causing test failures on the Phoenix branches.
> PS - I am using a bit of Phoenix API to get hold of HBaseAdmin. But it should 
> be fairly straightforward to adopt it for HBase IT tests. 
> The test fails consistently using HBase-0.98.23. It exhibits flappy behavior 
> with the 1.2 branch (failed twice in 5 tries). 
> {code}
> @Test
> public void testNullCheckAndPut() throws Exception {
>  try (Connection conn = DriverManager.getConnection(getUrl())) {
> try (HBaseAdmin admin = 
> conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
> Callable c1 = new CheckAndPutCallable();
> Callable c2 = new CheckAndPutCallable();
> ExecutorService e = Executors.newFixedThreadPool(5);
> Future f1 = e.submit(c1);
> Future f2 = e.submit(c2);
> assertTrue(f1.get() || f2.get());
> assertFalse(f1.get() && f2.get());
> }
> }
> }
> 
> 
> private static final class CheckAndPutCallable implements 
> Callable {
> @Override
> public Boolean call() throws Exception {
> byte[] rowToLock = "ROW".getBytes();
> byte[] colFamily = "COLUMN_FAMILY".getBytes();
> byte[] column = "COLUMN".getBytes();
> byte[] newValue = "NEW_VALUE".getBytes();
> byte[] oldValue = "OLD_VALUE".getBytes();
> byte[] tableName = "table".getBytes();
> boolean acquired = false;
> try (Connection conn = DriverManager.getConnection(getUrl())) {
> try (HBaseAdmin admin = 
> conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
> HTableDescriptor tableDesc = new 
> HTableDescriptor(TableName.valueOf(tableName));
> HColumnDescriptor columnDesc = new 
> HColumnDescriptor(colFamily);
> columnDesc.setTimeToLive(600);
> tableDesc.addFamily(columnDesc);
> try {
> admin.createTable(tableDesc);
> } catch (TableExistsException e) {
> // ignore
> }
> try (HTableInterface table = 
> admin.getConnection().getTable(tableName)) {
> Put put = new Put(rowToLock);
> put.add(colFamily, column, oldValue); // add a row 
> with column set to oldValue
> table.put(put);
> put = new Put(rowToLock);
> put.add(colFamily, column, newValue);
> // only one of the threads should be able to get 
> return value of true for the expected value of oldValue
> acquired = table.checkAndPut(rowToLock, colFamily, 
> column, oldValue, put); 
> if (!acquired) {
>// if a thread didn't get true before, then it 
> shouldn't get true this time either
>// because the column DOES exist
>acquired = table.checkAndPut(rowToLock, colFamily, 
> column, null, put);
> }
> }
> }
> }  
> return acquired;
> }
> }
> {code}
> cc [~apurtell], [~jamestaylor], [~lhofhansl]. 



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)