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
|
# Copyright: 2005 Gentoo Foundation
# Author(s): Brian Harring (ferringb@gentoo.org)
# License: GPL2
# $Id$
if not hasattr(__builtins__, "set"):
from sets import Set as set
from itertools import chain
from cache import cache_errors
def mirror_cache(valid_nodes_iterable, src_cache, trg_cache, eclass_cache=None, verbose_instance=None):
if not src_cache.complete_eclass_entries and not eclass_cache:
raise Exception("eclass_cache required for cache's of class %s!" % src_cache.__class__)
if verbose_instance == None:
noise=quiet_mirroring()
else:
noise=verbose_instance
dead_nodes = set(trg_cache)
count=0
if not trg_cache.autocommits:
trg_cache.sync(100)
for x in valid_nodes_iterable:
# print "processing x=",x
count+=1
dead_nodes.discard(x)
try: entry = src_cache[x]
except KeyError, e:
noise.missing_entry(x)
del e
continue
except cache_errors.CacheError, ce:
noise.exception(x, ce)
del ce
continue
write_it = True
trg = None
try:
trg = trg_cache[x]
if long(trg["_mtime_"]) == long(entry["_mtime_"]) and \
eclass_cache.is_eclass_data_valid(trg["_eclasses_"]) and \
set(trg["_eclasses_"]) == set(entry["_eclasses_"]):
write_it = False
except (cache_errors.CacheError, KeyError):
pass
if trg and not write_it:
""" We don't want to skip the write unless we're really sure that
the existing cache is identical, so don't trust _mtime_ and
_eclasses_ alone."""
for d in (entry, trg):
if "EAPI" in d and d["EAPI"] in ("", "0"):
del d["EAPI"]
for k in set(chain(entry, trg)).difference(
("_mtime_", "_eclasses_")):
if trg.get(k, "") != entry.get(k, ""):
write_it = True
break
if write_it:
try:
inherited = entry.get("INHERITED", None)
except cache_errors.CacheError, ce:
noise.exception(x, ce)
del ce
continue
if inherited:
if src_cache.complete_eclass_entries:
if not "_eclasses_" in entry:
noise.corruption(x,"missing _eclasses_ field")
continue
if not eclass_cache.is_eclass_data_valid(entry["_eclasses_"]):
noise.eclass_stale(x)
continue
else:
entry["_eclasses_"] = eclass_cache.get_eclass_data(entry["INHERITED"].split(), \
from_master_only=True)
if not entry["_eclasses_"]:
noise.eclass_stale(x)
continue
# by this time, if it reaches here, the eclass has been validated, and the entry has
# been updated/translated (if needs be, for metadata/cache mainly)
try: trg_cache[x] = entry
except cache_errors.CacheError, ce:
noise.exception(x, ce)
del ce
continue
if count >= noise.call_update_min:
noise.update(x)
count = 0
if not trg_cache.autocommits:
trg_cache.commit()
# ok. by this time, the trg_cache is up to date, and we have a dict
# with a crapload of cpv's. we now walk the target db, removing stuff if it's in the list.
for key in dead_nodes:
try:
del trg_cache[key]
except KeyError:
pass
except cache_errors.CacheError, ce:
noise.exception(ce)
del ce
noise.finish()
class quiet_mirroring(object):
# call_update_every is used by mirror_cache to determine how often to call in.
# quiet defaults to 2^24 -1. Don't call update, 'cept once every 16 million or so :)
call_update_min = 0xffffff
def update(self,key,*arg): pass
def exception(self,key,*arg): pass
def eclass_stale(self,*arg): pass
def missing_entry(self, key): pass
def misc(self,key,*arg): pass
def corruption(self, key, s): pass
def finish(self, *arg): pass
class non_quiet_mirroring(quiet_mirroring):
call_update_min=1
def update(self,key,*arg): print "processed",key
def exception(self, key, *arg): print "exec",key,arg
def missing(self,key): print "key %s is missing", key
def corruption(self,key,*arg): print "corrupt %s:" % key,arg
def eclass_stale(self,key,*arg):print "stale %s:"%key,arg
|