[Feature](resource-group) Support alter resource group (#18990)
This commit is contained in:
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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()));
|
||||
|
||||
@ -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();
|
||||
|
||||
Reference in New Issue
Block a user