[tahoe-dev] timestamps on mutable files

Brian Warner warner at lothar.com
Wed Jan 6 08:46:07 UTC 2010

Jody Harris wrote:

> IF the mutable file update problem is due to memory use problems with
> downloading the file, keeping it in memory then re-uploading it, then
> (for this use case) it is worth the overhead (to me) for now.
> IF there are other issues that I need to be aware of, please let me
> know.

Nope, it's just a performance issue. Most people believe that changing D
bytes of an existing N-byte mutable file should take
time/memory/bandwidth on the order of "D". But Tahoe's current mutable
files (known as SDMF: Small Distributed Mutable Files) actually cost
those things on the order of "N". I originally imposed the few-MB size
limit to discourage people from using SDMF outside the region of
reasonable performance expectations. Since then, we've found that more
people expressed surprise at an arbitrary size limit than at bad
performance, so we remove the limit.

> Question: Why was the decision made to download the file before
> uploading the new version?

Where are you seeing this behavior? The "tahoe put --mutable" code
should be overwriting the file without first downloading the contents.
There is a "servermap update" step that takes place, but that's only
discovering shares, not downloading them.

Now, in most cases, Tahoe's internal code uses download-then-upload,
because the general use case for mutable files is to perform
read-modify-write transformations, like with a directory listing (stored
in a mutable file) where you're adding a single entry. In this case,
you're adding about 300 bytes to a mutable file that contains about
300*dirsize bytes. The new contents are computed by unpacking the old
contents, changing or adding an entry, then repacking the table. You
can't determine the new contents without first learning the old

Tahoe's internal mutable-file API (available to python code running in
the same process as the node) has two different kinds of write()
operations. The first is read-modify-write, and is defined in
IMutableFileNode.modify (in src/allmydata/interfaces.py, about line
705), in terms of a modifier callback function: the current version of
the file will be downloaded, handed to the modifier callback, and
whatever the callback returns will be uploaded as the new version of the
file. This gives reasonable atomic modification cycles for things like
directory additions and removals, and handles certain race conditions
and multiply-applied idempotent operations by re-applying the semantic
delta. If two people modify the same Tahoe directory at about the same
time, they have an excellent chance of both seeing their desired change

The second operation is called IMutableFileNode.overwrite (line 694),
and skips the download step, for cases where the new version is not
directly derived from the old version. This is more appropriate for your
use of "tahoe put --mutable": your new version is sort-of derived from
the old version, but by means of a bunch of higher-level database
transactions. There's no expectation that two users could modify that
file at the same time and not clobber somebody's changes. So overwrite()
is the best you can do.

>From what I can tell, overwrite() is the only form exposed to the
webapi. Without a way to expose versioninfo to the webapi client, or to
otherwise expose the middle of the read-modify-write cycle, there's no
good way to do anything *but* overwrite here.

So if you're seeing download-then-upload from the "tahoe put --mutable"
command, I'd like to find out why.


More information about the tahoe-dev mailing list