private void addCoprocessors()

in phoenix-core-client/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java [1294:1560]


    private void addCoprocessors(byte[] tableName, TableDescriptorBuilder builder,
            PTableType tableType, Map<String, Object> tableProps, TableDescriptor existingDesc,
            boolean doNotAddGlobalIndexChecker) throws SQLException {
        // The phoenix jar must be available on HBase classpath
        int priority = props.getInt(QueryServices.COPROCESSOR_PRIORITY_ATTRIB, QueryServicesOptions.DEFAULT_COPROCESSOR_PRIORITY);
        try {
            TableDescriptor newDesc = builder.build();
            TransactionFactory.Provider provider = getTransactionProvider(tableProps);
            boolean isTransactional = (provider != null);

            boolean indexRegionObserverEnabled = config.getBoolean(
                    QueryServices.INDEX_REGION_OBSERVER_ENABLED_ATTRIB,
                    QueryServicesOptions.DEFAULT_INDEX_REGION_OBSERVER_ENABLED);
            boolean isViewIndex = TRUE_BYTES_AS_STRING
                    .equals(tableProps.get(MetaDataUtil.IS_VIEW_INDEX_TABLE_PROP_NAME));
            boolean isServerSideMaskingEnabled = config.getBoolean(
                    QueryServices.PHOENIX_TTL_SERVER_SIDE_MASKING_ENABLED,
                    QueryServicesOptions.DEFAULT_SERVER_SIDE_MASKING_ENABLED);

            boolean isViewBaseTransactional = false;
            if (!isTransactional && isViewIndex) {
                if (tableProps.containsKey(TRANSACTIONAL) &&
                        Boolean.TRUE.equals(tableProps.get(TRANSACTIONAL))) {
                    isViewBaseTransactional = true;
                }
            }

            if (!isTransactional && !isViewBaseTransactional
                    && (tableType == PTableType.INDEX || isViewIndex)) {
                if (!indexRegionObserverEnabled && newDesc.hasCoprocessor(QueryConstants.GLOBAL_INDEX_CHECKER_CLASSNAME)) {
                    builder.removeCoprocessor(QueryConstants.GLOBAL_INDEX_CHECKER_CLASSNAME);
                } else if (indexRegionObserverEnabled && !newDesc.hasCoprocessor(QueryConstants.GLOBAL_INDEX_CHECKER_CLASSNAME) &&
                        !isLocalIndexTable(newDesc.getColumnFamilyNames())) {
                    if (newDesc.hasCoprocessor(QueryConstants.INDEX_REGION_OBSERVER_CLASSNAME)) {
                        builder.removeCoprocessor(QueryConstants.INDEX_REGION_OBSERVER_CLASSNAME);
                    }
                    if (!doNotAddGlobalIndexChecker) {
                        builder.setCoprocessor(CoprocessorDescriptorBuilder
                                .newBuilder(QueryConstants.GLOBAL_INDEX_CHECKER_CLASSNAME)
                                .setPriority(priority - 1).build());
                    }
                }
            }

            if (!newDesc.hasCoprocessor(QueryConstants.SCAN_REGION_OBSERVER_CLASSNAME)) {
                builder.setCoprocessor(CoprocessorDescriptorBuilder.newBuilder(QueryConstants.SCAN_REGION_OBSERVER_CLASSNAME)
                        .setPriority(priority).build());
            }
            if (!newDesc.hasCoprocessor(QueryConstants.UNGROUPED_AGGREGATE_REGION_OBSERVER_CLASSNAME)) {
                builder.setCoprocessor(
                        CoprocessorDescriptorBuilder.newBuilder(QueryConstants.UNGROUPED_AGGREGATE_REGION_OBSERVER_CLASSNAME)
                                .setPriority(priority).build());
            }
            if (!newDesc.hasCoprocessor(QueryConstants.GROUPED_AGGREGATE_REGION_OBSERVER_CLASSNAME)) {
                builder.setCoprocessor(
                        CoprocessorDescriptorBuilder.newBuilder(QueryConstants.GROUPED_AGGREGATE_REGION_OBSERVER_CLASSNAME)
                                .setPriority(priority).build());
            }
            if (!newDesc.hasCoprocessor(QueryConstants.SERVER_CACHING_ENDPOINT_IMPL_CLASSNAME)) {
                builder.setCoprocessor(
                        CoprocessorDescriptorBuilder.newBuilder(QueryConstants.SERVER_CACHING_ENDPOINT_IMPL_CLASSNAME)
                                .setPriority(priority).build());
            }

            // TODO: better encapsulation for this
            // Since indexes can't have indexes, don't install our indexing coprocessor for indexes.
            // Also don't install on the SYSTEM.STATS table because we use
            // all-or-none mutate class which break when this coprocessor is installed (PHOENIX-1318).
            // With PHOENIX-7107 which introduced indexes on SYSTEM.CATALOG we need to install the
            // indexing coprocessor on SYSTEM.CATALOG
            if ((tableType != PTableType.INDEX && tableType != PTableType.VIEW && !isViewIndex)
                    && !SchemaUtil.isStatsTable(tableName)) {
                if (isTransactional) {
                    if (!newDesc.hasCoprocessor(QueryConstants.PHOENIX_TRANSACTIONAL_INDEXER_CLASSNAME)) {
                        builder.setCoprocessor(
                                CoprocessorDescriptorBuilder.newBuilder(QueryConstants.PHOENIX_TRANSACTIONAL_INDEXER_CLASSNAME)
                                        .setPriority(priority).build());
                    }
                    // For alter table, remove non transactional index coprocessor
                    if (newDesc.hasCoprocessor(QueryConstants.INDEXER_CLASSNAME)) {
                        builder.removeCoprocessor(QueryConstants.INDEXER_CLASSNAME);
                    }
                    if (newDesc.hasCoprocessor(QueryConstants.INDEX_REGION_OBSERVER_CLASSNAME)) {
                        builder.removeCoprocessor(QueryConstants.INDEX_REGION_OBSERVER_CLASSNAME);
                    }
                } else {
                    // If exception on alter table to transition back to non transactional
                    if (newDesc.hasCoprocessor(QueryConstants.PHOENIX_TRANSACTIONAL_INDEXER_CLASSNAME)) {
                        builder.removeCoprocessor(QueryConstants.PHOENIX_TRANSACTIONAL_INDEXER_CLASSNAME);
                    }
                    // we only want to mess with the indexing coprocs if we're on the original
                    // CREATE statement. Otherwise, if we're on an ALTER or CREATE TABLE
                    // IF NOT EXISTS of an existing table, we should leave them unaltered,
                    // because they should be upgraded or downgraded using the IndexUpgradeTool
                    if (!doesPhoenixTableAlreadyExist(existingDesc)) {
                        if (indexRegionObserverEnabled) {
                            if (newDesc.hasCoprocessor(QueryConstants.INDEXER_CLASSNAME)) {
                                builder.removeCoprocessor(QueryConstants.INDEXER_CLASSNAME);
                            }
                            if (!newDesc.hasCoprocessor(QueryConstants.INDEX_REGION_OBSERVER_CLASSNAME)) {
                                Map<String, String> opts = Maps.newHashMapWithExpectedSize(1);
                                opts.put(IndexUtil.CODEC_CLASS_NAME_KEY,  PhoenixIndexCodec.class.getName());
                                IndexUtil.enableIndexing(builder, IndexUtil.PHOENIX_INDEX_BUILDER_CLASSNAME,
                                        opts, priority, QueryConstants.INDEX_REGION_OBSERVER_CLASSNAME);
                            }
                        } else {
                            if (newDesc.hasCoprocessor(QueryConstants.INDEX_REGION_OBSERVER_CLASSNAME)) {
                                builder.removeCoprocessor(QueryConstants.INDEX_REGION_OBSERVER_CLASSNAME);
                            }
                            if (!newDesc.hasCoprocessor(QueryConstants.INDEXER_CLASSNAME)) {
                                Map<String, String> opts = Maps.newHashMapWithExpectedSize(1);
                                opts.put(IndexUtil.CODEC_CLASS_NAME_KEY, PhoenixIndexCodec.class.getName());
                                IndexUtil.enableIndexing(builder, IndexUtil.PHOENIX_INDEX_BUILDER_CLASSNAME,
                                        opts, priority, QueryConstants.INDEXER_CLASSNAME);
                            }
                        }
                    }
                }
            }

            if ((SchemaUtil.isStatsTable(tableName) || SchemaUtil.isMetaTable(tableName))
                    && !newDesc.hasCoprocessor(QueryConstants.MULTI_ROW_MUTATION_ENDPOINT_CLASSNAME)) {
                builder.setCoprocessor(
                        CoprocessorDescriptorBuilder
                                .newBuilder(QueryConstants.MULTI_ROW_MUTATION_ENDPOINT_CLASSNAME)
                                .setPriority(priority)
                                .setProperties(Collections.emptyMap())
                                .build());
            }

            Set<byte[]> familiesKeys = builder.build().getColumnFamilyNames();
            for (byte[] family: familiesKeys) {
                if (Bytes.toString(family).startsWith(QueryConstants.LOCAL_INDEX_COLUMN_FAMILY_PREFIX)) {
                    if (!newDesc.hasCoprocessor(QueryConstants.INDEX_HALF_STORE_FILE_READER_GENERATOR_CLASSNAME)) {
                        builder.setCoprocessor(
                                CoprocessorDescriptorBuilder
                                        .newBuilder(QueryConstants.INDEX_HALF_STORE_FILE_READER_GENERATOR_CLASSNAME)
                                        .setPriority(priority)
                                        .setProperties(Collections.emptyMap())
                                        .build());
                        break;
                    }
                }
            }

            // Setup split policy on Phoenix metadata table to ensure that the key values of a Phoenix table
            // stay on the same region.
            if (SchemaUtil.isMetaTable(tableName) || SchemaUtil.isFunctionTable(tableName)) {
                if (!newDesc.hasCoprocessor(QueryConstants.META_DATA_ENDPOINT_IMPL_CLASSNAME)) {
                    builder.setCoprocessor(
                            CoprocessorDescriptorBuilder
                                    .newBuilder(QueryConstants.META_DATA_ENDPOINT_IMPL_CLASSNAME)
                                    .setPriority(priority)
                                    .setProperties(Collections.emptyMap())
                                    .build());
                }
                if (SchemaUtil.isMetaTable(tableName) ) {
                    if (!newDesc.hasCoprocessor(QueryConstants.META_DATA_REGION_OBSERVER_CLASSNAME)) {
                        builder.setCoprocessor(
                                CoprocessorDescriptorBuilder
                                        .newBuilder(QueryConstants.META_DATA_REGION_OBSERVER_CLASSNAME)
                                        .setPriority(priority + 1)
                                        .setProperties(Collections.emptyMap())
                                        .build());
                    }
                }
            } else if (SchemaUtil.isSequenceTable(tableName)) {
                if (!newDesc.hasCoprocessor(QueryConstants.SEQUENCE_REGION_OBSERVER_CLASSNAME)) {
                    builder.setCoprocessor(
                            CoprocessorDescriptorBuilder
                                    .newBuilder(QueryConstants.SEQUENCE_REGION_OBSERVER_CLASSNAME)
                                    .setPriority(priority)
                                    .setProperties(Collections.emptyMap())
                                    .build());
                }
            } else if (SchemaUtil.isTaskTable(tableName)) {
                if (!newDesc.hasCoprocessor(QueryConstants.TASK_REGION_OBSERVER_CLASSNAME)) {
                    builder.setCoprocessor(
                            CoprocessorDescriptorBuilder
                                    .newBuilder(QueryConstants.TASK_REGION_OBSERVER_CLASSNAME)
                                    .setPriority(priority)
                                    .setProperties(Collections.emptyMap())
                                    .build());
                }
                if (!newDesc.hasCoprocessor(QueryConstants.TASK_META_DATA_ENDPOINT_CLASSNAME)) {
                    builder.setCoprocessor(
                            CoprocessorDescriptorBuilder
                                    .newBuilder(QueryConstants.TASK_META_DATA_ENDPOINT_CLASSNAME)
                                    .setPriority(priority)
                                    .setProperties(Collections.emptyMap())
                                    .build());
                }
            } else if (SchemaUtil.isChildLinkTable(tableName)) {
                if (!newDesc.hasCoprocessor(QueryConstants.CHILD_LINK_META_DATA_ENDPOINT_CLASSNAME)) {
                    builder.setCoprocessor(
                            CoprocessorDescriptorBuilder
                                    .newBuilder(QueryConstants.CHILD_LINK_META_DATA_ENDPOINT_CLASSNAME)
                                    .setPriority(priority)
                                    .setProperties(Collections.emptyMap())
                                    .build());
                }
            }

            if (isTransactional) {
                String coprocessorClassName = provider.getTransactionProvider().getCoprocessorClassName();
                if (!newDesc.hasCoprocessor(coprocessorClassName)) {
                    builder.setCoprocessor(
                            CoprocessorDescriptorBuilder
                                    .newBuilder(coprocessorClassName)
                                    .setPriority(priority - 10)
                                    .setProperties(Collections.emptyMap())
                                    .build());
                }
                String coprocessorGCClassName = provider.getTransactionProvider().getGCCoprocessorClassName();
                if (coprocessorGCClassName != null) {
                    if (!newDesc.hasCoprocessor(coprocessorGCClassName)) {
                        builder.setCoprocessor(
                                CoprocessorDescriptorBuilder
                                        .newBuilder(coprocessorGCClassName)
                                        .setPriority(priority - 10)
                                        .setProperties(Collections.emptyMap())
                                        .build());
                    }
                }
            } else {
                // Remove all potential transactional coprocessors
                for (TransactionFactory.Provider aprovider : TransactionFactory.Provider.available()) {
                    String coprocessorClassName = aprovider.getTransactionProvider().getCoprocessorClassName();
                    String coprocessorGCClassName = aprovider.getTransactionProvider().getGCCoprocessorClassName();
                    if (coprocessorClassName != null && newDesc.hasCoprocessor(coprocessorClassName)) {
                        builder.removeCoprocessor(coprocessorClassName);
                    }
                    if (coprocessorGCClassName != null && newDesc.hasCoprocessor(coprocessorGCClassName)) {
                        builder.removeCoprocessor(coprocessorGCClassName);
                    }
                }
            }

            // The priority for this co-processor should be set higher than the GlobalIndexChecker so that the read repair scans
            // are intercepted by the TTLAwareRegionObserver and only the rows that are not ttl-expired are returned.
            if (!SchemaUtil.isSystemTable(tableName)) {
                if (!newDesc.hasCoprocessor(QueryConstants.PHOENIX_TTL_REGION_OBSERVER_CLASSNAME) &&
                        isServerSideMaskingEnabled) {
                        builder.setCoprocessor(
                            CoprocessorDescriptorBuilder
                                    .newBuilder(QueryConstants.PHOENIX_TTL_REGION_OBSERVER_CLASSNAME)
                                    .setPriority(priority - 2)
                                    .setProperties(Collections.emptyMap())
                                    .build());
                }
            }

            if (Arrays.equals(tableName, SchemaUtil.getPhysicalName(SYSTEM_CATALOG_NAME_BYTES, props).getName())) {
                if (!newDesc.hasCoprocessor(QueryConstants.SYSTEM_CATALOG_REGION_OBSERVER_CLASSNAME)) {
                    builder.setCoprocessor(
                            CoprocessorDescriptorBuilder
                                    .newBuilder(QueryConstants.SYSTEM_CATALOG_REGION_OBSERVER_CLASSNAME)
                                    .setPriority(priority)
                                    .setProperties(Collections.emptyMap())
                                    .build());
                }
            }

        } catch (IOException e) {
            throw ClientUtil.parseServerException(e);
        }
    }