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.