kuldeepchowhan has asked for the wisdom of the Perl Monks concerning the following question:

I have a script which checks two drives (A & B) for the maximum free space available and starts copying to the drive which has the maximum free space available (lets say A).

Free Space :

A : 12GB

B : 6GB

Files to the copied : 5GB

In the mean time if other instance of the script is started which needs to copy 8 GB of files and even at that moment of time if A drive has the maximum free space, then the script starts copying files to the A drive only and after sometime as both the sizes add up to 13 GB, the script fails to copy the files successfully.

What is the best way to avoid this and make sure that the second instance of the script doesn't write to the same drive.

I have an idea to create a temp file in the drive in which i am copying the files and skip that drive if the file exists.

Is there any other effective way of doing this ?

Replies are listed 'Best First'.
Re: Need Advice on Folder/Drive locking
by cdarke (Prior) on Feb 04, 2010 at 13:00 UTC
    The problem with using locking files is that they hang-around if the system goes down. Using a kernel object such as a semaphore can be much safer. See IPC::Semaphore.

      As i don't want the drive to be shared, instead of semaphore can i use mutex? Also, how do we create a mutex on a remote machine?

        A Semaphore with a maximum count of 1 is functionally the same as a mutex (sometimes called a binary semaphore). Of course you can use a mutex instead, is this on Windows?

        Nowhere in your post did you mention that a remote machine is involved. In that case a Mutex or Semaphore is not appropriate (I'm not so sure that file locking would be either). Other options include named pipes, but this then depends on the operating system.
      Since this is a Windows machine, one facility that might or might not have applicability here is the RunOnce registry key. This allows you to say, "hey if the system crashes and reboots", run program X for this boot instance only (after that the OS deletes this entry). Program X might say, remove lock files.

      Some installation programs will register a program like this before starting some complex operation and then remove the RunOnce entry when the operation completes successfully. If Program X ever runs, it knows that "complex operation" didn't complete successfully and it can presumably go about some cleanup job to get things in a consistent state. Of course there are lot's of ways that lock files can be left dangling around out there short of a full system crash! But I thought this feature was worth a mention.

Re: Need Advice on Folder/Drive locking
by Corion (Patriarch) on Feb 04, 2010 at 12:54 UTC

    I wouldn't create the temp file on the target but under (say) /var/run or /tmp or some other central location for the machine, and use a filename derived from the name of the target device, but other than that, I don't see any other effective approach.

Re: Need Advice on Folder/Drive locking
by bot403 (Beadle) on Feb 04, 2010 at 21:04 UTC

    Not sure if windows supports sparse files but I did the same task in unix by making a *SPARSE* lock file that was the same size as the file I was copying and used that in my size calculations.

    sysopen( $fh, $lock_filename, O_RDWR | O_CREAT ); seek($fh, $filesize,0); truncate($fh,$filesize);

    Then a stat call gives us the sparse size while the filesystem hasn't grown at all. To get a rough idea of free space you can tally the free space the FS reports minus the sum of the size of all your sparse lock files.

    Update: Code typos fixed

      interesting idea. Yes, Windows NTFS does support sparse files. to make one...see below.

      One link http://msdn.microsoft.com/en-us/library/aa365564(VS.85).aspx
      Google "windows sparse file" for others including "FSUTIL Sparse" command line manager on Win XP.

      #!/usr/bin/perl -w use strict; open(FILE, ">", "sparse") || die "unable to open for write\n"; print FILE "some stuff"; seek(FILE,1000000,0); print FILE "more stuff"; close FILE;
Re: Need Advice on Folder/Drive locking
by repellent (Priest) on Feb 05, 2010 at 03:10 UTC
    # make sure /tmp/unlocked_[ab] exist first if ($write_to_A) { lock_region { print "Writing to Drive A ...\n"; ## do A stuff print "Done with Drive A.\n"; } qw(/tmp/unlocked_a /tmp/locked_a); } else { lock_region { print "Writing to Drive B ...\n"; ## do B stuff print "Done with Drive B.\n"; } qw(/tmp/unlocked_b /tmp/locked_b); }

Re: Need Advice on Folder/Drive locking
by vkk0125 (Initiate) on Feb 05, 2010 at 05:43 UTC
    At the risk of sounding to simplistic I would just create a temporary file with a specific filename format that "reserves" space on the drive. When your script starts it looks for "drive:\CopyScript*.log and if one or more exist it parses the filename(s) to determine how much space is reserved.

    That said, if the scripts calculates that this drive should be used it should first write it's temporary file, then sleep for a short time, then CHECK to make sure that another instance of the script hasn't already "slipped through" and reserved space, little checks like that can save you in the future.

    The logic sounds good to my weary head... hope it makes sense!