1 |
dpavlin |
1.1 |
#!/bin/sh |
2 |
|
|
# pgserv.tcl |
3 |
|
|
# (c) 2000 Thomas Lockhart, PostgreSQL Inc. |
4 |
|
|
# The next line will reinvoke as wish *DO NOT REMOVE OR ALTER* \ |
5 |
|
|
exec wish "$0" "$@" |
6 |
|
|
|
7 |
|
|
puts "Starting Replication Server demo" |
8 |
|
|
|
9 |
dpavlin |
1.2 |
set RSERV_BIN "/usr/lib/postgresql/bin" |
10 |
dpavlin |
1.1 |
|
11 |
|
|
# Bring in the interfaces we will be using... |
12 |
|
|
|
13 |
|
|
#package require Pgtcl |
14 |
|
|
load libpgtcl[info sharedlibextension] |
15 |
|
|
|
16 |
|
|
# elog |
17 |
|
|
# Information or error log and exit handler |
18 |
|
|
proc {elog} {level message} { |
19 |
|
|
global show |
20 |
|
|
switch -exact -- $level { |
21 |
|
|
DEBUG { |
22 |
|
|
if {$show(debug)} { |
23 |
|
|
puts "DEBUG $message" |
24 |
|
|
} |
25 |
|
|
} |
26 |
|
|
ERROR { |
27 |
|
|
if {$show(error)} { |
28 |
|
|
puts "ERROR $message" |
29 |
|
|
} |
30 |
|
|
FATAL { |
31 |
|
|
if ($show(error)} { |
32 |
|
|
puts "FATAL $message" |
33 |
|
|
} |
34 |
|
|
exit 1 |
35 |
|
|
} |
36 |
|
|
default { |
37 |
|
|
puts "INFO $message" |
38 |
|
|
} |
39 |
|
|
} |
40 |
|
|
} |
41 |
|
|
|
42 |
|
|
proc {ShowUsage} {} { |
43 |
|
|
global argv0 |
44 |
|
|
puts "Usage: $argv0 --host name --user name --password string masterdb slavedb" |
45 |
|
|
puts "\t--masterhost name --masteruser name --masterpassword string" |
46 |
|
|
puts "\t--slavehost name --slaveuser name --slavepassword string" |
47 |
|
|
} |
48 |
|
|
|
49 |
|
|
# Initial values for database access |
50 |
|
|
# master, slave variables are tied to text input boxes, |
51 |
|
|
# and will be updated on user input |
52 |
|
|
proc {SetDbInfo} {db name {host ""} {user ""} {pass ""}} { |
53 |
|
|
global dbinfo |
54 |
|
|
set dbinfo($db,name) $name |
55 |
|
|
set dbinfo($db,host) $host |
56 |
|
|
set dbinfo($db,user) $user |
57 |
|
|
set dbinfo($db,pass) $pass |
58 |
|
|
} |
59 |
|
|
|
60 |
|
|
# ConnInfo |
61 |
|
|
# Connection information for pgtcl library |
62 |
|
|
proc {ConnInfo} {{db master}} { |
63 |
|
|
global dbinfo |
64 |
|
|
set ci "dbname=$dbinfo($db,name)" |
65 |
|
|
if {[string length $dbinfo($db,host)] > 0} { |
66 |
|
|
set ci "$ci host=$dbinfo($db,host)" |
67 |
|
|
} |
68 |
|
|
if {[string length $dbinfo($db,user)] > 0} { |
69 |
|
|
set ci "$ci user=$dbinfo($db,user)" |
70 |
|
|
} |
71 |
|
|
if {[string length $dbinfo($db,pass)] > 0} { |
72 |
|
|
set ci "$ci password=$dbinfo($db,pass)" |
73 |
|
|
} |
74 |
|
|
# puts "Construct conninfo $ci" |
75 |
|
|
return $ci |
76 |
|
|
} |
77 |
|
|
|
78 |
|
|
# ConnInfoParams |
79 |
|
|
# Connection information for (perl) callable programs |
80 |
|
|
proc {ConnInfoParams} {{db master}} { |
81 |
|
|
global dbinfo |
82 |
|
|
set ci "" |
83 |
|
|
if {[string length $dbinfo($db,host)] > 0} { |
84 |
|
|
set ci "$ci --host=$dbinfo($db,host)" |
85 |
|
|
} |
86 |
|
|
if {[string length $dbinfo($db,user)] > 0} { |
87 |
|
|
set ci "$ci --user=$dbinfo($db,user)" |
88 |
|
|
} |
89 |
|
|
if {[string length $dbinfo($db,pass)] > 0} { |
90 |
|
|
set ci "$ci --password=$dbinfo($db,pass)" |
91 |
|
|
} |
92 |
|
|
# puts "Construct conninfo $ci" |
93 |
|
|
return $ci |
94 |
|
|
} |
95 |
|
|
|
96 |
|
|
# ConnInfoMaster |
97 |
|
|
# Connection information for (perl) callable programs |
98 |
|
|
proc {ConnInfoMaster} {{db master}} { |
99 |
|
|
global dbinfo |
100 |
|
|
set ci $dbinfo($db,name) |
101 |
|
|
if {[string length $dbinfo($db,host)] > 0} { |
102 |
|
|
set ci "$ci --masterhost=$dbinfo($db,host)" |
103 |
|
|
} |
104 |
|
|
if {[string length $dbinfo($db,user)] > 0} { |
105 |
|
|
set ci "$ci --masteruser=$dbinfo($db,user)" |
106 |
|
|
} |
107 |
|
|
if {[string length $dbinfo($db,pass)] > 0} { |
108 |
|
|
set ci "$ci --masterpassword=$dbinfo($db,pass)" |
109 |
|
|
} |
110 |
|
|
# puts "Construct conninfo $ci" |
111 |
|
|
return $ci |
112 |
|
|
} |
113 |
|
|
|
114 |
|
|
# ConnInfoSlave |
115 |
|
|
# Connection information for (perl) callable programs |
116 |
|
|
proc {ConnInfoSlave} {{db slave}} { |
117 |
|
|
global dbinfo |
118 |
|
|
set ci $dbinfo($db,name) |
119 |
|
|
if {[string length $dbinfo($db,host)] > 0} { |
120 |
|
|
set ci "$ci --slavehost=$dbinfo($db,host)" |
121 |
|
|
} |
122 |
|
|
if {[string length $dbinfo($db,user)] > 0} { |
123 |
|
|
set ci "$ci --slaveuser=$dbinfo($db,user)" |
124 |
|
|
} |
125 |
|
|
if {[string length $dbinfo($db,pass)] > 0} { |
126 |
|
|
set ci "$ci --slavepassword=$dbinfo($db,pass)" |
127 |
|
|
} |
128 |
|
|
# puts "Construct conninfo $ci" |
129 |
|
|
return $ci |
130 |
|
|
} |
131 |
|
|
|
132 |
|
|
|
133 |
|
|
SetDbInfo master master localhost |
134 |
|
|
SetDbInfo slave slave localhost |
135 |
dpavlin |
1.3 |
set dbinfo(snapshot,name) ".__Snapshot" |
136 |
dpavlin |
1.1 |
|
137 |
|
|
set update "" |
138 |
|
|
|
139 |
|
|
set show(debug) 1 |
140 |
|
|
set show(error) 1 |
141 |
|
|
|
142 |
|
|
set argi 0 |
143 |
|
|
while {$argi < $argc} { |
144 |
|
|
# puts "argi is $argi; argc is $argc" |
145 |
|
|
set arg [lindex $argv $argi] |
146 |
|
|
switch -glob -- $arg { |
147 |
|
|
-h - |
148 |
|
|
--host { |
149 |
|
|
incr argi |
150 |
|
|
set dbinfo(master,host) [lindex $argv $argi] |
151 |
|
|
set dbinfo(slave,host) [lindex $argv $argi] |
152 |
|
|
} |
153 |
|
|
--masterhost { |
154 |
|
|
incr argi |
155 |
|
|
set dbinfo(master,host) [lindex $argv $argi] |
156 |
|
|
} |
157 |
|
|
--slavehost { |
158 |
|
|
incr argi |
159 |
|
|
set dbinfo(slave,host) [lindex $argv $argi] |
160 |
|
|
} |
161 |
|
|
-u - |
162 |
|
|
--user { |
163 |
|
|
incr argi |
164 |
|
|
set dbinfo(master,user) [lindex $argv $argi] |
165 |
|
|
set dbinfo(slave,user) [lindex $argv $argi] |
166 |
|
|
} |
167 |
|
|
--masteruser { |
168 |
|
|
incr argi |
169 |
|
|
set dbinfo(master,user) [lindex $argv $argi] |
170 |
|
|
} |
171 |
|
|
--slaveuser { |
172 |
|
|
incr argi |
173 |
|
|
set dbinfo(slave,user) [lindex $argv $argi] |
174 |
|
|
} |
175 |
|
|
-s - |
176 |
|
|
--snapshot { |
177 |
|
|
incr argi |
178 |
|
|
set dbinfo(snapshot,name) [lindex $argv $argi] |
179 |
|
|
} |
180 |
|
|
-* { |
181 |
|
|
elog ERROR "$argv0: invalid parameter '$arg'" |
182 |
|
|
ShowUsage |
183 |
|
|
exit 1 |
184 |
|
|
} |
185 |
|
|
default { |
186 |
|
|
break |
187 |
|
|
} |
188 |
|
|
} |
189 |
|
|
incr argi |
190 |
|
|
} |
191 |
|
|
|
192 |
|
|
if {$argi < $argc} { |
193 |
|
|
set dbinfo(master,name) [lindex $argv $argi] |
194 |
|
|
incr argi |
195 |
|
|
} |
196 |
|
|
if {$argi < $argc} { |
197 |
|
|
set dbinfo(slave,name) [lindex $argv $argi] |
198 |
|
|
incr argi |
199 |
|
|
} |
200 |
|
|
if {$argi < $argc} { |
201 |
|
|
elog "$argv0: too many parameters" |
202 |
|
|
ShowUsage |
203 |
|
|
exit 1 |
204 |
|
|
} |
205 |
|
|
|
206 |
|
|
elog DEBUG "User is $dbinfo(master,user) $dbinfo(slave,user)" |
207 |
|
|
elog DEBUG "Host is $dbinfo(master,host) $dbinfo(slave,host)" |
208 |
|
|
|
209 |
|
|
# |
210 |
|
|
# TK layout |
211 |
|
|
# |
212 |
|
|
|
213 |
|
|
wm title . "Async Replication" |
214 |
|
|
|
215 |
|
|
wm geom . 400x400 |
216 |
|
|
|
217 |
|
|
proc {CreateResultFrame} {b l w} { |
218 |
|
|
pack [frame $b -borderwidth 10] -fill x |
219 |
|
|
pack [button $b.run -text $l -command $l -width $w] -side left |
220 |
|
|
# pack [entry $b.e -textvariable NewRow] -side left |
221 |
|
|
} |
222 |
|
|
|
223 |
|
|
set t .top |
224 |
|
|
pack [frame $t -borderwidth 10] -fill x |
225 |
|
|
pack [frame $t.h -borderwidth 10] -fill x |
226 |
|
|
pack [label $t.h.h -text "PostgreSQL Async Replication Server"] |
227 |
|
|
|
228 |
|
|
set b .b |
229 |
|
|
pack [frame $b -borderwidth 10] -fill x |
230 |
|
|
pack [frame $b.l -borderwidth 10] -fill x |
231 |
|
|
pack [label $b.l.ml -text "Master"] -side left |
232 |
|
|
pack [label $b.l.sl -text "Slave"] -side right |
233 |
|
|
pack [entry $b.m -textvariable dbinfo(master,name) -width 25] -side left |
234 |
|
|
pack [entry $b.s -textvariable dbinfo(slave,name) -width 25] -side right |
235 |
|
|
|
236 |
|
|
set b .u |
237 |
|
|
pack [frame $b -borderwidth 10] -fill x |
238 |
|
|
pack [button $b.run -text update -command Update -width 10] -side left |
239 |
|
|
pack [entry $b.e -textvariable update -width 50] -side left |
240 |
|
|
|
241 |
|
|
set r [CreateResultFrame .r Replicate 10] |
242 |
|
|
|
243 |
|
|
set b .s |
244 |
|
|
pack [frame $b -borderwidth 10] -fill x |
245 |
|
|
pack [button $b.b -text Show -command Show -width 10] -side left |
246 |
|
|
pack [label $b.e -text ""] -side left |
247 |
|
|
|
248 |
|
|
set b .button |
249 |
|
|
pack [frame $b -borderwidth 10] -fill x |
250 |
|
|
|
251 |
|
|
pack [button $b.quit -text "Quit" -command Shutdown] |
252 |
|
|
|
253 |
|
|
# |
254 |
|
|
# Functions mapped to buttons |
255 |
|
|
# |
256 |
|
|
|
257 |
|
|
proc {Update} {} { |
258 |
|
|
global dbinfo |
259 |
|
|
global update |
260 |
|
|
|
261 |
|
|
elog DEBUG "Opening database [ConnInfo master]..." |
262 |
|
|
set res [catch {set db [pg_connect -conninfo "[ConnInfo master]"]} msg] |
263 |
|
|
if {$res} { |
264 |
|
|
elog ERROR "Database '$dbinfo(master,name)' is not available: $res ($msg)" |
265 |
|
|
} else { |
266 |
|
|
elog DEBUG "Insert $update into database $dbinfo(master,name)..." |
267 |
|
|
set res [pg_exec $db "insert into test select '$update', max(k)+1, max(l)+1 from test"] |
268 |
|
|
elog DEBUG [pg_result $res -status] |
269 |
|
|
catch {pg_disconnect $db} |
270 |
|
|
} |
271 |
|
|
} |
272 |
|
|
|
273 |
|
|
proc {Replicate} {} { |
274 |
|
|
global dbinfo |
275 |
|
|
global RSERV_BIN |
276 |
|
|
|
277 |
|
|
elog DEBUG "Replicating [ConnInfoCmd master]..." |
278 |
|
|
exec "$RSERV_BIN/Replicate" --snapshot=$dbinfo(snapshot,name) [ConnInfoParams] [ConnInfoMaster] [ConnInfoSlave] |
279 |
|
|
} |
280 |
|
|
|
281 |
|
|
proc {Show} {} { |
282 |
|
|
global dbinfo |
283 |
|
|
global update |
284 |
|
|
|
285 |
|
|
elog DEBUG "Opening database [ConnInfo slave]..." |
286 |
|
|
set res [catch {set db [pg_connect -conninfo "[ConnInfo slave]"]} msg] |
287 |
|
|
if {$res} { |
288 |
|
|
elog ERROR "DB $dbinfo(slave,name) not available: $res ($msg)" |
289 |
|
|
} else { |
290 |
|
|
elog DEBUG "Select $update from database $dbinfo(slave,name)..." |
291 |
|
|
set res [pg_exec $db "select i from test where i='$update'"] |
292 |
|
|
if {[pg_result $res -status] != "PGRES_TUPLES_OK"} { |
293 |
|
|
.s.e config -text "n/a" |
294 |
|
|
} else { |
295 |
|
|
set ntups [pg_result $res -numTuples] |
296 |
|
|
if {$ntups <= 0} { |
297 |
|
|
.s.e config -text "n/a" |
298 |
|
|
} else { |
299 |
|
|
for {set i 0} {$i < $ntups} {incr i} { |
300 |
|
|
set val [pg_result $res -getTuple $i] |
301 |
|
|
.s.e config -text $val |
302 |
|
|
} |
303 |
|
|
} |
304 |
|
|
pg_result $res -clear |
305 |
|
|
} |
306 |
|
|
catch {pg_disconnect $db} |
307 |
|
|
} |
308 |
|
|
} |
309 |
|
|
|
310 |
|
|
proc {Shutdown} {} { |
311 |
|
|
global dbinfo |
312 |
|
|
exit |
313 |
|
|
} |