Icon View Thread

The following is the text of the current message along with any replies.
Messages 1 to 10 of 12 total
Thread LockSemaphore & UnlockSemaphore methods.
Thu, Oct 5 2006 8:24 AMPermanent Link

Abdulaziz Jasser
Hi,

In our application we sometimes need do some long operations which require exclusive access to the DB.  Therefore, before doing those long
operations we raise a Semaphore using and none used table something like this:


const   iBusyDBSemaphore     : Integer = 999;
................................................................................................................


Table1.LockSemaphore(iBusyDBSemaphore);

So every time a user start the application on the LAN it check this semaphore and if it's there the application terminate it self with a message
saying "The DB is busy, please try later."  The code for this check is:

if NOT Table1.LockSemaphore(iBusyDBSemaphore) then begin
  DBISAMDatabase1.Close;
  DBISAMSession1.Close;
  Showmessage('Database is busy, please try later.');
  Application.Terminate;
  Application.ProcessMessages;
end;

Now the problem:  When a user start the application from another PC the check for the semaphore takes as long as the long operation stays on the
other PC that runs the long operations.  In other words, the new user will not get the message until the long operations ends!!!  After a little
debugging I found that it freezes on this line:

if NOT Table1.LockSemaphore(iBusyDBSemaphore) then begin


Any idea why?

Regards,
Abdulaziz Jasser
Thu, Oct 5 2006 9:12 AMPermanent Link

Roy Lambert

NLH Associates

Team Elevate Team Elevate

Abdulaziz


What happens to other PC's that are already logged in?

Roy Lambert
Thu, Oct 5 2006 9:22 AMPermanent Link

"Robert"

"Abdulaziz Jasser" <jasser@cyberia.net.sa> wrote in message
news:421E7704-8486-4CC0-BF26-0B07A2D3F2AF@news.elevatesoft.com...
> Hi,
>
> In our application we sometimes need do some long operations which require
> exclusive access to the DB.  Therefore, before doing those long
> operations we raise a Semaphore using and none used table something like
> this:
>
>
> const   iBusyDBSemaphore     : Integer = 999;
> ...............................................................................................................
>
>
> Table1.LockSemaphore(iBusyDBSemaphore);
>
> So every time a user start the application on the LAN it check this
> semaphore and if it's there the application terminate it self with a
> message
> saying "The DB is busy, please try later."  The code for this check is:
>
> if NOT Table1.LockSemaphore(iBusyDBSemaphore) then begin
>   DBISAMDatabase1.Close;
>   DBISAMSession1.Close;
>   Showmessage('Database is busy, please try later.');
>   Application.Terminate;
>   Application.ProcessMessages;
> end

ELSE unlock the semaphore. Otherwise, you'll leave the database locked to
other users.

>
> Now the problem:  When a user start the application from another PC the
> check for the semaphore takes as long as the long operation stays on the
> other PC that runs the long operations.  In other words, the new user will
> not get the message until the long operations ends!!!  After a little
> debugging I found that it freezes on this line:
>
> if NOT Table1.LockSemaphore(iBusyDBSemaphore) then begin
>
>
> Any idea why?
>

Set the Session.LockWaitTime and Session.LockRetryTime to 1 before testing
the semaphore, then reset them to the normal values. Otherwise, DBISAM keeps
waiting and trying, just as with any other lock. In this case (as opposed to
a normal database function) you want to fail immediately if you can't place
the lock.

Robert

Thu, Oct 5 2006 9:30 AMPermanent Link

Abdulaziz Jasser
Roy,

<<What happens to other PC's that are already logged in?>>

Normally we make sure that everybody is off before starting this long operation.  But we were trying to prevent any user from login while this
process is running.
Thu, Oct 5 2006 9:43 AMPermanent Link

Abdulaziz Jasser
Robert,

<<Set the Session.LockWaitTime and Session.LockRetryTime to 1 before testing
the semaphore, then reset them to the normal values. Otherwise, DBISAM keeps
waiting and trying, just as with any other lock. In this case (as opposed to
a normal database function) you want to fail immediately if you can't place
the lock.>>

I did but nothing is changed.  Still freezes until the long operation on the other PC is finished.
Thu, Oct 5 2006 10:18 AMPermanent Link

"Robert"

"Abdulaziz Jasser" <jasser@cyberia.net.sa> wrote in message
news:34819FFB-1EFD-4EF2-8E8E-D633F459B03F@news.elevatesoft.com...
> Robert,
>
> <<Set the Session.LockWaitTime and Session.LockRetryTime to 1 before
> testing
> the semaphore, then reset them to the normal values. Otherwise, DBISAM
> keeps
> waiting and trying, just as with any other lock. In this case (as opposed
> to
> a normal database function) you want to fail immediately if you can't
> place
> the lock.>>
>
> I did but nothing is changed.  Still freezes until the long operation on
> the other PC is finished.
>

Hmmm, this is the code from my program. I'm sure it works, because it was
set up to deal with exactly the problem you describe. I use a negative
semaphore to do an unlock. "LeaveOn" is a boolean, set it to false if you
are just testing to see if the sempahore is locked.

Make sure you do not leave semaphores locked by mistake.

function TDM.setSem(const SemNo: Integer;
 const LeaveOn: Boolean): boolean;
var wSemNo : Integer;
   svLr, svLw : word;
begin
 svLr := DFPSessionName.LockRetryCount;
 svlw := DFPSessionName.LockWaitTime;
 SessionName.LockRetryCount := 1;
 SessionName.LockWaitTime := 1;
 result := false;
if SemNo < 0 then wSemNo := 0 - semNo else wSemNo := semNo;
 try
   if SemNo < 0 then Table.UnlockSemaphore(wSemNo) else
   begin
     // can not place sems if lockall is on
     if (wSemNo <> SemLockAll) then begin
      if (not Table.LockSemaphore(SemLockAll)) then begin
       result := false;  // LockAll was already set
       exit;
      end else Table.UnlockSemaphore(SemLockAll); //clean up
     end;
     result := Table.LockSemaphore(wSemNo);
     if (result = true) and (not LeaveOn)
       then Table.UnlockSemaphore(wSemNo);
   end;
 finally
   SessionName.LockRetryCount := svLr;
   SessionName.LockWaitTime := svLw;
 end;
end;

Thu, Oct 5 2006 10:39 AMPermanent Link

Abdulaziz Jasser
Robert,

Thanks for the code, however setting the semaphore is not really the problem.  The problem is the time it takes to test creating the same
semaphore form another PC on the same LAN.  If I tried to create the same semaphore on from another PC (PC-2) it freezes until the semaphore is
destroyed on the first PC (PC-1) even if the long operation is not running.
Thu, Oct 5 2006 12:40 PMPermanent Link

"Robert"

"Abdulaziz Jasser" <jasser@cyberia.net.sa> wrote in message
news:3443F04E-763C-4936-802B-B1AAE936AAB1@news.elevatesoft.com...
> Robert,
>
> Thanks for the code, however setting the semaphore is not really the
> problem.  The problem is the time it takes to test creating the same
> semaphore form another PC on the same LAN.  If I tried to create the same
> semaphore on from another PC (PC-2) it freezes until the semaphore is
> destroyed on the first PC (PC-1) even if the long operation is not
> running.

Go back thru this thread. You'll see that

a) You were not removing the lock after testing for it. You leave the lock
on. I marked that on your code.
b) You are not exiting right away after you fail.

EVERY PC, when attempting to set a semaphore, has to

a) reset lock counts and wait times
b) try to set the semaphore
c) if failed, return semaphore already set, if successful return sempahore
was set
d) restore normal session lock counts and wait times

and, when testing for a semaphore, remember that the only way to test is to
actually try to set it and see if you are successful, so if all you are
doing is testing, and if your lock was successful, you need to remove the
semaphore, or it will stay there.

Just assume that the thing works (because it does) and review your logic.

Robert


>

Thu, Oct 5 2006 1:19 PMPermanent Link

Abdulaziz Jasser
Robert,

This is exactly what I am doing.  The code I posted before was part of what I am doing.  In the original code I normally unlock the semaphore after
a successful call to that method.  Because the purpose as you know was to check if the semaphore is already created before by another user in
another PC.  Also the same application is running from all PCs.  I've also changed "LockRetryCount" and "LockWaitTime" properties to 1 before
checking but no luck.  Still the other instances of the same application freezes when checking for the creation of that semaphore:

if Table1.LockSemaphore(iBusySemaphoreID) then begin //It freezes here.
Thu, Oct 5 2006 2:02 PMPermanent Link

Abdulaziz Jasser
Robert,

I found the problem.  I knew I was doing something wrong.  Big thanks to you...

Regards,
Abdulaziz Jasser
Page 1 of 2Next Page »
Jump to Page:  1 2
Image