HDDS-1730. Implement File CreateDirectory Request to use Cache and Do… (#1026)

This commit is contained in:
Bharat Viswanadham 2019-06-30 22:38:53 -07:00 committed by GitHub
parent d203045c30
commit 1e727cf2a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 914 additions and 2 deletions

View File

@ -100,6 +100,17 @@ public interface OMMetadataManager {
String getOzoneKey(String volume, String bucket, String key); String getOzoneKey(String volume, String bucket, String key);
/**
* Given a volume, bucket and a key, return the corresponding DB directory
* key.
*
* @param volume - volume name
* @param bucket - bucket name
* @param key - key name
* @return DB directory key as String.
*/
String getOzoneDirKey(String volume, String bucket, String key);
/** /**
* Returns the DB key name of a open key in OM metadata store. Should be * Returns the DB key name of a open key in OM metadata store. Should be

View File

@ -46,6 +46,7 @@ import org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfoGroup;
import org.apache.hadoop.ozone.om.helpers.OmMultipartKeyInfo; import org.apache.hadoop.ozone.om.helpers.OmMultipartKeyInfo;
import org.apache.hadoop.ozone.om.helpers.OmPrefixInfo; import org.apache.hadoop.ozone.om.helpers.OmPrefixInfo;
import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs; import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs;
import org.apache.hadoop.ozone.om.helpers.OzoneFSUtils;
import org.apache.hadoop.ozone.om.helpers.S3SecretValue; import org.apache.hadoop.ozone.om.helpers.S3SecretValue;
import org.apache.hadoop.ozone.om.lock.OzoneManagerLock; import org.apache.hadoop.ozone.om.lock.OzoneManagerLock;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.VolumeList; import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.VolumeList;
@ -381,6 +382,12 @@ public class OmMetadataManagerImpl implements OMMetadataManager {
return builder.toString(); return builder.toString();
} }
@Override
public String getOzoneDirKey(String volume, String bucket, String key) {
key = OzoneFSUtils.addTrailingSlashIfNeeded(key);
return getOzoneKey(volume, bucket, key);
}
@Override @Override
public String getOpenKey(String volume, String bucket, public String getOpenKey(String volume, String bucket,
String key, long id) { String key, long id) {

View File

@ -23,6 +23,7 @@ import org.apache.hadoop.ozone.om.request.bucket.OMBucketCreateRequest;
import org.apache.hadoop.ozone.om.request.bucket.OMBucketDeleteRequest; import org.apache.hadoop.ozone.om.request.bucket.OMBucketDeleteRequest;
import org.apache.hadoop.ozone.om.request.bucket.OMBucketSetPropertyRequest; import org.apache.hadoop.ozone.om.request.bucket.OMBucketSetPropertyRequest;
import org.apache.hadoop.ozone.om.request.OMClientRequest; import org.apache.hadoop.ozone.om.request.OMClientRequest;
import org.apache.hadoop.ozone.om.request.file.OMDirectoryCreateRequest;
import org.apache.hadoop.ozone.om.request.key.OMAllocateBlockRequest; import org.apache.hadoop.ozone.om.request.key.OMAllocateBlockRequest;
import org.apache.hadoop.ozone.om.request.key.OMKeyCommitRequest; import org.apache.hadoop.ozone.om.request.key.OMKeyCommitRequest;
import org.apache.hadoop.ozone.om.request.key.OMKeyCreateRequest; import org.apache.hadoop.ozone.om.request.key.OMKeyCreateRequest;
@ -90,6 +91,8 @@ public final class OzoneManagerRatisUtils {
return new OMKeyDeleteRequest(omRequest); return new OMKeyDeleteRequest(omRequest);
case RenameKey: case RenameKey:
return new OMKeyRenameRequest(omRequest); return new OMKeyRenameRequest(omRequest);
case CreateDirectory:
return new OMDirectoryCreateRequest(omRequest);
default: default:
// TODO: will update once all request types are implemented. // TODO: will update once all request types are implemented.
return null; return null;

View File

@ -0,0 +1,282 @@
/**
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.hadoop.ozone.om.request.file;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.hadoop.fs.FileEncryptionInfo;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
import org.apache.hadoop.ozone.audit.AuditLogger;
import org.apache.hadoop.ozone.audit.OMAction;
import org.apache.hadoop.ozone.om.OMMetadataManager;
import org.apache.hadoop.ozone.om.OMMetrics;
import org.apache.hadoop.ozone.om.OzoneManager;
import org.apache.hadoop.ozone.om.exceptions.OMException;
import org.apache.hadoop.ozone.om.helpers.OmBucketInfo;
import org.apache.hadoop.ozone.om.helpers.OmKeyInfo;
import org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfoGroup;
import org.apache.hadoop.ozone.om.helpers.OzoneFSUtils;
import org.apache.hadoop.ozone.om.request.OMClientRequest;
import org.apache.hadoop.ozone.om.request.key.OMKeyRequest;
import org.apache.hadoop.ozone.om.response.OMClientResponse;
import org.apache.hadoop.ozone.om.response.file.OMDirectoryCreateResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.CreateDirectoryRequest;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.CreateDirectoryResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.KeyArgs;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.OMRequest;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.OMResponse;
import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer;
import org.apache.hadoop.ozone.security.acl.OzoneObj;
import org.apache.hadoop.util.Time;
import org.apache.hadoop.utils.db.cache.CacheKey;
import org.apache.hadoop.utils.db.cache.CacheValue;
import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.BUCKET_NOT_FOUND;
import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.FILE_ALREADY_EXISTS;
import static org.apache.hadoop.ozone.om.lock.OzoneManagerLock.Resource.BUCKET_LOCK;
/**
* Handle create directory request.
*/
public class OMDirectoryCreateRequest extends OMClientRequest
implements OMKeyRequest {
private static final Logger LOG =
LoggerFactory.getLogger(OMDirectoryCreateRequest.class);
public OMDirectoryCreateRequest(OMRequest omRequest) {
super(omRequest);
}
@Override
public OMRequest preExecute(OzoneManager ozoneManager) {
CreateDirectoryRequest createDirectoryRequest =
getOmRequest().getCreateDirectoryRequest();
Preconditions.checkNotNull(createDirectoryRequest);
KeyArgs.Builder newKeyArgs = createDirectoryRequest.getKeyArgs()
.toBuilder().setModificationTime(Time.now());
CreateDirectoryRequest.Builder newCreateDirectoryRequest =
createDirectoryRequest.toBuilder().setKeyArgs(newKeyArgs);
return getOmRequest().toBuilder().setCreateDirectoryRequest(
newCreateDirectoryRequest).build();
}
@Override
public OMClientResponse validateAndUpdateCache(OzoneManager ozoneManager,
long transactionLogIndex) {
KeyArgs keyArgs = getOmRequest().getCreateDirectoryRequest().getKeyArgs();
String volumeName = keyArgs.getVolumeName();
String bucketName = keyArgs.getBucketName();
String keyName = keyArgs.getKeyName();
OMResponse.Builder omResponse =
OzoneManagerProtocolProtos.OMResponse.newBuilder().setCmdType(
OzoneManagerProtocolProtos.Type.CreateDirectory).setStatus(
OzoneManagerProtocolProtos.Status.OK);
OMMetrics omMetrics = ozoneManager.getMetrics();
omMetrics.incNumCreateDirectory();
AuditLogger auditLogger = ozoneManager.getAuditLogger();
OzoneManagerProtocolProtos.UserInfo userInfo = getOmRequest().getUserInfo();
Map<String, String> auditMap = buildKeyArgsAuditMap(keyArgs);
OMMetadataManager omMetadataManager = ozoneManager.getMetadataManager();
boolean acquiredLock = false;
IOException exception = null;
OmKeyInfo dirKeyInfo = null;
try {
// check Acl
if (ozoneManager.getAclsEnabled()) {
checkAcls(ozoneManager, OzoneObj.ResourceType.BUCKET,
OzoneObj.StoreType.OZONE, IAccessAuthorizer.ACLType.WRITE,
volumeName, bucketName, keyName);
}
// Check if this is the root of the filesystem.
if (keyName.length() == 0) {
return new OMDirectoryCreateResponse(null,
omResponse.setCreateDirectoryResponse(
CreateDirectoryResponse.newBuilder()).build());
}
// acquire lock
acquiredLock = omMetadataManager.getLock().acquireLock(BUCKET_LOCK,
volumeName, bucketName);
// TODO: Not checking volume exist here, once we have full cache we can
// add volume exist check also.
OmBucketInfo omBucketInfo = omMetadataManager.getBucketTable().get(
omMetadataManager.getBucketKey(volumeName, bucketName));
if (omBucketInfo == null) {
throw new OMException("Bucket not found " + bucketName,
BUCKET_NOT_FOUND);
}
// Need to check if any files exist in the given path, if they exist we
// cannot create a directory with the given key.
OMDirectoryResult omDirectoryResult = verifyFilesInPath(omMetadataManager,
volumeName, bucketName, omMetadataManager.getOzoneDirKey(volumeName,
bucketName, keyName), Paths.get(keyName));
if (omDirectoryResult == OMDirectoryResult.FILE_ALREADY_EXISTS) {
throw new OMException("Unable to create directory: " +keyName
+ " in volume/bucket: " + volumeName + "/" + bucketName,
FILE_ALREADY_EXISTS);
} else if (omDirectoryResult == OMDirectoryResult.SUB_DIRECTORY_EXISTS ||
omDirectoryResult == OMDirectoryResult.NONE) {
dirKeyInfo = createDirectoryKeyInfo(ozoneManager, omBucketInfo,
volumeName, bucketName, keyName, keyArgs);
omMetadataManager.getKeyTable().addCacheEntry(
new CacheKey<>(omMetadataManager.getOzoneKey(volumeName, bucketName,
dirKeyInfo.getKeyName())),
new CacheValue<>(Optional.of(dirKeyInfo), transactionLogIndex));
}
// if directory already exists do nothing or do we need to throw
// exception? Current KeyManagerImpl code does just return, following
// similar approach.
} catch (IOException ex) {
exception = ex;
} finally {
if (acquiredLock) {
omMetadataManager.getLock().releaseLock(BUCKET_LOCK, volumeName,
bucketName);
}
}
auditLog(auditLogger, buildAuditMessage(OMAction.CREATE_DIRECTORY,
auditMap, exception, userInfo));
if (exception == null) {
LOG.debug("Directory is successfully created for Key: {} in " +
"volume/bucket:{}/{}", keyName, volumeName, bucketName);
omResponse.setCreateDirectoryResponse(
CreateDirectoryResponse.newBuilder());
return new OMDirectoryCreateResponse(dirKeyInfo,
omResponse.build());
} else {
LOG.error("CreateDirectory failed for Key: {} in volume/bucket:{}/{}",
keyName, volumeName, bucketName, exception);
omMetrics.incNumCreateDirectoryFails();
return new OMDirectoryCreateResponse(null,
createErrorOMResponse(omResponse, exception));
}
}
/**
* Verify any files exist in the given path in the specified volume/bucket.
* @param omMetadataManager
* @param volumeName
* @param bucketName
* @param keyPath
* @return true - if file exist in the given path, else false.
* @throws IOException
*/
private OMDirectoryResult verifyFilesInPath(
OMMetadataManager omMetadataManager, String volumeName, String bucketName,
String directoryName, Path keyPath) throws IOException {
while (keyPath != null) {
String keyName = keyPath.toString();
String dbKeyName = omMetadataManager.getOzoneKey(volumeName,
bucketName, keyName);
String dbDirKeyName = omMetadataManager.getOzoneDirKey(volumeName,
bucketName, keyName);
if (omMetadataManager.getKeyTable().get(dbKeyName) != null) {
// Found a file in the given path.
return OMDirectoryResult.FILE_ALREADY_EXISTS;
} else if (omMetadataManager.getKeyTable().get(dbDirKeyName) != null) {
if (dbDirKeyName.equals(directoryName)) {
return OMDirectoryResult.DIRECTORY_ALREADY_EXISTS;
} else {
return OMDirectoryResult.SUB_DIRECTORY_EXISTS;
}
}
keyPath = keyPath.getParent();
}
// Found no files/ directories in the given path.
return OMDirectoryResult.NONE;
}
private OmKeyInfo createDirectoryKeyInfo(OzoneManager ozoneManager,
OmBucketInfo omBucketInfo, String volumeName, String bucketName,
String keyName, KeyArgs keyArgs)
throws IOException {
FileEncryptionInfo encryptionInfo = getFileEncryptionInfo(ozoneManager,
omBucketInfo);
String dirName = OzoneFSUtils.addTrailingSlashIfNeeded(keyName);
return new OmKeyInfo.Builder()
.setVolumeName(volumeName)
.setBucketName(bucketName)
.setKeyName(dirName)
.setOmKeyLocationInfos(Collections.singletonList(
new OmKeyLocationInfoGroup(0, new ArrayList<>())))
.setCreationTime(keyArgs.getModificationTime())
.setModificationTime(keyArgs.getModificationTime())
.setDataSize(0)
.setReplicationType(HddsProtos.ReplicationType.RATIS)
.setReplicationFactor(HddsProtos.ReplicationFactor.ONE)
.setFileEncryptionInfo(encryptionInfo)
.setAcls(keyArgs.getAclsList())
.build();
}
/**
* Return codes used by verifyFilesInPath method.
*/
enum OMDirectoryResult {
DIRECTORY_ALREADY_EXISTS,
FILE_ALREADY_EXISTS,
SUB_DIRECTORY_EXISTS,
NONE
}
}

View File

@ -0,0 +1,23 @@
/*
* 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 contains classes related to file requests.
*/
package org.apache.hadoop.ozone.om.request.file;

View File

@ -0,0 +1,67 @@
/**
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.hadoop.ozone.om.response.file;
import org.apache.hadoop.ozone.om.OMMetadataManager;
import org.apache.hadoop.ozone.om.helpers.OmKeyInfo;
import org.apache.hadoop.ozone.om.response.OMClientResponse;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.OMResponse;
import org.apache.hadoop.utils.db.BatchOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import java.io.IOException;
/**
* Response for create directory request.
*/
public class OMDirectoryCreateResponse extends OMClientResponse {
public static final Logger LOG =
LoggerFactory.getLogger(OMDirectoryCreateResponse.class);
private OmKeyInfo dirKeyInfo;
public OMDirectoryCreateResponse(@Nullable OmKeyInfo dirKeyInfo,
OMResponse omResponse) {
super(omResponse);
this.dirKeyInfo = dirKeyInfo;
}
@Override
public void addToDBBatch(OMMetadataManager omMetadataManager,
BatchOperation batchOperation) throws IOException {
if (getOMResponse().getStatus() == OzoneManagerProtocolProtos.Status.OK) {
if (dirKeyInfo != null) {
String dirKey =
omMetadataManager.getOzoneKey(dirKeyInfo.getVolumeName(),
dirKeyInfo.getBucketName(), dirKeyInfo.getKeyName());
omMetadataManager.getKeyTable().putWithBatch(batchOperation, dirKey,
dirKeyInfo);
} else {
// When directory already exists, we don't add it to cache. And it is
// not an error, in this case dirKeyInfo will be null.
LOG.debug("Response Status is OK, dirKeyInfo is null in " +
"OMDirectoryCreateResponse");
}
}
}
}

View File

@ -0,0 +1,23 @@
/*
* 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 contains classes related to file responses.
*/
package org.apache.hadoop.ozone.om.response.file;

View File

@ -108,6 +108,7 @@ public class OzoneManagerHARequestHandlerImpl
case CommitKey: case CommitKey:
case DeleteKey: case DeleteKey:
case RenameKey: case RenameKey:
case CreateDirectory:
//TODO: We don't need to pass transactionID, this will be removed when //TODO: We don't need to pass transactionID, this will be removed when
// complete write requests is changed to new model. And also we can // complete write requests is changed to new model. And also we can
// return OMClientResponse, then adding to doubleBuffer can be taken // return OMClientResponse, then adding to doubleBuffer can be taken

View File

@ -85,7 +85,6 @@ public class OzoneManagerProtocolServerSideTranslatorPB implements
if (OmUtils.isReadOnly(request)) { if (OmUtils.isReadOnly(request)) {
return submitReadRequestToOM(request); return submitReadRequestToOM(request);
} else { } else {
// PreExecute if needed.
if (omRatisServer.isLeader()) { if (omRatisServer.isLeader()) {
try { try {
OMClientRequest omClientRequest = OMClientRequest omClientRequest =
@ -93,7 +92,7 @@ public class OzoneManagerProtocolServerSideTranslatorPB implements
if (omClientRequest != null) { if (omClientRequest != null) {
request = omClientRequest.preExecute(ozoneManager); request = omClientRequest.preExecute(ozoneManager);
} }
} catch (IOException ex) { } catch(IOException ex) {
// As some of the preExecute returns error. So handle here. // As some of the preExecute returns error. So handle here.
return createErrorResponse(request, ex); return createErrorResponse(request, ex);
} }

View File

@ -0,0 +1,327 @@
/**
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.hadoop.ozone.om.request.file;
import java.util.UUID;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
import org.apache.hadoop.ozone.om.helpers.OzoneFSUtils;
import org.apache.hadoop.ozone.om.response.OMClientResponse;
import org.apache.hadoop.utils.db.cache.CacheKey;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.mockito.Mockito;
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.ozone.audit.AuditLogger;
import org.apache.hadoop.ozone.audit.AuditMessage;
import org.apache.hadoop.ozone.om.OMConfigKeys;
import org.apache.hadoop.ozone.om.OMMetadataManager;
import org.apache.hadoop.ozone.om.OMMetrics;
import org.apache.hadoop.ozone.om.OmMetadataManagerImpl;
import org.apache.hadoop.ozone.om.OzoneManager;
import org.apache.hadoop.ozone.om.request.TestOMRequestUtils;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.CreateDirectoryRequest;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.KeyArgs;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.OMRequest;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
/**
* Test OM directory create request.
*/
public class TestOMDirectoryCreateRequest {
@Rule
public TemporaryFolder folder = new TemporaryFolder();
private OzoneManager ozoneManager;
private OMMetrics omMetrics;
private OMMetadataManager omMetadataManager;
private AuditLogger auditLogger;
@Before
public void setup() throws Exception {
ozoneManager = Mockito.mock(OzoneManager.class);
omMetrics = OMMetrics.create();
OzoneConfiguration ozoneConfiguration = new OzoneConfiguration();
ozoneConfiguration.set(OMConfigKeys.OZONE_OM_DB_DIRS,
folder.newFolder().getAbsolutePath());
omMetadataManager = new OmMetadataManagerImpl(ozoneConfiguration);
when(ozoneManager.getMetrics()).thenReturn(omMetrics);
when(ozoneManager.getMetadataManager()).thenReturn(omMetadataManager);
auditLogger = Mockito.mock(AuditLogger.class);
when(ozoneManager.getAuditLogger()).thenReturn(auditLogger);
Mockito.doNothing().when(auditLogger).logWrite(any(AuditMessage.class));
}
@After
public void stop() {
omMetrics.unRegister();
Mockito.framework().clearInlineMocks();
}
@Test
public void testPreExecute() throws Exception {
String volumeName = "vol1";
String bucketName = "bucket1";
String keyName = "a/b/c";
TestOMRequestUtils.addVolumeAndBucketToDB(volumeName, bucketName,
omMetadataManager);
OMRequest omRequest = createDirectoryRequest(volumeName, bucketName,
keyName);
OMDirectoryCreateRequest omDirectoryCreateRequest =
new OMDirectoryCreateRequest(omRequest);
OMRequest modifiedOmRequest =
omDirectoryCreateRequest.preExecute(ozoneManager);
// As in preExecute, we modify original request.
Assert.assertNotEquals(omRequest, modifiedOmRequest);
}
@Test
public void testValidateAndUpdateCache() throws Exception {
String volumeName = "vol1";
String bucketName = "bucket1";
String keyName = RandomStringUtils.randomAlphabetic(5);
for (int i =0; i< 3; i++) {
keyName += "/" + RandomStringUtils.randomAlphabetic(5);
}
// Add volume and bucket entries to DB.
TestOMRequestUtils.addVolumeAndBucketToDB(volumeName, bucketName,
omMetadataManager);
OMRequest omRequest = createDirectoryRequest(volumeName, bucketName,
keyName);
OMDirectoryCreateRequest omDirectoryCreateRequest =
new OMDirectoryCreateRequest(omRequest);
OMRequest modifiedOmRequest =
omDirectoryCreateRequest.preExecute(ozoneManager);
omDirectoryCreateRequest = new OMDirectoryCreateRequest(modifiedOmRequest);
OMClientResponse omClientResponse =
omDirectoryCreateRequest.validateAndUpdateCache(ozoneManager, 100L);
Assert.assertTrue(omClientResponse.getOMResponse().getStatus()
== OzoneManagerProtocolProtos.Status.OK);
Assert.assertTrue(omMetadataManager.getKeyTable().get(
omMetadataManager.getOzoneDirKey(
volumeName, bucketName, keyName)) != null);
}
@Test
public void testValidateAndUpdateCacheWithBucketNotFound() throws Exception {
String volumeName = "vol1";
String bucketName = "bucket1";
String keyName = RandomStringUtils.randomAlphabetic(5);
for (int i =0; i< 3; i++) {
keyName += "/" + RandomStringUtils.randomAlphabetic(5);
}
OMRequest omRequest = createDirectoryRequest(volumeName, bucketName,
keyName);
OMDirectoryCreateRequest omDirectoryCreateRequest =
new OMDirectoryCreateRequest(omRequest);
OMRequest modifiedOmRequest =
omDirectoryCreateRequest.preExecute(ozoneManager);
omDirectoryCreateRequest = new OMDirectoryCreateRequest(modifiedOmRequest);
OMClientResponse omClientResponse =
omDirectoryCreateRequest.validateAndUpdateCache(ozoneManager, 100L);
Assert.assertTrue(omClientResponse.getOMResponse().getStatus()
== OzoneManagerProtocolProtos.Status.BUCKET_NOT_FOUND);
// Key should not exist in DB
Assert.assertTrue(omMetadataManager.getKeyTable().get(
omMetadataManager.getOzoneDirKey(
volumeName, bucketName, keyName)) == null);
}
@Test
public void testValidateAndUpdateCacheWithSubDirectoryInPath()
throws Exception {
String volumeName = "vol1";
String bucketName = "bucket1";
String keyName = RandomStringUtils.randomAlphabetic(5);
for (int i =0; i< 3; i++) {
keyName += "/" + RandomStringUtils.randomAlphabetic(5);
}
// Add volume and bucket entries to DB.
TestOMRequestUtils.addVolumeAndBucketToDB(volumeName, bucketName,
omMetadataManager);
TestOMRequestUtils.addKeyToTable(false, volumeName, bucketName,
keyName.substring(0, 12), 1L, HddsProtos.ReplicationType.RATIS,
HddsProtos.ReplicationFactor.ONE, omMetadataManager);
OMRequest omRequest = createDirectoryRequest(volumeName, bucketName,
keyName);
OMDirectoryCreateRequest omDirectoryCreateRequest =
new OMDirectoryCreateRequest(omRequest);
OMRequest modifiedOmRequest =
omDirectoryCreateRequest.preExecute(ozoneManager);
omDirectoryCreateRequest = new OMDirectoryCreateRequest(modifiedOmRequest);
OMClientResponse omClientResponse =
omDirectoryCreateRequest.validateAndUpdateCache(ozoneManager, 100L);
Assert.assertTrue(omClientResponse.getOMResponse().getStatus()
== OzoneManagerProtocolProtos.Status.OK);
// Key should exist in DB and cache.
Assert.assertTrue(omMetadataManager.getKeyTable().get(
omMetadataManager.getOzoneDirKey(
volumeName, bucketName, keyName)) != null);
Assert.assertTrue(omMetadataManager.getKeyTable().getCacheValue(
new CacheKey<>(omMetadataManager.getOzoneDirKey(
volumeName, bucketName, keyName))) != null);
}
@Test
public void testValidateAndUpdateCacheWithDirectoryAlreadyExists()
throws Exception {
String volumeName = "vol1";
String bucketName = "bucket1";
String keyName = RandomStringUtils.randomAlphabetic(5);
for (int i =0; i< 3; i++) {
keyName += "/" + RandomStringUtils.randomAlphabetic(5);
}
// Add volume and bucket entries to DB.
TestOMRequestUtils.addVolumeAndBucketToDB(volumeName, bucketName,
omMetadataManager);
TestOMRequestUtils.addKeyToTable(false, volumeName, bucketName,
OzoneFSUtils.addTrailingSlashIfNeeded(keyName), 1L,
HddsProtos.ReplicationType.RATIS, HddsProtos.ReplicationFactor.ONE,
omMetadataManager);
OMRequest omRequest = createDirectoryRequest(volumeName, bucketName,
keyName);
OMDirectoryCreateRequest omDirectoryCreateRequest =
new OMDirectoryCreateRequest(omRequest);
OMRequest modifiedOmRequest =
omDirectoryCreateRequest.preExecute(ozoneManager);
omDirectoryCreateRequest = new OMDirectoryCreateRequest(modifiedOmRequest);
OMClientResponse omClientResponse =
omDirectoryCreateRequest.validateAndUpdateCache(ozoneManager, 100L);
Assert.assertTrue(omClientResponse.getOMResponse().getStatus()
== OzoneManagerProtocolProtos.Status.OK);
// Key should exist in DB
Assert.assertTrue(omMetadataManager.getKeyTable().get(
omMetadataManager.getOzoneDirKey(
volumeName, bucketName, keyName)) != null);
// As it already exists, it should not be in cache.
Assert.assertTrue(omMetadataManager.getKeyTable().getCacheValue(
new CacheKey<>(omMetadataManager.getOzoneDirKey(
volumeName, bucketName, keyName))) == null);
}
@Test
public void testValidateAndUpdateCacheWithFilesInPath() throws Exception {
String volumeName = "vol1";
String bucketName = "bucket1";
String keyName = RandomStringUtils.randomAlphabetic(5);
for (int i =0; i< 3; i++) {
keyName += "/" + RandomStringUtils.randomAlphabetic(5);
}
// Add volume and bucket entries to DB.
TestOMRequestUtils.addVolumeAndBucketToDB(volumeName, bucketName,
omMetadataManager);
// Add a key with first two levels.
TestOMRequestUtils.addKeyToTable(false, volumeName, bucketName,
keyName.substring(0, 11), 1L, HddsProtos.ReplicationType.RATIS,
HddsProtos.ReplicationFactor.ONE, omMetadataManager);
OMRequest omRequest = createDirectoryRequest(volumeName, bucketName,
keyName);
OMDirectoryCreateRequest omDirectoryCreateRequest =
new OMDirectoryCreateRequest(omRequest);
OMRequest modifiedOmRequest =
omDirectoryCreateRequest.preExecute(ozoneManager);
omDirectoryCreateRequest = new OMDirectoryCreateRequest(modifiedOmRequest);
OMClientResponse omClientResponse =
omDirectoryCreateRequest.validateAndUpdateCache(ozoneManager, 100L);
Assert.assertTrue(omClientResponse.getOMResponse().getStatus()
== OzoneManagerProtocolProtos.Status.FILE_ALREADY_EXISTS);
// Key should not exist in DB
Assert.assertTrue(omMetadataManager.getKeyTable().get(
omMetadataManager.getOzoneDirKey(
volumeName, bucketName, keyName)) == null);
}
/**
* Create OMRequest which encapsulates CreateDirectory request.
* @param volumeName
* @param bucketName
* @param keyName
* @return OMRequest
*/
private OMRequest createDirectoryRequest(String volumeName, String bucketName,
String keyName) {
return OMRequest.newBuilder().setCreateDirectoryRequest(
CreateDirectoryRequest.newBuilder().setKeyArgs(
KeyArgs.newBuilder().setVolumeName(volumeName)
.setBucketName(bucketName).setKeyName(keyName)))
.setCmdType(OzoneManagerProtocolProtos.Type.CreateDirectory)
.setClientId(UUID.randomUUID().toString()).build();
}
}

View File

@ -0,0 +1,23 @@
/*
* 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 contains test classes for file requests.
*/
package org.apache.hadoop.ozone.om.request.file;

View File

@ -0,0 +1,123 @@
/**
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.hadoop.ozone.om.response.file;
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
import org.apache.hadoop.ozone.om.OMConfigKeys;
import org.apache.hadoop.ozone.om.OMMetadataManager;
import org.apache.hadoop.ozone.om.OmMetadataManagerImpl;
import org.apache.hadoop.ozone.om.helpers.OmKeyInfo;
import org.apache.hadoop.ozone.om.helpers.OzoneFSUtils;
import org.apache.hadoop.ozone.om.request.TestOMRequestUtils;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos
.OMResponse;
import org.apache.hadoop.test.GenericTestUtils;
import org.apache.hadoop.utils.db.BatchOperation;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.slf4j.event.Level;
import java.util.UUID;
/**
* Tests OMDirectoryCreateResponse.
*/
public class TestOMDirectoryCreateResponse {
@Rule
public TemporaryFolder folder = new TemporaryFolder();
private OMMetadataManager omMetadataManager;
private BatchOperation batchOperation;
@Before
public void setup() throws Exception {
OzoneConfiguration ozoneConfiguration = new OzoneConfiguration();
ozoneConfiguration.set(OMConfigKeys.OZONE_OM_DB_DIRS,
folder.newFolder().getAbsolutePath());
omMetadataManager = new OmMetadataManagerImpl(ozoneConfiguration);
batchOperation = omMetadataManager.getStore().initBatchOperation();
}
@Test
public void testAddToDBBatch() throws Exception {
String volumeName = UUID.randomUUID().toString();
String keyName = UUID.randomUUID().toString();
String bucketName = UUID.randomUUID().toString();
OmKeyInfo omKeyInfo = TestOMRequestUtils.createOmKeyInfo(volumeName,
bucketName, OzoneFSUtils.addTrailingSlashIfNeeded(keyName),
HddsProtos.ReplicationType.RATIS, HddsProtos.ReplicationFactor.ONE);
OMResponse omResponse = OMResponse.newBuilder().setCreateDirectoryResponse(
OzoneManagerProtocolProtos.CreateDirectoryResponse.getDefaultInstance())
.setStatus(OzoneManagerProtocolProtos.Status.OK)
.setCmdType(OzoneManagerProtocolProtos.Type.CreateDirectory)
.build();
OMDirectoryCreateResponse omDirectoryCreateResponse =
new OMDirectoryCreateResponse(omKeyInfo, omResponse);
omDirectoryCreateResponse.addToDBBatch(omMetadataManager, batchOperation);
// Do manual commit and see whether addToBatch is successful or not.
omMetadataManager.getStore().commitBatchOperation(batchOperation);
Assert.assertNotNull(omMetadataManager.getKeyTable().get(
omMetadataManager.getOzoneDirKey(volumeName, bucketName, keyName)));
}
@Test
public void testAddToDBBatchWithNullOmkeyInfo() throws Exception {
GenericTestUtils.setLogLevel(OMDirectoryCreateResponse.LOG, Level.DEBUG);
GenericTestUtils.LogCapturer logCapturer = GenericTestUtils.LogCapturer
.captureLogs(OMDirectoryCreateResponse.LOG);
String volumeName = UUID.randomUUID().toString();
String keyName = UUID.randomUUID().toString();
String bucketName = UUID.randomUUID().toString();
OMResponse omResponse = OMResponse.newBuilder().setCreateDirectoryResponse(
OzoneManagerProtocolProtos.CreateDirectoryResponse.getDefaultInstance())
.setStatus(OzoneManagerProtocolProtos.Status.OK)
.setCmdType(OzoneManagerProtocolProtos.Type.CreateDirectory)
.build();
OMDirectoryCreateResponse omDirectoryCreateResponse =
new OMDirectoryCreateResponse(null, omResponse);
omDirectoryCreateResponse.addToDBBatch(omMetadataManager, batchOperation);
// Do manual commit and see whether addToBatch is successful or not.
omMetadataManager.getStore().commitBatchOperation(batchOperation);
Assert.assertNull(omMetadataManager.getKeyTable().get(
omMetadataManager.getOzoneDirKey(volumeName, bucketName, keyName)));
Assert.assertTrue(logCapturer.getOutput().contains("Response Status is " +
"OK, dirKeyInfo is null"));
}
}

View File

@ -0,0 +1,23 @@
/*
* 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 contains test classes for file responses.
*/
package org.apache.hadoop.ozone.om.response.file;