[Feature](resource-group) Support alter resource group (#18990)

This commit is contained in:
赵立伟
2023-04-27 10:48:17 +08:00
committed by GitHub
parent 971018c0f1
commit 908518915d
9 changed files with 188 additions and 12 deletions

View File

@ -0,0 +1,69 @@
// 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.doris.analysis;
import org.apache.doris.catalog.Env;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.common.ErrorReport;
import org.apache.doris.common.UserException;
import org.apache.doris.common.util.PrintableMap;
import org.apache.doris.mysql.privilege.PrivPredicate;
import org.apache.doris.qe.ConnectContext;
import java.util.Map;
public class AlterResourceGroupStmt extends DdlStmt {
private final String resourceGroupName;
private final Map<String, String> properties;
public AlterResourceGroupStmt(String resourceGroupName, Map<String, String> properties) {
this.resourceGroupName = resourceGroupName;
this.properties = properties;
}
public String getResourceGroupName() {
return resourceGroupName;
}
public Map<String, String> getProperties() {
return properties;
}
@Override
public void analyze(Analyzer analyzer) throws UserException {
super.analyze(analyzer);
// check auth
if (!Env.getCurrentEnv().getAccessManager().checkGlobalPriv(ConnectContext.get(), PrivPredicate.ADMIN)) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, "ADMIN");
}
if (properties == null || properties.isEmpty()) {
throw new AnalysisException("Resource group properties can't be null");
}
}
@Override
public String toSql() {
StringBuilder sb = new StringBuilder();
sb.append("ALTER RESOURCE GROUP '").append(resourceGroupName).append("' ");
sb.append("PROPERTIES(").append(new PrintableMap<>(properties, " = ", true, false)).append(")");
return sb.toString();
}
}

View File

@ -803,7 +803,8 @@ public class JournalEntity implements Writable {
isRead = true;
break;
}
case OperationType.OP_CREATE_RESOURCE_GROUP: {
case OperationType.OP_CREATE_RESOURCE_GROUP:
case OperationType.OP_ALTER_RESOURCE_GROUP: {
data = ResourceGroup.read(in);
isRead = true;
break;

View File

@ -1018,6 +1018,11 @@ public class EditLog {
env.getResourceGroupMgr().replayDropResourceGroup(operationLog);
break;
}
case OperationType.OP_ALTER_RESOURCE_GROUP: {
final ResourceGroup resource = (ResourceGroup) journal.getData();
env.getResourceGroupMgr().replayAlterResourceGroup(resource);
break;
}
case OperationType.OP_INIT_EXTERNAL_TABLE: {
// Do nothing.
break;
@ -1564,6 +1569,10 @@ public class EditLog {
logEdit(OperationType.OP_ALTER_RESOURCE, resource);
}
public void logAlterResourceGroup(ResourceGroup resourceGroup) {
logEdit(OperationType.OP_ALTER_RESOURCE_GROUP, resourceGroup);
}
public void logCreateResourceGroup(ResourceGroup resourceGroup) {
logEdit(OperationType.OP_CREATE_RESOURCE_GROUP, resourceGroup);
}

View File

@ -284,6 +284,7 @@ public class OperationType {
// resource group 410 ~ 419
public static final short OP_CREATE_RESOURCE_GROUP = 410;
public static final short OP_DROP_RESOURCE_GROUP = 411;
public static final short OP_ALTER_RESOURCE_GROUP = 412;
/**
* Get opcode name by op code.

View File

@ -35,6 +35,7 @@ import org.apache.doris.analysis.AlterDatabaseQuotaStmt;
import org.apache.doris.analysis.AlterDatabaseRename;
import org.apache.doris.analysis.AlterMaterializedViewStmt;
import org.apache.doris.analysis.AlterPolicyStmt;
import org.apache.doris.analysis.AlterResourceGroupStmt;
import org.apache.doris.analysis.AlterResourceStmt;
import org.apache.doris.analysis.AlterRoutineLoadStmt;
import org.apache.doris.analysis.AlterSqlBlockRuleStmt;
@ -303,6 +304,8 @@ public class DdlExecutor {
env.createAnalysisJob((AnalyzeStmt) ddlStmt);
} else if (ddlStmt instanceof AlterResourceStmt) {
env.getResourceMgr().alterResource((AlterResourceStmt) ddlStmt);
} else if (ddlStmt instanceof AlterResourceGroupStmt) {
env.getResourceGroupMgr().alterResourceGroup((AlterResourceGroupStmt) ddlStmt);
} else if (ddlStmt instanceof CreatePolicyStmt) {
env.getPolicyMgr().createPolicy((CreatePolicyStmt) ddlStmt);
} else if (ddlStmt instanceof DropPolicyStmt) {

View File

@ -25,6 +25,7 @@ import org.apache.doris.common.proc.BaseProcResult;
import org.apache.doris.persist.gson.GsonUtils;
import org.apache.doris.thrift.TPipelineResourceGroup;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.gson.annotations.SerializedName;
@ -33,6 +34,7 @@ import org.apache.commons.lang3.StringUtils;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class ResourceGroup implements Writable {
@ -65,11 +67,33 @@ public class ResourceGroup implements Writable {
this.version = 0;
}
private ResourceGroup(long id, String name, Map<String, String> properties, long version) {
this.id = id;
this.name = name;
this.properties = properties;
this.version = version;
}
public static ResourceGroup create(String name, Map<String, String> properties) throws DdlException {
checkProperties(properties);
return new ResourceGroup(Env.getCurrentEnv().getNextId(), name, properties);
}
public static ResourceGroup create(ResourceGroup resourceGroup, Map<String, String> updateProperties)
throws DdlException {
Map<String, String> newProperties = new HashMap<>();
newProperties.putAll(resourceGroup.getProperties());
for (Map.Entry<String, String> kv : updateProperties.entrySet()) {
if (!Strings.isNullOrEmpty(kv.getValue())) {
newProperties.put(kv.getKey(), kv.getValue());
}
}
checkProperties(newProperties);
return new ResourceGroup(
resourceGroup.getId(), resourceGroup.getName(), newProperties, resourceGroup.getVersion() + 1);
}
private static void checkProperties(Map<String, String> properties) throws DdlException {
for (String propertyName : properties.keySet()) {
if (!ALL_PROPERTIES_NAME.contains(propertyName)) {
@ -100,6 +124,10 @@ public class ResourceGroup implements Writable {
return properties;
}
private long getVersion() {
return version;
}
public void getProcNodeData(BaseProcResult result) {
for (Map.Entry<String, String> entry : properties.entrySet()) {
result.addRow(Lists.newArrayList(String.valueOf(id), name, entry.getKey(), entry.getValue()));

View File

@ -17,6 +17,7 @@
package org.apache.doris.resource.resourcegroup;
import org.apache.doris.analysis.AlterResourceGroupStmt;
import org.apache.doris.analysis.CreateResourceGroupStmt;
import org.apache.doris.analysis.DropResourceGroupStmt;
import org.apache.doris.catalog.Env;
@ -85,6 +86,12 @@ public class ResourceGroupMgr implements Writable, GsonPostProcessable {
lock.writeLock().unlock();
}
private void checkResourceGroupEnabled() throws DdlException {
if (!Config.enable_resource_group) {
throw new DdlException("unsupported feature now, coming soon.");
}
}
public void init() {
if (Config.enable_resource_group || Config.use_fuzzy_session_variable /* for github workflow */) {
checkAndCreateDefaultGroup();
@ -99,7 +106,6 @@ public class ResourceGroupMgr implements Writable, GsonPostProcessable {
if (resourceGroup == null) {
throw new UserException("Resource group " + groupName + " does not exist");
}
// need to check resource group privs
resourceGroups.add(resourceGroup.toThrift());
} finally {
readUnlock();
@ -129,19 +135,17 @@ public class ResourceGroupMgr implements Writable, GsonPostProcessable {
}
public void createResourceGroup(CreateResourceGroupStmt stmt) throws DdlException {
if (!Config.enable_resource_group) {
throw new DdlException("unsupported feature now, coming soon.");
}
checkResourceGroupEnabled();
ResourceGroup resourceGroup = ResourceGroup.create(stmt.getResourceGroupName(), stmt.getProperties());
String resourceGroupNameName = resourceGroup.getName();
String resourceGroupName = resourceGroup.getName();
writeLock();
try {
if (nameToResourceGroup.putIfAbsent(resourceGroupNameName, resourceGroup) != null) {
if (nameToResourceGroup.putIfAbsent(resourceGroupName, resourceGroup) != null) {
if (stmt.isIfNotExists()) {
return;
}
throw new DdlException("Resource group " + resourceGroupNameName + " already exist");
throw new DdlException("Resource group " + resourceGroupName + " already exist");
}
idToResourceGroup.put(resourceGroup.getId(), resourceGroup);
Env.getCurrentEnv().getEditLog().logCreateResourceGroup(resourceGroup);
@ -151,10 +155,30 @@ public class ResourceGroupMgr implements Writable, GsonPostProcessable {
LOG.info("Create resource group success: {}", resourceGroup);
}
public void dropResourceGroup(DropResourceGroupStmt stmt) throws DdlException {
if (!Config.enable_resource_group) {
throw new DdlException("unsupported feature now, coming soon.");
public void alterResourceGroup(AlterResourceGroupStmt stmt) throws DdlException {
checkResourceGroupEnabled();
String resourceGroupName = stmt.getResourceGroupName();
Map<String, String> properties = stmt.getProperties();
ResourceGroup newResourceGroup;
writeLock();
try {
if (!nameToResourceGroup.containsKey(resourceGroupName)) {
throw new DdlException("Resource Group(" + resourceGroupName + ") does not exist.");
}
ResourceGroup resourceGroup = nameToResourceGroup.get(resourceGroupName);
newResourceGroup = ResourceGroup.create(resourceGroup, properties);
nameToResourceGroup.put(resourceGroupName, newResourceGroup);
idToResourceGroup.put(newResourceGroup.getId(), newResourceGroup);
Env.getCurrentEnv().getEditLog().logAlterResourceGroup(newResourceGroup);
} finally {
writeUnlock();
}
LOG.info("Alter resource success: {}", newResourceGroup);
}
public void dropResourceGroup(DropResourceGroupStmt stmt) throws DdlException {
checkResourceGroupEnabled();
String resourceGroupName = stmt.getResourceGroupName();
if (resourceGroupName == DEFAULT_GROUP_NAME) {
@ -180,7 +204,7 @@ public class ResourceGroupMgr implements Writable, GsonPostProcessable {
LOG.info("Drop resource group success: {}", resourceGroupName);
}
public void replayCreateResourceGroup(ResourceGroup resourceGroup) {
private void insertResourceGroup(ResourceGroup resourceGroup) {
writeLock();
try {
nameToResourceGroup.put(resourceGroup.getName(), resourceGroup);
@ -190,6 +214,14 @@ public class ResourceGroupMgr implements Writable, GsonPostProcessable {
}
}
public void replayCreateResourceGroup(ResourceGroup resourceGroup) {
insertResourceGroup(resourceGroup);
}
public void replayAlterResourceGroup(ResourceGroup resourceGroup) {
insertResourceGroup(resourceGroup);
}
public void replayDropResourceGroup(DropResourceGroupOperationLog operationLog) {
long id = operationLog.getId();
writeLock();