Store mvnode in vector instead of manual linked list (#2312)

This simplifies code and avoids manual memory management.  References #2261.
This commit is contained in:
Andrew Gaul 2023-09-13 22:32:15 +09:00 committed by GitHub
parent f493cb5846
commit 01189e99fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 34 additions and 218 deletions

View File

@ -35,7 +35,6 @@ s3fs_SOURCES = \
s3fs_xml.cpp \
metaheader.cpp \
mpu_util.cpp \
mvnode.cpp \
curl.cpp \
curl_handlerpool.cpp \
curl_multi.cpp \

View File

@ -1,139 +0,0 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Takeshi Nakatani <ggtakec.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "s3fs.h"
#include "mvnode.h"
//-------------------------------------------------------------------
// Utility functions for moving objects
//-------------------------------------------------------------------
MVNODE *create_mvnode(const char *old_path, const char *new_path, bool is_dir, bool normdir)
{
MVNODE *p;
char *p_old_path;
char *p_new_path;
if(nullptr == (p_old_path = strdup(old_path))){
printf("create_mvnode: could not allocation memory for p_old_path\n");
S3FS_FUSE_EXIT();
return nullptr;
}
if(nullptr == (p_new_path = strdup(new_path))){
free(p_old_path);
printf("create_mvnode: could not allocation memory for p_new_path\n");
S3FS_FUSE_EXIT();
return nullptr;
}
p = new MVNODE();
p->old_path = p_old_path;
p->new_path = p_new_path;
p->is_dir = is_dir;
p->is_normdir = normdir;
p->prev = nullptr;
p->next = nullptr;
return p;
}
//
// Add sorted MVNODE data(Ascending order)
//
MVNODE *add_mvnode(MVNODE** head, MVNODE** tail, const char *old_path, const char *new_path, bool is_dir, bool normdir)
{
if(!head || !tail){
return nullptr;
}
MVNODE* cur;
MVNODE* mvnew;
for(cur = *head; cur; cur = cur->next){
if(cur->is_dir == is_dir){
int nResult = strcmp(cur->old_path, old_path);
if(0 == nResult){
// Found same old_path.
return cur;
}else if(0 > nResult){
// next check.
// ex: cur("abc"), mvnew("abcd")
// ex: cur("abc"), mvnew("abd")
continue;
}else{
// Add into before cur-pos.
// ex: cur("abc"), mvnew("ab")
// ex: cur("abc"), mvnew("abb")
if(nullptr == (mvnew = create_mvnode(old_path, new_path, is_dir, normdir))){
return nullptr;
}
if(cur->prev){
(cur->prev)->next = mvnew;
}else{
*head = mvnew;
}
mvnew->prev = cur->prev;
mvnew->next = cur;
cur->prev = mvnew;
return mvnew;
}
}
}
// Add into tail.
if(nullptr == (mvnew = create_mvnode(old_path, new_path, is_dir, normdir))){
return nullptr;
}
mvnew->prev = (*tail);
if(*tail){
(*tail)->next = mvnew;
}
(*tail) = mvnew;
if(!(*head)){
(*head) = mvnew;
}
return mvnew;
}
void free_mvnodes(MVNODE *head)
{
MVNODE *my_head;
MVNODE *next;
for(my_head = head, next = nullptr; my_head; my_head = next){
next = my_head->next;
free(my_head->old_path);
free(my_head->new_path);
delete my_head;
}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: expandtab sw=4 ts=4 fdm=marker
* vim<600: expandtab sw=4 ts=4
*/

View File

@ -1,53 +0,0 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef S3FS_MVNODE_H_
#define S3FS_MVNODE_H_
//-------------------------------------------------------------------
// Structure
//-------------------------------------------------------------------
typedef struct mvnode
{
char* old_path;
char* new_path;
bool is_dir;
bool is_normdir;
struct mvnode* prev;
struct mvnode* next;
} MVNODE;
//-------------------------------------------------------------------
// Utility functions for moving objects
//-------------------------------------------------------------------
MVNODE *create_mvnode(const char *old_path, const char *new_path, bool is_dir, bool normdir = false);
MVNODE *add_mvnode(MVNODE** head, MVNODE** tail, const char *old_path, const char *new_path, bool is_dir, bool normdir = false);
void free_mvnodes(MVNODE *head);
#endif // S3FS_MVNODE_H_
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: expandtab sw=4 ts=4 fdm=marker
* vim<600: expandtab sw=4 ts=4
*/

View File

@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <errno.h>
@ -39,7 +40,6 @@
#include "curl_multi.h"
#include "s3objlist.h"
#include "cache.h"
#include "mvnode.h"
#include "addhead.h"
#include "sighandlers.h"
#include "s3fs_xml.h"
@ -1736,9 +1736,7 @@ static int rename_directory(const char* from, const char* to)
std::string nowcache; // now cache path(not used)
dirtype DirType;
bool normdir;
MVNODE* mn_head = nullptr;
MVNODE* mn_tail = nullptr;
MVNODE* mn_cur;
std::vector<mvnode> mvnodes;
struct stat stbuf;
int result;
bool is_dir;
@ -1746,7 +1744,7 @@ static int rename_directory(const char* from, const char* to)
S3FS_PRN_INFO1("[from=%s][to=%s]", from, to);
//
// Initiate and Add base directory into MVNODE struct.
// Initiate and Add base directory into mvnode struct.
//
strto += "/";
if(0 == chk_dir_object_type(from, newpath, strfrom, nowcache, nullptr, &DirType) && dirtype::UNKNOWN != DirType){
@ -1756,9 +1754,7 @@ static int rename_directory(const char* from, const char* to)
normdir = true;
strfrom = from; // from directory is not removed, but from directory attr is needed.
}
if(nullptr == (add_mvnode(&mn_head, &mn_tail, strfrom.c_str(), strto.c_str(), true, normdir))){
return -ENOMEM;
}
mvnodes.emplace_back(strfrom, strto, true, normdir);
}else{
// Something wrong about "from" directory.
}
@ -1806,20 +1802,20 @@ static int rename_directory(const char* from, const char* to)
}
// push this one onto the stack
if(nullptr == add_mvnode(&mn_head, &mn_tail, from_name.c_str(), to_name.c_str(), is_dir, normdir)){
return -ENOMEM;
}
mvnodes.emplace_back(from_name, to_name, is_dir, normdir);
}
std::sort(mvnodes.begin(), mvnodes.end(), [](const mvnode& a, const mvnode& b) { return a.old_path < b.old_path; });
//
// rename
//
// rename directory objects.
for(mn_cur = mn_head; mn_cur; mn_cur = mn_cur->next){
if(mn_cur->is_dir && mn_cur->old_path && '\0' != mn_cur->old_path[0]){
for(auto mn_cur = mvnodes.cbegin(); mn_cur != mvnodes.cend(); ++mn_cur){
if(mn_cur->is_dir && !mn_cur->old_path.empty()){
std::string xattrvalue;
const char* pxattrvalue;
if(get_meta_xattr_value(mn_cur->old_path, xattrvalue)){
if(get_meta_xattr_value(mn_cur->old_path.c_str(), xattrvalue)){
pxattrvalue = xattrvalue.c_str();
}else{
pxattrvalue = nullptr;
@ -1829,9 +1825,8 @@ static int rename_directory(const char* from, const char* to)
// The ctime is updated only for the top (from) directory.
// Other than that, it will not be updated.
//
if(0 != (result = clone_directory_object(mn_cur->old_path, mn_cur->new_path, (strfrom == mn_cur->old_path), pxattrvalue))){
if(0 != (result = clone_directory_object(mn_cur->old_path.c_str(), mn_cur->new_path.c_str(), (strfrom == mn_cur->old_path), pxattrvalue))){
S3FS_PRN_ERR("clone_directory_object returned an error(%d)", result);
free_mvnodes(mn_head);
return result;
}
}
@ -1839,28 +1834,26 @@ static int rename_directory(const char* from, const char* to)
// iterate over the list - copy the files with rename_object
// does a safe copy - copies first and then deletes old
for(mn_cur = mn_head; mn_cur; mn_cur = mn_cur->next){
for(auto mn_cur = mvnodes.begin(); mn_cur != mvnodes.end(); ++mn_cur){
if(!mn_cur->is_dir){
if(!nocopyapi && !norenameapi){
result = rename_object(mn_cur->old_path, mn_cur->new_path, false); // keep ctime
result = rename_object(mn_cur->old_path.c_str(), mn_cur->new_path.c_str(), false); // keep ctime
}else{
result = rename_object_nocopy(mn_cur->old_path, mn_cur->new_path, false); // keep ctime
result = rename_object_nocopy(mn_cur->old_path.c_str(), mn_cur->new_path.c_str(), false); // keep ctime
}
if(0 != result){
S3FS_PRN_ERR("rename_object returned an error(%d)", result);
free_mvnodes(mn_head);
return result;
}
}
}
// Iterate over old the directories, bottoms up and remove
for(mn_cur = mn_tail; mn_cur; mn_cur = mn_cur->prev){
if(mn_cur->is_dir && mn_cur->old_path && '\0' != mn_cur->old_path[0]){
for(auto mn_cur = mvnodes.rbegin(); mn_cur != mvnodes.rend(); ++mn_cur){
if(mn_cur->is_dir && !mn_cur->old_path.empty()){
if(!(mn_cur->is_normdir)){
if(0 != (result = s3fs_rmdir(mn_cur->old_path))){
if(0 != (result = s3fs_rmdir(mn_cur->old_path.c_str()))){
S3FS_PRN_ERR("s3fs_rmdir returned an error(%d)", result);
free_mvnodes(mn_head);
return result;
}
}else{
@ -1869,7 +1862,6 @@ static int rename_directory(const char* from, const char* to)
}
}
}
free_mvnodes(mn_head);
return 0;
}

View File

@ -322,6 +322,23 @@ inline off_t total_mp_part_list(const mp_part_list_t& mplist)
return size;
}
//
// Rename directory struct
//
struct mvnode
{
mvnode(std::string old_path, std::string new_path, bool is_dir, bool is_normdir)
: old_path(std::move(old_path))
, new_path(std::move(new_path))
, is_dir(is_dir)
, is_normdir(is_normdir)
{}
std::string old_path;
std::string new_path;
bool is_dir;
bool is_normdir;
};
//-------------------------------------------------------------------
// mimes_t
//-------------------------------------------------------------------