class Thingfish::Datastore::Filesystem

A hashed-directory hierarchy filesystem datastore for Thingfish

Constants

HASH_DEPTH

The number of subdirectories to use in the hashed directory tree. Must be 2, 4, or 8

REVISION

Version control revision

VERSION

Package version

Attributes

root_path[R]

The root path of the datastore

Public Class Methods

new() click to toggle source

Create a new Filesystem Datastore.

Calls superclass method
# File lib/thingfish/datastore/filesystem.rb, line 41
def initialize
        super
        @root_path = self.class.root_path
        raise ArgumentError, "root path %s does not exist" % [ @root_path ] unless @root_path.exist?
end

Public Instance Methods

fetch( oid ) click to toggle source

Fetch the data corresponding to the given oid as an IOish object.

# File lib/thingfish/datastore/filesystem.rb, line 73
def fetch( oid )
        return self.retrieve( oid )
end
include?( oid ) click to toggle source

Returns true if the datastore has a file for the specified oid.

# File lib/thingfish/datastore/filesystem.rb, line 79
def include?( oid )
        return self.hashed_path( oid ).exist?
end
remove( oid ) click to toggle source

Remove the data associated with oid from the Datastore.

# File lib/thingfish/datastore/filesystem.rb, line 85
def remove( oid )
        return self.hashed_path( oid ).unlink
end
replace( oid, io ) click to toggle source

Replace the existing object associated with oid with the data read from the given io.

# File lib/thingfish/datastore/filesystem.rb, line 92
def replace( oid, io )
        pos = io.pos
        self.store( oid, io )

        return true
ensure
        io.pos = pos if pos
end
save( io ) click to toggle source

Save the data read from the specified io and return an ID that can be used to fetch it later.

# File lib/thingfish/datastore/filesystem.rb, line 60
def save( io )
        oid = make_object_id()

        pos = io.pos
        self.store( oid, io )

        return oid
ensure
        io.pos = pos if pos
end

Protected Instance Methods

hashed_path( oid ) click to toggle source

Generate a Pathname for the file used to store the data for the resource with the specified oid.

# File lib/thingfish/datastore/filesystem.rb, line 133
def hashed_path( oid )
        oid = oid.to_s

        # Split the first 8 characters of the UUID up into subdirectories, one for
        # each HASH_DEPTH
        chunksize = 8 / HASH_DEPTH
        hashed_dir = 0.step( 7, chunksize ).inject( self.root_path ) do |path, i|
                path + oid[i, chunksize]
        end

        return hashed_dir + oid
end
move_spoolfile( source, destination ) click to toggle source

Move the file at the specified source path to the destination path using atomic system calls.

# File lib/thingfish/datastore/filesystem.rb, line 149
def move_spoolfile( source, destination )
        self.log.debug "Moving %s to %s" % [ source, destination ]
        FileUtils.move( source.to_s, destination.to_s )
end
retrieve( oid ) click to toggle source

Look up the file corresponding to the specified oid and return a File for it.

# File lib/thingfish/datastore/filesystem.rb, line 124
def retrieve( oid )
        storefile = self.hashed_path( oid )
        return nil unless storefile.exist?
        return storefile.open( 'r', encoding: 'binary' )
end
spool_to_tempfile( io, storefile ) click to toggle source

Spool the data from the given io to a temporary file based on the specified storefile.

# File lib/thingfish/datastore/filesystem.rb, line 157
def spool_to_tempfile( io, storefile )
        io.rewind

        extension = "-%d.%5f.%s.spool" % [ Process.pid, Time.now.to_f, SecureRandom.hex(6) ]
        spoolfile = storefile.dirname + (storefile.basename.to_s + extension)
        spoolfile.open( IO::EXCL|IO::CREAT|IO::WRONLY, 0600, encoding: 'binary' ) do |fh|
                bytes = IO.copy_stream( io, fh )
                self.log.debug "Copied %d bytes." % [ bytes ]
        end

        return spoolfile
end
store( oid, io ) click to toggle source

Move the file behind the specified io into the datastore.

# File lib/thingfish/datastore/filesystem.rb, line 108
def store( oid, io )
        storefile = self.hashed_path( oid )
        FileUtils.mkpath( storefile.dirname.to_s, :mode => 0711 )

        if io.respond_to?( :path )
                self.move_spoolfile( io.path, storefile )
        else
                self.log.debug "Spooling in-memory upload to %s" % [ storefile.to_s ]
                spoolfile = self.spool_to_tempfile( io, storefile )
                self.move_spoolfile( spoolfile, storefile )
        end
end