So I'm bopping along in my project, building file classes with my modified Protoclass. Everything is fine until I get the bright idea to use an MV file with more than one data level. The main level is HOURLYEXTREMES with two data levels, HOURLYEXTREMES,HIGH and HOURLYEXTREMES,LOW. I had to add a little twist into my modified Protoclass to create a camel-cased class name for each datalevel. I have Weather.HourlyextremesHigh.cls and Weather.HourlyextremesLow.cls.
Everything *seems* hunky-dory. The classes open up the files at the right data level; the properties are exactly what I asked for; the Get() and Set() methods and my default query are all generated correctly.
So far so good. On to question one:
When I use %MV.getPrimaryMVClass() on any of the data levels though, none of the classes are detected. Is this an exception for multi-level data files? For me, it hurts nothing to regenerate a class if I want to (when I make a class for these files it's often what I want the first time). I can see where it could really mess things up if someone is depending on the class to keep the DICT up to date. (That's ever so much easier than fiddling with the DICT.) It just seems odd that the data levels don't associate a class, even though it compiles and appears to operate properly.
Two: In my Protoclass I set MVREPOPULATE to 1 when I create the class. I've moved the SetAt around (finally to be the last thing before save and compile the new class) but MVREPOPULATE still comes out as 0. It hurts nothing for me to go back and change it to 1 so I can maintain the DICT from the class. The down side is I have to remember and there are days when my memory isn't (snapping fingers) *that* long. Most of my code is the original PROTOCLASS code with a load of additions. Any of the other parameters seems to generate as requested.
Mostly, I'm curious. I can work around these idiosyncrasies easily enough, but they do seem to be exceptions to the rules.
1. What do you have on attribute 9 of the VOC pointer for the file?, it should be a multivalued list of the classes for the multiple data sections listed in attribute 7. If they are correct, add a temporary change to protoclass to invoke the Dump method on the open file handle, this should show if open has located the correct class for the data section.
2. If %MV.getPrimaryMVClass() creates a class then it will set MVREPOPULATE to zero. I assume you are settind it after this, what code are you using to do it?
> -----Original Message----- > From: intersystems-mv@googlegroups.com [mailto:intersystems- > mv@googlegroups.com] On Behalf Of Bill Farrell > Sent: Tuesday, March 06, 2012 11:55 AM > To: intersystems-mv@googlegroups.com > Subject: [InterSystems-MV] File classes and multi-level MV files
> So I'm bopping along in my project, building file classes with my > modified Protoclass. Everything is fine until I get the bright idea to > use an MV file with more than one data level. The main level is > HOURLYEXTREMES with two data levels, HOURLYEXTREMES,HIGH and > HOURLYEXTREMES,LOW. I had to add a little twist into my modified > Protoclass to create a camel-cased class name for each datalevel. I > have Weather.HourlyextremesHigh.cls and Weather.HourlyextremesLow.cls.
> Everything *seems* hunky-dory. The classes open up the files at the > right data level; the properties are exactly what I asked for; the Get() > and Set() methods and my default query are all generated correctly.
> So far so good. On to question one:
> When I use %MV.getPrimaryMVClass() on any of the data levels though, > none of the classes are detected. Is this an exception for multi-level > data files? For me, it hurts nothing to regenerate a class if I want to > (when I make a class for these files it's often what I want the first > time). I can see where it could really mess things up if someone is > depending on the class to keep the DICT up to date. (That's ever so > much easier than fiddling with the DICT.) It just seems odd that the > data levels don't associate a class, even though it compiles and appears > to operate properly.
> Two: In my Protoclass I set MVREPOPULATE to 1 when I create the class. > I've moved the SetAt around (finally to be the last thing before save > and compile the new class) but MVREPOPULATE still comes out as 0. It > hurts nothing for me to go back and change it to 1 so I can maintain the > DICT from the class. The down side is I have to remember and there are > days when my memory isn't (snapping fingers) *that* long. Most of my > code is the original PROTOCLASS code with a load of additions. Any of > the other parameters seems to generate as requested.
> Mostly, I'm curious. I can work around these idiosyncrasies easily > enough, but they do seem to be exceptions to the rules.
> Thanks, > Bill
> -- > You received this message because you are subscribed to the Google > Groups "InterSystems: MV Community" group. > To post to this group, send email to CacheMV@googlegroups.com To > unsubscribe from this group, send email to CacheMV- > unsubscribe@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/CacheMV?hl=en
0001 F 0002 ^HOURLYEXTREMES 0003 ^DICT.HOURLYEXTREMES 0004 M 0005 Weather.HOURLYEXTREMES 0006 0007 LOW]HIGH 0008 ^HOURLYEXTREMES.LOW]^HOURLYEXTREMES.HIGH 0009 0010
There was an old class in attribute nine that no longer exists on the system. I edited attribute 9 to remove the reference to a non-existent class and recompiled my new class (attached). I have noticed that neither the stock version nor my version of PROTOCLASS cleans up F-pointers properly. Ever. If there has EVER been a reference to an elder class (you think you've deleted), you must clean up the VOC pointers by hand. I added the following code to my method after discovering that the stock PROTOCLASS cleans up neither prior definitions nor attribute 9 of the F-pointer in question. This works "most" of the time (about 95%).
If DeleteExistingClass = @true Then
If ClassDefinition <> %MVBCommon->nil Then ClassToDelete = ClassDefinition->Name Else ClassToDelete = CompleteClassName "%Dictionary.ClassDefinition"->%DeleteId( ClassToDelete ) ; * delete the class object "%ExtentMgr.Util"->DeleteExtentDefinition( ClassToDelete ) ; * also delete the definition else the rest of this method may go awry. ClassDefinition = %MVBCommon->nil
End
If you have a previously-existing class in a different package to the one you want to put your new class in, you MUST clean the definition and object up by hand (or by adding the code above to the stock version). I'm guessing that occasionally the object reference counter isn't being decremented to zero, leaving a dangling reference that in point of fact points to nowhere.
I would have thought that after cleaning up a dangling definition and object then starting fresh I'd have attribute 9 looking right and upon executing getPrimaryMVClass() I'd have a class definition object matching the class I just compiled.
What's odd is that if I know the class I want to instantiate for a given MV file, I can instantiate it and use it just fine. If I'm querying during the compilation of a new class or Dump()-ing the file handle, the newly-compiled classes don't show up.
Now, I'll admit I still don't know all the ins and outs of creating file classes. Aside from this one odd instance, my modified version does exactly what I want it to do the way I want it do it. I will reiterate that attribute 9 of the targeted F-pointer is almost never to never cleaned up properly.
On Tue, 2012-03-06 at 21:47 +0000, John Lambert wrote: > Bill,
> 1. What do you have on attribute 9 of the VOC pointer for the file?, it should be a multivalued list of the classes for the multiple data sections listed in attribute 7. > If they are correct, add a temporary change to protoclass to invoke the Dump method on the open file handle, this should show if open has located the correct class for the data section.
> 2. If %MV.getPrimaryMVClass() creates a class then it will set MVREPOPULATE to zero. I assume you are settind it after this, what code are you using to do it?
> John
> > -----Original Message----- > > From: intersystems-mv@googlegroups.com [mailto:intersystems- > > mv@googlegroups.com] On Behalf Of Bill Farrell > > Sent: Tuesday, March 06, 2012 11:55 AM > > To: intersystems-mv@googlegroups.com > > Subject: [InterSystems-MV] File classes and multi-level MV files
> > So I'm bopping along in my project, building file classes with my > > modified Protoclass. Everything is fine until I get the bright idea to > > use an MV file with more than one data level. The main level is > > HOURLYEXTREMES with two data levels, HOURLYEXTREMES,HIGH and > > HOURLYEXTREMES,LOW. I had to add a little twist into my modified > > Protoclass to create a camel-cased class name for each datalevel. I > > have Weather.HourlyextremesHigh.cls and Weather.HourlyextremesLow.cls.
> > Everything *seems* hunky-dory. The classes open up the files at the > > right data level; the properties are exactly what I asked for; the Get() > > and Set() methods and my default query are all generated correctly.
> > So far so good. On to question one:
> > When I use %MV.getPrimaryMVClass() on any of the data levels though, > > none of the classes are detected. Is this an exception for multi-level > > data files? For me, it hurts nothing to regenerate a class if I want to > > (when I make a class for these files it's often what I want the first > > time). I can see where it could really mess things up if someone is > > depending on the class to keep the DICT up to date. (That's ever so > > much easier than fiddling with the DICT.) It just seems odd that the > > data levels don't associate a class, even though it compiles and appears > > to operate properly.
> > Two: In my Protoclass I set MVREPOPULATE to 1 when I create the class. > > I've moved the SetAt around (finally to be the last thing before save > > and compile the new class) but MVREPOPULATE still comes out as 0. It > > hurts nothing for me to go back and change it to 1 so I can maintain the > > DICT from the class. The down side is I have to remember and there are > > days when my memory isn't (snapping fingers) *that* long. Most of my > > code is the original PROTOCLASS code with a load of additions. Any of > > the other parameters seems to generate as requested.
> > Mostly, I'm curious. I can work around these idiosyncrasies easily > > enough, but they do seem to be exceptions to the rules.
> > Thanks, > > Bill
> > -- > > You received this message because you are subscribed to the Google > > Groups "InterSystems: MV Community" group. > > To post to this group, send email to CacheMV@googlegroups.com To > > unsubscribe from this group, send email to CacheMV- > > unsubscribe@googlegroups.com > > For more options, visit this group at > > http://groups.google.com/group/CacheMV?hl=en
This is what protoclass uses to locate existing classes for multiple data sections. Protoclass gets this information from the MVopen so anything else that relies on MVopen correctly setting the class may have problems.
When getPrimaryMVClass() creates a class for multiple data section then it adds an entry to attr9.
> -----Original Message----- > From: intersystems-mv@googlegroups.com [mailto:intersystems- > mv@googlegroups.com] On Behalf Of Bill Farrell > Sent: Wednesday, March 07, 2012 7:43 AM > To: InterSystems-MV@googlegroups.com > Subject: RE: [InterSystems-MV] File classes and multi-level MV files
> There was an old class in attribute nine that no longer exists on the > system. I edited attribute 9 to remove the reference to a non-existent > class and recompiled my new class (attached). I have noticed that > neither the stock version nor my version of PROTOCLASS cleans up F- > pointers properly. Ever. If there has EVER been a reference to an > elder class (you think you've deleted), you must clean up the VOC > pointers by hand. I added the following code to my method after > discovering that the stock PROTOCLASS cleans up neither prior > definitions nor attribute 9 of the F-pointer in question. This works > "most" of the time (about 95%).
> If DeleteExistingClass = @true Then
> If ClassDefinition <> %MVBCommon->nil Then ClassToDelete = > ClassDefinition->Name Else ClassToDelete = CompleteClassName > "%Dictionary.ClassDefinition"->%DeleteId( ClassToDelete ) ; * > delete the class object > "%ExtentMgr.Util"->DeleteExtentDefinition( ClassToDelete ) ; * > also delete the definition else the rest of this method may go awry. > ClassDefinition = %MVBCommon->nil
> End
> If you have a previously-existing class in a different package to the > one you want to put your new class in, you MUST clean the definition and > object up by hand (or by adding the code above to the stock version). > I'm guessing that occasionally the object reference counter isn't being > decremented to zero, leaving a dangling reference that in point of fact > points to nowhere.
> I would have thought that after cleaning up a dangling definition and > object then starting fresh I'd have attribute 9 looking right and upon > executing getPrimaryMVClass() I'd have a class definition object > matching the class I just compiled.
> What's odd is that if I know the class I want to instantiate for a given > MV file, I can instantiate it and use it just fine. If I'm querying > during the compilation of a new class or Dump()-ing the file handle, the > newly-compiled classes don't show up.
> Now, I'll admit I still don't know all the ins and outs of creating file > classes. Aside from this one odd instance, my modified version does > exactly what I want it to do the way I want it do it. I will reiterate > that attribute 9 of the targeted F-pointer is almost never to never > cleaned up properly.
> Thanks! > B
> On Tue, 2012-03-06 at 21:47 +0000, John Lambert wrote: > > Bill,
> > 1. What do you have on attribute 9 of the VOC pointer for the file?, > it should be a multivalued list of the classes for the multiple data > sections listed in attribute 7. > > If they are correct, add a temporary change to protoclass to invoke > the Dump method on the open file handle, this should show if open has > located the correct class for the data section.
> > 2. If %MV.getPrimaryMVClass() creates a class then it will set > MVREPOPULATE to zero. I assume you are settind it after this, what code > are you using to do it?
> > John
> > > -----Original Message----- > > > From: intersystems-mv@googlegroups.com [mailto:intersystems- > > > mv@googlegroups.com] On Behalf Of Bill Farrell > > > Sent: Tuesday, March 06, 2012 11:55 AM > > > To: intersystems-mv@googlegroups.com > > > Subject: [InterSystems-MV] File classes and multi-level MV files
> > > So I'm bopping along in my project, building file classes with my > > > modified Protoclass. Everything is fine until I get the bright idea > > > to use an MV file with more than one data level. The main level is > > > HOURLYEXTREMES with two data levels, HOURLYEXTREMES,HIGH and > > > HOURLYEXTREMES,LOW. I had to add a little twist into my modified > > > Protoclass to create a camel-cased class name for each datalevel. I > > > have Weather.HourlyextremesHigh.cls and > Weather.HourlyextremesLow.cls.
> > > Everything *seems* hunky-dory. The classes open up the files at the > > > right data level; the properties are exactly what I asked for; the > > > Get() and Set() methods and my default query are all generated > correctly.
> > > So far so good. On to question one:
> > > When I use %MV.getPrimaryMVClass() on any of the data levels though, > > > none of the classes are detected. Is this an exception for > > > multi-level data files? For me, it hurts nothing to regenerate a > > > class if I want to (when I make a class for these files it's often > > > what I want the first time). I can see where it could really mess > > > things up if someone is depending on the class to keep the DICT up > > > to date. (That's ever so much easier than fiddling with the DICT.) > > > It just seems odd that the data levels don't associate a class, even > > > though it compiles and appears to operate properly.
> > > Two: In my Protoclass I set MVREPOPULATE to 1 when I create the > class. > > > I've moved the SetAt around (finally to be the last thing before > > > save and compile the new class) but MVREPOPULATE still comes out as > > > 0. It hurts nothing for me to go back and change it to 1 so I can > > > maintain the DICT from the class. The down side is I have to > > > remember and there are days when my memory isn't (snapping fingers) > > > *that* long. Most of my code is the original PROTOCLASS code with a > > > load of additions. Any of the other parameters seems to generate as > requested.
> > > Mostly, I'm curious. I can work around these idiosyncrasies easily > > > enough, but they do seem to be exceptions to the rules.
> > > Thanks, > > > Bill
> > > -- > > > You received this message because you are subscribed to the Google > > > Groups "InterSystems: MV Community" group. > > > To post to this group, send email to CacheMV@googlegroups.com To > > > unsubscribe from this group, send email to CacheMV- > > > unsubscribe@googlegroups.com For more options, visit this group at > > > http://groups.google.com/group/CacheMV?hl=en
> -- > You received this message because you are subscribed to the Google > Groups "InterSystems: MV Community" group. > To post to this group, send email to CacheMV@googlegroups.com To > unsubscribe from this group, send email to CacheMV- > unsubscribe@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/CacheMV?hl=en
I started this email yesterday morning, then went back to work this through, trying different scenarios. Updates are in-line.
-----
What would prevent getPrimaryMVClass or compiling a new class from updating attribute 9? Indeed, what you've described is the behavior I expected; it's only occasionally what I observe.
One instance where I know attribute 9 is not updated for certain goes like this: You create a class using the stock PROTOCLASS, or in the case of my modified Protoclass, you don't specify a package. This creates a class in the default MVFile package. You then go "oops, that isn't where I want that class" and pay Hobb getting rid of it. If you create a class for that MV file in another package, attribute 9 is never updated again. (Update: neither is attribute 5.)
I've fiddled with this during the day and this is what I see: It would seem that at least one of a couple of possibilities is playing out. The code I included in my Protoclass doesn't actually get rid of all the old class information (though it seems to show up nowhere, not in filehandle->Dump() or in the F-pointer); it certainly never updates attribute 9 to reflect that the old class is gone; even though you can plainly see that the old class is nowhere to be found AND update attribute 9 of the F-pointer by hand, it never reflects the fact that a new class has been created for the file and has compiled successfully.
Long and short, make sure a class is in the package you want it in from the very start. It seems impossible to create a new class in a new package and have it associate with the file ever again. You can edit an existing class and recompile it as much as you want. Just don't ever attempt to delete a class and define a new one in another package.
The only solution I've found is to delete the whole file (dict, all datalevels, and indices) and start over.
Update: I can find no case in which attribute 5 is updated properly, either. I spent the rest of yesterday afternoon experimenting with deleting a class for a multi-level file and attempting to associate another class with it. Long and short, once you compile a class and associate it with a file, that's it and all. You can never fully delete it and associate another class in another package with it.
Update: There seems to be a certain danger in storing any meta-information in the VOC. VOCs are by nature volatile, hence, never trustworthy. To wit: there was a fashion in the MV world for a while to create PROCs on the fly, store them in the VOC, and execute them right away. That didn't work out so well for manifold reasons. Just thinking out loud here, but metadata belongs with metadata: I trust objects in the VOC about as far as I can toss the Empire State Building over my shoulder. Too many programmers treat the VOC as a free-for-all.
There must be a way to delete a class (definition and object) cleanly with the metadata matching reality.
(Update) Even after manually adding class names in attribute 9 of the F-pointer, they're still never updating if classes are deleted.
If you could, give me an opinion on the code I'm using in my Protoclass (in a previous email in this thread, quoted below). It claims to delete the definition and object (I can verify the definition is gone in Studio), but the VOC is never in sync with that fact. The object can persist whether or not there is an active reference to it. Since I'm the only user on a single-user instance, I can verify that by logging all terminal sessions off and logging back on cleanly, then restarting my test.
Now I've come to a new problem I ran up against this morning. There was an existing class for the main datalevel in the HOURLYEXTREMES MV file. I deleted the class (using all the best ways I know how), yet attribute 5 was never updated. I edited the F-pointer to get rid of the reference in attribute 5. I ran MVBProtoclass to create a class for the main datalevel (so I can maintain the DICT easily). Attribute 5 did update but the class refuses to compile, complaining that "Hourlyextremes" in the class query does not reference a unique table.
Uh, well. Why wouldn't it be? That's a separate datalevel to HourlyextremesLow (HOURLYEXTREMES,LOW) and HourlyextremesHigh (HOURLYEXTREMES,HIGH). I am throughly at a loss at this point. I'm ceasing work on this project until I can get a handle on keeping MV files, classes, and metadata squared away.
I'd love to know more about the inner workings of associating classes with MV files. Any enlightenment would be welcome.
> This is what protoclass uses to locate existing classes for multiple data sections. > Protoclass gets this information from the MVopen so anything else that relies on MVopen correctly setting the class may have problems.
> When getPrimaryMVClass() creates a class for multiple data section then it adds an entry to attr9.
> John
> > -----Original Message----- > > From: intersystems-mv@googlegroups.com [mailto:intersystems- > > mv@googlegroups.com] On Behalf Of Bill Farrell > > Sent: Wednesday, March 07, 2012 7:43 AM > > To: InterSystems-MV@googlegroups.com > > Subject: RE: [InterSystems-MV] File classes and multi-level MV files
> > There was an old class in attribute nine that no longer exists on the > > system. I edited attribute 9 to remove the reference to a non-existent > > class and recompiled my new class (attached). I have noticed that > > neither the stock version nor my version of PROTOCLASS cleans up F- > > pointers properly. Ever. If there has EVER been a reference to an > > elder class (you think you've deleted), you must clean up the VOC > > pointers by hand. I added the following code to my method after > > discovering that the stock PROTOCLASS cleans up neither prior > > definitions nor attribute 9 of the F-pointer in question. This works > > "most" of the time (about 95%).
> > If DeleteExistingClass = @true Then
> > If ClassDefinition <> %MVBCommon->nil Then ClassToDelete = > > ClassDefinition->Name Else ClassToDelete = CompleteClassName > > "%Dictionary.ClassDefinition"->%DeleteId( ClassToDelete ) ; * > > delete the class object > > "%ExtentMgr.Util"->DeleteExtentDefinition( ClassToDelete ) ; * > > also delete the definition else the rest of this method may go awry. > > ClassDefinition = %MVBCommon->nil
> > End
> > If you have a previously-existing class in a different package to the > > one you want to put your new class in, you MUST clean the definition and > > object up by hand (or by adding the code above to the stock version). > > I'm guessing that occasionally the object reference counter isn't being > > decremented to zero, leaving a dangling reference that in point of fact > > points to nowhere.
> > I would have thought that after cleaning up a dangling definition and > > object then starting fresh I'd have attribute 9 looking right and upon > > executing getPrimaryMVClass() I'd have a class definition object > > matching the class I just compiled.
> > What's odd is that if I know the class I want to instantiate for a given > > MV file, I can instantiate it and use it just fine. If I'm querying > > during the compilation of a new class or Dump()-ing the file handle, the > > newly-compiled classes don't show up.
> > Now, I'll admit I still don't know all the ins and outs of creating file > > classes. Aside from this one odd instance, my modified version does > > exactly what I want it to do the way I want it do it. I will reiterate > > that attribute 9 of the targeted F-pointer is almost never to never > > cleaned up properly.
> > Thanks! > > B
> > On Tue, 2012-03-06 at 21:47 +0000, John Lambert wrote: > > > Bill,
> > > 1. What do you have on attribute 9 of the VOC pointer for the file?, > > it should be a multivalued list of the classes for the multiple data > > sections listed in attribute 7. > > > If they are correct, add a temporary change to protoclass to invoke > > the Dump method on the open file handle, this should show if open has > > located the correct class for the data section.
> > > 2. If %MV.getPrimaryMVClass() creates a class then it will set > > MVREPOPULATE to zero. I assume you are settind it after this, what code > > are you using to do it?
> > > John
> > > > -----Original Message----- > > > > From: intersystems-mv@googlegroups.com [mailto:intersystems- > > > > mv@googlegroups.com] On Behalf Of Bill Farrell > > > > Sent: Tuesday, March 06, 2012 11:55 AM > > > > To: intersystems-mv@googlegroups.com > > > > Subject: [InterSystems-MV] File classes and multi-level MV files
> > > > So I'm bopping along in my project, building file classes with my > > > > modified Protoclass. Everything is fine until I get the bright idea > > > > to use an MV file with more than one data level. The main level is > > > > HOURLYEXTREMES with two data levels, HOURLYEXTREMES,HIGH and > > > > HOURLYEXTREMES,LOW. I had to add a little twist into my modified > > > > Protoclass to create a camel-cased class name for each datalevel. I > > > > have Weather.HourlyextremesHigh.cls and > > Weather.HourlyextremesLow.cls.
> > > > Everything *seems* hunky-dory. The classes open up the files at the > > > > right data level; the properties are exactly what I asked for; the > > > > Get() and Set() methods and my default query are all generated > > correctly.