Author Topic: replacement for dos_getini and dos_setini  (Read 2715 times)

0 Members and 1 Guest are viewing this topic.

laidbacklarry

  • Guest
replacement for dos_getini and dos_setini
« on: June 11, 2012, 07:27:26 PM »
Has anyone written a replacement for these functions in the doslib library? Pre Vlisp, we created lisp replacements for all the doslib functions we use in our application, including both of these (too many versions of DosLib required by our user base.)

For 99% of our users we have no problem, but we have one user with 11 workstations attached to the server and once or twice a year one of the .INI files becomes corrupt... probably as a result of two or more stations accessing the same .INI file at the same time - perhaps one reading and one writing. Any help with possible vla functions would be appreciated.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: replacement for dos_getini and dos_setini
« Reply #1 on: June 11, 2012, 08:57:33 PM »
Maybe one of these may help.
http://goo.gl/j5bih
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: replacement for dos_getini and dos_setini
« Reply #2 on: June 12, 2012, 03:42:50 AM »
...once or twice a year one of the .INI files becomes corrupt... probably as a result of two or more stations accessing the same .INI file at the same time - perhaps one reading and one writing. ...
In that case, you might have to start looking at another way to save settings. Even if you rewrite the INI get and set in plain ALisp, it's not going to fix concurrent access issues. You're still going to have text-file opens from each client PC, and thus these could happen concurrently. If anything goes wrong, you could still get stuff like corrupt data - or worse, if a PC crashes while saving to the INI that file may become unreadable to all other PCs.

The only way I can think of ensuring concurrent access not corrupting data is to use some sort of concurrent database server (something like MS-SQL / MySQL / FireBird / PostGre - my preference would be PostGre / FireBird because they're both Open Source and much more reliable + robust than MySQL) - then you'd need to connect to that DB through Lisp (perhaps using something like AdoLisp - it uses ActiveX so there's only "one version"). Though you'll have to install the DB server on one of the PC's or preferably on the server. If it's a Linux server then chances are that it already has MySQL and/or PostGre installed (but it would be a simple repo download to get either / FireBird, if a MS Server, then "possibly" MS-SQL is already available (or there's free downloads of any of the others).
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Lee Mac

  • Seagull
  • Posts: 12915
  • London, England
Re: replacement for dos_getini and dos_setini
« Reply #3 on: June 12, 2012, 07:26:09 AM »
The only way I can think of ensuring concurrent access not corrupting data is to use some sort of concurrent database server (something like MS-SQL / MySQL / FireBird / PostGre...

In that regard, not sure if this by Daniel would also help?

SQLite for AutoLISP

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: replacement for dos_getini and dos_setini
« Reply #4 on: June 12, 2012, 08:28:13 AM »
That should help a lot, it's better than a normal file open over a network connection. Though you might still find issues with file locking: http://www.sqlite.org/lockingv3.html

E.g. any process requires an "Exclusive" lock on the entire database (i.e. file) before it can write to it. Such lock requests are either set to "Pending" (i.e. wait until available) or rejected if there are any other locks already on the DB (e.g. "Shared" if one or more are reading from the DB).

IMO, the SQLite DB is very nice for client-only DB's. It "can" handle multiple users, but only in the same way as using an Access MDB / Paradox DB file can ... i.e. not very well at all. It relies heavily on the OS's own file locking to avoid contention and corruption. With the client-server databases I've noted, more than one client can actually write to the DB at the same time. E.g. the FireBird DB allows a record-level lock (i.e. one entry inside any one single table), not to mention it caches writes outside the OS and does not disallow writes if there's already a lock.

E.g. say user 1 saves a setting. But user 2 causes the exact same setting to be saved within a 1000'th of a sec. Then using SQLite / MDB / DB would either cause a fail for user 2, or keep him waiting until user 1's write is complete (which could be forever if anything goes wrong with user 1's PC/Software/Connection). With FB/PG/MySQL/MS-SQL both writes would complete from both users' view point, the server would cache (remember) user 2's write transaction and complete the write once it's completed user 1's write.

For the OP's scenario (i.e. 11 concurrent users) I'd say he's on the border-line between using a file-based DB (like SQLite/MDB/DB) and going for a full fledged client-server DBMS. Usually you'd be recommended to go with a C/S db for anything above 5 users (especially if you wanted to use a MDB - those get corrupted easily). SQLite is a bit better than Access in this regard, so I'd be willing to say 10 users max (though that depends on the size of the data to be read/written), but I'd start feeling itchy about 11. I'd actually say Paradox DB's might be better since they are able to lock only portions of each DB file - and each DB file is only one table. With the C/S stuff you can easily have 100's of concurrent users, e.g. most websites use MySQL and some (like Google / FaceBook / Amazon) number their concurrent writes in the 1000's per second (never mind just so many users).

The nice thing about SQLite is you don't need to install anything on the server or anything extra onto the client's PCs (except for those ARX's for each version of ACad/BricsCAD). With the C/S you'd need at least a server install (if the server doesn't already have one) as well as possibly an ODBC driver on each PC. BTW, FireBird also has an embeddable library: http://en.wikipedia.org/wiki/Embedded_database#Firebird_Embedded (which means it can be made similar to Daniel's ARX's).
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

TimSpangler

  • Water Moccasin
  • Posts: 2010
  • CAD Naked!!
Re: replacement for dos_getini and dos_setini
« Reply #5 on: June 12, 2012, 09:41:32 AM »
Why not create a lock file during the ini write?  then before you write to the ini check for the lock (like Autocad) once the data has been written and the file has been closed delete the lock?

Since your are recreating the functions anyway.
ACA 2015 - Windows 7 Pro
All Comments and Content by TimSpangler, Copyright © 2016

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: replacement for dos_getini and dos_setini
« Reply #6 on: June 12, 2012, 09:57:44 AM »
That's literally what MDB/DB/SQLite does in any case.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: replacement for dos_getini and dos_setini
« Reply #7 on: June 12, 2012, 11:36:10 AM »
BTW, if you do want to go the route Tim's suggesting - then either use Express Tools's acet-ini-get / acet-ini-set : http://www.afralisp.net/archive/lisp/acet-utils.htm

Or you can try this one: http://www.cadcoder.com/index.php?id=19

Just remember: If you've read the setting, then it might have changed after you've read it. So saving it back might cause loss of data. If you go with a file-lock method, then you should make each get + set into a "transaction" - i.e.:
  • Check if no lock file, else wait.
  • Create lock file
  • Then read current setting
  • Change current setting
  • Write change back
  • Delete lock file
See where this could cause corruption to data? Say your setting is something like "how many times have users used this tool". If user 1 increments this value at the same time as user 2 - then if you don't use a transaction method like above, you could find that instead of being incremented by 2, it's only incremented by 1.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

57gmc

  • Bull Frog
  • Posts: 366
Re: replacement for dos_getini and dos_setini
« Reply #8 on: June 12, 2012, 01:59:10 PM »
What about the option of each user having his own ini file?

laidbacklarry

  • Guest
Re: replacement for dos_getini and dos_setini
« Reply #9 on: June 12, 2012, 03:53:40 PM »
Thanks for the input. Based on previous input from the Swamp in regard to an earlier question about how to determine if a drawing is open using the .dwl file, I had used the technique Tim and irneb suggested. Taking a second look, I believe I put the lock file functions in the wrong place, in the _getini and _setini functions - meaning the lock file would be created and deleted perhaps dozens of times if an editing function covered many settings. A better location, I believe is at the beginning and end of the "write changes" portion of each program.

Each workstation does include an .ini file for settings that apply exclusively to that workstation. All of the other .ini files contain data designed to insure drawing uniformity regardless of who works on the drawing.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: replacement for dos_getini and dos_setini
« Reply #10 on: June 13, 2012, 02:58:37 AM »
The principle would be to have a get, set, lock & release function as separate functions. That way your code can decide when to lock and when to release. That way you can get around the issue as per my post #8. Just remember, don't lock and then wait for user input - that might lock the ini file until the user's finished their coffee!  :lmao:

BTW, you might want to "fine-grain" the locking as well. Save something into the lock file - like what type of lock (i.e. read / write). That way you can allow multiple read locks, but only one write-lock. You can even save a timestamp and decide on a time-out to get around the issue of a PC crashing and not releasing the lock file. In which case you've basically duplicated what's happening in MDB files exactly - Access uses a LDB file for locking and save stuff like user, date/time, lock-type into that file. Only it works with random file access, so it's possible to lock portions of the MDB while leaving other portions unlocked (though that's where most of the corruptions happen).
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.