Author | Topic: DbRLock()/RLock() wrong behavior when locking Phantom Record(LastRec()+1) on Win 7/10. | |
---|---|---|
Jose Manuel Acevedo Galva | DbRLock()/RLock() wrong behavior when locking Phantom Record(LastRec()+1) on Win 7/10. on Mon, 11 Apr 2016 12:40:39 -0500 Hi, recently I discovered this error with the next scenario: First, you've opened a DBF "TEST" and you try to lock the Phantom Record(LastRec() + 1) and everything is fine, you get a TRUE as result and DbRLockList() will report you the recocord as locked. Ok, up to here no problem. But, if you try to lock the Phantom Record(LastRec()+ 1) again(remeber that Phantom Record remains locked) you will get a TRUE as result and DbRLockList() will report the record on the list, the same record being locked previously and this is wrong, you should be receiving a FALSE as result and this record out of the list. Additional information about the work environment: Operating Systems: Windows 7 Professional - 64bits - SP1 Windows 10 Professional - 64bits Compiler: Alaska Xbase v1.90.335 DBE: FOXCDX You'll find here a ready to compile an run sample of code I've used to test. You can run the exe twice for a simple locking test. Any kind of help or sharing experiences about similar cases will be apreciated. Regards, --- José Manuel Acevedo Galván macevedo@compuks.com testLock.rar | |
Peter Alderliesten | Re: DbRLock()/RLock() wrong behavior when locking Phantom Record(LastRec()+1) on Win 7/10. on Wed, 13 Apr 2016 16:43:11 +0200 Jose, > Hi, recently I discovered this error with the next scenario: > > First, you've opened a DBF "TEST" and you try to lock the Phantom > Record(LastRec() + 1) and everything is fine, you get a TRUE as result > and DbRLockList() will report you the recocord as locked. Ok, up to here > no problem. But, if you try to lock the Phantom Record(LastRec()+ 1) > again(remeber that Phantom Record remains locked) you will get a TRUE as > result and DbRLockList() will report the record on the list, the same > record being locked previously and this is wrong, you should be > receiving a FALSE as result and this record out of the list. I don't know if this should be called an error. IMHO you shouldn't be locking the phantom record, at least not as a valid (and to be checked) option. Peter | |
Clifford Wiernik | Re: DbRLock()/RLock() wrong behavior when locking Phantom Record(LastRec()+1) on Win 7/10. on Wed, 13 Apr 2016 18:51:34 -0500 On 4/13/2016 9:43 AM, Peter Alderliesten wrote: > Jose, > >> Hi, recently I discovered this error with the next scenario: >> >> First, you've opened a DBF "TEST" and you try to lock the Phantom >> Record(LastRec() + 1) and everything is fine, you get a TRUE as result >> and DbRLockList() will report you the recocord as locked. Ok, up to here >> no problem. But, if you try to lock the Phantom Record(LastRec()+ 1) >> again(remeber that Phantom Record remains locked) you will get a TRUE as >> result and DbRLockList() will report the record on the list, the same >> record being locked previously and this is wrong, you should be >> receiving a FALSE as result and this record out of the list. > > I don't know if this should be called an error. > IMHO you shouldn't be locking the phantom record, at least not as a valid > (and to be checked) option. > > Peter > Are you looking the record the same time from the same thread, same workarea. If you are, even it is the phantom record, the 2nd lock releases the first lock first. Same would be on a real record. We use ADS and you can not lock the eof() record. We test if eof() so that you cannot lock it. | |
Jose Manuel Acevedo Galva | Re: DbRLock()/RLock() wrong behavior when locking Phantom Record(LastRec()+1) on Win 7/10. on Thu, 14 Apr 2016 09:29:13 -0500 El 13/04/2016 a las 06:51 p.m., Clifford Wiernik escribió: > On 4/13/2016 9:43 AM, Peter Alderliesten wrote: >> Jose, >> >>> Hi, recently I discovered this error with the next scenario: >>> >>> First, you've opened a DBF "TEST" and you try to lock the Phantom >>> Record(LastRec() + 1) and everything is fine, you get a TRUE as result >>> and DbRLockList() will report you the recocord as locked. Ok, up to here >>> no problem. But, if you try to lock the Phantom Record(LastRec()+ 1) >>> again(remeber that Phantom Record remains locked) you will get a TRUE as >>> result and DbRLockList() will report the record on the list, the same >>> record being locked previously and this is wrong, you should be >>> receiving a FALSE as result and this record out of the list. >> >> I don't know if this should be called an error. >> IMHO you shouldn't be locking the phantom record, at least not as a valid >> (and to be checked) option. >> >> Peter >> > Are you looking the record the same time from the same thread, same > workarea. If you are, even it is the phantom record, the 2nd lock > releases the first lock first. Same would be on a real record. We use > ADS and you can not lock the eof() record. We test if eof() so that you > cannot lock it. Hi Clifford, It is a classic scenario where you have a shared database and you have several users trying to get a unique data on a sequenced field like a Invoice or an Order Number. So, is a different thread and a different workarea. > We use ADS and you can not lock the eof() record. We test if eof() so > that you cannot lock it. I have not experienced using ADS yet. Regards, --- José Manuel Acevedo Galván macevedo@compuks.com | |
Carlos A Beling | Re: DbRLock()/RLock() wrong behavior when locking Phantom Record(LastRec()+1) on Win 7/10. on Thu, 14 Apr 2016 15:57:10 -0300 Good afternoon. To lock the phantom record has not sense because the phantom record is only an empty record that is "placed" in the work area until the record pointer being moved, a record is appended or the file is closed. This way many workstations may to have phantom records without to modify the database; then to lock a phantom record has not effect. Also if you update the phantom record and want inserting the new one record in the database, you will have to DbAppend() a record and then this will erase the updates that you did. Any way I agree that to lock the phantom record might always to return .t. and unlock should to do nothing. Fraternally Beling On 14/4/2016 11:29, Jose Manuel Acevedo Galva wrote: > El 13/04/2016 a las 06:51 p.m., Clifford Wiernik escribió: >> On 4/13/2016 9:43 AM, Peter Alderliesten wrote: >>> Jose, >>> >>>> Hi, recently I discovered this error with the next scenario: >>>> >>>> First, you've opened a DBF "TEST" and you try to lock the Phantom >>>> Record(LastRec() + 1) and everything is fine, you get a TRUE as result >>>> and DbRLockList() will report you the recocord as locked. Ok, up to >>>> here >>>> no problem. But, if you try to lock the Phantom Record(LastRec()+ 1) >>>> again(remeber that Phantom Record remains locked) you will get a >>>> TRUE as >>>> result and DbRLockList() will report the record on the list, the same >>>> record being locked previously and this is wrong, you should be >>>> receiving a FALSE as result and this record out of the list. >>> >>> I don't know if this should be called an error. >>> IMHO you shouldn't be locking the phantom record, at least not as a >>> valid >>> (and to be checked) option. >>> >>> Peter >>> >> Are you looking the record the same time from the same thread, same >> workarea. If you are, even it is the phantom record, the 2nd lock >> releases the first lock first. Same would be on a real record. We use >> ADS and you can not lock the eof() record. We test if eof() so that you >> cannot lock it. > Hi Clifford, > > It is a classic scenario where you have a shared database and you have > several users trying to get a unique data on a sequenced field like a > Invoice or an Order Number. > > So, is a different thread and a different workarea. > >> We use ADS and you can not lock the eof() record. We test if eof() so >> that you cannot lock it. > I have not experienced using ADS yet. > | |
Jorge L | Re: DbRLock()/RLock() wrong behavior when locking Phantom Record(LastRec()+1) on Win 7/10. on Fri, 15 Apr 2016 15:06:14 -0300 Hi José, I have in the register No. 1 (or anyone) a record fill with chr (33) then i use register 1like a phantom record regards "Carlos A Beling" escribió en el mensaje de noticias:7c9bbe0c$77831b4$4b671@news.alaska-software.com... Good afternoon. To lock the phantom record has not sense because the phantom record is only an empty record that is "placed" in the work area until the record pointer being moved, a record is appended or the file is closed. This way many workstations may to have phantom records without to modify the database; then to lock a phantom record has not effect. Also if you update the phantom record and want inserting the new one record in the database, you will have to DbAppend() a record and then this will erase the updates that you did. Any way I agree that to lock the phantom record might always to return .t. and unlock should to do nothing. Fraternally Beling On 14/4/2016 11:29, Jose Manuel Acevedo Galva wrote: > El 13/04/2016 a las 06:51 p.m., Clifford Wiernik escribió: >> On 4/13/2016 9:43 AM, Peter Alderliesten wrote: >>> Jose, >>> >>>> Hi, recently I discovered this error with the next scenario: >>>> >>>> First, you've opened a DBF "TEST" and you try to lock the Phantom >>>> Record(LastRec() + 1) and everything is fine, you get a TRUE as result >>>> and DbRLockList() will report you the recocord as locked. Ok, up to >>>> here >>>> no problem. But, if you try to lock the Phantom Record(LastRec()+ 1) >>>> again(remeber that Phantom Record remains locked) you will get a >>>> TRUE as >>>> result and DbRLockList() will report the record on the list, the same >>>> record being locked previously and this is wrong, you should be >>>> receiving a FALSE as result and this record out of the list. >>> >>> I don't know if this should be called an error. >>> IMHO you shouldn't be locking the phantom record, at least not as a >>> valid >>> (and to be checked) option. >>> >>> Peter >>> >> Are you looking the record the same time from the same thread, same >> workarea. If you are, even it is the phantom record, the 2nd lock >> releases the first lock first. Same would be on a real record. We use >> ADS and you can not lock the eof() record. We test if eof() so that you >> cannot lock it. > Hi Clifford, > > It is a classic scenario where you have a shared database and you have > several users trying to get a unique data on a sequenced field like a > Invoice or an Order Number. > > So, is a different thread and a different workarea. > >> We use ADS and you can not lock the eof() record. We test if eof() so >> that you cannot lock it. > I have not experienced using ADS yet. > | |
Jose Manuel Acevedo Galva | Re: DbRLock()/RLock() wrong behavior when locking Phantom Record(LastRec()+1) on Win 7/10. on Thu, 14 Apr 2016 09:15:29 -0500 El 13/04/2016 a las 09:43 a.m., Peter Alderliesten escribió: > Jose, > >> Hi, recently I discovered this error with the next scenario: >> >> First, you've opened a DBF "TEST" and you try to lock the Phantom >> Record(LastRec() + 1) and everything is fine, you get a TRUE as result >> and DbRLockList() will report you the recocord as locked. Ok, up to here >> no problem. But, if you try to lock the Phantom Record(LastRec()+ 1) >> again(remeber that Phantom Record remains locked) you will get a TRUE as >> result and DbRLockList() will report the record on the list, the same >> record being locked previously and this is wrong, you should be >> receiving a FALSE as result and this record out of the list. > > I don't know if this should be called an error. > IMHO you shouldn't be locking the phantom record, at least not as a valid > (and to be checked) option. > > Peter > Hi Peter, > I don't know if this should be called an error. I agree, may be it should be called a bug. > IMHO you shouldn't be locking the phantom record, at least not as a valid > (and to be checked) option. Thanks for the advise, but no matter if it is a good option or a good programming practice it is working bad. If the Phantom Record cannot be locked it must return a FALSE. In my case locking Phantom Record is a good option(if it were possible) because while the phantom record is locked nobody can append, so meanwhile you can perform several tasks to ensure avoid data corruption like duplicate keys. I would like to know the point of view or a clarification about this from the Alaska Software Development Team. Regards, --- José Manuel Acevedo macevedo@compuks.com | |
Andreas Gehrs-Pahl | Re: DbRLock()/RLock() wrong behavior when locking Phantom Record(LastRec()+1) on Win 7/10. on Thu, 14 Apr 2016 01:10:13 -0400 José The only reason I can imagine why you would want to lock the ghost record, is to prevent a different process to a add a new record to the table. For this, you should instead use FLock(), even though this prevents write access to any record of the table. Up to Build 1.30.212, locking the ghost record could result in DbAppend() running into an endless loop, hanging the application. This was apparently fixed with PDR 109-3545: http://www.Alaska-Software.com/scripts/waa001.dll?WAA_PACKAGE=PUBLICDTS&WAA_FORM=DISPLAYPDR&PDRID=3545 The original solution/workaround for this PDR was to simply not to lock the ghost record. It looks like the final solution for the PDR was to allow locking of the ghost record, but without having an actual record lock -- as there really isn't a real record to lock. So you now will always get .T. if you try to lock the ghost record, even it was already locked. This will apparently allow DbAppend() to work, even if the ghost record has been (supposedly) locked. But this will also no longer prevent a different process to append a new record. Hope that helps, Andreas Andreas Gehrs-Pahl Absolute Software, LLC phone: (989) 723-9927 email: Andreas@AbsoluteSoftwareLLC.com web: http://www.AbsoluteSoftwareLLC.com | |
Jose Manuel Acevedo Galva | Re: DbRLock()/RLock() wrong behavior when locking Phantom Record(LastRec()+1) on Win 7/10. on Thu, 14 Apr 2016 18:19:13 -0500 El 14/04/2016 a las 12:10 a.m., Andreas Gehrs-Pahl escribió: Hi Andreas, > José > > The only reason I can imagine why you would want to lock the ghost record, > is to prevent a different process to a add a new record to the table. For > this, you should instead use FLock(), even though this prevents write access > to any record of the table. Yes, it is correct. But, regrettably FLock() will not work fine for me because this process requires concurrent locks of other processes/users and this is the reason why I were testing to lock the Phantom Record. Let me tell you something, the problem is not really the Phantom Record Locking , initially I had a problem related to Data Corruption due to the SMB 2.0 and Oplocks issues and also work environments with a variety of operating systems(Win7/Win10 and WinServer 2012 specifically). Due to this problem I had to research into a new way to prevent data corruption(specifically duplicated keys) and the Phantom Record technique seems to be to me a good option/solution based on my experience with Clipp*r where this feature worked great. Before this situation I never had a problem with data corruption. All the tools and code I had developed to manage dbfs and records were working fine. > > Up to Build 1.30.212, locking the ghost record could result in DbAppend() > running into an endless loop, hanging the application. This was apparently > fixed with PDR 109-3545: > > http://www.Alaska-Software.com/scripts/waa001.dll?WAA_PACKAGE=PUBLICDTS&WAA_FORM=DISPLAYPDR&PDRID=3545 > > The original solution/workaround for this PDR was to simply not to lock the > ghost record. It looks like the final solution for the PDR was to allow > locking of the ghost record, but without having an actual record lock -- as > there really isn't a real record to lock. Thanks for letting me know it. > So you now will always get .T. if you try to lock the ghost record, even it > was already locked. This will apparently allow DbAppend() to work, even if > the ghost record has been (supposedly) locked. But this will also no longer > prevent a different process to append a new record. IMHO, according to the policy of Alaska Software, related to emulate or preserve the Clipp*r behavior in many of its language features, it results disconcerting, specially if the documentation is not clear enough or there is not. I really appreciate your help and your time. Regards, --- José Manuel Acevedo Galván macevedo@compuks.com | |
Pascal Boivin | Re: DbRLock()/RLock() wrong behavior when locking Phantom Record(LastRec()+1) on Win 7/10. on Fri, 15 Apr 2016 15:02:36 +0200 An easy way to solve your initial problem (duplicate key) is to use a small table with only two field: LOCAL aStruct := {} aAdd(aStruct, { "Number", "C", 10, 0} ) aAdd(aStruct, { "Value", "N", 15, 0} ) aAdd(aStruct, { "MaxValue", "N", 15, 0} ) DbCreate("Number.DBF", aStruct) Then fill it with the unique number you want Numer Value MaxValue Invoice 1 9999999 Order 1 999999 Customer 1 999999 FUNCTION GetUniqueValue(cNumber) LOCAL cAlias := Alias(), RetVal := "Record " + cNumber + " not found in Number.dbf" USE Number NEW SHARED SET ORDER TO TAG Number SEEK cNumber IF FOUND() IF TryLock(5) IF Value < MaxValue REPLACE Value WITH Value + 1 RetVal := Value ELSE RetVal := "Number of " + cNumber + " reach maximum value!" ENDIF DbrUnlock() ELSE RetVal := "Unable to lock record for " + cNumber ENDIF ENDIF USE IF !Empty(cAlias) SELECT (cAlias) ENDIF RETURN RetVal PROCEDURE AddInvoice() LOCAL nID nID := GetUniqueValue("INVOICE") IF Valtype(nID) == "N" //Add invoice with unique id nID ELSE MsgBox(nID) ENDIF RETURN | |
Jose Manuel Acevedo Galva | Re: DbRLock()/RLock() wrong behavior when locking Phantom Record(LastRec()+1) on Win 7/10. on Fri, 15 Apr 2016 10:51:09 -0500 Hi Pascal, thanks for your response and for sharing your solution. Regards, --- José Manuel Acevedo macevedo@compuks.com |