Return-Path: Delivered-To: apmail-hadoop-zookeeper-user-archive@minotaur.apache.org Received: (qmail 42336 invoked from network); 21 Apr 2010 17:38:47 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 21 Apr 2010 17:38:47 -0000 Received: (qmail 45562 invoked by uid 500); 21 Apr 2010 17:38:47 -0000 Delivered-To: apmail-hadoop-zookeeper-user-archive@hadoop.apache.org Received: (qmail 45483 invoked by uid 500); 21 Apr 2010 17:38:46 -0000 Mailing-List: contact zookeeper-user-help@hadoop.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: zookeeper-user@hadoop.apache.org Delivered-To: mailing list zookeeper-user@hadoop.apache.org Received: (qmail 45475 invoked by uid 99); 21 Apr 2010 17:38:46 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 21 Apr 2010 17:38:46 +0000 X-ASF-Spam-Status: No, hits=2.9 required=10.0 tests=HTML_MESSAGE,SPF_NEUTRAL X-Spam-Check-By: apache.org Received-SPF: neutral (nike.apache.org: local policy) Received: from [74.125.82.48] (HELO mail-ww0-f48.google.com) (74.125.82.48) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 21 Apr 2010 17:38:37 +0000 Received: by wwb29 with SMTP id 29so4458663wwb.35 for ; Wed, 21 Apr 2010 10:38:16 -0700 (PDT) MIME-Version: 1.0 Received: by 10.216.90.15 with HTTP; Wed, 21 Apr 2010 10:38:16 -0700 (PDT) In-Reply-To: References: Date: Wed, 21 Apr 2010 10:38:16 -0700 Received: by 10.216.88.68 with SMTP id z46mr982187wee.215.1271871496432; Wed, 21 Apr 2010 10:38:16 -0700 (PDT) Message-ID: Subject: Re: python client structure From: Henry Robinson To: zookeeper-user@hadoop.apache.org Content-Type: multipart/alternative; boundary=0016e6daa82bbeb0bc0484c2a890 X-Virus-Checked: Checked by ClamAV on apache.org --0016e6daa82bbeb0bc0484c2a890 Content-Type: text/plain; charset=ISO-8859-1 > > > The best place for help I was able to find is ``help(zookeeper)`` -- > is there somewhere else I should be looking instead? It looks like you > wrapped the c client, so I also have been looking in zookeeper.h and > trying to infer what's going on. > > zookeeper.h is helpful because, as you say, the Python bindings wrap the C library so the calls and parameters are similar. There is a README bundled with the zkpython code but that is very light on detail! You can also read the source code of the library itself - after ZOOKEEPER-631 gets committed, this should be more useful than the version released with 3.3.0. None of these are any substitute for good documentation, however. I've created https://issues.apache.org/jira/browse/ZOOKEEPER-745 for the purpose of tracking improved documentation, and any contributions or suggestions you want to make on that JIRA would be really appreciated! > > Does this help at all? Let me know if you have any follow on questions. > > Very much so! If I cleanup the sample code below would you want to put > this on a wiki or check in as an example? Would have been nice if > someone already figured this out when I started messing with things :) > > I think it could be very useful as part of the documentation effort - that would be great! cheers, Henry > --travis > > > > > > cheers, > > Henry > > > > On 20 April 2010 23:33, Travis Crawford > wrote: > > > > > 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 > > > > > > > > > > > -- > > Henry Robinson > > Software Engineer > > Cloudera > > 415-994-6679 > -- Henry Robinson Software Engineer Cloudera 415-994-6679 --0016e6daa82bbeb0bc0484c2a890--