/*------------------------------------------------------------------------
   File        : roundtrips.p
   Purpose     : Count SERVER ROUND TRIPS for retrieval and reposition, by
                 sampling the _ActServer VST before and after each operation.
   Notes       : Single session on purpose - no harness, no writer.  With one
                 client connected the _ActServer deltas are attributable, which
                 they would not be if a second session were generating traffic.

                 The observation logs used everywhere else show record CONTENT,
                 so they can reveal a stale window but never a round trip.  This
                 probe answers the questions content cannot:

                   - does REPOSITION walk to its target (delta scales with
                     distance) or seek to it (delta constant)?
                   - does INDEXED-REPOSITION differ?
                   - is the stored metaschema (_File) fetched from the server at
                     all, or served from the client's schema cache?  Zero messages
                     means the prefetch question does not apply to it.
                   - are VSTs (_Connect) fetched per row?
                   - independent cross-check of the theme 9 result: a static
                     query without SCROLLING should cost ~one message per row,
                     while FOR EACH should cost far fewer.

                 Reading the VST is itself a server request, so BASELINE measures
                 the instrument's own cost and every figure below should be read
                 net of it.
 ----------------------------------------------------------------------*/

define variable nRows   as integer no-undo.
define variable before  as int64   no-undo.
define variable after   as int64   no-undo.
define variable baseCost as int64  no-undo.
define variable i       as integer no-undo.
define variable rids    as rowid extent 120 no-undo.

define query qPlain     for Book.
define query qScroll    for Book scrolling.
define query qIdxRepos  for Book scrolling.

/* Messages RECEIVED by all server processes = requests this client made. */
function srvMsgs returns int64 ():
   define variable t as int64 no-undo.
   for each _ActServer no-lock:
      t = t + _ActServer._Server-MsgRec.
   end.
   return t.
end function.

define stream rep.
output stream rep to "C:\oetest\roundtrips.out".

procedure report:
   define input parameter what  as character no-undo.
   define input parameter delta as int64     no-undo.
   define input parameter rows  as integer   no-undo.
   put stream rep unformatted
       substitute("&1 msgs=&2 rows=&3 net=&4",
                  string(what, "x(46)"), string(delta, ">>>>>9"),
                  string(rows, ">>>>9"),
                  string(delta - baseCost, "->>>>9")) skip.
end procedure.

put stream rep unformatted "proversion=" proversion
    " dbparam=" dbparam(ldbname(1)) skip(1).

/* ---- instrument cost: two samples with nothing in between ---- */
before = srvMsgs().
after  = srvMsgs().
baseCost = after - before.
put stream rep unformatted "baseline (two consecutive VST samples) = "
    string(baseCost) " msgs -- subtract this from every figure" skip(1).

/* ---- retrieval forms ---- */
before = srvMsgs().
nRows = 0.
for each Book no-lock:
   nRows = nRows + 1.
end.
after = srvMsgs().
run report ("FOR EACH Book NO-LOCK", after - before, nRows).

before = srvMsgs().
nRows = 0.
open query qScroll for each Book no-lock.
get next qScroll.
do while available Book:
   nRows = nRows + 1.
   get next qScroll.
end.
close query qScroll.
after = srvMsgs().
run report ("static DEFINE QUERY SCROLLING + GET NEXT", after - before, nRows).

before = srvMsgs().
nRows = 0.
open query qPlain for each Book no-lock.
get next qPlain.
do while available Book:
   nRows = nRows + 1.
   get next qPlain.
end.
close query qPlain.
after = srvMsgs().
run report ("static DEFINE QUERY no SCROLLING + GET NEXT", after - before, nRows).

before = srvMsgs().
nRows = 0.
find first Book no-lock.
nRows = 1.
repeat:
   find next Book no-lock no-error.
   if not available Book then leave.
   nRows = nRows + 1.
end.
after = srvMsgs().
run report ("FIND FIRST + repeated FIND NEXT", after - before, nRows).

/* ---- capture rowids for the reposition probes ---- */
i = 0.
for each Book no-lock by Book.book-id:
   i = i + 1.
   if i <= extent(rids) then rids[i] = rowid(Book).
end.

/* ---- REPOSITION distance sweep, plain ---- */
do i = 1 to 3:
   define variable target as integer no-undo.
   target = (if i eq 1 then 2 else if i eq 2 then 50 else 100).

   open query qScroll for each Book no-lock.
   get next qScroll.
   before = srvMsgs().
   reposition qScroll to rowid rids[target] no-error.
   get next qScroll.
   after = srvMsgs().
   close query qScroll.
   run report (substitute("REPOSITION TO ROWID -> row &1", string(target)),
               after - before, 1).
end.

/* ---- REPOSITION distance sweep, INDEXED-REPOSITION ---- */
do i = 1 to 3:
   define variable target2 as integer no-undo.
   target2 = (if i eq 1 then 2 else if i eq 2 then 50 else 100).

   open query qIdxRepos for each Book no-lock indexed-reposition.
   get next qIdxRepos.
   before = srvMsgs().
   reposition qIdxRepos to rowid rids[target2] no-error.
   get next qIdxRepos.
   after = srvMsgs().
   close query qIdxRepos.
   run report (substitute("INDEXED-REPOSITION -> row &1", string(target2)),
               after - before, 1).
end.

/* ---- _meta: stored metaschema vs VST ---- */
before = srvMsgs().
nRows = 0.
for each _File no-lock:
   nRows = nRows + 1.
end.
after = srvMsgs().
run report ("FOR EACH _File NO-LOCK (stored metaschema)", after - before, nRows).

before = srvMsgs().
nRows = 0.
for each _Field no-lock:
   nRows = nRows + 1.
end.
after = srvMsgs().
run report ("FOR EACH _Field NO-LOCK (stored metaschema)", after - before, nRows).

before = srvMsgs().
nRows = 0.
for each _Connect no-lock:
   nRows = nRows + 1.
end.
after = srvMsgs().
run report ("FOR EACH _Connect NO-LOCK (VST)", after - before, nRows).

output stream rep close.
