Module: tools Branch: master Commit: c1658af0dac543ad77c327eecb7216b8cadc0fdc URL: http://source.winehq.org/git/tools.git/?a=commit;h=c1658af0dac543ad77c327eec...
Author: Francois Gouget fgouget@codeweavers.com Date: Tue May 6 12:40:27 2014 +0200
testbot/lib: Make Collections try harder to return existing Item objects to avoid inconsistencies.
Assume we have the following code: 1: my $Jobs = CreateJobs(); 2: my $VM1 = $Jobs->GetItem(100)->Steps->GetItem(1)->Tasks->GetItem(1)->VM; 3: my $VM2 = $Jobs->GetItem(101)->Steps->GetItem(1)->Tasks->GetItem(1)->VM; 4: my $VM2b = $Jobs->GetItem(101)->Steps->GetItem(1)->Tasks->GetItem(1)->VM; 5: print $VM1->Name, " is ", $VM1->Status, "\n"; # Prints 'buildvm is idle' 6: print $VM2->Name, " is ", $VM2->Status, "\n"; # Prints 'buildvm is idle' 7: $VM1->Status('running'); 8: $VM1->Save(); 9: print $VM1->Name, " is ", $VM1->Status, "\n"; # Prints 'buildvm is running' 10: print $VM2->Name, " is ", $VM2->Status, "\n"; # Prints 'buildvm is idle' !!! 11: print $VM2b->Name, " is ", $VM2b->Status, "\n"; # Prints 'buildvm is running'
The problem is that although $VM1, $VM2 and $VM2b refer to the same VM (buildvm), they are all separate objects. Then $VM2->Status gets loaded from the database for the print statement on line 6, and is then never refreshed; hence the out-of-date value printed on line 10. In contrast $VM2b->Status is loaded from database for the print statement on line 11 and thus shows the up-to-date value that was saved on line 8. This is very confusing.
This patch associates a scope to each Collection and ensures that there is no duplicate Item objects within that scope. Further, any object created from a Collection inherits its scope. So in the example above, because all objects can ultimately be traced back to the $Jobs collection, $VM1, $VM2 and $VM2b all point to the same object which avoids any inconsistency.
It's also possible to ensure that two Collections share the same scope by passing the reference collection as a parameter. For instance, in the above sample code, CreateVMs($Jobs)->GetItem('buildvm') will return $VM1.
As before, creating a new Collection normally, CreateVMs() for instance, ensures gets a new, empty, scope and thus reload the objects from the database. This ensures the new objects will reflect changes made to the database by other processes. This is also why having a global persistent cache would not work.
---
testbot/bin/WineSendLog.pl | 2 +- testbot/lib/ObjectModel/Collection.pm | 199 +++++++++++++++++++++++---- testbot/lib/ObjectModel/DBIBackEnd.pm | 10 +- testbot/lib/ObjectModel/Item.pm | 27 +++- testbot/lib/WineTestBot/Branches.pm | 6 +- testbot/lib/WineTestBot/CGI/Sessions.pm | 5 +- testbot/lib/WineTestBot/Jobs.pm | 6 +- testbot/lib/WineTestBot/Patches.pm | 5 +- testbot/lib/WineTestBot/PendingPatchSets.pm | 5 +- testbot/lib/WineTestBot/PendingPatches.pm | 6 +- testbot/lib/WineTestBot/Roles.pm | 5 +- testbot/lib/WineTestBot/Steps.pm | 7 +- testbot/lib/WineTestBot/StepsTasks.pm | 6 +- testbot/lib/WineTestBot/Tasks.pm | 7 +- testbot/lib/WineTestBot/UserRoles.pm | 7 +- testbot/lib/WineTestBot/Users.pm | 6 +- testbot/lib/WineTestBot/VMs.pm | 6 +- testbot/web/JobDetails.pl | 2 +- 18 files changed, 250 insertions(+), 67 deletions(-)
Diff: http://source.winehq.org/git/tools.git/?a=commitdiff;h=c1658af0dac543ad77c32...