summaryrefslogtreecommitdiffstats
path: root/Demo/pdist/cmptree.py
blob: 8a34f3f681b02641efb9aad5f9bf394a1dd2439e (plain)
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
"""Compare local and remote dictionaries and transfer differing files -- like rdist."""

import sys
from repr import repr
import FSProxy
import time
import os

def main():
	pwd = os.getcwd()
	s = raw_input("chdir [%s] " % pwd)
	if s:
		os.chdir(s)
		pwd = os.getcwd()
	host = ask("host", 'voorn.cwi.nl')
	port = 4127
	verbose = 1
	mode = ''
	print """\
Mode should be a string of characters, indicating what to do with differences.
r - read different files to local file system
w - write different files to remote file system
c - create new files, either remote or local
d - delete disappearing files, either remote or local
"""
	s = raw_input("mode [%s] " % mode)
	if s: mode = s
	address = (host, port)
	t1 = time.time()
	local = FSProxy.FSProxyLocal()
	remote = FSProxy.FSProxyClient(address, verbose)
	compare(local, remote, mode)
	remote._close()
	local._close()
	t2 = time.time()
	dt = t2-t1
	mins, secs = divmod(dt, 60)
	print mins, "minutes and", round(secs), "seconds"
	raw_input("[Return to exit] ")

def ask(prompt, default):
	s = raw_input("%s [%s] " % (prompt, default))
	return s or default

def askint(prompt, default):
	s = raw_input("%s [%s] " % (prompt, str(default)))
	if s: return string.atoi(s)
	return default

def compare(local, remote, mode):
	print
	print "PWD =", repr(os.getcwd())
	sums_id = remote._send('sumlist')
	subdirs_id = remote._send('listsubdirs')
	remote._flush()
	print "calculating local sums ..."
	lsumdict = {}
	for name, info in local.sumlist():
		lsumdict[name] = info
	print "getting remote sums ..."
	sums = remote._recv(sums_id)
	print "got", len(sums)
	rsumdict = {}
	for name, rsum in sums:
		rsumdict[name] = rsum
		if not lsumdict.has_key(name):
			print repr(name), "only remote"
			if 'r' in mode and 'c' in mode:
				recvfile(local, remote, name)
		else:
			lsum = lsumdict[name]
			if lsum != rsum:
				print repr(name),
				rmtime = remote.mtime(name)
				lmtime = local.mtime(name)
				if rmtime > lmtime:
					print "remote newer",
					if 'r' in mode:
						recvfile(local, remote, name)
				elif lmtime > rmtime:
					print "local newer",
					if 'w' in mode:
						sendfile(local, remote, name)
				else:
					print "same mtime but different sum?!?!",
				print
	for name in lsumdict.keys():
		if not rsumdict.keys():
			print repr(name), "only locally",
			fl()
			if 'w' in mode and 'c' in mode:
				sendfile(local, remote, name)
			elif 'r' in mode and 'd' in mode:
				os.unlink(name)
				print "removed."
			print
	print "gettin subdirs ..."
	subdirs = remote._recv(subdirs_id)
	common = []
	for name in subdirs:
		if local.isdir(name):
			print "Common subdirectory", repr(name)
			common.append(name)
		else:
			print "Remote subdirectory", repr(name), "not found locally"
			if 'r' in mode and 'c' in mode:
				pr = "Create local subdirectory %s? [y] " % \
				     repr(name)
				if 'y' in mode:
					ok = 'y'
				else:
					ok = ask(pr, "y")
				if ok[:1] in ('y', 'Y'):
					local.mkdir(name)
					print "Subdirectory %s made" % \
						repr(name)
					common.append(name)
	lsubdirs = local.listsubdirs()
	for name in lsubdirs:
		if name not in subdirs:
			print "Local subdirectory", repr(name), "not found remotely"
	for name in common:
		print "Entering subdirectory", repr(name)
		local.cd(name)
		remote.cd(name)
		compare(local, remote, mode)
		remote.back()
		local.back()

def sendfile(local, remote, name):
	try:
		remote.create(name)
	except (IOError, os.error), msg:
		print "cannot create:", msg
		return
	
	print "sending ...",
	fl()
	
	data = open(name).read()
	
	t1 = time.time()
	
	remote._send_noreply('write', name, data)
	remote._flush()
	
	t2 = time.time()
	
	dt = t2-t1
	print len(data), "bytes in", round(dt), "seconds",
	if dt:
		print "i.e.", round(len(data)/dt), "bytes/sec",
	print

def recvfile(local, remote, name):
	ok = 0
	try:
		rv = recvfile_real(local, remote, name)
		ok = 1
		return rv
	finally:
		if not ok:
			print "*** recvfile of %r failed, deleting" % (name,)
			local.delete(name)

def recvfile_real(local, remote, name):
	try:
		local.create(name)
	except (IOError, os.error), msg:
		print "cannot create:", msg
		return
	
	print "receiving ...",
	fl()
	
	f = open(name, 'w')
	t1 = time.time()
	
	length = 4*1024
	offset = 0
	id = remote._send('read', name, offset, length)
	remote._flush()
	while 1:
		newoffset = offset + length
		newid = remote._send('read', name, newoffset, length)
		data = remote._recv(id)
		id = newid
		if not data: break
		f.seek(offset)
		f.write(data)
		offset = newoffset
	size = f.tell()
	
	t2 = time.time()
	f.close()
	
	dt = t2-t1
	print size, "bytes in", round(dt), "seconds",
	if dt:
		print "i.e.", int(size/dt), "bytes/sec",
	print
	remote._recv(id) # ignored

def fl():
	sys.stdout.flush()

if __name__ == '__main__':
	main()