From 914bd023dfdf4564df8a231bafe6442796470110 Mon Sep 17 00:00:00 2001 From: chenheng Date: Fri, 8 Jan 2016 11:01:25 +0800 Subject: [PATCH] HBASE-15071 Cleanup bypass semantic in MasterCoprocessorHost --- .../hadoop/hbase/coprocessor/MasterObserver.java | 41 +++++++++++++--- .../org/apache/hadoop/hbase/master/HMaster.java | 53 +++++++++----------- .../hadoop/hbase/master/MasterCoprocessorHost.java | 56 +++++++++++----------- 3 files changed, 85 insertions(+), 65 deletions(-) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java index ede8cd4..27eb180 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/MasterObserver.java @@ -232,6 +232,7 @@ public interface MasterObserver extends Coprocessor { /** * Called prior to adding a new column family to the table. Called as part of * add column RPC call. + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @param tableName the name of the table * @param columnFamily the HColumnDescriptor @@ -250,7 +251,7 @@ public interface MasterObserver extends Coprocessor { * Implementation note: This replaces the deprecated * {@link #preAddColumn(ObserverContext, TableName, HColumnDescriptor)} method. * Make sure to implement only one of the two as both are called. - * + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @param tableName the name of the table * @param columnFamily the HColumnDescriptor @@ -290,6 +291,7 @@ public interface MasterObserver extends Coprocessor { /** * Called prior to adding a new column family to the table. Called as part of * add column handler. + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @param tableName the name of the table * @param columnFamily the HColumnDescriptor @@ -309,7 +311,7 @@ public interface MasterObserver extends Coprocessor { * Implementation note: This replaces the deprecated * {@link #preAddColumnHandler(ObserverContext, TableName, HColumnDescriptor)} method. * Make sure to implement only one of the two as both are called. - * + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @param tableName the name of the table * @param columnFamily the HColumnDescriptor @@ -353,6 +355,7 @@ public interface MasterObserver extends Coprocessor { /** * Called prior to modifying a column family's attributes. Called as part of * modify column RPC call. + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @param tableName the name of the table * @param columnFamily the HColumnDescriptor @@ -371,7 +374,7 @@ public interface MasterObserver extends Coprocessor { * Implementation note: This replaces the deprecated * {@link #preModifyColumn(ObserverContext, TableName, HColumnDescriptor)} method. * Make sure to implement only one of the two as both are called. - * + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @param tableName the name of the table * @param columnFamily the HColumnDescriptor @@ -411,6 +414,7 @@ public interface MasterObserver extends Coprocessor { /** * Called prior to modifying a column family's attributes. Called as part of * modify column handler. + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @param tableName the name of the table * @param columnFamily the HColumnDescriptor @@ -430,7 +434,7 @@ public interface MasterObserver extends Coprocessor { * Implementation note: This replaces the deprecated * {@link #preModifyColumnHandler(ObserverContext, TableName, HColumnDescriptor)} method. * Make sure to implement only one of the two as both are called. - * + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @param tableName the name of the table * @param columnFamily the HColumnDescriptor @@ -473,6 +477,7 @@ public interface MasterObserver extends Coprocessor { /** * Called prior to deleting the entire column family. Called as part of * delete column RPC call. + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @param tableName the name of the table * @param columnFamily the column family @@ -491,7 +496,7 @@ public interface MasterObserver extends Coprocessor { * Implementation note: This replaces the deprecated * {@link #preDeleteColumn(ObserverContext, TableName, byte[])} method. * Make sure to implement only one of the two as both are called. - * + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @param tableName the name of the table * @param columnFamily the column @@ -531,6 +536,7 @@ public interface MasterObserver extends Coprocessor { /** * Called prior to deleting the entire column family. Called as part of * delete column handler. + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @param tableName the name of the table * @param columnFamily the column family @@ -550,7 +556,7 @@ public interface MasterObserver extends Coprocessor { * Implementation note: This replaces the deprecated * {@link #preDeleteColumnHandler(ObserverContext, TableName, byte[])} method. * Make sure to implement only one of the two as both are called. - * + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @param tableName the name of the table * @param columnFamily the column family @@ -671,6 +677,7 @@ public interface MasterObserver extends Coprocessor { /** * Called before a abortProcedure request has been processed. + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @throws IOException */ @@ -688,6 +695,7 @@ public interface MasterObserver extends Coprocessor { /** * Called before a listProcedures request has been processed. + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @throws IOException */ @@ -729,6 +737,8 @@ public interface MasterObserver extends Coprocessor { /** * Called prior to assigning a specific region. + * If bypass the default action, it will return an empty AssignRegionResponse + * TODO: we should modify this interface to return AssignRegionResponse * @param ctx the environment to interact with the framework and master * @param regionInfo the regionInfo of the region */ @@ -745,6 +755,8 @@ public interface MasterObserver extends Coprocessor { /** * Called prior to unassigning a given region. + * If bypass the default action, it will return an empty UnassignRegionResponse + * TODO: we should modify this interface to return UnassignRegionResponse * @param ctx the environment to interact with the framework and master * @param regionInfo * @param force whether to force unassignment or not @@ -764,6 +776,7 @@ public interface MasterObserver extends Coprocessor { /** * Called prior to marking a given region as offline. ctx.bypass() will not have any * impact on this hook. + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @param regionInfo */ @@ -781,6 +794,8 @@ public interface MasterObserver extends Coprocessor { /** * Called prior to requesting rebalancing of the cluster regions, though after * the initial checks for regions in transition and the balance switch flag. + * If bypass the default action, it will return false + * TODO: we should modify this interface to return boolean * @param ctx the environment to interact with the framework and master */ void preBalance(final ObserverContext ctx) @@ -815,6 +830,7 @@ public interface MasterObserver extends Coprocessor { /** * Called prior to shutting down the full HBase cluster, including this + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * {@link org.apache.hadoop.hbase.master.HMaster} process. */ void preShutdown(final ObserverContext ctx) @@ -823,6 +839,7 @@ public interface MasterObserver extends Coprocessor { /** * Called immediately prior to stopping this + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * {@link org.apache.hadoop.hbase.master.HMaster} process. */ void preStopMaster(final ObserverContext ctx) @@ -838,6 +855,7 @@ public interface MasterObserver extends Coprocessor { /** * Call before the master initialization is set to true. + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * {@link org.apache.hadoop.hbase.master.HMaster} process. */ void preMasterInitialization(final ObserverContext ctx) @@ -961,6 +979,7 @@ public interface MasterObserver extends Coprocessor { /** * Called before a getTableDescriptors request has been processed. + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @param tableNamesList the list of table names, or null if querying for all * @param descriptors an empty list, can be filled with what to return if bypassing @@ -985,6 +1004,7 @@ public interface MasterObserver extends Coprocessor { /** * Called before a getTableNames request has been processed. + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @param descriptors an empty list, can be filled with what to return if bypassing * @param regex regular expression used for filtering the table names @@ -1017,6 +1037,7 @@ public interface MasterObserver extends Coprocessor { NamespaceDescriptor ns) throws IOException; /** * Called after the createNamespace operation has been requested. + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @param ns the NamespaceDescriptor for the table * @throws IOException @@ -1061,6 +1082,7 @@ public interface MasterObserver extends Coprocessor { /** * Called before a getNamespaceDescriptor request has been processed. + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @param namespace the name of the namespace * @throws IOException @@ -1079,6 +1101,7 @@ public interface MasterObserver extends Coprocessor { /** * Called before a listNamespaceDescriptors request has been processed. + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @param descriptors an empty list, can be filled with what to return if bypassing * @throws IOException @@ -1098,6 +1121,7 @@ public interface MasterObserver extends Coprocessor { /** * Called before the table memstore is flushed to disk. + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @param tableName the name of the table * @throws IOException @@ -1116,6 +1140,7 @@ public interface MasterObserver extends Coprocessor { /** * Called before the quota for the user is stored. + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @param userName the name of user * @param quotas the quota settings @@ -1136,6 +1161,7 @@ public interface MasterObserver extends Coprocessor { /** * Called before the quota for the user on the specified table is stored. + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @param userName the name of user * @param tableName the name of the table @@ -1158,6 +1184,7 @@ public interface MasterObserver extends Coprocessor { /** * Called before the quota for the user on the specified namespace is stored. + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @param userName the name of user * @param namespace the name of the namespace @@ -1180,6 +1207,7 @@ public interface MasterObserver extends Coprocessor { /** * Called before the quota for the table is stored. + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @param tableName the name of the table * @param quotas the quota settings @@ -1200,6 +1228,7 @@ public interface MasterObserver extends Coprocessor { /** * Called before the quota for the namespace is stored. + * It can't bypass the default action, e.g., ctx.bypass() won't have effect. * @param ctx the environment to interact with the framework and master * @param namespace the name of the namespace * @param quotas the quota settings diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java index 8ff7ab1..77ea5de 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java @@ -1846,9 +1846,7 @@ public class HMaster extends HRegionServer implements MasterServices { checkCompression(columnDescriptor); checkEncryption(conf, columnDescriptor); if (cpHost != null) { - if (cpHost.preAddColumn(tableName, columnDescriptor)) { - return -1; - } + cpHost.preAddColumn(tableName, columnDescriptor); } // Execute the operation synchronously - wait for the operation to complete before continuing. long procId = this.procedureExecutor.submitProcedure( @@ -1873,9 +1871,7 @@ public class HMaster extends HRegionServer implements MasterServices { checkCompression(descriptor); checkEncryption(conf, descriptor); if (cpHost != null) { - if (cpHost.preModifyColumn(tableName, descriptor)) { - return -1; - } + cpHost.preModifyColumn(tableName, descriptor); } LOG.info(getClientIdAuditPrefix() + " modify " + descriptor); @@ -1901,9 +1897,7 @@ public class HMaster extends HRegionServer implements MasterServices { throws IOException { checkInitialized(); if (cpHost != null) { - if (cpHost.preDeleteColumn(tableName, columnName)) { - return -1; - } + cpHost.preDeleteColumn(tableName, columnName); } LOG.info(getClientIdAuditPrefix() + " delete " + Bytes.toString(columnName)); @@ -2438,8 +2432,8 @@ public class HMaster extends HRegionServer implements MasterServices { throws IOException { checkInitialized(); TableName.isLegalNamespaceName(Bytes.toBytes(namespaceDescriptor.getName())); - if (this.cpHost != null && this.cpHost.preCreateNamespace(namespaceDescriptor)) { - throw new BypassCoprocessorException(); + if (this.cpHost != null) { + this.cpHost.preCreateNamespace(namespaceDescriptor); } LOG.info(getClientIdAuditPrefix() + " creating " + namespaceDescriptor); // Execute the operation synchronously - wait for the operation to complete before continuing. @@ -2460,8 +2454,8 @@ public class HMaster extends HRegionServer implements MasterServices { throws IOException { checkInitialized(); TableName.isLegalNamespaceName(Bytes.toBytes(namespaceDescriptor.getName())); - if (this.cpHost != null && this.cpHost.preModifyNamespace(namespaceDescriptor)) { - throw new BypassCoprocessorException(); + if (this.cpHost != null) { + this.cpHost.preModifyNamespace(namespaceDescriptor); } LOG.info(getClientIdAuditPrefix() + " modify " + namespaceDescriptor); // Execute the operation synchronously - wait for the operation to complete before continuing. @@ -2480,8 +2474,8 @@ public class HMaster extends HRegionServer implements MasterServices { long deleteNamespace(final String name, final long nonceGroup, final long nonce) throws IOException { checkInitialized(); - if (this.cpHost != null && this.cpHost.preDeleteNamespace(name)) { - throw new BypassCoprocessorException(); + if (this.cpHost != null) { + this.cpHost.preDeleteNamespace(name); } LOG.info(getClientIdAuditPrefix() + " delete " + name); // Execute the operation synchronously - wait for the operation to complete before continuing. @@ -2512,12 +2506,10 @@ public class HMaster extends HRegionServer implements MasterServices { final List nsds = new ArrayList(); boolean bypass = false; if (cpHost != null) { - bypass = cpHost.preListNamespaceDescriptors(nsds); - } - if (!bypass) { - nsds.addAll(this.clusterSchemaService.getNamespaces()); - if (this.cpHost != null) this.cpHost.postListNamespaceDescriptors(nsds); + cpHost.preListNamespaceDescriptors(nsds); } + nsds.addAll(this.clusterSchemaService.getNamespaces()); + if (this.cpHost != null) this.cpHost.postListNamespaceDescriptors(nsds); return nsds; } @@ -2576,13 +2568,12 @@ public class HMaster extends HRegionServer implements MasterServices { final List tableNameList, final boolean includeSysTables) throws IOException { List htds = new ArrayList(); - boolean bypass = cpHost != null? - cpHost.preGetTableDescriptors(tableNameList, htds, regex): false; - if (!bypass) { - htds = getTableDescriptors(htds, namespace, regex, tableNameList, includeSysTables); - if (cpHost != null) { - cpHost.postGetTableDescriptors(tableNameList, htds, regex); - } + if (cpHost != null) { + cpHost.preGetTableDescriptors(tableNameList, htds, regex); + } + htds = getTableDescriptors(htds, namespace, regex, tableNameList, includeSysTables); + if (cpHost != null) { + cpHost.postGetTableDescriptors(tableNameList, htds, regex); } return htds; } @@ -2597,11 +2588,11 @@ public class HMaster extends HRegionServer implements MasterServices { public List listTableNames(final String namespace, final String regex, final boolean includeSysTables) throws IOException { List htds = new ArrayList(); - boolean bypass = cpHost != null? cpHost.preGetTableNames(htds, regex): false; - if (!bypass) { - htds = getTableDescriptors(htds, namespace, regex, null, includeSysTables); - if (cpHost != null) cpHost.postGetTableNames(htds, regex); + if (cpHost != null) { + cpHost.preGetTableNames(htds, regex); } + htds = getTableDescriptors(htds, namespace, regex, null, includeSysTables); + if (cpHost != null) cpHost.postGetTableNames(htds, regex); List result = new ArrayList(htds.size()); for (HTableDescriptor htd: htds) result.add(htd.getTableName()); return result; diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java index 5fa92c6..d49c48e 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterCoprocessorHost.java @@ -105,8 +105,8 @@ public class MasterCoprocessorHost masterServices); } - public boolean preCreateNamespace(final NamespaceDescriptor ns) throws IOException { - return execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { + public void preCreateNamespace(final NamespaceDescriptor ns) throws IOException { + execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { @Override public void call(MasterObserver oserver, ObserverContext ctx) throws IOException { @@ -125,8 +125,8 @@ public class MasterCoprocessorHost }); } - public boolean preDeleteNamespace(final String namespaceName) throws IOException { - return execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { + public void preDeleteNamespace(final String namespaceName) throws IOException { + execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { @Override public void call(MasterObserver oserver, ObserverContext ctx) throws IOException { @@ -145,8 +145,8 @@ public class MasterCoprocessorHost }); } - public boolean preModifyNamespace(final NamespaceDescriptor ns) throws IOException { - return execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { + public void preModifyNamespace(final NamespaceDescriptor ns) throws IOException { + execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { @Override public void call(MasterObserver oserver, ObserverContext ctx) throws IOException { @@ -187,9 +187,9 @@ public class MasterCoprocessorHost }); } - public boolean preListNamespaceDescriptors(final List descriptors) + public void preListNamespaceDescriptors(final List descriptors) throws IOException { - return execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { + execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { @Override public void call(MasterObserver oserver, ObserverContext ctx) throws IOException { @@ -379,9 +379,9 @@ public class MasterCoprocessorHost }); } - public boolean preAddColumn(final TableName tableName, final HColumnDescriptor columnFamily) + public void preAddColumn(final TableName tableName, final HColumnDescriptor columnFamily) throws IOException { - return execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { + execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { @Override public void call(MasterObserver oserver, ObserverContext ctx) throws IOException { @@ -403,10 +403,10 @@ public class MasterCoprocessorHost }); } - public boolean preAddColumnHandler(final TableName tableName, + public void preAddColumnHandler(final TableName tableName, final HColumnDescriptor columnFamily) throws IOException { - return execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { + execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { @Override public void call(MasterObserver oserver, ObserverContext ctx) throws IOException { @@ -428,9 +428,9 @@ public class MasterCoprocessorHost }); } - public boolean preModifyColumn(final TableName tableName, final HColumnDescriptor columnFamily) + public void preModifyColumn(final TableName tableName, final HColumnDescriptor columnFamily) throws IOException { - return execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { + execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { @Override public void call(MasterObserver oserver, ObserverContext ctx) throws IOException { @@ -452,9 +452,9 @@ public class MasterCoprocessorHost }); } - public boolean preModifyColumnHandler(final TableName tableName, + public void preModifyColumnHandler(final TableName tableName, final HColumnDescriptor columnFamily) throws IOException { - return execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { + execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { @Override public void call(MasterObserver oserver, ObserverContext ctx) throws IOException { @@ -476,9 +476,9 @@ public class MasterCoprocessorHost }); } - public boolean preDeleteColumn(final TableName tableName, final byte[] columnFamily) + public void preDeleteColumn(final TableName tableName, final byte[] columnFamily) throws IOException { - return execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { + execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { @Override public void call(MasterObserver oserver, ObserverContext ctx) throws IOException { @@ -500,9 +500,9 @@ public class MasterCoprocessorHost }); } - public boolean preDeleteColumnHandler(final TableName tableName, final byte[] columnFamily) + public void preDeleteColumnHandler(final TableName tableName, final byte[] columnFamily) throws IOException { - return execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { + execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { @Override public void call(MasterObserver oserver, ObserverContext ctx) throws IOException { @@ -604,10 +604,10 @@ public class MasterCoprocessorHost }); } - public boolean preAbortProcedure( + public void preAbortProcedure( final ProcedureExecutor procEnv, final long procId) throws IOException { - return execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { + execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { @Override public void call(MasterObserver oserver, ObserverContext ctx) throws IOException { @@ -626,8 +626,8 @@ public class MasterCoprocessorHost }); } - public boolean preListProcedures() throws IOException { - return execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { + public void preListProcedures() throws IOException { + execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { @Override public void call(MasterObserver oserver, ObserverContext ctx) throws IOException { @@ -927,9 +927,9 @@ public class MasterCoprocessorHost }); } - public boolean preGetTableDescriptors(final List tableNamesList, + public void preGetTableDescriptors(final List tableNamesList, final List descriptors, final String regex) throws IOException { - return execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { + execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { @Override public void call(MasterObserver oserver, ObserverContext ctx) throws IOException { @@ -949,9 +949,9 @@ public class MasterCoprocessorHost }); } - public boolean preGetTableNames(final List descriptors, + public void preGetTableNames(final List descriptors, final String regex) throws IOException { - return execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { + execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { @Override public void call(MasterObserver oserver, ObserverContext ctx) throws IOException { -- 1.9.3 (Apple Git-50)