30 #include <boost/function.hpp>
31 #include <boost/any.hpp>
32 #include <boost/lexical_cast.hpp>
33 #include <boost/filesystem.hpp>
39 #include <sys/param.h>
47 #include <sys/types.h>
48 #if defined(osx_platform)
49 #include <sys/malloc.h>
60 #if defined(solaris_platform)
61 #include <sys/statvfs.h>
64 #if defined(osx_platform)
65 #include <sys/param.h>
66 #include <sys/mount.h>
69 #if defined(linux_platform)
91 const char* srcFileName,
92 const char* destFileName ) {
96 int inFd = open( srcFileName, O_RDONLY, 0 );
99 std::stringstream msg_stream;
100 msg_stream <<
"Open error for srcFileName \"" << srcFileName <<
"\", status = " << err_status;
101 result =
ERROR( err_status, msg_stream.str() );
105 int status = stat( srcFileName, &statbuf );
108 std::stringstream msg_stream;
109 msg_stream <<
"stat failed on \"" << srcFileName <<
"\", status: " << err_status;
112 else if ( ( statbuf.st_mode & S_IFREG ) == 0 ) {
113 std::stringstream msg_stream;
114 msg_stream <<
"srcFileName \"" << srcFileName <<
"\" is not a regular file.";
118 int outFd = open( destFileName, O_WRONLY | O_CREAT | O_TRUNC,
mode );
121 std::stringstream msg_stream;
122 msg_stream <<
"Open error for destFileName \"" << destFileName <<
"\", status = " << err_status;
123 result =
ERROR( err_status, msg_stream.str() );
126 size_t trans_buff_size;
135 std::vector<char> myBuf( trans_buff_size );
138 while ( result.
ok() && ( bytesRead = read( inFd, (
void * ) myBuf.data(), trans_buff_size ) ) > 0 ) {
139 int bytesWritten = write( outFd, (
void * ) myBuf.data(), bytesRead );
141 if ( ( result =
ASSERT_ERROR( bytesWritten > 0, err_status,
"Write error for srcFileName %s, status = %d",
142 destFileName,
status ) ).ok() ) {
143 bytesCopied += bytesWritten;
151 bytesCopied, statbuf.st_size, srcFileName );
166 const std::string& _phy_path,
167 std::string& _ret_string ) {
170 std::string vault_path;
174 if ( _phy_path.compare( 0, 1,
"/" ) != 0 &&
175 _phy_path.compare( 0, vault_path.size(), vault_path ) != 0 ) {
176 _ret_string = vault_path;
178 _ret_string += _phy_path;
182 _ret_string = _phy_path;
202 std::string full_path;
204 data_obj->physical_path(),
206 if ( ( result =
ASSERT_PASS( ret,
"Failed generating full path for object." ) ).ok() ) {
207 data_obj->physical_path( full_path );
217 template<
typename DEST_TYPE >
226 ret = _ctx.
valid< DEST_TYPE >();
227 if ( ( result =
ASSERT_PASS( ret,
"resource context is invalid." ) ).ok() ) {
246 if ( ( result =
ASSERT_PASS( ret,
"unix_check_params_and_path - resource context is invalid" ) ).ok() ) {
257 const std::string& path,
263 while ( !done && result.
ok() ) {
264 pos = path.find_first_of(
'/', pos + 1 );
266 subdir = path.substr( 0, pos );
272 subdir.c_str(), strerror( errno ),
status );
274 if ( pos == std::string::npos ) {
303 result =
ASSERT_PASS( ret,
"Invalid parameters or physical path." );
317 result =
ASSERT_PASS( ret,
"Invalid parameters or physical path." );
331 result =
ASSERT_PASS( ret,
"Invalid parameters or physical path." );
341 const std::string* ) {
345 result =
ASSERT_PASS( ret,
"Invalid parameters or physical path." );
360 if ( ( result =
ASSERT_PASS( ret,
"Invalid parameters or physical path." ) ).ok() ) {
365 size_t found = fco->physical_path().find_last_of(
"/" );
366 std::string path = fco->physical_path().substr( 0, found + 1 );
369 #if defined(solaris_platform)
370 struct statvfs statbuf;
372 struct statfs statbuf;
375 #if not defined(windows_platform)
376 #if defined(solaris_platform)
377 status = statvfs( path.c_str(), &statbuf );
378 #elif defined(sgi_platform)
379 status = statfs( path.c_str(), &statbuf,
sizeof(
struct statfs ), 0 );
380 #elif defined(aix_platform) || defined(linux_platform) || defined(osx_platform)
381 status = statfs( path.c_str(), &statbuf );
387 if ( ( result =
ASSERT_ERROR(
status >= 0, err_status,
"Statfs error for \"%s\", status = %d.",
388 path.c_str(), err_status ) ).ok() ) {
390 #if defined(sgi_platform)
391 if ( statbuf.f_frsize > 0 ) {
392 fssize = statbuf.f_frsize;
395 fssize = statbuf.f_bsize;
397 fssize *= statbuf.f_bavail;
400 #if defined(aix_platform) || defined(osx_platform) || \
401 defined(linux_platform)
402 fssize = statbuf.f_bavail * statbuf.f_bsize;
403 #elif defined(sgi_platform)
404 fssize = statbuf.f_bfree * statbuf.f_bsize;
406 result.
code( fssize );
417 const std::string& _path,
418 struct statfs& _sb ) {
419 namespace bfs = boost::filesystem;
421 bfs::path vp( _path );
426 vp = vp.parent_path();
430 std::string msg(
"path does not exist [" );
437 int err = statfs( vp.string().c_str(), &_sb );
439 std::stringstream msg;
440 msg <<
"statfs failed for ["
441 << _path <<
"] errno " << errno;
452 std::string resource_name;
455 rodsLog(
LOG_ERROR,
"warn_if_deprecated_context_string_set: failed to get resource name");
461 rodsLog(
LOG_NOTICE,
"warn_if_deprecated_context_string_set: resource [%s] is using deprecated context string [%s]", resource_name.c_str(),
HIGH_WATER_MARK.c_str());
471 std::string resource_name;
474 rodsLog(
LOG_ERROR,
"replica_exceeds_resource_free_space: failed to get resource name");
477 if (_file_size < 0) {
481 std::string minimum_free_space_string;
485 }
else if (!err.
ok()) {
486 rodsLog(
LOG_ERROR,
"replica_exceeds_resource_free_space: failed to get MINIMUM_FREE_SPACE_FOR_CREATE_IN_BYTES property for resource [%s]", resource_name.c_str());
491 if (minimum_free_space_string.size()>0 && minimum_free_space_string[0] ==
'-') {
492 rodsLog(
LOG_ERROR,
"replica_exceeds_resource_free_space: minimum free space < 0 [%s] for resource [%s]", minimum_free_space_string.c_str(), resource_name.c_str());
496 uintmax_t minimum_free_space = 0;
498 minimum_free_space = boost::lexical_cast<uintmax_t>(minimum_free_space_string);
499 }
catch (
const boost::bad_lexical_cast&) {
500 rodsLog(
LOG_ERROR,
"replica_exceeds_resource_free_space: invalid MINIMUM_FREE_SPACE_FOR_CREATE_IN_BYTES [%s] for resource [%s]", minimum_free_space_string.c_str(), resource_name.c_str());
504 std::string resource_free_space_string;
507 rodsLog(
LOG_ERROR,
"replica_exceeds_resource_free_space: minimum free space constraint was requested, and failed to get resource free space for resource [%s]", resource_name.c_str());
512 if (resource_free_space_string.size()>0 && resource_free_space_string[0] ==
'-') {
513 rodsLog(
LOG_ERROR,
"replica_exceeds_resource_free_space: resource free space < 0 [%s] for resource [%s]", resource_free_space_string.c_str(), resource_name.c_str());
517 uintmax_t resource_free_space = 0;
519 resource_free_space = boost::lexical_cast<uintmax_t>(resource_free_space_string);
520 }
catch (
const boost::bad_lexical_cast&) {
521 rodsLog(
LOG_ERROR,
"replica_exceeds_resource_free_space: invalid free space [%s] for resource [%s]", resource_free_space_string.c_str(), resource_name.c_str());
525 if (minimum_free_space > resource_free_space) {
529 if (resource_free_space - minimum_free_space <
static_cast<uint64_t
>(_file_size)) {
545 if ( ( result =
ASSERT_PASS( ret,
"Invalid parameters or physical path." ) ).ok() ) {
563 irods::kvp_map_t::iterator itr = kvp.begin();
564 for ( ; itr != kvp.end(); ++ itr ) {
567 "unix_file_create_plugin - kv_pass :: key [%s] - value [%s]",
569 itr->second.c_str() );
575 if ( ( result =
ASSERT_PASS( ret,
"Error determining freespace on system." ) ).ok() ) {
578 file_size, ret.
code() ) ).ok() ) {
581 mode_t myMask = umask( ( mode_t ) 0000 );
582 int fd = open( fco->physical_path().c_str(), O_RDWR | O_CREAT | O_EXCL, fco->mode() );
587 ( void ) umask( ( mode_t ) myMask );
594 int null_fd = open(
"/dev/null", O_RDWR, 0 );
598 mode_t myMask = umask( ( mode_t ) 0000 );
599 fd = open( fco->physical_path().c_str(), O_RDWR | O_CREAT | O_EXCL, fco->mode() );
601 if ( null_fd >= 0 ) {
608 ( void ) umask( ( mode_t ) myMask );
615 std::stringstream msg;
616 msg <<
"create error for \"";
617 msg << fco->physical_path();
618 msg <<
"\", errno = \"";
619 msg << strerror( errsav );
624 fco->file_descriptor(
status );
630 fco->file_descriptor( fd );
651 if ( ( result =
ASSERT_PASS( ret,
"Invalid parameters or physical path." ) ).ok() ) {
669 irods::kvp_map_t::iterator itr = kvp.begin();
670 for ( ; itr != kvp.end(); ++ itr ) {
673 "unix_file_open_plugin - kv_pass :: key [%s] - value [%s]",
675 itr->second.c_str() );
682 int flags = fco->flags();
684 #if defined(osx_platform)
686 if ( flags & 0x200 ) {
687 flags = flags ^ 0x200;
688 flags = flags | O_TRUNC;
694 int fd = open( fco->physical_path().c_str(), flags, fco->mode() );
701 int null_fd = open(
"/dev/null", O_RDWR, 0 );
702 fd = open( fco->physical_path().c_str(), flags, fco->mode() );
704 if ( null_fd >= 0 ) {
714 std::stringstream msg;
715 msg <<
"Open error for \"";
716 msg << fco->physical_path();
717 msg <<
"\", errno = \"";
718 msg << strerror( errsav );
719 msg <<
"\", status = \"";
721 msg <<
"\", flags = \"";
729 fco->file_descriptor( fd );
751 if ( ( result =
ASSERT_PASS( ret,
"Invalid parameters or physical path." ) ).ok() ) {
759 int status = read( fco->file_descriptor(), _buf, _len );
764 if ( !( result =
ASSERT_ERROR(
status >= 0, err_status,
"Read error for file: \"%s\", errno = \"%s\".",
765 fco->physical_path().c_str(), strerror( errno ) ) ).ok() ) {
766 result.
code( err_status );
790 if ( ( result =
ASSERT_PASS( ret,
"Invalid parameters or physical path." ) ).ok() ) {
798 int status = write( fco->file_descriptor(), _buf, _len );
803 if ( !( result =
ASSERT_ERROR(
status >= 0, err_status,
"Write file: \"%s\", errno = \"%s\", status = %d.",
804 fco->physical_path().c_str(), strerror( errno ), err_status ) ).ok() ) {
805 result.
code( err_status );
827 if ( ( result =
ASSERT_PASS( ret,
"Invalid parameters or physical path." ) ).ok() ) {
835 int status = close( fco->file_descriptor() );
840 if ( !( result =
ASSERT_ERROR(
status >= 0, err_status,
"Close error for file: \"%s\", errno = \"%s\", status = %d.",
841 fco->physical_path().c_str(), strerror( errno ), err_status ) ).ok() ) {
842 result.
code( err_status );
862 if ( ( result =
ASSERT_PASS( ret,
"Invalid parameters or physical path." ) ).ok() ) {
870 int status = unlink( fco->physical_path().c_str() );
875 if ( !( result =
ASSERT_ERROR(
status >= 0, err_status,
"Unlink error for \"%s\", errno = \"%s\", status = %d.",
876 fco->physical_path().c_str(), strerror( errno ), err_status ) ).ok() ) {
878 result.
code( err_status );
893 struct stat* _statbuf ) {
901 if ( ( result =
ASSERT_PASS( ret,
"resource context is invalid." ) ).ok() ) {
909 int status = stat( fco->physical_path().c_str(), _statbuf );
914 if ( ( result =
ASSERT_ERROR(
status >= 0, err_status,
"Stat error for \"%s\", errno = \"%s\", status = %d.",
915 fco->physical_path().c_str(), strerror( errno ), err_status ) ).ok() ) {
935 if ( ( result =
ASSERT_PASS( ret,
"Invalid parameters or physical path." ) ).ok() ) {
943 long long status = lseek( fco->file_descriptor(), _offset, _whence );
948 if ( ( result =
ASSERT_ERROR(
status >= 0, err_status,
"Lseek error for \"%s\", errno = \"%s\", status = %ld.",
949 fco->physical_path().c_str(), strerror( errno ), err_status ) ).ok() ) {
969 if ( ( result =
ASSERT_PASS( ret,
"resource context is invalid." ) ).ok() ) {
977 mode_t myMask = umask( ( mode_t ) 0000 );
978 int status = mkdir( fco->physical_path().c_str(), fco->mode() );
982 umask( ( mode_t ) myMask );
988 if ( ( result =
ASSERT_ERROR(
status >= 0, err_status,
"Mkdir error for \"%s\", errno = \"%s\", status = %d.",
989 fco->physical_path().c_str(), strerror( errno ), err_status ) ).ok() ) {
1006 if ( ( result =
ASSERT_PASS( ret,
"Invalid parameters or physical path." ) ).ok() ) {
1014 int status = rmdir( fco->physical_path().c_str() );
1019 result =
ASSERT_ERROR(
status >= 0, err_status,
"Rmdir error for \"%s\", errno = \"%s\", status = %d.",
1020 fco->physical_path().c_str(), strerror( errno ), err_status );
1035 irods::error ret = unix_check_params_and_path< irods::collection_object >( _ctx );
1037 return PASSMSG(
"Invalid parameters or physical path.", ret );
1046 DIR* dir_ptr = opendir( fco->physical_path().c_str() );
1051 if (
NULL == dir_ptr ) {
1053 std::stringstream msg;
1054 msg <<
"Open error for \"";
1055 msg << fco->physical_path();
1056 msg <<
"\", errno = \"";
1057 msg << strerror( errsav );
1058 msg <<
"\", status = \"";
1066 fco->directory_pointer( dir_ptr );
1082 irods::error ret = unix_check_params_and_path< irods::collection_object >( _ctx );
1083 if ( ( result =
ASSERT_PASS( ret,
"Invalid parameters or physical path." ) ).ok() ) {
1091 int status = closedir( fco->directory_pointer() );
1096 result =
ASSERT_ERROR(
status >= 0, err_status,
"Closedir error for \"%s\", errno = \"%s\", status = %d.",
1097 fco->physical_path().c_str(), strerror( errno ), err_status );
1113 irods::error ret = unix_check_params_and_path< irods::collection_object >( _ctx );
1114 if ( ( result =
ASSERT_PASS( ret,
"Invalid parameters or physical path." ) ).ok() ) {
1126 struct dirent * tmp_dirent = readdir( fco->directory_pointer() );
1130 if ( ( result =
ASSERT_ERROR( tmp_dirent !=
NULL, -1,
"End of directory list reached." ) ).ok() ) {
1134 if ( !( *_dirent_ptr ) ) {
1146 #if defined(solaris_platform)
1154 if ( ( result =
ASSERT_ERROR( errno == 0,
status,
"Readdir error, status = %d, errno= \"%s\".",
1155 status, strerror( errno ) ) ).ok() ) {
1169 const char* _new_file_name ) {
1175 if ( ( result =
ASSERT_PASS( ret,
"Invalid parameters or physical path." ) ).ok() ) {
1179 std::string new_full_path;
1181 if ( ( result =
ASSERT_PASS( ret,
"Unable to generate full path for destination file: \"%s\".",
1182 _new_file_name ) ).ok() ) {
1201 std::string new_path = new_full_path;
1202 std::size_t last_slash = new_path.find_last_of(
'/' );
1203 new_path.erase( last_slash );
1205 if ( ( result =
ASSERT_PASS( ret,
"Mkdir error for \"%s\".", new_path.c_str() ) ).ok() ) {
1211 int status =
rename( fco->physical_path().c_str(), new_full_path.c_str() );
1214 fco->physical_path(new_full_path);
1219 if ( ( result =
ASSERT_ERROR(
status >= 0, err_status,
"Rename error for \"%s\" to \"%s\", errno = \"%s\", status = %d.",
1220 fco->physical_path().c_str(), new_full_path.c_str(), strerror( errno ), err_status ) ).ok() ) {
1238 irods::error ret = unix_check_params_and_path< irods::file_object >( _ctx );
1239 if ( ( result =
ASSERT_PASS( ret,
"Invalid parameters or physical path." ) ).ok() ) {
1247 int status = truncate( file_obj->physical_path().c_str(), file_obj->size() );
1252 result =
ASSERT_ERROR(
status >= 0, err_status,
"Truncate error for: \"%s\", errno = \"%s\", status = %d.",
1253 file_obj->physical_path().c_str(), strerror( errno ), err_status );
1267 const char* _cache_file_name ) {
1273 if ( ( result =
ASSERT_PASS( ret,
"Invalid parameters or physical path." ) ).ok() ) {
1279 ret =
unix_file_copy( fco->mode(), fco->physical_path().c_str(), _cache_file_name );
1291 const char* _cache_file_name ) {
1297 if ( ( result =
ASSERT_PASS( ret,
"Invalid parameters or physical path." ) ).ok() ) {
1303 ret =
unix_file_copy( fco->mode(), _cache_file_name, fco->physical_path().c_str() );
1315 const std::string& _resc_name,
1316 const std::string& _curr_host,
1317 float& _out_vote ) {
1322 int resc_status = 0;
1324 if ( ( result =
ASSERT_PASS( get_ret,
"Failed to get \"status\" property." ) ).ok() ) {
1346 std::string host_name;
1348 if ( ( result =
ASSERT_PASS( get_ret,
"Failed to get \"location\" property." ) ).ok() ) {
1352 if ( _curr_host == host_name ) {
1362 "create :: resc name [%s] curr host [%s] resc host [%s] vote [%f]",
1379 const std::string& _resc_name,
1380 const std::string& _curr_host,
1381 float& _out_vote ) {
1390 int resc_status = 0;
1392 if ( ( result =
ASSERT_PASS( get_ret,
"Failed to get \"status\" property." ) ).ok() ) {
1400 std::string host_name;
1402 if ( ( result =
ASSERT_PASS( get_ret,
"Failed to get \"location\" property." ) ).ok() ) {
1406 bool curr_host = ( _curr_host == host_name );
1410 bool need_repl = ( _file_obj->repl_requested() > -1 );
1415 std::vector< irods::physical_object > objs = _file_obj->replicas();
1416 std::vector< irods::physical_object >::iterator itr = objs.begin();
1420 for ( ; itr != objs.end(); ++itr ) {
1424 std::string last_resc;
1426 parser.set_string( itr->resc_hier() );
1427 parser.last_resc( last_resc );
1431 bool repl_us = ( _file_obj->repl_requested() == itr->repl_num() );
1432 bool resc_us = ( _resc_name == last_resc );
1433 bool is_dirty = ( itr->is_dirty() != 1 );
1476 "open :: resc name [%s] curr host [%s] resc host [%s] vote [%f]",
1491 result =
PASS( result );
1504 const std::string* _opr,
1505 const std::string* _curr_host,
1507 float* _out_vote ) {
1513 if ( ( result =
ASSERT_PASS( ret,
"Invalid resource context." ) ).ok() ) {
1528 std::string resc_name;
1530 if ( ( result =
ASSERT_PASS( ret,
"Failed in get property for name." ) ).ok() ) {
1540 result =
ASSERT_PASS( ret,
"Failed redirecting for open." );
1547 result =
ASSERT_PASS( ret,
"Failed redirecting for create." );
1557 if( *_out_vote > 0 && result.
ok() ) {
1600 rodsLog(
LOG_NOTICE,
"unixfilesystem_resource::post_disconnect_maintenance_operation - [%s]",
1612 const std::string& _inst_name,
1613 const std::string& _context ) :
1620 std::vector< std::string > props;
1628 irods::kvp_map_t::iterator itr = kvp.begin();
1629 for( ; itr != kvp.end(); ++itr ) {
1647 return ERROR( -1,
"nop" );
1669 using namespace irods;
1670 using namespace std;
1689 function<error(plugin_context&,void*,int)>(
1704 function<error(plugin_context&, struct stat*)>(
1719 function<error(plugin_context&,struct rodsDirent**)>(
1724 function<error(plugin_context&, const char*)>(
1734 function<error(plugin_context&, long long, int)>(
1749 function<error(plugin_context&, const char*)>(
1754 function<error(plugin_context&, const char*)>(
1774 function<error(plugin_context&, const std::string*)>(
1784 function<error(plugin_context&,const std::string*, const std::string*, irods::hierarchy_parser*, float*)>(