======================================================================
USING REFRESH & VERIFY IN MULTI-USER APPLICATIONS
======================================================================
PRODUCT : R:BASE VERSION : 3.1 or Higher
CATEGORY : PROGRAMMING SUBCATEGORY : MULTI-USER
======================================================================
From David Blocker, 65 Morse Street, Sharon, MA 02067. David is an
R:BASE author, consultant, and trainer. With Bill Downall, he recently
wrote and self-published a book on R:BASE 3.1. The material in this
article is adapted from his workbook on networking R:BASE 3.1.
In a network (multi-user) environment, R:BASE uses a system called
concurrency control to protect against data conflicts when more than
one person edits the same data at the same time.
The different levels of concurrency control are basically the same as
those described in Who Locked Me Out? in the July/August 1990 R:BASE
EXCHANGE. But in R:BASE 3.1, developers can use a new command SET REFRESH
to better control when and how R:BASE tells users about changes made to
the same row by other, concurrent users.
Two commands, SET REFRESH and SET VERIFY, affect what you see on the
screen when you edit data using either a form or the Browse/edit screen
(the screen brought up by choosing Info or Views from the R:BASE Main
Menu or by using the EDIT or BROWSE commands from the R> prompt).
The SET VERIFY Command
======================
SET VERIFY ROW and SET VERIFY COLUMN tell R:BASE when to inform you
that someone else just changed the data you're currently editing with
a form.
<> When VERIFY is set to COLUMN, R:BASE alerts you when someone else
changes the data in the exact column and row you are currently in.
<> When VERIFY is set to ROW, R:BASE alerts you when someone else
changes any column in the exact row you are currently in.
In both cases, R:BASE alerts you only when you try to save your changes
to the row. If you just look at it, R:BASE normally does not notify you
that a change was made by someone else unless you use SET REFRESH to
cause R:BASE to automatically refresh the display at a given interval.
The VERIFY setting doesn't affect deletions. With either setting, R:BASE
tells you if someone else deleted the row while you were editing it but
only when you save changes to the row.
In the event of an editing conflict in which two users are changing the
same row, the last one out determines the final changes to that row.
For example, Alan and Sue both edit the same row at the same time and
Alan saves the row before Sue makes her changes. When Sue completes her
changes to the row and tries to save it, R:BASE will give her a message
showing Alan's changes. At that point, Sue can either leave the row as
is, accepting Alan's changes, or she can edit the row to reinstate her
own changes. But she'll have to type them in again (see examples below).
The SET REFRESH Command
=======================
If you want R:BASE to notify you of all changes, regardless of whether
you make a change, you have two options:
<> Use SET REFRESH in conjunction with SET VERIFY to set up an automatic
screen refresh.
<> Press [Ctrl-F10] in a form
When REFRESH is set to zero (the default), R:BASE won't automatically
refresh form screens. This command sets REFRESH off:
SET REFRESH 0
To set REFRESH on, set it to a number between 10 and 65535 seconds. For
example, the following command tells R:BASE to automatically refresh
form screens every 12 seconds:
SET REFRESH 12
Now you'll see changes made to the row by others during the last 12
seconds whether or not you tried to save changes to the row.
When REFRESH is set to 10 or more, R:BASE automatically refreshes both
forms and Browse/edit screens.
R:BASE refreshes a form screen after the REFRESH time period and gives
the messages described in the examples below.
<> R:BASE refreshes a Browse/edit screen more often. R:BASE refreshes
the screen as soon as you move the cursor if you haven't moved to
a new row in the SET REFRESH time period or if someone changed that
table's data since the last time you moved the cursor. R:BASE never
refreshes the Browse/edit screen until you move the cursor.
Settings Are Station Specific
=============================
Each workstation on the network makes its own settings at the R>
prompt, in the Settings menu, or in application code. For example,
one workstation might set VERIFY to ROW while another sets VERIFY to
COLUMN. A third workstation might turn auto-refresh off by setting
REFRESH to 0 while a fourth has REFRESH set to 10 seconds.
Example: VERIFY Set to COLUMN
=============================
Alan and Sue are both using forms to edit Wanda Smith's record. Alan
changes Wanda's first name to Cindy and saves the row. Assuming that
REFRESH is set to zero (the default) and VERIFY is set to COLUMN (the
default), here are several scenarios showing how the form will behave
for Sue.
If Sue only looks at the row and then moves on to the next row by
pressing [F8] or by using the menu, or if she chooses to quit from the
form, R:BASE won't tell her that Alan changed the row.
If, instead, Sue changes Wanda's last name to Smithe but doesn't touch
the first name and then she saves the row, R:BASE won't tell her that
Alan changed the row. The name on the row will now be Cindy Smithe.
You might notice a quick shifting of the screen just before R:BASE
leaves the form or brings up the next row. In that split second, R:BASE
shows Alan's changes on the screen, but Sue gets no explicit message
and no opportunity to make a change. Alan gets no message. Even though
the changes were made simultaneously, Sue had not yet saved her change
when Alan saved his. Because VERIFY is set to COLUMN and Alan and Sue
changed different columns, R:BASE doesn't treat either change as
newsworthy for the other user.
If, however, Sue changes Wanda's first name to Joan and her last name
to Smithe (remember that Alan has already changed the first name to
Cindy), R:BASE displays the following two messages at the bottom of
the form when Sue tries to save the row: Blinking shows another user's
conflicting changes. Press Enter to edit the displayed data; press Esc
to discard your changes. In addition to the messages, Cindy is
highlighted on the form to draw Sue's attention to Alan's change. Now
it's Sue's call. She can bow to Alan's change by pressing [Esc]. But
then Sue's last name change to Smithe will not be saved. Sue can press
[Enter] to have the last word. If she presses [Enter], R:BASE places
the cursor in the first name field and display Alan's data: first name
Cindy, last name Smith. Sue can now change the first name to Joan and
the last to Smithe and save the row to make the final change. Alan gets
no retroactive message telling him that someone else has undone his
changes. The last one out gets the message and gets to decide. If more
than two users change the same row at the same time, the first user to
save would get no message and the others would each get a message as
they saved the row. The final decision would rest with the last person
to save the row.
If you try to save your changes by pressing [Esc] and selecting Exit
from the menu, R:BASE first asks whether you want to save your changes.
Only if you answer Yes will concurrency control kick in and tell you of
the conflict.
Here's a final scenario. If Sue makes no changes to the row but while
looking at the row presses [Ctrl-F10] to refresh the screen, R:BASE
displays Alan's saved changes and puts these messages at the bottom of
the screen: Blinking shows another user's conflicting changes. Press
any key to continue.
In the previous instance, Sue wanted to save her changes, and R:BASE let
her choose to accept Alan's edits or reinstate her own. But in this case
Sue has in effect asked, Has anyone else changed this row in the same
columns I've changed? In this case, R:BASE's response depends on the
position of the cursor. If it's in the first name field, R:BASE assumes
you were about to change that column and responds by highlighting Alan's
change to the first name (Cindy), telling you that the highlighted fields
have changed. Then R:BASE displays the message Press any key to continue.
When Sue presses a key, R:BASE returns the cursor to the conflicting
field and displays Alan's change. If the cursor is in a field that Alan
didn't change when Sue presses [Ctrl-F10], however, R:BASE just displays
Alan's change with no message. Because VERIFY is set to COLUMN, R:BASE
is set to inform you only if a change was made to a column you changed.
If Sue changes the last name to Smithe and then presses [Ctrl-F10],
R:BASE keeps Sue's last name change and also displays Alan's change, so
the name now reads Cindy Smithe. Again, Sue gets no message informing
her of the conflict because according to the VERIFY setting no conflict
exists.
Example: VERIFY Set to ROW
==========================
If you want R:BASE to inform you if any change is made to the same row,
even if that change does not conflict with your changes, set VERIFY to
ROW with this command:
SET VERIFY ROW
Again assuming that REFRESH is still set to 0, here's how the form will
behave for Sue once Alan changes the first name to Cindy and saves the
row.
If Sue only looks at the row and then moves on by pressing [F8], by
choosing Next row under Go to on the menu, or by choosing Exit to leave
the form, R:BASE won't tell her that Alan changed the row because no
conflicting changes occurred.
If Sue changes Wanda's last name to Smithe without touching the first
name, however, R:BASE will show the row as it was when Alan saved it
(first name Cindy and last name Smith) when Sue tries to save it. Sue's
changes are no longer shown. R:BASE will also show these two messages
at the bottom of the form: Another user changed this row. The database
contains the displayed information. Press Enter to edit the displayed
data; press Esc to move on. But in this case, the changes made by Alan
are not highlighted.
Again, it's Sue's call. She can accept Alan's change (Cindy Smith) by
pressing [Esc], or she can press [Enter] and have the last word. If she
presses [Enter], R:BASE places the cursor in the field where Sue was
when she tried to save the row. Now Sue can change the last name to
Smithe again and change the first name back to Wanda.
If Sue changes the first name to Joan instead of changing the last name,
the form behaves the same when Sue attempts to save it. R:BASE shows
Alan's saved row and displays the same message: Another user changed
this row. The database contains the displayed information. Press Enter
to edit the displayed data; press Esc to move on. Sue can accept Alan's
row or press [Enter] to have the last word.
If Sue presses [Ctrl-F10] instead of trying to save the row, R:BASE
displays Alan's saved row and shows this message at the bottom of the
form: Another user has updated/changed this row. Press any key to
continue.
When Sue presses a key, R:BASE returns her to the spot where where she
was when she pressed [Ctrl-F10]. Sue will have lost any changes she made
up to that point, so she'll have to rekey them.
Deletes
=======
When a network user deletes a row, R:BASE handles the deletion the same
way no matter what the VERIFY setting. Suppose that Alan and Sue are
again both editing Wanda's record. Alan deletes the row.
If Sue makes no changes to the row and moves forward or back to another
row, R:BASE doesn't tell her about the deletion. Remember, no conflict
exists unless two people try to change the same row at the same time.
If she then tries to return to the row Alan deleted, she'll find it's
gone.
If Sue makes any change, R:BASE will display this message when she tries
to save the row or move to another row: Another user deleted this row.
Press Enter to add your row; press Esc to accept deletion.
If Sue presses [Esc], the row is gone. But if she presses [Enter], the
row is placed back in the database with Sue's data. Now, if Alan presses
[F8] or [F7] to move back to the row he thought he'd deleted, he'll find
the row restored to the database.
Note that R:BASE adds the row back at the end of the table, so it becomes
the last row.
Here's a final scenario. If Sue makes no changes to the row Alan just
deleted but presses [Ctrl-F10] for a status check, R:BASE will give her
the same screen and message as if she had made a change. Again, she can
accept or abort the deletion.
Setting REFRESH
===============
If you don't press [Ctrl-F10] to ask for a status check on the row, you
won't be alerted to other people's changes unless you try to change
something in the row. If you want all concurrent users to see changes
even if they aren't making changes, set REFRESH to a value between 10
and 65,535 seconds.
For example, if you set REFRESH to 10 seconds, R:BASE refreshes the
screen every 10 seconds either showing the same screen or showing a
changed screen with a message at the bottom. The message R:BASE displays
corresponds to the message R:BASE would have displayed had you pressed
[Ctrl-F10].
At first glance, this seems like a better idea because R:BASE advises
you of row changes regardless of whether you make a change. But it could
be a nuisance unless you remember to set VERIFY appropriately. For
example, say Sue and Alan are editing the same employee row. Sue has
VERIFY set to ROW and REFRESH set to 10 as she changes address
information. Alan is changing salary information. If Alan saves his
salary changes and Sue doesn't save her changes within 10 seconds, all
her changes up to that point will be undone when R:BASE refreshes the
screen. In this case, Sue clearly should have set VERIFY to COLUMN.
When you're going into a form to make wholesale changes, set VERIFY to
COLUMN so you're notified only if someone else changes a column.
When developing a multi-user application, think through each menu action
and decide what combination of settings makes the most sense. R:BASE
provides you with a flexible set of networking tools that you need to
apply appropriately to each situation you encounter. Experiment with
different combinations of VERIFY and REFRESH settings to see how the
screen behaves in different situations. This will give you a good feel
for when to use which settings.