class FuseFS::SqliteMapperFS

Attributes

db[R]

The database connection

db_path[R]

The database file

scan_id[R]

Maintains a count of the number of times through the scan loop

Public Class Methods

new(db_path,sql,options = { },&row_mapper) click to toggle source

@param [String] db_path Path to Sqlite database @param [String] sql query @param [Hash] options see {PathMapperFS#initialize} @yieldparam [Row] row to map @yieldreturn [String,String,Hash<Symbol,Object>] newpath, realpath, options

* newpath - the mapped path
* realpath -  path to the real file
* options -  additional information to store with this path
Calls superclass method FuseFS::PathMapperFS::new
# File lib/fusefs/sqlitemapper.rb, line 28
def initialize(db_path,sql,options = { },&row_mapper)
    @db_path = db_path.to_s
    @sql = sql.to_s
    define_singleton_method(:map_row,row_mapper) if block_given?
    super(options)
end

Public Instance Methods

map_row(row) click to toggle source

Maps a row into a new filepath

@param [Hash] row sqlite result hash for a row @return [String,String,Hash<Symbol,Object>] newpath, realpath, options

* newpath - the mapped path
* realpath -  path to the real file
* options -  additional information to store with this path

@abstract

# File lib/fusefs/sqlitemapper.rb, line 43
def map_row(row)
    raise NotImplementedError, "abstract method #{__method__} not implemented"
end
mounted() click to toggle source

FuseFS callback when the filesystem is mounted Starts the scanning loop and performs the initial scan @api FuseFS

# File lib/fusefs/sqlitemapper.rb, line 50
def mounted()
    @mounted = true
    @mutex = Mutex.new
    @cv = ConditionVariable.new
    @scan_thread = Thread.new() { scan_loop() }
end
rescan() click to toggle source

Trigger a rescan of the database

# File lib/fusefs/sqlitemapper.rb, line 69
def rescan()
    @mutex.synchronize { @cv.signal() }
end
scan() click to toggle source

Executes the sql query and passes each row to map_row (or the block passed in {#initialize})

Subclasses can override this method for pre/post scan processing, calling super as required

# File lib/fusefs/sqlitemapper.rb, line 76
def scan()
    db.execute(@sql) do |row|
        new_path, real_path, options =  map_row(row)
        options ||= {}
        options[:sqlite_scan_id] = @scan_id
        begin
            map_file(new_path, real_path, options)
        rescue StandardError => e
            puts e
            puts e.backtrace.join("\n")
        end
    end
    cleanup() { |file_node| file_node.options[:sqlite_scan_id] != @scan_id }
end
sighup() click to toggle source

Rescan on HUP signal

# File lib/fusefs/sqlitemapper.rb, line 92
def sighup
  rescan()
end
unmounted() click to toggle source

FuseFS callback when filesystem is unmounted

Stops the database watching threads @api FuseFS

# File lib/fusefs/sqlitemapper.rb, line 61
def unmounted()
    @mounted = false
    @mutex.synchronize { @cv.signal() }
    @scan_thread.join
end

Private Instance Methods

scan_loop() click to toggle source
# File lib/fusefs/sqlitemapper.rb, line 98
def scan_loop()
    @mutex.synchronize() do
        @scan_id = 0
        while @mounted
            begin
                @db = SQLite3::Database.new(@db_path,:readonly => true)
                @db.results_as_hash = true
                @db.busy_timeout(10000)
                @scan_id = @scan_id + 1
                scan()
            rescue StandardError => e
                puts e
                puts e.backtrace.join("\n")
            ensure
                @db.close unless @db.closed?
                @db = nil
            end
            @cv.wait(@mutex) 
        end
    end
end