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:
parent
f493cb5846
commit
01189e99fc
|
@ -35,7 +35,6 @@ s3fs_SOURCES = \
|
||||||
s3fs_xml.cpp \
|
s3fs_xml.cpp \
|
||||||
metaheader.cpp \
|
metaheader.cpp \
|
||||||
mpu_util.cpp \
|
mpu_util.cpp \
|
||||||
mvnode.cpp \
|
|
||||||
curl.cpp \
|
curl.cpp \
|
||||||
curl_handlerpool.cpp \
|
curl_handlerpool.cpp \
|
||||||
curl_multi.cpp \
|
curl_multi.cpp \
|
||||||
|
|
139
src/mvnode.cpp
139
src/mvnode.cpp
|
@ -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
|
|
||||||
*/
|
|
53
src/mvnode.h
53
src/mvnode.h
|
@ -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
|
|
||||||
*/
|
|
42
src/s3fs.cpp
42
src/s3fs.cpp
|
@ -18,6 +18,7 @@
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
@ -39,7 +40,6 @@
|
||||||
#include "curl_multi.h"
|
#include "curl_multi.h"
|
||||||
#include "s3objlist.h"
|
#include "s3objlist.h"
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
#include "mvnode.h"
|
|
||||||
#include "addhead.h"
|
#include "addhead.h"
|
||||||
#include "sighandlers.h"
|
#include "sighandlers.h"
|
||||||
#include "s3fs_xml.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)
|
std::string nowcache; // now cache path(not used)
|
||||||
dirtype DirType;
|
dirtype DirType;
|
||||||
bool normdir;
|
bool normdir;
|
||||||
MVNODE* mn_head = nullptr;
|
std::vector<mvnode> mvnodes;
|
||||||
MVNODE* mn_tail = nullptr;
|
|
||||||
MVNODE* mn_cur;
|
|
||||||
struct stat stbuf;
|
struct stat stbuf;
|
||||||
int result;
|
int result;
|
||||||
bool is_dir;
|
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);
|
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 += "/";
|
strto += "/";
|
||||||
if(0 == chk_dir_object_type(from, newpath, strfrom, nowcache, nullptr, &DirType) && dirtype::UNKNOWN != DirType){
|
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;
|
normdir = true;
|
||||||
strfrom = from; // from directory is not removed, but from directory attr is needed.
|
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))){
|
mvnodes.emplace_back(strfrom, strto, true, normdir);
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
}else{
|
}else{
|
||||||
// Something wrong about "from" directory.
|
// 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
|
// 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)){
|
mvnodes.emplace_back(from_name, to_name, is_dir, normdir);
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::sort(mvnodes.begin(), mvnodes.end(), [](const mvnode& a, const mvnode& b) { return a.old_path < b.old_path; });
|
||||||
|
|
||||||
//
|
//
|
||||||
// rename
|
// rename
|
||||||
//
|
//
|
||||||
// rename directory objects.
|
// rename directory objects.
|
||||||
for(mn_cur = mn_head; mn_cur; mn_cur = mn_cur->next){
|
for(auto mn_cur = mvnodes.cbegin(); mn_cur != mvnodes.cend(); ++mn_cur){
|
||||||
if(mn_cur->is_dir && mn_cur->old_path && '\0' != mn_cur->old_path[0]){
|
if(mn_cur->is_dir && !mn_cur->old_path.empty()){
|
||||||
std::string xattrvalue;
|
std::string xattrvalue;
|
||||||
const char* pxattrvalue;
|
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();
|
pxattrvalue = xattrvalue.c_str();
|
||||||
}else{
|
}else{
|
||||||
pxattrvalue = nullptr;
|
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.
|
// The ctime is updated only for the top (from) directory.
|
||||||
// Other than that, it will not be updated.
|
// 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);
|
S3FS_PRN_ERR("clone_directory_object returned an error(%d)", result);
|
||||||
free_mvnodes(mn_head);
|
|
||||||
return result;
|
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
|
// iterate over the list - copy the files with rename_object
|
||||||
// does a safe copy - copies first and then deletes old
|
// 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(!mn_cur->is_dir){
|
||||||
if(!nocopyapi && !norenameapi){
|
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{
|
}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){
|
if(0 != result){
|
||||||
S3FS_PRN_ERR("rename_object returned an error(%d)", result);
|
S3FS_PRN_ERR("rename_object returned an error(%d)", result);
|
||||||
free_mvnodes(mn_head);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate over old the directories, bottoms up and remove
|
// Iterate over old the directories, bottoms up and remove
|
||||||
for(mn_cur = mn_tail; mn_cur; mn_cur = mn_cur->prev){
|
for(auto mn_cur = mvnodes.rbegin(); mn_cur != mvnodes.rend(); ++mn_cur){
|
||||||
if(mn_cur->is_dir && mn_cur->old_path && '\0' != mn_cur->old_path[0]){
|
if(mn_cur->is_dir && !mn_cur->old_path.empty()){
|
||||||
if(!(mn_cur->is_normdir)){
|
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);
|
S3FS_PRN_ERR("s3fs_rmdir returned an error(%d)", result);
|
||||||
free_mvnodes(mn_head);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
|
@ -1869,7 +1862,6 @@ static int rename_directory(const char* from, const char* to)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free_mvnodes(mn_head);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
17
src/types.h
17
src/types.h
|
@ -322,6 +322,23 @@ inline off_t total_mp_part_list(const mp_part_list_t& mplist)
|
||||||
return size;
|
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
|
// mimes_t
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue