Edit Extended / Edit WorkArea - ABM / ABM2

Topic Specific Tutorials and Tips.

Moderator: Rathinagiri

Post Reply
User avatar
esgici
Posts: 4543
Joined: Wed Jul 30, 2008 9:17 pm
DBs Used: DBF
Location: iskenderun / Turkiye
Contact:

Re: recordlocking

Post by esgici »

Dear Richard
t57042 wrote: The record is indeed locked just before writing to disk.

This is called ‘postlock’ or ‘optimistic’ locking. In this scenario user2 can update a record which is currently edited by user1. When user1 writes his update to disk, user2’s is lost.

The advantage of this method is that the record is only locked for a very short duration.
The disadvantage is possible lost update (can be overcome by reading back the record just before updating and comparing it with the saved original version - when both are equal write is ok)

The method used by the BROWSE command is ‘prelock’ or ‘pessimistic’ locking.

As soon as one user reads a record to update it that record is locked. It stays locked as long as it has not been written back to disk.
The ‘lost update of the other method is avoided.

A disadvantage is that records could be locked longer.

What I would like is the second method implemented in the EDIT EXTENDED code.
Sorry, I haven't such deep technical background on locking schemes.
the lock should be made at the moment the intention of editing (or adding/ deleting) is given.
IMO this is wrong. Because if record locking applied when one user intent editing a record, no other users can access this record while editing process continue. And editing process may take long time; for example user may go to another job and left open that editing.

As the result, record locking implementation of both EDIT EXTENDED and BROWSE are perfect for me.

As course, you can select and do any method you like into your code.

Happy HMG'ing :D
Viva INTERNATIONAL HMG :D
t57042
Posts: 148
Joined: Tue Mar 16, 2010 9:46 am
Location: belgium

Re: recordlocking

Post by t57042 »

IMO this is wrong. Because if record locking applied when one user intent editing a record, no other users can access this record while editing process continue. And editing process may take long time; for example user may go to another job and left open that editing.
You may be right, but this is the way it done in BROWSE.
The most ideal solution is the one used in EDIT EXTENDED, provided a check is made before writing the record,
that no one else has changed it in between.

PS: Could you explain to me how you make a .ch file from a .prg file?

Thanks
Richard
User avatar
mol
Posts: 3720
Joined: Thu Sep 11, 2008 5:31 am
Location: Myszków, Poland
Contact:

Re: recordlocking

Post by mol »

Record locking should be provided st the beginning of edition, I think. Programmer can use timer for timeout generation and abandon edition in situation, when user forget about current job and switch to another work. I've realised it in one of my application.
User avatar
esgici
Posts: 4543
Joined: Wed Jul 30, 2008 9:17 pm
DBs Used: DBF
Location: iskenderun / Turkiye
Contact:

Re: recordlocking

Post by esgici »

t57042 wrote:...this is the way it done in BROWSE.
I'm not sure; could you demonstrate by a little example ?
The most ideal solution is the one used in EDIT EXTENDED, provided a check is made before writing the record,
that no one else has changed it in between.
Yes, agreed.
Could you explain to me how you make a .ch file from a .prg file?
.ch means "C header" and as name implied, this coding way borrowed from C language.

Normally, that files doesn't made from .prg files; written individually and are included into .prg file via #include directive.

In general, .ch files includes pre-processor directives for constant declarations, pseudo functions and commands; including #include directives for other files. These lines are general purpose code line and may or not may #included by more than one .prg files.

For example, say we have same values like :

Code: Select all

pi := 22 / 7
MaxUserCount := 10
If we declare this constants as above in the .prg file, this two identifiers are variables.

We can declare that values in another way :

Code: Select all

#define pi  22 / 7
#define MaxUserCount  10
In this case this two identifiers are constant, so their values has been fixed, no changeable afterward. #define is a pre-processor directive, these two identifiers are meta-constants and can be use in the code (.prg) file, after defined place ( if defined at top of file, can be use anywhere in that file).

I we want use that two value into other code (.prg) files, we need repeat above two lines ( consider a quite large list ) for all that code (.prg) files. And of course when a modification required, we need edit all code files.

In this case we build a .ch file that contains that definitions and add an #include directive to code files that need this definitions.

That's all.

.ch file extension is a general tradition and doesn't implies any specific action to compiler.

Sorry for long speech, I hope help you.

Regards
Viva INTERNATIONAL HMG :D
User avatar
esgici
Posts: 4543
Joined: Wed Jul 30, 2008 9:17 pm
DBs Used: DBF
Location: iskenderun / Turkiye
Contact:

Re: recordlocking

Post by esgici »

mol wrote:Record locking should be provided st the beginning of edition, I think. Programmer can use timer for timeout generation and abandon edition in situation, when user forget about current job and switch to another work. I've realised it in one of my application.
Dear Marek

Could you explain what is dominant advantage of this way;

that worth to extra bothers such as timer usage, timeout control :?

Regards
Viva INTERNATIONAL HMG :D
t57042
Posts: 148
Joined: Tue Mar 16, 2010 9:46 am
Location: belgium

Re: recordlocking

Post by t57042 »

This is a BROWSE sample from a previous HMG build.
Just replace the line dbf="tsunami" with your own database and try. You will see record is locked before editing can start.

Richard

Code: Select all

/*browse1
 * MINIGUI - Harbour Win32 GUI library Demo
 *
 * Copyright 2002 Roberto Lopez <roblez@ciudad.com.ar>
 * http://www.geocities.com/harbour_minigui/
*/

* Value property selects a record by its number (RecNo())
* Value property returns selected record number (recNo())
* Browse control does not change the active work area
* Browse control does not change the record pointer in any area
* (nor change selection when it changes) when SET BROWSESYNC is OFF (the default)
* You can programatically refresh it using refresh method.
* Variables called <MemVar>.<WorkAreaName>.<FieldName> are created for
* validation in browse editing window. You can use it in VALID array.
* Using APPEND clause you can add records to table associated with WORKAREA
* clause. The hotkey to add records is Alt+A.
* Append Clause Can't Be Used With Fields Not Belonging To Browse WorkArea
* Using DELETE clause allows to mark selected record for deletion pressing <Del> key
* The leftmost column in a browse control must be left aligned.

#include "minigui.ch"

Function Main
 
_w=1000
_h=700   

private aFields:={},aBrFields:={} ,alenFields:={}, i
Use &dbf shared
go top
aFields:=dbStruct() // get structure info to an array
for i=1 to len(aFields) // create array for FIELDS
AADD(aBrFields,aFields[i,1])
AADD(alenFields,aFields[i,3]*12)
next i

   SET CENTURY ON
   SET DELETED ON

SET BROWSESYNC on
   
   DEFINE WINDOW Form_1 ;
      AT 0,0 ;
      WIDTH _w HEIGHT _h ;
      TITLE 'MiniGUI Browse Demo' ;
      MAIN NOMAXIMIZE;
      NOSIZE;
      ON INIT go()  ;
      ON RELEASE CloseTables()
      
      DEFINE STATUSBAR
         STATUSITEM ''
         STATUSITEM '<Enter> / Double Click: Edit' WIDTH 200
         STATUSITEM 'Alt+A: Append' WIDTH 120
         //STATUSITEM '<Del>: Delete Record' WIDTH 120
      END STATUSBAR

      @ 10,10 BROWSE Browse_1   ;
         WIDTH _w-30 ;
            HEIGHT _h-90    ;
            FONT 'VERDANA' SIZE 10;      
         WORKAREA &dbf ;
         WIDTHS alenFields ;
         HEADERS aBrFields ;
         FIELDS aBrFields;
         ON CHANGE ChangeTest() ;
         DELETE ;
         LOCK ;
         EDIT;
            APPEND
         
   end WINDOW
   CENTER WINDOW Form_1
   Form_1.Browse_1.SetFocus
   ACTIVATE WINDOW Form_1
Return Nil

Procedure CloseTables()
    Use
Return Nil

Procedure ChangeTest()
   Form_1.StatusBar.Item(1) := dbf +".dbf" + '   -   Rec: ' + Alltrim(Str(RecNo()))
Return
*************************
Procedure go()                    
   Form_1.Browse_1.Value := RecNo()   
Return Nil   
t57042
Posts: 148
Joined: Tue Mar 16, 2010 9:46 am
Location: belgium

Re: recordlocking

Post by t57042 »

Record locking should be provided at the beginning of edition, I think. Programmer can use timer for timeout generation and abandon edition in situation, when user forget about current job and switch to another work. I've realised it in one of my application.
Dear Marek, I totally agree and would like EDIT EXTENDED changed in this way.

Richard
User avatar
mol
Posts: 3720
Joined: Thu Sep 11, 2008 5:31 am
Location: Myszków, Poland
Contact:

Re: recordlocking

Post by mol »

This is not acceptable that one user edits record and the second user can edit the same record too. Which one has higher priority??? Which data is more major? The only way is locking records at the beginning of edit.
User avatar
esgici
Posts: 4543
Joined: Wed Jul 30, 2008 9:17 pm
DBs Used: DBF
Location: iskenderun / Turkiye
Contact:

Re: recordlocking

Post by esgici »

mol wrote:This is not acceptable that one user edits record and the second user can edit the same record too. Which one has higher priority??? Which data is more major? The only way is locking records at the beginning of edit.
OK guys, I'm resign :lol:

Tested, BROWSE apply "prelock"; surely Maestro know the best ;)

But sorry, please don't wait from me to modify EDIT EXTENDED to "prelock" :(

Regards
Viva INTERNATIONAL HMG :D
User avatar
dhaine_adp
Posts: 457
Joined: Wed Aug 06, 2008 12:22 pm
Location: Manila, Philippines

Re: recordlocking

Post by dhaine_adp »

Hi t57042,

I think BROWSE locks the record(s) before any amendment (edit mode) is made on the physical record is to ensure that the changes are save and records are available to be overwritten.

There are two types of locks FILE LOCK and RECORD LOCK and it is the same as those locking scheme implemented by Clipper. So you should also use COMMIT/COMMIT ALL or the function DBCOMMIT() or DBCOMMITALL() in tandem with file/record lock. That would ensure that the changes is written on disk (after every update/changes) so the subsequent read request by users on DBF will reflect changes made.

You can write your own UDF to customize your record/table maintenance routine.

Marek is right that the first user who successfully locks the records will get the write privilege. Now it is up to your UDF how would you like to handle if another user attempts to write on a record which has been locked by another user. There are many varieties of handling this event such as that mentioned by Marek by incorporating TIME. How long would you like the user locks a record? If 15 minutes, poll the system time after a successful lock and check the time elapse, then terminate the window. Another way is temporarily log the workstation name of users who logged-in to your system. So when another user attempts to write, simply display information on the screen of the second user.

Regards,

Danny
Regards,

Danny
Manila, Philippines
Post Reply