My understanding is that while you can easily retrieve environment variables visible to your process using the $system.Util.GetEnviron() interface, you simply do not have access to an equivalent $system.Util.SetEnviron(), as setting of environment variables can be quite tricky, risky and very OS specific.

If you do absolutely need to be able to change an environment variable for your running process, and you are dealing with one specific platform, you can probably create your own $ZF("SetEnviron",var,value) code, based on OS specific calls like the Linux system service setenviron()..

Again: the short answer would be that out of the box you will be able to read but not set environment variables.
If you really do have the need of setting them, you would need to look into building the necessary $ZF call-out interface based on your target OS.


With the assumption that running a full integrity check on the primary, Live instance is not really an option here, my approach would be something along these lines:

- backup of your primary instance using your preferred third party tool

- automate the restore of the backup into a separate environment

- run the integrity check in this second server

I see a couple of advantages in such a scenario:
you can verify that your backups are indeed valid and can be restored, quite a good felling in case of actual needs at some point in time.

As an integrity check is quite I/O intensive, you would move all those extra IOs away from your Live storage and only affect a separate set of disks.

Our documentation includes a section on how to script integrity checks:

"Checking Database Integrity Using the ^Integrity Utility"

Hi Joyce,

I just tested the documentation steps on my Mac just to confirm that they would work correctly with the current Docker release, and it seems IO got everything going through correctly.

The "permission denied"  error suggests some kind of permission issue, and looking at your "docker run" command I have a strong suspicion that the problem may be coming from the --volume /Users/docker:/external mapping, as anything under "Users" is handled quite strictly by MacOS (and correctly so I would add:-)

Try your test by using a different path for your storage volume.. This is an example of what I ended up running with for my current test run (I used a /Temp/durable/ directory to store my key and password file):
docker run --name iris \
> --detach \
> --publish 52773:52773 \
> --volume /Temp/durable/:/external \
> --env ICM_SENTINEL_DIR=/external \
> acme/iris:stable \
> --key /external/iris.key \
> --before "/usr/irissys/dev/Cloud/ICM/ /external/password.txt"

docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                      NAMES
b23d2d4c8b1d        acme/iris:stable    "/iris-main --key /e…"   9 minutes ago       Up 9 minutes>52773/tcp   iris

Let us know if the /Users/docker path was indeed the cause of your issue.

While possibly being a bit out of scope for your specific request here, as it seems you may be working on a standalone server, I wanted to point out a recent Community article on "VM Backups and Caché freeze/thaw scripts" containing some useful batch examples too:

The article also includes discussions on the use of OS authentication for the script etc

Hi Anzelem,

if your question is "how can I allocate more than 2GB of memory for my shared memory segment", Dmitry already answered that pointing out that this is an expected limitation of your 32bit environment, with a switch to 64bit being the required factor to go over 2GB..

On the other hand, if your question is "why I am only getting 1.GB instead of the full 2GB", the answer is that by using manual configuration values, starting from your current 1622MB total shared memory, you can try to increase them by small amounts, until you find the ones that finally report a "Failed to allocate", but I would expect that you will not be able to go much further than a max of 1.7GB total:

there are internal structures both at the Caché and Windows level that also need to fit in the 32bit addressable space, thus reducing the actual space for the shared memory segment.

Hopefully this covers your question.. and let us know if there may be further points worth reviewing together.

Is there any specific reason for not wanting to use the RoutineList() query from the %Library.Routine class?

query RoutineList(spec As %String(MAXLEN=512), dir As %Integer, type As %Integer, nsp As %String)

    This query provides a list of all routines that match the pattern specified by spec.

    spec may contain both * and ? as wildcards. It may also consist of more than one, comma-delimited selections. For example:
    dir specifies the direction to search in, 1 is forwards and -1 is backwards.
    type is 1 to include OBJ files in the search and the default, 0 will just include INT, MAC, INC, BAS.
    nsp is the namespace to list from. If omitted, the query returns the routines from the current namespace. nsp can be either an explicit or an implied namespace. 

Your request could then be implemented with a simple call like:

 s tRS=##class(%ResultSet).%New("%Routine:RoutineList")
 d tRS.Execute("ABC*.INT")
 f  q:'tRS.Next()  s routName=tRS.GetData(1) w "Found ",routName,!

I have to pass.. as my example, expanded with your calculated/private Active property (a simplified version of it), still works as I would expect it to:

Property Name As %String(POPSPEC = "Name()") [ Required ];

Property NickName As %String(POPSPEC = "Name()") [ Private ];

Property Active As %Integer [ Calculated, Private, SqlComputeCode = { Set {Active}=($R(100))}, SqlComputed ];
select Name,NickName,Active from Test.PrivateTest
Name    NickName    Active
Hills,Lawrence B.    Wilson,Barb G.    0
Frost,Brendan H.    Smith,Zoe T.    98
Cooper,Tara C.    Edwards,Mo G.    19
Hanson,Howard H.    Cerri,Buzz X.    74
Hammel,Elmo P.    Klausner,Peter G.    77
Quincy,Robert Q.    Townsend,Alice M.    52

It will probably be "too basic" for your needs, but I was curious to test this, and got it working with the following class example:

Class Test.PrivateTest Extends (%Persistent, %Populate)
Property Name As %String(POPSPEC = "Name()") [ Required ];
Property NickName As %String(POPSPEC = "Name()") [ Private ];

A "select * from Test.PrivateTest" would only return my "Name" data, while a "select Name,NickName from Test.PrivateTest" returns the private property values too.

Can you get such a basic example working for you too?

If you post your class definition, someone could have some better suggestions/ideas.

I know this is not the ready-to-use procedure that you were looking for, but as a starting point for anyone landing here looking for ideas, some starting modules that you can use would be:

- automated restore of a BCK backup file can be accomplished with the EXTALL^DBREST or EXTSELCT^DBREST entry points.

- integrity check of one or multiple databases are available through the SYS.Database class, with the methods IntegrityCheck() or SilentIntegrityCheck()

Good morning Wolf,

I tested the 2017.1.726 Caché kit from our "Developer Download" page and, indeed, it is reporting an error during its un-zipping phase.

Using a copy of the same installation kit taken from an internal repository I could go through a normal installation without problems, so it would seem that the issue is limited to the copy made available through the download page.

We have asked for the archive to be replaced, and hopefully a new copy will go online soon.

For completeness, I wanted to mention that the Windows x64 Ensemble 2017.1.726 kit did download and install correctly in my tests.

Edit: let me edit this.. I got an error on the Ensemble kit too, different place. We will ask for that kit too being reviewed.