Index: /trunk/Nebulous-Server/docs/design.txt
===================================================================
--- /trunk/Nebulous-Server/docs/design.txt	(revision 4942)
+++ /trunk/Nebulous-Server/docs/design.txt	(revision 4943)
@@ -1,119 +1,138 @@
-# Copryight (C) 2004  Joshua Hoblitt
+# Copyright (C) 2004-2005  Joshua Hoblitt
 #
-# $Id: design.txt,v 1.1.1.1 2004-12-22 02:16:23 jhoblitt Exp $
-
-Terminology
---
-    - Storage Object
-There is one Storage Object per resource (a file) that is being managed by the
-IPP Pixel Data Server.  A Storage Object maps an External Identifier (eg.
-file name) to a Storage ID that is internal to the IPP Pixel Data Server.  In
-addition, creation time and comments may be stored in a Storage Object.
-Storage Objects /do not/ contain the storage location of a resource as we need
-to allow for N copies of a resource to be stored.  The actual storage location
-of a resource is held in a Storage Object Instance, which maps to a Storage ID
-in a many-to-one relationship.
-
-    - [Storage Object] Instance
+# $Id: design.txt,v 1.2 2005-09-02 04:20:29 jhoblitt Exp $
+
+Overview
+--
+
+Nebulous is a user-space distributed object (file) storage system.  The system
+is distributed in the sense of it's data storage model where objects are stored
+across a number of storage volumes and may have redundant copies.  While IPC
+is done in the traditional client/server model with a single[1] centralized
+server containing all storage object meta-data.  This system was designed,
+unlike most distributed filesystems, specifically so that Nebulous clients
+could also host one or more storage volumes. Although, there is no requirement
+that clients also provide storage space.  If you so choose, clients and the
+storage volumes can reside on independent hardware.
+
+There are 4 principle components required for a working Nebulous system;
+server, client, data transport, and data storage.  The Nebulous system only
+provides the server and the client software.  Data transport[2] and Data
+storage are left to 3rd party software packages.  As this function is typically
+included with most operation system it is unlikely that those specific
+technologies can be improved upon.
+
+[1] Multiple Nebulous servers should be possible via database replication.
+[2] A future version of Nebulous may include it's own data transport layer
+based on the WEB DAV protocol.
+
+Client <-> Server IPC
+--
+
+The Nebulous Server and clients communicate via the SOAP protocol.  Since SOAP
+is platform independent this allows native Nebulous client to be written in a
+variety of languages.  With in the Nebulous Server itself the IPC mechanism is
+abstracted to allow ether multi-protocol support or complete replacement of
+SOAP by another protocol.
+
+XXX SOAP namespace
+
+Data model
+--
+
+In Nebulous terminology a file is refereed to as a a resource.  Each resource
+is represented inside the Nebulous Server as a "Storage Object".  There is one
+Storage Object per resource (a file) that is being managed by the Nebulous
+Server.  A Storage Object maps an External Identifier (eg. filename) to a
+Storage ID.  In addition, creation time and comments may be stored in a
+Storage Object.  Storage Objects /do not/ contain the storage location of a
+resource as we need to allow for N copies of a resource to be stored.  The
+actual storage location of a resource is held in a Storage Object Instance,
+which maps to a Storage ID in a many-to-one relationship.
+
 A Storage Object Instance, or just Instance, represents a single copy of a
-resource being managed by the IPP Pixel Data Server. An Instance contains an
-Instance ID, the location of the resource as a URI, a checksum of the
-resource, a Storage ID, a read lock semaphore (unsigned integer), a write lock
-mutex (enum( 'write', 'wait', 'free' ) - is this better then using an int and
-constants?), and a UTC timestamp of the last modification date & time.
-
-    - Lock Record
-A Lock Record is used to double check the indicated lock state of an Instance
-and can be used to identify system failures.  It must contain the Instance ID
-of of the locked instance and the type of lock, eg, enum( 'read', 'write').
+resource being managed by the Nebulous Server. An Instance contains an
+Instance ID, the parent Storage ID, the location of the resource as a URI, and
+other assorted meta-data.
+
+Storage IDs are a signed 64-bit integer.  Negative values are considered
+reserved for future use.  Allocation should be incremental and, as we are
+unlikely to exceed 2^63 Storage Objects in the life time of the project, never
+reused. Instance IDs follow the same scheme as Storage IDs but exists in a
+unique namespace.
+
+Database record relationships
+--
+* All Storage Objects must have at least once associated Instance.
+
+* All Instances must be associated with a Storage Object.
+
+* All Instances must be associated with a valid URI (file exists).
+
+* All Storage Objects with locks set must have the correct number of
+corresponding Lock Records.
+
+* All Lock Records must be associated with a Storage Object.
+
+Data transport
+--
+XXX
+
+Data Storage
+--
+XXX
+
+Storage volume state tracking.
+
+Nebulous itself does not attempt to determine the state of storage volumes.
+Instead, it relies on some 3rd party to determine both the state
+(available/not) and capacity (total size + % utilized).  This information is
+then feed into Nebulous via either the administrative API or CLI management
+tools.
+
+XXX Storage Location determination
+
 
 Locking semantics
 --
-A lock is required to either read from or write to a Storage Object Instance
-being managed by the IPP Pixel Data Server.  Stated another way, locking
-granularity is managed on the level of Storage Object Instances instead of on
-the more abstract Storage Objects.  Although, from the client perspective,
-operations are carried out on a Storage Object.   The locking state of a
-Storage Object Instance is maintained by in the Storage Object Instance and a
-Lock Record.
-
-Two types of locks are used on an Instance, a semaphore is used to track read
-locks and an exclusive mutex is for write locking.
+Nebulous uses 'advisory locking' where clients are excepted to check for the
+existence of locks but this policy is not enforced.  Locks are set on a
+Storage Object and apply to all Instances of that object.
+
+Two types of locks can be set; 'read' locks and 'write' locks.  Read locks are
+implemented as a semaphore while write locks use an exclusive mutex.
 
     - Read lock
-In order to read from a Storage Object Instance the Read Lock semaphore must
-first be incremented by one and a Lock Record created.  After the read is
-completed the Lock Record must be deleted and the Read Lock semaphore
-decremented by one.  The incrementation of the Read Lock and Lock Record
-creation or the decrementation of the Read Lock and the Lock Record deletion
-must happen atomically.  A Read lock can not be aquired unless the Write mutex
-is in the state of 'free'.  If a Read lock can not be aquired, a client must
-not "spin lock" on the Instanace ID as it may be in the process of being
-removed.  Instead, the "spin lock" should be re-resolving the external
-identifier to a Storage ID, and the Storage ID to Storage Instances.
+In order to obtain a Read Lock on a Storage Object the Write Lock mutex must
+be in the state of 'free'.  When a Read Lock is acquire the Read semaphore is
+incremented by one.  When a Read Lock is released the Read semaphore is
+decremented by one.  This must happen atomically with the
+creation/destruction of a Lock Record.
 
     - Write lock
-In order to obtain a Write lock on a Storage Object Instance the Write Lock
-mutex must be in the state of 'free' and the Read lock semaphore must have a
-value of zero.  A client should either "spin lock" or fail if all the Lock
-mutex is set or the Read Semaphore has a non-zero value.  A Lock Record must
-be created atomically with the setting of the Write mutex.  The setting of the
-Write mutex and Lock Record insertion or the clearing of the Write mutex and
-the Lock Record deletion must happen atomically.  If the Write lock has a
-state of 'free' and the Read lock has a non-zero value, the Write lock may be
-set to the 'wait' state to prevent new Read locks from being aquired.
-
-Storage Object Operations
---
-    - Add
-The resource must already be on disk (having been named through some sort of
-mechanism to generate new filenames).  A new Storage Object must be created with a new/unqiue  Storage ID and has
-an associated with an External Identifier.  At least one Instance must be
-created atomicaly at the same time.  Each new Instance must be initially created with a Write lock.
-The resource may then be written to it's storage location.  When the writing
-of the resource is completed the Write lock must be cleared as early as is
-feasible.  The association of an External Identifier must wait until Instance
-creation is completed
-
-    - Delete
-In order to remove a Storage Object, a Write lock must be obtained on
-/all/ associated Instances.  Then the resources are removed.  As each resource
-is deleted the corresponding Instance must be deleted.  After all Instances are
-removed the Storage Object must then be deleted.
-
-    - Update
-Storage Object Instances are not truly written to.  Instead, a new set of
-Storage Object Instances and a new Storage Object are created in parallel.
-
-Write locks must be aquired on all the orignal Intances of a Storage Object.
-Then an Add operation is performed to create a new Storage Object and
-associated Instances.  Then the External Identifier must be atomically moved
-from the original Storage Object to the new Storage Object.  After the
-External Identifier migration, the original Storage Object and it's Instances
-should be removed with a special case of the Delete operation (one that will
-operate on already held locks).  If the old Storage Object is merely
-abandoned, ie. it still exists but doesn't have an External Identifier, it and
-the associated Instances will be removed during the next Consistency Sweep.
-If a Delete is not peformed, the Write locks on the orignal Instances must be
-released. [use a dead Storage Object table or flag, similar to mark and sweep
-garbage collection?]
-
-    - Move
-This is the same operation as an Update except the new Instances are identical
-to the old.
-
-    - Open
-Sets a Read lock on an Instances of a Storage Object and determines it's
-storage location.  A Read lock must only be placed on one Instance of a
-Storage Object.  All Instances of a Storage Object should be iterated through
-in a "spin lock" until a Read lock is aquired.
-
-    - Close
-Releases a Read lock aquired with open.
-
-The lock must be released as soon as is feasible.
-
-Lock sweeping
---
+In order to obtain a Write lock on a Storage Object the Write Lock mutex must
+be in the state of 'free' and the Read lock semaphore must have a value of
+zero.  When a Write Lock is acquired the Write mutex is set to 'write'.  When a
+Write Lock is released the Write mutex is set to to 'free'.  This must happen
+atomically with the creation/destruction of a Lock Record.  As an extension, a
+sate of 'wait' may be implemented such that clients waiting on Read Locks to
+be released may prevent any additional Read Locks from being acquired.
+
+XXX Lock Records are currently unimplemented
+    - Lock Records A Lock Record is used to double check the indicated lock
+      state of a Storage Object and can be used to identify logical system
+errors.  A Lock Record contains the Storage ID of the object and the type of
+lock set.  eg, enum( 'read', 'write').
+
+    - Client best practices
+When attempting to acquire a lock a client should either "spin lock" with a
+reasonable pause between lock attempts or fail completely.  Aggressive "spin
+locking" is considered antisocial and may eventually require the Nebulous
+Server to identify and ignore such clients.
+
+
+House keeping
+--
+    - Lock sweeping
 In the event that a Storage Object operation fails to complete successfully
 stale locks will have to be identified and removed from the IPP Pixel Data
@@ -129,35 +148,106 @@
 Record entries themselves must be removed from the lock table.
 
-Consistency sweeping
---
+    - Consistency sweeping
 Periodically the IPP Pixel Data Server meta-data and Storage Object will need
 to be checked for sanity.  This would be similar to running fsck on a modern
 filesystem.  Consistency sweeping should include Lock sweeping and should be
-considered a superset.
-
-All Storage Objects must have at least once associated Instance.
-
-All Storage Object Instances must be associated with a Storage Object.
-
-All Storage Object Instances with a lock set must have the correct number of
-corresponding Lock Records.
-
-All Lock Records must be plausible, ie. the Instance pointed at must be in a
-corresponding state.
-
-Storage ID Allocation
---
-Storage IDs are a signed 64-bit integer.  Negative values are considered
-reserved for future use.  Allocation should be incremental and, as we are
-unlikely to exceed 2^63 Storage Objects in the life time of the project, never
-reused.
-
-Allocated via [SQL auto-increment/stored procedure/app server?]
-
-Instance ID Allocation
---
-Indentical to a Storage ID but exists in a unique namespace.
-
-Storage Location determination
---
-???
+considered a super-set.
+
+
+Server Operations
+--
+    - setup
+    - create_object
+    - rename_object
+        XXX unimplemented
+    - replicate object
+    - lock_object
+    - unlock_object
+    - find_instances
+    - delete_instance
+    - split_instance
+        XXX unimplemented
+    - stat_object
+    - stat_instance
+        XXX unimplemented
+
+Client Operations
+--
+    - create
+Creates and opens new Storage Object
+
+    - replicate
+Adds an Instance to a Storage Object
+
+    - cull
+Removes an Instance from a Storage Object
+
+This operation can not remove the last Instance of a Storage Object.
+
+    - lock
+Trys to acquire a lock on a storage object
+
+This operation times out after a default interval of 10s.
+
+    - unlock
+Trys to release a lock on a storage object
+    
+    - find_instances
+Find all instances of a storage object
+
+Only Instances on active storage volumes are found.
+
+    - find
+Find any instance of a storage object
+
+Only Instances on active storage volumes are found.
+
+    - open
+Open a storage object for read or write
+
+Opening a storage object as 'write' will remove all but one Instance to
+prevent Instances from becoming inconsistent.
+
+    - delete
+Delete a storage object and all of it's instances
+
+Removes a storage object and all of it's instances by sequentially deleting each
+Instance.  When a Storage Object has no more associated instances it is
+automatically removed by the Nebulous server.
+
+    - copy
+Copy a storage object
+
+The new storage object will be created with only one Instance.  Most properties
+of the source Storage Object will be preserved.
+
+    - move
+Rename a storage object
+
+Currently this operation will remove all but one instance of the storage
+object and may change it's storage location.
+
+    - delete_instance
+    
+Remove a storage object instance
+
+Removing the last Instance of a Storage Object will destroy the Storage
+Object.
+
+    - stat
+View the properties of a storage object
+
+
+    - import
+        XXX unimplemented
+Import a file into Nebulous
+
+Creates a new Storage Object with the specified External Identifier.  The
+source file will then be "copied" into the Nebulous system leaving the original
+file unmodified.
+
+    - fission
+        XXX unimplemented
+Create a new Storage Object from an existing one by either splitting off an
+Instance and re-parenting it or by cloning an existing Instance and associating
+it with the new Storage Object.
Index: /trunk/Nebulous-Server/docs/setup.txt
===================================================================
--- /trunk/Nebulous-Server/docs/setup.txt	(revision 4942)
+++ /trunk/Nebulous-Server/docs/setup.txt	(revision 4943)
@@ -25,6 +25,8 @@
     mkdir /po03/nebulous
     mkdir /po04/nebulous
-    chown nobody:nebulous /po0?/nebulous
-    chmod 0770 /po0?/nebulous
+    perl -e 'for (1..24) { $i = sprintf "po%02d", $_ ; mkdir "/$i/nebulous" }'
+    chown nobody:nebulous /po??/nebulous
+    chmod 0770 /po??/nebulous
+    ls -lad /po??/nebulous
 
 =head2 Build and install the Nebulous Perl modules (see: README)
@@ -174,4 +176,6 @@
     neb-addvol --name po03 --uri file:/po03/nebulous
     neb-addvol --name po04 --uri file:/po04/nebulous
+
+    perl -e 'for (1..24) { $i = sprintf "po%02d", $_ ; system "neb-addvol --name $i --uri file:/$i/nebulous" }'
     .
     .
Index: /trunk/Nebulous/docs/design.txt
===================================================================
--- /trunk/Nebulous/docs/design.txt	(revision 4942)
+++ /trunk/Nebulous/docs/design.txt	(revision 4943)
@@ -1,119 +1,138 @@
-# Copryight (C) 2004  Joshua Hoblitt
+# Copyright (C) 2004-2005  Joshua Hoblitt
 #
-# $Id: design.txt,v 1.1.1.1 2004-12-22 02:16:23 jhoblitt Exp $
-
-Terminology
---
-    - Storage Object
-There is one Storage Object per resource (a file) that is being managed by the
-IPP Pixel Data Server.  A Storage Object maps an External Identifier (eg.
-file name) to a Storage ID that is internal to the IPP Pixel Data Server.  In
-addition, creation time and comments may be stored in a Storage Object.
-Storage Objects /do not/ contain the storage location of a resource as we need
-to allow for N copies of a resource to be stored.  The actual storage location
-of a resource is held in a Storage Object Instance, which maps to a Storage ID
-in a many-to-one relationship.
-
-    - [Storage Object] Instance
+# $Id: design.txt,v 1.2 2005-09-02 04:20:29 jhoblitt Exp $
+
+Overview
+--
+
+Nebulous is a user-space distributed object (file) storage system.  The system
+is distributed in the sense of it's data storage model where objects are stored
+across a number of storage volumes and may have redundant copies.  While IPC
+is done in the traditional client/server model with a single[1] centralized
+server containing all storage object meta-data.  This system was designed,
+unlike most distributed filesystems, specifically so that Nebulous clients
+could also host one or more storage volumes. Although, there is no requirement
+that clients also provide storage space.  If you so choose, clients and the
+storage volumes can reside on independent hardware.
+
+There are 4 principle components required for a working Nebulous system;
+server, client, data transport, and data storage.  The Nebulous system only
+provides the server and the client software.  Data transport[2] and Data
+storage are left to 3rd party software packages.  As this function is typically
+included with most operation system it is unlikely that those specific
+technologies can be improved upon.
+
+[1] Multiple Nebulous servers should be possible via database replication.
+[2] A future version of Nebulous may include it's own data transport layer
+based on the WEB DAV protocol.
+
+Client <-> Server IPC
+--
+
+The Nebulous Server and clients communicate via the SOAP protocol.  Since SOAP
+is platform independent this allows native Nebulous client to be written in a
+variety of languages.  With in the Nebulous Server itself the IPC mechanism is
+abstracted to allow ether multi-protocol support or complete replacement of
+SOAP by another protocol.
+
+XXX SOAP namespace
+
+Data model
+--
+
+In Nebulous terminology a file is refereed to as a a resource.  Each resource
+is represented inside the Nebulous Server as a "Storage Object".  There is one
+Storage Object per resource (a file) that is being managed by the Nebulous
+Server.  A Storage Object maps an External Identifier (eg. filename) to a
+Storage ID.  In addition, creation time and comments may be stored in a
+Storage Object.  Storage Objects /do not/ contain the storage location of a
+resource as we need to allow for N copies of a resource to be stored.  The
+actual storage location of a resource is held in a Storage Object Instance,
+which maps to a Storage ID in a many-to-one relationship.
+
 A Storage Object Instance, or just Instance, represents a single copy of a
-resource being managed by the IPP Pixel Data Server. An Instance contains an
-Instance ID, the location of the resource as a URI, a checksum of the
-resource, a Storage ID, a read lock semaphore (unsigned integer), a write lock
-mutex (enum( 'write', 'wait', 'free' ) - is this better then using an int and
-constants?), and a UTC timestamp of the last modification date & time.
-
-    - Lock Record
-A Lock Record is used to double check the indicated lock state of an Instance
-and can be used to identify system failures.  It must contain the Instance ID
-of of the locked instance and the type of lock, eg, enum( 'read', 'write').
+resource being managed by the Nebulous Server. An Instance contains an
+Instance ID, the parent Storage ID, the location of the resource as a URI, and
+other assorted meta-data.
+
+Storage IDs are a signed 64-bit integer.  Negative values are considered
+reserved for future use.  Allocation should be incremental and, as we are
+unlikely to exceed 2^63 Storage Objects in the life time of the project, never
+reused. Instance IDs follow the same scheme as Storage IDs but exists in a
+unique namespace.
+
+Database record relationships
+--
+* All Storage Objects must have at least once associated Instance.
+
+* All Instances must be associated with a Storage Object.
+
+* All Instances must be associated with a valid URI (file exists).
+
+* All Storage Objects with locks set must have the correct number of
+corresponding Lock Records.
+
+* All Lock Records must be associated with a Storage Object.
+
+Data transport
+--
+XXX
+
+Data Storage
+--
+XXX
+
+Storage volume state tracking.
+
+Nebulous itself does not attempt to determine the state of storage volumes.
+Instead, it relies on some 3rd party to determine both the state
+(available/not) and capacity (total size + % utilized).  This information is
+then feed into Nebulous via either the administrative API or CLI management
+tools.
+
+XXX Storage Location determination
+
 
 Locking semantics
 --
-A lock is required to either read from or write to a Storage Object Instance
-being managed by the IPP Pixel Data Server.  Stated another way, locking
-granularity is managed on the level of Storage Object Instances instead of on
-the more abstract Storage Objects.  Although, from the client perspective,
-operations are carried out on a Storage Object.   The locking state of a
-Storage Object Instance is maintained by in the Storage Object Instance and a
-Lock Record.
-
-Two types of locks are used on an Instance, a semaphore is used to track read
-locks and an exclusive mutex is for write locking.
+Nebulous uses 'advisory locking' where clients are excepted to check for the
+existence of locks but this policy is not enforced.  Locks are set on a
+Storage Object and apply to all Instances of that object.
+
+Two types of locks can be set; 'read' locks and 'write' locks.  Read locks are
+implemented as a semaphore while write locks use an exclusive mutex.
 
     - Read lock
-In order to read from a Storage Object Instance the Read Lock semaphore must
-first be incremented by one and a Lock Record created.  After the read is
-completed the Lock Record must be deleted and the Read Lock semaphore
-decremented by one.  The incrementation of the Read Lock and Lock Record
-creation or the decrementation of the Read Lock and the Lock Record deletion
-must happen atomically.  A Read lock can not be aquired unless the Write mutex
-is in the state of 'free'.  If a Read lock can not be aquired, a client must
-not "spin lock" on the Instanace ID as it may be in the process of being
-removed.  Instead, the "spin lock" should be re-resolving the external
-identifier to a Storage ID, and the Storage ID to Storage Instances.
+In order to obtain a Read Lock on a Storage Object the Write Lock mutex must
+be in the state of 'free'.  When a Read Lock is acquire the Read semaphore is
+incremented by one.  When a Read Lock is released the Read semaphore is
+decremented by one.  This must happen atomically with the
+creation/destruction of a Lock Record.
 
     - Write lock
-In order to obtain a Write lock on a Storage Object Instance the Write Lock
-mutex must be in the state of 'free' and the Read lock semaphore must have a
-value of zero.  A client should either "spin lock" or fail if all the Lock
-mutex is set or the Read Semaphore has a non-zero value.  A Lock Record must
-be created atomically with the setting of the Write mutex.  The setting of the
-Write mutex and Lock Record insertion or the clearing of the Write mutex and
-the Lock Record deletion must happen atomically.  If the Write lock has a
-state of 'free' and the Read lock has a non-zero value, the Write lock may be
-set to the 'wait' state to prevent new Read locks from being aquired.
-
-Storage Object Operations
---
-    - Add
-The resource must already be on disk (having been named through some sort of
-mechanism to generate new filenames).  A new Storage Object must be created with a new/unqiue  Storage ID and has
-an associated with an External Identifier.  At least one Instance must be
-created atomicaly at the same time.  Each new Instance must be initially created with a Write lock.
-The resource may then be written to it's storage location.  When the writing
-of the resource is completed the Write lock must be cleared as early as is
-feasible.  The association of an External Identifier must wait until Instance
-creation is completed
-
-    - Delete
-In order to remove a Storage Object, a Write lock must be obtained on
-/all/ associated Instances.  Then the resources are removed.  As each resource
-is deleted the corresponding Instance must be deleted.  After all Instances are
-removed the Storage Object must then be deleted.
-
-    - Update
-Storage Object Instances are not truly written to.  Instead, a new set of
-Storage Object Instances and a new Storage Object are created in parallel.
-
-Write locks must be aquired on all the orignal Intances of a Storage Object.
-Then an Add operation is performed to create a new Storage Object and
-associated Instances.  Then the External Identifier must be atomically moved
-from the original Storage Object to the new Storage Object.  After the
-External Identifier migration, the original Storage Object and it's Instances
-should be removed with a special case of the Delete operation (one that will
-operate on already held locks).  If the old Storage Object is merely
-abandoned, ie. it still exists but doesn't have an External Identifier, it and
-the associated Instances will be removed during the next Consistency Sweep.
-If a Delete is not peformed, the Write locks on the orignal Instances must be
-released. [use a dead Storage Object table or flag, similar to mark and sweep
-garbage collection?]
-
-    - Move
-This is the same operation as an Update except the new Instances are identical
-to the old.
-
-    - Open
-Sets a Read lock on an Instances of a Storage Object and determines it's
-storage location.  A Read lock must only be placed on one Instance of a
-Storage Object.  All Instances of a Storage Object should be iterated through
-in a "spin lock" until a Read lock is aquired.
-
-    - Close
-Releases a Read lock aquired with open.
-
-The lock must be released as soon as is feasible.
-
-Lock sweeping
---
+In order to obtain a Write lock on a Storage Object the Write Lock mutex must
+be in the state of 'free' and the Read lock semaphore must have a value of
+zero.  When a Write Lock is acquired the Write mutex is set to 'write'.  When a
+Write Lock is released the Write mutex is set to to 'free'.  This must happen
+atomically with the creation/destruction of a Lock Record.  As an extension, a
+sate of 'wait' may be implemented such that clients waiting on Read Locks to
+be released may prevent any additional Read Locks from being acquired.
+
+XXX Lock Records are currently unimplemented
+    - Lock Records A Lock Record is used to double check the indicated lock
+      state of a Storage Object and can be used to identify logical system
+errors.  A Lock Record contains the Storage ID of the object and the type of
+lock set.  eg, enum( 'read', 'write').
+
+    - Client best practices
+When attempting to acquire a lock a client should either "spin lock" with a
+reasonable pause between lock attempts or fail completely.  Aggressive "spin
+locking" is considered antisocial and may eventually require the Nebulous
+Server to identify and ignore such clients.
+
+
+House keeping
+--
+    - Lock sweeping
 In the event that a Storage Object operation fails to complete successfully
 stale locks will have to be identified and removed from the IPP Pixel Data
@@ -129,35 +148,106 @@
 Record entries themselves must be removed from the lock table.
 
-Consistency sweeping
---
+    - Consistency sweeping
 Periodically the IPP Pixel Data Server meta-data and Storage Object will need
 to be checked for sanity.  This would be similar to running fsck on a modern
 filesystem.  Consistency sweeping should include Lock sweeping and should be
-considered a superset.
-
-All Storage Objects must have at least once associated Instance.
-
-All Storage Object Instances must be associated with a Storage Object.
-
-All Storage Object Instances with a lock set must have the correct number of
-corresponding Lock Records.
-
-All Lock Records must be plausible, ie. the Instance pointed at must be in a
-corresponding state.
-
-Storage ID Allocation
---
-Storage IDs are a signed 64-bit integer.  Negative values are considered
-reserved for future use.  Allocation should be incremental and, as we are
-unlikely to exceed 2^63 Storage Objects in the life time of the project, never
-reused.
-
-Allocated via [SQL auto-increment/stored procedure/app server?]
-
-Instance ID Allocation
---
-Indentical to a Storage ID but exists in a unique namespace.
-
-Storage Location determination
---
-???
+considered a super-set.
+
+
+Server Operations
+--
+    - setup
+    - create_object
+    - rename_object
+        XXX unimplemented
+    - replicate object
+    - lock_object
+    - unlock_object
+    - find_instances
+    - delete_instance
+    - split_instance
+        XXX unimplemented
+    - stat_object
+    - stat_instance
+        XXX unimplemented
+
+Client Operations
+--
+    - create
+Creates and opens new Storage Object
+
+    - replicate
+Adds an Instance to a Storage Object
+
+    - cull
+Removes an Instance from a Storage Object
+
+This operation can not remove the last Instance of a Storage Object.
+
+    - lock
+Trys to acquire a lock on a storage object
+
+This operation times out after a default interval of 10s.
+
+    - unlock
+Trys to release a lock on a storage object
+    
+    - find_instances
+Find all instances of a storage object
+
+Only Instances on active storage volumes are found.
+
+    - find
+Find any instance of a storage object
+
+Only Instances on active storage volumes are found.
+
+    - open
+Open a storage object for read or write
+
+Opening a storage object as 'write' will remove all but one Instance to
+prevent Instances from becoming inconsistent.
+
+    - delete
+Delete a storage object and all of it's instances
+
+Removes a storage object and all of it's instances by sequentially deleting each
+Instance.  When a Storage Object has no more associated instances it is
+automatically removed by the Nebulous server.
+
+    - copy
+Copy a storage object
+
+The new storage object will be created with only one Instance.  Most properties
+of the source Storage Object will be preserved.
+
+    - move
+Rename a storage object
+
+Currently this operation will remove all but one instance of the storage
+object and may change it's storage location.
+
+    - delete_instance
+    
+Remove a storage object instance
+
+Removing the last Instance of a Storage Object will destroy the Storage
+Object.
+
+    - stat
+View the properties of a storage object
+
+
+    - import
+        XXX unimplemented
+Import a file into Nebulous
+
+Creates a new Storage Object with the specified External Identifier.  The
+source file will then be "copied" into the Nebulous system leaving the original
+file unmodified.
+
+    - fission
+        XXX unimplemented
+Create a new Storage Object from an existing one by either splitting off an
+Instance and re-parenting it or by cloning an existing Instance and associating
+it with the new Storage Object.
Index: /trunk/Nebulous/docs/setup.txt
===================================================================
--- /trunk/Nebulous/docs/setup.txt	(revision 4942)
+++ /trunk/Nebulous/docs/setup.txt	(revision 4943)
@@ -25,6 +25,8 @@
     mkdir /po03/nebulous
     mkdir /po04/nebulous
-    chown nobody:nebulous /po0?/nebulous
-    chmod 0770 /po0?/nebulous
+    perl -e 'for (1..24) { $i = sprintf "po%02d", $_ ; mkdir "/$i/nebulous" }'
+    chown nobody:nebulous /po??/nebulous
+    chmod 0770 /po??/nebulous
+    ls -lad /po??/nebulous
 
 =head2 Build and install the Nebulous Perl modules (see: README)
@@ -174,4 +176,6 @@
     neb-addvol --name po03 --uri file:/po03/nebulous
     neb-addvol --name po04 --uri file:/po04/nebulous
+
+    perl -e 'for (1..24) { $i = sprintf "po%02d", $_ ; system "neb-addvol --name $i --uri file:/$i/nebulous" }'
     .
     .
