- Timestamp:
- Mar 29, 2009, 6:15:31 PM (17 years ago)
- Location:
- branches/cnb_branches/cnb_branch_20090301
- Files:
-
- 4 edited
-
. (modified) (1 prop)
-
Nebulous-Server/Changes (modified) (1 diff)
-
Nebulous-Server/bin/neb-admin (modified) (2 diffs)
-
Nebulous-Server/lib/Nebulous/Server.pm (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/cnb_branches/cnb_branch_20090301
-
branches/cnb_branches/cnb_branch_20090301/Nebulous-Server/Changes
r20155 r23594 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 -
branches/cnb_branches/cnb_branch_20090301/Nebulous-Server/bin/neb-admin
r23352 r23594 152 152 153 153 exit unless scalar @rows; 154 155 # compare number of responses to limit below 156 my $Npending = @rows; 154 157 155 158 print "replicatePending MULTI\n\n"; … … 198 201 } 199 202 200 return 1; 203 # use a different exit status if we hit the limit (likely more files pending) 204 if ($Npending == $limit) { 205 exit 1; 206 } 207 exit 0; 201 208 } 202 203 209 204 210 sub removal -
branches/cnb_branches/cnb_branch_20090301/Nebulous-Server/lib/Nebulous/Server.pm
r20990 r23594 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: while (1) { 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: $@"); 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 last; 233 240 } 234 241 … … 269 276 $newkey = parse_neb_key($newkey); 270 277 271 eval { 272 # rename storage_object 273 my $query = $db->prepare_cached($sql->rename_object); 274 # this SQL statment takes the new key name as the first param 275 my $rows = $query->execute($newkey->path, $key->path); 276 277 # if we affected more then one row something very bad has happened. 278 unless ($rows == 1) { 279 $query->finish; 280 $log->logdie("affected row count is $rows instead of 1"); 281 } 282 283 $db->commit; 284 $log->debug("commit"); 285 }; 286 if ($@) { 287 $db->rollback; 288 $log->debug("rollback"); 289 $log->logdie("database error: $@"); 290 } 278 TRANS: while (1) { 279 eval { 280 # rename storage_object 281 my $query = $db->prepare_cached($sql->rename_object); 282 # this SQL statment takes the new key name as the first param 283 my $rows = $query->execute($newkey->path, $key->path); 284 285 # if we affected more then one row something very bad has happened. 286 unless ($rows == 1) { 287 $query->finish; 288 $log->logdie("affected row count is $rows instead of 1"); 289 } 290 291 $db->commit; 292 $log->debug("commit"); 293 }; 294 if ($@) { 295 $db->rollback; 296 $log->debug("rollback"); 297 if ($@ =~ /Deadlock found/) { 298 $log->warn("database deadlock retrying transaction: $@"); 299 redo TRANS; 300 } 301 $log->logdie("database error: $@"); 302 } 303 last; 304 } 291 305 292 306 $log->debug("leaving"); … … 330 344 # key1.swap -> key2 331 345 332 eval { 333 { 334 # key1 -> key1.swap 335 my $query = $db->prepare_cached($sql->rename_object); 336 # this SQL statment takes the new key name as the first param 337 my $rows = $query->execute($key1->path . ".swap", $key1->path); 338 339 # if we affected more then one row something very bad has happened. 340 unless ($rows == 1) { 341 $query->finish; 342 $log->logdie("affected row count is $rows instead of 1"); 343 } 344 } 345 346 { 347 # key2 -> key1 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, $key2->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 # key1.swap -> key2 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($key2->path, $key1->path . ".swap"); 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 $db->commit; 373 $log->debug("commit"); 374 }; 375 if ($@) { 376 $db->rollback; 377 $log->debug("rollback"); 378 $log->logdie("database error: $@"); 346 TRANS: while (1) { 347 eval { 348 { 349 # key1 -> key1.swap 350 my $query = $db->prepare_cached($sql->rename_object); 351 # this SQL statment takes the new key name as the first param 352 my $rows = $query->execute($key1->path . ".swap", $key1->path); 353 354 # if we affected more then one row something very bad has happened. 355 unless ($rows == 1) { 356 $query->finish; 357 $log->logdie("affected row count is $rows instead of 1"); 358 } 359 } 360 361 { 362 # key2 -> key1 363 my $query = $db->prepare_cached($sql->rename_object); 364 # this SQL statment takes the new key name as the first param 365 my $rows = $query->execute($key1->path, $key2->path); 366 367 # if we affected more then one row something very bad has happened. 368 unless ($rows == 1) { 369 $query->finish; 370 $log->logdie("affected row count is $rows instead of 1"); 371 } 372 } 373 374 { 375 # key1.swap -> key2 376 my $query = $db->prepare_cached($sql->rename_object); 377 # this SQL statment takes the new key name as the first param 378 my $rows = $query->execute($key2->path, $key1->path . ".swap"); 379 380 # if we affected more then one row something very bad has happened. 381 unless ($rows == 1) { 382 $query->finish; 383 $log->logdie("affected row count is $rows instead of 1"); 384 } 385 } 386 387 $db->commit; 388 $log->debug("commit"); 389 }; 390 if ($@) { 391 $db->rollback; 392 $log->debug("rollback"); 393 if ($@ =~ /Deadlock found/) { 394 $log->warn("database deadlock retrying transaction: $@"); 395 redo TRANS; 396 } 397 $log->logdie("database error: $@"); 398 } 399 last; 379 400 } 380 401 … … 448 469 449 470 my $uri; 450 eval { 451 my $so_id; 452 { 453 # verify that at least one instance is currently available 454 my $query = $db->prepare_cached( $sql->get_object_instances ); 455 my $rows = $query->execute($key->path, 1); 456 457 unless ( $rows > 0 ) { 471 TRANS: while (1) { 472 eval { 473 my $so_id; 474 { 475 # verify that at least one instance is currently available 476 my $query = $db->prepare_cached( $sql->get_object_instances ); 477 my $rows = $query->execute($key->path, 1); 478 479 unless ( $rows > 0 ) { 480 $query->finish; 481 $log->logdie( "storage object does not exist" ); 482 } 483 484 $so_id = $query->fetchrow_hashref->{ 'so_id' }; 458 485 $query->finish; 459 $log->logdie( "storage object does not exist" ); 460 } 461 462 $so_id = $query->fetchrow_hashref->{ 'so_id' }; 463 $query->finish; 464 } 465 466 { 467 my $query = $db->prepare_cached( $sql->new_instance ); 468 $query->execute($so_id, $vol_id); 469 } 470 471 my $ins_id; 472 { 473 my $query = $db->prepare_cached( $sql->last_insert_id ); 474 $query->execute(); 475 ($ins_id) = $query->fetchrow_array; 476 # XXX finish seems to be required when using LAST_INSERT_ID() or we 477 # get a warning about the stmt handling still being active the next 478 # time LAST_INSERT_ID() is invoked 479 $query->finish; 480 } 481 482 # Unfortunately, since we want to use the instance row's ID as part of 483 # the actual on disk file name we can't try to create the file until 484 # after we've create both a new storage_storage object and instance. 485 486 # TODO add some stuff here to retry if unsucessful 487 $uri = $self->_create_empty_instance_file($key->path, $so_id, $ins_id, $vol_path, $vol_xattr); 488 489 { 490 my $query = $db->prepare_cached( $sql->update_instance_uri ); 491 # vol_id, uri, ins_id 492 $query->execute($vol_id, $uri, $ins_id); 493 } 494 495 $db->commit; 496 $log->debug("commit"); 497 }; 498 if ($@) { 499 $db->rollback; 500 # handle soft volumes 501 if (defined $vol_name and defined $key->soft_volume) { 502 $log->debug("retrying with 'any' volume"); 503 return $self->replicate_object($key->path, 'any'); 504 } 505 $log->debug("rollback"); 506 $log->logdie("error: $@"); 486 } 487 488 { 489 my $query = $db->prepare_cached( $sql->new_instance ); 490 $query->execute($so_id, $vol_id); 491 } 492 493 my $ins_id; 494 { 495 my $query = $db->prepare_cached( $sql->last_insert_id ); 496 $query->execute(); 497 ($ins_id) = $query->fetchrow_array; 498 # XXX finish seems to be required when using LAST_INSERT_ID() or we 499 # get a warning about the stmt handling still being active the next 500 # time LAST_INSERT_ID() is invoked 501 $query->finish; 502 } 503 504 # Unfortunately, since we want to use the instance row's ID as part of 505 # the actual on disk file name we can't try to create the file until 506 # after we've create both a new storage_storage object and instance. 507 508 # TODO add some stuff here to retry if unsucessful 509 $uri = $self->_create_empty_instance_file($key->path, $so_id, $ins_id, $vol_path, $vol_xattr); 510 511 { 512 my $query = $db->prepare_cached( $sql->update_instance_uri ); 513 # vol_id, uri, ins_id 514 $query->execute($vol_id, $uri, $ins_id); 515 } 516 517 $db->commit; 518 $log->debug("commit"); 519 }; 520 if ($@) { 521 $db->rollback; 522 # handle soft volumes 523 if (defined $vol_name and defined $key->soft_volume) { 524 $log->debug("retrying with 'any' volume"); 525 return $self->replicate_object($key->path, 'any'); 526 } 527 $log->debug("rollback"); 528 if ($@ =~ /Deadlock found/) { 529 $log->warn("database deadlock retrying transaction: $@"); 530 redo TRANS; 531 } 532 $log->logdie("error: $@"); 533 } 534 last; 507 535 } 508 536 … … 545 573 my $write_lock; 546 574 547 eval { 548 { 549 # this will set update locks 550 my $query = $db->prepare_cached( $sql->get_object_locks ); 551 my $rows = $query->execute( $key->path ); 552 unless ( $rows == 1 ) { 575 TRANS: while (1) { 576 eval { 577 { 578 # this will set update locks 579 my $query = $db->prepare_cached( $sql->get_object_locks ); 580 my $rows = $query->execute( $key->path ); 581 unless ( $rows == 1 ) { 582 $query->finish; 583 $log->logdie( "storage object does not exist" ); 584 } 585 586 my $row = $query->fetchrow_hashref; 553 587 $query->finish; 554 $log->logdie( "storage object does not exist" ); 555 } 556 557 my $row = $query->fetchrow_hashref; 558 $query->finish; 559 560 $so_id = $row->{ 'so_id' }; 561 $read_lock = $row->{ 'read_lock' }; 562 $write_lock = $row->{ 'write_lock' }; 563 } 564 565 if ($type eq 'write') { 566 # can't set a write lock twice and 567 # can't set a write lock if there are read locks 568 if ($write_lock) { 569 $log->logdie("can not write lock twice -- retry"); 570 } 571 572 if ($read_lock > 0) { 573 $log->logdie("can not write lock after read lock -- retry"); 574 } 575 576 { 577 my $query = $db->prepare_cached( $sql->set_write_lock ); 578 my $rows = $query->execute($key->path); 579 580 # if we affected more then one row something very bad has happened. 581 unless ($rows == 1) { 582 $log->logdie("affected row count is $rows instead of 1"); 583 } 584 585 } 586 } elsif ($type eq 'read') { 587 # can't set a read lock if there's a write lock 588 if ($write_lock) { 589 $log->logdie("can not read lock after write lock -- retry"); 590 } 591 592 { 593 my $query = $db->prepare_cached( $sql->increment_read_lock ); 594 my $rows = $query->execute($key->path); 595 596 # if we affected more then one row something very bad has happened. 597 unless ($rows == 1) { 598 $log->logdie("affected row count is $rows instead of 1"); 599 } 600 } 601 } 602 603 $db->commit; 604 $log->debug("commit"); 605 }; 606 if ($@) { 607 $db->rollback; 608 $log->debug("rollback"); 609 $log->logdie("error: $@"); 588 589 $so_id = $row->{ 'so_id' }; 590 $read_lock = $row->{ 'read_lock' }; 591 $write_lock = $row->{ 'write_lock' }; 592 } 593 594 if ($type eq 'write') { 595 # can't set a write lock twice and 596 # can't set a write lock if there are read locks 597 if ($write_lock) { 598 $log->logdie("can not write lock twice -- retry"); 599 } 600 601 if ($read_lock > 0) { 602 $log->logdie("can not write lock after read lock -- retry"); 603 } 604 605 { 606 my $query = $db->prepare_cached( $sql->set_write_lock ); 607 my $rows = $query->execute($key->path); 608 609 # if we affected more then one row something very bad has happened. 610 unless ($rows == 1) { 611 $log->logdie("affected row count is $rows instead of 1"); 612 } 613 614 } 615 } elsif ($type eq 'read') { 616 # can't set a read lock if there's a write lock 617 if ($write_lock) { 618 $log->logdie("can not read lock after write lock -- retry"); 619 } 620 621 { 622 my $query = $db->prepare_cached( $sql->increment_read_lock ); 623 my $rows = $query->execute($key->path); 624 625 # if we affected more then one row something very bad has happened. 626 unless ($rows == 1) { 627 $log->logdie("affected row count is $rows instead of 1"); 628 } 629 } 630 } 631 632 $db->commit; 633 $log->debug("commit"); 634 }; 635 if ($@) { 636 $db->rollback; 637 $log->debug("rollback"); 638 if ($@ =~ /Deadlock found/) { 639 $log->warn("database deadlock retrying transaction: $@"); 640 redo TRANS; 641 } 642 $log->logdie("error: $@"); 643 } 644 last; 610 645 } 611 646 … … 648 683 my $write_lock; 649 684 650 eval { 651 { 652 # this will set update locks 653 my $query = $db->prepare_cached( $sql->get_object_locks ); 654 my $rows = $query->execute($key->path); 655 unless ($rows == 1) { 685 TRANS: while (1) { 686 eval { 687 { 688 # this will set update locks 689 my $query = $db->prepare_cached( $sql->get_object_locks ); 690 my $rows = $query->execute($key->path); 691 unless ($rows == 1) { 692 $query->finish; 693 $log->logdie("storage object does not exist"); 694 } 695 696 my $row = $query->fetchrow_hashref; 656 697 $query->finish; 657 $log->logdie("storage object does not exist"); 658 } 659 660 my $row = $query->fetchrow_hashref; 661 $query->finish; 662 663 $so_id = $row->{ 'so_id' }; 664 $read_lock = $row->{ 'read_lock' }; 665 $write_lock = $row->{ 'write_lock' }; 666 } 667 668 if ($type eq 'write') { 669 # can't remove a write lock if it doesn't exist 670 if ($read_lock) { 671 $log->logdie("can not have a write lock under a read lock"); 672 } 673 674 unless ($write_lock) { 675 $log->logdie("can not remove non-existant write lock"); 676 } 677 678 { 679 my $query = $db->prepare_cached( $sql->delete_write_lock ); 680 my $rows = $query->execute($key->path); 681 682 # if we affected more then one row something very bad has happened. 683 unless ($rows == 1) { 684 $log->logdie("affected row count is $rows instead of 1"); 685 } 686 } 687 } elsif ($type eq 'read') { 688 # can't remove a read lock if there's a write lock and 689 # can't remove a read lock if there aren't any 690 if ($write_lock) { 691 $log->logdie("can not have a read lock under a write lock"); 692 } 693 694 if ($read_lock == 0) { 695 $log->logdie("can not remove non-existant read lock"); 696 } 697 698 { 699 my $query = $db->prepare_cached( $sql->decrement_read_lock ); 700 my $rows = $query->execute($key->path); 701 702 # if we affected more then one row something very bad has happened. 703 unless ($rows == 1) { 704 $log->logdie("affected row count is $rows instead of 1"); 705 } 706 707 } 708 } 709 $db->commit; 710 $log->debug("commit"); 711 }; 712 if ($@) { 713 $db->rollback; 714 $log->debug("rollback"); 715 $log->logdie("error: $@"); 698 699 $so_id = $row->{ 'so_id' }; 700 $read_lock = $row->{ 'read_lock' }; 701 $write_lock = $row->{ 'write_lock' }; 702 } 703 704 if ($type eq 'write') { 705 # can't remove a write lock if it doesn't exist 706 if ($read_lock) { 707 $log->logdie("can not have a write lock under a read lock"); 708 } 709 710 unless ($write_lock) { 711 $log->logdie("can not remove non-existant write lock"); 712 } 713 714 { 715 my $query = $db->prepare_cached( $sql->delete_write_lock ); 716 my $rows = $query->execute($key->path); 717 718 # if we affected more then one row something very bad has happened. 719 unless ($rows == 1) { 720 $log->logdie("affected row count is $rows instead of 1"); 721 } 722 } 723 } elsif ($type eq 'read') { 724 # can't remove a read lock if there's a write lock and 725 # can't remove a read lock if there aren't any 726 if ($write_lock) { 727 $log->logdie("can not have a read lock under a write lock"); 728 } 729 730 if ($read_lock == 0) { 731 $log->logdie("can not remove non-existant read lock"); 732 } 733 734 { 735 my $query = $db->prepare_cached( $sql->decrement_read_lock ); 736 my $rows = $query->execute($key->path); 737 738 # if we affected more then one row something very bad has happened. 739 unless ($rows == 1) { 740 $log->logdie("affected row count is $rows instead of 1"); 741 } 742 743 } 744 } 745 $db->commit; 746 $log->debug("commit"); 747 }; 748 if ($@) { 749 $db->rollback; 750 $log->debug("rollback"); 751 if ($@ =~ /Deadlock found/) { 752 $log->warn("database deadlock retrying transaction: $@"); 753 redo TRANS; 754 } 755 $log->logdie("error: $@"); 756 } 757 last; 716 758 } 717 759 … … 756 798 $key = parse_neb_key($key); 757 799 758 eval { 759 my $query; 760 761 if ($flags eq 'create') { 762 $query = $db->prepare_cached( $sql->new_object_xattr ); 763 } else { 764 # replace 765 $query = $db->prepare_cached( $sql->replace_object_xattr ); 766 } 767 768 # name, value, ext_id 769 my $rows = $query->execute($name, $value, $key->path); 770 $query->finish; 771 772 # if we affected more then one row something very bad has happened. 773 if ($flags eq 'create') { 774 unless ($rows == 1) { 775 $log->logdie( "affected row count is $rows instead of 1" ); 776 } 777 } else { 778 # replace_object_xattr can effect either 1 or 2 rows. 2 rows in 779 # the case of a replace and 1 if the xattr didn't already exist. 780 unless ($rows == 1 or $rows == 2) { 781 $log->logdie( "affected row count is $rows instead of 2" ); 782 } 783 } 784 785 $db->commit; 786 $log->debug("commit"); 787 }; 788 if ($@) { 789 $db->rollback; 790 $log->debug("rollback"); 791 $log->logdie("database error: $@"); 800 TRANS: while (1) { 801 eval { 802 my $query; 803 804 if ($flags eq 'create') { 805 $query = $db->prepare_cached( $sql->new_object_xattr ); 806 } else { 807 # replace 808 $query = $db->prepare_cached( $sql->replace_object_xattr ); 809 } 810 811 # name, value, ext_id 812 my $rows = $query->execute($name, $value, $key->path); 813 $query->finish; 814 815 # if we affected more then one row something very bad has happened. 816 if ($flags eq 'create') { 817 unless ($rows == 1) { 818 $log->logdie( "affected row count is $rows instead of 1" ); 819 } 820 } else { 821 # replace_object_xattr can effect either 1 or 2 rows. 2 rows in 822 # the case of a replace and 1 if the xattr didn't already exist. 823 unless ($rows == 1 or $rows == 2) { 824 $log->logdie( "affected row count is $rows instead of 2" ); 825 } 826 } 827 828 $db->commit; 829 $log->debug("commit"); 830 }; 831 if ($@) { 832 $db->rollback; 833 $log->debug("rollback"); 834 if ($@ =~ /Deadlock found/) { 835 $log->warn("database deadlock retrying transaction: $@"); 836 redo TRANS; 837 } 838 $log->logdie("database error: $@"); 839 } 840 last; 792 841 } 793 842 … … 919 968 $key = parse_neb_key($key); 920 969 921 eval { 922 my $query = $db->prepare_cached( $sql->remove_object_xattr ); 923 # ext_id, name 924 my $rows = $query->execute($key->path, $name); 925 $query->finish; 926 927 # if we affected more then one row something very bad has happened. 928 unless ($rows == 1) { 929 $log->logdie( "affected row count is $rows instead of 1" ); 930 } 931 932 $db->commit; 933 $log->debug("commit"); 934 }; 935 if ($@) { 936 $db->rollback; 937 $log->debug("rollback"); 938 $log->logdie("database error: $@"); 939 } 970 TRANS: while (1) { 971 eval { 972 my $query = $db->prepare_cached( $sql->remove_object_xattr ); 973 # ext_id, name 974 my $rows = $query->execute($key->path, $name); 975 $query->finish; 976 977 # if we affected more then one row something very bad has happened. 978 unless ($rows == 1) { 979 $log->logdie( "affected row count is $rows instead of 1" ); 980 } 981 982 $db->commit; 983 $log->debug("commit"); 984 }; 985 if ($@) { 986 $db->rollback; 987 $log->debug("rollback"); 988 if ($@ =~ /Deadlock found/) { 989 $log->warn("database deadlock retrying transaction: $@"); 990 redo TRANS; 991 } 992 $log->logdie("database error: $@"); 993 } 994 last; 995 } 940 996 941 997 $log->debug("leaving"); … … 1099 1155 $log->debug( "entered - @_" ); 1100 1156 1101 eval { 1102 my $so_id; 1103 my $instances; 1104 # get so_id 1105 { 1106 my $query = $db->prepare_cached( $sql->get_object_from_uri ); 1107 my $rows = $query->execute( $uri ); 1108 1109 unless ( $rows > 0 ) { 1157 TRANS: while (1) { 1158 eval { 1159 my $so_id; 1160 my $instances; 1161 # get so_id 1162 { 1163 my $query = $db->prepare_cached( $sql->get_object_from_uri ); 1164 my $rows = $query->execute( $uri ); 1165 1166 unless ( $rows > 0 ) { 1167 $query->finish; 1168 $log->logdie( "no instance is associated with uri" ); 1169 } 1170 1171 $so_id = $query->fetchrow_hashref->{ 'so_id' }; 1110 1172 $query->finish; 1111 $log->logdie( "no instance is associated with uri" ); 1112 } 1113 1114 $so_id = $query->fetchrow_hashref->{ 'so_id' }; 1115 $query->finish; 1116 1117 } 1118 1119 { 1120 my $query = $db->prepare_cached( $sql->get_instance_count ); 1121 $query->execute( $so_id ); 1122 1123 $instances = $query->fetchrow_hashref->{ 'count(ins_id)' }; 1124 $query->finish; 1125 } 1126 1127 # remove instance 1128 { 1129 my $query = $db->prepare_cached( $sql->delete_instance ); 1130 my $rows = $query->execute( $uri ); 1131 $query->finish; 1132 1133 # if we affected something other then two rows something very bad 1134 # has happened 1135 unless ( $rows == 1 ) { 1136 $log->logdie( "affected row count is $rows instead of 1" ); 1137 } 1138 } 1139 1140 # if we just deleted the last instance associated with a storage object 1141 # remove it too 1142 if ( $instances == 1 ) { 1143 # we just removed the last instance 1144 my $query = $db->prepare_cached( $sql->delete_object ); 1145 my $rows = $query->execute( $so_id ); 1146 $query->finish; 1147 1148 # TODO: this will have to be changed in order to support hardlinks 1149 unless ( $rows == 1 ) { 1150 $log->logdie( "affected row count is $rows instead of 2" ); 1151 } 1152 } 1153 1154 $db->commit; 1155 $log->debug("commit"); 1156 }; 1157 if ( $@ ) { 1158 $db->rollback; 1159 $log->debug("rollback"); 1160 $log->logdie( "database error: $@" ); 1173 1174 } 1175 1176 { 1177 my $query = $db->prepare_cached( $sql->get_instance_count ); 1178 $query->execute( $so_id ); 1179 1180 $instances = $query->fetchrow_hashref->{ 'count(ins_id)' }; 1181 $query->finish; 1182 } 1183 1184 # remove instance 1185 { 1186 my $query = $db->prepare_cached( $sql->delete_instance ); 1187 my $rows = $query->execute( $uri ); 1188 $query->finish; 1189 1190 # if we affected something other then two rows something very bad 1191 # has happened 1192 unless ( $rows == 1 ) { 1193 $log->logdie( "affected row count is $rows instead of 1" ); 1194 } 1195 } 1196 1197 # if we just deleted the last instance associated with a storage object 1198 # remove it too 1199 if ( $instances == 1 ) { 1200 # we just removed the last instance 1201 my $query = $db->prepare_cached( $sql->delete_object ); 1202 my $rows = $query->execute( $so_id ); 1203 $query->finish; 1204 1205 # TODO: this will have to be changed in order to support hardlinks 1206 unless ( $rows == 1 ) { 1207 $log->logdie( "affected row count is $rows instead of 2" ); 1208 } 1209 } 1210 1211 $db->commit; 1212 $log->debug("commit"); 1213 }; 1214 if ( $@ ) { 1215 $db->rollback; 1216 $log->debug("rollback"); 1217 if ($@ =~ /Deadlock found/) { 1218 $log->warn("database deadlock retrying transaction: $@"); 1219 redo TRANS; 1220 } 1221 $log->logdie( "database error: $@" ); 1222 } 1223 last; 1161 1224 } 1162 1225
Note:
See TracChangeset
for help on using the changeset viewer.
