Note on object locking
When you read objects from the datastore, the object table is locked with a shared lock; when you write to the datastore, the table is locked with an exclusive lock.
Thus, note that saving or removing objects in the same loop where you are loading them from an iterator will not work - the reason is that the datastore maintains a shared lock on the object table while objects are being loaded from the iterator, and thus the attempt to gain an exclusive lock when saving or removing an object will cause deadlock.
For example, you cannot do the following:
my $iter = MT::Foo->load_iter({ foo => 'bar' });
while (my $foo = $iter->()) {
$foo->remove;
}
Instead you should do either this:
my @foo = MT::Foo->load({ foo => 'bar' });
for my $foo (@foo) {
$foo->remove;
}
or this:
my $iter = MT::Foo->load_iter({ foo => 'bar' });
my @to_remove;
while (my $foo = $iter->()) {
push @to_remove, $foo
if SOME CONDITION;
}
for my $foo (@to_remove) {
$foo->remove;
}
This last example is useful if you will not be removing every MT::Foo
object where foo
equals bar
, because it saves memory - only the
MT::Foo
objects that you will be deleting are kept in memory at the same
time.