Konstantin Stepanov > FusqlFS > FusqlFS::Entry

Download:
FusqlFS-0.009.tar.gz

Dependencies

Annotate this POD

View/Report Bugs
Source  

NAME ^

FusqlFS::Entry - abstract fusqlfs file system entry class

SYNOPSIS ^

    use FusqlFS::Entry;
    use FusqlFS::Backend;

    my $fs = FusqlFS::Backend->new(engine => 'PgSQL', user => 'postgres', database => 'dbname');
    my $entry = FusqlFS::Entry->new($fs, "/tables/sometable/struct/field");
    print $entry->get();
    print $entry->read(0, 10);
    $entry->write($newdata, 0);

DESCRIPTION ^

This class represents file system object in FusqlFS, i.e. all files, directories, symlinks etc. are instances of this class.

This class defines thin convenience layer between database backend and fuse subsystem, providing file path to database artifact resolution and interface between fuse subsystem hooks and actual backend database operations, translating database artifacts storing/dropping/renaming/etc. to correspondent file system operations.

You should never work with this class directly, as it's abstracts from database backend nicely, so you should implement database backends most of time, but this document can be useful if you want to understand what happens behind the scene when file names are converted to real database backend object instances.

Every entry instance keeps following data about file system entry:

  1. Last FusqlFS::Artifact instance found in entry lookup process (see "new" description for more info about entry lookup). This instance is called entry's "package" or "pkg" for short.
  2. All path elements used to lookup next entries with "get" in FusqlFS::Artifact calls. Number of such elements is called entry's "depth".
  3. Cached data about entry contents.
  4. All path elements seen after last FusqlFS::Artifact instance met in lookup process. Number of such elements is called entry's "height".

Beside these data each kind of entry can contain some additional kind-specific data.

METHODS ^

new

File system entry constructor.

Input: $fs, $path, $leaf_absent=undef. Output: $entry_instance.

This constructor is the heart of full file path to actual database artifact object translation. Understanding of this method is the key to understanding the process of finding different database artifacts in file system tree and defining kind of found file system entry (i.e. if it is a plain file, subdirectory, symlink or a pseudopipe).

$fs is the FusqlFS::Backend::Base instance, which represents file system "root". This is an entry point where the search begins. $path is the full path to subject file system object passed to every fuse hook subroutine as first argument.

At first $path is cleaned up from spare /-es and is splitted into path elements. And then it is walked through from head to tail, resolving every path element one by one. If any of elements in the path is absent (except for the last one, which is a special case reviewed a little later), undef is returned, which means file is absent and usually translated to -ENOENT error by hooks in FusqlFS.

The first path element is looked for in $fs->{subpackages}, and any subsequent element is looked for in the last found entry.

Every entry is searched for subsequent path element according following simple rules:

  • If the entry is a hashref or an arrayref, it is a directory, and it must have key (or index) equal to currently parsed path element. If it isn't, undef is returned immediately, otherwise the next entry is found and equal to this hashref's (or arrayref's) value by given key name (or index).
  • If the entry is an FusqlFS::Artifact instance, "get" in FusqlFS::Artifact is called with all gathered path elements used in FusqlFS::Artifact lookup up to this point, and entry is equal to the returned result. If the result is undefined, undef is returned immediately.

    For every FusqlFS::Artifact instance met, path element used to lookup next entry is remembered in a special @names array, so for example /tables/sometable lookup will lead to $fs->{subpackages}->{tables}->get('sometable') invocation, while /tables/sometable/indices/someindex lookup will result in the following chain of calls:

        $fs->{subpackages}->{tables}->get('sometable')->{indices}->get('sometable', 'someindex');
  • If at any iteration except for the last one entry is not a directory, undef is returned, as you can't lookup next path element in anything except subdirectory.
  • On the last iteration the resulting entry type is defined. If the last found entry is a hashref or an arrayref, it will be FusqlFS::Entry::Dir instance and is represented with directory, if it is a scalarref it will be FusqlFS::Entry::Symlink instance and will be visible as symlink, if it is a coderef it will be FusqlFS::Entry::Pipe instance and will be represented with pseudopipe, and if it is a simple scalar it will be FusqlFS::Entry::File instance and will be represented with plain file.

    If the last found entry is an FusqlFS::Artifact instance, its list() method will be called and if its result is not an undef, the entry will be visible as directory, otherwise get() method will be called and the resulting value will be interpreted as described in previous paragraph (but it won't be interpreted as directory anymore).

    If this last entry is undef, undef will be returned unless $leaf_absent argument is given. If it is given and it is not undef, then this entry will be assigned to its value and interpreted as described above. This way you can create new files/directories/etc.

init

Abstract method called on entry initialization.

Input: @path.

This method is called every time after new entry instance is blessed into its class, i.e. just after instance construction.

The @path is the cleaned up and splitted into elements version of $path argument to "new" constructor method. It can be used by this method anyway it might be useful. The return value of this method is ignored.

get

Returns cached entry's content.

Output: $entry_content.

size

Returns size of entry's content.

Output: $entry_length.

list

Returns list of items contained in entry if the entry is a directory, undef otherwise.

Output: $entry_items|undef.

move

Moves entry from one position in files tree to another.

Input: $target.

$target is another target FusqlFS::Entry instance. The original entry is destroyed in process, and target entry becomes identical to original one.

This method is used in rename fuse hook. It is recommended to construct new target entry with defined $leaf_absent argument to "new", as this operation on already existing entry backed up with real database object can be unpredictable or even destructive.

drop

Removes entry from database.

create

Creates new file entry.

store

Stores new data into entry.

Input: $data.

put

Modifies data, returned by FusqlFS::Artifact instance in given tail point.

Input: $data. Output: $success.

The problem this method is to solve is entry instance doesn't always correspond to real FusqlFS::Artifact instance directly, but to some substructure in "subtree" exposed by this instance. But all modification operations are handled by FusqlFS::Artifact, so it is necessary to get whole structure from entry's package, modify it in necessary place and store it back with "store" in FusqlFS::Artifact method call.

And that's what this method does.

It returns true if such complex modification/storage process is required and done, undef otherwise.

tailref

Backbone of different complex entry operations, such as "put" and "move".

Input: $entry=undef, $data=undef. Output: $entry.

This method gets full entry structure, returned by "get" in FusqlFS::Artifact call (defaults to current entry's structure returned with "entry" method), traverses it down to the last tail piece of data, correspondent to the entry instance, modifies it with given data (or removes it altogether if the data is undefined) and returns this modified entry structure back, ready to be passed to "store" in FusqlFS::Artifact method.

isdir, islink, isfile, ispipe

These are entry type identification methods and return true if the entry implements correspondent behavior (i.e. if the entry is directory, symlink, plain file or pseudopipe). Usually only one of these methods returns true, and all the others return undef.

writable

Returns true if the entry is writable.

pkg, names, tail, name, depth

These are properties accessor methods (see "DESCRIPTION" for full list of data kept in entry instance, "new" for description of file path resolution process).

pkg returns last FusqlFS::Artifact instance met in file path traversion (i.e. entry's "package"), names returns list of all path elements used to lookup next entry with "get" in FusqlFS::Artifact call during file path resolution, tail returns list of all path elements met after the last FusqlFS::Artifact instance met, depth and height return number of elements in lists, returned with names and tail methods correspondingly (i.e. entry's "depth" and "height").

entry

Returns not cached entry contents, got with direct call to entry's package get call.

Please mention it can be quite different with what "get" entry's method returns, as get returns only tail file object itself, while entry method returns full data structure got from original FusqlFS::Artifact instance.

For example if you have role's struct entry instance for path /roles/somerole/struct $entry->get() call will give you only struct file content, while $entry->entry() call will bring you full raw role's structure, including all subroles symlinks, "struct" file itself etc.

read, write

Abstract methods implemented primarily for plain files to handle read and write calls.

Read accepts offset and length arguments and returns data part stored in the entry by given coordinates.

Write accepts offset and scalar data buffer and modifies and stores the entry immediately.

All cached write operations must be (and they really are) handled by upper fuse subsystem layer in FusqlFS.

syntax highlighting: