Automating Network Optimization in Alpha Five version 4

by Dr. Peter Wayne

Alpha Five version 4 introduces network optimization. Here we'll develop the capability to automate the synchronization of an application among all your network's computers.

Alpha Five version 4 greatly improves network performance by allowing the the creation of shadow databases on each workstation. A shadow database is a local copy of the server database, containing all the layouts (forms, reports, letters, browses), scripts and functions in the original. Each table in the original database is duplicated in the shadow as a single-record table with one field, shadow. The shadow field contains the full path and file name of the original table.

For example, if my site table is located on g:\program files\a5v4\wms, then the local shadow table will contain the single record with the entry, g:\program files\a5v4\wms\site.dbf.

Creating and updating the shadow tables for an application can be a chore, and A5v4 simplifies the task considerably by a new option on the Files menu. The option, Network Optimize, is enabled whenever an original database is active:

Network Optimize on Files Menu

Figure 1. Network Optimize on the Files Menu.

If you choose Network Optimize, then Alpha Five will prompt you to create a shadow database. Usually this will be in a folder named Shadow in your local workstation's Alpha Five folder:

Create a shadow database

Figure 2. Alpha Five creates a shadow database for you.

After the shadow database is created, you will have a local database that contains a copy of each layout, along with shadow tables corresponding to each table in your original database. The shadow tables are visible in the Control Panel as shaded table icons suggesting a shadow. The shadow tables reside in a shadow database on your local workstation. You can view and edit the records in the shadow tables, but you can't change the field rules or restructure a shadow table: you must access the original table for that kind of change.

I don't know about you, but my applications are never complete. There's always a change that has to be made. When the change is made, I need to distribute the change to all the workstations. In previous versions of Alpha Five, application updating was a non-issue, since all the files in an application resided in only one place, the server. With shadow databases, locally stored reports and forms will not be updated when the server is modified. You can update a pre-existing shadow database by choosing Refresh Shadow from the Files menu when a shadow database is open:

Refresh Shadow in the Files Menu

Figure 3. Refresh Shadow is enabled when a shadow database is open. Note that the table icons in the Control Panel are shaded to remind you that you are in a shadow database.

Even in my office, with only 7 computers, manually refreshing each workstation after a change is made to the server files is a chore that positively invites error. In a large network environment you want to guarantee that all users are working with the latest copy of your forms and reports. You can update a shadow database through Xbasic with the Xbasic function, refresh_shadow(). As the name suggests, this command takes the place of manually updating the shadow through the Files menu.

Steps to automate shadow synchronization

Let's break down the steps we need to to take to automate the refreshing of an application's shadow. We need

  1. to record the date and time the server copy was modified
  2. to record the date and time the local copy was last refreshed
  3. to compare the two dates and times, and then
  4. to refresh the shadow if it is out of date.

Since Alpha Five doesn't have a date_time field or variable type, we need first to create a way to compare one date and time with another. We can do this by storing the date and time in 2 separate variables or fields and comparing them both, but we can do it more elegantly by inventing our own date_time field type.

Alpha Five doesn't allow us to create our own field types, but we'll use our creativity to make a date_time type out of a character field type. 

We'll simply take the date, convert it to a string in yyyymmdd format, and then append the time of day in seconds past midnight. We'll have to pad the seconds to a constant number of characters so comparisons between two date_time values will always be accurate. We need a function to create a date_time value from a given date and time:

function date_time as C(d as D,t as C)
' takes a date and time and produces a compound date_time string
dim cd as c
dim ct as c
cd=cdate(d)
ct=padl(ltrim(str(toseconds(t),5,0)),5,"0")
date_time=cd+"."+ct
end function

Script 1. The date_time function.

Let's see this function in operation:

Usage of date_time function

Figure 4. Usage of date_time() function.

Note that date_time() will always return a character string of length 14. We can store the date and time of the last update in a single-field, single-record table that we incorporate into the server's database. My application is called "WMS", so I named my update table wms_update, and the single field is called last_revised:

Structure of WMS_Update table

Figure 5. Structure of WMS_Update table

Next, I wrote a small script that I can run to stuff the current date and time into the last_revised field of wms_update:

''XBasic
' update the date_time field in the wms_update table
' used for automatic refresh_shadow on startup
CONSTANT TN="wms_update"
dim current_date_time as c
dim t as p

t=table.open(TN,file_rw_exclusive)

current_date_time=date_time(date(),time())
if t.records_get()=0 then
	t.enter_begin()
		t.last_revised=current_date_time
	t.enter_end(.t.)
else
	t.change_begin()
		t.last_revised=current_date_time
	t.change_end(.t.) 
end if
t.close()

Script 2. The update wms date_time script.

Script 2 is not run automatically. I run it whenever I want to update the versions on each local workstation. The workstations run a different script when they begin my application. That script is:

''XBasic
' refresh wms shadow
' 11/14/98
dim is_found as l
dim fp as p
dim latest_version as c
dim update_table as p

CONSTANT FN="shadow_version.txt"

update_table=table.open("wms_update",file_ro_shared)
latest_version=update_table.last_revised
update_table.close()
is_found=file.exists(FN)
if is_found=.f. then
	fp=file.create(FN,file_rw_exclusive)
	fp.write_line(date_time({1/1/1998},"00:00:01"))
	fp.flush()
	fp.close() 
end if
fp=file.open(FN,file_ro_exclusive)
this_version=fp.read_line()
fp.close()

if this_version<latest_version then
	hourglass_cursor(.t.)
	fp=file.open(FN,file_rw_exclusive)
	fp.seek(0)
	fp.write_line(latest_version)
	fp.flush()
	fp.close()
	on error goto no_shadow
	refresh_shadow()
	on error goto 0
	hourglass_cursor(.f.)
	a5.close() 
end if

finis:
end

no_shadow:
	on error goto 0
	resume finis

Script 3. The refresh wms shadow script.

Script 3 is attached to the OnInit event of the database's autoload form, the form that starts automatically with the database and is the springboard for my application. What does Script 3 do? First, it looks in the user's private directory for the file, shadow_version.txt. If the file is present, it reads the date_time value that is stored in the file. If the file is absent, it creates the file and stuffs it with the value of 19980101.00001, a date_time that is guaranteed to precede the value in the wms_update table.

Second, Script 3 compares the date_time in the latest_version field in wms_update with the one it reads from the shadow_version.txt file. If the latest_version is more recent than what is found in shadow_version.txt, then script 3 will update the value in the local file and perform a refresh_shadow. The last action which Script 3 performs is an a5.close(). It is necessary to close down the shadow and reopen your application for the refresh to take effect.

If you add a new table to your database, then you should check that the refresh_shadow() method adds the table to your shadow database. At the time of this writing, refresh_shadow() does not add new tables to the shadow. That may change in future releases of version 4.

11/20/98

Don't forget, we need your feedback to make this site better!

Return to home