8

I am trying to rename() a 900 KiB PDF file in PHP. It is taking a long time to rename it for some reason. I thought it should be instant.

This is on a CentOS server. While the file is being renamed I can get properties and it seems like rename() is copying and replacing the old file with new renamed file.

The old name and new name paths are in the same directory.

Has anyone stumbled upon this issue before?


Code:

    //If exists change name and then return path
    $pieces = explode("@", $filename);
    $newName = $pieces[0].' '.$pieces[2];

    rename($uidPath.$filename, $uidPath.$newName);

    if (preg_match('/pdf/', $pieces[2]))
    {
        $result['status'] = '1';
        $result['path'] = 'path to file';
    } 
    else 
    {
        $result['status'] = '1';
        $result['path'] = 'path to file';
    }
Marin Sagovac
  • 3,932
  • 5
  • 23
  • 53
TeaCupApp
  • 11,316
  • 18
  • 70
  • 150
  • Is it possible that another process has the file locked and rename is waiting for the lock to release? Renaming a file shouldn't result in it being copied at all and should be instant as you expect. – drew010 Oct 17 '12 at 23:15
  • maybe you should show your code? – Ibu Oct 17 '12 at 23:15
  • 5
    Is the process of renaming a file causing it to move from one disk partition to another? – Mike Brant Oct 17 '12 at 23:17
  • show your code, otherwise we don't know how you rename that file. Not that it is more obvious then what the problem is, but it might be. – hakre Oct 17 '12 at 23:38
  • 1
    http://www.java-samples.com/showtutorial.php?tutorialid=934 – cmbuckley Oct 17 '12 at 23:41
  • 2
    @MikeBrant This is clearly written in the question: "The old name and new name paths are in the same directory." – Jocelyn Oct 17 '12 at 23:51
  • I have just added the code, Sorry for earlier. I thought it's just a simple one liner and I should get away with it :) – TeaCupApp Oct 18 '12 at 00:33
  • does `$uidPath` end with a slash ?? – Baba Oct 18 '12 at 00:38
  • The file name actually contains an '@' character? – Wiseguy Oct 18 '12 at 01:00
  • I've seen this for NFS mounted file systems. Is this file local? – Brent Baisley Oct 18 '12 at 01:53
  • 1
    Perhaps using exec() with a call to 'mv filename newName' would work better? – Lars Rohrbach Oct 18 '12 at 07:50
  • @Baba, yes the uid path has slash at the end – TeaCupApp Oct 18 '12 at 09:47
  • @Wiseguy, The old name contains @ char in it – TeaCupApp Oct 18 '12 at 09:48
  • @BrentBaisley, I don't have clue of the file system but I could get back to you by asking our network admin – TeaCupApp Oct 18 '12 at 09:49
  • visit: http://stackoverflow.com/questions/1004478/read-pdf-files-with-php and http://stackoverflow.com/questions/5180718/reading-pdf-files-in-php – krishna Oct 19 '12 at 10:05
  • 5
    @pbvamsi I do not understand what those questions have to do with this question? – Pekka Oct 19 '12 at 22:08
  • Are you using a virtual machine? – BurninLeo Oct 19 '12 at 22:12
  • Suhosin pack active or is modified? – Marin Sagovac Oct 19 '12 at 22:22
  • If you have just closed resource pointing to that file PHP will be quite slow to release the lock. I haven't found a way around it, so I just have it sleep for a second after close. – c2h5oh Oct 19 '12 at 23:51
  • 1
    Did you actually profile it and found that `rename` is the bottleneck? also check the values of `$uidPath.$filename` and `$uidPath.$newName` in run-time using `var_dump` or a debugger. – Shiplu Mokaddim Oct 20 '12 at 07:27
  • @c2h5oh, Your point sounds interesting, as I do have file_put_content method called just before I am renaming that file. Does file_put_content creates file first and then write data incrementally? Or spits out entire file and content altogeather? – TeaCupApp Oct 20 '12 at 13:58
  • 1
    @Owl From PHP docs: `This function is identical to calling fopen(), fwrite() and fclose() successively to write data to a file.` So most likely your rename is slowed down by the very same issue I had - `fclose` being slow to release the file lock. – c2h5oh Oct 20 '12 at 14:21
  • @c2h5oh, hmmm...thats a good catch! Let me re-work the logic so the file only gets renamed after entire file is wriiten succesfully. – TeaCupApp Oct 21 '12 at 08:57
  • How many files do you have in this folder? – Nazariy Oct 22 '12 at 15:57
  • @c2h5oh, Hey mate! could you please add your comment as an answer so I can accept it. It was indeed the locking issue. – TeaCupApp Oct 23 '12 at 01:00
  • @Owl Done :-) BTW did you find a way around it? – c2h5oh Oct 23 '12 at 19:52
  • Nah I end up re-engineering the process :) now I am changing name twice. First time with temp keyword in it and then the name of file by which I am checking, if file exists. :) – TeaCupApp Oct 23 '12 at 20:27

1 Answers1

3

PHP is for some reason very slow to release file lock on fclose(), so if you are writing to the file prior to moving it you might have to wait for a bit. I've had this very problem with a low priority background job, so I didn't really look into why this happens or what I can do to prevent it - I just added 1 second sleep between fclose() and rename.

c2h5oh
  • 4,492
  • 2
  • 23
  • 30