diff -r 804e1c2b9a40 -r 66beb495a861 lib/ezmlm/listdaemon.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/ezmlm/listdaemon.rb Wed Aug 06 17:24:00 2008 +0000 @@ -0,0 +1,153 @@ +#!/usr/bin/ruby +# +# A DRb interface to one or more ezmlm-idx mailing lists. +# +# == Version +# +# $Id$ +# +# == Authors +# +# * Michael Granger +# * Jeremiah Jordan +# +# :include: LICENSE +# +#--- +# +# Please see the file LICENSE in the base directory for licensing details. +# + +require 'pathname' +require 'ezmlm' +require 'ezmlm/list' +require 'drb' +require 'ostruct' + + +### A DRb interface to one or more ezmlm-idx mailing lists +class Ezmlm::ListDaemon + + # The default port to listen on + DEFAULT_PORT = 32315 + + # The default address to bind to + DEFAULT_ADDRESS = '127.0.0.1' + + + ### The interface that is presented to DRb + class Service + include Enumerable + + ### Create a new service endpoint for the specified +listsdir+, which is a directory + ### which contains ezmlm-idx list directories. + def initialize( listsdir ) + listsdir = Pathname.new( listsdir ) + @listsdir = listsdir + end + + + ###### + public + ###### + + # The directory which contains the list directories that should be served. + attr_reader :listsdir + + + ### Create a new Ezmlm::List object for the list directory with the specified +name+. + def get_list( name ) + name = validate_listdir_name( name ) + return Ezmlm::List.new( self.listsdir + name ) + end + + + ### Iterate over each current list in the Service's listsdir, yielding an Ezmlm::List object + ### for each one. + def each_list( &block ) # :yields: list_object + Ezmlm.each_list( self.listsdir, &block ) + end + alias_method :each, :each_list + + + ####### + private + ####### + + VALID_LISTNAME_PATTERN = /^[a-z0-9.-]+$/i + + ### Ensure that the given +name+ is a valid list name, raising an exception if not. Returns + ### an untainted copy of +name+. + def validate_listdir_name( name ) + unless match = VALID_LISTNAME_PATTERN.match( name ) + raise ArgumentError, "invalid list name %p" % [ name ] + end + + return match[0].untaint + end + + end # class Service + + + + ### Return an OpenStruct that contains the default options + def self::default_options + opts = OpenStruct.new + + opts.bind_addr = DEFAULT_ADDRESS + opts.bind_port = DEFAULT_PORT + opts.debugmode = false + opts.helpmode = false + opts.foreground = false + + return opts + end + + + ################################################################# + ### I N S T A N C E M E T H O D S + ################################################################# + + ### Create a new Ezmlm::ListDaemon that will serve objects for the list directories + ### contained in +listsdir+. The +options+ argument, if given, is an object (such as the one + ### returned from ::default_options) that contains values for the following methods: + ### + ### bind_addr:: + ### The address to bind to. Defaults to DEFAULT_ADDRESS. + ### bind_port:: + ### The port to listen on. Defaults to DEFAULT_PORT. + ### debugmode:: + ### Whether to run in debugging mode, which causes the daemon to run in the foreground + ### and send any output to STDERR. Defaults to +false+. + ### foreground:: + ### Don't go into the background. + def initialize( listsdir, options=nil ) + @service = Service.new( listsdir ) + @options = options || self.class.default_options + end + + + ###### + public + ###### + + # The daemon's configuration options + attr_reader :options + + # The Ezmlm::ListDaemon::Service object that serves as the DRb interface + attr_reader :service + + + ### Daemonize unless configured otherwise, start the DRb service and return the listening + ### Thread object + def start + uri = "druby://%s:%d" % [ self.options.bind_addr, self.options.bind_port ] + DRb.start_service( uri, @service ) + + return DRb.thread + end + + +end # class Ezmlm::ListDaemon + +# vim: set nosta noet ts=4 sw=4: