Index: trunk/Nebulous-Server/lib/Nebulous/Server/Config.pm
===================================================================
--- trunk/Nebulous-Server/lib/Nebulous/Server/Config.pm	(revision 23699)
+++ trunk/Nebulous-Server/lib/Nebulous/Server/Config.pm	(revision 23932)
@@ -8,10 +8,10 @@
 use warnings FATAL => qw( all );
 
-our $VERSION = 0.02;
+our $VERSION = 0.03;
 
 use base qw( Class::Accessor::Fast );
 
 use Log::Log4perl qw( :levels );
-use Params::Validate qw( validate SCALAR );
+use Params::Validate qw( validate validate_pos SCALAR );
 
 our %LEVELS = (
@@ -25,12 +25,19 @@
 );
 
-my $new_validate = {
+my $db_validate = {
+    dbindex       => {
+        type => SCALAR,
+        regex => qr/^\d+$/,
+    },
     dsn         => { type => SCALAR },
     dbuser      => { type => SCALAR },
     dbpasswd    => { type => SCALAR },
-    log_level   => {
+};
+
+my $new_validate = {
+    trace       => {
         type        => SCALAR,
         optional    => 1,
-        default     => 'all',
+        default     => 'fatal',
         callbacks   => {
             'is valid level' => sub {
@@ -39,9 +46,14 @@
         },
     },
+    dsn         => { type => SCALAR, optional => 1 },
+    dbuser      => { type => SCALAR, optional => 1 },
+    dbpasswd    => { type => SCALAR, optional => 1 },
 };
 
 __PACKAGE__->mk_ro_accessors( keys %$new_validate );
 
-sub init {
+
+sub new
+{
     my $class = shift;
 
@@ -49,13 +61,74 @@
 
     # normalize log levels to lower-case
-    $p{ log_level } = lc $p{ log_level };
-
-    my $self = \%p;
+    my $self = { trace => $LEVELS{lc($p{trace})} };
 
     bless $self, $class || ref $class;
+
+    my @dbs;
+    $self->{dbs} = \@dbs;
+
+    if (defined $p{dsn} or defined $p{dbuser} or defined $p{dbpasswd}) {
+        $self->add_db(
+            dbindex     => 0,
+            dsn         => $p{dsn},
+            dbuser      => $p{dbuser},
+            dbpasswd    => $p{dbpasswd},
+        );
+    }
 
     return $self;
 }
 
+
+sub add_db
+{
+    my $self = shift;
+    
+    my %p = validate( @_, $db_validate );
+
+    my $config_db = Nebulous::Server::Config::DB->new({
+        dsn         => $p{dsn},
+        dbuser      => $p{dbuser},
+        dbpasswd    => $p{dbpasswd},
+    });
+
+    $self->{dbs}->[$p{dbindex}] = $config_db;
+
+    return $self;
+}
+
+
+sub db 
+{
+    my $self = shift;
+
+    my ($db_index) = validate_pos( @_, { type => SCALAR, optional => 1, });
+
+    # default to 0
+    $db_index ||= 0;
+
+    return $self->{dbs}->[$db_index];
+}
+
+
+sub n_db 
+{
+    my $self = shift;
+
+    return scalar @{ $self->{dbs} };
+}
+
+
+package Nebulous::Server::Config::DB;
+
+use strict;
+use warnings FATAL => qw( all );
+
+our $VERSION = 0.01;
+
+use base qw( Class::Accessor::Fast );
+
+__PACKAGE__->mk_ro_accessors(qw( dsn dbuser dbpasswd )); 
+
 1;
 
Index: trunk/Nebulous-Server/lib/Nebulous/Server/Log.pm
===================================================================
--- trunk/Nebulous-Server/lib/Nebulous/Server/Log.pm	(revision 23699)
+++ trunk/Nebulous-Server/lib/Nebulous/Server/Log.pm	(revision 23932)
@@ -16,7 +16,7 @@
     my ($self, $config) = @_;
 
-    my $dsn         = $config->dsn;
-    my $dbuser      = $config->dbuser;
-    my $dbpasswd    = $config->dbpasswd;
+#    my $dsn         = $config->db->dsn;
+#    my $dbuser      = $config->db->dbuser;
+#    my $dbpasswd    = $config->db->dbpasswd;
 
     my $conf = <<END;
@@ -30,9 +30,9 @@
 #   date | hostname | priority | method/sub - message\n
 
-    log4perl.appender.SQLLOG            = Log::Log4perl::Appender::DBI
-    log4perl.appender.SQLLOG.datasource = $dsn
-    log4perl.appender.SQLLOG.username   = $dbuser
-    log4perl.appender.SQLLOG.password   = $dbpasswd
-    log4perl.appender.SQLLOG.sql        = \
+#    log4perl.appender.SQLLOG            = Log::Log4perl::Appender::DBI
+#    log4perl.appender.SQLLOG.sql        = \
+#    log4perl.appender.SQLLOG.datasource = 
+#    log4perl.appender.SQLLOG.username   = 
+#    log4perl.appender.SQLLOG.password   = 
     INSERT INTO log (timestamp, hostname, level, sub, message) \
     VALUES          (%d,        %H,       %p,    %M,  %m)
Index: trunk/Nebulous-Server/lib/Nebulous/Server/SOAP.pm
===================================================================
--- trunk/Nebulous-Server/lib/Nebulous/Server/SOAP.pm	(revision 23699)
+++ trunk/Nebulous-Server/lib/Nebulous/Server/SOAP.pm	(revision 23932)
@@ -1,5 +1,5 @@
 # Copyright (c) 2004  Joshua Hoblitt
 #
-# $Id: SOAP.pm,v 1.6 2008-12-14 22:54:25 eugene Exp $
+# $Id: SOAP.pm,v 1.4.32.1 2008-12-14 22:52:37 eugene Exp $
 
 package Nebulous::Server::SOAP;
@@ -17,8 +17,10 @@
 our $AUTOLOAD;
 
-our @args;
+our $config;
 our $neb;
 
-sub new_on_init {
+
+sub new_on_init
+{
     my $self = shift;
 
@@ -27,5 +29,5 @@
     require Apache2::ServerUtil;
 
-    @args = @_;
+    $config = shift;
 
     my $s = Apache2::ServerUtil->server;
@@ -35,13 +37,17 @@
 }
 
-sub init {
+
+sub init
+{
     my $self = shift;
 
-    $neb = Nebulous::Server->new(@args);        
+    $neb = Nebulous::Server->new_from_config($config);        
 
     return Apache2::Const::OK;
 }
 
-sub AUTOLOAD {
+
+sub AUTOLOAD
+{
     my $self = shift;
 
@@ -76,3 +82,4 @@
 }
 
+
 1;
Index: trunk/Nebulous-Server/lib/Nebulous/Server/SQL.pm
===================================================================
--- trunk/Nebulous-Server/lib/Nebulous/Server/SQL.pm	(revision 23699)
+++ trunk/Nebulous-Server/lib/Nebulous/Server/SQL.pm	(revision 23932)
@@ -8,5 +8,5 @@
 use warnings FATAL => qw( all );
 
-our $VERSION = '0.02';
+our $VERSION = '0.04';
 
 use base qw( Class::Accessor::Fast );
@@ -26,6 +26,6 @@
     new_object          => qq{
         INSERT INTO storage_object
-        (so_id, ext_id, type)
-        VALUES (?, ?, 'REG_FILE')
+        (so_id, ext_id, ext_id_basename, type, dir_id)
+        VALUES (?, ?, ?, 'REG_FILE', ?)
     },
     new_object_attr  => qq{
@@ -60,4 +60,16 @@
         USING (so_id)
         WHERE ext_id = ?
+    },
+    get_directory       => qq{
+        SELECT
+            dir_id
+        FROM directory
+        WHERE parent_id = ?
+            AND dirname = ?
+    },
+    new_directory       => qq{
+        INSERT INTO directory
+        (dirname, parent_id)
+        VALUES (?, ?)
     },
     check_object_name => qq{
@@ -297,12 +309,17 @@
             USING(vol_id)
     },
-    find_objects => qq{
-        SELECT *
-        FROM storage_object
-        WHERE ext_id REGEXP ?
+    find_object_by_ext_id => qq{
+        SELECT ext_id, ext_id_basename
+        FROM storage_object
+        WHERE ext_id = ?
+    },
+    find_object_by_dir_id => qq{
+        SELECT ext_id, ext_id_basename
+        FROM storage_object
+        WHERE dir_id = ?
     },
     rename_object => qq{
         UPDATE storage_object
-        SET ext_id = ?
+        SET ext_id = ?, ext_id_basename = ?, dir_id = ?
         WHERE ext_id = ?
     },
@@ -330,4 +347,27 @@
         GROUP BY so_id
         HAVING available_instances < instances OR instances < copies
+    },
+    find_objects_with_extra_instances_by_xattr => qq{
+        SELECT
+            so.so_id,
+            so.ext_id,
+            count(ins_id) as instances,
+            mv.name as volume_name,
+            mv.host as volume_host,
+            count(mv.vol_id) as available_instances,
+            xattr.value as copies
+        FROM storage_object AS so
+        JOIN storage_object_xattr as xattr
+            ON so.so_id = xattr.so_id
+            AND xattr.name = 'user.copies'
+        JOIN instance AS i
+            ON so.so_id = i.so_id
+        JOIN mountedvol AS mv
+            USING(vol_id)
+        WHERE
+            mv.available = 1
+        GROUP BY so_id
+        HAVING available_instances > copies
+        limit 5;
     },
     find_objects_with_extra_instances => qq{
@@ -387,4 +427,5 @@
 DROP TABLE IF EXISTS log;
 DROP TABLE IF EXISTS mountedvol;
+DROP TABLE IF EXISTS directory;
 DROP PROCEDURE IF EXISTS getmountedvol;
 SET FOREIGN_KEY_CHECKS=1
@@ -408,7 +449,25 @@
 
 __DATA__
+CREATE TABLE directory (
+    dir_id BIGINT NOT NULL AUTO_INCREMENT,
+    dirname CHAR(255) NOT NULL,
+    parent_id BIGINT NOT NULL,
+    FOREIGN KEY(parent_id) REFERENCES directory(dir_id),
+    PRIMARY KEY(dir_id),
+    KEY(parent_id)
+) ENGINE=innodb DEFAULT CHARSET=latin1;
+
+###
+
+INSERT INTO directory (dir_id, dirname, parent_id) VALUES (1, '/', 1);
+
+###
+
 CREATE TABLE storage_object (
     so_id BIGINT NOT NULL AUTO_INCREMENT,
     ext_id VARCHAR(255) NOT NULL UNIQUE,
+    ext_id_basename VARCHAR(255) NOT NULL,
+    dir_id BIGINT NOT NULL,
+    FOREIGN KEY(dir_id) REFERENCES directory(dir_id),
     type enum('REG_FILE'),
     PRIMARY KEY(so_id),
