Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -31,6 +31,7 @@
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.replication.ChainWALEntryFilter;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.wal.WAL;
import org.apache.hadoop.hbase.wal.WALEdit;
Expand DownExpand Up@@ -134,11 +135,17 @@ public void testSystemCatalogWALEntryFilter() throws Exception {

//verify that the tenant view WAL.Entry passes the filter and the non-tenant view does not
SystemCatalogWALEntryFilter filter = new SystemCatalogWALEntryFilter();
Assert.assertNull(filter.filter(nonTenantEntry));
WAL.Entry filteredTenantEntry = filter.filter(tenantEntry);
// Chain the system catalog WAL entry filter to ChainWALEntryFilter
ChainWALEntryFilter chainWALEntryFilter = new ChainWALEntryFilter(filter);
// Asserting the WALEdit for non tenant has cells before getting filtered
Assert.assertTrue(nonTenantEntry.getEdit().size() > 0);
// All the cells will get removed by the filter since they do not belong to tenant
Assert.assertTrue("Non tenant edits for system catalog should not get filtered",
chainWALEntryFilter.filter(nonTenantEntry).getEdit().isEmpty());
WAL.Entry filteredTenantEntry = chainWALEntryFilter.filter(tenantEntry);
Assert.assertNotNull("Tenant view was filtered when it shouldn't be!", filteredTenantEntry);
Assert.assertEquals(tenantEntry.getEdit().size(),
filter.filter(tenantEntry).getEdit().size());
Assert.assertEquals("filtered entry is not correct",
tenantEntry.getEdit().size(), filteredTenantEntry.getEdit().size());

//now check that a WAL.Entry with cells from both a tenant and a non-tenant
//catalog row only allow the tenant cells through
Expand All@@ -150,7 +157,7 @@ public void testSystemCatalogWALEntryFilter() throws Exception {
Assert.assertEquals(tenantEntry.getEdit().size() + nonTenantEntry.getEdit().size()
, comboEntry.getEdit().size());
Assert.assertEquals(tenantEntry.getEdit().size(),
filter.filter(comboEntry).getEdit().size());
chainWALEntryFilter.filter(comboEntry).getEdit().size());
}

public Get getGet(PTable catalogTable, byte[] tenantId, String viewName) {
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -17,16 +17,13 @@
*/
package org.apache.phoenix.replication;

import java.util.List;

import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.replication.WALCellFilter;
import org.apache.hadoop.hbase.replication.WALEntryFilter;
import org.apache.hadoop.hbase.wal.WAL;
import org.apache.phoenix.query.QueryConstants;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we can get rid of List and Lists imports

import org.apache.phoenix.util.SchemaUtil;

import org.apache.phoenix.thirdparty.com.google.common.collect.Lists;

/**
* Standard replication of the SYSTEM.CATALOG table can be dangerous because schemas
Expand All@@ -35,36 +32,40 @@
* be copied. This WALEntryFilter will only allow tenant-owned rows in SYSTEM.CATALOG to
* be replicated. Data from all other tables is automatically passed.
*/
public class SystemCatalogWALEntryFilter implements WALEntryFilter {
public class SystemCatalogWALEntryFilter implements
WALEntryFilter, WALCellFilter {
/**
* This is an optimization to just skip the cell filter if we do not care
* about cell filter for certain WALEdits.
*/
private boolean skipCellFilter;

@Override
public WAL.Entry filter(WAL.Entry entry) {

//if the WAL.Entry's table isn't System.Catalog or System.Child_Link, it auto-passes this filter
//TODO: when Phoenix drops support for pre-1.3 versions of HBase, redo as a WALCellFilter
// We use the WALCellFilter to filter the cells from entry, WALEntryFilter
// should not block anything
// if the WAL.Entry's table isn't System.Catalog or System.Child_Link,
// it auto-passes this filter
if (!SchemaUtil.isMetaTable(entry.getKey().getTableName().getName())){
return entry;
skipCellFilter = true;
} else {
skipCellFilter = false;
}
return entry;
}

List<Cell> cells = entry.getEdit().getCells();
List<Cell> cellsToRemove = Lists.newArrayList();
for (Cell cell : cells) {
if (!isTenantRowCell(cell)){
cellsToRemove.add(cell);
}
}
cells.removeAll(cellsToRemove);
if (cells.size() > 0) {
return entry;
} else {
return null;
@Override
public Cell filterCell(final WAL.Entry entry, final Cell cell) {
if (skipCellFilter) {
return cell;
}
return isTenantRowCell(cell) ? cell : null;
}

private boolean isTenantRowCell(Cell cell) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not related to this changes, but wondering if we need to construct ImmutableBytesWritable object.
Can this method impl be reduced to:

 return cell.getRowArray()[cell.getRowOffset()] != QueryConstants.SEPARATOR_BYTE;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@virajjasani - yes, I believe that will work. ImmutableBytesWritable.get() just returns the underlying byte array

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, it should be same, I will change that

publicbyte [] get() {
if (this.bytes == null) {
thrownewIllegalStateException("Uninitialiized. Null constructor " +
"called w/o accompaying readFields invocation");
}
returnthis.bytes;
}

ImmutableBytesWritable key =
new ImmutableBytesWritable(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength());
//rows in system.catalog that aren't tenant-owned will have a leading separator byte
return key.get()[key.getOffset()] != QueryConstants.SEPARATOR_BYTE;
// rows in system.catalog that aren't tenant-owned
// will have a leading separator byte
return cell.getRowArray()[cell.getRowOffset()]
!= QueryConstants.SEPARATOR_BYTE;
}
}