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
The root path of the datastore
Public Class Methods
Create a new Filesystem
Datastore.
# 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 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
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 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 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 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
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 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
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 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
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