couchdb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Antony Blakey <>
Subject Re: Simple erlang plugins (was Re: couch_gen_btree: pluggable storage / tree engines)
Date Mon, 02 Feb 2009 06:39:45 GMT

On 02/02/2009, at 4:46 PM, Chris Anderson wrote:

> On Sun, Feb 1, 2009 at 9:40 PM, Antony Blakey  
> <> wrote:
>> There are command line options for manipulating the list of  
>> plugins. By
>> default it will load plugins from /etc/couchdb/plugins/ or whatever  
>> your
>> localconfdir is - mine is always relative - but this can be  
>> controlled by
>> the options:
>> -C      clean the plugins list
>> -D      add all the plugins in $DEFAULT_PLUGIN_DIR
>> -G DIR  add all the plugins in DIR
>> -P DIR  add the plugin DIR
>> Bit light on testing, I wanted to show how trivial it is.
> Thanks for getting started on this. It looks like with a make plugins
> target, this will be ready to roll.

I think there are multiple levels of modularity possible - some core  
features could be plugins, purely in a separation-of-concerns kind of  
way. Then there would be third-party plugins. This could be a  
convenient way to play with some new contributions without having to  
merge into the a single code directory (assuming each plugin is  
separate in the source). And finally there would be per-user plugins  
that customize couch on a per-app basis.

I assume you mean a make plugins target for core plugins?

> One thing I don't understand is the plugins list and the additional
> command-line options to launch script. I wonder if there's a
> non-ephemeral way to control the list of loaded plugins.

Well, there is the default location. If a plugin were to have an  
extension e.g. '.plugin' then the activation could be controlled via  
renaming. OTOH I like the Apache (httpd) mechanism of having  
'available/active' dirs, which seems cleaner.

I use the command line options to the startup script because I have  
couchdb/erlang/icu etc packaged as ruby gems that deploys couch using  
dependcies, and the class that controls couchdb allows multiple  
instances in self-contained locations. It looks a bit like this:


require 'memetic'
require 'memetic-erlang'
require 'memetic-spidermonkey'
require 'memetic-icu'

module Memetic

   class CouchDB

     DIRECTORY = %x{cd #{File.dirname(File.dirname(__FILE__)) + "/ 
BUILD"} ; pwd}.split()[0]

     def CouchDB.configure_environment(env)

     def initialize(local_directory)
       @local_directory = local_directory
       Dir.mkdir(@local_directory) unless File.exists?(@local_directory)

       @log_directory = "#{@local_directory}/log"
       Dir.mkdir(@log_directory) unless File.exists?(@log_directory)

       @data_directory = "#{@local_directory}/data"
       Dir.mkdir(@data_directory) unless File.exists?(@data_directory)"#{@local_directory}/configuration.ini", "w") do |f|
         f << configuration()


     def start
       env =
       cmd = env.as_command_prefix
       cmd << "( cd '#{DIRECTORY}' ; "
       cmd << "./bin/couchdb -b "
       cmd << "-o '#{@log_directory}/couchdb.stdout' "
       cmd << "-e '#{@log_directory}/couchdb.stderr' "
       cmd << "-p '#{@local_directory}/pid' "
       cmd << "-c './etc/couchdb/default.ini' "
       cmd << "-c '#{@local_directory}/configuration.ini' "
       #cmd << "-G '#{@local_directory}/plugins' "
       cmd << " )"
       IO.popen(cmd) do |p|
         s = p.gets
         s.chomp if s

     def status
       env =
       IO.popen("#{env.as_command_prefix} #{DIRECTORY}/bin/couchdb -p  
#{@local_directory}/pid -s") do |p|
         s = p.gets
         s.chomp if s

     def stop
       env =
       IO.popen("#{env.as_command_prefix} #{DIRECTORY}/bin/couchdb -p  
#{@local_directory}/pid -d") do |p|
         s = p.gets
         s.chomp if s

     def configuration
       return <<END_OF_STRING
database_dir = #{@data_directory}

file = #{@log_directory}/couch.log
level = debug




> As far as configuration, users will likely also want to configure
> their API endpoints as http_db_handlers or http_global_handlers. These
> allow you to hook an Erlang function directly to a CouchDB path.


I imagined that the ini file in the plugin directory wouldn't be  
modified by users i.e. that's "part of the plugin". Users would modify  
the local.ini file to change the user-configurable parts of that. That  
makes me think that the startup script should load local.*.ini, so you  
can separate your per-plugin user-configurable bits. The reason for  
not modifying the plugin.ini directly is so that you can update them  

Antony Blakey
CTO, Linkuistics Pty Ltd
Ph: 0438 840 787

A reasonable man adapts himself to suit his environment. An  
unreasonable man persists in attempting to adapt his environment to  
suit himself. Therefore, all progress depends on the unreasonable man.
   -- George Bernard Shaw

View raw message