alibaba / tfs

TFS (Taobao File System) is a distributed file system similar to GFS.
http://tfs.taobao.org
GNU General Public License v2.0
1.24k stars 457 forks source link

tfs带offset写入的问题 #14

Closed lanyuliuyun closed 8 years ago

lanyuliuyun commented 8 years ago

1, t_pwrite() 带 offset 写入数据,写入OK,t_close() 也正常返回了一个tfs文件名,但后续用tfstool的stat命令查看该文件,结果失败。打印中有 -8025 的错误码,如下 ERROR async_rsp_stat_file (tfs_file.cpp:1542) [140430609741664] stat file fail. blockid: 1450, fileid: 3, ret: -8025, erorr msg: readfileinfo fail, blockid: 1450, fileid: 3, ret: -8025 意思是在index文件中未找到该文件的meta信息 继续用lsf命令查看该block,结果中没有该文件。

2,类似的重新以 T_WRITE 方式打开现有的tfs文件,写入新的数据之后,发现文件原有的数据被截断。似乎内部写入offset值是从0开始的,但手工lseek到文件结尾(T_SEEK_END),也没有效果。——后来看client代码发现该seek方式无效果,只有SET/CUR有用,算是一个坑!

目前是在虚拟机里搭建一个单机环境,使用tfstool工具写入文件没有问题;直接 t_write() 不带offset将一个完整文件的数据写入也没有问题。

使用的版本是 http://code.taobao.org/svn/tfs/branches/dev_for_outer_users/

lanyuliuyun commented 8 years ago

初步看了一下tfs客户端代码,发现 t_write() 与 tpwrite() 的差别在于,后者通过参数指定当前数据块的写入offset,并且不会更新 TfsFile::offset 内部的偏移指针而已。其他的流程与 t_write() 无异。

不太明白在自己的案例中怎么会如此,有对此熟悉的同学解答一下么?

lanyuliuyun commented 8 years ago

@tfs-taobao

lanyuliuyun commented 8 years ago

直接使用 t_write(),每次手工 t_lseek() 到指定位置,可以写入成功。 但 t_close() 之后,再以 RW 方式打开,t_lseek() 到指定位置,追加写入新的数据,t_write() 成功,根据log显示,offset值是对的,但 t_close() 却失败了,返回 -8013 ,意思”datafile is NULL / crc / getdata error“。再使用 stat 命令查看文件状态,发现后续RW打开文件后,写入的数据没有被保存。

lanyuliuyun commented 8 years ago

分析了 dataserver 的代码之后,知道原因了,每次 t_open() 之后分配一个新的filenumber。初次写入数据时,dataserver 会为当前的会话 new 一个 DataFile对象进行标识,其包含一个2MiB的buffer。若此时 seek 设置写入offset再写入,写入的data前面会包含一些空洞(offset + size小于2MiB时)。t_close() 时,dataserver 会对 DataFile 的的buffer,从起始位置到数据结尾进行计算得到一个 CRC,拿这个 CRC 值与client提交的CRC值进行比较,此时就因CRC值不同而t_close() 失败了。

而刚才 DataFile 中计算CRC时,是将那些空洞里的数据算在内的,但该空洞中的数据是不确定的(new的原因),从而计算出的CRC值是无意义的,因此 t_close() 时 dataserver 必然出错。

只能说 tfs 太坑了!虽然提供了 lseek,但根本就不是常规 seek 的语义,形同虚设! 上传数据时,必须一次性全部写入,保证数据连续,不能后续重新打开后append !