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
|
#! /usr/bin/env python
"""Londiste launcher.
"""
import sys, os, optparse, skytools
# python 2.3 will try londiste.py first...
import sys, os.path
if os.path.exists(os.path.join(sys.path[0], 'londiste.py')) \
and not os.path.exists(os.path.join(sys.path[0], 'londiste')):
del sys.path[0]
from londiste import *
command_usage = """
%prog [options] INI CMD [subcmd args]
commands:
provider install installs modules, creates queue
provider add TBL ... add table to queue
provider remove TBL ... remove table from queue
provider tables show all tables linked to queue
provider seqs show all sequences on provider
subscriber install installs schema
subscriber add TBL ... add table to subscriber
subscriber remove TBL ... remove table from subscriber
subscriber tables list tables subscriber has attached to
subscriber seqs list sequences subscriber is interested
subscriber missing list tables subscriber has not yet attached to
subscriber link QUE create mirror queue
subscriber unlink dont mirror queue
replay replay events to subscriber
switchover switch the roles between provider & subscriber
compare [TBL ...] compare table contents on both sides
repair [TBL ...] repair data on subscriber
copy full copy of table, internal cmd
subscriber check compare table structure on both sides
subscriber fkeys print out fkey drop/create commands
subscriber resync TBL ... do full copy again
subscriber register attaches subscriber to queue (also done by replay)
subscriber unregister detach subscriber from queue
"""
"""switchover:
goal is to launch a replay with reverse config
- should link be required? (link should guarantee all tables/seqs same?)
- should link auto-add tables for subscriber
1. lock all tables on provider, in order specified by 'nr'
2. wait until old replay is past the point
3. sync seq
4. replace queue triggers on provider with deny triggers
5. replace deny triggers on subscriber with queue triggers
6. sync pgq tick seqs? change pgq config?
"""
class Londiste(skytools.DBScript):
def __init__(self, args):
skytools.DBScript.__init__(self, 'londiste', args)
if self.options.rewind or self.options.reset:
self.script = Replicator(args)
return
if len(self.args) < 2:
print "need command"
sys.exit(1)
cmd = self.args[1]
if cmd =="provider":
script = ProviderSetup(args)
elif cmd == "subscriber":
script = SubscriberSetup(args)
elif cmd == "replay":
method = self.cf.get('method', 'direct')
if method == 'direct':
script = Replicator(args)
elif method == 'file_write':
script = FileWrite(args)
elif method == 'file_write':
script = FileWrite(args)
else:
print "unknown method, quitting"
sys.exit(1)
elif cmd == "copy":
script = CopyTable(args)
elif cmd == "compare":
script = Comparator(args)
elif cmd == "repair":
script = Repairer(args)
elif cmd == "upgrade":
script = UpgradeV2(args)
else:
print "Unknown command '%s', use --help for help" % cmd
sys.exit(1)
self.script = script
def start(self):
self.script.start()
def init_optparse(self, parser=None):
p = skytools.DBScript.init_optparse(self, parser)
p.set_usage(command_usage.strip())
g = optparse.OptionGroup(p, "expert options")
g.add_option("--force", action="store_true",
help = "add: ignore table differences, repair: ignore lag")
g.add_option("--expect-sync", action="store_true", dest="expect_sync",
help = "add: no copy needed", default=False)
g.add_option("--skip-truncate", action="store_true", dest="skip_truncate",
help = "add: keep old data", default=False)
g.add_option("--rewind", action="store_true",
help = "replay: sync queue pos with subscriber")
g.add_option("--reset", action="store_true",
help = "replay: forget queue pos on subscriber")
p.add_option_group(g)
return p
if __name__ == '__main__':
script = Londiste(sys.argv[1:])
script.start()
|