Connect timed progress tracking callbacks inside execute_command() (#760709)
The timed progress tracking callback for execution of xfs copy follows this pattern: sigc::connection c; ... c = Glib::signal_timeout().connect( ... sigc::mem_fun( *this, &xfs::copy_progress ) ..., 500 /*ms*/ ); ... execute_command( ... ); c.disconnect(); As with output progress tracking callbacks for ext2/3/4 and ntfs file system specific commands, pass the callback slot and a flag into execute_command() and connect the timed callback inside. This simplified the pattern to: ... execute_command( ...|EXEC_PROGRESS_TIMED, static_cast<TimedSlot>( sigc::mem_fun( *this, &xfs::copy_progress ) ) ); NOTE: The type of sigc::mem_fun() doesn't allow the compiler to choose between the two overloaded variants of execute_command() with the fourth parameter of either (full types without typedefs of StreamSlot and TimedSlot respectively): sigc::slot<void, OperationDetail *> stream_progress_slot sigc::slot<bool, OperationDetail *> timed_progress_slot Therefore have to cast the result of all callback slots to the relevant type. Hence: static_cast<StreamSlot>( sigc::mem_fun( *this, &{CLASS}::{NAME}_progress ) ) static_cast<TimedSlot>( sigc::mem_fun( *this, &xfs::copy_progress ) ) References: * [sigc] Functor not resolving between overloaded methods with different slot types https://mail.gnome.org/archives/libsigc-list/2016-February/msg00000.html * Bug 306705 - Can't overload methods based on different slot<> parameters. https://bugzilla.gnome.org/show_bug.cgi?id=306705 Bug 760709 - Add progress bars to XFS and EXT2/3/4 file system specific copy methods
This commit is contained in:
parent
e67bbe906f
commit
438b35aed9
|
@ -41,7 +41,8 @@ enum ExecFlags
|
|||
EXEC_CANCEL_SAFE = 1 << 2,
|
||||
EXEC_PROGRESS_STDOUT = 1 << 3, // Run progress tracking callback after reading new
|
||||
// data on stdout from command.
|
||||
EXEC_PROGRESS_STDERR = 1 << 4 // Same but for stderr.
|
||||
EXEC_PROGRESS_STDERR = 1 << 4, // Same but for stderr.
|
||||
EXEC_PROGRESS_TIMED = 1 << 5 // Run progress tracking callback periodically.
|
||||
};
|
||||
|
||||
inline ExecFlags operator|( ExecFlags lhs, ExecFlags rhs )
|
||||
|
@ -82,17 +83,16 @@ public:
|
|||
|
||||
protected:
|
||||
typedef sigc::slot<void, OperationDetail *> StreamSlot;
|
||||
typedef sigc::slot<bool, OperationDetail *> TimedSlot;
|
||||
|
||||
// Use sigc::slot<> class default constructor, via StreamSlot typedef, to create
|
||||
// an empty, unconnected slot to use as the default stream_progress_slot parameter
|
||||
// for when none is provided.
|
||||
// References:
|
||||
// * How to set default parameter as class object in c++?
|
||||
// http://stackoverflow.com/questions/12121645/how-to-set-default-parameter-as-class-object-in-c
|
||||
// * C++ function, what default value can I give for an object?
|
||||
// http://stackoverflow.com/questions/9909444/c-function-what-default-value-can-i-give-for-an-object
|
||||
int execute_command( const Glib::ustring & command, OperationDetail & operationdetail,
|
||||
ExecFlags flags = EXEC_NONE, StreamSlot stream_progress_slot = StreamSlot() );
|
||||
ExecFlags flags = EXEC_NONE );
|
||||
int execute_command( const Glib::ustring & command, OperationDetail & operationdetail,
|
||||
ExecFlags flags,
|
||||
StreamSlot stream_progress_slot );
|
||||
int execute_command( const Glib::ustring & command, OperationDetail & operationdetail,
|
||||
ExecFlags flags,
|
||||
TimedSlot timed_progress_slot );
|
||||
void set_status( OperationDetail & operationdetail, bool success );
|
||||
void execute_command_eof();
|
||||
Glib::ustring mk_temp_dir( const Glib::ustring & infix, OperationDetail & operationdetail ) ;
|
||||
|
@ -105,6 +105,10 @@ protected:
|
|||
unsigned int index ;
|
||||
|
||||
private:
|
||||
int execute_command_internal( const Glib::ustring & command, OperationDetail & operationdetail,
|
||||
ExecFlags flags,
|
||||
StreamSlot stream_progress_slot,
|
||||
TimedSlot timed_progress_slot );
|
||||
void store_exit_status( GPid pid, int status );
|
||||
bool running;
|
||||
int pipecount;
|
||||
|
|
|
@ -81,7 +81,33 @@ static void setup_child()
|
|||
}
|
||||
|
||||
int FileSystem::execute_command( const Glib::ustring & command, OperationDetail & operationdetail,
|
||||
ExecFlags flags, StreamSlot stream_progress_slot )
|
||||
ExecFlags flags )
|
||||
{
|
||||
StreamSlot empty_stream_slot;
|
||||
TimedSlot empty_timed_slot;
|
||||
return execute_command_internal( command, operationdetail, flags, empty_stream_slot, empty_timed_slot );
|
||||
}
|
||||
|
||||
int FileSystem::execute_command( const Glib::ustring & command, OperationDetail & operationdetail,
|
||||
ExecFlags flags,
|
||||
StreamSlot stream_progress_slot )
|
||||
{
|
||||
TimedSlot empty_timed_slot;
|
||||
return execute_command_internal( command, operationdetail, flags, stream_progress_slot, empty_timed_slot );
|
||||
}
|
||||
|
||||
int FileSystem::execute_command( const Glib::ustring & command, OperationDetail & operationdetail,
|
||||
ExecFlags flags,
|
||||
TimedSlot timed_progress_slot )
|
||||
{
|
||||
StreamSlot empty_stream_slot;
|
||||
return execute_command_internal( command, operationdetail, flags, empty_stream_slot, timed_progress_slot );
|
||||
}
|
||||
|
||||
int FileSystem::execute_command_internal( const Glib::ustring & command, OperationDetail & operationdetail,
|
||||
ExecFlags flags,
|
||||
StreamSlot stream_progress_slot,
|
||||
TimedSlot timed_progress_slot )
|
||||
{
|
||||
operationdetail.add_child( OperationDetail( command, STATUS_EXECUTE, FONT_BOLD_ITALIC ) );
|
||||
Glib::Pid pid;
|
||||
|
@ -126,12 +152,16 @@ int FileSystem::execute_command( const Glib::ustring & command, OperationDetail
|
|||
errorcapture.signal_update.connect( sigc::bind( sigc::ptr_fun( update_command_output ),
|
||||
children[children.size() - 1],
|
||||
&error ) );
|
||||
sigc::connection timed_conn;
|
||||
if ( flags & EXEC_PROGRESS_STDOUT && ! stream_progress_slot.empty() )
|
||||
// Call progress tracking callback when stdout updates
|
||||
outputcapture.signal_update.connect( sigc::bind( stream_progress_slot, &operationdetail ) );
|
||||
else if ( flags & EXEC_PROGRESS_STDERR && ! stream_progress_slot.empty() )
|
||||
// Call progress tracking callback when stderr updates
|
||||
errorcapture.signal_update.connect( sigc::bind( stream_progress_slot, &operationdetail ) );
|
||||
else if ( flags & EXEC_PROGRESS_TIMED && ! timed_progress_slot.empty() )
|
||||
// Call progress tracking callback every 500 ms
|
||||
timed_conn = Glib::signal_timeout().connect( sigc::bind( timed_progress_slot, &operationdetail ), 500 );
|
||||
outputcapture.connect_signal();
|
||||
errorcapture.connect_signal();
|
||||
|
||||
|
@ -151,6 +181,8 @@ int FileSystem::execute_command( const Glib::ustring & command, OperationDetail
|
|||
}
|
||||
close( out );
|
||||
close( err );
|
||||
if ( timed_conn.connected() )
|
||||
timed_conn.disconnect();
|
||||
operationdetail.stop_progressbar();
|
||||
return exit_status;
|
||||
}
|
||||
|
|
10
src/ext2.cc
10
src/ext2.cc
|
@ -231,7 +231,7 @@ bool ext2::create( const Partition & new_partition, OperationDetail & operationd
|
|||
return ! execute_command( mkfs_cmd + " -F -L \"" + new_partition.get_filesystem_label() + "\" " +
|
||||
new_partition.get_path(),
|
||||
operationdetail, EXEC_CHECK_STATUS|EXEC_CANCEL_SAFE|EXEC_PROGRESS_STDOUT,
|
||||
sigc::mem_fun( *this, &ext2::create_progress ) );
|
||||
static_cast<StreamSlot>( sigc::mem_fun( *this, &ext2::create_progress ) ) );
|
||||
}
|
||||
|
||||
bool ext2::resize( const Partition & partition_new, OperationDetail & operationdetail, bool fill_partition )
|
||||
|
@ -243,14 +243,14 @@ bool ext2::resize( const Partition & partition_new, OperationDetail & operationd
|
|||
partition_new .get_sector_length(), partition_new .sector_size, UNIT_KIB ) ) ) + "K";
|
||||
|
||||
return ! execute_command( str_temp, operationdetail, EXEC_CHECK_STATUS|EXEC_PROGRESS_STDOUT,
|
||||
sigc::mem_fun( *this, &ext2::resize_progress ) );
|
||||
static_cast<StreamSlot>( sigc::mem_fun( *this, &ext2::resize_progress ) ) );
|
||||
}
|
||||
|
||||
bool ext2::check_repair( const Partition & partition, OperationDetail & operationdetail )
|
||||
{
|
||||
exit_status = execute_command( fsck_cmd + " -f -y -v -C 0 " + partition.get_path(), operationdetail,
|
||||
EXEC_CANCEL_SAFE|EXEC_PROGRESS_STDOUT,
|
||||
sigc::mem_fun( *this, &ext2::check_repair_progress ) );
|
||||
static_cast<StreamSlot>( sigc::mem_fun( *this, &ext2::check_repair_progress ) ) );
|
||||
bool success = ( exit_status == 0 || exit_status == 1 || exit_status == 2 );
|
||||
set_status( operationdetail, success );
|
||||
return success;
|
||||
|
@ -270,7 +270,7 @@ bool ext2::move( const Partition & partition_new,
|
|||
|
||||
fs_block_size = partition_old.fs_block_size;
|
||||
return ! execute_command( cmd, operationdetail, EXEC_CHECK_STATUS|EXEC_CANCEL_SAFE|EXEC_PROGRESS_STDERR,
|
||||
sigc::mem_fun( *this, &ext2::copy_progress ) );
|
||||
static_cast<StreamSlot>( sigc::mem_fun( *this, &ext2::copy_progress ) ) );
|
||||
}
|
||||
|
||||
bool ext2::copy( const Partition & src_part,
|
||||
|
@ -280,7 +280,7 @@ bool ext2::copy( const Partition & src_part,
|
|||
fs_block_size = src_part.fs_block_size;
|
||||
return ! execute_command( image_cmd + " -ra -p " + src_part.get_path() + " " + dest_part.get_path(),
|
||||
operationdetail, EXEC_CHECK_STATUS|EXEC_CANCEL_SAFE|EXEC_PROGRESS_STDERR,
|
||||
sigc::mem_fun( *this, &ext2::copy_progress ) );
|
||||
static_cast<StreamSlot>( sigc::mem_fun( *this, &ext2::copy_progress ) ) );
|
||||
}
|
||||
|
||||
//Private methods
|
||||
|
|
|
@ -236,7 +236,7 @@ bool ntfs::resize( const Partition & partition_new, OperationDetail & operationd
|
|||
|
||||
if ( ! execute_command( cmd + " " + partition_new.get_path(),
|
||||
operationdetail.get_last_child(), EXEC_CHECK_STATUS|EXEC_PROGRESS_STDOUT,
|
||||
sigc::mem_fun( *this, &ntfs::resize_progress ) ) )
|
||||
static_cast<StreamSlot>( sigc::mem_fun( *this, &ntfs::resize_progress ) ) ) )
|
||||
{
|
||||
operationdetail .get_last_child() .set_status( STATUS_SUCCES ) ;
|
||||
return_value = true ;
|
||||
|
|
19
src/xfs.cc
19
src/xfs.cc
|
@ -254,20 +254,13 @@ bool xfs::copy( const Partition & src_part,
|
|||
|
||||
if ( success )
|
||||
{
|
||||
sigc::connection c;
|
||||
if ( src_used > 0LL )
|
||||
{
|
||||
operationdetail.run_progressbar( 0.0, (double)src_used, PROGRESSBAR_TEXT_COPY_BYTES );
|
||||
// Get xfs::copy_progress() called every 500 ms to update progress
|
||||
c = Glib::signal_timeout().connect(
|
||||
sigc::bind<OperationDetail*>( sigc::mem_fun( *this, &xfs::copy_progress ),
|
||||
&operationdetail ),
|
||||
500 );
|
||||
}
|
||||
success &= ! execute_command( "sh -c 'xfsdump -J - " + src_mount_point +
|
||||
" | xfsrestore -J - " + dest_mount_point + "'",
|
||||
operationdetail, EXEC_CHECK_STATUS|EXEC_CANCEL_SAFE );
|
||||
c.disconnect();
|
||||
operationdetail,
|
||||
EXEC_CHECK_STATUS|EXEC_CANCEL_SAFE|EXEC_PROGRESS_TIMED,
|
||||
static_cast<TimedSlot>( sigc::mem_fun( *this, &xfs::copy_progress ) ) );
|
||||
operationdetail.stop_progressbar();
|
||||
|
||||
success &= ! execute_command( "umount -v " + dest_part.get_path(), operationdetail,
|
||||
|
@ -296,6 +289,12 @@ bool xfs::check_repair( const Partition & partition, OperationDetail & operation
|
|||
// recorded source FS used bytes.
|
||||
bool xfs::copy_progress( OperationDetail * operationdetail )
|
||||
{
|
||||
if ( src_used <= 0LL )
|
||||
{
|
||||
operationdetail->stop_progressbar();
|
||||
// Failed to get source FS used bytes. Remove this timed callback early.
|
||||
return false;
|
||||
}
|
||||
Byte_Value fs_size;
|
||||
Byte_Value fs_free;
|
||||
Byte_Value dst_used;
|
||||
|
|
Loading…
Reference in New Issue