http://api.drupal.org/api/function/drupal_build_css_cache/6
http://api.drupal.org/api/function/drupal_build_js_cache/6
http://api.drupal.org/api/function/_color_save_stylesheet/6
All 3 of these function call file_save_data() with FILE_EXISTS_REPLACE. file_move() -> file_save_data() -> file_move() -> file_copy(). Once in file_copy it finally calls copy(). The copy function is slow in comparison to rename(); rename is also safer in this case, less likely for a race condition.
Comment | File | Size | Author |
---|---|---|---|
#52 | drupal-818818-52-file-save-D8.patch | 1.75 KB | mikeytown2 |
#51 | drupal-818818-51-file-save-D7.patch | 1.73 KB | mikeytown2 |
#50 | drupal-818818-50-file-save-D6.patch | 2.2 KB | mikeytown2 |
#47 | drupal-818818-47-file-save-D8.patch | 1.75 KB | mikeytown2 |
#47 | drupal-818818-47-file-save-D7-do-not-test.patch | 1.73 KB | mikeytown2 |
Comments
Comment #1
mikeytown2 CreditAttribution: mikeytown2 commentedThis is similar to what I use in the boost module.
Comment #2
c960657 CreditAttribution: c960657 commentedfile_copy() should not remove the source file. We need to introduce a temporary file, possibly in the same directory (because renames across partitions/mounts are not atomic).
This needs to be fixed in HEAD and then backported.
Comment #3
mikeytown2 CreditAttribution: mikeytown2 commented7.x equivalent is file_unmanaged_copy() from what I can tell.
Comment #4
mikeytown2 CreditAttribution: mikeytown2 commentedPatch with rename in the same dir level now & early abort if the first copy fails.
Comment #6
mikeytown2 CreditAttribution: mikeytown2 commentedThink I fixed the php error & incorrect calling of drupal_tempnam.
Comment #7
carlos8f CreditAttribution: carlos8f commentedsubscribing
Comment #9
mikeytown2 CreditAttribution: mikeytown2 commentedtrying file_put_contents after the drupal_tempnam call instead of copy.
Comment #10
mikeytown2 CreditAttribution: mikeytown2 commentedComment #11
mikeytown2 CreditAttribution: mikeytown2 commentedComment #13
mikeytown2 CreditAttribution: mikeytown2 commentedLooks like I need to fire up 7.x in order to figure this one out.
Comment #14
mikeytown2 CreditAttribution: mikeytown2 commentedWhen I run the test locally I get errors on file_unmanaged_delete_recursive & file_unmanaged_delete.
These are the only errors I get. Any ideas?
.htaccess is marked read only, is this the issue?
Comment #15
mikeytown2 CreditAttribution: mikeytown2 commentedThis patch passes all tests on my local box.
Why did I have to add in chmod($path, 0777) to file_unmanaged_delete()?
Edit:Think I ran the wrong test (File), should have been (File API). Have a feeling this will bomb as well... I'll see how the local one goes for me...
Comment #17
c960657 CreditAttribution: c960657 commentedThe chmod() issue is covered by #443286: Windows File Handling: International characters break file handling, permissions don't translate.
Comment #18
mikeytown2 CreditAttribution: mikeytown2 commentedGoing to try it without using drupal_tempnam. I have a feeling this function isn't working as I'm expecting it to.
Comment #19
mikeytown2 CreditAttribution: mikeytown2 commentedwithout chmod
Comment #20
mikeytown2 CreditAttribution: mikeytown2 commentedTrying
$temp_name = drupal_tempnam(dirname($destination . '/'), 'file');
Comment #21
mikeytown2 CreditAttribution: mikeytown2 commentedHelps to grab the right file...
Comment #23
mikeytown2 CreditAttribution: mikeytown2 commentedGoing ahead & not using drupal_tempnam. Besides this point, how does the patch look?
Comment #24
mikeytown2 CreditAttribution: mikeytown2 commentedRe-roll of 6.x based off the latest changes to the 7.x patch
Comment #25
c960657 CreditAttribution: c960657 commentedPlease add a comment explaining why we have two different code paths here.
The else part covering the two other modes could be extended with a fopen($file, 'x') call to ensure that existing files are never overwritten (another race condition). But that is probably a separate issue.
You may also add a comment mentioning that the unlink() call is necessary, because rename() cannot overwrite existing files on Windows. It would be nice if we could avoid the unlink() on platforms where rename() supports overwriting, though (one approach can be seen here: http://www.smarty.net/forums/viewtopic.php?t=6956&postdays=0&postorder=a...).
$temp_name will always evalute to TRUE here.
Could we choose a name that looks more "temporary"? E.g. add ".tmp" or something.
Elsewhere in core, e.g. in lock.inc we use
uniqid(mt_rand(), TRUE)
for generating a unique random identifier. But why not use drupal_tempnam() ? If there is a good reason, please add a comment explaining why.Comment #26
mikeytown2 CreditAttribution: mikeytown2 commented@c960657
I tried drupal_tempnam many times in different ways but it always fails the testbot. That's the reason there are so many fails in this thread.
Comment #27
c960657 CreditAttribution: c960657 commentedWhy does the testbot not like it?
Do the tests pass on your local machine? If they do, we should fix the testbot (or whatever is causing the tests to fail), rather than implementing workarounds.
Comment #28
mikeytown2 CreditAttribution: mikeytown2 commentedfile_directory_temp uses OS detection so I wouldn't feel bad doing it again in core
Option A
Option B
Comment #29
mikeytown2 CreditAttribution: mikeytown2 commentedtests fail on my local box
Comment #30
mikeytown2 CreditAttribution: mikeytown2 commentedadded comments & went for option A
I have 5 different ways of creating the temp file; 2 without drupal_tempnam (A & E) 3 with (B, C & D).
Comment #31
mikeytown2 CreditAttribution: mikeytown2 commented... can't get this right. Here are all of the D7 done again.
Comment #32
mikeytown2 CreditAttribution: mikeytown2 commentedFound 2 functions
drupal_dirname
drupal_realpath
I think I can make this work correctly now...
Comment #34
mikeytown2 CreditAttribution: mikeytown2 commentednot using drupal_dirname
Comment #36
mikeytown2 CreditAttribution: mikeytown2 commentednot using drupal_realpath
Comment #37
mikeytown2 CreditAttribution: mikeytown2 commentedremove the temp file if rename or copy failed
Comment #38
mikeytown2 CreditAttribution: mikeytown2 commentedComment #39
andypostWhy not assign result in copy
Is there any benchmarks about copy and rename?
Comment #40
sun.core CreditAttribution: sun.core commentedIt's not clear to me what "atomic" means in this context. The further description seems to try to explain parts of it, but overall it looks like the problem space that caused this (ugly) workaround is not properly explained.
1) Typo in "mutiple".
2) "temp" should be "temporary". (and elsewhere)
1) Missing trailing periods.
2) Typo in "opperation".
Powered by Dreditor.
Comment #41
mikeytown2 CreditAttribution: mikeytown2 commented@sun
Thanks for the review. Latest changes to the code. Hopefully the comments explain the code better, and why it's needed.
@andypost
We don't care if the copy to the temporary file worked; we care if the copy to the destination works. That is why I assigned
$result = @rename($temporary_file, $destination)
and not do it here@copy($source, $temporary_file)
Comment #42
pillarsdotnet CreditAttribution: pillarsdotnet commentedBumping and tagging per standard policy.
Comment #43
pillarsdotnet CreditAttribution: pillarsdotnet commented#41: drupal-818818-41-D7.patch queued for re-testing.
Comment #45
oriol_e9g@andypost: Just out of curiosity: copy() / rename() benchmarks in my localhost: Seems that a single copy operation is slower than a rename operation, but a lot of consecutively copy operations are faster O.o
Code used for benchmarking attached.
Comment #46
oriol_e9gPorted to D8, NR for testbot.
Comment #47
mikeytown2 CreditAttribution: mikeytown2 commented#46 rerolled and back ported to D7 & D6
Comment #49
mikeytown2 CreditAttribution: mikeytown2 commented#47: drupal-818818-47-file-save-D8.patch queued for re-testing.
Got a fatal error on line #37... looks like testbot messed up, so going to retest
Screenshot of testpage: http://drupal.org/node/1158322#comment-6417676
EDIT: Test looks good now :)
Comment #50
mikeytown2 CreditAttribution: mikeytown2 commentedWant to make sure patch passes testbot. Fixed 2 errors that I found when back porting the patch to 6.x as drupal_tempnam and drupal_dirname are 7.x+ functions.
Comment #51
mikeytown2 CreditAttribution: mikeytown2 commentedTesting the 7.x patch now.
Comment #52
mikeytown2 CreditAttribution: mikeytown2 commentedMoving back to 8.x and waiting...
Comment #53
amontero#52: drupal-818818-52-file-save-D8.patch queued for re-testing.
Comment #54
mikeytown2 CreditAttribution: mikeytown2 commentedGoing to mark this as a duplicate of #1377740: file_unmanaged_move() should issue rename() where possible instead of copy() & unlink()