home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 35 Internet
/
35-Internet.zip
/
srev13h.zip
/
SREFQUE.DOC
< prev
next >
Wrap
Text File
|
2001-03-27
|
31KB
|
746 lines
15 Apr 1998: SREF_QUEUE: Working with SRE-http queues.
Abstract: SREF_QUEUE is an SRE-http "macrospace" procedure that allows you to
work with "SRE-http queues". These queues provide
a convenient, queue-like means of storing and sharing data
in a globally accessible, semi-permanent location.
Table of Contents
I. Introduction
II. The SREF_QUEUE procedure
II.a SREF_QUEUE actions
II.a.1 POP and READ
II.a.1.i The TYPE modifer
II.a.1.ii The INFOFIELD modifer
II.a.1.iii Examples
II.b FIND
II.c PUSH and QUEUE
III. The INIT, KILL, LOCK and INFO actions
III.a INIT
III.b KILL
III.c INFO
III.d LOCK
IV. Examples
V. Using SREF_QUEUE with a dedicated daemon
Appendix 1. SREF_QUEUE error codes
--------------------
I. Introduction
SRE-http (as of ver 1.2L) supports a flexible form of "queue".
The primary purpose of these SRE-http queues is to store and retrieve
information in a globally accessible, semi-permanent location. In many ways,
they are functionally similar to REXX queues, but are much more easily
manipulated.
SREF_QUEUE "macrospace" procedure is primarily meant to be used by SRE-http
addons that have light to moderate needs (for passing and storing data).
If you have more substantial needs, you might want to use regular REXX queues,
or create an SRE-http daemon (see DAEMONS.DOC for a discussion of how
to work with SRE-http daemons). Another interesting possiblity is the SRE-Data
addon; which is designed to perform fast lookup in fairly large,
static datasets.
To support these queues, SRE-http uses its "variable storage daemon". This
introduces a few drawbacks:
> when GoServe shuts down, SRE-http queues disappear.
> The variable storage daemon services a number of SRE-http needs;
if an SRE-http queue is heavily used, other SRE-http functions will
be impacted.
The latter problem can be partially overcome by starting multiple
"variable storage" daemons. This does require some special configuration;
which is discussed in section V below.
--------------------
II. SREF_QUEUE
The SREF_QUEUE procedure is used to access and manipulate SRE-http queues.
SREF_QUEUE is called as:
retvalue=SREF_QUEUE(queueName,action,value,port)
where:
queuename: The name of a queue; it can be any REXX-style, variable name.
Queuename can also contain a daemon identifier, in which
case quenamename will be of the form: name.daemon_id
action: Type of action. and list of modifier. Valid actions include:
INIT, INFO, LOCK, PUSH, POP, READ, FIND, and KILL.
value: The record to be added (used with PUSH, FIND, and INFO)
port: Used when SREF_QUEUE is called from an external process (i.e;
not from a thread or child-process of GoServe).
Port should be the port that GoServe/SRE-http is running under
(typically, port=80).
The action parameter consists of an action, plus an optional list of modifiers.
The POP, READ, FIND, QUEUE and PUSH actions are described in section II.a to II.c.
Section III discusses the KILL, INIT, LOCK and INFO actions; and section IV
contains a simple example.
Summarizing what follows, to use SREF_QUEUE you should:
1) Initialize a queue using INIT.
2) Write to a queue using PUSH and QUEUE.
Read from a queue using FIND, POP or READ.
Administer a queue using the LOCK and INFO
3) Stop a queue using the KILL action
--------------------
II.a: The action parameter:
The action is used to specify what you want to do with an SRE-http queue.
It consists of two components: the action, and a list of modifiers.
There are five read/write actions: POP, READ, FIND, QUEUE, and PUSH
There are four administrative actions: INIT, INFO, LOCK, and KILL.
The modifiers (there can be several) depend on the action.
Notes:
* At its simplest, without specifing modifiers, using POP and QUEUE
will create a LIFO (last in,first out) queue.
* The actions and modifiers should be seperated by spaces. The "action"
should ALWAYS be first, but the modifiers can appear in any order.
* Several of the actions and modifiers can contain an = sign, followed
by a value. This = sign should NOT be surrounded by spaces.
For example: REC=19 is okay, REC= 19 is bad.
For most of these actions, a string (text or binary), or a numeric count,
will be returned. If an error occurs, either an empty string or a negative valued
error code will be returned. Appendix 1 summarizes the error codes.
II.a.1. POP and READ
POP will "read and remove" a record, while READ will "read and retain"
a record. Otherwise (with a few small exceptions) they are similar.
You can POP (or READ) from the top of a queue, the bottom of a queue.
You can also POP (or READ) multiple records; either explicitily specified,
or based on a timespan.
POP and READ can have two modifiers: a TYPE and an INFOFIELD.
TYPE: The location and size of the POP or READ. Valid TYPEs are:
TOP, BOTTOM, TOP=nnn, BOTTOM=nnn, NEWEST=ttt, OLDEST=ttt, and REC=nnn
INFOFIELD: The information to be returned. Valid INFOFIELDs are:
VALUE, TIME, SIZE, NOREAD, and #RECORDS
Note that the default TYPE is TOP, and the default INFOTYPE is VALUE.
Also, REC=nnn can only be used with READ.
II.a.1.i: The TYPE modifier
The TYPE modifiers have the following effects:
TOP : Read one record from the top of the queue
BOTTOM: Read one record from the bottom of the queue
TOP=nnn : Read nnn records from the top of the queue.
For example, TOP=3 will read (and remove) the top 3 records.
Note that TOP=1 and TOP have the same effect
BOTTOM=nnn: Read nnn records from the bottom of the queue
Note that BOTTOM=1 and BOTTOM have the same effect
NEWEST=ttt: Similar to TOP=nnn, but ttt refers to a time offset.
Thus, records written (to the top) within ttt (of the
current time) will be read (and removed).
ttt should contain a value and a time unit: where the case-
insensitive time unit is D,H,M or S (for days, hours, minutes
or seconds). For example: 0.042D=1H=60M=3600S.
OLDEST=ttt : Similar to NEWEST=ttt, but from the bottom of the queue,
and using the "queue creation time" as the reference time.
REC=nnn : Read from the nnn'th record: from the top if nnn<0
or from the bottom if nnn>0. For example:
READ REC=-1 is the same as READ TOP
READ REC=-2 will read the 2nd record from the top
READ REC=1 is the same as READ BOTTOM
Removing versus Retaining:
POP will read and REMOVE records; while READ will read and RETAIN
records. Thus, multiple calls to READ will return the same record (say,
the top record), while multiple calls to POP will return progressively
older records (until the queue is empty).
To READ progressively older records (without removing), you can increase (or
decrease) the nnn in a series of READ REC=nnn calls. That is, use
READ REC=-1, READ REC=-2, etc. Note that you may want to LOCK the queue
first (see section III for a discussion of queue LOCKing).
Multiple record returns:
For multiple record returns, each record will be delimited by a
CRLF ('0d0a'x). If your records are multi-line records, or contain
binary information, this will cause problems. You can work around this
by setting an alternate DELIMiter when you INITialize
No data results:
> If the SRE-http queue is empty, an empty string or a -3 error
code is returned.
> If the NEWEST (or OLDEST) record is older (newer) then specified
(as set by the value), then an empty string is returned (or
a -9 error code).
Multiple record READs and POPs:
> By default, when a "multiple record request" is made (such as TOP=5), then
CRLFs ('0d0a'x) are used to seperate records when. For binary records,
or for multiple-line records, this will clearly cause problems.
You can work-around this dilemna by setting a queue-specific DELIMiter
when you INITialize.
> If you ask for more records then exist, all records will be
returned (you can use the INFO action to get the length of an SRE-http
queue).
> For TOP or NEWEST: the topmost records are written first
For BOTTOM or OLDEST: the bottommost records are written first
> To extract records from the value returned, you can use:
mm=0 ; dlm='0d0a'x
do until value=""
parse var value aline (dlm) value
mm=mm+1; stuff.mm=aline
end
II.a.1.ii: The INFOFIELD modifier
You can specify a VALUE, TIME, SIZE, #RECORDS or NOREAD
INFOFIELD modifiers. These effect what information is returned.
Bot READ and POP recognize the same INFOFIELD delimiters:
VALUE : Return the value of the record(s). Note that records may be
of any length, and may be text or binary.
ID : Return the value of the ID field.
TIME : The time the record was written,as an absolute date. For example:
13:33:51 21 Nov 1997 will yield 729348.56517
SIZE : Size of the record, in bytes
#RECORDS : A count of the number of records that would be returned.
This is designed to be used with READ NEWEST and READ OLDEST --
it tells you how many records are newer (or older)
then the specified timespan. And if used with POP, it's
a quick way of removing too new (or too old) records.
NOREAD : Used with POP.
POP the record(s), but don't bother returning any information.
This speeds up removal of records from the queue, since SREF_QUEUE
won't wait for a status message to be returned from the
storage daemon. However, this means that several errors will
not be reported; thus, NOREAD should be used with some caution.
A Shortcut: You can use STRIP as a short hand for POP NOREAD.
II.a.1.iii Examples of POP and READ
a=sref_queue('myqueue','POP TOP')
a=sref_queue('myqueue','POP TOP VALUE ') -- this is the same as POP TOP
a=sref_queue('myqueue','POP NEWEST=30s')
a=sref_queue('myqueue','POP BOTTOM=6 ')
a=sref_queue('myqueue','POP TOP TIME')
a=sref_queue('myqueue','READ REC=1')
a=sref_queue('myqueue','READ BOTTOM REC=3')
a=sref_queue('myqueue','READ OLDEST=1h #RECORDS')
a=sref_queue('myqueue','READ TOP=5 SIZE ') -- 5 sizes, seperated by CRLFS
a=sref_queue('myqueue','POP NOREAD TOP ') -- removes top record
a=sref_queue('myqueue','STRIP') -- same as POP TOP NOREAD
II.a.2: FIND
FIND is used to search the queue for a match. By default, it will search
the "ID" field (that can be optionally set when you PUSH or QUEUE a
record). However, it can also be used to search the "values" of the
records (but the search will be slower).
FIND can have a TYPE, ID, MATCH, and INFOFIELD modifiers. You MUST also
specify a "value" parameter containing the string (text or binary) to search for.
Based on the TYPE and INFOFIELD modifiers, the first match will be returned.
The valid TYPE modifiers are:
TOP : Start search from the top of the queue.
TOP=nnn: Start search from the nnn'th record (inclusive), where
nnn=1 means "top of the queue".
BOTTOM: Start search from the bottom of the queue.
BOTTOM=nnn: Start search from the nnn'th record (inclusive), where
nnn=1 means "bottom of the queue".
Note that if the TYPE modifier is not specified, TOP is assumed.
The ID modifier is used to select whether to search the ID or "value" fields
of the record.
ID=YES : search the ID field
ID=NO : search the "value" of the record
By default, ID=YES is used.
Note that when searching the ID, a case insensitive search is used. When
searching the "value" field, a case sensitive search is used.
The MATCH modifier is used to set what kind of search to perform.
MATCH=EXACT : Exact match.
MATCH=PARTIAL : Case insensitive partial match -- can match any substring
(note that ID searchs are always case insensitive).
MATCH=WILD : Wildcard match -- * characters will be used to do a
wildcard match.
Note that the default is EXACT. Although WILD= is fairly powerful (you can
have multiple *s), it's somewhat slower; in many cases PARTIAL can be used
instead.
The INFOFIELD modifier dictates what information should be returned
(see the descriptions of the READ and POP INFOTYPE modifier for
further details):
VALUE: Return the value of the record.
TIME: The time the record was written,as an absolute date.
SIZE: Size of the record, in bytes
ID: Id of the field
REC: Record number of the match (from the bottom if READ BOTTOM,
otherwise from the TOP). Can be used with READ REC= to directly
query the record (after you've found a match), or as a base
for another search (i.e.; add 1 and use in TOP=nnn).
Note that if the INFOFIELD modifier is not specified, VALUE is assumed.
The "value" parameter should contain the string to search for.
This string will be compared against the ID field, or the "value" field, of
each record, with the first match returned.
Examples:
a=sref_queue('myqueue','FIND','MY_DAD ')
a=sref_queue('myqueue','FIND BOTTOM TIME ID=NO MATCH=PARTIAL ','chevy')
a=sref_queue('myqueue','FIND BOTTOM=10 TIME ','WILD=*TRUCK*')
II.a.3: PUSH and QUEUE
PUSH and QUEUE are used to place records on the queue. You can add a record
to the top or bottom of the queue.
The action parameter consists of a TYPE and several OPTIONs. With PUSH the
TYPES are TOP, BOTTOM and REC=nnn. The OPTIONS include QUICK, REMOVE, and ID.
QUEUE is actually a shorthand for PUSH BOTTOM -- hence, no TYPE is needed.
In addition to the action, you must specify a value parameter. The value
parameter can be any text or binary string.
TYPEs for PUSH:
TOP: Write a record to the top of the queue.
BOTTOM: Write a record on the bottom of the queue. Note that QUEUE = PUSH BOTTOM
REC=nnn: Write to record nnn; where nnn=1 is the bottom, and
nnn=-1 is the top.
Note that if a PUSH actions has no TYPE modifier, TOP is assumed.
A TYPE should never be used with QUEUE -- QUEUE always means PUSH BOTTOM!
OPTIONS for PUSH and QUEUE:
QUICK: Do not wait for a response from the variable storage queue.
This speeds things up a bit, but is somewhat riskier
(since errors are more likely to be undetected).
REMOVE: If the queue currently has its maximum value of records
(as specified by the INIT action) remove a record and then
write this record.
If REMOVE is not specified, a "can't write new record"
error is returned.
The record removed will be at the "other end" of the queue. Thus,
PUSH TOP REMOVE may cause the bottom record to be removed; while
PUSH BOTTOM REMOVE (or QUEUE REMOVE) may cause the top record to be
removed.
ID=xxx: Set the ID field for this record with value xxx.
xxx can be any length text string, but can not contain
spaces or CRLFs. We recommend keeping it relatively short
(say, less than 30 characters).
The ID field is used with the POP and READ "ID" INFOTYPE,
and can be searched by the FIND action.
Caution concerning PUSH REC=nnn
As with READ REC=nnn, the sign of nnn determines whether the record
is determined from the top or bottom of the queue.
As a relative number (from the top or bottom), additions/subtractions
from the queue will change a record's REC number.
This can cause unexpected problems in cases where multiple threads have
access to the queue.
Therefore, you may want to LOCK the queue before using
PUSH REC=nnn and READ REC=nnn.
Time of Creation:
When you PUSH or QUEUE stores a record, the current time is also stored
(accurate to about 1 second). READ NEWEST=ttt and POP NEWEST=ttt use
this to selectively return a set of records -- all records stored within
a specified timespan will be returned.
Examples:
a=srefqueue('myq','PUSH TOP', ' this is a record on the top')
a=srefqueue('myq','QUEUE ',' this is a bottom record')
a=srefqueue('myq','PUSH TOP ID=MY_DAD',birthday)
a=srefqueue('myq','PUSH BOTTOM QUICK','store me, and move on ')
a=srefqueue('myq','PUSH REMOVE',' store me, and make room ')
a=srefqueue('myq','PUSH REC=10 ID=TENTH_VICTIM ',' replace the 10th record')
--------------------
III. INIT, KILL, INFO and LOCK
III.a. INIT
The INIT action is used to initialize a queue, and to set a few INIT_OPTIONS.
The INIT_OPTIONS should be set in the "value" parameter; and may include any
or all of the following:
SIZE=nnn : Maximum size of the queue (in records). Thus, SIZE=100
means "no more then 100 records".
SIZE=0 means "no limit"
LIFESPAN=ttt : Clear out records with that are older then lifespan.
As with other SREF_QUEUE timespans, you can specify
days, hours, minutes or seconds (i.e.; 1D=24M=3600M).
LIFESPAN=0 means "indefinite lifespan".
Caution:
To save time, LIFESPAN will only check from the
bottom of the queue up; and stop when it hits a
"still alive" record. Thus, LIFESPAN should NOT be
used for queues that will have records added to the
bottom!
DELIM=ppp : Specify an alternate delimiter to use to seperate records
on multiple-record returns. By default, a CRLF ('0d0a'x) is
used. If you have multiple-line records, or binary records,
this can cause problems. The use of an alternate "delimiter"
can often offer a workaround (so long as you know that the
alternate delimiter is never used in the records!).
Note that ppp MUST be a "packed 64" string. You can
use SREF_MKPACK64 to create such a string. For example:
mydelim='0d0a'x||' &&%**%&& '||'0d0a'x
ppp=mk_pack64(mydelim)
foo=sref_queue('ourqueue','INIT ','DELIM='||ppp)
and then use mydelim when parsing multiple line returns
(that is, do NOT use ppp; ppp is only used to transfer
information to SREF_QUEUE).
By default, SIZE=0, LIFESPAN=0 and DLM='0d0a'x
Examples:
Set up an unlimited length queue named 'myqueue_1'
status=SREF_QUEUE('myqueue_1','INIT')
Set up an 100 record (maximum) queue with the name 'his_queue', and
automatically remove records older then 1 hour.
status=SREF_QUEUE('his_queue','INIT',' size=100 lifespan=1h ')
The returned value (status) will be 1 if success, and a negative number if
an error occured. Error codes include:
-5 : Queuename already exists
-10 : Queue not specified
-187: System error.
Notes:
* When a maximum is hit...
If REMOVE is not a PUSH (or QUEUE) OPTION:
then additional records will not be accepted -- and a -8
error code is returned.
You'll have to POP open a space on the queue.
If REMOVE is a PUSH OPTION
then a record will be removed from the "other end" --
for example: for PUSH TOP, a record will be removed from the
bottom end (the new record being added to the top).
* If you write to a queue without initializing, a new queue will be created
with unlimited length, infinite lifespan, and a CRLF delimiter.
* When you INITialize a queue, the "creation time" is recorded. The "creation
time" is used with READ OLDEST. Note that the creation time can not
be changed (short of KILLing and reINITializing the queue).
* Removal of "older then lifespan" records occurs after every PUSH
(or QUEUE). As noted above, a "work from the bottom up until
you hit a live record" algorithim is used -- thus, if you add records
to the bottom of a queue, LIFESPAN will have unexpected consequences.
--------------------
III.b KILL
KILL is used to end a queue. Use KILL to save resources.
Example:
status=sref_queue('myqueue','KILL')
will kill the myqueue SRE-http queue.
The returned value will equal the number of records that were in
the queue. If an error occurs, a negative value will be returned.
Error codes include:
-1 : No such queuename
-10 : Queue not specified
Note that anyone call kill an SRE-http queue -- SRE-http queues are not
"owned" !
--------------------
III.c INFO
INFO is used to obtain info about the SRE-http queue. The value parameter is
used to specify what to get. Valid values are:
RECORDS : # of records in queue; 0 if none.
SIZE : Total storage, in bytes. 0 if no records, or if all empty
records.
CREATION : Time of creation, in "julian" format. For example:
13:33:51 21 Nov 1997 will yield 729348.56517
MAX : Maximum size (0 if unlimited)
LOCK : Return LOCKING status. If not locked, or if the LOCK has
expire, a 0 is returned. Otherwise, the current
key is returned (note that the default key is "1").
There several "summary of all queues" options. To uses these, queuename
should be * (or *.daemon_id). These "summary options" are:
#QUEUES : Number of queues
SIZE : Size (in bytes) of all queues
NAMES : Names of all the queues (in a space delimited list)
A negative returned value is used as an error code, including:
-1 : No such queuename
-4 : No such value parameter
-10 : Queue not specified
Examples:
To find the current number of records in the myqueue:
ngot=sref_queue('myqueue','INFO','Records')
To find the maximum size of myqueue:
maxsize=sref_queue('myqueue','info','max')
To list all currnently active queues:
nqueues=sref_queue('*','INFO','NAMES')
III.d LOCK
The LOCK action is used to lock a queue; which means that records can
not be added or removed. There are two variants of LOCK.
LOCK ON=aaa : Lock a queue, with a key of aaa
and
LOCK OFF=aaa : Unlock a queue, using the aaa key.
The "aaa" key is optional; if not specified, a value of 1 is used.
Key's can be used to help independent processes know "who has locked the queue".
For example:
LOCK ON : Lock the queue, using the default key (1).
LOCK ON=T1 : Lock the queue, using a key of T1
LOCK OFF=T1 : Unlock the queue IF it was locked with a key of T1
LOCK OFF : Unlock the queue, regardless of what the key is.
Thus, LOCK OFF is universal -- which means that anyone can unlock a
queue!
When you LOCK a queue you can also specify, in the value parameter, a
timspan; after this timepspan the queue will be unlocked. If not
specified, the queue will be locked indefinitely. As with other SREF_QUEUE
timespans (such as in POP NEWEST=ttt), a (case insensitive) D,H,M, or S
unit should be the last character of the timespan.
For example, six hours can be spedified as: 0.25D, 6H, 360M, or 21600s
Queue locking is most useful when used prior to a READ REC= and PUSH REC=
(since it prevents additions to, and removals from, the queue; relative
positions will be stable). However, should a thread that locks a
queue fail/forget to unlock it, the queue will remain locked until
the timespan expires (perhaps indefinitely), or until some other thread
decides to unlock it (note that anyone can LOCK or UNLOCK a queue).
As mentioned above, in highly multi-threaded environments, the KEY
can be used to help keep track of who's "locked" the queue.
LOCK will return a 1 for success (either locked or unlocked), or
a negatively valued error code:
-1 : No such queuename
-10 : Queue not specified
-15 : Mismatched key (you can use INFO to find the current key)
-14 : Queue already locked
Examples:
astat=sref_queue('myqueue','LOCK ON','10s')
astat=sref_queue('myqueue','LOCK ON=T1')
astat=sref_queue('myqueue','LOCK OFF=T2')
astat=sref_queue('myqueue','LOCK OFF')
--------------------
IV: An Example
**** The following is an SRE-http addon that provides a useless demonstration:
parse arg ddir, tempfile
myq='myqueue'
a1=sref_queue(myq,'INIT 100') /* initialize a queue, max of 100 records */
call lineout tempfile,' Sample results '
call lineout tempfile,' '
if a1<0 then call lineout tempfile,' Warning: queue exists '
call lineout tempfile,' '
call lineout tempfile, ' loading ... '
aa=sref_queue(myq,'PUSH ','This is line 1')
call lineout tempfile," PUSH result= "aa
aa=sref_queue(myq,'PUSH ID=GREAT_1 ','This is line 2 ')
call lineout tempfile,' PUSH ID result = 'aa
aa=sref_queue(myq,'QUEUE ID=BOT_ONE ','This is line zero')
call lineout queuefile', QUEUE result= ' aa
call lineout tempfile, ' '
call lineout tempfile, ' retrieving ... '
in=sref_queue(myq,'INFO','SIZE')
call lineout tempfile,' INFO SIZE='in
w1=sref_queue(myq,'FIND BOTTOM ','GREAT_1')
call lineout tempfile,' FIND ID = ' w1
b1=sref_queue(myq,'POP')
b2a=sref_queue(myq,'READ BOTTOM SIZE')
b2b=sref_queue(myq,'READ BOTTOM')
b2ba=sref_queue(myq,'READ BOTTOM SIZE')
b2bb=sref_queue(myq,'READ BOTTOM TIME')
b2bc=sref_queue(myq,'READ BOTTOM ID')
b3=sref_queue(myq,'POP top=2')
b4=sref_queue(myq,'READ')
call lineout tempfile,' POP result=' b1
call lineout tempfile,' READ BOTTOM SIZE=' b2a
call lineout tempfile,' READ BOTTOM (val,size,time,id) = ' b2b', 'b2ba', 'b2bb', 'b2bc
call lineout tempfile,' POP top=2 = ' b3
call lineout tempfile,' READ = ' b4
call lineout tempfile
'FILE ERASE type text/plain name ' tempfile
return 'test queue '
**** Will return:
Sample results
Warning: queue exists
loading ...
PUSH result= 1
PUSH ID result = 1
retrieving ...
INFO SIZE=45
FIND ID = This is line 2
POP result= This is line 2
READ BOTTOM SIZE= 17
READ BOTTOM (val,size,time,id) = This is line zero, 17, 729352.04117, BOT_ONE
POP top=2 = This is line 1
This is line zero
READ =
--------------------
V: Running SREF_QUEUE with a dedicated daemon
As mentioned in the introduction, SREF_QUEUE uses the SRE-http "variable
storage daemon" to store SRE-http queues. This daemon also provides a number
of other services to SRE-http, such as "variable storage" and storage for
the "hit cache". Thus, heavy use of SREF_QUEUE (such as extensive
ID searches) may adversely impact the performance of other SRE-http functions;
hence reponse time for other requests (that have nothing to do with the
SRE-http queues).
In order to avoid some of these problems, you may want to use a seperate
"daemon" for SRE-http queue storage. In fact, you can even generate several
queue storage daemons, with each of these daemons handling a subset
of the SRE-http queues (in the extreme, you could have one daemon per
SRE-http queue).
To do this requires two steps:
1) Changing the STORAGE_DAEMONS parameter
2) Modifying the queuename argument
The STORAGE_DAEMONS parameter (which is set in SREFMON.CMD) controls how
many instances of the SRE-http "variable storage" daemon are launched.
By default (STORAGE_DAEMONS=1) a single instance is launched. Increasing
this parameter will increase the number of "variable storage daemons"
launched. That is, when STORAGE_DAEMONS=3, then 3 instances of this daemon
are launched.
Note that these daemons are functionally independent -- they do NOT share
data storage. Thus, when using an particular SRE-http queue, you have to
decide which "instance" of the daemon to use, and stick with this decision.
Given that multiple storage daemons are avaiable, you can dictate
which one to use by appending (after a .) a daemon_id to the end of the
queuename. The daemon_id is simply a number between 1 and STORAGE_DAEMONS.
Example: to initialize the "myqueue" SRE-http queue under the number 2 daemon,
and then PUSH a record:
stat=sref_queue('myqueue.2','INIT')
if stat>0 then do
stat2=sref_queue('myqueue.2','PUSH','Hello world')
end
Notes:
* queuename.1 is the same as queuename -- the "number 1 daemon" is always
the default daemon.
* if you specify a non-existent daemon id, an error will occur; with
either an empty string returned, or a -187 error code.
--------------------
Appendix 1. SREF_QUEUE Error codes
Error codes will be returned when some kind of error occurs. Their
values will depend on what action was requested.
action=READ, FIND or POP
If INFOFIELD=VALUE
For all errors, an empty string is returned.
If INFOFIELD=SIZE, ID, TIME, RECNUM
-1 = no such queuename
-2 = no such record (only used with READ REC)
-3 = empty queue
-8 = bad value
-9 = no records within selected timespan (used with NEWEST and OLDEST)
-10 = queue name not specified
-11 = no id specified (only used with FIND)
-12 = no id match (only used with FIND)
-16 = FIND: offset > then # records in queue
-20 = queue locked (only used with POP)
-100 = no such modifier (2nd word not OLDEST NEWEST TOP or BOTTOM)
action=INIT
-5 = queuename in use
-6 = bad value for maximum size
-10 = queuename not specified
action=KILL or INFO
-1 = no such queuename
-4 = no such INFO value (not RECORDS CREATION MAX SIZE #QUEUES NAMES)
-10 = queuename not specified
action=LOCK
-1 : No such queuename
-10 : Queue not specified
-15 : Mismatched key
-14 : Queue already locked
action=PUSH
-1 = no such queuename
-2 = no such record (used with PUSH REC)
-8 = no room left on queue
-10 = queuename not specified
-20 = queue locked
For all actions:
System errors cause a -187 to be returned.
System error include:
specifying a non-existent daemon_id that
could not create semaphore (used to communicate with daemon)
could not use semaphore
problem communication with daemon
Note that when a system error occurs, error messages will be displayed
in the pmprintf window.