Hi,
I'm attempting to update my Pier site with the latest Pier code. After updating, the site returns a 403 (forbidden) instead of the rendered pages. Investigating it seems that some instance variables have been added to PRCommand, which results in:
PRViewCommand classHistory size = 2 The page checks to see if it has permission to be viewed by calling the following and passing in PRViewCommand: PUPermission >> #= aCommand
^ self species = aCommand species and: [ self command = aCommand command ]
which fails when previously it would have succeed: PRViewCommand species = (PRViewCommand classHistory at: 1) species "false" and:
PRViewCommand species = (PRViewCommand classHistory at: 2) species "true" --- So assuming I've tracked the problem, I could either modify the check in PUPermission, or try ensure that the permissions associated with my Pier site structure only hold the latest command classes.
I'm still unsure how to set about locating the objects that are holding references to previous versions of the class. I tried: SystemRepository findReferencePathToObject: (PRViewCommand classHistory at: 1)
which either returned nil or threw an exception: "An attempt to execute a method that requires an abort or prevents further commits would result in lost data". How do people track down objects holding onto previous class versions? Has anyone else hit this Pier permissioning problem?
Cheers Nick
|
Nick,
that is one of the things that I've been starting to worry about in Pier ... there seem to be a number of places where Pier assumes that class identity is constant ... the class is (has been?) been used for calculating hashes and here it is used in an equality test ... With that said, I would have to guess that somehow migration wasn't done for a some of the instances ofPrViewCommand as you shouldn't ahve instances of older classes in the classHistory. The oldest class in the classHistory is in slot 1 so: PRViewCommand species = (PRViewCommand classHistory at: 1) species should be false in your case. What I find interesting is that the PUPermission species and aCommand species would ever be #=, since they are completely different classes... Dale On 12/13/2010 07:53 PM, Nick Ager wrote: > Hi, > > I'm attempting to update my Pier site with the latest Pier code. > After updating, the site returns a 403 (forbidden) instead of the > rendered pages. > > Investigating it seems that some instance variables have been added to > PRCommand, which results in: > PRViewCommand classHistory size = 2 > > The page checks to see if it has permission to be viewed by calling the > following and passing in PRViewCommand: > > PUPermission >> #= aCommand > ^ self species = aCommand species > and: [ self command = aCommand command ] > > which fails when previously it would have succeed: > > PRViewCommand species = (PRViewCommand classHistory at: 1) species "false" > > and: > > PRViewCommand species = (PRViewCommand classHistory at: 2) species "true" > > --- > > So assuming I've tracked the problem, I could either modify the check in > PUPermission, or try ensure that the permissions associated with my Pier > site structure only hold the latest command classes. > > I'm still unsure how to set about locating the objects that are holding > references to previous versions of the class. I tried: > > SystemRepository findReferencePathToObject: (PRViewCommand classHistory > at: 1) > > which either returned nil or threw an exception: "An attempt to execute > a method that requires an abort or prevents further commits would result > in lost data". > > How do people track down objects holding onto previous class versions? > Has anyone else hit this Pier permissioning problem? > > Cheers > > Nick |
Hi Dale,
Thanks again for the tips. The results are negative. There are no non-migrated instances. Perhaps I've been asking the wrong question. I think the problem is that we have objects holding references to command classes not command class instances. For example:
PUPermission allInstances size. "646" (PUPermission allInstances select: [:aPermission | aPermission command ~~ aPermission command classHistory last]) size. "641" where aPermission command holds a reference to a class not a class instance: PUPermission allInstances fourth command "PRMoveCommand" And now the solution presents itself:
PUPermission allInstances do: [:aPermission | aPermission setCommand: aPermission command classHistory last] Which solved my immediate problem, but begs another question. Could all code that holds a reference to a class be potentially problematic in long running installations when the class is modified eg PRComponent #componentClass or WABuilder #rootClass, #documentClass, #rendererClass, #scriptGeneratorClass, etc. Have I misunderstood?
Is there a way of tracking down all the places that hold onto a reference to a class where: class ~~ class classHistory last? Thanks again Nick
On 14 December 2010 17:59, Dale Henrichs <[hidden email]> wrote: Nick,
classHistory didn't like #copyFrom:to: so rewriting slightly:
| classArray results trouble | classArray := Array new. PRCommand allSubclasses do: [:cl | cl classHistory size > 1 ifTrue: [ cl classHistory do: [:aClass | classArray add: aClass] ] ].
trouble := Dictionary new. System abortTransaction. results := SystemRepository listInstances: classArray. 1 to: results size do: [:index | (results at: index) notEmpty
ifTrue: [ trouble at: (classArray at: index) put: (results at: index) ]]. trouble associations collect: [:anAssoc | Association key: anAssoc key value: anAssoc value size]. "anArray( PRRemoveCommand->7, IZNewProjectCommand->108, IZRemoveBlogPost->1, IZLogin->275, IZEditUser->20, IZLogout->25, PRMoveCommand->2, PRViewCommand->1259, PREditCommand->207, PRAddCommand->9, IZAddComment->6, IZEditBlogPost->65, IZEditProjectCommand->10, IZCreateBlogPost->12, IZLoginRegisterCommand->542)"
I'
|
Nick,
Ahhhhhhhh, yesssssssssss:( Hanging onto direct references to classes can lead to trouble in GemStone ... Now that I'm looking at this problem square in the eye, I suppose that there are some things that we could do ... along with auto migration we _should_ automatically swizzle the references to classes ... There are a couple of different possibilities and I will take a look at them today and see if they hold promise: - use #become: on the old version of the class ... this causes my brain to loop back upon itself, but if we've solved the nasty problems in the #become: primitive, then it has promise - search for all references to the old version of the class and replace them with a reference to the new class ... assuming we can identify the reference sites that shouldn't be swapped (the class history array is the most obvious spot and there might be others) Dale On 12/14/2010 04:52 PM, Nick Ager wrote: > Hi Dale, > > Thanks again for the tips. The results are negative. There are no > non-migrated instances. > Perhaps I've been asking the wrong question. I think the problem is that > we have objects holding references to command classes not command class > instances. For example: > > PUPermission allInstances size. "646" > (PUPermission allInstances select: [:aPermission | aPermission command > ~~ aPermission command classHistory last]) size. "641" > > where aPermission command holds a reference to a class not a class instance: > > PUPermission allInstances fourth command "PRMoveCommand" > > And now the solution presents itself: > > PUPermission allInstances do: [:aPermission | aPermission setCommand: > aPermission command classHistory last] > > Which solved my immediate problem, but begs another question. Could all > code that holds a reference to a class be potentially problematic in > long running installations when the class is modified eg PRComponent > #componentClass or WABuilder #rootClass, #documentClass, #rendererClass, > #scriptGeneratorClass, etc. Have I misunderstood? > > Is there a way of tracking down all the places that hold onto a > reference to a class where: > class ~~ class classHistory last? > > Thanks again > > Nick > > > On 14 December 2010 17:59, Dale Henrichs <[hidden email] > <mailto:[hidden email]>> wrote: > > Nick, > > The classHistories are not automatically thrown away ... they are > kept around by GemStone whether or not you have instances of them or > not ... > > I think that to validate that all instances have been migrated, you > would do someting like: > > (PRViewCommand classHistory at: 1) allInstances > > > If the list is empty you are good to go... > > The classHistory can be cleaned up (see the class ClassHistory), so > you could write a script that looked like this to clean up class > history (note the abort in the middle): > > | classArray results trouble | > classArray := Array new. > PRCommand allSubclasses do: [:cl | > cl classHistory size > 1 > ifTrue: [ > classArray addAll: > ( cl classHistory copyFrom: 1 to: cl classHistory size -1)]]. > trouble := Dictionary new. > System abortTransaction. > results := SystemRepository listInstances: classArray. > 1 to: results size do: [:index | > (results at: index) notEmpty > ifTrue: [ > trouble at: (classArray at: index) put: (results at: index) ]]. > trouble > > If trouble is not empty, then you have unmigrated instances ... if > trouble is empty, then you can trim the classHistory for those > classes using #removeVersion: > > > classHistory didn't like #copyFrom:to: so rewriting slightly: > > | classArray results trouble | > classArray := Array new. > PRCommand allSubclasses do: [:cl | > cl classHistory size > 1 > ifTrue: [ > cl classHistory do: [:aClass | classArray add: aClass] ] ]. > trouble := Dictionary new. > System abortTransaction. > results := SystemRepository listInstances: classArray. > 1 to: results size do: [:index | > (results at: index) notEmpty > ifTrue: [ > trouble at: (classArray at: index) put: (results at: index) ]]. > trouble associations collect: [:anAssoc | Association key: anAssoc key > value: anAssoc value size]. "anArray( PRRemoveCommand->7, > IZNewProjectCommand->108, IZRemoveBlogPost->1, IZLogin->275, > IZEditUser->20, IZLogout->25, PRMoveCommand->2, PRViewCommand->1259, > PREditCommand->207, PRAddCommand->9, IZAddComment->6, > IZEditBlogPost->65, IZEditProjectCommand->10, IZCreateBlogPost->12, > IZLoginRegisterCommand->542)" > > I' > > > > Dale > > On 12/14/2010 09:33 AM, Nick Ager wrote: > > Hi Dale, > > Thanks for the response, I'm still unsure how to go about > tracking down > the objects that are holding onto the old class versions. I tried: > > SystemRepository findReferencePathToObject: (PRViewCommand > classHistory > at: 1) > > which I couldn't get to work. Any suggestions? > > There are other command classes which didn't migrate: > > PRCommand allSubclasses size. "35" > (PRCommand allSubclasses select:[:aClass | aClass classHistory > size > > 2]) size "21" > > (PRCommand allSubclasses select:[:aClass | aClass classHistory > size > > 1]) collect: [ :aClass | aClass classHistory size]. "anArray( 2, > 2, 3, > 5, 3, 3, 5, 3, 5, 3, 2, 3, 3, 2, 3, 3, 3, 2, 2, 3, 5, 4, 6, 2, > 2, 2, 3, > 2, 3, 3, 2, 3, 2, 2, 2)" > > Any thoughts on the best way to track down who is holding onto my > historical classes. > > Cheers > > Nick > > On 14 December 2010 17:15, Dale Henrichs <[hidden email] > <mailto:[hidden email]> > <mailto:[hidden email] <mailto:[hidden email]>>> wrote: > > Nick, > > that is one of the things that I've been starting to worry > about in > Pier ... there seem to be a number of places where Pier > assumes that > class identity is constant ... the class is (has been?) been > used > for calculating hashes and here it is used in an equality > test ... > > With that said, I would have to guess that somehow migration > wasn't > done for a some of the instances ofPrViewCommand as you > shouldn't > ahve instances of older classes in the classHistory. > > The oldest class in the classHistory is in slot 1 so: > > > PRViewCommand species = (PRViewCommand classHistory at: 1) > species > > should be false in your case. > > What I find interesting is that the PUPermission species and > aCommand species would ever be #=, since they are completely > different classes... > > Dale > > > > On 12/13/2010 07:53 PM, Nick Ager wrote: > > Hi, > > I'm attempting to update my Pier site with the latest > Pier code. > After updating, the site returns a 403 (forbidden) > instead of the > rendered pages. > > Investigating it seems that some instance variables have > been > added to > PRCommand, which results in: > PRViewCommand classHistory size = 2 > > The page checks to see if it has permission to be viewed by > calling the > following and passing in PRViewCommand: > > PUPermission >> #= aCommand > ^ self species = aCommand species > and: [ self command = aCommand command ] > > which fails when previously it would have succeed: > > PRViewCommand species = (PRViewCommand classHistory at: 1) > species "false" > > and: > > PRViewCommand species = (PRViewCommand classHistory at: 2) > species "true" > > --- > > So assuming I've tracked the problem, I could either > modify the > check in > PUPermission, or try ensure that the permissions > associated with > my Pier > site structure only hold the latest command classes. > > I'm still unsure how to set about locating the objects > that are > holding > references to previous versions of the class. I tried: > > SystemRepository findReferencePathToObject: (PRViewCommand > classHistory > at: 1) > > which either returned nil or threw an exception: "An > attempt to > execute > a method that requires an abort or prevents further commits > would result > in lost data". > > How do people track down objects holding onto previous class > versions? > Has anyone else hit this Pier permissioning problem? > > Cheers > > Nick > > > > > |
Nick,
It doesn't look like any generic swapping algorithm will work very well. It is going to take application-specific knowledge to know what is safe and what is not safe ... given this, I am inclined to make modifications to Pier/Seaside and change the code so that instead of storing direct references to a class, the name of the class is stored and a lookup is done when referenced .... I think that this is the safest route to take ... That means that in applications written in Pharo and deployed in GemStone the same precautions need to be taken ... I'm inclined to add something to MockGemStone (and GLASS) GsClassReference or something that should be used when you need to store a direct reference to a class ... How does that sound? Any better ideas? Dale asOn 12/16/2010 09:57 AM, Dale Henrichs wrote: > Nick, > > Ahhhhhhhh, yesssssssssss:( > > Hanging onto direct references to classes can lead to trouble in > GemStone ... > > Now that I'm looking at this problem square in the eye, I suppose that > there are some things that we could do ... along with auto migration we > _should_ automatically swizzle the references to classes ... > > There are a couple of different possibilities and I will take a look at > them today and see if they hold promise: > > - use #become: on the old version of the class ... this causes my > brain to loop back upon itself, but if we've solved the nasty > problems in the #become: primitive, then it has promise > - search for all references to the old version of the class and > replace them with a reference to the new class ... assuming we can > identify the reference sites that shouldn't be swapped (the class > history array is the most obvious spot and there might be others) > > Dale |
Hi Dale,
Thanks for getting back. It feels like something along the lines of GRClassReference should probably go into Grease, with Pier, Magritte and Seaside all storing direct references to classes.
In the meantime is there a way to track down what objects are holding references to old classes - something similar to a pointer-finder? Thanks Nick
On 16 December 2010 19:05, Dale Henrichs <[hidden email]> wrote: Nick, |
Nick,
You can try something like the following: | classes references map | classes := Object allSubclasses asArray. ClassOrganizer _resetCachedOrganizer. System abortTransaction. references := SystemRepository listReferences: classes withLimit: 1. map := Dictionary new. 1 to: classes size do: [:index | | coll | coll := (references at: index) select: [:ref | ((ref isKindOf: ClassSet) or: [ref isKindOf: GsSessionMethodDictionary]) not]. coll notEmpty ifTrue:[ map at: (classes at: index) put: coll ]]. map. Instead of allSubclasses of Object you might want to try subclasses of WAObject ... You are going to have to filter out more cruft but this will get you started... Dale On Dec 16, 2010, at 6:33 PM, Nick Ager wrote: Hi Dale, Thanks for getting back. It feels like something along the lines of GRClassReference should probably go into Grease, with Pier, Magritte and Seaside all storing direct references to classes. In the meantime is there a way to track down what objects are holding references to old classes - something similar to a pointer-finder? Thanks Nick On 16 December 2010 19:05, Dale Henrichs <[hidden email]<mailto:[hidden email]>> wrote: Nick, It doesn't look like any generic swapping algorithm will work very well. It is going to take application-specific knowledge to know what is safe and what is not safe ... given this, I am inclined to make modifications to Pier/Seaside and change the code so that instead of storing direct references to a class, the name of the class is stored and a lookup is done when referenced .... I think that this is the safest route to take ... That means that in applications written in Pharo and deployed in GemStone the same precautions need to be taken ... I'm inclined to add something to MockGemStone (and GLASS) GsClassReference or something that should be used when you need to store a direct reference to a class ... How does that sound? Any better ideas? Dale asOn 12/16/2010 09:57 AM, Dale Henrichs wrote: Nick, Ahhhhhhhh, yesssssssssss:( Hanging onto direct references to classes can lead to trouble in GemStone ... Now that I'm looking at this problem square in the eye, I suppose that there are some things that we could do ... along with auto migration we _should_ automatically swizzle the references to classes ... There are a couple of different possibilities and I will take a look at them today and see if they hold promise: - use #become: on the old version of the class ... this causes my brain to loop back upon itself, but if we've solved the nasty problems in the #become: primitive, then it has promise - search for all references to the old version of the class and replace them with a reference to the new class ... assuming we can identify the reference sites that shouldn't be swapped (the class history array is the most obvious spot and there might be others) Dale |
In reply to this post by Dale Henrichs
On 16.12.2010, at 20:05, Dale Henrichs wrote: Can you elaborate a little on the problematic cases? When are class references troublesome? I always thought that methods don't have class references but lookup the class when it is being used. If this would be right than we are talking about ivars holding class references? That would included cases like seaside configuration where you specify a class that is responsible handling certain stuff, etc. Norbert
|
Hi Norbert,
That's my understanding of the problem I'm seeing. As I understand it, when you assign a class to an ivar in Gemstone you are assigning a specific class version. If subsequently you change the class, Gemstone will faithfully give you back a reference to the original class. If I've understood correctly it is a pervasive problem throughout Seaside, Pier, Magritte. The short term solution for me is to work out all those places I'm holding onto a class reference and ensure that they are using the latest class. Longer term would be to ensure that all stored classes are wrapped in a ##ClassReference who's job is to ensure that latest version of the class is returned on request; or have I misunderstood?
Nick
|
Hi, I have a problem with: WASimpleNavigation. There are three tabs. Each one is render nicely. Each tab has a list of objects. The last column of the list is
an image when clicked you access the clicked object in another component. initialize super
initialize. rolsList
:= WARolListComponent new. activitiesList
:= WAActivityListComponent new. statesList
:= WAStateListComponent new. nav
:= WASimpleNavigation new add:
activitiesList label: 'Activities'; add:
rolsList label: 'Rols'; add:
statesList label: 'States'; select:
'Activities'. renderContentOn: html …. rolsList
list: model rols. activitiesList
list: model activities. statesList
list: model states. html
render: nav. The problem is that the new opened component is create inside
the Tab, and I want the component in a new clean web page. I tried with #show: and #call: and the method #children, but
with no luck. Still searching… The other question is how to claim all process that fails (because
DNU) during development. I have a lot of useless walkbacks. I’m searching this in the manuals. Regards, Bruno |
Free forum by Nabble | Edit this page |