Jeffrey,

I'd try to define namespace global mapping, something like this:

[Map.YOURNSP]
...
Global_Ens*=YOURNSPDB,,YOURNSP-LOCKS
...

where

YOURNSP - your namespace
YOURNSPDB - database where ^Ens* globals are stored (mirrored one)
YOURNSP-LOCKS - database ^Ens* globals locks will be associated with (local one, RO or RW, it doesn't matter).

The similar definitions should exist for each global groups that can be locked.

Disclaimer: I didn't try this trick myself with mirrored DBs. It might help to bypass the locking problem, while not guarantee against other suprises one can face with running something on Mirror Backup member. Consulting with WRC might be of use... 

Hi Julius,

Your solution is beautiful; alas, this code

open jouFile:"WL":1 // try to get ownership

instantly returns $Test=1 in Caché for Linux as its behavior differs from Windows version in this case according to documentation:
Caché Development References  >  Caché I/O Device Guide  >  Sequential File I/O: OPEN Mode Locking

I've checked it in Cache for UNIX (Red Hat Enterprise Linux for x86-64) 2017.2.2 before writing here.

Here is my solution. A couple of words as a preface. There are two tasks:
#1

  • Switches journal and fixes the name of new journal file (e.g., in @..#GtrlJ@("JrnFirst")).
  • Processes the globals of a namespace. The algorithm of processing doesn't matter here, it's usually some kind of data re-coding. 

#2. This task occurred just because users' activity during the task #1 execution can introduce the changes in globals already processed by the task #1.

  • Wait for the next journal file available for processing (WaitForJrnSwitch());
  • Process the globals found in this journal using the algorithm similar to the task_#1's one.

The latter is a pseudo-code of WaitForJrnSwitch() method and GetJrnID(), its helper. 

 /// If new jrn is available, set %JrnID=Jrn ID and return 1;
/// waiting by ..#TimeWait steps till ..#TimeLimit
ClassMethod WaitForJrnSwitch() As %Boolean
{
 set rc=0
 set nTimes = ..#TimeLimit \ ..#TimeWait
 for i=1:1:nTimes {
  $$$TOE(sc, ..GetJrnID(.JrnID)) // current journal
  if %JrnID="" {
    set JrnNext=@..#GtrlJ@("JrnFirst")
  else {
    set JrnNext=%JrnID+1
  }
  if JrnNext<JrnID { // avoid extra journal switching ("by restore")
    set %JrnID=JrnNext
    set rc=1
    quit
  }  
  hang ..#TimeWait
 }
 quit rc
}


/// Get Jrn ID of the current journal file
/// Out:
/// returns %Status;
/// pJrnID - journal file name w/o prefix and "."
ClassMethod GetJrnID(Output pJrnID) As %Status
{
 set sc=1
 try {
   set file=##class(%File).GetFilename(##class(%SYS.Journal.System).GetCurrentFileName())
   set prefix=##class(%SYS.Journal.System).GetJournalFilePrefix() 
   set pJrnID=$tr($e(file,$l(prefix)+1,*),".")
 catch ex {
   set sc=$$$ERROR($s(ex.%IsA("%Exception.SystemException"):5002,'ex.Code:5002,1:ex.Code),$lg(ex.Data)_" "_ex.Location_" "_ex.Name)
 }
 quit sc
}

Hi Julius,

My solution is similar to yours while it is based on journal API only. If anybody is interested, I'll post it in a few days (being on vacations at the moment).

Thank you for reminding to check if the shutdown is in progress, while I am not sure how often my code should wake up to detect it for sure. Yours waking up each one second as I see.

Eduard,

You have just forgotten about "Щ" in your awesome one-liner, while the $replacing of "Ш" is excessive. So, it should look like that: 

 $tr($zcvt($replace($replace($tr(russian, "абвгдезийклмнопрстуфхыэАБВГДЕЗИЙКЛМНОПРСТУФХЫЭЖЦЧШЮЯжцчшюяьЬъЪ", "abvgdeziyklmnoprstufhyeABVGDEZIYKLMNOPRSTUFHYE婨味䍨卨奵奡穨瑳捨獨祵祡"),"щ","shch"),"Щ","Shch"),"O","UnicodeBig"),$c(0))

Another part of my solution was published as a comment here.

This trick with answers (fin.txt) and messages (fout.txt) files was possible with background job only as only this kind of Caché processes allows the separation principal-input device from principal-output one.

Controlling the execution state would not be so easy in this case as fout.txt is kept opened during the execution of JRNREST. I partially bypass this limitation looping my dejournaling activity for each journal file I need to restore and feeding JRNREST with only one file on each iteration  (pLast = pFirst); so it's possible to report the restore state of each file that has been restored with very modest delay as the restoration of one journal file is usually a quick process.

HTH and happy coding to you!

Robert,

As to (simulated) named arguments approach:

(+): Good readability.

(-):  We should be pretty sure that values would not contain separators, neither "=" nor ":", although screening of them is not a very hard problem ("\=", "\:", "\\"). 

(-): Handling binary data (e.g., $list or $bit) seems to be more serious problem. In this case it seems that one argument structured as $lb($lb("name1",value1),...$lb("nameN",valueN)) is better option.

David,

you can try

set rc=$zf(-1,"export MYVAR="_someValue)

while it would hardly work as Caché process environment will be destroyed after the process halt. Honestly, I've never tried it.

I usually use signal files to pass values back from Caché, as it was shown in the 1st sample here: How to return the status code of Cache process to OS shell script?

See Timothy Leavitt's answer to the same post for another option which is more convenient when you are to return numeric values.