robk-tahoe [Sat, 1 Mar 2008 03:12:41 +0000 (20:12 -0700)]
macfuse: slew of updates
various updates to improve the functionality of the mac fuse plugin
1. caching
previously, the experimental tahoefuse plugin pre-loaded the whole
structure of the specified mount into memory at launch time. changes
which were made through that fuse plugin would be remembered, but any
changes made through other tahoe clients would not be reflected.
now directory contents are only loaded when needed, and the data is
cached for a limited time. any use of Directory objects should first
call maybe_refresh() which will check the time since the cache was last
loaded, and if the data is older than some validity period (currently
26s) then the directory's contents will be refetched and reloaded.
this replaces the 'load_dir()' method of TFS
whenever a local change is made to a Directory object, or when the
aforementioned cache reloading notices a change in directory data, the
mtime of the directory is automatically updated.
2. stat / metadata
the retrieval of 'stat' information for getattr(), and the way that
metadata is handled, has been refactored to better reflect the fact that
metadata in tahoe is only represented by 'edges' (i.e entries in
directories) not on 'nodes' (files or directories themselves) hence a
stat lookup should be a query to the parent directory (specifically the
parent specified by the path being queried in the case that a node has
multiple parents) for details known by that directory for the given
child, rather than a query to the child itself.
the TStat utility class for returning stat information to the python-
fuse layer has been extended to accept a 'metadata' argument in its
constructor. any fields found in the metadata dict which match the
names of the stat attributes are loaded into the TStat object. the
'ctime' and 'mtime' attributes are translated to st_ctime and st_mtime
to mesh with the existing timestamp handling code. any fields specified
by kwargs to the constructor override things that might be loaded from
the metadata dict.
Directory objects now track their children as a dict mapping name to
(child_obj, metadata) tuples. This is because the metadata in tahoe
will be stored exclusively on the edges of the graph. each Directory
maintains its own mtime however, and get_stat() calls will report the
mtime of a directory based on the last modification of the Directory
object, not based on any mtime records from the parent directory's
metadata for that child. This addresses the fact that since directories
may be shared, a given parent may or may not reflect the latest changes,
however one of the Finder's behaviours is to examine the stat of a
directory, and not to bother doing a readdir() if the stat is unchanged.
i.e. unless directories report their changes in their stat info, the
Finder will not show changes within that directory.
3. refactoring
reporting of many error codes has been refactored to raise IOError
subclasses with the appropriate errno. this exploits python-fuse's
built-in mechanism for catching IOError and reporting the errno
embedded within it automatically, while simplifying the code within
the plugin.
the add_child() method on TFS was removed in favour of simply having an
add_child() method on Directory objects. this provides a more OO
approach in that Directory is responsible for maintaining its own in
memory state and also writing changes back to the node. similarly for
remove_child()
these changes, along with the new tfs.compose_url() method,
significantly simplify and improve readability of mkdir, rename methods
along with the newer link and unlink. these also get improved error
reporting.
various operations (chmod, chown, truncate, utime) are now ignored.
previously they would report an unsupported operation (EOPNOTSUPP)
but now are simply logged and ignored. this surpresses errors caused
by some client programs which try to use these operations, but at the
moment those operations are meaningless to the tahoe filesystem anyway.
4. link / unlink / rmdir
link, symlink calls are now supported, though with semantics differing
from posix, both equivalent. unlink, rmdir calls are now supported,
also equivalent.
link or symlink calls duplicate the uri of the named source and adds it
as a child of another directory according to the destination path. for
directories, this creates a 'hard' link, i.e. the same directory will
appear in multiple locations within the filesystem, and changes in
any place will be reflected everywhere. for files, by contrast, since
the uri being duplicated is an immutable CHK uri, link/symlink for files
is equivalent to a copy - though significantly cheaper. (a file copy
with the fuse plugin is likely to cause a new file to be written and
uploaded, the link command simply adds an entry referring to an
existing uri)
in testing, the 'ln' command is unable to make hard links (i.e. call
link()) for directories, though symlink ('ln -s') is supported.
either forms works equivalently for files.
unlink and rmdir both remove the specified entry from its parent
directory.
5. logging
the 'tfuse.log' file now only reports launches of the fuse plugin. once
the plugin has parsed the options, it reopens the log file with the
name of the mount, e.g. tfuse.root_dir.log, so that multiple instances
running concurrently will not interfere with each others' logging.
6. bug fixes
the tmp_file in the cache dir backing files opened for write was
intermittently failing to open the file. added O_CREAT to the os.open
call so that files will be created if missing, not throw errors.
a failure to correctly parse arguments if no mount (dir_cap) name was
given but also no fuse options were given has been fixed. now the
command 'tahoe fuse mountpoint' will correctly default to root_dir
also when running from source, arguments to tahoefuse were not handled
to correctly match the 'tahoe fuse ...' behaviour.
wapi: add POST /uri/$DIRECTORY?t=set_children
Unfinished bits: doc in webapi.txt, test handling of badly formed JSON, return reasonable HTTP response, examination of the effect of this patch on code coverage -- but I'm committing it anyway because MikeB can use it and I'm being called to dinner...
test: refactor webist.POSTHandler() to have a method for each "?t=" command
Input validation and decoding is still done in the body of POSTHandler.renderHTTP().
robk-tahoe [Wed, 27 Feb 2008 01:48:22 +0000 (18:48 -0700)]
mac build: ahem. fix makefile probs
oops. I screwed up the makefile syntax further. buildslave would spend a
lot of fruitless time trawling the entire drive. this fixes that. and a
stray -n. ahem. [looks down sheepishly]
robk-tahoe [Wed, 27 Feb 2008 01:20:10 +0000 (18:20 -0700)]
mac build: fix makefile bug
blah $( foo ) is more explicit than blah ` foo ` in a bash-like context
unfortunately it doesn't translate very well to makefiles, for which $(
means something else entirely
robk-tahoe [Wed, 27 Feb 2008 01:08:44 +0000 (18:08 -0700)]
mac build: tweaks to build fuse for 10.4 and 10.5
rather than trying to build a single .app with both 10.4 and 10.5 fuse
libraries embedded within it, for the time being, we're just going to
have independant 10.4 and 10.5 builds.
this provides a 10.5 _fusemodule.so, and build changes to copy the
appropriate versions of files for 10.4 or 10.5 from sub dirs of mac/
into the build tree before triggering py2app
robk-tahoe [Wed, 27 Feb 2008 00:39:07 +0000 (17:39 -0700)]
mac build: make a couple of build dependency hints soft imports
the existing environment on otto requires a few build hints in order for
xml parsing to work properly. these hints are unnecessary, and moreover
their import by depends.py is broken, in the 10.5 environment in which
zandr's buildslave is running.
robk-tahoe [Wed, 27 Feb 2008 00:03:53 +0000 (17:03 -0700)]
mac build: updates to respect UPLOAD_DEST argument to make
the make mac-upload target now requires an UPLOAD_DEST argument to be given,
which is the rsync destination (including trailing '/') to which the version
stamped directory containing the .dmg should be placed. the account the
build is running as (e.g. 'buildslave') should have ssh access to the account
specified in that dest. one might also consider locking the key down to the
target directory by adding something like
command="rsync --server -vlogDtpr . /home/amduser/public_html/dist/mac-blah/"
to the corresponding authorized_key entry on the target machine.
robk-tahoe [Fri, 22 Feb 2008 01:40:04 +0000 (18:40 -0700)]
confwiz: change smb service name to remove 'tahoe'
the name 'tahoe' is in the process of being removed from the windows
installer and binaries. this changes the name of the smb service the
confwiz tries to start to 'Allmydata SMB'
robk-tahoe [Wed, 20 Feb 2008 01:56:59 +0000 (18:56 -0700)]
mac: added 'mount filesystem' action to the mac gui
this adds an action to the dock menu and to the file menu (when visible)
"Mount Filesystem". This action opens a windows offering the user an
opportunity to select from any of the named *.cap files in their
.tahoe/private directory, and choose a corresponding mount point to mount
that at.
it launches the .app binary as a subprocess with the corresponding command
line arguments to launch the 'tahoe fuse' functionality to mount that file
system. if a NAME.icns file is present in .tahoe/private alonside the
chosen NAME.cap, then that icon will be used when the filesystem is mounted.
this is highly unlikely to work when running from source, since it uses
introspection on sys.executable to find the relavent binary to launch in
order to get the right built .app's 'tahoe fuse' functionality.
it is also relatively likely that the code currently checked in, hence
linked into the build, will have as yet unresolved library dependencies.
it's quite unlikely to work on 10.5 with macfuse 1.3.1 at the moment.
robk-tahoe [Wed, 20 Feb 2008 00:18:17 +0000 (17:18 -0700)]
macfuse: move macfuse files around to simplify pythonpath
the mac/macfuse subdirectory needed to be added to the pythonpath in order
to build a binary incorporating the mac fuse system. this change should
make those modules accessible relative to the mac/ directory which is
implicitly included in the .app build process.
robk-tahoe [Wed, 20 Feb 2008 00:16:08 +0000 (17:16 -0700)]
macfuse: rework fuse initialisation, integrate with 'tahoe'
this provides a variety of changes to the macfuse 'tahoefuse' implementation.
most notably it extends the 'tahoe' command available through the mac build
to provide a 'fuse' subcommand, which invokes tahoefuse. this addresses
various aspects of main(argv) handling, sys.argv manipulation to provide an
appropriate command line syntax that meshes with the fuse library's built-
in command line parsing.
this provides a "tahoe fuse [dir_cap_name] [fuse_options] mountpoint"
command, where dir_cap_name is an optional name of a .cap file to be found
in ~/.tahoe/private defaulting to the standard root_dir.cap. fuse_options
if given are passed into the fuse system as its normal command line options
and the mountpoint is checked for existence before launching fuse.
the tahoe 'fuse' command is provided as an additional_command to the tahoe
runner in the case that it's launched from the mac .app binary.
this also includes a tweak to the TFS class which incorporates the ctime
and mtime of files into the tahoe fs model, if available.
robk-tahoe [Wed, 20 Feb 2008 00:05:14 +0000 (17:05 -0700)]
runner: tweaked runner to make it easier to extend with additional subcommands
runner provides the main point of entry for the 'tahoe' command, and
provides various subcommands by default. this provides a hook whereby
additional subcommands can be added in in other contexts, providing a
simple way to extend the (sub)commands space available through 'tahoe'
robk-tahoe [Fri, 15 Feb 2008 03:12:58 +0000 (20:12 -0700)]
confwiz: update the config wiz to open the welcome page
regardless of platform, the confwiz now opens the welcoe page upon
writing a config. it also provides a 'plat' argument (from python's
sys.platform) to help disambiguate our instructions by platform.
robk-tahoe [Fri, 15 Feb 2008 02:44:29 +0000 (19:44 -0700)]
confwiz: add command line options
adds command line option parsing to the confwiz.
the previous --uninstall option behaves as before, but it parsed
more explicitly with the twisted usage library.
added is a --server option, which controls which web site the
backend script for configuration is to be found on. (it is looked
for at /native_client.php on the given server) this option can be
used on conjunction with --uninstall to control where the uninstall
is recorded
Options:
-u, --uninstall record uninstall
-s, --server= url of server to contact
[default: https://beta.allmydata.com/]
e.g. confwiz.py -s https://www-test.allmydata.com/
docs: update install and usage docs, improve cli "usage" output, make new example directories, add unit test that fails code which prints out sentences that don't end with punctuation marks
robk-tahoe [Fri, 15 Feb 2008 01:35:10 +0000 (18:35 -0700)]
macfuse: another tahoe fuse implementation
This is the result of various experimentation done into using python-fuse
to provide access to tahoe on the mac. It's rough in quite a few places,
and is really the result of investigation more than a thorough
implemenation of the fuse api.
upon launch, it looks for the users root_dir by opening ~/.tahoe/node.url
and ~/.tahoe/private/root_dir.cap it then proceeds to cache the directory
structure found by walking the users tahoe drive (safely in the face of
directory loops) into memory and then mounts that filesystem.
when a file is read, it calls the tahoe node to first download the file
into a cache directory (~/.tahoe/_cache) and then serves up the file
from there.
when a file is written, a temporary file is allocated within the tmp dir
of the cache, and upon close() (specifically upon release()) the file is
uploaded to the tahoe node, and the new directory entry written.
note that while the durectory structure is cached into memory only when
the filesystem is mounted, that it is 'write through' i.e. changes made
via fuse are reflected into the underlying tahoe fs, even though changes
made to the tahoe fs otherwise show up only upon restart.
in addition to opening files for read and write, the mkdir() and rename()
calls are supported. most other file system operations are not yet
supported. notably stat() metadata is not currently tracked by tahoe,
and is variably reported by this fs depending on write cache files.
also note that this version does not fully support Finder. access through
normal unix commands such as cat, cp, mv, ls etc works fine, and read
access to file from within finder (including preview images and double-
click to open) work ok. but copies to the tahoe drive from within finder
may or may not succeed, but will always report an error. This is still
under investigation.
also note that this does not include any build integration. the included
_fusemodule.so was built on mac os 10.4 against macfuse 1.3.0, and is
known to not work against 10.5-1.3.1 it's possible it may also contain
dependencies upon parts of macports used to build the python that it was
built against. this will be cleaned up later.
usage:
python tahoefuse.py /Path/to/choice/of/mountpoint
or optionally
python tahoefuse.py -ovolicon=/Path/to/icon.icns /Path/to/mountpoint
upon startup, tahoefuse will walk the tahoe directory, then print a
summary of files and folders found, and then daemonise itself. to exit,
either eject the 'drive' (note: 10.5 doesn't show it as a drive, since
it considers fuse to be a connected server instead) or unmount it via
umount /Path/to/mountpoint etc.
robk-tahoe [Fri, 15 Feb 2008 00:23:07 +0000 (17:23 -0700)]
idlib: make failures much clearer when encountering unicode
while investigating fuse related stuff, I spent quite a while staring at
very cryptic explosions I got from idlib. it turns out that unicode
objects and str objects have .translate() methods with differing signatures.
to save anyone else the headache, this makes it very clear if you accidentally
try to pass a unicode object in to a2b() etc.
robk-tahoe [Thu, 14 Feb 2008 01:17:16 +0000 (18:17 -0700)]
windows installer: remove uninstall tracking, add welcome page
in justin's testing, the uninstall tracking was hanging the uninstall
process (on vista) for now, until we see enough need for it to warrant
more detailed testing/debugging/tweaks, I'm simply disabling the call
to confwiz --uninstall
also this adds a 'welcome page' to the install process. once the user
has installed the windows build, then the installer will open a web
browser to the 'welcome page' on the website ('/welcome_install')
Brian Warner [Wed, 13 Feb 2008 04:28:52 +0000 (21:28 -0700)]
webish.py: fix for #237: when listing large directories, insert a turn break once every 100 children, to work around non-optimized tail recursion Deferreds
use base62 encoding for storage indexes, on disk and in verifier caps, and in logging and diagnostic tools
base62 encoding fits more information into alphanumeric chars while avoiding the troublesome non-alphanumeric chars of base64 encoding. In particular, this allows us to work around the ext3 "32,000 entries in a directory" limit while retaining the convenient property that the intermediate directory names are leading prefixes of the storage index file names.