comp.lang.ada
 help / color / mirror / Atom feed
From: brbarkstrom@gmail.com
Subject: Re: Exclusive file access
Date: Tue, 1 Sep 2015 13:02:14 -0700 (PDT)
Date: 2015-09-01T13:02:14-07:00	[thread overview]
Message-ID: <23506b3b-57f4-4e74-947a-c0655f15d198@googlegroups.com> (raw)
In-Reply-To: <ed3129f2-7c95-4ad9-ba0a-a8c7e4bfe6ae@googlegroups.com>

On Tuesday, September 1, 2015 at 10:05:42 AM UTC-4, ah...@marriott.org wrote:
> On Thursday, August 27, 2015 at 3:52:36 PM UTC+2, ah...@marriott.org wrote:
> > Dear All,
> > 
> > Obviously I'm misunderstanding something here.
> > 
> > I thought that if two processes tried to open the same file for write access then the second process would get an exception.
> > 
> > I have a simple example which when compiled using GnatPro 7.3.1 and run under 32-bit Windows XP demonstrates that this is not so.
> > 
> > Which then begs the question on how to detect if the file is in use and abort if it is.
> > This should be simple but obviously too complex for my tiny brain.
> > Does anyone know how to do this from Ada (without resorting to the OS directly)?
> > 
> > My simple test program is
> > 
> > package body Test is
> > 
> >   package Io renames Ada.Text_IO;
> > 
> >   procedure Work is
> >     The_File : Io.File_Type;
> >   begin
> >     Io.Open (The_File, Io.Out_File, "Test.Txt");
> >     for Count in Natural'value(Ada.Command_Line.Argument(1)) .. Natural'value(Ada.Command_Line.Argument(2)) loop
> >       Io.Put_Line (The_File, "Count =" & Count'img);
> >       Io.Put_Line ("Count =" & Count'img);
> >       delay 1.0;
> >     end loop;
> >     Io.Close (The_File);
> >   exception
> >   when others =>
> >     Io.Put_Line ("Exception");
> >   end Work;
> > 
> > end Test;
> > 
> > If I execute this from one process with parameters 1 10 and then when it reaches 8 start the program again from a second process with parameters 3 7 on the same machine, the resultant file is a nice mixture! :-(
> > 
> > Count = 3
> > Count = 4
> > Count = 5
> > Count = 6
> > Count = 7
> > Count = 6
> > Count = 7
> > Count = 8
> > Count = 9
> > Count = 10
> > 
> > This is not what I want. I want what the first instance produces and the second instance to fail. Surely nobody would want otherwise ;-)
> > 
> > Best wishes,
> > Ahlan
> 
> I am not trying to protect the file from other tasks I am trying to protect the file from other processes - ie other programs or utilities - perhaps executing on other computers if the file in question is on a network. I want to open the file in such a way that I am granted exclusive write access. This has absolutely nothing to do with tasking or protected objects etc.
> Bruce B. tells me that there are routines in the package Directories that can be used to check if the file is already open. However that wouldn't be a full solution because there would be nothing to stop any other program from opening the file and messing with it. However it would be a start. If the file was already opened (by some other process) then I could avoid opening it. Unfortunately I couldn't find any such routine in Ada.Directories. Am I going blind?
> So far the only solution I can see is for me to write my own filing system, one that has the ability to open the file for exclusive file access. However I cannot believe that this is what people really do.
> As it stands if I write a program that writes a log to a text file a second occurrence of the program if run concurrently will mess up this log.
> Is there really no way for an Gnat Ada program to open a file for exclusive access against other processes without resorting to the program writing his/her own filing system? (Open/Read/Write/Close that call directly the OS API)

My Linux version of the reference manual is a bit hard to find from my e-mail.
The Ada-2012 version of the RM has a function Is_Open that returns a Boolean
for each of the IO types defined in that document.  For example section A.10.1
has Is_Open as the first function in the description for Text_IO.  I apologize
for not checking Ada.Directories in the RM when I posted my note earlier today.

I'm still not sure why the alternate processes you're referring to wouldn't
be Ada Tasks.  In that case, the appropriate design would embed the information
you want to protect into an object that forces the other tasks to wait until
the task accessing the file ends.  If you are really running multi-language
implementations, you'll probably need to uncover the code to identify which
process is your Ada process and then have code that interfaces with the Ada.

If you try to run concurrent write operations to text files without using
protected objects or some other form of locking, the IO buffer will certainly 
get confused.  As a result, the output will have a strange interleaving of 
characters from the different processes.  This difficulty certainly makes
debugging by printing lines of text more complicated.  

McCormick, et al. have a
very nice (and simple) code example for a package called "Protected_Output"
that uses a pattern called a Semaphore that deals with this problem.  The
code is on pp. 145-146 of their book.  It may be that their web site
<htttp://www.cambridge.org/9780521197168> can provide the source code.
After you open the site, find a tab labelled "Resources".  Then choose
one called "Source Code" and download the zip file.  The Protected_Output
code is from section 4.7 in the book.  I think the driver for this code
is included in the zip file.

I have compiled and run this demo successfully.  I strongly suggest you consult 
McCormick et al. before you try writing your own file system.

I do apologize for not carefully checking the RM for the proper location
and name of the Is_Open function.

Bruce B.

  parent reply	other threads:[~2015-09-01 20:02 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-08-27 13:52 Exclusive file access ahlan
2015-08-27 14:27 ` gautier_niouzes
2015-08-31 23:20   ` Randy Brukardt
2015-09-01 16:23     ` Pascal Obry
2015-09-01 20:48       ` Randy Brukardt
2015-08-27 14:42 ` Björn Lundin
2015-08-27 14:48 ` G.B.
2015-08-27 15:08   ` Björn Lundin
2015-08-27 18:38     ` tmoran
2015-08-27 23:16     ` Georg Bauhaus
2015-08-27 23:29       ` Pascal Obry
2015-08-28  7:25         ` Georg Bauhaus
2015-08-27 15:15   ` ahlan
2015-08-27 18:29     ` Jeffrey R. Carter
2015-08-28  5:41 ` ahlan
2015-08-28  7:10   ` Georg Bauhaus
2015-08-28 17:40 ` ahlan
2015-08-28 19:49   ` Anh Vo
2015-08-28 21:06     ` Simon Wright
2015-08-28 21:38       ` Jeffrey R. Carter
2015-08-29  7:05   ` Dmitry A. Kazakov
2015-08-29  8:31     ` Pascal Obry
2015-08-29 12:02       ` Dmitry A. Kazakov
2015-08-30 11:35         ` Florian Weimer
2015-08-30 12:44           ` Dmitry A. Kazakov
2015-08-30 19:37             ` Florian Weimer
2015-08-31  7:22               ` Dmitry A. Kazakov
2015-08-31 21:12                 ` Florian Weimer
2015-09-01  7:26                   ` Dmitry A. Kazakov
2015-09-07 18:27                     ` Florian Weimer
2015-09-07 19:06                       ` Dmitry A. Kazakov
2015-09-11 16:54                         ` Florian Weimer
2015-08-31 23:34             ` Randy Brukardt
2015-09-01  7:33               ` Dmitry A. Kazakov
2015-08-29 16:07     ` gautier_niouzes
2015-08-29 17:12       ` Dmitry A. Kazakov
2015-09-01 12:37 ` brbarkstrom
2015-09-01 14:05 ` ahlan
2015-09-01 15:13   ` Simon Wright
2015-09-01 20:36     ` Randy Brukardt
2015-09-01 15:17   ` Jacob Sparre Andersen
2015-09-01 20:37     ` Randy Brukardt
2015-09-01 16:05   ` G.B.
2015-09-01 20:02   ` brbarkstrom [this message]
2015-09-01 21:17     ` Simon Wright
2015-09-05 15:52       ` Björn Lundin
2015-09-01 20:31   ` Randy Brukardt
2015-09-01 15:31 ` ahlan
2015-09-05 15:56   ` Björn Lundin
2015-09-06 17:38     ` brbarkstrom
2015-09-06 19:52       ` Björn Lundin
2015-09-07 15:18         ` brbarkstrom
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox