Monday, November 08, 2010 at 12:01 AM.
system.verbs.apps.Filemaker.examples.transactions
<<These examples show how to use transactions with Filemaker
<<Filemaker is not threaded and can not handle multiple script interactions at
<<the same time. Since scripting Filemaker often assumes that the database
<<was left in a certain state (ie a found set, after a find), you want a way
<<to make sure that Filemaker ignores messages from other scripts while the
<<current script is interacting with it.
<<There are two ways to limit interaction with Filemaker, transactions and semaphores.
----------------------------------------------------------------------------;
<<Transactions
<<Transactions are Filemaker's own way of limiting interaction.
<<A transaction locks Filemaker from Filemaker and will limit interaction from any
<<Apple Event system (Frontier or Applescript). This is more secure but is just a bit
<<slower as it requires events to begin and end the transaction.
<<
<<You need to use some special constructions if you want to make repeated
<<attempts to begin a transaction, see the example below.
<<
<<The ONLY way to end a transaction is from a script or by quitting and relaunching Filemaker!
bundle { <<using transactions
try {
local(transID=beginTransaction()); <<beginTransaction() returns a number
<<event transactions are an Apple Event device
<<all statements until "setEventTransaction" carry an implied ID
SetEventTransactionID (transID);
bundle { <<Filmaker statements go here
delete(request[all]);
create(request,"requestData",0,endOf(database[1].layout[1]));
find(window[1]);
local(foundSet=get(document[1].layout[1].record[all]))};
<<"document" contains the found set
EndTransaction (); <<the transaction ID is passed to filemaker since we are still in an event transaction
SetEventTransactionID (0)}
else { <<be sure to end the transaction no matter what
EndTransaction ();
SetEventTransactionID (0);
scriptError(tryError)}};
loop { <<using transactions with repeated attempts
<<you could modify this to only try 10 times, or for a certain amount of time
try {
local(transID=beginTransaction());
SetEventTransactionID (transID);
bundle { <<Filmaker statements go here
delete(request[all]);
create(request,"requestData",0,endOf(database[1].layout[1]));
find(window[1]);
local(foundSet=get(document[1].layout[1].record[all]))};
<<"document" contains the found set
EndTransaction ();
SetEventTransactionID (0);
break} <<end the loop
else {
if tryError contains "transaction" {
clock.waitseconds(1)}
<<or
<<sys.systemTask()
else { <<be sure to end the transaction no matter what
EndTransaction ();
SetEventTransactionID (0);
scriptError(tryError)}}};
---------------------------------------------------------------------------;
<<Semaphores
<<Semaphores provide a way to lock a value within Frontier that other scripts can check
<<the status of. When a script trys to lock a semaphore it will try for a specified amount of
<<time and then result in an error. The semaphore will remain locked until unlocked, but may
<<be unlocked from any script- not only the one that locked it. This can be useful if you want
<<different scripts to work together, with one script locking the semaphore and another
<<unlocking it (ie script a performs a find, script b gets the records).
<<
<<Semaphores exist only within Frontier and do not prevent Filemaker from interacting
<<with other applications, so if other applications are sending Apple Events to Filemaker
<<use transactions.
<<
<<Since locking a semaphore will try for a certain amount of time, no special construct is needed
bundle { <<using Semephores
try {
semaphores.lock("filemaker",1800)} <<#ticks to try and lock the semaphore
else {
scriptError("The Database was busy for too long!")};
try { <<was able to lock the semaphore within 1800 ticks
bundle { <<Filmaker statements go here
delete(request[all]);
create(request,"requestData",0,endOf(database[1].layout[1]));
find(window[1]);
local(foundSet=get(document[1].layout[1].record[all]))};
<<"document" contains the found set
semaphores.unlock("filemaker")}
else { <<be sure to unlock the semaphore in case of an error
semaphores.unlock("filemaker");
scriptError(tryError)}}
This listing is for code that runs in the OPML Editor environment. I created these listings because I wanted the search engines to index it, so that when I want to look up something in my codebase I don't have to use the much slower search functionality in my object database. Dave Winer.