Foundset Synchronization

Hi all,

I developed a simple program to store the click count in a database table. Multiple users click “Click” the same button simultaneously. Then Program counts the number of clicks and store in the database table. Specific user’s clicks can be seen by clicking view clicks button.

Problem

User A clicks “Click” button 10 times and user B clicks “Click” button 10 times simultaneously. At the end, click count value which was stored in database table, should be 20. But the actual value is less than 20. When we check the user clicks, by clicking “view Click” button, then the number of clicks are correct for when totaled for both users.

Click button code

function countClick()
{
var success=false;
if(foundset.find())
{
foundset.rec_no = 1;
foundset.search();
}
databaseManager.startTransaction();
while(!success){
success=databaseManager.acquireLock(foundset,-1);
}
if(success){
foundset.relookup();
foundset.click_count += 1;
clickCounter++;
arr+=‘,’+clickCounter;
if(databaseManager.saveData()){
databaseManager.commitTransaction();
}else{
databaseManager.rollbackTransaction();
}
databaseManager.releaseAllLocks();
}
}

View Click button code

function viewArray()
{
plugins.dialogs.showInfoDialog('Number of Clicks,'Array is : '+arr);
}

Please show me the correct way to get the click count in function countClick() in a multi-user environment.

Regards,
Sirikumara

Hi,

Interesting issue.

I tested this with 3.5.9 on an Oracle 10g database.

Same issue here

Even changed the code a bit to be sure that the counter does not raise when the save or commit fails;

	if(databaseManager.saveData())
	{
		application.output('saved')
		success2 = databaseManager.commitTransaction();
		application.output('suc= ' + success)
		if(success2 = true)
		{
			clickCounter += 1;
			application.output('cc= ' + clickCounter)
    		                arr+=','+clickCounter;
		}
	}

But this does not solve the issue.

A few times during testing the solution frooze on both sides and we had to kill java.exe.

I will investigate further…

Regards,

Hans

What happens if you replace

foundset.relookup();

by

databaseManager.refreshRecordFromDatabase(foundset, foundset.getSelectedIndex())

That is the method I would use in such a situation.

Martin

Why is it nescessary to do a relookup or refreshrecordfromdatabase ??

This would suggest that the foundset is not in sync with the database !!

Regards,

Hans

Hans Nieuwenhuis:
This would suggest that the foundset is not in sync with the database !!

That is exactly the problem that I have for some of my customers.
I had already a case that databroadcasting is not working, but Servoy support couldn’t find what the reason is why databroadcasting is not working.

So therefore I use the databaseManager.refreshRecordFromDatabase(foundset, foundset.getSelectedIndex()) to be sure that I have a record with the actual contents

I will try te create a case with a samople solution in which Servoy can reproduce this.

Regards,

Hans

Look here viewtopic.php?f=3&t=3705&start=15 (last two post)

we have seen this also!

Created a case for this : 201845

It includes a sample solution to reproduce the issue.

Seems rather important to me.

Foundset should never be out of sync !!!

Regards,

Hans

Laurian Vostinar from Servoy already looked to my case some time ago (october 2008).
Case 182152
The problem with databroadcasting was already in 3.5.7

Laurian didn’t find anything.
Even with some sample solutions, that were not working on my site, but they worked @ servoy

So the conlusion was that it is very specific.
It looks like it depends on the environment.
Perhaps network or firewall related

My sample solution is not specific,

I tested it on two computers next to each other.
So no Firewall or network issues.

Regards,

Hans

I tested the same situation. That is why it is so strange.

If Servoy can not reproduce it, I will go to Amersfoort with my collegue
and our two laptops and show it there.

Regards,

Hans

This issue (with 10 clicks) is indeed reproduceable; we are currently working on it.

Laurian,

When you have found/fixed the problem, can you tell us here if it could have been the same problem as we discussed before concerning the databroadcasting issue

Thanks

Martin

martinh:
Laurian,

When you have found/fixed the problem, can you tell us here if it could have been the same problem as we discussed before concerning the databroadcasting issue

Thanks

Martin

Sure. This seems to be a broadcasting problem too.

The issue here was that the first client modified the value, released the lock then the second client acquired the lock and read the value before broadcasting was done. So, the second client read the old value. This is fixed now in 3.5 and 4.1 and will be included in next release.

martinh:
Laurian,

When you have found/fixed the problem, can you tell us here if it could have been the same problem as we discussed before concerning the databroadcasting issue

Thanks

Martin

Our solution is basically the same as yours, when acquire lock we take the latest data from database.So, if databaseManager.refreshRecordFromDatabase(foundset, foundset.getSelectedIndex()) makes it work for you, it means it is the same issue.

Hi Laurian,

What you describe looks indeed that I had the same problem couple of months ago.
So the acquire lock / refresh problem has been solved.
But is there a reason why the broadcasting hasn’t been done yet, because in my case the broadcasting wasn’t done at all.
So it was not only a problem when several users click at the same time.
Even after couple minutes the broadcasting was still not done. Perhaps there is also a part of the problem.

Martin

Laurian,

for the time being,

where exactly do you we place the databaseManager.refreshRecordFromDatabase?

Harjo:
Laurian,

for the time being,

where exactly do you we place the databaseManager.refreshRecordFromDatabase?

databaseManager.refreshRecordFromDatabase should be called immediately after acquireLock; our refresh is inside acquireLock function

martinh:
Hi Laurian,

What you describe looks indeed that I had the same problem couple of months ago.
So the acquire lock / refresh problem has been solved.
But is there a reason why the broadcasting hasn’t been done yet, because in my case the broadcasting wasn’t done at all.
So it was not only a problem when several users click at the same time.
Even after couple minutes the broadcasting was still not done. Perhaps there is also a part of the problem.

Martin

This was a threading issue, broadcast was done after the value was read . I don’t know why broadcast wouldn’t happen at all.

Hi All,

I programmed again with some modification in Servoy Version: 4.1.1 i3 - build 661. But I think problem was not solved. Because when I checked for big numbers (e.g. more than 25 clicks each client),total number of clicks was incorrect. On top of that, sometimes program got stuck. When I checked via the servoy admin module, it reflects that there is a lock which is not released. But, in the code, using try/catch blocks, i’ve tried to eliminate all such instances where locks might not get released.

My countClick() function is below.

function countClick()
{
//find record
if (foundset.find()) {
foundset.rec_no = 1;
foundset.search();
} else {
throw (“Cannot execute find command, click not registered”);
}

if (foundset.getSize() != 1) {
throw (“Cannot find record, click not registered”);
}

//acquire lock
var _lockCount = 0;
var success = false;
while (!success) {
success = databaseManager.acquireLock(foundset, -1);
if (success) {
break;
}
if (_lockCount > 50) {
throw (“Cannot acquire lock, click not registered”);
}
application.sleep(20);
_lockCount++;
}

try {
databaseManager.refreshRecordFromDatabase(foundset, foundset.getSelectedIndex()) // This was used after the initial attempt to see whether this will correct the issue.
databaseManager.startTransaction();
//Update record
foundset.click_count++;
clickCounter++; // To confirm the number of clicks by each user
success = false;
if (databaseManager.saveData(foundset.getRecord(1))) {
databaseManager.commitTransaction();
success = true;
savedClicks+=‘,’+clickCounter; // To confirm the number of saved clicks by each user
} else {
databaseManager.rollbackTransaction();
}
} catch (e) {
//TODO
} finally {
databaseManager.releaseAllLocks();
if (!success) {
throw(‘Unable to update clickcount, click not registered’)
}
}

enteredClicks+=‘,’+clickCounter; // To view number of user clicks.
}

Function to View Number of User Clicks (per client session)

function viewArray()
{
plugins.dialogs.showInfoDialog(‘CLICK HISTORY’,‘ENTERED CLICKS : ‘+enteredClicks+’\n SAVED CLICKS’+savedClicks);
}

Function to Clear Number of User Clicks (per client session)

function clear()
{
enteredClicks='ENTERED CLICKS : ';
savedClicks="SAVED CLICKS : ";
clickCounter=0;
}

Regards,

Sirikumara
Returnpool Lanka (Pvt) Ltd