Robert Cemper · Mar 8, 2018 go to post

IF you did a Restore of "%SYS" DB  (.../mgr/CACHE.DAT)
then you may have destroyed essential instance specific installation information
Go back and do a fresh install. And don't touch %SYS during restore.

Robert Cemper · Mar 8, 2018 go to post

IF it was really only permissions you could run ^SECURITY from terminal prompt

USER>zn "%SYS"
%SYS>d ^SECURITY
1) User setup
2) Role setup
3) Service setup
4) Resource setup
5) Application setup
6) Auditing setup
7) Domain setup
8) SSL configuration setup
9) Mobile phone service provider setup
10) OpenAM Identity Services setup
11) Encryption key setup
12) System parameter setup
13) X509 User setup
14) Exit
 
Option? 1
1) Create user
2) Edit user
3) List users
4) Detailed list users
5) Delete user
6) Export users
7) Import users
8) Exit
 
or   Option? 2
1) Create role
2) Edit role
3) List roles
4) Detailed list roles
5) Delete role
6) Export roles
7) Import roles
8) Exit
 
or   Option? 3
1) Edit service
2) List services
3) Detailed list services
4) Export services
5) Import services
6) Exit
 
Option? 4
Export which services? * => *
Export to file name ServicesExport.xml =>
and so on...

and Import on your test server .....
But take care how you handle external connections! 

Robert Cemper · Mar 8, 2018 go to post

backups typically backup a DB in  Cachè but never a full installation. (e.g ref to registry and similar)
Do a fresh installation and next move / restore your DB

Robert Cemper · Mar 8, 2018 go to post

Thanks Vitaly!

My almost first task when I joined ISC was to translate a CSP training developed by "Salva" Jose-Tomas Salvador
from Spanish to German and English.
So I have very personal feelings about this subject.

Robert Cemper · Mar 7, 2018 go to post

Customizing DashboardViewer may take a lot of time for testing with questionable success.

Alternate approach: Trigger your source control manually.

- create a method to export your changes. example:

#; find actual changes
   &SQL(select List(documentname) into :list 
          from  %DeepSee_Dashboard.Definition 
         where timemodified-now()+1>0 )
   set  sc=$system.OBJ.Export(list,"DeepSee.xml")

- next define an Action (in a KPI) that calls you method
http://localhost:57774/csp/docbook/DocBook.UI.Page.cls?KEY=D2IMP_ch_action

- next define a Control "button" to your main Widget and add this Action to activate your source management.
I admit. It's no an automatic & generic solution as directly inside DashboardViewer  (engineering may have a hint howto use it)  
but you get the advantage to decide which dashboard you want to manage and when
since not every change in dashboards may need to go immediately to source control
And it's definitely simpler than to do it our of Studio.

Robert Cemper · Mar 7, 2018 go to post

sorry!

examining the source it turns out that this parameter didn't make it to call parameters (ZENURL) nor to settings.
though I found a bunch of comments  // +DTB103 - source control
with no hint how to use it.
It might be necessary to build a private copy.
Attention on line +7 says:
/// This class should be considered as *internal*; subclassing is not supported. 

Robert Cemper · Mar 7, 2018 go to post

Hi Evgeny,
class %DeepSee.UserPortal.DashboardViewer  has a property saveAction as %ZEN.Datatype.string;

Container for the current save mode for source control.

http://localhost:57774/csp/documatic/%25CSP.Documatic.cls?PAGE=CLASS&LIBRARY=samples&CLASSNAME=%25DeepSee.UserPortal.DashboardViewer#PROPERTY_saveAction

if you combine this with standard $system.OBJ.Export()  this may do it.

SAMPLES>s sc=$system.OBJ.Export("B*.DFI","DeepSee.xml")
 
Exporting to XML started on 03/07/2018 09:36:32
Exporting type : Basic Dashboard Demo.dashboard.DFI
Export finished successfully.
Robert Cemper · Mar 4, 2018 go to post

A good friend of mine provided this solution using also  JSON types and internal $LB() types for more detailed type analysis.
Of course there's no guaranty  for the hidden types in $LB() . 
 

types ; Show COS-Datatypes ; kav ; 2018-03-04
 //
 set obj=##class(Person).%New()
 write "VALUE",?15,"JSON",?22,"$LISTBUILD",! ,$TR($J("",32)," ","-"),!
 for val="453","abcd",1234,"abc"_$c(352), -34, 1.3, -7.9, $double(1.25),obj {
   write val,?15,$$TypeOf1(val),?22,$$TypeOf2(val,.txt),.txt! }
 quit
 // Return JSON datatype by the documented way
 //
TypeOf1(val) Public
{
  quit [(val)].%GetTypeOf(0) }
 // Return datatype by the undocumented $LB() way
 //
TypeOf2(val) Public
 if $length(val)>253
    set typ=$ziswide(val)+1
  else 
    set typ=$a($lb(val),2) }
  set txt=$case(typ
    ,1:" 8bitString"
    ,2:" 16bitString"
    ,4:" nonNegativeInteger"
    ,5:" negativeInteger"
    ,6:" nonNegativeFloat"
    ,7:" negativeFloat"
    ,8:" double"
    , :" ??? never seen before")
 
 quit typ
}
d ^types
VALUE          JSON   $LISTBUILD
--------------------------------
453            string 1 8bitString
abcd           string 1 8bitString
1234           number 4 nonNegativeInteger
abcŠ           string 2 16bitString
-34            number 5 negativeInteger
1.3            number 6 nonNegativeFloat
-7.9           number 7 negativeFloat
1.25           number 8 double
1@User.Person  oref   1 8bitString

 
Robert Cemper · Mar 1, 2018 go to post

you need an oref in ref 
and also in Myproperty1, ... 
So you have to check both . see answer

Robert Cemper · Mar 1, 2018 go to post
ClassMethod myfuct( id) As %String
{
  set ref=##class(myClass).%OpenId(id)
  If '$isobject(ref) quit "no object 1, no return"
  if '$isrobject(ref.
Myproperty1) quit "no object 2, no return"
  set str="my return: "_ref.Myproperty1.OtherClass1Property
  quit str
}
Robert Cemper · Mar 1, 2018 go to post

you do 

set ref=##class(myClass).%OpenId(id)

but you don't check if you really got an object.  the id might be invalid
continue with 

if '$isobject(ref) quit ""

Robert Cemper · Mar 1, 2018 go to post

the code causing the problem in MyClass.2.int looks most likely like this:

Set oid=$select(i%Myproperty="":"",1:$listbuild(i%Myproperty_""))

you are inside an ObjectMethod   and miss the actual Object  reference.
This happens when you try to access a property inside a Classmethod.
 classic mistake:

ClassMethod MyMethod(1,2,3) as %Status {
 set x=..Myproperty
}

correct use: 

ClassMethod MyMethod(oref,1,2,3) as %Status {
 set x=oref.Myproperty
}
Robert Cemper · Mar 1, 2018 go to post

Whether external backup or backup from a mirror (also asynchronous) or Caché backup you always have to identify
the point in time when your DB is logically consistent. What I think of is no open transactions, no open dependencies.

If you know that point in time you could separate your async mirror or shadow and run any backup from there.
Or just shut down your async server instance and run snapshots.
But there might also be a time gap between master and async server.
Once completed your async server can join again and catch up whatever time that may take.   
The critical point is to know when the async server has reached consistency.
But that depends on the application.
 

Robert Cemper · Feb 28, 2018 go to post

there is a method CopyFromStream that really moves the content to a new Stream
So your PDF moves from physical file to a Global stream that you work up and down as a "private" copy.
Without touching the original anymore. This might be a useful option.
 

Robert Cemper · Feb 28, 2018 go to post

for a file stream it's a physical file, for a global stream it's a global or part of it.
if you clear it you either delete the file or the global (or its part )that holds the stream.
stream in Caché describes a sequence of persistent bytes on disk that you work on with dedicated common methods.
this must not be mixed up with a stream of characters on a network connection. if you miss a character there it's gone. 

Robert Cemper · Feb 28, 2018 go to post

Clear() removes all content. The easiest way to CLEAR a file is to remove it. in any file system.

Robert Cemper · Feb 28, 2018 go to post

"lightweight" is the theoretical approach for object purists that want to have just 1 object covering the world and don't care about practical use. They often were moaning "oh only 1.n relationship".  
 As you noted "heavy" allows real relation management. And could be faster in some cases.

Robert Cemper · Feb 28, 2018 go to post

Hi Alexey,
You hit the point: "lightweight"  just documents the relation.  Full stop. No further service.
You have to service (ie. Delete) it at both ends.
If you use a serial object with OREF + Status)  you still have to service both ends.

The "heavy" variant does it centralized at one place.
Though from storage point of view you move out the additional subscript level from array.

Robert Cemper · Feb 27, 2018 go to post

Hi, Evegeny!
for both variants you work along the array by GetNext() method
for each employee you have an array with the OREFs of the company. So you have the full object at hands.
similar the opposite direction from company to employee and employee->nae in SQL or employee.name

And as we always have a Collection type Array indexing is simple either by (KEY) or (ELEMENT). whether you  need the ID or the OREF
http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GSQLOPT_indices#GSQLOPT_indices_collections

The only tricky action is DELETE: there you have to have a method to "DisRelate" before delete.
But real commercial systems never delete anything. Just set a flag "isDeleted". Which is much easier for any "undo" action. 

Robert Cemper · Feb 27, 2018 go to post

It's a value returned from OS:
So this might be platform dependent.
the call is  $zu(140,5,$select($$$isVMS&&(%file'[";"):%file_";*",1:%file))
the part for VMS deletes all versions of the file if the name is not terminated by " ;"

Robert Cemper · Feb 27, 2018 go to post

First I would expect Soap.InboundAdapter writes to stream and has no limit.

But if longstrings are enabled the MAXsize of a %String is ~3.6 MB.   Your description sounds to fit this.
You may look at your Adapter where the input goes.
But it might be also later processing of a stream to cause the problem.

Robert Cemper · Feb 27, 2018 go to post

doc say:

classmethod Delete(filename As %String, Output return As %Integer) as %Integer
Deletes the file filename. Returns true if it succeeds and false otherwise. Pass return by reference to obtain the low level return value in case of errors

so try:

set success = file.Delete(File, .return)

to see the reason for failing