From 505e75eee4c35bdf7cefb1fedaac99ee920b6177 Mon Sep 17 00:00:00 2001 From: Steve Slaven Date: Thu, 23 Jul 2009 09:48:31 -0700 Subject: Converted debugging messages to print based on levels, fix truncate to use the archive file ftruncate to make sure we don't hose up the file format diff --git a/fusearchive.py b/fusearchive.py index 6f6305f..328ee49 100755 --- a/fusearchive.py +++ b/fusearchive.py @@ -2,6 +2,7 @@ # Copyright (C) 2001 Jeff Epler # Copyright (C) 2006 Csaba Henk +# Copyright (C) 2009 Steve Slaven # # This program can be distributed under the terms of the GNU LGPL. # See the file COPYING. @@ -25,6 +26,11 @@ fuse.feature_assert('stateful_files', 'has_init') magic_blocksize = 1024 * 32 magic_depth = 5 +debug_level = 2 + +def dmsg(level,message): + if level <= debug_level: + print str(level) + ": " + message def flag2mode(flags): md = {os.O_RDONLY: 'r', os.O_WRONLY: 'w', os.O_RDWR: 'w+'} @@ -39,16 +45,16 @@ def flag2mode(flags): # should go # we assume our chunks are in storage/ def inflate( src, dest ): - print "inflate!" + dmsg( 1, "inflate!" ) out = open( dest, "w" ) - print "Unpickling: " + src + dmsg( 2, "Unpickling: " + src ) # TODO: return an IO error if inflating fails inp = gzip.open( src, "r" ) magic = pickle.load( inp ) inp.close() - print "Got data: " + str( magic ) + dmsg( 2, "Got data: " + str( magic ) ) #pdb.set_trace() @@ -57,27 +63,27 @@ def inflate( src, dest ): ( hash, seq ) = key chars = list( hash ) - print chars + dmsg( 4, chars ) # Todo: make a digest -> path function to share with deflate hexdigest = ''.join( [ "%02x" % ord( x ) for x in chars ] ); subparts = [ "%02x" % ord( x ) for x in chars[ :magic_depth ] ] subpath = '/'.join( subparts ); - print "Subpath: " + subpath + dmsg( 3, "Subpath: " + subpath ) subpath += "/" + hexdigest + "_" + str( seq ); - print "Chunk path: " + subpath + dmsg( 3, "Chunk path: " + subpath ) if os.path.exists( "./storage/" + subpath ): - print "Exporting chunk" + dmsg( 3, "Exporting chunk" ) readchunk = gzip.open( "./storage/" + subpath ) out.write( readchunk.read() ) readchunk.close() else: raise IOError - print "File inflated" + dmsg( 2, "File inflated" ) out.close() # TODO: deflate only if the file has been modified @@ -85,7 +91,7 @@ def inflate( src, dest ): # Deflate a file, src is the unpacked file, dest is where we want to pack # to, and we assume storage/ is where chunks are stored def deflate( src, dest ): - print "deflate!" + dmsg( 2, "deflate!" ) inp = open( src, "r" ) hashs = []; @@ -106,7 +112,7 @@ def deflate( src, dest ): # Write out our chunk chars = list( digest ) - print chars + dmsg( 4, chars ) # We make the hexdigest here, yeah we could just call hexdigest() # but we need to essentially do this same thing to reassemble the @@ -116,23 +122,23 @@ def deflate( src, dest ): # Subparts just needs the first N chars subparts = [ "%02x" % ord( x ) for x in chars[ :magic_depth ] ] - print subparts + dmsg( 4, subparts ) subpath = '/'.join( subparts ); - print "Subpath: " + subpath + dmsg( 3, "Subpath: " + subpath ) # Make sure this sub path exists nextpart = "./storage" for part in subparts: nextpart += "/" + part if not os.path.exists( nextpart ): - print "Creating subdir: " + nextpart + dmsg( 3, "Creating subdir: " + nextpart ) os.mkdir( nextpart ) # Find a chunk slot sub = 0 while True: checkpath = "./storage/" + subpath + "/" + hexdigest + "_" + str( sub ) - print "Checking: " + checkpath + dmsg( 3, "Checking: " + checkpath ) if os.path.exists( checkpath ): # Check if this is our data verify = gzip.open( checkpath, "r" ) @@ -140,20 +146,20 @@ def deflate( src, dest ): verify.close() if verify_contents == chunk: - print "Found existing block" + dmsg( 2, "Found existing block" ) break else: - print "Block exists but is not the same" + dmsg( 2, "Block exists but is not the same" ) sub += 1 else: # We found a spot, dump our data here - print "No block here, creating new block" + dmsg( 2, "No block here, creating new block" ) savechunk = gzip.open( checkpath, "w" ) savechunk.write( chunk ) savechunk.close break - print "Got chunk slot: " + str( sub ) + dmsg( 2, "Got chunk slot: " + str( sub ) ) hashs.append( [ digest, sub ] ) inp.close() @@ -195,7 +201,7 @@ class FuseArchive(Fuse): stats = os.lstat( treefile ) if os.path.isfile( treefile ): - print "Reading file to get size: " + path + dmsg( 3, "Reading file to get size: " + path ) #pdb.set_trace() @@ -204,7 +210,7 @@ class FuseArchive(Fuse): magic = pickle.load( inp ) inp.close() - print "Overridding getattr" + dmsg( 3, "Overridding getattr" ) stats = FuseArchiveStat( stats, magic[ 'stat' ] ) return stats @@ -238,9 +244,11 @@ class FuseArchive(Fuse): os.chown("./tree" + path, user, group) def truncate(self, path, len): - f = open("./tree" + path, "a") - f.truncate(len) - f.close() + # Truncate using the ftruncate on the file + dmsg( 2, "Using FuseArchiveFile to truncate " + path + " to " + str(len) ) + f = self.FuseArchiveFile( path, os.O_APPEND, 0 ) + f.ftruncate(len) + f.release( 0 ) def mknod(self, path, mode, dev): os.mknod("./tree" + path, mode, dev) @@ -310,56 +318,62 @@ class FuseArchive(Fuse): def __init__(self, path, flags, *mode): # Inflate the file - print "Init file: " + path + dmsg( 2, "Init file: " + path ) self.orig_path = path; ( fdnum, self.tmp_name ) = tempfile.mkstemp(); #os.close( fdnum ); if os.path.exists( "./tree" + self.orig_path ): inflate( "./tree" + path, self.tmp_name ) + else: + if re.match( '(a|w)', flag2mode( flags ) ): + dmsg( 2, "File doesn't exist and we're going to write, creating temp empty file" ) + deflate( "/dev/null", "./tree" + path ) - print "Shadow file: " + self.tmp_name + " for " + self.orig_path - print "Going to open shadow file with flags: " + str(flags) + " mode " + str(mode) + dmsg( 2, "Shadow file: " + self.tmp_name + " for " + self.orig_path ) + dmsg( 2, "Going to open shadow file with flags: " + str(flags) + " mode " + str(mode) ) # pdb.set_trace() - print "Flag2mode is: " + str( flag2mode( flags ) ) + dmsg( 2, "Flag2mode is: " + str( flag2mode( flags ) ) ) # Just use the fdnum they gave us instead of reopening it, # since that might fail # fdnum = os.open( self.tmp_name, flags, *mode ) #print "Got fdnum: " + str(fdnum) self.file = os.fdopen( fdnum, flag2mode( flags ) ) - print "Open" + dmsg( 2, "Open" ) self.fd = self.file.fileno() self.direct_io = False self.keep_cache = False - print str(self) + " init complete" + self.modified = False + + dmsg( 2, str(self) + " init complete" ) def read(self, length, offset): - print "Reading from " + self.orig_path + dmsg( 2, "Reading from " + self.orig_path ) self.file.seek(offset) return self.file.read(length) def write(self, buf, offset): - print "Writing to " + self.orig_path + dmsg( 2, "Writing to " + self.orig_path ) self.file.seek(offset) self.file.write(buf) return len(buf) def release(self, flags): # Deflate the file - print "Release: " + self.orig_path + dmsg( 2, "Release: " + self.orig_path ) self.file.close() - print "Copying working file back to storage: " + \ - self.tmp_name + " -> " + self.orig_path + dmsg( 2, "Copying working file back to storage: " + \ + self.tmp_name + " -> " + self.orig_path ) #pdb.set_trace() deflate( self.tmp_name, "./tree" + self.orig_path ); - print "Deleting old file: " + self.tmp_name + dmsg( 2, "Deleting old file: " + self.tmp_name ) os.unlink( self.tmp_name ); def _fflush(self): -- cgit v0.10.2