file.read() doesn't read the whole file

Sreejith K sreejithemk at gmail.com
Sat Mar 21 01:25:58 EDT 2009


	class MedusaFile(object):
		def __init__(self, path, flags, *mode):
			global METHOD
			global NORMAL
			global SNAP
			global FRESH_SNAP
			self.path = path
			tf.writelines("File initiating..\n")
			self.file = os.fdopen(os.open("." + path, flags, *mode),flag2mode
(flags))
			self.fd = self.file.fileno()
			curdir = GetDirPath('.' + path)
			self.snapdir = '.' + path + '_snaps'
			self.snap_cnt = 0
			if os.path.exists(self.snapdir):
				self.snap_cnt = len(os.listdir(self.snapdir))
				METHOD = SNAP
			elif FRESH_SNAP == 1:
				self.snap_cnt += 1
				os.mkdir(self.snapdir)
				os.mkdir(self.snapdir+'/snap%s' % repr(self.snap_cnt))
				METHOD = SNAP
				FRESH_SNAP = 0
			tf.writelines("File initiated..\n")
		def read(self, length, offset):
			global METHOD
			global NORMAL
			global SNAP
			tf.writelines("Read length: %d offset: %d\n" % (length,offset))
			blk_num = offset/4096
			no_blks = length/4096 + 1
			blocks = []
			block_read = False
			## Read form the Base File (Snap 1)
			if METHOD == NORMAL:
				self.file.seek(offset)
				tf.writelines("Normal read\n")
				return self.file.read(length)
			## Read blocks from the snapshots
			else:
				snap_list = range(self.snap_cnt)
				rev_snap_list = snap_list
				rev_snap_list.reverse()
				for i in snap_list:
					blocks.append(os.listdir(self.snapdir+'/snap%s' % repr(i+1))) ##
list of blocks in the current snapshot
				off = offset
				bend = 0
				data = ''
				for block in range(blk_num,blk_num+no_blks): ## loop through the
blocks which are to be read
					for i in rev_snap_list: ## loop through snapshots (starting from
latest snap)
						tf.writelines('Snapshot %d opened..\n' % i)
						if repr(block) in blocks[i]:  ## Check if it is in the snapshot
							tf.writelines("Snap read\n")
							self.snap = open(self.snapdir + '/snap%d/%d' % (i+1,
block),'r')
							self.snap.seek(off%4096)
							bend = 4096-(off%4096)
							block_read = True
							if length-bend <= 0: ## if only a part of block file is to be
read (i.e. not till the end of block file)
								tf.writelines("Partial read from snap \n")
								data = self.snap.read(length)
								self.snap.close()
								break
							tf.writelines("Full block read from snap\n")
							data += self.snap.read(bend)
							length -= bend
							off = 4096
							self.snap.close()
							break
						tf.writelines("Block not in snap\n")
					if block_read:
						block_read = False
						continue
					## otherwise the block should be in the base file itself. So,
read from there
					tf.writelines("Reading from Base File\n")
					self.file.seek(block*4096 + off%4096)
					bend = 4096-(off%4096)
					if length-bend <= 0: ## if only a part of a block is to be read
(not till the end of the block)
						data = self.file.read(length)
						break
					data += self.file.read(bend)
					length -= bend
					off = 4096
				return data

This is the filesystem class for files. Whenever a read occurs an
instance is created and read function is called. In my example when
accessing a file named 'mango.txt' it checks for mango.txt_snaps/snap1
dirctory and open file '0' as self.snap. But the read() returns (i.e
data) a small part....

Almost all the code worked weird in this example. Apart from read(),
the break and continue also works weird. When opening the file
'mango.txt' the following output is written by tf (an output file).
Here METHOD is not NORMAL, self.snap_cnt is 1, blocks is [['0']]

File initiating..
File initiated..
Read length: 4096 offset: 0
Snapshot 0 opened..
Snap read
Partial read from snap
Snapshot 0 opened..
Block not in snap
Reading from Base File

See the weirdness of continue and break here ?(loop was supposed to
loop only once as rev_snap_list contains 0 only)



More information about the Python-list mailing list