* vfs/fish.c (fish_file_store): Improve the upload speed by using the

`head' utility when possible. Fallback to a new improved `dd' method
if `head' is not availaible or just stupid.
This commit is contained in:
Pavel Tsekov 2006-03-30 14:39:33 +00:00
parent 52a724a2c8
commit 407497fd43
2 changed files with 55 additions and 5 deletions

View File

@ -1,3 +1,9 @@
2006-03-30 Dmitry Butskoj <buc@odusz.so-cdu.ru>
* fish.c (fish_file_store): Improve the upload speed by using the
`head' utility when possible. Fallback to a new improved `dd' method
if `head' is not availaible or just stupid.
2006-03-30 Pavel Tsekov <ptsekov@gmx.net>
* direntry.c (vfs_s_inode_from_path): Revert last change.

View File

@ -494,7 +494,31 @@ fish_file_store(struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *loc
close (h);
ERRNOR (EIO, -1);
}
/* Use this as stor: ( dd block ; dd smallblock ) | ( cat > file; cat > /dev/null ) */
/* First, try this as stor:
*
* ( head -c number ) | ( cat > file; cat >/dev/null )
*
* If `head' is not present on the remote system, `dd' will be used.
* Unfortunately, we cannot trust most non-GNU `head' implementations
* even if `-c' options is supported. Therefore, we separate GNU head
* (and other modern heads?) using `-q' and `-' . This causes another
* implementations to fail (because of "incorrect options").
*
* Fallback is:
*
* rest=<number>
* while [ $rest -gt 0 ]
* do
* cnt=`expr \( $rest + 255 \) / 256`
* n=`dd bs=256 count=$cnt | tee -a <target_file> | wc -c`
* rest=`expr $rest - $n`
* done
*
* `dd' was not designed for full filling of input buffers,
* and does not report exact number of bytes (not blocks).
* Therefore a more complex shell script is needed.
*/
print_vfs_message(_("fish: store %s: sending command..."), name );
quoted_name = name_quote (name, 0);
@ -505,25 +529,45 @@ fish_file_store(struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *loc
"#STOR %lu /%s\n"
"> /%s\n"
"echo '### 001'\n"
"res=`exec 3>&1\n"
"(\n"
"dd bs=1 count=%lu\n"
"head -c %lu -q - || echo DD >&3\n"
") 2>/dev/null | (\n"
"cat > /%s\n"
"cat > /dev/null\n"
"); echo '### 200'\n",
")`; [ \"$res\" = DD ] && {\n"
"rest=%lu\n"
"while [ $rest -gt 0 ]\n"
"do\n"
" cnt=`expr \\( $rest + 255 \\) / 256`\n"
" n=`dd bs=256 count=$cnt | tee -a /%s | wc -c`\n"
" rest=`expr $rest - $n`\n"
"done\n"
"}; echo '### 200'\n",
(unsigned long) s.st_size, name, quoted_name,
(unsigned long) s.st_size, quoted_name,
(unsigned long) s.st_size, quoted_name);
else
n = fish_command (me, super, WAIT_REPLY,
"#STOR %lu /%s\n"
"echo '### 001'\n"
"res=`exec 3>&1\n"
"(\n"
"dd bs=1 count=%lu\n"
"head -c %lu -q - || echo DD >&3\n"
") 2>/dev/null | (\n"
"cat >> /%s\n"
"cat > /dev/null\n"
"); echo '### 200'\n",
")`; [ \"$res\" = DD ] && {\n"
"rest=%lu\n"
"while [ $rest -gt 0 ]\n"
"do\n"
" cnt=`expr \\( $rest + 255 \\) / 256`\n"
" n=`dd bs=256 count=$cnt | tee -a /%s | wc -c`\n"
" rest=`expr $rest - $n`\n"
"done\n"
"}; echo '### 200'\n",
(unsigned long) s.st_size, name,
(unsigned long) s.st_size, quoted_name,
(unsigned long) s.st_size, quoted_name);
g_free (quoted_name);