Changeset 23458
- Timestamp:
- Mar 20, 2009, 1:24:39 PM (17 years ago)
- Location:
- trunk/Nebulous-Server
- Files:
-
- 2 edited
-
Changes (modified) (1 diff)
-
lib/Nebulous/Server.pm (modified) (10 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Nebulous-Server/Changes
r20155 r23458 1 1 Revision history for Nebulous 2 3 0.17 4 - retry database transactions when a deadlock is detected 2 5 3 6 0.16 -
trunk/Nebulous-Server/lib/Nebulous/Server.pm
r23455 r23458 163 163 164 164 my $uri; 165 eval { 166 { 167 # create storage_object 168 my $query = $db->prepare_cached( $sql->new_object ); 169 $query->execute('NULL', $key->path); 170 } 171 172 my $so_id; 173 { 174 # get object ID 175 my $query = $db->prepare_cached( $sql->last_insert_id ); 176 $query->execute; 177 ($so_id) = $query->fetchrow_array; 178 # XXX finish seems to be required when using LAST_INSERT_ID() or we 179 # get a warning about the stmt handling still be active the next 180 # time LAST_INSERT_ID() is invoked 181 $query->finish; 182 } 183 184 { 185 # create storage_object_attr 186 my $query = $db->prepare_cached( $sql->new_object_attr ); 187 $query->execute($so_id); 188 } 189 190 { 191 192 # create instance with no URI 165 TRANS: do { 166 eval { 167 { 168 # create storage_object 169 my $query = $db->prepare_cached( $sql->new_object ); 170 $query->execute('NULL', $key->path); 171 } 172 173 my $so_id; 174 { 175 # get object ID 176 my $query = $db->prepare_cached( $sql->last_insert_id ); 177 $query->execute; 178 ($so_id) = $query->fetchrow_array; 179 # XXX finish seems to be required when using LAST_INSERT_ID() or we 180 # get a warning about the stmt handling still be active the next 181 # time LAST_INSERT_ID() is invoked 182 $query->finish; 183 } 184 185 { 186 # create storage_object_attr 187 my $query = $db->prepare_cached( $sql->new_object_attr ); 188 $query->execute($so_id); 189 } 190 191 { 192 193 # create instance with no URI 193 194 # my $query = $db->prepare_cached( $sql->new_instance ); 194 my $query = $db->prepare_cached( $sql->new_object_instance );195 $query->execute($vol_id);196 }197 198 my $ins_id;199 {200 # get instance ID201 my $query = $db->prepare_cached( $sql->last_insert_id );202 $query->execute;203 ($ins_id) = $query->fetchrow_array;204 # XXX finish seems to be required when using LAST_INSERT_ID() or we205 # get a warning about the stmt handling still be active the next206 # time LAST_INSERT_ID() is invoked207 $query->finish;208 }209 210 # Unfortunately, since we want to use the instance row's ID as part of the211 # actual on disk file name we can't try to create the file until after212 # we've create both a new storage_storage object and instance.213 214 # TODO add some stuff here to retry if unsucessful215 $uri = $self->_create_empty_instance_file($key->path, $so_id, $ins_id, $vol_path, $vol_xattr);216 $log->debug("created $uri on volume ID: $vol_id");217 218 {219 # update the instance with URI & vol_id that the file is on220 my $query = $db->prepare_cached( $sql->update_instance_uri );221 # vol_id, uri, ins_id222 $query->execute($vol_id, "$uri", $ins_id);223 }224 225 $db->commit;226 $log->debug("commit");227 };228 if ($@) {195 my $query = $db->prepare_cached( $sql->new_object_instance ); 196 $query->execute($vol_id); 197 } 198 199 my $ins_id; 200 { 201 # get instance ID 202 my $query = $db->prepare_cached( $sql->last_insert_id ); 203 $query->execute; 204 ($ins_id) = $query->fetchrow_array; 205 # XXX finish seems to be required when using LAST_INSERT_ID() or we 206 # get a warning about the stmt handling still be active the next 207 # time LAST_INSERT_ID() is invoked 208 $query->finish; 209 } 210 211 # Unfortunately, since we want to use the instance row's ID as part of the 212 # actual on disk file name we can't try to create the file until after 213 # we've create both a new storage_storage object and instance. 214 215 # TODO add some stuff here to retry if unsucessful 216 $uri = $self->_create_empty_instance_file($key->path, $so_id, $ins_id, $vol_path, $vol_xattr); 217 $log->debug("created $uri on volume ID: $vol_id"); 218 219 { 220 # update the instance with URI & vol_id that the file is on 221 my $query = $db->prepare_cached( $sql->update_instance_uri ); 222 # vol_id, uri, ins_id 223 $query->execute($vol_id, "$uri", $ins_id); 224 } 225 226 $db->commit; 227 $log->debug("commit"); 228 }; 229 if ($@) { 229 230 # and not $key->soft_volume 230 $db->rollback; 231 $log->debug("rollback"); 232 $log->logdie("error: $@"); 233 } 231 $db->rollback; 232 $log->debug("rollback"); 233 if ($@ =~ /Deadlock found/) { 234 $log->warn("database deadlock retrying transaction: $@"); 235 redo TRANS; 236 } 237 $log->logdie("error: $@"); 238 } 239 } while ($@); 234 240 235 241 $log->debug("leaving"); … … 269 275 $newkey = parse_neb_key($newkey); 270 276 271 TRANS: do {277 TRANS: do { 272 278 eval { 273 279 # rename storage_object … … 290 296 if ($@ =~ /Deadlock found/) { 291 297 $log->warn("database deadlock retrying transaction: $@"); 292 redo ;298 redo TRANS; 293 299 } 294 300 $log->logdie("database error: $@"); … … 336 342 # key1.swap -> key2 337 343 338 eval { 339 { 340 # key1 -> key1.swap 341 my $query = $db->prepare_cached($sql->rename_object); 342 # this SQL statment takes the new key name as the first param 343 my $rows = $query->execute($key1->path . ".swap", $key1->path); 344 345 # if we affected more then one row something very bad has happened. 346 unless ($rows == 1) { 347 $query->finish; 348 $log->logdie("affected row count is $rows instead of 1"); 349 } 350 } 351 352 { 353 # key2 -> key1 354 my $query = $db->prepare_cached($sql->rename_object); 355 # this SQL statment takes the new key name as the first param 356 my $rows = $query->execute($key1->path, $key2->path); 357 358 # if we affected more then one row something very bad has happened. 359 unless ($rows == 1) { 360 $query->finish; 361 $log->logdie("affected row count is $rows instead of 1"); 362 } 363 } 364 365 { 366 # key1.swap -> key2 367 my $query = $db->prepare_cached($sql->rename_object); 368 # this SQL statment takes the new key name as the first param 369 my $rows = $query->execute($key2->path, $key1->path . ".swap"); 370 371 # if we affected more then one row something very bad has happened. 372 unless ($rows == 1) { 373 $query->finish; 374 $log->logdie("affected row count is $rows instead of 1"); 375 } 376 } 377 378 $db->commit; 379 $log->debug("commit"); 380 }; 381 if ($@) { 382 $db->rollback; 383 $log->debug("rollback"); 384 $log->logdie("database error: $@"); 385 } 344 TRANS: do { 345 eval { 346 { 347 # key1 -> key1.swap 348 my $query = $db->prepare_cached($sql->rename_object); 349 # this SQL statment takes the new key name as the first param 350 my $rows = $query->execute($key1->path . ".swap", $key1->path); 351 352 # if we affected more then one row something very bad has happened. 353 unless ($rows == 1) { 354 $query->finish; 355 $log->logdie("affected row count is $rows instead of 1"); 356 } 357 } 358 359 { 360 # key2 -> key1 361 my $query = $db->prepare_cached($sql->rename_object); 362 # this SQL statment takes the new key name as the first param 363 my $rows = $query->execute($key1->path, $key2->path); 364 365 # if we affected more then one row something very bad has happened. 366 unless ($rows == 1) { 367 $query->finish; 368 $log->logdie("affected row count is $rows instead of 1"); 369 } 370 } 371 372 { 373 # key1.swap -> key2 374 my $query = $db->prepare_cached($sql->rename_object); 375 # this SQL statment takes the new key name as the first param 376 my $rows = $query->execute($key2->path, $key1->path . ".swap"); 377 378 # if we affected more then one row something very bad has happened. 379 unless ($rows == 1) { 380 $query->finish; 381 $log->logdie("affected row count is $rows instead of 1"); 382 } 383 } 384 385 $db->commit; 386 $log->debug("commit"); 387 }; 388 if ($@) { 389 $db->rollback; 390 $log->debug("rollback"); 391 if ($@ =~ /Deadlock found/) { 392 $log->warn("database deadlock retrying transaction: $@"); 393 redo TRANS; 394 } 395 $log->logdie("database error: $@"); 396 } 397 } while ($@); 386 398 387 399 $log->debug("leaving"); … … 454 466 455 467 my $uri; 456 eval { 457 my $so_id; 458 { 459 # verify that at least one instance is currently available 460 my $query = $db->prepare_cached( $sql->get_object_instances ); 461 my $rows = $query->execute($key->path, 1); 462 463 unless ( $rows > 0 ) { 468 TRANS: do { 469 eval { 470 my $so_id; 471 { 472 # verify that at least one instance is currently available 473 my $query = $db->prepare_cached( $sql->get_object_instances ); 474 my $rows = $query->execute($key->path, 1); 475 476 unless ( $rows > 0 ) { 477 $query->finish; 478 $log->logdie( "storage object does not exist" ); 479 } 480 481 $so_id = $query->fetchrow_hashref->{ 'so_id' }; 464 482 $query->finish; 465 $log->logdie( "storage object does not exist" ); 466 } 467 468 $so_id = $query->fetchrow_hashref->{ 'so_id' }; 469 $query->finish; 470 } 471 472 { 473 my $query = $db->prepare_cached( $sql->new_instance ); 474 $query->execute($so_id, $vol_id); 475 } 476 477 my $ins_id; 478 { 479 my $query = $db->prepare_cached( $sql->last_insert_id ); 480 $query->execute(); 481 ($ins_id) = $query->fetchrow_array; 482 # XXX finish seems to be required when using LAST_INSERT_ID() or we 483 # get a warning about the stmt handling still being active the next 484 # time LAST_INSERT_ID() is invoked 485 $query->finish; 486 } 487 488 # Unfortunately, since we want to use the instance row's ID as part of 489 # the actual on disk file name we can't try to create the file until 490 # after we've create both a new storage_storage object and instance. 491 492 # TODO add some stuff here to retry if unsucessful 493 $uri = $self->_create_empty_instance_file($key->path, $so_id, $ins_id, $vol_path, $vol_xattr); 494 495 { 496 my $query = $db->prepare_cached( $sql->update_instance_uri ); 497 # vol_id, uri, ins_id 498 $query->execute($vol_id, $uri, $ins_id); 499 } 500 501 $db->commit; 502 $log->debug("commit"); 503 }; 504 if ($@) { 505 $db->rollback; 506 # handle soft volumes 507 if (defined $vol_name and defined $key->soft_volume) { 508 $log->debug("retrying with 'any' volume"); 509 return $self->replicate_object($key->path, 'any'); 510 } 511 $log->debug("rollback"); 512 $log->logdie("error: $@"); 513 } 483 } 484 485 { 486 my $query = $db->prepare_cached( $sql->new_instance ); 487 $query->execute($so_id, $vol_id); 488 } 489 490 my $ins_id; 491 { 492 my $query = $db->prepare_cached( $sql->last_insert_id ); 493 $query->execute(); 494 ($ins_id) = $query->fetchrow_array; 495 # XXX finish seems to be required when using LAST_INSERT_ID() or we 496 # get a warning about the stmt handling still being active the next 497 # time LAST_INSERT_ID() is invoked 498 $query->finish; 499 } 500 501 # Unfortunately, since we want to use the instance row's ID as part of 502 # the actual on disk file name we can't try to create the file until 503 # after we've create both a new storage_storage object and instance. 504 505 # TODO add some stuff here to retry if unsucessful 506 $uri = $self->_create_empty_instance_file($key->path, $so_id, $ins_id, $vol_path, $vol_xattr); 507 508 { 509 my $query = $db->prepare_cached( $sql->update_instance_uri ); 510 # vol_id, uri, ins_id 511 $query->execute($vol_id, $uri, $ins_id); 512 } 513 514 $db->commit; 515 $log->debug("commit"); 516 }; 517 if ($@) { 518 $db->rollback; 519 # handle soft volumes 520 if (defined $vol_name and defined $key->soft_volume) { 521 $log->debug("retrying with 'any' volume"); 522 return $self->replicate_object($key->path, 'any'); 523 } 524 $log->debug("rollback"); 525 $log->logdie("error: $@"); 526 } 527 } while ($@); 514 528 515 529 $log->debug("leaving"); … … 551 565 my $write_lock; 552 566 553 eval { 554 { 555 # this will set update locks 556 my $query = $db->prepare_cached( $sql->get_object_locks ); 557 my $rows = $query->execute( $key->path ); 558 unless ( $rows == 1 ) { 567 TRANS: do { 568 eval { 569 { 570 # this will set update locks 571 my $query = $db->prepare_cached( $sql->get_object_locks ); 572 my $rows = $query->execute( $key->path ); 573 unless ( $rows == 1 ) { 574 $query->finish; 575 $log->logdie( "storage object does not exist" ); 576 } 577 578 my $row = $query->fetchrow_hashref; 559 579 $query->finish; 560 $log->logdie( "storage object does not exist" ); 561 }562 563 my $row = $query->fetchrow_hashref;564 $query->finish;565 566 $so_id = $row->{ 'so_id' };567 $read_lock = $row->{ 'read_lock' };568 $write_lock = $row->{ 'write_lock' };569 }570 571 if ($type eq 'write') {572 # can't set a write lock twice and573 # can't set a write lock if there are read locks574 if ($write_lock) {575 $log->logdie("can not write lock twice -- retry");576 } 577 578 if ($read_lock > 0) {579 $log->logdie("can not write lock after read lock -- retry");580 }581 582 {583 my $query = $db->prepare_cached( $sql->set_write_lock);584 my $rows = $query->execute($key->path);585 586 # if we affected more then one row something very bad has happened.587 unless ($rows == 1) {588 $log->logdie("affected row count is $rows instead of 1");589 }590 591 }592 } elsif ($type eq 'read') { 593 # can't set a read lock if there's a write lock594 if ($write_lock) {595 $log->logdie("can not read lock after write lock -- retry");596 }597 598 {599 my $query = $db->prepare_cached( $sql->increment_read_lock);600 my $rows = $query->execute($key->path);601 602 # if we affected more then one row something very bad has happened.603 unless ($rows == 1) { 604 $log->logdie("affected row count is $rows instead of 1");605 }606 }607 }608 609 $db->commit;610 $log->debug("commit");611 };612 if ($@) {613 $db->rollback;614 $log->debug("rollback");615 $log->logdie("error: $@");616 } 580 581 $so_id = $row->{ 'so_id' }; 582 $read_lock = $row->{ 'read_lock' }; 583 $write_lock = $row->{ 'write_lock' }; 584 } 585 586 if ($type eq 'write') { 587 # can't set a write lock twice and 588 # can't set a write lock if there are read locks 589 if ($write_lock) { 590 $log->logdie("can not write lock twice -- retry"); 591 } 592 593 if ($read_lock > 0) { 594 $log->logdie("can not write lock after read lock -- retry"); 595 } 596 597 { 598 my $query = $db->prepare_cached( $sql->set_write_lock ); 599 my $rows = $query->execute($key->path); 600 601 # if we affected more then one row something very bad has happened. 602 unless ($rows == 1) { 603 $log->logdie("affected row count is $rows instead of 1"); 604 } 605 606 } 607 } elsif ($type eq 'read') { 608 # can't set a read lock if there's a write lock 609 if ($write_lock) { 610 $log->logdie("can not read lock after write lock -- retry"); 611 } 612 613 { 614 my $query = $db->prepare_cached( $sql->increment_read_lock ); 615 my $rows = $query->execute($key->path); 616 617 # if we affected more then one row something very bad has happened. 618 unless ($rows == 1) { 619 $log->logdie("affected row count is $rows instead of 1"); 620 } 621 } 622 } 623 624 $db->commit; 625 $log->debug("commit"); 626 }; 627 if ($@) { 628 $db->rollback; 629 $log->debug("rollback"); 630 if ($@ =~ /Deadlock found/) { 631 $log->warn("database deadlock retrying transaction: $@"); 632 redo TRANS; 633 } 634 $log->logdie("error: $@"); 635 } 636 } while ($@); 617 637 618 638 $log->debug("leaving"); … … 654 674 my $write_lock; 655 675 656 eval { 657 { 658 # this will set update locks 659 my $query = $db->prepare_cached( $sql->get_object_locks ); 660 my $rows = $query->execute($key->path); 661 unless ($rows == 1) { 676 TRANS: do { 677 eval { 678 { 679 # this will set update locks 680 my $query = $db->prepare_cached( $sql->get_object_locks ); 681 my $rows = $query->execute($key->path); 682 unless ($rows == 1) { 683 $query->finish; 684 $log->logdie("storage object does not exist"); 685 } 686 687 my $row = $query->fetchrow_hashref; 662 688 $query->finish; 663 $log->logdie("storage object does not exist"); 664 }665 666 my $row = $query->fetchrow_hashref;667 $query->finish;668 669 $so_id = $row->{ 'so_id' };670 $read_lock = $row->{ 'read_lock' };671 $write_lock = $row->{ 'write_lock' };672 }673 674 if ($type eq 'write') { 675 # can't remove a write lock if it doesn't exist676 if ($read_lock) {677 $log->logdie("can not have a write lock under a read lock");678 } 679 680 unless ($write_lock) {681 $log->logdie("can not remove non-existant write lock");682 }683 684 {685 my $query = $db->prepare_cached( $sql->delete_write_lock);686 my $rows = $query->execute($key->path);687 688 # if we affected more then one row something very bad has happened.689 unless ($rows == 1) {690 $log->logdie("affected row count is $rows instead of 1");691 }692 }693 } elsif ($type eq 'read') {694 # can't remove a read lock if there's a write lock and695 # can't remove a read lock if there aren't any696 if ($write_lock) {697 $log->logdie("can not have a read lock under a write lock");698 } 699 700 if ($read_lock == 0) {701 $log->logdie("can not remove non-existant read lock");702 }703 704 {705 my $query = $db->prepare_cached( $sql->decrement_read_lock);706 my $rows = $query->execute($key->path);707 708 # if we affected more then one row something very bad has happened.709 unless ($rows == 1) {710 $log->logdie("affected row count is $rows instead of 1");711 }712 713 }714 }715 $db->commit;716 $log->debug("commit");717 };718 if ($@) {719 $db->rollback;720 $log->debug("rollback");721 $log->logdie("error: $@");722 } 689 690 $so_id = $row->{ 'so_id' }; 691 $read_lock = $row->{ 'read_lock' }; 692 $write_lock = $row->{ 'write_lock' }; 693 } 694 695 if ($type eq 'write') { 696 # can't remove a write lock if it doesn't exist 697 if ($read_lock) { 698 $log->logdie("can not have a write lock under a read lock"); 699 } 700 701 unless ($write_lock) { 702 $log->logdie("can not remove non-existant write lock"); 703 } 704 705 { 706 my $query = $db->prepare_cached( $sql->delete_write_lock ); 707 my $rows = $query->execute($key->path); 708 709 # if we affected more then one row something very bad has happened. 710 unless ($rows == 1) { 711 $log->logdie("affected row count is $rows instead of 1"); 712 } 713 } 714 } elsif ($type eq 'read') { 715 # can't remove a read lock if there's a write lock and 716 # can't remove a read lock if there aren't any 717 if ($write_lock) { 718 $log->logdie("can not have a read lock under a write lock"); 719 } 720 721 if ($read_lock == 0) { 722 $log->logdie("can not remove non-existant read lock"); 723 } 724 725 { 726 my $query = $db->prepare_cached( $sql->decrement_read_lock ); 727 my $rows = $query->execute($key->path); 728 729 # if we affected more then one row something very bad has happened. 730 unless ($rows == 1) { 731 $log->logdie("affected row count is $rows instead of 1"); 732 } 733 734 } 735 } 736 $db->commit; 737 $log->debug("commit"); 738 }; 739 if ($@) { 740 $db->rollback; 741 $log->debug("rollback"); 742 if ($@ =~ /Deadlock found/) { 743 $log->warn("database deadlock retrying transaction: $@"); 744 redo TRANS; 745 } 746 $log->logdie("error: $@"); 747 } 748 } while ($@); 723 749 724 750 $log->debug( "leaving" ); … … 762 788 $key = parse_neb_key($key); 763 789 764 eval { 765 my $query; 766 767 if ($flags eq 'create') { 768 $query = $db->prepare_cached( $sql->new_object_xattr ); 769 } else { 770 # replace 771 $query = $db->prepare_cached( $sql->replace_object_xattr ); 772 } 773 774 # name, value, ext_id 775 my $rows = $query->execute($name, $value, $key->path); 776 $query->finish; 777 778 # if we affected more then one row something very bad has happened. 779 if ($flags eq 'create') { 780 unless ($rows == 1) { 781 $log->logdie( "affected row count is $rows instead of 1" ); 782 } 783 } else { 784 # replace_object_xattr can effect either 1 or 2 rows. 2 rows in 785 # the case of a replace and 1 if the xattr didn't already exist. 786 unless ($rows == 1 or $rows == 2) { 787 $log->logdie( "affected row count is $rows instead of 2" ); 788 } 789 } 790 791 $db->commit; 792 $log->debug("commit"); 793 }; 794 if ($@) { 795 $db->rollback; 796 $log->debug("rollback"); 797 $log->logdie("database error: $@"); 798 } 790 TRANS: do { 791 eval { 792 my $query; 793 794 if ($flags eq 'create') { 795 $query = $db->prepare_cached( $sql->new_object_xattr ); 796 } else { 797 # replace 798 $query = $db->prepare_cached( $sql->replace_object_xattr ); 799 } 800 801 # name, value, ext_id 802 my $rows = $query->execute($name, $value, $key->path); 803 $query->finish; 804 805 # if we affected more then one row something very bad has happened. 806 if ($flags eq 'create') { 807 unless ($rows == 1) { 808 $log->logdie( "affected row count is $rows instead of 1" ); 809 } 810 } else { 811 # replace_object_xattr can effect either 1 or 2 rows. 2 rows in 812 # the case of a replace and 1 if the xattr didn't already exist. 813 unless ($rows == 1 or $rows == 2) { 814 $log->logdie( "affected row count is $rows instead of 2" ); 815 } 816 } 817 818 $db->commit; 819 $log->debug("commit"); 820 }; 821 if ($@) { 822 $db->rollback; 823 $log->debug("rollback"); 824 if ($@ =~ /Deadlock found/) { 825 $log->warn("database deadlock retrying transaction: $@"); 826 redo TRANS; 827 } 828 $log->logdie("database error: $@"); 829 } 830 } while ($@); 799 831 800 832 $log->debug("leaving"); … … 925 957 $key = parse_neb_key($key); 926 958 927 eval { 928 my $query = $db->prepare_cached( $sql->remove_object_xattr ); 929 # ext_id, name 930 my $rows = $query->execute($key->path, $name); 931 $query->finish; 932 933 # if we affected more then one row something very bad has happened. 934 unless ($rows == 1) { 935 $log->logdie( "affected row count is $rows instead of 1" ); 936 } 937 938 $db->commit; 939 $log->debug("commit"); 940 }; 941 if ($@) { 942 $db->rollback; 943 $log->debug("rollback"); 944 $log->logdie("database error: $@"); 945 } 959 TRANS: do { 960 eval { 961 my $query = $db->prepare_cached( $sql->remove_object_xattr ); 962 # ext_id, name 963 my $rows = $query->execute($key->path, $name); 964 $query->finish; 965 966 # if we affected more then one row something very bad has happened. 967 unless ($rows == 1) { 968 $log->logdie( "affected row count is $rows instead of 1" ); 969 } 970 971 $db->commit; 972 $log->debug("commit"); 973 }; 974 if ($@) { 975 $db->rollback; 976 $log->debug("rollback"); 977 if ($@ =~ /Deadlock found/) { 978 $log->warn("database deadlock retrying transaction: $@"); 979 redo TRANS; 980 } 981 $log->logdie("database error: $@"); 982 } 983 } while ($@); 946 984 947 985 $log->debug("leaving"); … … 1105 1143 $log->debug( "entered - @_" ); 1106 1144 1107 eval { 1108 my $so_id; 1109 my $instances; 1110 # get so_id 1111 { 1112 my $query = $db->prepare_cached( $sql->get_object_from_uri ); 1113 my $rows = $query->execute( $uri ); 1114 1115 unless ( $rows > 0 ) { 1145 TRANS: do { 1146 eval { 1147 my $so_id; 1148 my $instances; 1149 # get so_id 1150 { 1151 my $query = $db->prepare_cached( $sql->get_object_from_uri ); 1152 my $rows = $query->execute( $uri ); 1153 1154 unless ( $rows > 0 ) { 1155 $query->finish; 1156 $log->logdie( "no instance is associated with uri" ); 1157 } 1158 1159 $so_id = $query->fetchrow_hashref->{ 'so_id' }; 1116 1160 $query->finish; 1117 $log->logdie( "no instance is associated with uri" ); 1118 } 1119 1120 $so_id = $query->fetchrow_hashref->{ 'so_id' };1121 $query->finish;1122 1123 } 1124 1125 {1126 my $query = $db->prepare_cached( $sql->get_instance_count );1127 $query->execute( $so_id ); 1128 1129 $instances = $query->fetchrow_hashref->{ 'count(ins_id)' };1130 $query->finish;1131 }1132 1133 # remove instance1134 {1135 my $query = $db->prepare_cached( $sql->delete_instance );1136 my $rows = $query->execute( $uri );1137 $query->finish;1138 1139 # if we affected something other then two rows something very bad1140 # has happened 1141 unless ( $rows == 1 ) {1142 $log->logdie( "affected row count is $rows instead of 1" );1143 }1144 }1145 1146 # if we just deleted the last instance associated with a storage object1147 # remove it too1148 if ( $instances == 1 ) { 1149 # we just removed the last instance1150 my $query = $db->prepare_cached( $sql->delete_object );1151 my $rows = $query->execute( $so_id);1152 $query->finish;1153 1154 # TODO: this will have to be changed in order to support hardlinks 1155 unless ( $rows == 1 ) {1156 $log->logdie( "affected row count is $rows instead of 2");1157 }1158 }1159 1160 $db->commit;1161 $log->debug("commit");1162 };1163 if ( $@ ) {1164 $db->rollback;1165 $log->debug("rollback");1166 $log->logdie( "database error: $@" );1167 } 1161 1162 } 1163 1164 { 1165 my $query = $db->prepare_cached( $sql->get_instance_count ); 1166 $query->execute( $so_id ); 1167 1168 $instances = $query->fetchrow_hashref->{ 'count(ins_id)' }; 1169 $query->finish; 1170 } 1171 1172 # remove instance 1173 { 1174 my $query = $db->prepare_cached( $sql->delete_instance ); 1175 my $rows = $query->execute( $uri ); 1176 $query->finish; 1177 1178 # if we affected something other then two rows something very bad 1179 # has happened 1180 unless ( $rows == 1 ) { 1181 $log->logdie( "affected row count is $rows instead of 1" ); 1182 } 1183 } 1184 1185 # if we just deleted the last instance associated with a storage object 1186 # remove it too 1187 if ( $instances == 1 ) { 1188 # we just removed the last instance 1189 my $query = $db->prepare_cached( $sql->delete_object ); 1190 my $rows = $query->execute( $so_id ); 1191 $query->finish; 1192 1193 # TODO: this will have to be changed in order to support hardlinks 1194 unless ( $rows == 1 ) { 1195 $log->logdie( "affected row count is $rows instead of 2" ); 1196 } 1197 } 1198 1199 $db->commit; 1200 $log->debug("commit"); 1201 }; 1202 if ( $@ ) { 1203 $db->rollback; 1204 $log->debug("rollback"); 1205 if ($@ =~ /Deadlock found/) { 1206 $log->warn("database deadlock retrying transaction: $@"); 1207 redo TRANS; 1208 } 1209 $log->logdie( "database error: $@" ); 1210 } 1211 } while ($@); 1168 1212 1169 1213 $log->debug( "leaving" );
Note:
See TracChangeset
for help on using the changeset viewer.
