[gparted/psusi/refactor: 4/19] Refactor btrfs to use async execute_command



commit cf98edbe28143f6e0623963390deb1c97b14a0d9
Author: Phillip Susi <psusi ubuntu com>
Date:   Sun Feb 12 19:08:13 2012 -0500

    Refactor btrfs to use async execute_command
    
    Instead of the old synchronous Filesystem::execute_command or
    Utils::execute_command, the btrfs methods now use the async
    execute_command, and block the calling thread on a mutex until the
    job completes.  Methods that invoked multiple external utilities
    have been split into multiple functions that are invoked as the
    callback when the previous command has completed.

 include/btrfs.h |   36 ++++++-
 src/btrfs.cc    |  333 ++++++++++++++++++++++++++++++++++++++++---------------
 2 files changed, 273 insertions(+), 96 deletions(-)
---
diff --git a/include/btrfs.h b/include/btrfs.h
index f1f8fac..90372c3 100644
--- a/include/btrfs.h
+++ b/include/btrfs.h
@@ -29,20 +29,48 @@ class btrfs : public FileSystem
 public:
 	FS get_filesystem_support() ;
 	void set_used_sectors( Partition & partition ) ;
+	void set_used_sectors( Partition & partition, sigc::slot<bool, double> slot );
 	void read_label( Partition & partition ) ;
+	void read_label( Partition & partition, sigc::slot<bool, double> slot );
 	bool write_label( const Partition & partition, OperationDetail & operationdetail ) ;
+	void write_label( const Partition & partition, OperationDetail & operationdetail, sigc::slot<bool, double> slot );
 	void read_uuid( Partition & partition ) ;
+	void read_uuid( Partition & partition, sigc::slot<bool, double> slot );
 	bool write_uuid( const Partition & partition, OperationDetail & operationdetail ) ;
+	void write_uuid( const Partition & partition, OperationDetail & operationdetail, sigc::slot<bool, double> slot );
 	bool create( const Partition & new_partition, OperationDetail & operationdetail ) ;
+	void create( const Partition & new_partition, OperationDetail & operationdetail, sigc::slot<bool, double> slot );
 	bool resize( const Partition & partition_new, OperationDetail & operationdetail, bool fill_partition = false ) ;
-	bool move( const Partition & partition_new
-	         , const Partition & partition_old
-	         , OperationDetail & operationdetail
-	         ) ;
+	void resize( const Partition &partition_new, OperationDetail & operationdetail,
+		     bool fill_partition, sigc::slot<bool, double> slot );
+
+	void move( const Partition & partition_new,
+		   const Partition & partition_old,
+		   OperationDetail & operationdetail,
+		   sigc::slot<bool, double> slot);
+	bool move( const Partition & partition_new,
+		   const Partition & partition_old,
+		   OperationDetail & operationdetail );
 	bool copy( const Glib::ustring & src_part_path,
 		   const Glib::ustring & dest_part_path,
 		   OperationDetail & operationdetail ) ;
+	void copy( const Glib::ustring & src_part_path,
+		   const Glib::ustring & dest_part_path,
+		   OperationDetail & operationdetail,
+		   sigc::slot<bool, double> slot );
 	bool check_repair( const Partition & partition, OperationDetail & operationdetail ) ;
+	void check_repair( const Partition & partition, OperationDetail & operationdetail, sigc::slot<bool, double> slot );
+private:
+	bool set_used_sectors2( double progress, Partition *partition );
+	bool resize2( double progress, const Partition *partition_new, OperationDetail *operationdetail, bool fill_partition );
+	bool resize3( double progress, const Partition *partition_new, OperationDetail *operationdetail, bool fill_partition );
+	bool resize4( double progress, const Partition *partition_new, OperationDetail *operationdetail, bool fill_partition );
+	bool read_label2( double progress, Partition *partition );
+	bool read_uuid2( double progress, Partition *partitions );
+	bool check_repair2( double progress );
+	bool create2( double progress );
+	bool write_label2( double progress );
+	Glib::ustring mount_point;
 };
 } //GParted
 
diff --git a/src/btrfs.cc b/src/btrfs.cc
index a0265f8..9ea722e 100644
--- a/src/btrfs.cc
+++ b/src/btrfs.cc
@@ -107,21 +107,72 @@ FS btrfs::get_filesystem_support()
 
 bool btrfs::create( const Partition & new_partition, OperationDetail & operationdetail )
 {
-	return (! execute_command( "mkfs.btrfs -L \"" + new_partition .label + "\" " + new_partition .get_path(), operationdetail ) );
+	create( new_partition, operationdetail, unlock_mutex );
+	mutex.lock();  // wait for completion
+	return success;
+}
+
+bool btrfs::create2( double progress )
+{
+	if ( progress != 1.0 )
+		return false;
+	success = !exit_status;
+	return slot( 1.0 );
+}
+
+void btrfs::create( const Partition & new_partition, OperationDetail & operationdetail, sigc::slot<bool, double> slot )
+{
+	this->slot = slot;
+	execute_command( "mkfs.btrfs -L \"" + new_partition .label + "\" " + new_partition .get_path(),
+			 operationdetail, sigc::mem_fun( *this, &btrfs::create2 ) );
 }
 
 bool btrfs::check_repair( const Partition & partition, OperationDetail & operationdetail )
 {
-	return (! execute_command( "btrfsck " + partition .get_path(), operationdetail )) ;
+	check_repair( partition, operationdetail, unlock_mutex );
+	mutex.lock();  // wait for completion
+	return success;
+}
+
+void btrfs::check_repair( const Partition & partition, OperationDetail & operationdetail, sigc::slot<bool, double> slot )
+{
+	this->slot = slot;
+	execute_command( "btrfsck " + partition .get_path(), operationdetail, sigc::mem_fun( *this, &btrfs::check_repair2 ) );
+}
+
+bool btrfs::check_repair2( double progress )
+{
+	if( progress != 1.0 )
+		return false;
+	success = !exit_status;
+	return slot( 1.0 );
 }
 
 void btrfs::set_used_sectors( Partition & partition )
 {
+	set_used_sectors( partition, unlock_mutex );
+	mutex.lock();  // wait for completion
+}
 
+void btrfs::set_used_sectors( Partition & partition, sigc::slot<bool, double> slot )
+{
+	this->slot = slot;
 	if ( btrfs_found )
-		exit_status = Utils::execute_command( "btrfs filesystem show " + partition .get_path(), output, error, true ) ;
+		execute_command(
+			"btrfs filesystem show " + partition .get_path(),
+			sigc::bind( sigc::mem_fun( *this, &btrfs::set_used_sectors2 ),
+				       &partition ) );
 	else
-		exit_status = Utils::execute_command( "btrfs-show " + partition .get_path(), output, error, true ) ;
+		execute_command( "btrfs-show " + partition .get_path(),
+				 sigc::bind(
+					 sigc::mem_fun( *this, &btrfs::set_used_sectors2 ),
+					 &partition ) );
+}
+
+bool btrfs::set_used_sectors2( double progress, Partition *partition )
+{
+	if ( progress != 1.0 )
+		return false;
 	if ( ! exit_status )
 	{
 		Glib::ustring size_label;
@@ -148,22 +199,44 @@ void btrfs::set_used_sectors( Partition & partition )
 					mult=1;
 					break;
 					}
-			partition .set_used( Utils::round( (rawN * mult)/ double(partition .sector_size) ) ) ;
+			partition->set_used( Utils::round( (rawN * mult)/ double(partition->sector_size) ) );
 		}
 	}
 	else
 	{
-		if ( ! output .empty() )
-			partition .messages .push_back( output ) ;
+		if ( !output.empty() )
+			partition->messages.push_back( output );
 
-		if ( ! error .empty() )
-			partition .messages .push_back( error ) ;
+		if ( !error .empty() )
+			partition->messages.push_back( error );
 	}
+	return slot( progress );
 }
 
 bool btrfs::write_label( const Partition & partition, OperationDetail & operationdetail )
 {
-	return ! execute_command( "btrfs filesystem label " + partition .get_path() + " \"" + partition .label + "\"", operationdetail ) ;
+	write_label( partition, operationdetail, unlock_mutex );
+	mutex.lock();
+	return success;
+}
+
+void btrfs::write_label( const Partition & partition, OperationDetail & operationdetail, sigc::slot<bool, double> slot )
+{
+	this->slot = slot;
+	execute_command( "btrfs filesystem label " + partition .get_path() + " \"" + partition .label + "\"",
+			 operationdetail, sigc::mem_fun( *this, &btrfs::write_label2 ) );
+}
+
+bool btrfs::write_label2( double progress )
+{
+	if ( progress != 1.0 )
+		return false;
+	success = !exit_status;
+	return slot( 1.0 );
+}
+
+void btrfs::write_uuid( const Partition & partition, OperationDetail & operationdetail, sigc::slot<bool, double> slot )
+{
 }
 
 bool btrfs::write_uuid( const Partition & partition, OperationDetail & operationdetail )
@@ -171,141 +244,217 @@ bool btrfs::write_uuid( const Partition & partition, OperationDetail & operation
 	return true ;
 }
 
-bool btrfs::move( const Partition & partition_new
-                , const Partition & partition_old
-                , OperationDetail & operationdetail
-                )
+void btrfs::move( const Partition & partition_new,
+		  const Partition & partition_old,
+		  OperationDetail & operationdetail,
+		  sigc::slot<bool, double> slot)
+{
+}
+
+bool btrfs::move( const Partition & partition_new,
+		  const Partition & partition_old,
+		  OperationDetail & operationdetail )
 {
 	return true ;
 }
 
 bool btrfs::copy( const Glib::ustring & src_part_path,
-                    const Glib::ustring & dest_part_path,
-                    OperationDetail & operationdetail )
+		  const Glib::ustring & dest_part_path,
+		  OperationDetail & operationdetail )
 {
 // TODO
         return true ;
 }
 
-bool btrfs::resize( const Partition & partition_new, OperationDetail & operationdetail, bool fill_partition )
+void btrfs::copy( const Glib::ustring & src_part_path,
+		  const Glib::ustring & dest_part_path,
+		  OperationDetail & operationdetail,
+		  sigc::slot<bool, double> slot )
 {
-	bool success = true ;
+}
 
-	Glib::ustring mount_point = mk_temp_dir( "", operationdetail ) ;
-	if ( mount_point .empty() )
-		return false ;
+bool btrfs::resize( const Partition &partition_new, OperationDetail & operationdetail, bool fill_partition )
+{
+	resize( partition_new, operationdetail, fill_partition, unlock_mutex );
+	mutex.lock(); // wait for completion
+	return !success;
+}
 
-	success &= ! execute_command_timed( "mount -v -t btrfs " + partition_new .get_path() + " " + mount_point, operationdetail ) ;
+void btrfs::resize( const Partition &partition_new, OperationDetail & operationdetail,
+		    bool fill_partition, sigc::slot<bool, double> slot )
+{
+	this->slot = slot;
+	mount_point = mk_temp_dir( "", operationdetail ) ;
+	success = false;
+	if ( mount_point .empty() )
+		slot( 1.0 );
+	execute_command( "mount -v -t btrfs " + partition_new .get_path() + " " + mount_point,
+			 operationdetail,
+			 sigc::bind( sigc::mem_fun( *this, &btrfs::resize2 ),
+				     &partition_new, &operationdetail, fill_partition ) );
+}
 
-	if ( success )
+bool btrfs::resize2( double progress, const Partition *partition_new, OperationDetail *operationdetail, bool fill_partition )
+{
+	if ( progress != 1.0 )
+		return slot( 0.0 );
+	if ( !exit_status )
 	{
-		Glib::ustring size ;
+		operationdetail->get_last_child().set_status( STATUS_SUCCES );
+		Glib::ustring size;
 		if ( ! fill_partition )
 			size = Utils::num_to_str( floor( Utils::sector_to_unit(
-					partition_new .get_sector_length(), partition_new .sector_size, UNIT_KIB ) ) ) + "K" ;
+					partition_new->get_sector_length(), partition_new->sector_size, UNIT_KIB ) ) ) + "K";
 		else
-			size = "max" ;
-		Glib::ustring cmd ;
+			size = "max";
+		Glib::ustring cmd;
 		if ( btrfs_found )
-			cmd = "btrfs filesystem resize " + size + " " + mount_point ;
+			cmd = "btrfs filesystem resize " + size + " " + mount_point;
 		else
-			cmd = "btrfsctl -r " + size + " " + mount_point ;
-		exit_status = execute_command_timed( cmd, operationdetail, false ) ;
-		bool resize_succeeded = ( exit_status == 0 ) ;
-		if ( resize_to_same_size_fails )
-		{
-			//Linux before version 3.2 fails when resizing a
-			//  btrfs file system to the same size with ioctl()
-			//  returning -1 EINVAL (Invalid argument) from the
-			//  kernel btrfs code.
-			//  *   Btrfs filesystem resize reports this as exit
-			//      status 30:
-			//          ERROR: Unable to resize '/MOUNTPOINT'
-			//  *   Btrfsctl -r reports this as exit status 1:
-			//          ioctl:: Invalid argument
-			//  WARNING:
-			//  Ignoring these errors could mask real failures,
-			//  but not ignoring them will cause resizing to the
-			//  same size as part of check operation to fail.
-			resize_succeeded = (    exit_status == 0
-			                     || (   btrfs_found && exit_status == 30<<8 )
-			                     || ( ! btrfs_found && exit_status ==  1<<8 )
-			                   ) ;
-		}
-		operationdetail .get_last_child() .set_status( resize_succeeded ? STATUS_SUCCES : STATUS_ERROR ) ;
-		success &= resize_succeeded ;
-
-		success &= ! execute_command_timed( "umount -v " + mount_point, operationdetail ) ;
+			cmd = "btrfsctl -r " + size + " " + mount_point;
+		execute_command( cmd, *operationdetail,
+				 sigc::bind( sigc::mem_fun( *this, &btrfs::resize3 ),
+					     partition_new, operationdetail, fill_partition ) );
+		return false;
+	} else {
+		operationdetail->get_last_child().set_status( STATUS_ERROR );
+		return slot( progress );
 	}
+}
 
-	rm_temp_dir( mount_point, operationdetail ) ;
+bool btrfs::resize3( double progress, const Partition *partition_new, OperationDetail *operationdetail, bool fill_partition )
+{
+	if ( progress != 1.0 )
+		return slot( 0.0 );
+	if ( resize_to_same_size_fails )
+	{
+		//Linux before version 3.2 fails when resizing a
+		//  btrfs file system to the same size with ioctl()
+		//  returning -1 EINVAL (Invalid argument) from the
+		//  kernel btrfs code.
+		//  *   Btrfs filesystem resize reports this as exit
+		//      status 30:
+		//          ERROR: Unable to resize '/MOUNTPOINT'
+		//  *   Btrfsctl -r reports this as exit status 1:
+		//          ioctl:: Invalid argument
+		//  WARNING:
+		//  Ignoring these errors could mask real failures,
+		//  but not ignoring them will cause resizing to the
+		//  same size as part of check operation to fail.
+		success = ( exit_status == 0 ||
+			    ( btrfs_found && exit_status == 30<<8 ) ||
+			    ( !btrfs_found && exit_status == 1<<8 ) );
+	} else success = !exit_status;
+	operationdetail->get_last_child().set_status( success ? STATUS_SUCCES : STATUS_ERROR );
+	execute_command( "umount -v " + mount_point, *operationdetail,
+			 sigc::bind( sigc::mem_fun( *this, &btrfs::resize4 ),
+				     partition_new, operationdetail, fill_partition ) );
+	return slot( 0.999 );
+}
 
-	return success ;
+bool btrfs::resize4( double progress, const Partition *partition_new, OperationDetail *operationdetail, bool fill_partition )
+{
+	if ( progress != 1.0 )
+		return false;
+	rm_temp_dir( mount_point, *operationdetail );
+	return slot( 1.0 );
 }
 
 void btrfs::read_label( Partition & partition )
 {
+	read_label( partition, unlock_mutex );
+	mutex.lock(); // wait for completion
+}
+
+void btrfs::read_label( Partition & partition, sigc::slot<bool, double> slot )
+{
+	this->slot = slot;
 	if ( btrfs_found )
 	{
-		exit_status = Utils::execute_command( "btrfs filesystem show " + partition .get_path(), output, error, true ) ;
-		if ( ! exit_status )
+		execute_command( "btrfs filesystem show " + partition .get_path(),
+				 sigc::bind( sigc::mem_fun( *this, &btrfs::read_label2 ), &partition ) );
+	} else {
+		execute_command( "btrfs-show " + partition .get_path(),
+				 sigc::bind( sigc::mem_fun( *this, &btrfs::read_label2 ), &partition ) );
+	}
+}
+
+bool btrfs::read_label2( double progress, Partition *partition )
+{
+	if ( progress != 1.0 )
+		return false;
+	if ( exit_status )
+	{
+		if ( !output.empty() )
+			partition->messages.push_back( output );
+		if ( !error .empty() )
+			partition->messages.push_back( error );
+		success = false;
+	} else {
+		if ( btrfs_found )
 		{
-			partition .label = Utils::regexp_label( output, "^Label: '(.*)'  uuid:" );
+			partition->label = Utils::regexp_label( output, "^Label: '(.*)'  uuid:" );
 			//Btrfs filesystem show encloses the label in single
 			//  quotes or reports "none" without single quotes, so
 			//  the cases are disginguishable and this regexp won't
 			//  match the no label case.
 		}
-	}
-	else
-	{
-		exit_status = Utils::execute_command( "btrfs-show " + partition .get_path(), output, error, true ) ;
-		if ( ! exit_status )
+		else
 		{
-			Glib::ustring label = Utils::regexp_label( output, "^Label: (.*)  uuid:" ) ;
+			Glib::ustring label = Utils::regexp_label( output, "^Label: (.*)  uuid:" );
 			//Btrfs-show reports "none" when there is no label, but
 			//  this is indistinguishable from the label actually
 			//  being "none".  Assume no label case.
 			if ( label != "none" )
-				partition .label = label ;
+				partition->label = label;
 		}
+		success = true;
 	}
-	if ( exit_status )
-	{
-		if ( ! output .empty() )
-			partition .messages .push_back( output ) ;
-
-		if ( ! error .empty() )
-			partition .messages .push_back( error ) ;
-	}
+	return slot( 1.0 );
 }
 
 void btrfs::read_uuid( Partition & partition )
 {
+	read_uuid( partition, unlock_mutex );
+	mutex.lock();
+}
+
+void btrfs::read_uuid( Partition & partition, sigc::slot<bool, double> slot )
+{
+	this->slot = slot;
 	if ( btrfs_found )
 	{
-		exit_status = Utils::execute_command( "btrfs filesystem show " + partition .get_path(), output, error, true ) ;
-		if ( ! exit_status )
-		{
-			partition .uuid = Utils::regexp_label( output, "uuid:[[:blank:]]*([^[:space:]]*)" );
-		}
+		execute_command( "btrfs filesystem show " + partition .get_path(),
+				 sigc::bind( sigc::mem_fun( *this, &btrfs::read_uuid2 ), &partition ) );
+	} else {
+		execute_command( "btrfs-show " + partition .get_path(),
+				 sigc::bind( sigc::mem_fun( *this, &btrfs::read_uuid2 ), &partition ) );
 	}
-	else
+}
+
+bool btrfs::read_uuid2( double progress, Partition *partition )
+{
+	if ( progress != 1.0 )
+		return false;
+	if ( exit_status )
 	{
-		exit_status = Utils::execute_command( "btrfs-show " + partition .get_path(), output, error, true ) ;
-		if ( ! exit_status )
+		if ( !output.empty() )
+			partition->messages.push_back( output );
+		if ( !error.empty() )
+			partition->messages.push_back( error );
+		success = false;
+	} else {
+		if ( btrfs_found )
 		{
-			partition .uuid = Utils::regexp_label( output, "uuid:[[:blank:]]*([^[:space:]]*)" );
+			partition->uuid = Utils::regexp_label( output, "uuid:[[:blank:]]*([^[:space:]]*)" );
 		}
+		else
+		{
+			partition->uuid = Utils::regexp_label( output, "uuid:[[:blank:]]*([^[:space:]]*)" );
+		}
+		success = true;
 	}
-	if ( exit_status )
-	{
-		if ( ! output .empty() )
-			partition .messages .push_back( output ) ;
-
-		if ( ! error .empty() )
-			partition .messages .push_back( error ) ;
-	}
+	return slot( 1.0 );
 }
 
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]