fix error where the ADLS directory cannot be deleted: prod bug (#420)

* fix error where the ADLS directory cannot be deleted: prod bug

* tabs to spaces
This commit is contained in:
Nara 2020-06-14 01:21:02 -07:00 коммит произвёл GitHub
Родитель 69ca26dec5
Коммит c07e502835
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
9 изменённых файлов: 160 добавлений и 30 удалений

Просмотреть файл

@ -106,6 +106,14 @@ namespace microsoft_azure { namespace storage {
/// <returns>A <see cref="std::future" /> object that represents the current operation.</returns>
AZURE_STORAGE_API std::future<storage_outcome<void>> upload_block_blob_from_stream(const std::string &container, const std::string &blob, std::istream &is, const std::vector<std::pair<std::string, std::string>> &metadata);
/// <summary>
/// Intitiates an asynchronous operation to delete a directory blob.
/// </summary>
/// <param name="container">The container name.</param>
/// <param name="blob">The directory blob name.</param>
/// <returns>A <see cref="std::future" /> object that represents the current operation.</returns>
AZURE_STORAGE_API std::future<storage_outcome<void>> delete_blobdir(const std::string &container, const std::string &blob);
/// <summary>
/// Intitiates an asynchronous operation to delete a blob.
/// </summary>
@ -366,6 +374,13 @@ namespace microsoft_azure { namespace storage {
/// <param name="blob">The blob name.</param>
virtual void delete_blob(const std::string &container, const std::string &blob) = 0;
/// <summary>
/// Deletes a directory blob.
/// </summary>
/// <param name="container">The container name.</param>
/// <param name="blob">The directory blob name.</param>
virtual void delete_blobdir(const std::string &container, const std::string &blob) = 0;
/// <summary>
/// Copy a blob to another.
/// </summary>
@ -543,6 +558,13 @@ namespace microsoft_azure { namespace storage {
/// <param name="blob">The blob name.</param>
void delete_blob(const std::string &container, const std::string &blob);
/// <summary>
/// Deletes a directory blob.
/// </summary>
/// <param name="container">The container name.</param>
/// <param name="blob">The directory blob name.</param>
void delete_blobdir(const std::string &container, const std::string &blob);
/// <summary>
/// Copy a blob to another.
/// </summary>
@ -834,6 +856,13 @@ namespace microsoft_azure { namespace storage {
/// <param name="blob">The blob name.</param>
void delete_blob(const std::string &container, const std::string &blob);
/// <summary>
/// Deletes a directory blob.
/// </summary>
/// <param name="container">The container name.</param>
/// <param name="blob">The directory blob name.</param>
void delete_blobdir(const std::string &container, const std::string &blob);
/// <summary>
/// Copy a blob to another.
/// </summary>

Просмотреть файл

@ -0,0 +1,32 @@
#pragma once
#include "delete_blob_request_base.h"
namespace microsoft_azure {
namespace storage {
class delete_blobdir_request final : public delete_blob_request_base {
public:
delete_blobdir_request(const std::string &container, const std::string &blob)
: m_container(container),
m_blob(blob) {}
std::string container() const override {
return m_container;
}
std::string blob() const override {
return m_blob;
}
delete_snapshots ms_delete_snapshots() const override {
return delete_snapshots::unspecified;
}
private:
std::string m_container;
std::string m_blob;
};
}
}

Просмотреть файл

@ -5,6 +5,7 @@
#include "blob/download_blob_request.h"
#include "blob/create_block_blob_request.h"
#include "blob/delete_blob_request.h"
#include "blob/delete_blobdir_request.h"
#include "blob/copy_blob_request.h"
#include "blob/create_container_request.h"
#include "blob/delete_container_request.h"
@ -118,6 +119,14 @@ std::future<storage_outcome<void>> blob_client::delete_blob(const std::string &c
return async_executor<void>::submit(m_account, request, http, m_context);
}
std::future<storage_outcome<void>> blob_client::delete_blobdir(const std::string &container, const std::string &blob) {
auto http = m_client->get_handle();
auto request = std::make_shared<delete_blobdir_request>(container, blob);
return async_executor<void>::submit(m_account, request, http, m_context);
}
std::future<storage_outcome<void>> blob_client::create_container(const std::string &container) {
auto http = m_client->get_handle();
@ -192,8 +201,8 @@ std::future<storage_outcome<list_containers_response>> blob_client::list_contain
auto request = std::make_shared<list_containers_request>(prefix, include_metadata);
request->set_maxresults(max_result);
request->set_marker(continuation_token);
request->set_marker(continuation_token);
return async_executor<list_containers_response>::submit(m_account, request, http, m_context);
}

Просмотреть файл

@ -336,6 +336,22 @@ namespace microsoft_azure {
cache_item->m_confirmed = false;
}
/// <summary>
/// Deletes a blob.
/// </summary>
/// <param name="container">The container name.</param>
/// <param name="blob">The blob name.</param>
void blob_client_attr_cache_wrapper::delete_blobdir(const std::string &container, const std::string &blob)
{
// These calls cannot be cached because we do not have a negative cache - blobs in the cache are either valid/confirmed, or unknown (which could be deleted, or not checked on the service.)
std::shared_ptr<boost::shared_mutex> dir_mutex = attr_cache.get_dir_item(get_parent_str(blob));
std::shared_ptr<blob_client_attr_cache_wrapper::blob_cache_item> cache_item = attr_cache.get_blob_item(blob);
boost::shared_lock<boost::shared_mutex> dirlock(*dir_mutex);
std::unique_lock<boost::shared_mutex> uniquelock(cache_item->m_mutex);
m_blob_client_wrapper->delete_blobdir(container, blob);
cache_item->m_confirmed = false;
}
/// <summary>
/// Copy a blob to another.
/// </summary>

Просмотреть файл

@ -833,7 +833,7 @@ namespace microsoft_azure {
errno = client_not_init;
return;
}
if(container.empty() || blob.empty())
if(container.empty() || blob.empty() )
{
errno = invalid_parameters;
return;
@ -862,6 +862,42 @@ namespace microsoft_azure {
}
}
void blob_client_wrapper::delete_blobdir(const std::string &container, const std::string &blob)
{
if(!is_valid())
{
errno = client_not_init;
return;
}
if(container.empty() || blob.empty() )
{
errno = invalid_parameters;
return;
}
try
{
auto task = m_blobClient->delete_blobdir(container, blob);
task.wait();
auto result = task.get();
if(!result.success())
{
errno = std::stoi(result.error().code);
}
else
{
errno = 0;
}
}
catch(std::exception& ex)
{
syslog(LOG_ERR, "Unknown failure in delete_blobdir. ex.what() = %s, container = %s, blob = %s.", ex.what(), container.c_str(), blob.c_str());
errno = unknown_error;
return;
}
}
void blob_client_wrapper::start_copy(const std::string &sourceContainer, const std::string &sourceBlob, const std::string &destContainer, const std::string &destBlob)
{

Просмотреть файл

@ -43,23 +43,23 @@ float kernel_version = 0.0;
void populate_kernel_version()
{
struct utsname buffer;
if (uname (&buffer) == 0) {
char *p = buffer.release;
int i = 0;
float ver[5];
if (uname (&buffer) == 0) {
char *p = buffer.release;
int i = 0;
float ver[5];
while (*p) {
if (isdigit(*p)) {
ver[i] = strtof(p, &p);
i++;
} else {
p++;
}
if (i >= 5) break;
}
if (i > 2)
while (*p) {
if (isdigit(*p)) {
ver[i] = strtof(p, &p);
i++;
} else {
p++;
}
if (i >= 5) break;
}
if (i > 2)
kernel_version = ver[0];
}
}
}
#define OPTION(t, p) { t, offsetof(struct options, p), 1 }

Просмотреть файл

@ -168,7 +168,7 @@ int azs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t, stru
{
// Avoid duplicate directories - this avoids duplicate entries of legacy WASB and HNS directories
local_list_results.push_back(prev_token_str);
local_list_results.push_back(prev_token_str);
struct stat stbuf;
stbuf.st_mode = S_IFDIR | default_permission;
@ -222,17 +222,25 @@ int azs_rmdir(const char *path)
return -ENOTEMPTY;
}
// TODO: change this to just delete blobs.
errno = 0;
// delete the actual directory path if it exists
azure_blob_client_wrapper->delete_blobdir(str_options.containerName, pathString.substr(1));
int dir_blob_deletedir_errno = errno;
if (dir_blob_deletedir_errno == 0)
{
syslog(LOG_INFO, "Successfully deleted directory %s. ", path);
}
// now delete the directory marker
azure_blob_client_wrapper->delete_blob(str_options.containerName, pathString.substr(1));
int dir_blob_delete_errno = errno;
if (dir_blob_delete_errno == 0)
{
syslog(LOG_INFO, "Successfully deleted directory marker %s for path %s. ", pathString.c_str()+1, path);
syslog(LOG_INFO, "Successfully deleted zero-length directory marker %s for path %s. ", pathString.c_str()+1, path);
}
else
// the below code is old and may not be needed any more.
if (dir_blob_deletedir_errno != 0 && dir_blob_delete_errno != 0)
{
AZS_DEBUGLOGV("Failed to delete directory marker %s at path %s, errno = %d. Checking the .directory version.\n", mntPath, pathString.c_str()+1, dir_blob_delete_errno);
AZS_DEBUGLOGV("Failed to delete directory marker %s at path %s and the directory, errno = %d. Checking the .directory version.\n", mntPath, pathString.c_str()+1, dir_blob_delete_errno);
pathString.append("/.directory");
@ -244,12 +252,10 @@ int azs_rmdir(const char *path)
{
syslog(LOG_INFO, "Successfully deleted .directory-style directory marker for path %s to blob %s. ", path, pathString.c_str()+1);
}
else
{
// If they both fail, dir_blob_delete_errno will be the important one in 99.99% of cases
syslog(LOG_ERR, "Failed I/O operation to delete directory %s. errno = %d\n", path, dir_blob_delete_errno);
return 0 - map_errno(dir_blob_delete_errno);
}
// If they both fail, dir_blob_delete_errno will be the important one in 99.99% of cases
syslog(LOG_ERR, "Failed I/O operation to delete zero-length directory marker %s. errno = %d\n", path, dir_blob_delete_errno);
syslog(LOG_ERR, "Failed I/O operation to delete directory %s. errno = %d\n", path, dir_blob_deletedir_errno);
return 0 - map_errno(dir_blob_delete_errno);
}
return 0;

Просмотреть файл

@ -17,7 +17,8 @@ public:
MOCK_METHOD5(download_blob_to_file, void(const std::string &container, const std::string &blob, const std::string &destPath, time_t &returned_last_modified, size_t parallel));
MOCK_METHOD2(get_blob_property, blob_property(const std::string &container, const std::string &blob));
MOCK_METHOD2(blob_exists, bool(const std::string &container, const std::string &blob));
MOCK_METHOD2(delete_blob, void(const std::string &container, const std::string &blob));
MOCK_METHOD2(delete_blob, void(const std::string &container, const std::string &blob));
MOCK_METHOD2(delete_blobdir, void(const std::string &container, const std::string &blob));
MOCK_METHOD4(start_copy, void(const std::string &sourceContainer, const std::string &sourceBlob, const std::string &destContainer, const std::string &destBlob));
};

Просмотреть файл

@ -19,6 +19,7 @@ public:
MOCK_METHOD2(get_blob_property, blob_property(const std::string &container, const std::string &blob));
MOCK_METHOD2(blob_exists, bool(const std::string &container, const std::string &blob));
MOCK_METHOD2(delete_blob, void(const std::string &container, const std::string &blob));
MOCK_METHOD2(delete_blobdir, void(const std::string &container, const std::string &blob));
MOCK_METHOD4(start_copy, void(const std::string &sourceContainer, const std::string &sourceBlob, const std::string &destContainer, const std::string &destBlob));
};