forked from xedakini/replicator
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCache.py
117 lines (83 loc) · 2.89 KB
/
Cache.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import Params, os, hashlib
def makedirs( path ):
dir = os.path.dirname( path )
if dir and not os.path.isdir( dir ):
if os.path.isfile( dir ):
print 'directory %s mistaken for file' % dir
os.remove( dir )
else:
makedirs( dir )
os.mkdir( dir )
class File:
size = -1
mtime = -1
def __init__( self, path ):
if Params.MAXFILELEN > -1:
newpath = os.sep.join( item if len(item) <= Params.MAXFILELEN else
item[:Params.MAXFILELEN-34] + '..' + hashlib.md5( item[Params.MAXFILELEN-34:] ).hexdigest()
for item in path.split( os.sep ) )
if newpath != path:
print 'Shortened path to %s characters' % '/'.join( str(len(w)) for w in newpath.split(os.sep) )
path = newpath
sep = path.find( '?' )
if sep != -1:
path = path[ :sep ] + path[ sep: ].replace( '/', '%2F' )
if Params.FLAT:
path = os.path.basename( path )
if Params.VERBOSE:
print 'Cache position:', path
self.__path = Params.ROOT + path
self.__file = None
def partial( self ):
return os.path.isfile( self.__path + Params.SUFFIX ) and os.stat( self.__path + Params.SUFFIX )
def full( self ):
return os.path.isfile( self.__path ) and os.stat( self.__path )
def open_new( self ):
print 'Preparing new file in cache'
try:
makedirs( self.__path )
self.__file = open( self.__path + Params.SUFFIX, 'w+' )
except Exception, e:
print 'Failed to open file:', e
self.__file = os.tmpfile()
def open_partial( self, offset=-1 ):
self.mtime = os.stat( self.__path + Params.SUFFIX ).st_mtime
self.__file = open( self.__path + Params.SUFFIX, 'a+' )
if offset >= 0:
assert offset <= self.tell(), 'range does not match file in cache'
self.__file.seek( offset )
self.__file.truncate()
print 'Resuming partial file in cache at byte', self.tell()
def open_full( self ):
self.mtime = os.stat( self.__path ).st_mtime
self.__file = open( self.__path, 'r' )
self.size = self.tell()
print 'Reading complete file from cache'
def remove_full( self ):
os.remove( self.__path )
print 'Removed complete file from cache'
def remove_partial( self ):
print 'Removed partial file from cache'
os.remove( self.__path + Params.SUFFIX )
def read( self, pos, size ):
self.__file.seek( pos )
return self.__file.read( size )
def write( self, chunk ):
self.__file.seek( 0, 2 )
return self.__file.write( chunk )
def tell( self ):
self.__file.seek( 0, 2 )
return self.__file.tell()
def close( self ):
size = self.tell()
self.__file.close()
if self.mtime >= 0:
os.utime( self.__path + Params.SUFFIX, ( self.mtime, self.mtime ) )
if self.size == size:
os.rename( self.__path + Params.SUFFIX, self.__path )
print 'Finalized', self.__path
def __del__( self ):
try:
self.close()
except:
pass