summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Kreen2008-04-25 14:48:32 +0000
committerMarko Kreen2008-04-25 14:48:32 +0000
commit7ad93d5ca136a10c970a38837641b5789f3f8033 (patch)
tree93c4be1e4089e99c7cb735b40918f6c369b04aa3
parenta6bc0ffa2c37b9e43a5bca7b4003313ce1875ad3 (diff)
pgq_set: pause/resume/change-provider/rename-node work now
-rwxr-xr-xpython/londiste.py14
-rw-r--r--python/londiste/setup.py10
-rw-r--r--python/pgq/setadmin.py262
-rw-r--r--python/pgq/setconsumer.py13
-rw-r--r--python/pgq/setinfo.py63
-rw-r--r--python/skytools/adminscript.py82
-rw-r--r--sql/londiste/expected/londiste_fkeys.out12
-rw-r--r--sql/londiste/expected/londiste_provider.out10
-rw-r--r--sql/londiste/expected/londiste_subscriber.out12
-rw-r--r--sql/londiste/functions/londiste.node_add_table.sql22
-rw-r--r--sql/londiste/functions/londiste.node_disable_triggers.sql10
-rw-r--r--sql/londiste/functions/londiste.node_prepare_triggers.sql8
-rw-r--r--sql/londiste/functions/londiste.node_refresh_triggers.sql14
-rw-r--r--sql/londiste/functions/londiste.node_remove_seq.sql6
-rw-r--r--sql/londiste/functions/londiste.node_remove_table.sql10
-rw-r--r--sql/londiste/functions/londiste.set_add_table.sql8
-rw-r--r--sql/londiste/functions/londiste.set_remove_table.sql6
-rw-r--r--sql/pgq_set/expected/pgq_set.out46
-rw-r--r--sql/pgq_set/functions/pgq_set.add_member.sql16
-rw-r--r--sql/pgq_set/functions/pgq_set.change_provider.sql30
-rw-r--r--sql/pgq_set/functions/pgq_set.create_node.sql14
-rw-r--r--sql/pgq_set/functions/pgq_set.drop_member.sql59
-rw-r--r--sql/pgq_set/functions/pgq_set.get_node_info.sql18
-rw-r--r--sql/pgq_set/functions/pgq_set.rename_node.sql190
-rw-r--r--sql/pgq_set/functions/pgq_set.set_node_paused.sql46
-rw-r--r--sql/pgq_set/functions/pgq_set.set_node_uptodate.sql2
-rw-r--r--sql/pgq_set/functions/pgq_set.subscribe_node.sql55
-rw-r--r--sql/pgq_set/sql/pgq_set.sql7
-rw-r--r--sql/pgq_set/structure/functions.sql4
-rw-r--r--sql/pgq_set/structure/pgq_set.sql14
-rwxr-xr-xtests/londiste/gendb.sh4
31 files changed, 847 insertions, 220 deletions
diff --git a/python/londiste.py b/python/londiste.py
index 06ec17db..e7e4f95e 100755
--- a/python/londiste.py
+++ b/python/londiste.py
@@ -25,13 +25,18 @@ Node Initialization:
fetching, later actual provider's connect string is used.
Node Administration:
+ status Show set state
members Show members in set
+ rename-node OLD NEW Rename a node
+ change-provider NODE NEWSRC
+ pause NODE
+ resume NODE
+
+ switchover NEWROOT
+ failover NEWROOT
tag-dead NODE .. Tag node as dead
tag-alive NODE .. Tag node as alive
- redirect Switch provider
- make-root Promote to root
-
Replication Daemon:
worker replay events to subscriber
@@ -57,7 +62,8 @@ Internal Commands:
cmd_handlers = (
(('init-root', 'init-branch', 'init-leaf', 'members', 'tag-dead', 'tag-alive',
- 'redirect', 'promote-root', 'status'), londiste.LondisteSetup),
+ 'change-provider', 'rename-node', 'status', 'pause', 'resume',
+ 'switchover', 'failover'), londiste.LondisteSetup),
(('add', 'remove', 'add-seq', 'remove-seq', 'tables', 'seqs',
'missing', 'resync', 'check', 'fkeys'), londiste.LondisteSetup),
(('worker', 'replay'), londiste.Replicator),
diff --git a/python/londiste/setup.py b/python/londiste/setup.py
index 7ab6093d..31394e8d 100644
--- a/python/londiste/setup.py
+++ b/python/londiste/setup.py
@@ -45,27 +45,27 @@ class LondisteSetup(pgq.setadmin.SetAdmin):
def cmd_add(self, args = []):
q = "select * from londiste.node_add_table(%s, %s)"
db = self.get_database('node_db')
- self.db_cmd_many(db, q, [self.set_name], args)
+ self.exec_cmd_many(db, q, [self.set_name], args)
def cmd_remove(self, args = []):
q = "select * from londiste.node_remove_table(%s, %s)"
db = self.get_database('node_db')
- self.db_cmd_many(db, q, [self.set_name], args)
+ self.exec_cmd_many(db, q, [self.set_name], args)
def cmd_add_seq(self, args = []):
q = "select * from londiste.node_add_seq(%s, %s)"
db = self.get_database('node_db')
- self.db_cmd_many(db, q, [self.set_name], args)
+ self.exec_cmd_many(db, q, [self.set_name], args)
def cmd_remove_seq(self, args = []):
q = "select * from londiste.node_remove_seq(%s, %s)"
db = self.get_database('node_db')
- self.db_cmd_many(db, q, [self.set_name], args)
+ self.exec_cmd_many(db, q, [self.set_name], args)
def cmd_resync(self, args = []):
q = "select * from londiste.node_resync_table(%s, %s)"
db = self.get_database('node_db')
- self.db_cmd_many(db, q, [self.set_name], args)
+ self.exec_cmd_many(db, q, [self.set_name], args)
def cmd_tables(self, args = []):
q = "select table_name, merge_state from londiste.node_get_table_list(%s)"
diff --git a/python/pgq/setadmin.py b/python/pgq/setadmin.py
index 7dba1959..4f33794a 100644
--- a/python/pgq/setadmin.py
+++ b/python/pgq/setadmin.py
@@ -1,6 +1,6 @@
#! /usr/bin/env python
-import sys, optparse, skytools
+import sys, time, optparse, skytools
from pgq.setinfo import *
@@ -13,9 +13,6 @@ commands:
"""
class SetAdmin(skytools.AdminScript):
- root_name = None
- root_info = None
- member_map = {}
set_name = None
extra_objs = []
initial_db_name = 'node_db'
@@ -36,6 +33,10 @@ class SetAdmin(skytools.AdminScript):
skytools.AdminScript.reload(self)
self.set_name = self.cf.get('set_name')
+ #
+ # Node initialization.
+ #
+
def cmd_init_root(self, args):
if len(args) != 2:
raise Exception('init-root needs 2 args')
@@ -74,9 +75,9 @@ class SetAdmin(skytools.AdminScript):
global_watermark = None
combined_set = None
provider_name = None
- self.exec_sql(db, "select pgq_set.add_member(%s, %s, %s, false)",
+ self.exec_cmd(db, "select * from pgq_set.add_member(%s, %s, %s, false)",
[self.set_name, node_name, node_location])
- self.exec_sql(db, "select pgq_set.create_node(%s, %s, %s, %s, %s, %s)",
+ self.exec_cmd(db, "select * from pgq_set.create_node(%s, %s, %s, %s, %s, %s)",
[self.set_name, node_type, node_name, provider_name, global_watermark, combined_set])
provider_db = None
else:
@@ -88,22 +89,19 @@ class SetAdmin(skytools.AdminScript):
self.log.error("Node '%s' already exists" % node_name)
sys.exit(1)
- global_watermark = set.global_watermark
combined_set = None
provider_db = self.get_database('provider_db', connstr = provider_loc)
- curs = provider_db.cursor()
- curs.execute("select node_type, node_name from pgq_set.get_node_info(%s)", [self.set_name])
- provider_db.commit()
- row = curs.fetchone()
- if not row:
+ q = "select node_type, node_name from pgq_set.get_node_info(%s)"
+ res = self.exec_query(provider_db, q, [self.set_name])
+ row = res[0]
+ if not row['node_name']:
raise Exception("provider node not found")
provider_name = row['node_name']
# register member on root
- self.exec_sql(root_db, "select pgq_set.add_member(%s, %s, %s, false)",
+ self.exec_cmd(root_db, "select * from pgq_set.add_member(%s, %s, %s, false)",
[self.set_name, node_name, node_location])
- root_db.commit()
# lookup provider
provider = set.get_member(provider_name)
@@ -112,21 +110,26 @@ class SetAdmin(skytools.AdminScript):
sys.exit(1)
# register on provider
- self.exec_sql(provider_db, "select pgq_set.add_member(%s, %s, %s, false)",
+ self.exec_cmd(provider_db, "select * from pgq_set.add_member(%s, %s, %s, false)",
[self.set_name, node_name, node_location])
- self.exec_sql(provider_db, "select pgq_set.subscribe_node(%s, %s)",
- [self.set_name, node_name])
- provider_db.commit()
+ rows = self.exec_cmd(provider_db, "select * from pgq_set.subscribe_node(%s, %s)",
+ [self.set_name, node_name])
+ global_watermark = rows[0]['global_watermark']
# initialize node itself
- self.exec_sql(db, "select pgq_set.add_member(%s, %s, %s, false)",
+
+ # insert members
+ self.exec_cmd(db, "select * from pgq_set.add_member(%s, %s, %s, false)",
[self.set_name, node_name, node_location])
- self.exec_sql(db, "select pgq_set.add_member(%s, %s, %s, false)",
- [self.set_name, provider_name, provider.location])
- self.exec_sql(db, "select pgq_set.create_node(%s, %s, %s, %s, %s, %s)",
+ for m in set.member_map.values():
+ self.exec_cmd(db, "select * from pgq_set.add_member(%s, %s, %s, %s)",
+ [self.set_name, m.name, m.location, m.dead])
+
+ # real init
+ self.exec_cmd(db, "select * from pgq_set.create_node(%s, %s, %s, %s, %s, %s)",
[self.set_name, node_type, node_name, provider_name,
global_watermark, combined_set])
- db.commit()
+
self.extra_init(node_type, db, provider_db)
@@ -145,11 +148,6 @@ class SetAdmin(skytools.AdminScript):
db = self.get_database('root_db', connstr = loc)
- if 1:
- curs = db.cursor()
- curs.execute("select current_database()")
- n = curs.fetchone()[0]
- self.log.debug("real dbname=%s" % n)
# query current status
res = self.exec_query(db, "select * from pgq_set.get_node_info(%s)", [self.set_name])
info = res[0]
@@ -169,20 +167,9 @@ class SetAdmin(skytools.AdminScript):
raise Exception("find_root_db: got loop: %s" % loc)
loc = info['provider_location']
if loc is None:
- self.log.info("Sub node provider not initialized?")
+ self.log.error("Sub node provider not initialized?")
sys.exit(1)
- def load_set_info(self, db):
- res = self.exec_query(db, "select * from pgq_set.get_node_info(%s)", [self.set_name])
- info = res[0]
-
- q = "select * from pgq_set.get_member_info(%s)"
- member_list = self.exec_query(db, q, [self.set_name])
-
- db.commit()
-
- return SetInfo(self.set_name, info, member_list)
-
def install_code(self, db):
objs = [
skytools.DBLanguage("plpgsql"),
@@ -195,6 +182,10 @@ class SetAdmin(skytools.AdminScript):
skytools.db_install(db.cursor(), objs, self.log)
db.commit()
+ #
+ # Print status of whole set.
+ #
+
def cmd_status(self, args):
root_db = self.find_root_db()
sinf = self.load_set_info(root_db)
@@ -214,17 +205,80 @@ class SetAdmin(skytools.AdminScript):
def load_extra_status(self, curs, node):
pass
- def cmd_switch(self, node_name, new_provider):
+ #
+ # Normal commands.
+ #
+
+ def cmd_change_provider(self, args):
+ node_name = args[0]
+ new_provider = args[1]
+ old_provider = None
+
+ self.load_local_info()
+ node_location = self.set_info.get_member(node_name).location
node_db = self.get_node_database(node_name)
- new_provider_db = self.get_node_database(new_provider)
- node_info = self.load_set_info(node_db)
+ node_set_info = self.load_set_info(node_db)
+ node = node_set_info.local_node
+ old_provider = node.provider_node
- #
- [['node', 'PAUSE']]
- [['new_parent', 'select * from pgq_set.subscribe_node(%(set_name)s, %(node_name)s, %(node_pos)s)']]
- [['node', 'select * from pgq_set.change_provider(%(set_name)s, %(new_provider)s)']]
- [['old_parent', 'select * from pgq_set.unsubscribe_node(%(set_name)s, %(node_name)s, %(node_pos)s)']]
- [['node', 'RESUME']]
+ if old_provider == new_provider:
+ self.log.info("Node %s has already %s as provider" % (node_name, new_provider))
+
+ # pause target node
+ self.pause_node(node_name)
+
+ # reload node info
+ node_set_info = self.load_set_info(node_db)
+ node = node_set_info.local_node
+
+ # subscribe on new provider
+ q = "select * from pgq_set.add_member(%s, %s, %s, false)"
+ self.node_cmd(new_provider, q, [self.set_name, node_name, node_location])
+ q = 'select * from pgq_set.subscribe_node(%s, %s, %s)'
+ self.node_cmd(new_provider, q, [self.set_name, node_name, node.completed_tick])
+
+ # change provider on node
+ q = 'select * from pgq_set.change_provider(%s, %s)'
+ self.node_cmd(node_name, q, [self.set_name, new_provider])
+
+ # unsubscribe from old provider
+ q = "select * from pgq_set.unsubscribe_node(%s, %s)"
+ self.node_cmd(old_provider, q, [self.set_name, node_name])
+
+ # resume node
+ self.resume_node(node_name)
+
+ def cmd_rename_node(self, args):
+ old_name = args[0]
+ new_name = args[1]
+
+ self.load_local_info()
+
+ root_db = self.find_root_db()
+
+ # pause target node
+ self.pause_node(old_name)
+ node = self.load_node_info(old_name)
+ provider_node = node.provider_node
+
+
+ # create copy of member info / subscriber+queue info
+ step1 = 'select * from pgq_set.rename_node_step1(%s, %s, %s)'
+ # rename node itself, drop copies
+ step2 = 'select * from pgq_set.rename_node_step2(%s, %s, %s)'
+
+ # step1
+ self.exec_cmd(root_db, step1, [self.set_name, old_name, new_name])
+ self.node_cmd(provider_node, step1, [self.set_name, old_name, new_name])
+ self.node_cmd(old_name, step1, [self.set_name, old_name, new_name])
+
+ # step1
+ self.node_cmd(old_name, step2, [self.set_name, old_name, new_name])
+ self.node_cmd(provider_node, step1, [self.set_name, old_name, new_name])
+ self.exec_cmd(root_db, step2, [self.set_name, old_name, new_name])
+
+ # resume node
+ self.resume_node(old_name)
def cmd_promote(self):
old_root = 'foo'
@@ -243,27 +297,111 @@ class SetAdmin(skytools.AdminScript):
[['old_parent', 'select * from pgq_set.unsubscribe_node(%(set_name)s, %(node_name)s, %(node_pos)s)']]
[['node', 'RESUME']]
+ def cmd_pause(self, args):
+ self.load_local_info()
+ self.pause_node(args[0])
+
+ def cmd_resume(self, args):
+ self.load_local_info()
+ self.resume_node(args[0])
+
+ def cmd_members(self, args):
+ db = self.get_database(self.initial_db_name)
+ q = "select node_name from pgq_set.get_node_info(%s)"
+ rows = self.exec_query(db, q, [self.set_name])
+
+ desc = 'Member info on %s:' % rows[0]['node_name']
+ q = "select node_name, dead, node_location"\
+ " from pgq_set.get_member_info(%s) order by 1"
+ self.display_table(db, desc, q, [self.set_name])
+
+ #
+ # Shortcuts for operating on nodes.
+ #
+
+ def load_local_info(self):
+ """fetch set info from local node."""
+ db = self.get_database(self.initial_db_name)
+ self.set_info = self.load_set_info(db)
+
+ def get_node_database(self, node_name):
+ """Connect to node."""
+ if node_name == self.set_info.local_node.name:
+ db = self.get_database(self.initial_db_name)
+ else:
+ m = self.set_info.get_member(node_name)
+ if not m:
+ self.log.error("cannot resolve %s" % node_name)
+ sys.exit(1)
+ loc = m.location
+ db = self.get_database('node.' + node_name, connstr = loc)
+ return db
+
+ def close_node_database(self, node_name):
+ """Disconnect node's connection."""
+ if node_name == self.set_info.local_node.name:
+ self.close_database(self.initial_db_name)
+ else:
+ self.close_database("node." + node_name)
+
+ def node_cmd(self, node_name, sql, args):
+ """Execute SQL command on particular node."""
+ db = self.get_node_database(node_name)
+ return self.exec_cmd(db, sql, args)
+
+ #
+ # Various operation on nodes.
+ #
+
+ def set_paused(self, db, pause_flag):
+ q = "select * from pgq_set.set_node_paused(%s, %s)"
+ self.exec_cmd(db, q, [self.set_name, pause_flag])
+
+ self.log.info('Waiting for worker to accept')
+ while 1:
+ q = "select * from pgq_set.get_node_info(%s)"
+ stat = self.exec_query(db, q, [self.set_name])[0]
+ if stat['paused'] != pause_flag:
+ raise Exception('operation canceled? %s <> %s' % (repr(stat['paused']), repr(pause_flag)))
+
+ if stat['uptodate']:
+ break
+ time.sleep(1)
+
+ op = pause_flag and "paused" or "resumed"
+
+ self.log.info("Node %s %s" % (stat['node_name'], op))
+
+ def pause_node(self, node_name):
+ db = self.get_node_database(node_name)
+ self.set_paused(db, True)
+
+ def resume_node(self, node_name):
+ db = self.get_node_database(node_name)
+ self.set_paused(db, False)
+
def subscribe_node(self, target_node, subscriber_node, tick_pos):
q = "select * from pgq_set.subscribe_node(%s, %s, %s)"
- self.node_exec(target_node, q, [self.set_name, target_node, tick_pos])
+ self.node_cmd(target_node, q, [self.set_name, target_node, tick_pos])
def unsubscribe_node(self, target_node, subscriber_node, tick_pos):
q = "select * from pgq_set.subscribe_node(%s, %s, %s)"
- self.node_exec(target_node, q, [self.set_name, target_node, tick_pos])
+ self.node_cmd(target_node, q, [self.set_name, target_node, tick_pos])
- def node_cmd(self, node_name, sql, args, commit = True):
- m = self.lookup_member(node_name)
- db = self.get_database('node_'+node_name)
- self.db_cmd(db, sql, args, commit = commit)
+ def load_node_info(self, node_name):
+ db = self.get_node_database(node_name)
+ q = "select * from pgq_set.get_node_info(%s)"
+ rows = self.exec_query(db, q, [self.set_name])
+ return NodeInfo(self.set_name, rows[0])
- def connect_node(self, node_name):
- sinf = self.get_set_info()
- m = sinf.get_member(node_name)
- loc = m.node_location
- db = self.get_database("node." + node_name, connstr = loc)
+ def load_set_info(self, db):
+ res = self.exec_query(db, "select * from pgq_set.get_node_info(%s)", [self.set_name])
+ info = res[0]
- def disconnect_node(self, node_name):
- self.close_database("node." + node_name)
+ q = "select * from pgq_set.get_member_info(%s)"
+ member_list = self.exec_query(db, q, [self.set_name])
+
+ return SetInfo(self.set_name, info, member_list)
if __name__ == '__main__':
script = SetAdmin('set_admin', sys.argv[1:])
diff --git a/python/pgq/setconsumer.py b/python/pgq/setconsumer.py
index baa18b28..4ec754e7 100644
--- a/python/pgq/setconsumer.py
+++ b/python/pgq/setconsumer.py
@@ -28,7 +28,7 @@ class SetConsumer(skytools.DBScript):
dst_node = self.load_node_info(dst_db)
if self.main_worker:
self.consumer_name = dst_node.name
- if not dst_node.up_to_date:
+ if not dst_node.uptodate:
self.tag_node_uptodate(dst_db)
if dst_node.paused:
@@ -108,7 +108,7 @@ class SetConsumer(skytools.DBScript):
def process_set_event(self, dst_curs, ev):
if ev.type == 'set-tick':
self.handle_set_tick(dst_curs, ev)
- elif ev.type == 'set-member-info':
+ elif ev.type == 'member-info':
self.handle_member_info(dst_curs, ev)
elif ev.type == 'global-watermark':
self.handle_global_watermark(dst_curs, ev)
@@ -133,11 +133,10 @@ class SetConsumer(skytools.DBScript):
dst_curs.execute(q, [self.set_name, set_name, tick_id])
def handle_member_info(self, dst_curs, ev):
- data = skytools.db_urldecode(ev.data)
- set_name = data['set_name']
- node_name = data['node_name']
- node_location = data['node_location']
- dead = data['dead']
+ node_name = ev.ev_data
+ set_name = ev.ev_extra1
+ node_location = ev.ev_extra2
+ dead = ev.ev_extra3
# this can also be member for part set, ignore then
if set_name != self.set_name:
return
diff --git a/python/pgq/setinfo.py b/python/pgq/setinfo.py
index da2e1ba9..17ff781c 100644
--- a/python/pgq/setinfo.py
+++ b/python/pgq/setinfo.py
@@ -1,11 +1,10 @@
#! /usr/bin/env python
-import skytools
-
__all__ = ['MemberInfo', 'NodeInfo', 'SetInfo',
'ROOT', 'BRANCH', 'LEAF', 'COMBINED_ROOT',
'COMBINED_BRANCH', 'MERGE_LEAF']
+# node types
ROOT = 'root'
BRANCH = 'branch'
LEAF = 'leaf'
@@ -13,6 +12,7 @@ COMBINED_ROOT = 'combined-root'
COMBINED_BRANCH = 'combined-branch'
MERGE_LEAF = 'merge-leaf'
+# which nodes need to do what actions
action_map = {
'process-batch': {'root':0, 'branch':1, 'leaf':1, 'combined-root':0, 'combined-branch':1, 'merge-leaf-to-root':1, 'merge-leaf-to-branch':1},
'process-events': {'root':0, 'branch':1, 'leaf':1, 'combined-root':0, 'combined-branch':1, 'merge-leaf-to-root':1, 'merge-leaf-to-branch':0},
@@ -46,7 +46,7 @@ class NodeInfo:
self.provider_location = row['provider_location']
self.paused = row['paused']
self.resync = row['resync']
- self.up_to_date = row['up_to_date']
+ self.uptodate = row['uptodate']
self.combined_set = row['combined_set']
self.combined_type = row['combined_type']
self.combined_queue = row['combined_queue']
@@ -56,15 +56,18 @@ class NodeInfo:
self._info_lines = []
def need_action(self, action_name):
+ """Returns True if worker for this node needs
+ to do specified action.
+ """
if not self.main_worker:
return action_name in ('process-batch', 'process-events')
typ = self.type
- if type == 'merge-leaf':
- if self.target_type == 'combined-branch':
- typ += "merge-leaf-to-branch"
- elif self.target_type == 'combined-root':
- typ += "merge-leaf-to-root"
+ if type == MERGE_LEAF:
+ if self.target_type == COMBINED_BRANCH:
+ typ = "merge-leaf-to-branch"
+ elif self.target_type == COMBINED_ROOT:
+ typ = "merge-leaf-to-root"
else:
raise Exception('bad target type')
@@ -94,7 +97,12 @@ class NodeInfo:
lag = root_time - tick_time
else:
lag = self.queue_info['ticker_lag']
- lst.append("lag: %s" % lag)
+ txt = "lag: %s" % lag
+ if self.paused:
+ txt += ", PAUSED"
+ if not self.uptodate:
+ txt += ", NOT UPTODATE"
+ lst.append(txt)
return lst
def add_info_line(self, ln):
@@ -119,13 +127,11 @@ class NodeInfo:
class SetInfo:
def __init__(self, set_name, info_row, member_rows):
- self.root_info = info_row
+ self.local_node = NodeInfo(set_name, info_row)
self.set_name = set_name
self.member_map = {}
self.node_map = {}
- self.root_name = info_row['node_name']
- self.root_type = info_row['node_type']
- self.global_watermark = info_row['global_watermark']
+ self.add_node(self.local_node)
for r in member_rows:
n = MemberInfo(r)
@@ -137,22 +143,23 @@ class SetInfo:
def get_node(self, name):
return self.node_map.get(name)
- def get_root_node(self):
- return self.get_node(self.root_name)
-
def add_node(self, node):
self.node_map[node.name] = node
_DATAFMT = "%-30s%s"
def print_tree(self):
- self._prepare_tree()
- root = self.get_root_node()
+ """Print ascii-tree for set.
+ Expects that data for all nodes is filled in."""
+
+ root = self._prepare_tree()
self._tree_calc(root)
datalines = self._print_node(root, '', [])
for ln in datalines:
print self._DATAFMT % (' ', ln)
def _print_node(self, node, pfx, datalines):
+ # print a tree fragment for node and info
+ # returns list of unprinted data rows
for ln in datalines:
print self._DATAFMT % (_setpfx(pfx, '|'), ln)
datalines = node.get_infolines()
@@ -160,16 +167,20 @@ class SetInfo:
for i, n in enumerate(node.child_list):
sfx = ((i < len(node.child_list) - 1) and ' |' or ' ')
- tmppfx = pfx + sfx
- datalines = self._print_node(n, tmppfx, datalines)
+ datalines = self._print_node(n, pfx + sfx, datalines)
return datalines
def _prepare_tree(self):
+ # reset vars, fill parent and child_list for each node
+ # returns root
+ root = None
for node in self.node_map.itervalues():
node.total_childs = 0
node.levels = 0
node.child_list = []
+ if node.type in (ROOT, COMBINED_ROOT):
+ root = node
for node in self.node_map.itervalues():
if node.provider_node:
p = self.node_map[node.provider_node]
@@ -178,7 +189,13 @@ class SetInfo:
else:
node.parent = None
+ if root is None:
+ raise Exception("root nod enot found")
+ return root
+
def _tree_calc(self, node):
+ # calculate levels and count total childs
+ # sort the tree based on them
total = len(node.child_list)
levels = 1
for subnode in node.child_list:
@@ -199,7 +216,7 @@ def _setpfx(pfx, sfx):
def _cmp_node(n1, n2):
# returns neg if n1 smaller
cmp = n1.levels - n2.levels
- if cmp:
- return cmp
- return n1.total_childs - n2.total_childs
+ if cmp == 0:
+ cmp = n1.total_childs - n2.total_childs
+ return cmp
diff --git a/python/skytools/adminscript.py b/python/skytools/adminscript.py
index 15aa13e7..838b990f 100644
--- a/python/skytools/adminscript.py
+++ b/python/skytools/adminscript.py
@@ -3,9 +3,10 @@
"""Admin scripting.
"""
-import sys, os, skytools
+import sys, os
from skytools.scripting import DBScript
+from skytools.quoting import quote_statement
__all__ = ['AdminScript']
@@ -28,20 +29,25 @@ class AdminScript(DBScript):
self.log.error('bad subcommand, see --help for usage')
sys.exit(1)
- def fetch_list(self, curs, sql, args, keycol = None):
+ def fetch_list(self, db, sql, args, keycol = None):
+ curs = db.cursor()
curs.execute(sql, args)
- rows = curs.dictfetchall()
+ rows = curs.fetchall()
+ db.commit()
if not keycol:
res = rows
else:
res = [r[keycol] for r in rows]
return res
- def display_table(self, desc, curs, sql, args = [], fields = []):
+ def display_table(self, db, desc, sql, args = [], fields = []):
"""Display multirow query as a table."""
+ self.log.debug("display_table: %s" % quote_statement(sql, args))
+ curs = db.cursor()
curs.execute(sql, args)
rows = curs.fetchall()
+ db.commit()
if len(rows) == 0:
return 0
@@ -67,70 +73,80 @@ class AdminScript(DBScript):
print '\n'
return 1
- def db_display_table(self, db, desc, sql, args = [], fields = []):
- curs = db.cursor()
- res = self.display_table(desc, curs, sql, args, fields)
- db.commit()
- return res
-
- def exec_checked(self, curs, sql, args):
+ def _exec_cmd(self, curs, sql, args):
+ self.log.debug("exec_cmd: %s" % quote_statement(sql, args))
curs.execute(sql, args)
ok = True
- for row in curs.fetchall():
- level = row['ret_code'] / 100
+ rows = curs.fetchall()
+ for row in rows:
+ try:
+ code = row['ret_code']
+ msg = row['ret_note']
+ except KeyError:
+ self.log.error("Query does not conform to exec_cmd API:")
+ self.log.error("SQL: %s" % quote_statement(sql, args))
+ self.log.error("Row: %s" % repr(row.copy()))
+ sys.exit(1)
+ level = code / 100
if level == 1:
- self.log.debug("%d %s" % (row[0], row[1]))
+ self.log.debug("%d %s" % (code, msg))
elif level == 2:
- self.log.info("%d %s" % (row[0], row[1]))
+ self.log.info("%d %s" % (code, msg))
elif level == 3:
- self.log.warning("%d %s" % (row[0], row[1]))
+ self.log.warning("%d %s" % (code, msg))
else:
- self.log.error("%d %s" % (row[0], row[1]))
+ self.log.error("%d %s" % (code, msg))
+ self.log.error("Query was: %s" % skytools.quote_statement(sql, args))
ok = False
- return ok
+ return (ok, rows)
- def exec_many(self, curs, sql, baseargs, extra_list):
+ def _exec_cmd_many(self, curs, sql, baseargs, extra_list):
ok = True
+ rows = []
for a in extra_list:
- tmp = self.exec_checked(curs, sql, baseargs + [a])
- ok = tmp and ok
- return ok
+ (tmp_ok, tmp_rows) = self._exec_cmd(curs, sql, baseargs + [a])
+ ok = tmp_ok and ok
+ rows += tmp_rows
+ return (ok, rows)
- def db_cmd(self, db, q, args, commit = True):
- ok = self.exec_checked(db.cursor(), q, args)
+ def exec_cmd(self, db, q, args, commit = True):
+ (ok, rows) = self._exec_cmd(db.cursor(), q, args)
if ok:
if commit:
self.log.info("COMMIT")
db.commit()
+ return rows
else:
self.log.info("ROLLBACK")
db.rollback()
raise EXception("rollback")
- def db_cmd_many(self, db, sql, baseargs, extra_list, commit = True):
+ def exec_cmd_many(self, db, sql, baseargs, extra_list, commit = True):
curs = db.cursor()
- ok = self.exec_many(curs, sql, baseargs, extra_list)
+ (ok, rows) = self._exec_cmd_many(curs, sql, baseargs, extra_list)
if ok:
if commit:
self.log.info("COMMIT")
db.commit()
+ return rows
else:
self.log.info("ROLLBACK")
db.rollback()
+ raise EXception("rollback")
- def exec_sql(self, db, q, args):
- self.log.debug(q)
+ def exec_stmt(self, db, sql, args):
+ self.log.debug("exec_stmt: %s" % quote_statement(sql, args))
curs = db.cursor()
- curs.execute(q, args)
+ curs.execute(sql, args)
db.commit()
- def exec_query(self, db, q, args):
- self.log.debug(q)
+ def exec_query(self, db, sql, args):
+ self.log.debug("exec_query: %s" % quote_statement(sql, args))
curs = db.cursor()
- curs.execute(q, args)
- res = curs.dictfetchall()
+ curs.execute(sql, args)
+ res = curs.fetchall()
db.commit()
return res
diff --git a/sql/londiste/expected/londiste_fkeys.out b/sql/londiste/expected/londiste_fkeys.out
index 5c2a0cfb..ed220cc8 100644
--- a/sql/londiste/expected/londiste_fkeys.out
+++ b/sql/londiste/expected/londiste_fkeys.out
@@ -17,37 +17,37 @@ create table ref_3 (
);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "ref_3_pkey" for table "ref_3"
select * from londiste.set_add_table('branch_set', 'public.ref_1');
- ret_code | ret_desc
+ ret_code | ret_note
----------+----------
200 | OK
(1 row)
select * from londiste.set_add_table('branch_set', 'public.ref_2');
- ret_code | ret_desc
+ ret_code | ret_note
----------+----------
200 | OK
(1 row)
select * from londiste.set_add_table('branch_set', 'public.ref_3');
- ret_code | ret_desc
+ ret_code | ret_note
----------+----------
200 | OK
(1 row)
select * from londiste.node_add_table('branch_set', 'public.ref_1');
- ret_code | ret_desc
+ ret_code | ret_note
----------+---------------------------
200 | Table added: public.ref_1
(1 row)
select * from londiste.node_add_table('branch_set', 'public.ref_2');
- ret_code | ret_desc
+ ret_code | ret_note
----------+---------------------------
200 | Table added: public.ref_2
(1 row)
select * from londiste.node_add_table('branch_set', 'public.ref_3');
- ret_code | ret_desc
+ ret_code | ret_note
----------+---------------------------
200 | Table added: public.ref_3
(1 row)
diff --git a/sql/londiste/expected/londiste_provider.out b/sql/londiste/expected/londiste_provider.out
index 52f12e88..bfa0d4a4 100644
--- a/sql/londiste/expected/londiste_provider.out
+++ b/sql/londiste/expected/londiste_provider.out
@@ -24,19 +24,19 @@ select * from pgq_set.add_member('aset', 'rnode', 'dbname=db', false);
(1 row)
select * from pgq_set.create_node('aset', 'root', 'rnode', 'londiste_root', null::text, null::int8, null::text);
- ret_code | ret_desc
+ ret_code | ret_note
----------+----------
200 | Ok
(1 row)
select * from londiste.node_add_table('aset', 'public.testdata_nopk');
- ret_code | ret_desc
+ ret_code | ret_note
----------+----------------------------------------------------
400 | Primary key missing on table: public.testdata_nopk
(1 row)
select * from londiste.node_add_table('aset', 'public.testdata');
- ret_code | ret_desc
+ ret_code | ret_note
----------+------------------------------
200 | Table added: public.testdata
(1 row)
@@ -49,13 +49,13 @@ select * from londiste.node_get_table_list('aset');
(1 row)
select * from londiste.node_remove_table('aset', 'public.testdata');
- ret_code | ret_desc
+ ret_code | ret_note
----------+--------------------------------
200 | Table removed: public.testdata
(1 row)
select * from londiste.node_remove_table('aset', 'public.testdata');
- ret_code | ret_desc
+ ret_code | ret_note
----------+----------------------------
400 | Not found: public.testdata
(1 row)
diff --git a/sql/londiste/expected/londiste_subscriber.out b/sql/londiste/expected/londiste_subscriber.out
index b09399ae..feb73397 100644
--- a/sql/londiste/expected/londiste_subscriber.out
+++ b/sql/londiste/expected/londiste_subscriber.out
@@ -26,25 +26,25 @@ select * from pgq_set.add_member('branch_set', 'pnode', 'dbname=db2', false);
(1 row)
select * from pgq_set.create_node('branch_set', 'branch', 'snode', 'londiste_branch', 'pnode', 100, null::text);
- ret_code | ret_desc
+ ret_code | ret_note
----------+----------
200 | Ok
(1 row)
select * from londiste.node_add_table('branch_set', 'public.slavedata');
- ret_code | ret_desc
+ ret_code | ret_note
----------+-----------------------------------------------
400 | Table not registered in set: public.slavedata
(1 row)
select * from londiste.set_add_table('branch_set', 'public.slavedata');
- ret_code | ret_desc
+ ret_code | ret_note
----------+----------
200 | OK
(1 row)
select * from londiste.node_add_table('branch_set', 'public.slavedata');
- ret_code | ret_desc
+ ret_code | ret_note
----------+-------------------------------
200 | Table added: public.slavedata
(1 row)
@@ -56,13 +56,13 @@ select * from londiste.node_get_table_list('branch_set');
(1 row)
select * from londiste.node_remove_table('branch_set', 'public.slavedata');
- ret_code | ret_desc
+ ret_code | ret_note
----------+---------------------------------
200 | Table removed: public.slavedata
(1 row)
select * from londiste.node_remove_table('branch_set', 'public.slavedata');
- ret_code | ret_desc
+ ret_code | ret_note
----------+-----------------------------
400 | Not found: public.slavedata
(1 row)
diff --git a/sql/londiste/functions/londiste.node_add_table.sql b/sql/londiste/functions/londiste.node_add_table.sql
index a2cebe05..06125167 100644
--- a/sql/londiste/functions/londiste.node_add_table.sql
+++ b/sql/londiste/functions/londiste.node_add_table.sql
@@ -2,7 +2,7 @@ create or replace function londiste.node_add_table(
in i_set_name text,
in i_table_name text,
out ret_code int4,
- out ret_desc text)
+ out ret_note text)
as $$
-- ----------------------------------------------------------------------
-- Function: londiste.node_add_table(2)
@@ -21,24 +21,24 @@ begin
fq_table_name := londiste.make_fqname(i_table_name);
col_types := londiste.find_column_types(fq_table_name);
if position('k' in col_types) < 1 then
- select 400, 'Primary key missing on table: ' || fq_table_name into ret_code, ret_desc;
+ select 400, 'Primary key missing on table: ' || fq_table_name into ret_code, ret_note;
return;
end if;
perform 1 from pgq_set.set_info where set_name = i_set_name;
if not found then
- select 400, 'No such set: ' || i_set_name into ret_code, ret_desc;
+ select 400, 'No such set: ' || i_set_name into ret_code, ret_note;
return;
end if;
perform 1 from londiste.node_table where set_name = i_set_name and table_name = fq_table_name;
if found then
- select 200, 'Table already added: ' || fq_table_name into ret_code, ret_desc;
+ select 200, 'Table already added: ' || fq_table_name into ret_code, ret_note;
return;
end if;
if pgq_set.is_root(i_set_name) then
- select * into ret_code, ret_desc
+ select * into ret_code, ret_note
from londiste.set_add_table(i_set_name, fq_table_name);
if ret_code <> 200 then
return;
@@ -48,7 +48,7 @@ begin
else
perform 1 from londiste.set_table where set_name = i_set_name and table_name = fq_table_name;
if not found then
- select 400, 'Table not registered in set: ' || fq_table_name into ret_code, ret_desc;
+ select 400, 'Table not registered in set: ' || fq_table_name into ret_code, ret_note;
return;
end if;
new_state := NULL;
@@ -57,8 +57,8 @@ begin
insert into londiste.node_table (set_name, table_name, merge_state)
values (i_set_name, fq_table_name, new_state);
- for ret_code, ret_desc in
- select f.ret_code, f.ret_desc
+ for ret_code, ret_note in
+ select f.ret_code, f.ret_note
from londiste.node_prepare_triggers(i_set_name, fq_table_name) f
loop
if ret_code > 299 then
@@ -66,8 +66,8 @@ begin
end if;
end loop;
- for ret_code, ret_desc in
- select f.ret_code, f.ret_desc
+ for ret_code, ret_note in
+ select f.ret_code, f.ret_note
from londiste.node_refresh_triggers(i_set_name, fq_table_name) f
loop
if ret_code > 299 then
@@ -75,7 +75,7 @@ begin
end if;
end loop;
- select 200, 'Table added: ' || fq_table_name into ret_code, ret_desc;
+ select 200, 'Table added: ' || fq_table_name into ret_code, ret_note;
return;
end;
$$ language plpgsql strict;
diff --git a/sql/londiste/functions/londiste.node_disable_triggers.sql b/sql/londiste/functions/londiste.node_disable_triggers.sql
index df5a0759..f86dc869 100644
--- a/sql/londiste/functions/londiste.node_disable_triggers.sql
+++ b/sql/londiste/functions/londiste.node_disable_triggers.sql
@@ -3,7 +3,7 @@ create or replace function londiste.node_disable_triggers(
in i_set_name text,
in i_table_name text,
out ret_code int4,
- out ret_desc text)
+ out ret_note text)
returns setof record strict as $$
-- ----------------------------------------------------------------------
-- Function: londiste.node_disable_triggers(2)
@@ -38,7 +38,7 @@ begin
|| ' on ' || londiste.quote_fqname(fq_table_name);
select 200, 'Dropped trigger ' || tg.tg_name
|| ' from table ' || fq_table_name
- into ret_code, ret_desc;
+ into ret_code, ret_note;
return next;
end if;
end loop;
@@ -49,7 +49,7 @@ $$ language plpgsql security definer;
create or replace function londiste.node_disable_triggers(
in i_set_name text,
out ret_code int4,
- out ret_desc text)
+ out ret_note text)
returns setof record strict as $$
-- ----------------------------------------------------------------------
-- Function: londiste.node_disable_triggers(1)
@@ -64,8 +64,8 @@ begin
where set_name = i_set_name
order by nr
loop
- for ret_code, ret_desc in
- select f.ret_code, f.ret_desc
+ for ret_code, ret_note in
+ select f.ret_code, f.ret_note
from londiste.node_disable_triggers(i_set_name, t.table_name) f
loop
return next;
diff --git a/sql/londiste/functions/londiste.node_prepare_triggers.sql b/sql/londiste/functions/londiste.node_prepare_triggers.sql
index ade870d4..6a82f1dd 100644
--- a/sql/londiste/functions/londiste.node_prepare_triggers.sql
+++ b/sql/londiste/functions/londiste.node_prepare_triggers.sql
@@ -3,7 +3,7 @@ create or replace function londiste.node_prepare_triggers(
in i_set_name text,
in i_table_name text,
out ret_code int4,
- out ret_desc text)
+ out ret_note text)
returns setof record strict as $$
-- ----------------------------------------------------------------------
-- Function: londiste.node_prepare_triggers(2)
@@ -22,7 +22,7 @@ begin
fq_table_name := londiste.make_fqname(i_table_name);
select queue_name into qname from pgq_set.set_info where set_name = i_set_name;
if not found then
- select 400, 'Set not found: ' || i_set_name into ret_code, ret_desc;
+ select 400, 'Set not found: ' || i_set_name into ret_code, ret_note;
return next;
return;
end if;
@@ -33,7 +33,7 @@ begin
|| ' for each row execute procedure pgq.sqltriga(' || quote_literal(qname) || ')';
insert into londiste.node_trigger (set_name, table_name, tg_name, tg_type, tg_def)
values (i_set_name, fq_table_name, logtrg_name, 'root', logtrg);
- select 200, logtrg into ret_code, ret_desc;
+ select 200, logtrg into ret_code, ret_note;
return next;
end if;
@@ -43,7 +43,7 @@ begin
|| ' for each row execute procedure pgq.denytriga(' || quote_literal(i_set_name) || ')';
insert into londiste.node_trigger (set_name, table_name, tg_name, tg_type, tg_def)
values (i_set_name, fq_table_name, denytrg_name, 'non-root', denytrg);
- select 200, denytrg into ret_code, ret_desc;
+ select 200, denytrg into ret_code, ret_note;
return next;
return;
diff --git a/sql/londiste/functions/londiste.node_refresh_triggers.sql b/sql/londiste/functions/londiste.node_refresh_triggers.sql
index 76da2d22..68d3f985 100644
--- a/sql/londiste/functions/londiste.node_refresh_triggers.sql
+++ b/sql/londiste/functions/londiste.node_refresh_triggers.sql
@@ -3,7 +3,7 @@ create or replace function londiste.node_refresh_triggers(
in i_set_name text,
in i_table_name text,
out ret_code int4,
- out ret_desc text)
+ out ret_note text)
returns setof record strict as $$
-- ----------------------------------------------------------------------
-- Function: londiste.node_refresh_triggers(2)
@@ -35,7 +35,7 @@ begin
select 400, 'trigger ' || tg.tg_name
|| ' on table ' || fq_table_name
|| ' had unsupported type: ' || tg.tg_type
- into ret_code, ret_desc;
+ into ret_code, ret_note;
return next;
else
-- check if active
@@ -51,7 +51,7 @@ begin
execute tg.tg_def;
select 200, 'Created trigger ' || tg.tg_name
|| ' on table ' || fq_table_name
- into ret_code, ret_desc;
+ into ret_code, ret_note;
return next;
end if;
else
@@ -61,7 +61,7 @@ begin
|| ' on ' || londiste.quote_fqname(fq_table_name);
select 200, 'Dropped trigger ' || tg.tg_name
|| ' from table ' || fq_table_name
- into ret_code, ret_desc;
+ into ret_code, ret_note;
return next;
end if;
end if;
@@ -74,7 +74,7 @@ $$ language plpgsql security definer;
create or replace function londiste.node_refresh_triggers(
in i_set_name text,
out ret_code int4,
- out ret_desc text)
+ out ret_note text)
returns setof record strict as $$
-- ----------------------------------------------------------------------
-- Function: londiste.node_refresh_triggers(2)
@@ -89,8 +89,8 @@ begin
where set_name = i_set_name
order by nr
loop
- for ret_code, ret_desc in
- select f.ret_code, f.ret_desc
+ for ret_code, ret_note in
+ select f.ret_code, f.ret_note
from londiste.node_refresh_triggers(i_set_name, t.table_name) f
loop
return next;
diff --git a/sql/londiste/functions/londiste.node_remove_seq.sql b/sql/londiste/functions/londiste.node_remove_seq.sql
index 3906ca5d..ae142547 100644
--- a/sql/londiste/functions/londiste.node_remove_seq.sql
+++ b/sql/londiste/functions/londiste.node_remove_seq.sql
@@ -1,19 +1,19 @@
create or replace function londiste.provider_remove_seq(
in i_set_name text, in i_seq_name text,
- out ret_code int4, out ret_desc text)
+ out ret_code int4, out ret_note text)
as $$
begin
delete from londiste.node_seq
where set_name = i_set_name
and seq_name = i_seq_name;
if not found then
- select 400, 'Not found: '||i_seq_name into ret_code, ret_desc;
+ select 400, 'Not found: '||i_seq_name into ret_code, ret_note;
return;
end if;
-- perform londiste.provider_notify_change(i_queue_name);
- select 200, 'OK' into ret_code, ret_desc;
+ select 200, 'OK' into ret_code, ret_note;
return;
end;
$$ language plpgsql strict;
diff --git a/sql/londiste/functions/londiste.node_remove_table.sql b/sql/londiste/functions/londiste.node_remove_table.sql
index 93b7d21b..9e4ff637 100644
--- a/sql/londiste/functions/londiste.node_remove_table.sql
+++ b/sql/londiste/functions/londiste.node_remove_table.sql
@@ -1,15 +1,15 @@
create or replace function londiste.node_remove_table(
in i_set_name text, in i_table_name text,
- out ret_code int4, out ret_desc text)
+ out ret_code int4, out ret_note text)
as $$
declare
fq_table_name text;
begin
fq_table_name := londiste.make_fqname(i_table_name);
- for ret_code, ret_desc in
- select f.ret_code, f.ret_desc from londiste.node_disable_triggers(i_set_name, fq_table_name) f
+ for ret_code, ret_note in
+ select f.ret_code, f.ret_note from londiste.node_disable_triggers(i_set_name, fq_table_name) f
loop
if ret_code > 299 then
return;
@@ -22,7 +22,7 @@ begin
where set_name = i_set_name
and table_name = fq_table_name;
if not found then
- select 400, 'Not found: ' || fq_table_name into ret_code, ret_desc;
+ select 400, 'Not found: ' || fq_table_name into ret_code, ret_note;
return;
end if;
@@ -31,7 +31,7 @@ begin
perform londiste.root_notify_change(i_set_name, 'remove-table', fq_table_name);
end if;
- select 200, 'Table removed: ' || fq_table_name into ret_code, ret_desc;
+ select 200, 'Table removed: ' || fq_table_name into ret_code, ret_note;
return;
end;
$$ language plpgsql strict;
diff --git a/sql/londiste/functions/londiste.set_add_table.sql b/sql/londiste/functions/londiste.set_add_table.sql
index 7e11a84c..8a6461c8 100644
--- a/sql/londiste/functions/londiste.set_add_table.sql
+++ b/sql/londiste/functions/londiste.set_add_table.sql
@@ -3,7 +3,7 @@ create or replace function londiste.set_add_table(
in i_set_name text,
in i_table_name text,
out ret_code int4,
- out ret_desc text)
+ out ret_note text)
as $$
-- ----------------------------------------------------------------------
-- Function: londiste.node_add_table(x)
@@ -29,19 +29,19 @@ begin
perform 1 from pgq_set.set_info where set_name = i_set_name;
if not found then
- select 400, 'No such set: ' || i_set_name into ret_code, ret_desc;
+ select 400, 'No such set: ' || i_set_name into ret_code, ret_note;
return;
end if;
perform 1 from londiste.set_table where set_name = i_set_name and table_name = fq_table_name;
if found then
- select 200, 'OK, already added: ' || fq_table_name into ret_code, ret_desc;
+ select 200, 'OK, already added: ' || fq_table_name into ret_code, ret_note;
return;
end if;
insert into londiste.set_table (set_name, table_name)
values (i_set_name, fq_table_name);
- select 200, 'OK' into ret_code, ret_desc;
+ select 200, 'OK' into ret_code, ret_note;
return;
end;
$$ language plpgsql strict;
diff --git a/sql/londiste/functions/londiste.set_remove_table.sql b/sql/londiste/functions/londiste.set_remove_table.sql
index 080785a4..683ea837 100644
--- a/sql/londiste/functions/londiste.set_remove_table.sql
+++ b/sql/londiste/functions/londiste.set_remove_table.sql
@@ -1,7 +1,7 @@
create or replace function londiste.set_remove_table(
in i_set_name text, in i_table_name text,
- out ret_code int4, out ret_desc text)
+ out ret_code int4, out ret_note text)
as $$
-- ----------------------------------------------------------------------
-- Function: londiste.set_remove_table(2)
@@ -29,10 +29,10 @@ begin
where set_name = i_set_name
and table_name = fq_table_name;
if not found then
- select 400, 'Not found: '||fq_table_name into ret_code, ret_desc;
+ select 400, 'Not found: '||fq_table_name into ret_code, ret_note;
return;
end if;
- select 200, 'OK' into ret_code, ret_desc;
+ select 200, 'OK' into ret_code, ret_note;
return;
end;
$$ language plpgsql strict;
diff --git a/sql/pgq_set/expected/pgq_set.out b/sql/pgq_set/expected/pgq_set.out
index e99129f0..5f57f970 100644
--- a/sql/pgq_set/expected/pgq_set.out
+++ b/sql/pgq_set/expected/pgq_set.out
@@ -2,25 +2,25 @@
select * from pgq_set.add_member('aset', 'node1', 'dbname=node1', false);
ret_code | ret_note
----------+----------
- 200 | Ok
+ 100 | Ok
(1 row)
select * from pgq_set.add_member('aset', 'node2', 'dbname=node2', false);
ret_code | ret_note
----------+----------
- 200 | Ok
+ 100 | Ok
(1 row)
select * from pgq_set.add_member('aset', 'node3', 'dbname=node3', false);
ret_code | ret_note
----------+----------
- 200 | Ok
+ 100 | Ok
(1 row)
select * from pgq_set.add_member('aset', 'node4', 'dbname=node4', false);
ret_code | ret_note
----------+----------
- 200 | Ok
+ 100 | Ok
(1 row)
select * from pgq_set.get_member_info('aset');
@@ -47,15 +47,33 @@ select * from pgq_set.get_member_info('aset');
(3 rows)
select * from pgq_set.create_node('aset', 'root', 'node1', null, null, null);
- ret_code | ret_desc
+ ret_code | ret_note
+----------+---------------------------------------------------
+ 200 | Node "node1" added to set "aset" with type "root"
+(1 row)
+
+select * from pgq_set.subscribe_node('aset', 'node2');
+ ret_code | ret_note | global_watermark
+----------+----------+------------------
+ 200 | Ok | 1
+(1 row)
+
+select * from pgq_set.subscribe_node('aset', 'node3', 1);
+ ret_code | ret_note | global_watermark
+----------+----------+------------------
+ 200 | Ok | 1
+(1 row)
+
+select * from pgq_set.unsubscribe_node('aset', 'node3');
+ ret_code | ret_note
----------+----------
200 | Ok
(1 row)
select * from pgq_set.get_node_info('aset');
- node_type | node_name | queue_name | global_watermark | local_watermark | completed_tick | provider_node | provider_location | paused | resync | up_to_date | combined_set | combined_type | combined_queue
------------+-----------+------------+------------------+-----------------+----------------+---------------+-------------------+--------+--------+------------+--------------+---------------+----------------
- root | node1 | aset | 1 | 1 | | | | f | f | f | | |
+ ret_code | ret_note | node_type | node_name | queue_name | global_watermark | local_watermark | completed_tick | provider_node | provider_location | paused | resync | uptodate | combined_set | combined_type | combined_queue
+----------+----------+-----------+-----------+------------+------------------+-----------------+----------------+---------------+-------------------+--------+--------+----------+--------------+---------------+----------------
+ 100 | Ok | root | node1 | aset | 1 | 1 | | | | f | f | f | | |
(1 row)
select * from pgq_set.is_root('q');
@@ -68,3 +86,15 @@ select * from pgq_set.is_root('aset');
select * from pgq_set.is_root(null);
ERROR: set does not exist: <NULL>
+select * from pgq_set.rename_node_step1('aset', 'node2', 'node2x');
+ ret_code | ret_note
+----------+----------
+ 200 | Ok
+(1 row)
+
+select * from pgq_set.rename_node_step2('aset', 'node2', 'node2x');
+ ret_code | ret_note
+----------+----------
+ 200 | Ok
+(1 row)
+
diff --git a/sql/pgq_set/functions/pgq_set.add_member.sql b/sql/pgq_set/functions/pgq_set.add_member.sql
index 064b65e8..53cb2733 100644
--- a/sql/pgq_set/functions/pgq_set.add_member.sql
+++ b/sql/pgq_set/functions/pgq_set.add_member.sql
@@ -28,7 +28,13 @@ returns record as $$
-- ----------------------------------------------------------------------
declare
o record;
+ node record;
begin
+ select node_type in ('root', 'combined-root') as is_root
+ into node
+ from pgq_set.set_info where set_name = i_set_name
+ for update;
+
select node_location into o
from pgq_set.member_info
where set_name = i_set_name
@@ -43,7 +49,15 @@ begin
insert into pgq_set.member_info (set_name, node_name, node_location, dead)
values (i_set_name, i_node_name, i_node_location, i_dead);
end if;
- select 200, 'Ok' into ret_code, ret_note;
+
+ if node.is_root then
+ perform pgq.insert_event(s.queue_name, 'member-info',
+ i_node_name, i_set_name, i_node_location, i_dead::text, null)
+ from pgq_set.set_info s
+ where s.set_name = i_set_name;
+ end if;
+
+ select 100, 'Ok' into ret_code, ret_note;
return;
end;
$$ language plpgsql security definer;
diff --git a/sql/pgq_set/functions/pgq_set.change_provider.sql b/sql/pgq_set/functions/pgq_set.change_provider.sql
new file mode 100644
index 00000000..29ed310a
--- /dev/null
+++ b/sql/pgq_set/functions/pgq_set.change_provider.sql
@@ -0,0 +1,30 @@
+
+create or replace function pgq_set.change_provider(
+ in i_set_name text,
+ in i_new_provider text,
+ out ret_code int4,
+ out ret_note text)
+as $$
+-- ----------------------------------------------------------------------
+-- Function: pgq_set.change_provider(2)
+--
+-- Change provider for this node.
+--
+-- Parameters:
+-- i_set_name - set name
+-- i_new_provider - node name for new provider
+-- ----------------------------------------------------------------------
+begin
+ update pgq_set.set_info
+ set provider_node = i_new_provider,
+ uptodate = false
+ where set_name = i_set_name;
+ if not found then
+ select 404, 'Unknown set: ' || i_set_name into ret_code, ret_note;
+ return;
+ end if;
+ select 200, 'Node provider set to : ' || i_new_provider into ret_code, ret_note;
+ return;
+end;
+$$ language plpgsql security definer;
+
diff --git a/sql/pgq_set/functions/pgq_set.create_node.sql b/sql/pgq_set/functions/pgq_set.create_node.sql
index 84ada82c..65a2dd25 100644
--- a/sql/pgq_set/functions/pgq_set.create_node.sql
+++ b/sql/pgq_set/functions/pgq_set.create_node.sql
@@ -7,7 +7,7 @@ create or replace function pgq_set.create_node(
in i_global_watermark bigint,
in i_combined_set text,
out ret_code int4,
- out ret_desc text)
+ out ret_note text)
returns record as $$
-- ----------------------------------------------------------------------
-- Function: pgq_set.create_node(7)
@@ -23,7 +23,7 @@ returns record as $$
-- i_combined_set - merge-leaf: target set
--
-- Returns:
--- desc
+-- 401 - node already initialized
--
-- Node Types:
-- root - master node
@@ -38,6 +38,12 @@ declare
_wm_consumer text;
_global_wm bigint;
begin
+ perform 1 from pgq_set.set_info where set_name = i_set_name;
+ if found then
+ select 401, 'Node already initialized' into ret_code, ret_note;
+ return;
+ end if;
+
if i_node_type in ('root', 'combined-root') then
if coalesce(i_provider_name, i_global_watermark::text,
i_combined_set) is not null then
@@ -84,7 +90,9 @@ begin
values (i_set_name, i_node_name, _global_wm);
end if;
- select 200, 'Ok' into ret_code, ret_desc;
+ select 200, 'Node "' || i_node_name || '" added to set "'
+ || i_set_name || '" with type "' || i_node_type || '"'
+ into ret_code, ret_note;
return;
end;
$$ language plpgsql security definer;
diff --git a/sql/pgq_set/functions/pgq_set.drop_member.sql b/sql/pgq_set/functions/pgq_set.drop_member.sql
new file mode 100644
index 00000000..35584c77
--- /dev/null
+++ b/sql/pgq_set/functions/pgq_set.drop_member.sql
@@ -0,0 +1,59 @@
+
+create or replace function pgq_set.drop_member(
+ in i_set_name text,
+ in i_node_name text,
+ out ret_code int4,
+ out ret_note text)
+returns record as $$
+-- ----------------------------------------------------------------------
+-- Function: pgq_set.drop_member(1)
+--
+-- Drop unreferenced member.
+--
+-- Parameters:
+-- i_set_name - set name
+-- i_node_name - node to drop
+--
+-- Returns:
+-- ret_code - error code
+-- ret_note - error description
+--
+-- Return Codes:
+-- 200 - Ok
+-- 404 - No such set
+-- ----------------------------------------------------------------------
+declare
+ _queue_name text;
+ _wm_consumer text;
+ _global_wm bigint;
+ sub record;
+ node record;
+begin
+ select * into node from pgq_set.set_info
+ where set_name = i_set_name;
+ if not found then
+ select 404, 'No such set: ' || i_set_name into ret_code, ret_note;
+ return;
+ end if;
+ if node.node_name = i_node_name then
+ select 403, 'Cannot use drop_member on node itself' into ret_code, ret_note;
+ return;
+ end if;
+ if node.provider_node = i_node_name then
+ select 403, 'Cannot use drop_member on node child' into ret_code, ret_note;
+ return;
+ end if;
+
+ perform 1 from pgq_set.subscriber_info
+ where set_name = i_set_name
+ and node_name = i_node_name;
+ if found then
+ select f.ret_code, f.ret_note into ret_code, ret_note
+ from pgq_set.unsubscribe_node(i_set_name, i_node_name) f;
+ end if;
+ perform * from pgq_set.remove_member(i_set_name, i_node_name);
+ select 200, 'Ok' into ret_code, ret_note;
+ return;
+end;
+$$ language plpgsql security definer;
+
diff --git a/sql/pgq_set/functions/pgq_set.get_node_info.sql b/sql/pgq_set/functions/pgq_set.get_node_info.sql
index a738eb14..701e8ff8 100644
--- a/sql/pgq_set/functions/pgq_set.get_node_info.sql
+++ b/sql/pgq_set/functions/pgq_set.get_node_info.sql
@@ -2,6 +2,8 @@
create or replace function pgq_set.get_node_info(
in i_set_name text,
+ out ret_code int4,
+ out ret_note text,
out node_type text,
out node_name text,
out queue_name text,
@@ -13,7 +15,7 @@ create or replace function pgq_set.get_node_info(
out provider_location text,
out paused boolean,
out resync boolean,
- out up_to_date boolean,
+ out uptodate boolean,
out combined_set text,
out combined_type text,
@@ -38,7 +40,7 @@ create or replace function pgq_set.get_node_info(
-- provider_location - connect string to provider node
-- paused - this node should not do any work
-- resync - re-register on provider queue (???)
--- up_to_date - if consumer has loaded last changes
+-- uptodate - if consumer has loaded last changes
-- combined_set - target set name for merge-leaf
-- combined_type - node type of target set
-- combined_queue - queue name for target set
@@ -46,19 +48,23 @@ create or replace function pgq_set.get_node_info(
declare
sql text;
begin
- select n.node_type, n.node_name, t.tick_id, n.queue_name,
+ select 100, 'Ok', n.node_type, n.node_name, t.tick_id, n.queue_name,
c.set_name, c.node_type, c.queue_name, n.global_watermark,
- n.provider_node, n.paused, n.resync, n.up_to_date,
+ n.provider_node, n.paused, n.resync, n.uptodate,
p.node_location
- into node_type, node_name, completed_tick, queue_name,
+ into ret_code, ret_note, node_type, node_name, completed_tick, queue_name,
combined_set, combined_type, combined_queue, global_watermark,
- provider_node, paused, resync, up_to_date,
+ provider_node, paused, resync, uptodate,
provider_location
from pgq_set.set_info n
left join pgq_set.completed_tick t on (t.set_name = n.set_name and t.worker_name = n.node_name)
left join pgq_set.set_info c on (c.set_name = n.combined_set)
left join pgq_set.member_info p on (p.set_name = n.set_name and p.node_name = n.provider_node)
where n.set_name = i_set_name;
+ if not found then
+ select 404, 'Unknown set: ' || i_set_name into ret_code, ret_note;
+ return;
+ end if;
select min(u.tick_id) into local_watermark
from (select tick_id
diff --git a/sql/pgq_set/functions/pgq_set.rename_node.sql b/sql/pgq_set/functions/pgq_set.rename_node.sql
new file mode 100644
index 00000000..b48a2d05
--- /dev/null
+++ b/sql/pgq_set/functions/pgq_set.rename_node.sql
@@ -0,0 +1,190 @@
+
+create or replace function pgq_set.rename_node_step1(
+ in i_set_name text,
+ in i_node_name_old text,
+ in i_node_name_new text,
+ out ret_code int4,
+ out ret_note text)
+returns record as $$
+-- ----------------------------------------------------------------------
+-- Function: pgq_set.rename_node_step1(3)
+--
+-- Rename a node - step1.
+--
+-- Parameters:
+-- i_set_name - set name
+-- i_node_name_old - node name
+-- i_node_name_new - node connect string
+--
+-- Returns:
+-- ret_code - error code
+-- ret_note - error description
+--
+-- Return Codes:
+-- 200 - Ok
+-- 404 - No such set
+-- ----------------------------------------------------------------------
+declare
+ n record;
+ reg record;
+begin
+ select s.node_name, s.node_type, s.paused, s.uptodate, s.queue_name
+ into n from pgq_set.set_info s
+ where s.set_name = i_set_name for update;
+ if not found then
+ select 404, 'Unknown set: ' || i_set_name into ret_code, ret_note;
+ return;
+ end if;
+
+ -- make copy of member info
+ perform 1 from pgq_set.member_info
+ where set_name = i_set_name
+ and node_name = i_node_name_new;
+ if not found then
+ insert into pgq_set.member_info
+ (set_name, node_name, node_location, dead)
+ select set_name, i_node_name_new, node_location, dead
+ from pgq_set.member_info
+ where set_name = i_set_name
+ and node_name = i_node_name_old;
+ end if;
+
+ -- make copy of subscriber info
+ perform 1 from pgq_set.subscriber_info
+ where set_name = i_set_name
+ and node_name = i_node_name_new;
+ if not found then
+ insert into pgq_set.subscriber_info
+ (set_name, node_name, local_watermark)
+ select set_name, i_node_name_new, local_watermark
+ from pgq_set.subscriber_info
+ where set_name = i_set_name
+ and node_name = i_node_name_old;
+ end if;
+
+ if n.queue_name is not null then
+ select f.last_tick into reg
+ from pgq.get_consumer_info(n.queue_name, i_node_name_old) f;
+ if found then
+ perform 1 from pgq.get_consumer_info(n.queue_name, i_node_name_new);
+ if not found then
+ perform pgq.register_consumer_at(n.queue_name, i_node_name_new, reg.last_tick);
+ end if;
+ end if;
+ end if;
+
+ -- FIXME: on root insert event about new node
+
+ select 200, 'Ok' into ret_code, ret_note;
+ return;
+end;
+$$ language plpgsql security definer;
+
+
+create or replace function pgq_set.rename_node_step2(
+ in i_set_name text,
+ in i_node_name_old text,
+ in i_node_name_new text,
+ out ret_code int4,
+ out ret_note text)
+returns record as $$
+-- ----------------------------------------------------------------------
+-- Function: pgq_set.rename_node_step2(3)
+--
+-- Rename a node - step2.
+--
+-- Parameters:
+-- i_set_name - set name
+-- i_node_name_old - node name
+-- i_node_name_new - node connect string
+--
+-- Returns:
+-- ret_code - error code
+-- ret_note - error description
+--
+-- Return Codes:
+-- 200 - Ok
+-- 404 - No such set
+-- ----------------------------------------------------------------------
+declare
+ n record;
+ det record;
+ reg record;
+begin
+ select s.node_name, s.node_type, s.paused, s.uptodate, s.queue_name, s.provider_node
+ into n from pgq_set.set_info s
+ where s.set_name = i_set_name for update;
+ if not found then
+ select 404, 'Unknown set: ' || i_set_name into ret_code, ret_note;
+ return;
+ end if;
+
+ if n.node_name = i_node_name_old then
+ if not n.paused or not n.uptodate then
+ select 401, 'Bad node state during rename' into ret_code, ret_note;
+ return;
+ end if;
+ update pgq_set.set_info
+ set node_name = i_node_name_new,
+ uptodate = false
+ where set_name = i_set_name;
+ elsif n.provider_node = i_node_name_old then
+ update pgq_set.set_into
+ set provider_node = i_node_name_new,
+ uptodate = false
+ where set_name = i_set_name;
+ end if;
+
+ -- delete old copy of subscriber info
+ select into det
+ (select count(1) from pgq_set.subscriber_info
+ where set_name = i_set_name
+ and node_name = i_node_name_old) as got_old,
+ (select count(1) from pgq_set.subscriber_info
+ where set_name = i_set_name
+ and node_name = i_node_name_new) as got_new;
+ if det.got_old > 0 and det.got_new > 0 then
+ delete from pgq_set.subscriber_info
+ where set_name = i_set_name
+ and node_name = i_node_name_old;
+ elsif det.got_old > 0 then
+ select 401, 'got old subscriber but not new' into ret_code, ret_note;
+ return;
+ end if;
+
+ -- delete old copy of subscriber info
+ select into det
+ (select count(1) from pgq_set.member_info
+ where set_name = i_set_name
+ and node_name = i_node_name_old) > 0 as got_old,
+ (select count(1) from pgq_set.member_info
+ where set_name = i_set_name
+ and node_name = i_node_name_new) > 0 as got_new;
+ if det.got_old and det.got_new then
+ delete from pgq_set.member_info
+ where set_name = i_set_name
+ and node_name = i_node_name_old;
+ elsif det.got_old then
+ select 401, 'got old member but not new' into ret_code, ret_note;
+ return;
+ end if;
+
+ if n.queue_name is not null then
+ select f.last_tick into reg
+ from pgq.get_consumer_info(n.queue_name, i_node_name_old) f;
+ if found then
+ perform 1 from pgq.get_consumer_info(n.queue_name, i_node_name_new);
+ if not found then
+ perform pgq.register_consumer_at(n.queue_name, i_node_name_new, reg.last_tick);
+ end if;
+ end if;
+ end if;
+
+ -- FIXME: on parent remove old registration
+ -- FIXME: on root insert event about old node delete
+
+ select 200, 'Ok' into ret_code, ret_note;
+ return;
+end;
+$$ language plpgsql security definer;
+
diff --git a/sql/pgq_set/functions/pgq_set.set_node_paused.sql b/sql/pgq_set/functions/pgq_set.set_node_paused.sql
new file mode 100644
index 00000000..dd659b3a
--- /dev/null
+++ b/sql/pgq_set/functions/pgq_set.set_node_paused.sql
@@ -0,0 +1,46 @@
+
+create or replace function pgq_set.set_node_paused(
+ in i_set_name text,
+ in i_paused boolean,
+ out ret_code int4,
+ out ret_note text)
+as $$
+-- ----------------------------------------------------------------------
+-- Function: pgq_set.set_node_paused(2)
+--
+-- Set node paused flag.
+--
+-- Parameters:
+-- i_set_name - set name
+-- i_paused - new flag state
+-- ----------------------------------------------------------------------
+declare
+ cur_paused boolean;
+ nname text;
+ op text;
+begin
+ op := case when i_paused then 'paused' else 'resumed' end;
+ select paused, node_name into cur_paused, nname
+ from pgq_set.set_info
+ where set_name = i_set_name
+ for update;
+ if not found then
+ select 400, 'Set does not exist: ' || i_set_name into ret_code, ret_note;
+ return;
+ end if;
+
+ if cur_paused = i_paused then
+ select 200, 'Node already '|| op || ': ' || nname into ret_code, ret_note;
+ return;
+ end if;
+
+ update pgq_set.set_info
+ set paused = i_paused,
+ uptodate = false
+ where set_name = i_set_name;
+ select 200, 'Node ' || op || ': ' || nname into ret_code, ret_note;
+ return;
+end;
+$$ language plpgsql security definer;
+
+
diff --git a/sql/pgq_set/functions/pgq_set.set_node_uptodate.sql b/sql/pgq_set/functions/pgq_set.set_node_uptodate.sql
index ce99083a..d578c6a5 100644
--- a/sql/pgq_set/functions/pgq_set.set_node_uptodate.sql
+++ b/sql/pgq_set/functions/pgq_set.set_node_uptodate.sql
@@ -17,7 +17,7 @@ returns int4 as $$
-- ----------------------------------------------------------------------
begin
update pgq_set.set_info
- set up_to_date = i_uptodate
+ set uptodate = i_uptodate
where set_name = i_set_name;
if not found then
raise exception 'no such set: %', i_set_name;
diff --git a/sql/pgq_set/functions/pgq_set.subscribe_node.sql b/sql/pgq_set/functions/pgq_set.subscribe_node.sql
index cdf6da47..01a5af77 100644
--- a/sql/pgq_set/functions/pgq_set.subscribe_node.sql
+++ b/sql/pgq_set/functions/pgq_set.subscribe_node.sql
@@ -2,29 +2,37 @@
create or replace function pgq_set.subscribe_node(
in i_set_name text,
in i_remote_node_name text,
+ in i_custom_tick_id int8,
out ret_code int4,
out ret_note text,
out global_watermark bigint)
returns record as $$
-- ----------------------------------------------------------------------
--- Function: pgq_set.subscribe_node(2)
+-- Function: pgq_set.subscribe_node(3)
--
--- Subscribe remote node to local node.
+-- Subscribe remote node to local node at custom position.
+-- Should be used when changing provider for existing node.
--
-- Parameters:
-- i_set_name - set name
-- i_remote_node_name - node name
+-- i_custom_tick_id - tick id
--
-- Returns:
-- ret_code - error code
-- ret_note - description
--- global_watermark - minimal watermark, also subscription pos
+-- global_watermark - minimal watermark
-- ----------------------------------------------------------------------
declare
n record;
begin
select s.node_type, s.global_watermark, s.queue_name into n
- from pgq_set.set_info s where s.set_name = i_set_name;
+ from pgq_set.set_info s where s.set_name = i_set_name
+ for update;
+ if not found then
+ select 404, 'Unknown set: ' || i_set_name into ret_code, ret_note;
+ return;
+ end if;
global_watermark := n.global_watermark;
if n.node_type in ('leaf', 'merge-leaf') then
@@ -33,7 +41,7 @@ begin
return;
end if;
- perform pgq.register_consumer_at(n.queue_name, i_remote_node_name, n.global_watermark);
+ perform pgq.register_consumer_at(n.queue_name, i_remote_node_name, i_custom_tick_id);
insert into pgq_set.subscriber_info (set_name, node_name, local_watermark)
values (i_set_name, i_remote_node_name, n.global_watermark);
@@ -43,3 +51,40 @@ begin
end;
$$ language plpgsql security definer;
+create or replace function pgq_set.subscribe_node(
+ in i_set_name text,
+ in i_remote_node_name text,
+ out ret_code int4,
+ out ret_note text,
+ out global_watermark bigint)
+returns record as $$
+-- ----------------------------------------------------------------------
+-- Function: pgq_set.subscribe_node(2)
+--
+-- Subscribe remote node to local node at global_watermark position,
+-- so it receivec all events.
+--
+-- Parameters:
+-- i_set_name - set name
+-- i_remote_node_name - node name
+--
+-- Returns:
+-- ret_code - error code
+-- ret_note - description
+-- global_watermark - minimal watermark, also subscription pos
+-- ----------------------------------------------------------------------
+declare
+ n record;
+begin
+ select s.global_watermark into n
+ from pgq_set.set_info s where s.set_name = i_set_name
+ for update;
+
+ select f.ret_code, f.ret_note, f.global_watermark
+ into ret_code, ret_note, global_watermark
+ from pgq_set.subscribe_node(i_set_name, i_remote_node_name, n.global_watermark) f;
+
+ return;
+end;
+$$ language plpgsql security definer;
+
diff --git a/sql/pgq_set/sql/pgq_set.sql b/sql/pgq_set/sql/pgq_set.sql
index 941e315c..d7aa3fb4 100644
--- a/sql/pgq_set/sql/pgq_set.sql
+++ b/sql/pgq_set/sql/pgq_set.sql
@@ -17,9 +17,16 @@ select * from pgq_set.get_member_info('aset');
select * from pgq_set.create_node('aset', 'root', 'node1', null, null, null);
+select * from pgq_set.subscribe_node('aset', 'node2');
+select * from pgq_set.subscribe_node('aset', 'node3', 1);
+select * from pgq_set.unsubscribe_node('aset', 'node3');
+
select * from pgq_set.get_node_info('aset');
select * from pgq_set.is_root('q');
select * from pgq_set.is_root('aset');
select * from pgq_set.is_root(null);
+select * from pgq_set.rename_node_step1('aset', 'node2', 'node2x');
+select * from pgq_set.rename_node_step2('aset', 'node2', 'node2x');
+
diff --git a/sql/pgq_set/structure/functions.sql b/sql/pgq_set/structure/functions.sql
index fd9d27c7..c19b7449 100644
--- a/sql/pgq_set/structure/functions.sql
+++ b/sql/pgq_set/structure/functions.sql
@@ -10,6 +10,10 @@
\i functions/pgq_set.subscribe_node.sql
\i functions/pgq_set.unsubscribe_node.sql
\i functions/pgq_set.set_node_uptodate.sql
+\i functions/pgq_set.set_node_paused.sql
+\i functions/pgq_set.change_provider.sql
+\i functions/pgq_set.drop_member.sql
+\i functions/pgq_set.rename_node.sql
-- Group: Node Info
\i functions/pgq_set.get_node_info.sql
diff --git a/sql/pgq_set/structure/pgq_set.sql b/sql/pgq_set/structure/pgq_set.sql
index 75f8a019..ed5d09e3 100644
--- a/sql/pgq_set/structure/pgq_set.sql
+++ b/sql/pgq_set/structure/pgq_set.sql
@@ -1,3 +1,13 @@
+-- ----------------------------------------------------------------------
+-- Section: Londiste internals
+--
+-- Londiste storage: tables/seqs/fkeys/triggers/events.
+--
+-- pgq_set event types:
+-- member-info - ev_data: node_name, extra1: set_name, extra2: location, extra3: dead
+-- global-watermark - ev_data: tick_id, extra1: set_name
+-- tick-id - ev_data: tick_id, extra1: set_name
+-- ----------------------------------------------------------------------
create schema pgq_set;
grant usage on schema pgq_set to public;
@@ -37,7 +47,7 @@ create table pgq_set.member_info (
-- global_watermark - set's global watermark, set by root node
-- paused - true if worker for this node should sleep
-- resync - true if worker for this node needs to re-register itself on provider queue
--- up_to_date - true if worker for this node has seen table changes
+-- uptodate - true if worker for this node has seen table changes
--
-- Node types:
-- root - data + batches is generated here
@@ -59,7 +69,7 @@ create table pgq_set.set_info (
paused boolean not null default false,
resync boolean not null default false,
- up_to_date boolean not null default false,
+ uptodate boolean not null default false,
foreign key (set_name, node_name) references pgq_set.member_info,
foreign key (set_name, provider_node) references pgq_set.member_info,
diff --git a/tests/londiste/gendb.sh b/tests/londiste/gendb.sh
index 2942b4c1..9e66879c 100755
--- a/tests/londiste/gendb.sh
+++ b/tests/londiste/gendb.sh
@@ -3,7 +3,7 @@
. ../env.sh
./stop.sh
-rm -f sys/*.log sys/*.ini
+rm -f sys/*.log sys/*.ini sys/*.log.[0-9]
set -e
@@ -13,6 +13,8 @@ set -e
./makenode.sh test_set node1 branch root
londiste.py sys/worker_root.ini status
+londiste.py sys/worker_root.ini rename-node n_node1 node1renamed
+
#exit 0
./makenode.sh test_set node2 branch root