fsdb 0.6.0 → 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +6 -0
- data/README.txt +1 -1
- data/lib/fsdb/database.rb +1 -1
- data/rakefile +5 -3
- data/test/test-concurrency.rb +5 -3
- data/test/test-formats.rb +3 -1
- data/test/test-fsdb.rb +5 -3
- metadata +10 -148
- data/junk/OLDRakefile +0 -98
- data/junk/OLDRakefile2 +0 -55
- data/junk/check-cache.rb +0 -18
- data/junk/create-lock.rb +0 -25
- data/junk/doc/old-api/classes/FSDB.html +0 -139
- data/junk/doc/old-api/classes/FSDB/Database.html +0 -953
- data/junk/doc/old-api/classes/FSDB/Database.src/M000029.html +0 -16
- data/junk/doc/old-api/classes/FSDB/Database.src/M000030.html +0 -16
- data/junk/doc/old-api/classes/FSDB/Database.src/M000031.html +0 -16
- data/junk/doc/old-api/classes/FSDB/Database.src/M000032.html +0 -16
- data/junk/doc/old-api/classes/FSDB/Database.src/M000033.html +0 -33
- data/junk/doc/old-api/classes/FSDB/Database.src/M000034.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Database.src/M000035.html +0 -22
- data/junk/doc/old-api/classes/FSDB/Database.src/M000036.html +0 -16
- data/junk/doc/old-api/classes/FSDB/Database.src/M000037.html +0 -22
- data/junk/doc/old-api/classes/FSDB/Database.src/M000038.html +0 -43
- data/junk/doc/old-api/classes/FSDB/Database.src/M000039.html +0 -25
- data/junk/doc/old-api/classes/FSDB/Database.src/M000040.html +0 -43
- data/junk/doc/old-api/classes/FSDB/Database.src/M000041.html +0 -23
- data/junk/doc/old-api/classes/FSDB/Database.src/M000042.html +0 -22
- data/junk/doc/old-api/classes/FSDB/Database.src/M000043.html +0 -16
- data/junk/doc/old-api/classes/FSDB/Database.src/M000044.html +0 -16
- data/junk/doc/old-api/classes/FSDB/Database.src/M000045.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Database.src/M000046.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Database.src/M000047.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Database.src/M000048.html +0 -16
- data/junk/doc/old-api/classes/FSDB/Database.src/M000049.html +0 -71
- data/junk/doc/old-api/classes/FSDB/Database.src/M000050.html +0 -43
- data/junk/doc/old-api/classes/FSDB/Database.src/M000051.html +0 -53
- data/junk/doc/old-api/classes/FSDB/Database.src/M000052.html +0 -44
- data/junk/doc/old-api/classes/FSDB/Database.src/M000053.html +0 -39
- data/junk/doc/old-api/classes/FSDB/Database.src/M000054.html +0 -72
- data/junk/doc/old-api/classes/FSDB/Database.src/M000055.html +0 -39
- data/junk/doc/old-api/classes/FSDB/Database.src/M000056.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Database.src/M000057.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Database.src/M000058.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Database.src/M000059.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Database.src/M000060.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Database.src/M000061.html +0 -23
- data/junk/doc/old-api/classes/FSDB/Database.src/M000062.html +0 -23
- data/junk/doc/old-api/classes/FSDB/Database.src/M000063.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Database.src/M000064.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Database/AbortedTransaction.html +0 -118
- data/junk/doc/old-api/classes/FSDB/Database/CreateFileError.html +0 -120
- data/junk/doc/old-api/classes/FSDB/Database/DirIsImmutableError.html +0 -117
- data/junk/doc/old-api/classes/FSDB/Database/DirNotEmptyError.html +0 -117
- data/junk/doc/old-api/classes/FSDB/Database/FormatError.html +0 -117
- data/junk/doc/old-api/classes/FSDB/Database/MissingFileError.html +0 -117
- data/junk/doc/old-api/classes/FSDB/Database/MissingObjectError.html +0 -117
- data/junk/doc/old-api/classes/FSDB/Database/NotDirError.html +0 -118
- data/junk/doc/old-api/classes/FSDB/Database/PathComponentError.html +0 -120
- data/junk/doc/old-api/classes/FSDB/DatabaseDebuggable.html +0 -148
- data/junk/doc/old-api/classes/FSDB/DatabaseDebuggable.src/M000005.html +0 -21
- data/junk/doc/old-api/classes/FSDB/DatabaseDebuggable.src/M000007.html +0 -21
- data/junk/doc/old-api/classes/FSDB/DirectoryIterators.html +0 -210
- data/junk/doc/old-api/classes/FSDB/DirectoryIterators.src/M000006.html +0 -22
- data/junk/doc/old-api/classes/FSDB/DirectoryIterators.src/M000007.html +0 -22
- data/junk/doc/old-api/classes/FSDB/DirectoryIterators.src/M000008.html +0 -22
- data/junk/doc/old-api/classes/FSDB/DirectoryIterators.src/M000009.html +0 -22
- data/junk/doc/old-api/classes/FSDB/DirectoryIterators.src/M000010.html +0 -22
- data/junk/doc/old-api/classes/FSDB/DirectoryIterators.src/M000011.html +0 -22
- data/junk/doc/old-api/classes/FSDB/DirectoryIterators.src/M000012.html +0 -22
- data/junk/doc/old-api/classes/FSDB/DirectoryIterators.src/M000013.html +0 -22
- data/junk/doc/old-api/classes/FSDB/ForkSafely.html +0 -126
- data/junk/doc/old-api/classes/FSDB/Modex.html +0 -237
- data/junk/doc/old-api/classes/FSDB/Modex.src/M000024.html +0 -21
- data/junk/doc/old-api/classes/FSDB/Modex.src/M000025.html +0 -30
- data/junk/doc/old-api/classes/FSDB/Modex.src/M000026.html +0 -21
- data/junk/doc/old-api/classes/FSDB/Modex.src/M000027.html +0 -30
- data/junk/doc/old-api/classes/FSDB/Modex.src/M000028.html +0 -44
- data/junk/doc/old-api/classes/FSDB/Modex.src/M000029.html +0 -26
- data/junk/doc/old-api/classes/FSDB/Modex.src/M000030.html +0 -48
- data/junk/doc/old-api/classes/FSDB/Modex/ForkSafely.html +0 -105
- data/junk/doc/old-api/classes/FSDB/Mutex.html +0 -244
- data/junk/doc/old-api/classes/FSDB/Mutex.src/M000018.html +0 -19
- data/junk/doc/old-api/classes/FSDB/Mutex.src/M000019.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Mutex.src/M000020.html +0 -19
- data/junk/doc/old-api/classes/FSDB/Mutex.src/M000021.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Mutex.src/M000022.html +0 -23
- data/junk/doc/old-api/classes/FSDB/Mutex.src/M000023.html +0 -30
- data/junk/doc/old-api/classes/FSDB/Mutex.src/M000024.html +0 -26
- data/junk/doc/old-api/classes/FSDB/Mutex.src/M000025.html +0 -21
- data/junk/doc/old-api/classes/FSDB/Mutex/ForkSafely.html +0 -105
- data/junk/doc/old-api/classes/FSDB/PathUtilities.html +0 -257
- data/junk/doc/old-api/classes/FSDB/PathUtilities.src/M000012.html +0 -23
- data/junk/doc/old-api/classes/FSDB/PathUtilities.src/M000013.html +0 -18
- data/junk/doc/old-api/classes/FSDB/PathUtilities.src/M000014.html +0 -23
- data/junk/doc/old-api/classes/FSDB/PathUtilities.src/M000015.html +0 -18
- data/junk/doc/old-api/classes/FSDB/PathUtilities.src/M000016.html +0 -18
- data/junk/doc/old-api/classes/FSDB/PathUtilities.src/M000017.html +0 -22
- data/junk/doc/old-api/classes/FSDB/PathUtilities.src/M000018.html +0 -23
- data/junk/doc/old-api/classes/FSDB/PathUtilities.src/M000019.html +0 -18
- data/junk/doc/old-api/classes/FSDB/PathUtilities/InvalidPathError.html +0 -111
- data/junk/doc/old-api/classes/File.html +0 -272
- data/junk/doc/old-api/classes/File.src/M000001.html +0 -17
- data/junk/doc/old-api/classes/File.src/M000002.html +0 -17
- data/junk/doc/old-api/classes/File.src/M000003.html +0 -20
- data/junk/doc/old-api/classes/File.src/M000004.html +0 -20
- data/junk/doc/old-api/classes/File.src/M000005.html +0 -32
- data/junk/doc/old-api/classes/File.src/M000006.html +0 -32
- data/junk/doc/old-api/created.rid +0 -1
- data/junk/doc/old-api/files/README.html +0 -112
- data/junk/doc/old-api/files/RELEASE-NOTES.html +0 -233
- data/junk/doc/old-api/files/fsdb_txt.html +0 -888
- data/junk/doc/old-api/files/lib/fsdb/database_rb.html +0 -115
- data/junk/doc/old-api/files/lib/fsdb/file-lock_rb.html +0 -109
- data/junk/doc/old-api/files/lib/fsdb/modex_rb.html +0 -121
- data/junk/doc/old-api/files/lib/fsdb/mutex_rb.html +0 -108
- data/junk/doc/old-api/files/lib/fsdb/util_rb.html +0 -108
- data/junk/doc/old-api/fr_class_index.html +0 -47
- data/junk/doc/old-api/fr_file_index.html +0 -34
- data/junk/doc/old-api/fr_method_index.html +0 -90
- data/junk/doc/old-api/index.html +0 -24
- data/junk/doc/old-api/rdoc-style.css +0 -208
- data/junk/file-lock-nb.rb +0 -15
- data/junk/fl.rb +0 -144
- data/junk/flock-test.rb +0 -39
- data/junk/fsdb.kateproject +0 -47
- data/junk/fsdb.prj +0 -196
- data/junk/fsdb.sf +0 -46
- data/junk/insert-dir.rb +0 -48
- data/junk/lock-test-bug.rb +0 -150
- data/junk/lock-test-too-simple.rb +0 -136
- data/junk/lock-test.rb +0 -151
- data/junk/mkrdoc +0 -7
- data/junk/restore-fsdb.rb +0 -37
- data/junk/rf.txt +0 -5
- data/junk/solaris-bug-fixed.rb +0 -184
- data/junk/solaris-bug.rb +0 -182
- data/junk/solaris-bug.txt +0 -43
- data/junk/sync.rb +0 -327
- data/junk/test-file-lock.html +0 -86
- data/junk/test-file-lock.rb +0 -84
- data/junk/test-processes.rb +0 -131
- data/junk/test-threads.rb +0 -113
- data/junk/wiki-mutex.rb +0 -108
- data/misc/fsdb-blorubu.txt +0 -47
- data/misc/mtime-and-file-id.txt +0 -23
- data/misc/posixlock.txt +0 -148
@@ -1,888 +0,0 @@
|
|
1
|
-
<?xml version="1.0" encoding="iso-8859-1"?>
|
2
|
-
<!DOCTYPE html
|
3
|
-
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
4
|
-
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
5
|
-
|
6
|
-
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
7
|
-
<head>
|
8
|
-
<title>File: fsdb.txt</title>
|
9
|
-
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
10
|
-
<meta http-equiv="Content-Script-Type" content="text/javascript" />
|
11
|
-
<link rel="stylesheet" href=".././rdoc-style.css" type="text/css" media="screen" />
|
12
|
-
<script type="text/javascript">
|
13
|
-
// <![CDATA[
|
14
|
-
|
15
|
-
function popupCode( url ) {
|
16
|
-
window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
|
17
|
-
}
|
18
|
-
|
19
|
-
function toggleCode( id ) {
|
20
|
-
if ( document.getElementById )
|
21
|
-
elem = document.getElementById( id );
|
22
|
-
else if ( document.all )
|
23
|
-
elem = eval( "document.all." + id );
|
24
|
-
else
|
25
|
-
return false;
|
26
|
-
|
27
|
-
elemStyle = elem.style;
|
28
|
-
|
29
|
-
if ( elemStyle.display != "block" ) {
|
30
|
-
elemStyle.display = "block"
|
31
|
-
} else {
|
32
|
-
elemStyle.display = "none"
|
33
|
-
}
|
34
|
-
|
35
|
-
return true;
|
36
|
-
}
|
37
|
-
|
38
|
-
// Make codeblocks hidden by default
|
39
|
-
document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
|
40
|
-
|
41
|
-
// ]]>
|
42
|
-
</script>
|
43
|
-
|
44
|
-
</head>
|
45
|
-
<body>
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
<div id="fileHeader">
|
50
|
-
<h1>fsdb.txt</h1>
|
51
|
-
<table class="header-table">
|
52
|
-
<tr class="top-aligned-row">
|
53
|
-
<td><strong>Path:</strong></td>
|
54
|
-
<td>fsdb.txt
|
55
|
-
</td>
|
56
|
-
</tr>
|
57
|
-
<tr class="top-aligned-row">
|
58
|
-
<td><strong>Last Update:</strong></td>
|
59
|
-
<td>Tue Mar 14 11:20:07 PST 2006</td>
|
60
|
-
</tr>
|
61
|
-
</table>
|
62
|
-
</div>
|
63
|
-
<!-- banner header -->
|
64
|
-
|
65
|
-
<div id="bodyContent">
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
<div id="contextContent">
|
70
|
-
|
71
|
-
<div id="description">
|
72
|
-
<h1>What is <a href="../classes/FSDB.html">FSDB</a>?</h1>
|
73
|
-
<p>
|
74
|
-
<a href="../classes/FSDB.html">FSDB</a> is a file system data base. <a
|
75
|
-
href="../classes/FSDB.html">FSDB</a> provides a thread-safe, process-safe
|
76
|
-
Database class which uses the native file system as its back end and allows
|
77
|
-
multiple file formats and serialization methods. Users access objects in
|
78
|
-
terms of their paths relative to the base directory of the database.
|
79
|
-
It’s very light weight (the state of a Database is essentially just a
|
80
|
-
path string, and code size is very small, under 1K lines, all ruby).
|
81
|
-
</p>
|
82
|
-
<p>
|
83
|
-
<a href="../classes/FSDB.html">FSDB</a> stores bundles of ruby objects at
|
84
|
-
nodes in the file system. Each bundle is saved and restored as a whole, so
|
85
|
-
internal references persist as usual. These bundles are the atoms of
|
86
|
-
transactions. References between bundles are handled through path strings.
|
87
|
-
The format of each bundle on disk can vary; format classes for plain text
|
88
|
-
strings, marshalled data, and yaml data are included, but <a
|
89
|
-
href="../classes/FSDB.html">FSDB</a> can easily be extended to recognize
|
90
|
-
other formats, both binary and text. <a
|
91
|
-
href="../classes/FSDB.html">FSDB</a> treats directories as collections and
|
92
|
-
provides directory iterator methods.
|
93
|
-
</p>
|
94
|
-
<p>
|
95
|
-
<a href="../classes/FSDB.html">FSDB</a> has been tested on a variety of
|
96
|
-
platforms and ruby versions, and is not known to have any problems. (On
|
97
|
-
WindowsME/98/95, multiple processes can access a database unsafely, because
|
98
|
-
flock() is not available on the platform.) See the Testing section for
|
99
|
-
details.
|
100
|
-
</p>
|
101
|
-
<p>
|
102
|
-
<a href="../classes/FSDB.html">FSDB</a> does not yet have any indexing or
|
103
|
-
querying mechanisms, and is probably missing many other useful database
|
104
|
-
features, so it is not a general replacement for RDBs or OODBs. However, if
|
105
|
-
you are looking for a lightweight, concurrent object store with reasonable
|
106
|
-
performance and better granularity than PStore, in pure Ruby, with a Ruby
|
107
|
-
license, take a look at <a href="../classes/FSDB.html">FSDB</a>. Also, if
|
108
|
-
you are looking for an easy way of making an existing file tree look like a
|
109
|
-
database, especially if it has heterogeneous file formats, <a
|
110
|
-
href="../classes/FSDB.html">FSDB</a> might be useful.
|
111
|
-
</p>
|
112
|
-
<h2>Installation</h2>
|
113
|
-
<pre>
|
114
|
-
ruby install.rb config
|
115
|
-
ruby install.rb setup
|
116
|
-
ruby install.rb install
|
117
|
-
</pre>
|
118
|
-
<h2>Synopsis</h2>
|
119
|
-
<pre>
|
120
|
-
require 'fsdb'
|
121
|
-
|
122
|
-
db = FSDB::Database.new('/tmp/my-data')
|
123
|
-
|
124
|
-
db['recent-movies/myself'] = ["LOTR II", "Austin Powers"]
|
125
|
-
puts db['recent-movies/myself'][0] # ==> "LOTR II"
|
126
|
-
|
127
|
-
db.edit 'recent-movies/myself' do |list|
|
128
|
-
list << "A la recherche du temps perdu"
|
129
|
-
end
|
130
|
-
</pre>
|
131
|
-
<h2>Path names</h2>
|
132
|
-
<p>
|
133
|
-
Keys in the database are path strings, which are simply strings in the
|
134
|
-
usual forward-slash delimited format, relative to the database’s
|
135
|
-
directory. There are some points to be aware of when using them to refer to
|
136
|
-
database objects.
|
137
|
-
</p>
|
138
|
-
<ul>
|
139
|
-
<li>Paths to directories are formed in one of two ways:
|
140
|
-
|
141
|
-
<ul>
|
142
|
-
<li>explicitly, with a trailing slash, as in <tt>db[‘foo/’]</tt>
|
143
|
-
|
144
|
-
</li>
|
145
|
-
<li>implicitly, as in <tt>db[‘foo’]</tt> if foo is already a
|
146
|
-
directory, or as in <tt>db[‘foo/bar’]</tt>, which creates
|
147
|
-
<tt>‘foo’</tt> if it did not already exist.
|
148
|
-
|
149
|
-
</li>
|
150
|
-
</ul>
|
151
|
-
<p>
|
152
|
-
The root dir of the database is simply <tt>/</tt>, its child directories
|
153
|
-
are of the form <tt>foo/</tt> and so on. The leading and trailing slashes
|
154
|
-
are both optional.
|
155
|
-
</p>
|
156
|
-
</li>
|
157
|
-
<li>Objects can be stored in various formats, indicated by path name. A typical
|
158
|
-
mapping might be:
|
159
|
-
|
160
|
-
<table>
|
161
|
-
<tr><td valign="top"><tt>foo.obj</tt>:</td><td>Marshalled data (the default for unrecognized extension)
|
162
|
-
|
163
|
-
</td></tr>
|
164
|
-
<tr><td valign="top"><tt>foo.txt</tt>:</td><td>String
|
165
|
-
|
166
|
-
</td></tr>
|
167
|
-
<tr><td valign="top"><tt>foo/</tt>:</td><td>Directory (the contents is presented to the caller as a list of file and
|
168
|
-
subdirectory paths that can be used in browse, edit, etc.)
|
169
|
-
|
170
|
-
</td></tr>
|
171
|
-
<tr><td valign="top"><tt>foo.yml</tt>:</td><td>YAML data—see examples/yaml.rb
|
172
|
-
|
173
|
-
</td></tr>
|
174
|
-
</table>
|
175
|
-
<p>
|
176
|
-
New formats, which correlate filename pattern with serialization behavior,
|
177
|
-
can be defined and plugged in to databases. Each format has its own rules
|
178
|
-
for matching patterns in the file name and recognizing the file. Patterns
|
179
|
-
can be anything with a #=== method (such as a regex). See
|
180
|
-
lib/fsdb/formats.rb examples of defining formats. For examples of
|
181
|
-
associating formats with patterns, see examples/formats.rb.
|
182
|
-
</p>
|
183
|
-
</li>
|
184
|
-
<li>Different notations for the same path, such as
|
185
|
-
|
186
|
-
<pre>
|
187
|
-
/foo/bar
|
188
|
-
foo/bar
|
189
|
-
foo//bar
|
190
|
-
foo/../foo/bar
|
191
|
-
</pre>
|
192
|
-
<p>
|
193
|
-
work correctly, as do paths that denote hard or soft links, if supported on
|
194
|
-
the platform.
|
195
|
-
</p>
|
196
|
-
<p>
|
197
|
-
Links are subject to the same naming convention as normal files with regard
|
198
|
-
to format identification: format is determined by the path within the
|
199
|
-
database used to access the object. Using a different name for a link can
|
200
|
-
be useful if you need to access the file using two different formats (e.g.,
|
201
|
-
plain text via ‘foo.txt’ and tabular data via
|
202
|
-
‘foo.table’ or whatever).
|
203
|
-
</p>
|
204
|
-
</li>
|
205
|
-
<li>Accessing objects in a database is unaffected by the current dir of your
|
206
|
-
process. The database knows it’s own absolute path, and path
|
207
|
-
arguments to the Database API are interpreted relative to that. If you want
|
208
|
-
to work with a subdirectory of the database, and paths relative to that,
|
209
|
-
use Database#subdb:
|
210
|
-
|
211
|
-
<pre>
|
212
|
-
db = Database.new['/tmp']
|
213
|
-
db['foo/bar'] = 1
|
214
|
-
foo = db.subdb('foo')
|
215
|
-
foo['bar'] # ==> 1
|
216
|
-
</pre>
|
217
|
-
</li>
|
218
|
-
<li>Paths that are outside the database (’../../zap’) are allowed,
|
219
|
-
but may or may not be desirable. Use valid? and validate in util.rb to
|
220
|
-
check for them.
|
221
|
-
|
222
|
-
</li>
|
223
|
-
<li>Directories are created when needed. So db[‘a/b/c’] = 1 creates
|
224
|
-
two dirs and one file.
|
225
|
-
|
226
|
-
</li>
|
227
|
-
<li>Files beginning with ’..’ are ignored by fsdb dir iterators,
|
228
|
-
though they can still be accessed in transaction operators. Some such files
|
229
|
-
(<tt>..fsdb.meta.<filename></tt>) are used internally. All others
|
230
|
-
<em>not</em> beginning with <tt>..fsdb</tt> are reserved for applications
|
231
|
-
to use.
|
232
|
-
|
233
|
-
<p>
|
234
|
-
The <tt>..fsdb.meta.<filename></tt> file holds a version number for
|
235
|
-
<filename>, which is used along with mtime to check for changes
|
236
|
-
(mtime usually has a precision of only 1 second). In the future, the file
|
237
|
-
may also be used to hold other metadata. (The meta file is only created
|
238
|
-
when a file is written to and does not need to be created in advance when
|
239
|
-
using existing files as a <a href="../classes/FSDB.html">FSDB</a>.)
|
240
|
-
</p>
|
241
|
-
</li>
|
242
|
-
<li>util.rb has directory iterators, path globbing, and other useful tools.
|
243
|
-
|
244
|
-
</li>
|
245
|
-
</ul>
|
246
|
-
<h2>Transactions</h2>
|
247
|
-
<p>
|
248
|
-
<a href="../classes/FSDB.html">FSDB</a> transactions are thread-safe and
|
249
|
-
process-safe. They can be nested for larger-grained transactions; it is the
|
250
|
-
user’s responsibility to avoid deadlock.
|
251
|
-
</p>
|
252
|
-
<p>
|
253
|
-
<a href="../classes/FSDB.html">FSDB</a> is ACID
|
254
|
-
(atomic/consistent/isolated/durable) to the extent that the underlying file
|
255
|
-
system is. For instance, when an object that has been modified in a
|
256
|
-
transaction is written to the file system, nothing persistent is changed
|
257
|
-
until the final system call to write the data to the OS’s buffers. If
|
258
|
-
there is an interruption (e.g., a power failure) while the OS flushes those
|
259
|
-
buffers to disk, data will not be consistent. If this bothers you, you may
|
260
|
-
want to use a journaling file system. <a
|
261
|
-
href="../classes/FSDB.html">FSDB</a> does not need to do its own journaling
|
262
|
-
because of the availability of good journaling file systems.
|
263
|
-
</p>
|
264
|
-
<p>
|
265
|
-
There are two kinds of transactions:
|
266
|
-
</p>
|
267
|
-
<ul>
|
268
|
-
<li>A simple transfer of a value, as in <tt>db[‘x’]</tt> and
|
269
|
-
<tt>db[‘x’] = 1</tt>.
|
270
|
-
|
271
|
-
<p>
|
272
|
-
Note that a sequence of such transactions is not itself a transaction, and
|
273
|
-
can be affected by other processes and threads.
|
274
|
-
</p>
|
275
|
-
<pre>
|
276
|
-
db['foo/bar'] = [1,2,3]
|
277
|
-
db['foo/bar'] += [4] # This is actually 2 transactions
|
278
|
-
db['foo/bar'][-1]
|
279
|
-
</pre>
|
280
|
-
<p>
|
281
|
-
It is possible for the result of these transactions to be <tt>4</tt>. But,
|
282
|
-
if other threads or processes are scheduled during this code fragment, the
|
283
|
-
result could be a completely different value, or the code could raise an
|
284
|
-
method-missing exception because the object at the path has been replaced
|
285
|
-
with one that does not have the <tt>+</tt> method or the <tt>[ ]</tt>
|
286
|
-
method. The four operations are atomic by themselves, but the sequence is
|
287
|
-
not.
|
288
|
-
</p>
|
289
|
-
<p>
|
290
|
-
Note that changes to a database object using this kind of transaction
|
291
|
-
cannot be made using destructive methods (such as <tt><<</tt>) but
|
292
|
-
only by assignments of the form <tt>db[<path>] = <data></tt>.
|
293
|
-
Note that <tt>+=</tt> and similar "assignment operators" can be
|
294
|
-
used but are not atomic, because
|
295
|
-
</p>
|
296
|
-
<pre>
|
297
|
-
db[<path>] += 1
|
298
|
-
</pre>
|
299
|
-
<p>
|
300
|
-
is really
|
301
|
-
</p>
|
302
|
-
<pre>
|
303
|
-
db[<path>] = db[<path>] + 1
|
304
|
-
</pre>
|
305
|
-
<p>
|
306
|
-
So another thread or process could change the value stored at <tt>path</tt>
|
307
|
-
while the addition is happening.
|
308
|
-
</p>
|
309
|
-
</li>
|
310
|
-
<li>Transactions that allow more complex interaction:
|
311
|
-
|
312
|
-
<pre>
|
313
|
-
path = 'foo/bar'
|
314
|
-
db[path] = [1,2,3]
|
315
|
-
|
316
|
-
db.edit path do |bar|
|
317
|
-
bar += [4]
|
318
|
-
bar[-1]
|
319
|
-
end
|
320
|
-
</pre>
|
321
|
-
<p>
|
322
|
-
This guarantees that, if the object at the path is still <tt>[1, 2, 3]</tt>
|
323
|
-
at the time of the edit call, the value returned by the transaction will be
|
324
|
-
+4+.
|
325
|
-
</p>
|
326
|
-
<p>
|
327
|
-
Simply put, edit allows exclusive write access to the object at the path
|
328
|
-
for the duration of the block. Other threads or processes that use <a
|
329
|
-
href="../classes/FSDB.html">FSDB</a> methods to read or write the object
|
330
|
-
will be blocked for the duration of the transaction. There is also browse,
|
331
|
-
which allows read access shared by any number of threads and processes, and
|
332
|
-
replace, which also allows exclusive write access like edit. The
|
333
|
-
differences between replace and edit are:
|
334
|
-
</p>
|
335
|
-
<ul>
|
336
|
-
<li>replace’s block must return the new value, whereas edit’s block
|
337
|
-
must operate (destructively) on the block argument to produce the new
|
338
|
-
value. (The new value in replace’s block can be a modification of the
|
339
|
-
old value, or an entirely different object.)
|
340
|
-
|
341
|
-
</li>
|
342
|
-
<li>replace yields <tt>nil</tt> if there is no preexisting object, whereas edit
|
343
|
-
calls default_edit (which by default calls object_missing, which by default
|
344
|
-
throws MissingObjectError).
|
345
|
-
|
346
|
-
</li>
|
347
|
-
<li>edit is useless over a drb connection, since is it operating on a
|
348
|
-
Marshal.dump-ed copy. Use replace with drb.
|
349
|
-
|
350
|
-
</li>
|
351
|
-
</ul>
|
352
|
-
<p>
|
353
|
-
You can delete an object from the database (and the file system) with
|
354
|
-
delete, which returns the object. Also, delete can take a block, which can
|
355
|
-
examine the object and abort the transaction to prevent deletion. (The
|
356
|
-
delete transaction has the same exclusion semantics as edit and replace.)
|
357
|
-
</p>
|
358
|
-
<p>
|
359
|
-
The fetch and insert methods are aliased with <tt>[ ]</tt> and <tt>[
|
360
|
-
]=</tt>.
|
361
|
-
</p>
|
362
|
-
<p>
|
363
|
-
When the object at the path specified in a transaction does not exist in
|
364
|
-
the file system, the different transaction methods behave differently:
|
365
|
-
</p>
|
366
|
-
<ul>
|
367
|
-
<li>browse calls default_browse, which, in Database’s implementation,
|
368
|
-
calls object_missing, which raises Database::MissingObjectError.
|
369
|
-
|
370
|
-
</li>
|
371
|
-
<li>edit calls default_edit, which, in Database’s implementation, calls
|
372
|
-
object_missing, which raises Database::MissingObjectError.
|
373
|
-
|
374
|
-
</li>
|
375
|
-
<li>replace and insert (and #[]) ignore any missing file.
|
376
|
-
|
377
|
-
</li>
|
378
|
-
<li>delete does nothing (if you want, you can detect the fact that the object
|
379
|
-
is missing by checking for nil in the block argument).
|
380
|
-
|
381
|
-
</li>
|
382
|
-
<li>fetch calls default_fetch, which, in Database’s implementation,
|
383
|
-
returns nil.
|
384
|
-
|
385
|
-
</li>
|
386
|
-
</ul>
|
387
|
-
<p>
|
388
|
-
Transactions can be nested. However, the order in which objects are locked
|
389
|
-
can lead to deadlock if, for example, the nesting is cyclic, or two threads
|
390
|
-
or processes request the same set of locks in a different order. One
|
391
|
-
approach is to only request nested locks on paths in the lexicographic
|
392
|
-
order of the path strings: "foo/bar", "foo/baz",
|
393
|
-
…
|
394
|
-
</p>
|
395
|
-
<p>
|
396
|
-
A transaction can be aborted with Database#abort and Database.abort, after
|
397
|
-
which the state of the object in the database remains as before the
|
398
|
-
transaction. An exception that is raised but not handled within a
|
399
|
-
transaction also aborts the transaction.
|
400
|
-
</p>
|
401
|
-
<p>
|
402
|
-
Note that there is no locking on directories, but you can designate a lock
|
403
|
-
file for each dir and effectively have multiple-reader, single writer
|
404
|
-
(advisory) locking on dirs. Just make sure you enclose your dir operation
|
405
|
-
in a transaction on the lock object, and always access these objects using
|
406
|
-
this technique.
|
407
|
-
</p>
|
408
|
-
<pre>
|
409
|
-
db.browse('lock for dir') do
|
410
|
-
db['dir/x'] = 1
|
411
|
-
end
|
412
|
-
</pre>
|
413
|
-
</li>
|
414
|
-
</ul>
|
415
|
-
<h2>Guarding against concurrency problems</h2>
|
416
|
-
<ul>
|
417
|
-
<li>It’s the user’s responsibility to avoid deadlock. See above.
|
418
|
-
|
419
|
-
</li>
|
420
|
-
<li>If you want to fork from a multithreaded process, you should include <a
|
421
|
-
href="../classes/FSDB.html">FSDB</a> or <a
|
422
|
-
href="../classes/FSDB/ForkSafely.html">FSDB::ForkSafely</a>. This prevents
|
423
|
-
"ghost" threads in the child process from permanently holding
|
424
|
-
locks.
|
425
|
-
|
426
|
-
</li>
|
427
|
-
<li>It is not safe to fork while in a transaction.
|
428
|
-
|
429
|
-
</li>
|
430
|
-
<li>A database can be configured to use fcntl locking instead of ruby’s
|
431
|
-
usual flock call. This is necessary for Linux NFS, for example. There
|
432
|
-
doesn’t seem to be any performance difference when running on a local
|
433
|
-
filesystem.
|
434
|
-
|
435
|
-
</li>
|
436
|
-
</ul>
|
437
|
-
<h2>Limitations</h2>
|
438
|
-
<ul>
|
439
|
-
<li>Transactions are not journaled. There’s no commit, undo, or
|
440
|
-
versioning. (You can abort a transaction, however.) These could be
|
441
|
-
added…
|
442
|
-
|
443
|
-
</li>
|
444
|
-
</ul>
|
445
|
-
<h2>Testing</h2>
|
446
|
-
<p>
|
447
|
-
<a href="../classes/FSDB.html">FSDB</a> has been tested on the following
|
448
|
-
platforms and file systems:
|
449
|
-
</p>
|
450
|
-
<pre>
|
451
|
-
- Linux/x86 (single and dual cpu, ext3fs and reiserfs)
|
452
|
-
|
453
|
-
- Solaris/sparc (dual and quad cpu, nfs and ufs)
|
454
|
-
|
455
|
-
- QNX 6.2.1 (dual PIII)
|
456
|
-
|
457
|
-
- Windows 2000 (dual cpu, NTFS)
|
458
|
-
|
459
|
-
- Windows ME (single cpu, FAT32)
|
460
|
-
</pre>
|
461
|
-
<p>
|
462
|
-
<a href="../classes/FSDB.html">FSDB</a> is currently tested with ruby-1.9.0
|
463
|
-
and ruby-1.8.1.
|
464
|
-
</p>
|
465
|
-
<p>
|
466
|
-
On windows, both the mswin32 and mingw32 builds of ruby have been used with
|
467
|
-
<a href="../classes/FSDB.html">FSDB</a>. It has never been tested with
|
468
|
-
cygwin or bccwin.
|
469
|
-
</p>
|
470
|
-
<p>
|
471
|
-
The tests include unit and stress tests. Unit tests isolate individual
|
472
|
-
features of the library. The stress test (called test/test-concurrency.rb)
|
473
|
-
has many parameters, but typically involves several processes, each with
|
474
|
-
several threads, doing millions of transactions on a small set of objects.
|
475
|
-
</p>
|
476
|
-
<p>
|
477
|
-
The only known testing failure is on Windows ME (and presumably 95 and 98).
|
478
|
-
The stress test succeeds with one process and multiple threads. It succeeds
|
479
|
-
with multiple processes each with one thread. However, with two processes
|
480
|
-
each with two threads, the test usually deadlocks very quickly.
|
481
|
-
</p>
|
482
|
-
<h2>Performance</h2>
|
483
|
-
<p>
|
484
|
-
<a href="../classes/FSDB.html">FSDB</a> is not very fast. It’s useful
|
485
|
-
more for its safety, flexibility, and ease of use.
|
486
|
-
</p>
|
487
|
-
<ul>
|
488
|
-
<li><a href="../classes/FSDB.html">FSDB</a> operates on cached data as much as
|
489
|
-
possible. In order to be process safe, changing an object (with edit,
|
490
|
-
replace, insert) results in a dump of the object to the file system. This
|
491
|
-
includes marshalling or other custom serialization to a string, as well as
|
492
|
-
a syswrite call. The file system buffers may keep the latter part from
|
493
|
-
being too costly, but the former part can be costly, especially for complex
|
494
|
-
objects. By using either custom marshal methods, or nonpersistent attrs
|
495
|
-
where possible (see nonpersistent-attr.rb), or <a
|
496
|
-
href="../classes/FSDB.html">FSDB</a> dump/load methods that use a faster
|
497
|
-
format (e.g., plain text, rather than a marshalled String), this may not be
|
498
|
-
so bad.
|
499
|
-
|
500
|
-
</li>
|
501
|
-
<li>On an 850MHz PIII under linux, with debugging turned off (-b option),
|
502
|
-
test-concurrency.rb reports:
|
503
|
-
|
504
|
-
<pre>
|
505
|
-
processes threads objects transactions per cpu second
|
506
|
-
---------------------------------------------------------------
|
507
|
-
1 1 10 965
|
508
|
-
1 10 10 165
|
509
|
-
10 1 10 684
|
510
|
-
10 10 10 122
|
511
|
-
10 10 100 100
|
512
|
-
10 10 10000 92
|
513
|
-
</pre>
|
514
|
-
<p>
|
515
|
-
These results are not representative of typical applications, because the
|
516
|
-
test was designed to stress the database and expose stability problems, not
|
517
|
-
to immitate typical use of database-stored objects. See bench/bench.rb for
|
518
|
-
for bechmarks.
|
519
|
-
</p>
|
520
|
-
</li>
|
521
|
-
<li>For speed, avoid using fetch and its alias #[]. As noted in the API docs,
|
522
|
-
these methods cannot safely return the same object that is cached, so must
|
523
|
-
clear out the cache’s reference to the object so that is will be
|
524
|
-
loaded freshly the next time fetch is called on the path.
|
525
|
-
|
526
|
-
<p>
|
527
|
-
The performance hit of fetch is of course greater with larger objects, and
|
528
|
-
with objects that are loaded by a more complex procedure, such as
|
529
|
-
Masrshal.load.
|
530
|
-
</p>
|
531
|
-
<p>
|
532
|
-
You can think of fetch as a "deep copy" of the object. If you
|
533
|
-
call it twice, you get different copies that do not share any parts. Or you
|
534
|
-
can think of it as File.read—it gives you an instantaneous snapshot
|
535
|
-
of the file, but does not give you a transaction "window" in
|
536
|
-
which no other thread or process can modify the object.
|
537
|
-
</p>
|
538
|
-
<p>
|
539
|
-
There is no analogous concern with insert and its alias #[]=. These methods
|
540
|
-
always write to the file system, but they also leave the object in the
|
541
|
-
cache.
|
542
|
-
</p>
|
543
|
-
</li>
|
544
|
-
<li>Performance is worse on Windows. Most of the delay seems to be in system,
|
545
|
-
rather than user, code.
|
546
|
-
|
547
|
-
</li>
|
548
|
-
</ul>
|
549
|
-
<h2>Advantages</h2>
|
550
|
-
<ul>
|
551
|
-
<li><a href="../classes/FSDB.html">FSDB</a> is useful with heterogeneous data,
|
552
|
-
that is, with files in varying formats that can be recognized based on file
|
553
|
-
name.
|
554
|
-
|
555
|
-
</li>
|
556
|
-
<li><a href="../classes/FSDB.html">FSDB</a> can be used as an interface to the
|
557
|
-
file system that understands file types. By defining new format clases,
|
558
|
-
it’s easy to set up databases that allow:
|
559
|
-
|
560
|
-
<pre>
|
561
|
-
home['.forward'] += ["nobody@nowhere.net"]
|
562
|
-
etc.edit('passwd') { |passwd| passwd['fred'].shell = '/bin/zsh' }
|
563
|
-
window.setIcon(icons['apps/editor.png'])
|
564
|
-
</pre>
|
565
|
-
</li>
|
566
|
-
<li>A <a href="../classes/FSDB.html">FSDB</a> can be operated on with ordinary
|
567
|
-
file tools. <a href="../classes/FSDB.html">FSDB</a> can even treat existing
|
568
|
-
file hierarchies as databases. It’s easy to backup, export, grep,
|
569
|
-
… the database. Its just files.
|
570
|
-
|
571
|
-
</li>
|
572
|
-
<li><a href="../classes/FSDB.html">FSDB</a> is process-safe, so it can be used
|
573
|
-
for <b>persistent</b>, *fault-tolerant* interprocess communication, such as
|
574
|
-
a queue that doesn’t require both processes to be alive at the same
|
575
|
-
time. It’s a good way to safely connect a suite of applications that
|
576
|
-
share common files. Also, you can take advantage of multiprocessor systems
|
577
|
-
by forking a new process to handle a CPU-intesive transaction.
|
578
|
-
|
579
|
-
</li>
|
580
|
-
<li><a href="../classes/FSDB.html">FSDB</a> is thread-safe, so it can be used
|
581
|
-
in a threaded server, such as drb. In fact, the <a
|
582
|
-
href="../classes/FSDB.html">FSDB</a> Database itself can be the drb server
|
583
|
-
object, allowing browse, replace (but not edit), insert, and delete from
|
584
|
-
remote clients! (See the examples server.rb and client.rb.)
|
585
|
-
|
586
|
-
</li>
|
587
|
-
<li><a href="../classes/FSDB.html">FSDB</a> can be used as a portable interface
|
588
|
-
to multithreaded file locking. (File#flock does not have consistent
|
589
|
-
semantics across platforms.)
|
590
|
-
|
591
|
-
</li>
|
592
|
-
<li>Compared with PStore, <a href="../classes/FSDB.html">FSDB</a> has the
|
593
|
-
potential for finer granularity, and it scales better. The cost of using
|
594
|
-
fine granularity is that referential structures, unless contained within
|
595
|
-
individual nodes, must be based on path strings. (But of course this would
|
596
|
-
be a problem with multiple PStores, as well.)
|
597
|
-
|
598
|
-
</li>
|
599
|
-
<li><a href="../classes/FSDB.html">FSDB</a> scales up to large numbers of
|
600
|
-
objects.
|
601
|
-
|
602
|
-
</li>
|
603
|
-
<li>Objects in a <a href="../classes/FSDB.html">FSDB</a> can be anything
|
604
|
-
serializable. They don’t have to inherit or mix in anything.
|
605
|
-
|
606
|
-
</li>
|
607
|
-
<li>By using only the file system and standard ruby libraries, installation
|
608
|
-
requirements are minimal.
|
609
|
-
|
610
|
-
</li>
|
611
|
-
<li>It may be fast enough for many purposes, especially using multiple
|
612
|
-
processes rather than multiple threads.
|
613
|
-
|
614
|
-
</li>
|
615
|
-
<li>Pure ruby. Ruby license. Free sotware.
|
616
|
-
|
617
|
-
</li>
|
618
|
-
</ul>
|
619
|
-
<h2>Applications</h2>
|
620
|
-
<p>
|
621
|
-
I’ve heard from a couple of people writing applications that use <a
|
622
|
-
href="../classes/FSDB.html">FSDB</a>. One app is:
|
623
|
-
</p>
|
624
|
-
<ul>
|
625
|
-
<li><a href="http://tourneybot.rubyforge.org">tourneybot.rubyforge.org</a>
|
626
|
-
|
627
|
-
</li>
|
628
|
-
</ul>
|
629
|
-
<h2>To do</h2>
|
630
|
-
<h3>Fix (potential) bugs</h3>
|
631
|
-
<ul>
|
632
|
-
<li>If two FSDBs are in use in the same process, they share the cache. If they
|
633
|
-
associate different formats with the same file, the results will be
|
634
|
-
surprising. Maybe the cache should remember the format used and flag an
|
635
|
-
error if it detects an inconsistency. A similar problem could happen for
|
636
|
-
other Database attributes, like lock-type (which should probably be
|
637
|
-
global).
|
638
|
-
|
639
|
-
</li>
|
640
|
-
</ul>
|
641
|
-
<h3>Features</h3>
|
642
|
-
<ul>
|
643
|
-
<li>Should the Format objects be classes instead of just instances of Format?
|
644
|
-
|
645
|
-
</li>
|
646
|
-
<li>Default value and proc for Database, like Hash.
|
647
|
-
|
648
|
-
</li>
|
649
|
-
<li>FSDB::Reference class:
|
650
|
-
|
651
|
-
<pre>
|
652
|
-
db['foo/bar.obj'] = "some string"
|
653
|
-
referrer = { :my_bar => FSDB::Reference.new('../foo/bar.obj') }
|
654
|
-
db['x/y.yml'] = referrer
|
655
|
-
p db['x/y.yml'][:my_bar] # ==> "some string"
|
656
|
-
</pre>
|
657
|
-
<p>
|
658
|
-
Or, more like DRbUndumped:
|
659
|
-
</p>
|
660
|
-
<pre>
|
661
|
-
str = "some string"
|
662
|
-
str.extend FSDB::Undumped
|
663
|
-
db['foo/bar.obj'] = str
|
664
|
-
referrer = { :my_bar => str }
|
665
|
-
db['x/y.yml'] = referrer
|
666
|
-
p db['x/y.yml'][:my_bar] # ==> "some string"
|
667
|
-
</pre>
|
668
|
-
<p>
|
669
|
-
Extending with FSDB::Undumped will have to insert state in the object that
|
670
|
-
remembers the db path at which it is stored (‘foo/bar.obj’ in
|
671
|
-
this case).
|
672
|
-
</p>
|
673
|
-
</li>
|
674
|
-
<li>Use (optionally) weak references in CacheEntry.
|
675
|
-
|
676
|
-
</li>
|
677
|
-
<li>use metafiles to emulate locking on dirs?
|
678
|
-
|
679
|
-
</li>
|
680
|
-
<li>optionally, for each file, store a md5 sum of the raw data, so that we may
|
681
|
-
be able to avoid Marshal.load and (after dump) the actual write.
|
682
|
-
|
683
|
-
</li>
|
684
|
-
<li>optionally, do not create ..fsdb.meta.* files.
|
685
|
-
|
686
|
-
</li>
|
687
|
-
<li>transactions on groups of objects
|
688
|
-
|
689
|
-
<ul>
|
690
|
-
<li>for edit and browse, but not replace or insert. Maybe delete.
|
691
|
-
|
692
|
-
</li>
|
693
|
-
<li>db.edit [path1, path2] do |obj1, obj2| … end
|
694
|
-
|
695
|
-
<ul>
|
696
|
-
<li>lock order is explicit, up to user to avoid deadlock
|
697
|
-
|
698
|
-
</li>
|
699
|
-
</ul>
|
700
|
-
</li>
|
701
|
-
<li>db.edit_glob "foo/**/bar*/{zap,zow}" … do |hash|
|
702
|
-
|
703
|
-
<pre>
|
704
|
-
for path, object in hash ... end
|
705
|
-
</pre>
|
706
|
-
<p>
|
707
|
-
end
|
708
|
-
</p>
|
709
|
-
</li>
|
710
|
-
</ul>
|
711
|
-
</li>
|
712
|
-
<li>Make irb-based database shell
|
713
|
-
|
714
|
-
<ul>
|
715
|
-
<li>class Database; def irb_browse(path); browse(path) {|obj| irb obj}; end;
|
716
|
-
end
|
717
|
-
|
718
|
-
<p>
|
719
|
-
then:
|
720
|
-
</p>
|
721
|
-
<pre>
|
722
|
-
irb> irb db
|
723
|
-
irb#1> irb_browse path
|
724
|
-
...
|
725
|
-
... # got a read lock for this session
|
726
|
-
...
|
727
|
-
irb#1> ^D
|
728
|
-
irb>
|
729
|
-
</pre>
|
730
|
-
<p>
|
731
|
-
one problem: irb defines singleton methods, so can’t dump (in edit)
|
732
|
-
</p>
|
733
|
-
<p>
|
734
|
-
maybe we can extend the class of the object by some module instead…
|
735
|
-
</p>
|
736
|
-
</li>
|
737
|
-
</ul>
|
738
|
-
</li>
|
739
|
-
<li>iterator, query, indexing methods
|
740
|
-
|
741
|
-
</li>
|
742
|
-
<li>more formats
|
743
|
-
|
744
|
-
<ul>
|
745
|
-
<li>tabular data, excel, xml, ascii db, csv
|
746
|
-
|
747
|
-
</li>
|
748
|
-
<li>SOAP marshal, XML marshal
|
749
|
-
|
750
|
-
</li>
|
751
|
-
<li>filters for compression, encryption
|
752
|
-
|
753
|
-
</li>
|
754
|
-
</ul>
|
755
|
-
</li>
|
756
|
-
<li>more node types
|
757
|
-
|
758
|
-
<pre>
|
759
|
-
.que : use IO#read_object, IO#write_object (at end of file)
|
760
|
-
to implement a persistent queue
|
761
|
-
|
762
|
-
fifo, named socket, device, ...
|
763
|
-
</pre>
|
764
|
-
</li>
|
765
|
-
<li>interface to file attributes (mode, etc)
|
766
|
-
|
767
|
-
</li>
|
768
|
-
<li>access control lists (use meta files)
|
769
|
-
|
770
|
-
</li>
|
771
|
-
</ul>
|
772
|
-
<h3>Stability, Security, and Error Checking</h3>
|
773
|
-
<ul>
|
774
|
-
<li>investigate using the BDB lock mechanism in place of flock.
|
775
|
-
|
776
|
-
</li>
|
777
|
-
<li>in transactions, if path is tainted, apply the validation of util.rb?
|
778
|
-
|
779
|
-
</li>
|
780
|
-
<li>detect fork in transaction
|
781
|
-
|
782
|
-
</li>
|
783
|
-
<li>purge empty dirs?
|
784
|
-
|
785
|
-
</li>
|
786
|
-
<li>periodically clear_cache to keep the hash size low
|
787
|
-
|
788
|
-
<ul>
|
789
|
-
<li>every Nth new CacheEntry?
|
790
|
-
|
791
|
-
</li>
|
792
|
-
<li>should cache entries be in an LRU queue so we can purge the LRU?
|
793
|
-
|
794
|
-
</li>
|
795
|
-
</ul>
|
796
|
-
</li>
|
797
|
-
<li>should we detect recursive lock attempt and fail? (Now, it just deadlocks.)
|
798
|
-
|
799
|
-
</li>
|
800
|
-
</ul>
|
801
|
-
<h3>Performance</h3>
|
802
|
-
<ul>
|
803
|
-
<li>Profiling says that Thread.exclusive consumes about 20% of cpu. Also,
|
804
|
-
Thread.stop and Thread.run when there are multiple threads. Using
|
805
|
-
Thread.critical in places where it is safe to do so (no exceptions raised)
|
806
|
-
instead of Thread.exclusive would reduce this to an estimated 6%. ((See
|
807
|
-
faster-modex .rb and faster-mutex.rb.))
|
808
|
-
|
809
|
-
</li>
|
810
|
-
<li>Better way of waiting for file lock in the multithread case
|
811
|
-
|
812
|
-
<ul>
|
813
|
-
<li>this may be unfixable until ruby has native threads
|
814
|
-
|
815
|
-
</li>
|
816
|
-
</ul>
|
817
|
-
</li>
|
818
|
-
<li>Use shared memory for the cache, so write is not necessary after edit.
|
819
|
-
|
820
|
-
<ul>
|
821
|
-
<li>actually, this may not make much sense
|
822
|
-
|
823
|
-
</li>
|
824
|
-
</ul>
|
825
|
-
</li>
|
826
|
-
<li>Option for Database to ignore file locking and possibility of other
|
827
|
-
writers.
|
828
|
-
|
829
|
-
</li>
|
830
|
-
<li>fetch could use the cache better if the cache kept the file contents string
|
831
|
-
as well as the loaded object. Then the stale! call would only have to wipe
|
832
|
-
the reference to the object, and could leave the contents string. But this
|
833
|
-
would increase file size and duplicate the file system’s own cache.
|
834
|
-
|
835
|
-
</li>
|
836
|
-
</ul>
|
837
|
-
<h2>Version</h2>
|
838
|
-
<p>
|
839
|
-
fsdb 0.5
|
840
|
-
</p>
|
841
|
-
<p>
|
842
|
-
The current version of this software can be found at <a
|
843
|
-
href="http://redshift.sourceforge.net/fsdb">redshift.sourceforge.net/fsdb</a>.
|
844
|
-
</p>
|
845
|
-
<h2>License</h2>
|
846
|
-
<p>
|
847
|
-
This software is distributed under the Ruby license. See <a
|
848
|
-
href="http://www.ruby-lang.org">www.ruby-lang.org</a>.
|
849
|
-
</p>
|
850
|
-
<h2>Author</h2>
|
851
|
-
<p>
|
852
|
-
Joel VanderWerf, <a
|
853
|
-
href="mailto:vjoel@users.sourceforge.net">vjoel@users.sourceforge.net</a>
|
854
|
-
Copyright © 2005, Joel VanderWerf.
|
855
|
-
</p>
|
856
|
-
|
857
|
-
</div>
|
858
|
-
|
859
|
-
|
860
|
-
</div>
|
861
|
-
|
862
|
-
|
863
|
-
</div>
|
864
|
-
|
865
|
-
|
866
|
-
<!-- if includes -->
|
867
|
-
|
868
|
-
<div id="section">
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
<!-- if method_list -->
|
878
|
-
|
879
|
-
|
880
|
-
</div>
|
881
|
-
|
882
|
-
|
883
|
-
<div id="validator-badges">
|
884
|
-
<p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
|
885
|
-
</div>
|
886
|
-
|
887
|
-
</body>
|
888
|
-
</html>
|