====================================================================== 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.