7. Sample program

[<<<] [>>>]

This program represents how to create a counter in a database. The counter is a typical programming task that many programmers lacking concurrent programming experience fail to implement correctly.

A simple counter reads the current value of the counter, increments it and then writes the new result back. The issue is the record protection when there are more than one processes trying to use the counter. The process getting access to the counter should prevent the other processes accessing the counter until it has finished its incrementing the counter.

This protection can be done using transactions. Transactions automatically perform the necessary underlying record locks and provide a simpler view of the program flow. The transaction can be seen as a single, non-interruptible sequence of program lines.

To test the sample program, run it from the command line simultaneously in two windows on the same machine. Start the program in one window switch the other window and start the program again in the other window. The program instance started first starts the transaction, gets the counter value and waits your key press. The second instance opens the database, starts the transaction and gets locked when trying to read the counter value. Switch back to the first instance and press enter twice to let the transaction proceed. When the code finishes the transaction, commits the changes and releases the locks, you will soon see the second instance in the other window to proceed getting and displaying the new value of the counter.

Try and experience the program behavior starting it simultaneously in two or more terminal windows.

include bdb.bas
Const nl = "\n"

This line opens the database. This command is not locked by any transaction

DB = bdb::open("counter.db",bdb::BTree,bdb::Create,0)

Begin a transaction. This command just starts a transaction telling the database software that all record accesses from now on are performed under the transaction.

bdb::BeginTransaction
print "transaction started\n"

Accessing the record can be done only if the record is not locked. In other words if there is any program executing this transaction and has already got this record locking it this call will not return until the record is freed.

Counter = bdb::Get(DB,"COUNTER")
print "Counter is ",Counter,nl
print "Press enter to continue...\n"
line input wait$

If IsDefined(Counter) Then

If there was already a record with the key COUNTER then increment it and update. Numbers are converted to string and stored as decimal numbers.

  Counter = Counter + 1
  bdb::Update DB,Counter
  print "updated\nPress enter to continue...\n"
  line input wait$
Else

If there is no record with the key COUNTER then create one with the value 1.

 Counter = 1
 bdb::Put DB,"COUNTER",Counter
  print "put\nPress enter to continue...\n"
  line input wait$
End If

End the transaction, commit all changes and release the counter record.

bdb::EndTransaction
print "transaction has finished\n"

Although the interpreter automatically closes databases it is a disciplined behavior to close it programmatically.

bdb::close(DB)

[<<<] [>>>]