You are not logged in.
Pages: 1
There is IMHO a caching problem with the Locks.
This code works perfect on several clients:
// Lock Record
if not MyClient.Retrieve( DataID, DataRec, True ) then
begin
ShowMessage( 'No Lock' );
Exit;
end;
try
// Performing some actions with DataRec
MyClient.Update( DataRec );
finally
// UnLock Record
MyClient.UnLock( DataRec );
end;
but if a client A tries to get the lock while another client B has already the lock, this client A won't get the lock, even if the lock is released by client B.
It took a small amount of time to get the lock from the server, but after client A didn't get the lock the next Retrieve on that ID is received without this little delay.
Thats why I think it is a caching problem.
Next thing on Locking is:
var
Locked : Boolean;
// Lock Record
Locked := MyClient.Retrieve( DataID, DataRec, True );
try
if Locked then
begin
// Performing some actions with DataRec
MyClient.Update( DataRec );
end;
finally
// UnLock Record
MyClient.UnLock( DataRec ); // UnLocks, even if we haven't got the Lock
end;
when client A gets no lock, because client B has the lock, then performing on client A then
MyClient.UnLock( DataRec )
will UnLock then record.
ok, i could handle this with the code above, but it is strange anyway
Offline
ok, i've located the problem for both cases in SQLite3Commons.pas
function TSQLRestClientURI.Retrieve(aID: integer; Value: TSQLRecord;
ForUpdate: boolean=false): boolean;
var Table: TSQLRecordClass;
Resp: RawUTF8;
begin
result := false;
if (self=nil) or (aID<=0) or (Value=nil) then
exit;
Table := Value.RecordClass;
// try to get the lock from the local Model
if ForUpdate and not Model.Lock(Table,aID) then
exit; // error marking as locked by the client
// try to get the lock from the Server
with URIGet(Table,aID,Resp,ForUpdate) do
if Lo=200 then begin
// we successfully get the lock from Server
Value.FillFrom(Resp);
Value.fInternalState := Hi;
if ForceBlobTransfert then
result := RetrieveBlobFields(Value) else
result := true;
end;
end;
But what happened if we didn't get a successful lock from the server?
The record in the Model is still marked as locked.
Because of this, we
a) will never get a lock on this record
b) can Unlock a record, even we didn't receive the lock at any time from Server
The solution for this is really simple:
function TSQLRestClientURI.Retrieve(aID: integer; Value: TSQLRecord;
ForUpdate: boolean=false): boolean;
var Table: TSQLRecordClass;
Resp: RawUTF8;
begin
result := false;
if (self=nil) or (aID<=0) or (Value=nil) then
exit;
Table := Value.RecordClass;
if ForUpdate and not Model.Lock(Table,aID) then
exit; // error marking as locked by the client
with URIGet(Table,aID,Resp,ForUpdate) do
if Lo=200 then begin
Value.FillFrom(Resp);
Value.fInternalState := Hi;
if ForceBlobTransfert then
result := RetrieveBlobFields(Value) else
result := true;
end
else
// if we didn't get the lock from the server, we have to unlock the record in the Model :o)
Model.UnLock(Table,aID);
end;
Offline
You are right!
There is some obvious issue in the code.
I've fixed it as you suggested (adding a "if ForUpdate" and a "try...finally" to avoid a save unlocking):
see http://synopse.info/fossil/info/84bf8e1520
Thanks for the report.
Offline
Pages: 1