hadoop-zookeeper-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Travis Crawford <traviscrawf...@gmail.com>
Subject python client structure
Date Wed, 21 Apr 2010 06:33:07 GMT
Hey zookeeper gurus -

I'm getting started with Zookeeper and the python client and an curious if
I'm structuring watches correctly. I'd like to watch a znode and do stuff
when its children change. Something doesn't feel right about having two
methods: one to handle the actual get children call, and one to handle the
watch.

Does this seem like the right direction? If not, any suggestions on how to
better structure things?


#!/usr/bin/python

import signal
import threading
import zookeeper

import logging
logger = logging.getLogger()

from optparse import OptionParser
options = None
args = None


class ZKTest(threading.Thread):
  zparent = '/home/travis/zktest'

  def __init__(self):
    threading.Thread.__init__(self)
    if options.verbose:
      zookeeper.set_debug_level(zookeeper.LOG_LEVEL_DEBUG)
    self.zh = zookeeper.init(options.servers)
    zookeeper.aget_children(self.zh, self.zparent, self.watcher,
self.handler)

  def __del__(self):
    zookeeper.close(self.zh)

  def handler(self, rc, rc1, children):
    """Handle zookeeper.aget_children() responses.

    Args:
      Arguments are not documented well and I'm not entirely sure what to
      call these. ``rc`` appears to be the response code, such as OK.
      However, the only possible mapping of 0 is OK, so in successful cases
      there appear to be two response codes. The example with no children
      returned ``rc1`` of -7 which maps to OPERATIONTIMEOUT so that appears
      to be an error code, but its not clear what was OK in that case.

      If anyone figures this out I would love to know.

    Example args:
      'args': (0, 0, ['a', 'b'])
      'args': (0, -7, [])

    Does not provide a return value.
    """
    logger.debug('Processing response: (%d, %d, %s)' % (rc, rc1, children))
    if (zookeeper.OK == rc and zookeeper.OK == rc1):
      logger.debug('Do the actual work here.')
    else:
      logger.debug('Error getting children! Retrying.')
      zookeeper.aget_children(self.zh, self.zparent, self.watcher,
self.handler)

  def watcher(self, rc, event, state, path):
    """Handle zookeeper.aget_children() watches.

    This code is called when an child znode changes and triggers a child
    watch. It is not called to handle the aget_children call itself.

    Numeric arguments map to constants. See ``DATA`` in ``help(zookeeper)``
    for more information.

    Args:
      rc Return code.
      event Event that caused the watch (often called ``type`` elsewhere).
      stats Connection state.
      path Znode that triggered this watch.

    Does not provide a return value.
    """
    logger.debug('Child watch: (%d, %d, %d, %s)' % (rc, event, state, path))
    zookeeper.aget_children(self.zh, self.zparent, self.watcher,
self.handler)

  def run(self):
    while True:
      pass


def main():
  # Allow Ctrl-C
  signal.signal(signal.SIGINT, signal.SIG_DFL)

  parser = OptionParser()
  parser.add_option('-v', '--verbose',
    dest='verbose',
    default=True,
    action='store_true',
    help='Verbose logging. (default: %default)')
  parser.add_option('--servers',
    dest='servers',
    default='localhost:2181',
    help='Comma-separated list of host:port pairs. (default: %default)')
  global options
  global args
  (options, args) = parser.parse_args()

  if options.verbose:
    logger.setLevel(logging.DEBUG)
  else:
    logger.setLevel(logging.INFO)
  formatter = logging.Formatter("%(asctime)s %(filename)s:%(lineno)d -
%(message)s")
  stream_handler = logging.StreamHandler()
  stream_handler.setFormatter(formatter)
  logger.addHandler(stream_handler)

  zktest = ZKTest()
  zktest.daemon = True
  zktest.start()


if __name__ == '__main__':
  main()


Thanks!
Travis

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message