make sure progressfraction stays between 0.0 and 1.0 implemented rollback

* src/Dialog_Progress.cc: make sure progressfraction stays between 0.0
  and 1.0
* include/GParted_Core.h,
  src/GParted_Core.cc: implemented rollback in case of failed move of
  overlapping filesystems. Together with the readonly test moving
  should be quite save now :)
This commit is contained in:
Bart Hakvoort 2006-09-10 12:17:33 +00:00
parent 9010255c1c
commit 79672a5298
4 changed files with 164 additions and 38 deletions

View File

@ -1,3 +1,12 @@
2006-09-10 Bart Hakvoort <hakvoort@cvs.gnome.org>
* src/Dialog_Progress.cc: make sure progressfraction stays between 0.0
and 1.0
* include/GParted_Core.h,
src/GParted_Core.cc: implemented rollback in case of failed move of
overlapping filesystems. Together with the readonly test moving
should be quite save now :)
2006-09-09 Bart Hakvoort <hakvoort@cvs.gnome.org> 2006-09-09 Bart Hakvoort <hakvoort@cvs.gnome.org>
* src/fat16.cc, * src/fat16.cc,

View File

@ -108,10 +108,29 @@ private:
Partition & partition_dst, Partition & partition_dst,
Sector min_size, Sector min_size,
OperationDetail & operationdetail ) ; OperationDetail & operationdetail ) ;
bool copy_filesystem_simulation( const Partition & partition_src,
const Partition & partition_dst,
OperationDetail & operationdetail ) ;
bool copy_filesystem( const Partition & partition_src, bool copy_filesystem( const Partition & partition_src,
const Partition & partition_dest, const Partition & partition_dst,
OperationDetail & operationdetail, OperationDetail & operationdetail,
bool readonly = false ) ; bool readonly = false ) ;
bool copy_filesystem( const Partition & partition_src,
const Partition & partition_dst,
OperationDetail & operationdetail,
Sector & total_done ) ;
bool copy_filesystem( const Glib::ustring & src_device,
const Glib::ustring & dst_device,
Sector src_start,
Sector dst_start,
Sector length,
OperationDetail & operationdetail,
bool readonly,
Sector & total_done ) ;
void rollback_transaction( const Partition & partition_src,
const Partition & partition_dst,
OperationDetail & operationdetail,
Sector total_done ) ;
bool check_repair_filesystem( const Partition & partition, OperationDetail & operationdetail ) ; bool check_repair_filesystem( const Partition & partition, OperationDetail & operationdetail ) ;
@ -126,7 +145,8 @@ private:
Sector length, Sector length,
Sector blocksize, Sector blocksize,
OperationDetail & operationdetail, OperationDetail & operationdetail,
bool readonly ) ; bool readonly,
Sector & total_done ) ;
bool copy_block( PedDevice * lp_device_src, bool copy_block( PedDevice * lp_device_src,
PedDevice * lp_device_dst, PedDevice * lp_device_dst,

View File

@ -181,7 +181,7 @@ void Dialog_Progress::dispatcher_on_update_gui_elements()
if ( operationdetail .fraction >= 0 ) if ( operationdetail .fraction >= 0 )
{ {
progressbar_current .set_fraction( operationdetail .fraction ) ; progressbar_current .set_fraction( operationdetail .fraction > 1.0 ? 1.0 : operationdetail .fraction ) ;
progressbar_current .set_text( operationdetail .progress_text ) ; progressbar_current .set_text( operationdetail .progress_text ) ;
} }
} }
@ -196,7 +196,7 @@ void Dialog_Progress::on_signal_show()
label_current .set_markup( "<b>" + operations[ t ] ->description + "</b>" ) ; label_current .set_markup( "<b>" + operations[ t ] ->description + "</b>" ) ;
progressbar_all .set_text( String::ucompose( _("%1 of %2 operations completed"), t, operations .size() ) ) ; progressbar_all .set_text( String::ucompose( _("%1 of %2 operations completed"), t, operations .size() ) ) ;
progressbar_all .set_fraction( fraction * t ) ; progressbar_all .set_fraction( fraction * t > 1.0 ? 1.0 : fraction * t ) ;
treerow = treestore_operations ->children()[ t ] ; treerow = treestore_operations ->children()[ t ] ;

View File

@ -1129,14 +1129,27 @@ bool GParted_Core::move_filesystem( const Partition & partition_old,
succes = false ; succes = false ;
if ( partition_new .test_overlap( partition_old ) ) if ( partition_new .test_overlap( partition_old ) )
{ {
operationdetail .get_last_child() .add_child( OperationDetail( _("perform readonly test"), STATUS_NONE ) ) ; if ( copy_filesystem_simulation( partition_old, partition_new, operationdetail .get_last_child() ) )
if ( copy_filesystem(
partition_old, partition_new, operationdetail .get_last_child() .get_last_child(), true ) )
{ {
operationdetail .get_last_child() .add_child( operationdetail .get_last_child() .add_child( OperationDetail( _("perform real move") ) ) ;
OperationDetail( _("perform real move"), STATUS_NONE ) ) ;
succes = copy_filesystem( Sector total_done ;
partition_old, partition_new, operationdetail .get_last_child() .get_last_child() ) ; succes = copy_filesystem( partition_old,
partition_new,
operationdetail .get_last_child() .get_last_child(),
total_done ) ;
operationdetail .get_last_child() .get_last_child()
.set_status( succes ? STATUS_SUCCES : STATUS_ERROR ) ;
if ( ! succes )
{
rollback_transaction( partition_old,
partition_new,
operationdetail .get_last_child(),
total_done ) ;
check_repair_filesystem( partition_old, operationdetail ) ;
}
} }
} }
else else
@ -1520,23 +1533,71 @@ bool GParted_Core::copy( const Partition & partition_src,
return false ; return false ;
} }
bool GParted_Core::copy_filesystem_simulation( const Partition & partition_src,
const Partition & partition_dst,
OperationDetail & operationdetail )
{
operationdetail .add_child( OperationDetail( _("perform readonly test") ) ) ;
bool succes = copy_filesystem( partition_src, partition_dst, operationdetail .get_last_child(), true ) ;
operationdetail .get_last_child() .set_status( succes ? STATUS_SUCCES : STATUS_ERROR ) ;
return succes ;
}
bool GParted_Core::copy_filesystem( const Partition & partition_src, bool GParted_Core::copy_filesystem( const Partition & partition_src,
const Partition & partition_dst, const Partition & partition_dst,
OperationDetail & operationdetail, OperationDetail & operationdetail,
bool readonly ) bool readonly )
{ {
operationdetail .add_child( OperationDetail( _("using internal algorithm"), STATUS_NONE ) ) ; Sector dummy ;
return copy_filesystem( partition_src .device_path,
partition_dst .device_path,
partition_src .sector_start,
partition_dst .sector_start,
partition_src .get_length(),
operationdetail,
readonly,
dummy ) ;
}
bool GParted_Core::copy_filesystem( const Partition & partition_src,
const Partition & partition_dst,
OperationDetail & operationdetail,
Sector & total_done )
{
total_done = 0 ;
return copy_filesystem( partition_src .device_path,
partition_dst .device_path,
partition_src .sector_start,
partition_dst .sector_start,
partition_src .get_length(),
operationdetail,
false,
total_done ) ;
}
bool GParted_Core::copy_filesystem( const Glib::ustring & src_device,
const Glib::ustring & dst_device,
Sector src_start,
Sector dst_start,
Sector length,
OperationDetail & operationdetail,
bool readonly,
Sector & total_done )
{
operationdetail .add_child( OperationDetail( _("using internal algorithm"), STATUS_NONE ) ) ;
//FIXME: consider displaying length here and total_done in the end...
operationdetail .add_child( OperationDetail( _("finding optimal blocksize"), STATUS_NONE ) ) ; operationdetail .add_child( OperationDetail( _("finding optimal blocksize"), STATUS_NONE ) ) ;
Sector optimal_blocksize = readonly ? 128 : 64, N = 32768 ; Sector optimal_blocksize = readonly ? 128 : 64, N = 32768 ;
Sector offset_read = partition_src .sector_start, Sector offset_read = src_start,
offset_write = partition_dst .sector_start ; offset_write = dst_start ;
if ( partition_dst .sector_start > partition_src .sector_start ) if ( dst_start > src_start )
{ {
offset_read += (partition_src .get_length() -N) ; offset_read += (length -N) ;
offset_write += (partition_src .get_length() -N) ; offset_write += (length -N) ;
} }
Sector done = 0 ; Sector done = 0 ;
@ -1546,7 +1607,7 @@ bool GParted_Core::copy_filesystem( const Partition & partition_src,
while ( succes && while ( succes &&
timer .elapsed() <= smallest_time && timer .elapsed() <= smallest_time &&
std::abs( done ) + N <= partition_src .get_length() && std::abs( done ) + N <= length &&
optimal_blocksize * 2 < N ) optimal_blocksize * 2 < N )
{ {
if ( done != 0 ) if ( done != 0 )
@ -1556,20 +1617,21 @@ bool GParted_Core::copy_filesystem( const Partition & partition_src,
} }
timer .reset() ; timer .reset() ;
succes = copy_blocks( partition_src .device_path, succes = copy_blocks( src_device,
partition_dst .device_path, dst_device,
offset_read + done, offset_read + done,
offset_write + done, offset_write + done,
N, N,
optimal_blocksize, optimal_blocksize,
operationdetail .get_last_child(), operationdetail .get_last_child(),
readonly) ; readonly,
total_done ) ;
timer.stop() ; timer.stop() ;
operationdetail .get_last_child() .get_last_child() .add_child( OperationDetail( operationdetail .get_last_child() .get_last_child() .add_child( OperationDetail(
String::ucompose( _("%1 seconds"), timer .elapsed() ), STATUS_NONE, FONT_ITALIC ) ) ; String::ucompose( _("%1 seconds"), timer .elapsed() ), STATUS_NONE, FONT_ITALIC ) ) ;
if ( ( partition_dst .sector_start > partition_src .sector_start ) ) if ( ( dst_start > src_start ) )
done -= N ; done -= N ;
else else
done += N ; done += N ;
@ -1585,14 +1647,46 @@ bool GParted_Core::copy_filesystem( const Partition & partition_src,
STATUS_NONE ) ) ; STATUS_NONE ) ) ;
return succes && return succes &&
copy_blocks( partition_src .device_path, copy_blocks( src_device,
partition_dst .device_path, dst_device,
partition_src .sector_start + ( partition_dst .sector_start > partition_src .sector_start ? 0 : done ), src_start + ( dst_start > src_start ? 0 : done ),
partition_dst .sector_start + ( partition_dst .sector_start > partition_src .sector_start ? 0 : done ), dst_start + ( dst_start > src_start ? 0 : done ),
partition_src .get_length() - std::abs( done ), length - std::abs( done ),
optimal_blocksize, optimal_blocksize,
operationdetail, operationdetail,
readonly ) ; readonly,
total_done ) ;
}
void GParted_Core::rollback_transaction( const Partition & partition_src,
const Partition & partition_dst,
OperationDetail & operationdetail,
Sector total_done )
{
if ( total_done > 0 )
{
operationdetail .add_child( OperationDetail( _("rollback last transaction") ) ) ;
//find out exactly which part of the filesystem was copied (and to where it was copied)..
Partition temp_src = partition_src ;
Partition temp_dst = partition_dst ;
if ( partition_dst .sector_start > partition_src .sector_start )
{
temp_src .sector_start = temp_src .sector_end - (total_done-1) ;
temp_dst .sector_start = temp_dst .sector_end - (total_done-1) ;
}
else
{
temp_src .sector_end = temp_src .sector_start + (total_done -1) ;
temp_dst .sector_end = temp_dst .sector_start + (total_done -1) ;
}
//and copy it back (NOTE the reversed dst and src)
bool succes = copy_filesystem( temp_dst, temp_src, operationdetail .get_last_child() ) ;
operationdetail .get_last_child() .set_status( succes ? STATUS_SUCCES : STATUS_ERROR ) ;
}
} }
bool GParted_Core::check_repair_filesystem( const Partition & partition, OperationDetail & operationdetail ) bool GParted_Core::check_repair_filesystem( const Partition & partition, OperationDetail & operationdetail )
@ -1697,7 +1791,8 @@ bool GParted_Core::copy_blocks( const Glib::ustring & src_device,
Sector length, Sector length,
Sector blocksize, Sector blocksize,
OperationDetail & operationdetail, OperationDetail & operationdetail,
bool readonly ) bool readonly,
Sector & total_done )
{ {
if ( blocksize > length ) if ( blocksize > length )
blocksize = length ; blocksize = length ;
@ -1709,7 +1804,6 @@ bool GParted_Core::copy_blocks( const Glib::ustring & src_device,
operationdetail .add_child( OperationDetail( operationdetail .add_child( OperationDetail(
String::ucompose( _("copy %1 sectors using a blocksize of %2 sectors"), length, blocksize ) ) ) ; String::ucompose( _("copy %1 sectors using a blocksize of %2 sectors"), length, blocksize ) ) ) ;
Sector done = length % blocksize ; Sector done = length % blocksize ;
if ( dst_start > src_start ) if ( dst_start > src_start )
@ -1726,13 +1820,12 @@ bool GParted_Core::copy_blocks( const Glib::ustring & src_device,
if ( lp_device_src && lp_device_dst && ped_device_open( lp_device_src ) && ped_device_open( lp_device_dst ) ) if ( lp_device_src && lp_device_dst && ped_device_open( lp_device_src ) && ped_device_open( lp_device_dst ) )
{ {
ped_device_sync( lp_device_dst ) ;
Glib::ustring error_message ; Glib::ustring error_message ;
buf = static_cast<char *>( malloc( std::abs( blocksize ) * 512 ) ) ; buf = static_cast<char *>( malloc( std::abs( blocksize ) * 512 ) ) ;
if ( buf ) if ( buf )
{ {
ped_device_sync( lp_device_dst ) ;
succes = true ; succes = true ;
if ( done != 0 ) if ( done != 0 )
succes = copy_block( lp_device_src, succes = copy_block( lp_device_src,
@ -1742,6 +1835,8 @@ bool GParted_Core::copy_blocks( const Glib::ustring & src_device,
done, done,
error_message, error_message,
readonly ) ; readonly ) ;
if ( ! succes )
done = 0 ;
//add an empty sub which we will constantly update in the loop //add an empty sub which we will constantly update in the loop
operationdetail .get_last_child() .add_child( OperationDetail( "", STATUS_NONE ) ) ; operationdetail .get_last_child() .add_child( OperationDetail( "", STATUS_NONE ) ) ;
@ -1787,6 +1882,8 @@ bool GParted_Core::copy_blocks( const Glib::ustring & src_device,
operationdetail .get_last_child() .add_child( operationdetail .get_last_child() .add_child(
OperationDetail( error_message, STATUS_NONE, FONT_ITALIC ) ) ; OperationDetail( error_message, STATUS_NONE, FONT_ITALIC ) ) ;
total_done += std::abs( done ) ;
//close and destroy the devices.. //close and destroy the devices..
ped_device_close( lp_device_src ) ; ped_device_close( lp_device_src ) ;
ped_device_destroy( lp_device_src ) ; ped_device_destroy( lp_device_src ) ;