One of the solutions
1) Have a look at
%OnNew(initvalue As %CacheString) method
of the %Library.Persistent class
initvalue is an optional argument,
2) You will have to override the method in your class to prevent more
than one/whatevernumber instance(s) being created.
In the studio from the menu
Class->Override and select the method to override.
The code in this method should be like
set vstat=1
if ..%ExistsId(N) {
s vstat=0
}
quit vstat
---------
3) Replace N with maximum number of instances allowed.
If somebody tries to create a new instance greater than N,
The %New method will return a null object reference (OREF)
HTH
Regards
Sukesh Hoogan
Bombay, India
[Enterprise Resource Planning & Business Intelligence]
http://sukeshhoogan.blogspot.com
I am not sure whether you and Edwin (he says he is fairly new to Caché)
are the same person or are from the same organisation.
In any case, the answer to your question.
The one instance would indeed be stored in a persistent class, which
extends the RegisteredObject class. And you have to override %OnNew
method in the persistent class.
Regards
Sukesh Hoogan
Bombay, India
[Enterprise Resource Planning & Business Intelligence]
http://sukeshhoogan.blogspot.com
> Maybe the best solution would be to persist it (as Sukesh suggested)
> but modify the storage so that it end up in CacheTemp. I just tested
> it and it works!
Eric,
See below an implementation for %RegisteredObject.
HTH
Herman
Class PlacidSky.Singleton Extends %RegisteredObject
{
Method %OnNew(initvalue As %CacheString) As %Status [ Private,
ProcedureBlock = 1, ServerOnly = 1 ] {
Set Obj="",Found=0
For {
Set Obj=$zobjnext(Obj)
If Obj="" Quit
If Obj=##this Continue
If Obj.%ClassName(1)=..%ClassName(1) {
Set Found=1
Quit
}
}
If Found {
Quit $$$ERROR($$$GeneralError,..%ClassName(1)_" already
instantiated")
}
Quit $$$OK
}
ClassMethod Get() as PlacidSky.Singleton {
Set Obj="",Found=0
For {
Set Obj=$zobjnext(Obj)
If Obj="" Quit
If Obj.%ClassName(1)=..%ClassName(1) {
Set Found=1
Quit
}
}
If Found {
Quit Obj
}
Quit ..%New()
}
}
In Terminal:
LSP200>s o1=##class(PlacidSky.Singleton).%New()
LSP200>w
o1=<OBJECT REFERENCE>[1...@PlacidSky.Singleton]
LSP200>s o2=##class(PlacidSky.Singleton).%New()
LSP200>w
%objlasterror="0 _ ? *PlacidSky.Singleton already
instantiated(%OnNew+11^PlacidSky.Singleton.3:LSP200"
o1=<OBJECT REFERENCE>[1...@PlacidSky.Singleton]
o2=""
LSP200>s o3=##class(PlacidSky.Singleton).Get()
LSP200>w
%objlasterror="0 _ ? *PlacidSky.Singleton already
instantiated(%OnNew+11^PlacidSky.Singleton.3:LSP200"
o1=<OBJECT REFERENCE>[1...@PlacidSky.Singleton]
o2=""
o3=<OBJECT REFERENCE>[1...@PlacidSky.Singleton]
Eric,
> not documented
Well, documentation isn't one of ISC's strongest points ;-)
Normally I wouldn't use undocumented stuff, but after working with Cache for
more then ten years, you get a feeling for what's really undocumented and
what they forgot to document.
Ofcourse if they change or remove the implementation of $zobjnext (highly
unlikely), your code would break.
But over the years I've seen documented features break in new releases too.
:-S
The documented ones are: $zobjproperty, $zobjmethod and $zobjclassmethod.
There's also a $zobjclass(object), which is about ten times faster then
object.%ClassName(1).
I've also seen $zobjval, $zobjmod, $zobjmods and $zobjexport, don't know
what they do.
> Am I understanding correctly that you are
> iterating through all objects in the current process?
Yep, all instantiated objects in memory.
Herman
A) The documentation has notes on only three
$zobjclassmethod
$zobjmethod
$zobjproperty
http://127.0.0.1:1972/csp/docbook/DocBook.UI.Page.cls?KEY=AZOBJ
The documentation is silent on
$zobjnew(ClassName As %String)
$zobjval
$zobjexport
$zobjmods
$zobjnew(classname) is equivalent to %New()
I will post about $zobjval later in the day.
Regards
Sukesh Hoogan
Bombay, India
[Enterprise Resource Planning & Business Intelligence]
http://sukeshhoogan.blogspot.com
Here is the SingletonClass (can't be inherited)
Class Utile.SingletonClass Extends %Persistent [ NoExtent]
{
Property InternalId As %String;
Index MyId On InternalId [ IdKey, PrimaryKey, Unique ];
Property TestProp As %String [ Transient ];
ClassMethod Test()
{
set obj1=##class(Utile.SingletonClass).%OpenId(1)
set obj1.TestProp=3
set obj2=##class(Utile.SingletonClass).%OpenId(1)
set obj3=##class(Utile.SingletonClass).%OpenId(2)
set obj3.TestProp=2
set obj4=##class(Utile.SingletonClass).%OpenId(2)
w
w !,"TEST id1: "_obj2.TestProp_" id2: "_obj4.TestProp,!
}
Method %LoadData(id As %String) As %Status [ Private, ProcedureBlock =
1, ServerOnly = 1 ]
{
QUIT $$$OK
}
<Storage name="MyStorage">
<SequenceNumber>6</SequenceNumber>
<Type>%CustomStorage</Type>
</Storage>
}
You will have to:
1. maintain the InternalId prop, the MyId index and the MyStorage
declaration;
2. All the properties has to be declared with attribute [Transient];
I have test this on CACHE 2007.1 and is working.
It has one limitation. The instance can't be accessed form different
processes it works only on one process (connection).
to see the result call the Test method in Terminal.
"Eric" <Eric....@gmail.com> wrote in message
news:d62dce3a-dc5e-4f00...@25g2000hsx.googlegroups.com...
Feel free to update/annotate this list as appropriate.
Regards
George
George James Software
www.georgejames.com