@@ -23,62 +23,51 @@ BEGIN
23
23
END
24
24
$$;
25
25
26
- -- available commands
27
- CREATE TYPE cmd AS ENUM (' add_node' , ' rm_node' , ' create_hash_partitions' ,
28
- ' move_part' , ' create_replica' , ' rebalance' ,
29
- ' set_replevel' );
30
- -- command status
31
- CREATE TYPE cmd_status AS ENUM (' waiting' , ' canceled' , ' failed' , ' in progress' ,
32
- ' success' , ' done' );
33
-
34
26
CREATE TABLE cmd_log (
35
27
id bigserial PRIMARY KEY ,
36
- cmd_type cmd NOT NULL ,
28
+ cmd_type TEXT NOT NULL ,
37
29
cmd_opts TEXT [],
38
- status cmd_status DEFAULT ' waiting' NOT NULL
30
+ status TEXT DEFAULT ' waiting' NOT NULL ,
31
+
32
+ -- available commands
33
+ CONSTRAINT check_cmd_type
34
+ CHECK (cmd_type IN (' add_node' , ' rm_node' , ' create_hash_partitions' ,
35
+ ' move_part' , ' create_replica' , ' rebalance' ,
36
+ ' set_replevel' )),
37
+
38
+ -- command status
39
+ CONSTRAINT check_cmd_status
40
+ CHECK (status IN (' waiting' , ' canceled' , ' failed' , ' in progress' ,
41
+ ' success' , ' done' ))
39
42
);
40
43
41
- -- Notify shardlord bgw about new commands
42
- CREATE FUNCTION notify_shardlord () RETURNS trigger AS $$
43
- BEGIN
44
- NOTIFY shardman_cmd_log_update;
45
- RETURN NULL ;
46
- END
47
- $$ LANGUAGE plpgsql;
48
- CREATE TRIGGER cmd_log_inserts
49
- AFTER INSERT ON cmd_log
50
- FOR EACH STATEMENT EXECUTE PROCEDURE notify_shardlord();
51
44
52
45
-- Interface functions
53
46
47
+
54
48
-- Add a node. Its state will be reset, all shardman data lost.
55
49
CREATE FUNCTION add_node (connstring text ) RETURNS int AS $$
56
50
DECLARE
57
- c_id int ;
51
+ cmd text ;
52
+ opts text [];
58
53
BEGIN
59
- INSERT INTO @extschema@.cmd_log
60
- VALUES (DEFAULT, ' add_node' , ARRAY[connstring])
61
- RETURNING id INTO c_id;
54
+ cmd = ' add_node' ;
55
+ opts = ARRAY[connstring::text ];
62
56
63
- RETURN c_id ;
57
+ RETURN @extschema@.register_cmd(cmd, opts) ;
64
58
END
65
59
$$ LANGUAGE plpgsql;
66
60
67
61
-- Remove node. Its state will be reset, all shardman data lost.
68
- CREATE FUNCTION rm_node (node_id int , force bool default false) RETURNS int AS $$
62
+ CREATE FUNCTION rm_node (node_id int , force bool DEFAULT false) RETURNS int AS $$
69
63
DECLARE
70
- c_id int ;
64
+ cmd text ;
65
+ opts text [];
71
66
BEGIN
72
- INSERT INTO @extschema@.cmd_log
73
- VALUES (DEFAULT,
74
- ' rm_node' ,
75
- CASE force
76
- WHEN true THEN ARRAY[node_id::text , ' force' ]
77
- ELSE ARRAY[node_id::text ]
78
- END)
79
- RETURNING id INTO c_id;
80
-
81
- RETURN c_id;
67
+ cmd = ' rm_node' ;
68
+ opts = ARRAY[node_id::text , force::text ];
69
+
70
+ RETURN @extschema@.register_cmd(cmd, opts);
82
71
END
83
72
$$ LANGUAGE plpgsql;
84
73
@@ -89,79 +78,112 @@ CREATE FUNCTION create_hash_partitions(
89
78
rebalance bool DEFAULT true)
90
79
RETURNS int AS $$
91
80
DECLARE
92
- c_id int ;
81
+ cmd_id int ;
82
+ cmd text ;
83
+ opts text [];
93
84
BEGIN
94
- INSERT INTO @extschema@.cmd_log
95
- VALUES (DEFAULT,
96
- ' create_hash_partitions' ,
97
- ARRAY[node_id::text , relation, expr, partitions_count::text ])
98
- RETURNING id INTO c_id;
99
-
100
- IF rebalance THEN
101
- PERFORM shardman .rebalance (relation);
85
+ cmd = ' create_hash_partitions' ;
86
+ opts = ARRAY[node_id::text ,
87
+ relation::text ,
88
+ expr::text ,
89
+ partitions_count::text ,
90
+ rebalance::text ];
91
+
92
+ cmd_id = @extschema@.register_cmd(cmd, opts);
93
+
94
+ -- additional steps must check node's type
95
+ IF @extschema@.me_lord() AND rebalance THEN
96
+ cmd_id = @extschema@.rebalance(relation);
102
97
END IF;
103
- RETURN c_id;
98
+
99
+ -- return last command's id
100
+ RETURN cmd_id;
104
101
END
105
102
$$ LANGUAGE plpgsql;
106
103
107
104
-- Move primary or replica partition to another node. Params:
108
105
-- 'part_name' is name of the partition to move
109
- -- 'dest ' is id of the destination node
106
+ -- 'dst ' is id of the destination node
110
107
-- 'src' is id of the node with partition. If NULL, primary partition is moved.
111
- CREATE FUNCTION move_part (part_name text , dest int , src int DEFAULT NULL )
108
+ CREATE FUNCTION move_part (part_name text , dst int , src int DEFAULT NULL )
112
109
RETURNS int AS $$
113
110
DECLARE
114
- c_id int ;
111
+ cmd text ;
112
+ opts text [];
115
113
BEGIN
116
- INSERT INTO @extschema@.cmd_log
117
- VALUES (DEFAULT, ' move_part' , ARRAY[part_name, src::text , dest::text ])
118
- RETURNING id INTO c_id;
114
+ cmd = ' move_part' ;
115
+ opts = ARRAY[part_name::text , dst::text , src::text ];
119
116
120
- RETURN c_id;
121
- END $$ LANGUAGE plpgsql;
117
+ RETURN @extschema@.register_cmd(cmd, opts);
118
+ END
119
+ $$ LANGUAGE plpgsql;
122
120
123
121
-- Create replica partition. Params:
124
122
-- 'part_name' is name of the partition to replicate
125
- -- 'dest ' is id of the node on which part will be created
126
- CREATE FUNCTION create_replica (part_name text , dest int ) RETURNS int AS $$
123
+ -- 'dst ' is id of the node on which part will be created
124
+ CREATE FUNCTION create_replica (part_name text , dst int ) RETURNS int AS $$
127
125
DECLARE
128
- c_id int ;
126
+ cmd text ;
127
+ opts text [];
129
128
BEGIN
130
- INSERT INTO @extschema@.cmd_log
131
- VALUES (DEFAULT, ' create_replica' , ARRAY[part_name, dest::text ])
132
- RETURNING id INTO c_id;
129
+ cmd = ' create_replica' ;
130
+ opts = ARRAY[part_name::text , dst::text ];
133
131
134
- RETURN c_id;
135
- END $$ LANGUAGE plpgsql;
132
+ RETURN @extschema@.register_cmd(cmd, opts);
133
+ END
134
+ $$ LANGUAGE plpgsql;
136
135
137
136
-- Evenly distribute partitions of table 'relation' across all nodes.
138
137
CREATE FUNCTION rebalance (relation text ) RETURNS int AS $$
139
138
DECLARE
140
- c_id int ;
139
+ cmd text ;
140
+ opts text [];
141
141
BEGIN
142
- INSERT INTO @extschema@.cmd_log
143
- VALUES (DEFAULT, ' rebalance' , ARRAY[relation])
144
- RETURNING id INTO c_id;
142
+ cmd = ' rebalance' ;
143
+ opts = ARRAY[relation::text ];
145
144
146
- RETURN c_id;
147
- END $$ LANGUAGE plpgsql;
145
+ RETURN @extschema@.register_cmd(cmd, opts);
146
+ END
147
+ $$ LANGUAGE plpgsql;
148
148
149
149
-- Add replicas to partitions of table 'relation' until we reach replevel
150
150
-- replicas for each one. Note that it is pointless to set replevel to more than
151
151
-- number of active workers - 1. Replica deletions is not implemented yet.
152
152
CREATE FUNCTION set_replevel (relation text , replevel int ) RETURNS int AS $$
153
153
DECLARE
154
- c_id int ;
154
+ cmd text ;
155
+ opts text [];
155
156
BEGIN
156
- INSERT INTO @extschema@.cmd_log
157
- VALUES (DEFAULT, ' set_replevel' , ARRAY[relation, replevel::text ])
158
- RETURNING id INTO c_id;
157
+ cmd = ' set_replevel' ;
158
+ opts = ARRAY[relation::text , replevel::text ];
159
+
160
+ RETURN @extschema@.register_cmd(cmd, opts);
161
+ END
162
+ $$ LANGUAGE plpgsql STRICT;
159
163
160
- RETURN c_id;
161
- END $$ LANGUAGE plpgsql STRICT;
162
164
163
165
-- Internal functions
164
166
167
+
168
+ -- Register command cmd_type for execution on shardlord.
169
+ CREATE FUNCTION register_cmd (cmd_type text , cmd_opts text []) RETURNS int AS $$
170
+ DECLARE
171
+ cmd_id int ;
172
+ BEGIN
173
+ IF NOT @extschema@.me_lord() THEN
174
+ RETURN @extschema@.execute_on_lord_c(cmd_type, cmd_opts);
175
+ END IF;
176
+
177
+ INSERT INTO @extschema@.cmd_log
178
+ VALUES (DEFAULT, cmd_type, cmd_opts)
179
+ RETURNING id INTO cmd_id;
180
+
181
+ NOTIFY shardman_cmd_log_update; -- Notify bgw about the job
182
+
183
+ RETURN cmd_id;
184
+ END
185
+ $$ LANGUAGE plpgsql STRICT;
186
+
165
187
-- Called on shardlord bgw start. Add itself to nodes table, set id, create
166
188
-- publication.
167
189
CREATE FUNCTION lord_boot () RETURNS void AS $$
@@ -194,7 +216,8 @@ BEGIN
194
216
IF init_lord THEN
195
217
-- TODO: set up lr channels
196
218
END IF;
197
- END $$ LANGUAGE plpgsql;
219
+ END
220
+ $$ LANGUAGE plpgsql;
198
221
199
222
-- These tables will be replicated to worker nodes, notifying them about changes.
200
223
-- Called on lord.
@@ -255,15 +278,17 @@ CREATE FUNCTION terminate_repslot_walsender(slot_name text) RETURNS void AS $$
255
278
BEGIN
256
279
EXECUTE format(' SELECT pg_terminate_backend(active_pid) FROM
257
280
pg_replication_slots WHERE slot_name = %L' , slot_name);
258
- END $$ LANGUAGE plpgsql STRICT;
281
+ END
282
+ $$ LANGUAGE plpgsql STRICT;
259
283
260
284
-- Drop with fire repslot and publication with the same name. Useful for 1-to-1
261
285
-- pub-sub.
262
286
CREATE FUNCTION drop_repslot_and_pub (pub name) RETURNS void AS $$
263
287
BEGIN
264
288
EXECUTE format(' DROP PUBLICATION IF EXISTS %I' , pub);
265
289
PERFORM shardman .drop_repslot (pub, true);
266
- END $$ LANGUAGE plpgsql STRICT;
290
+ END
291
+ $$ LANGUAGE plpgsql STRICT;
267
292
268
293
-- If sub exists, disable it, detach repslot from it and possibly drop. We
269
294
-- manage repslots ourselves, so it is essential to detach rs before dropping
@@ -283,7 +308,8 @@ BEGIN
283
308
EXECUTE format(' DROP SUBSCRIPTION %I' , subname);
284
309
END IF;
285
310
END IF;
286
- END $$ LANGUAGE plpgsql STRICT;
311
+ END
312
+ $$ LANGUAGE plpgsql STRICT;
287
313
288
314
-- Remove all our logical replication stuff in case of drop extension.
289
315
-- Dropping extension cleanup is not that easy:
@@ -337,3 +363,7 @@ CREATE EVENT TRIGGER cleanup_lr_trigger ON ddl_command_start
337
363
338
364
CREATE FUNCTION alter_system_c (opt text , val text ) RETURNS void
339
365
AS ' pg_shardman' LANGUAGE C STRICT;
366
+
367
+ -- Ask shardlord to perform a command if we're but a worker node.
368
+ CREATE FUNCTION execute_on_lord_c (cmd_type text , cmd_opts text []) RETURNS text
369
+ AS ' pg_shardman' LANGUAGE C STRICT;
0 commit comments