summaryrefslogtreecommitdiff
path: root/fml/doc/en/tutorial/internals/io_abstraction.sgml
blob: 5dcf7cd5a71949135fc4af23724beb932c33f378 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
<!--
   $FML: io_abstraction.sgml,v 1.1 2005/07/28 13:27:48 fukachan Exp $
-->


<chapter id="io.abstraction">
	<title>
	IO Interface And Operations
	</title>

<para>
We need IO abstraction layer for porting and extension.
See Vnode/VFS interface (vnode(9)) on IO abstraction. 
<screen>
struct vnode {
		...
        voff_t          v_size;                 /* size of file */
        int             v_numoutput;            /* num pending writes */
        long            v_writecount;           /* ref count of writers */
		...
        int             (**v_op)(void *);       /* vnode ops vector */
		...
        void            *v_data;                /* private data for fs */
};
</screen>
vop_open(),
vop_read(),
vop_getattr(), ...
are defined over v_op.
</para>

<para>
**v_op (vnode operation vector) corresponds to a method of object
oriented programming. &fml8; provides IO::Adapter class as IO
abstraction layer.
</para>


<sect1 id="io.abstraction.overview">
	<title>
	Fundamentals Of IO::Adapter
	</title>

<para>
<link linkend="module.io.adapter">
IO::Adapter
</link>
is most fundamental in &fml8; architecture.
It is well considered and implemented.
It provides enough primitive methods.
</para>

<para>
<link linkend="module.io.adapter">
IO::Adapter
</link>
class abstracts
<screen>
KEY => VALUE
</screen>
or
<screen>
KEY => [ VALUE, VALUE2, VALUE3 ]
</screen>
type data structure.
It is similar to RDBMS theory like this.
</para>
<screen>
KEY1 VALUE1-1 ""     ""
KEY2 VALUE2-1 VALUE2-2 VALUE2-3
KEY3 VALUE3-1 VALUE3-2 VALUE3-3
KEY4 VALUE4-1 VALUE4-2 VALUE4-3
</screen>

<para>
To maintain address list, least fundamental methods of IO::Adapter are
<screen>
open()
close()
</screen>
and IO operations to the object
<screen>
add(KEY, ARGV) (ARGV is class dependent)
delete(KEY)
find(KEY or REGEXP)
get_next_key()
</screen>
methods.
At least, enough to write user management codes.
</para>

</sect1>


<sect1 id="io.abstraction.ops">
	<title>
	Methods / Operation Vector
	</title>

<para>
Mentioned above, the fundamental methods of IO::Adapter are as
follows:
<screen>
open()
close()
add(KEY, ARGV) (ARGV = class dependent)
delete(KEY)
find(KEY or REGEXP)
get_next_key()
</screen>
</para>

<para>
Other than these methods, new() as a constructor and destructor() are
needed.
</para>

<para>
The constructor is new() methond.
For example, use like this;
<screen>
$obj = new IO::Adapter MAP;
</screen>
The argument is a map which calls map dependent constructor.
</para>


<sect2>
	<title>
	open()
	</title>

<para>
For a file, call open(2), for RDBMS, connect to the specified SQL
server.
</para>

</sect2>


<sect2>
	<title>
	close()
	</title>

<para>
Reverse of open().
</para>

</sect2>


<sect2>
	<title>
	add(KEY, ARGV)
	</title>

<para>
add KEY (primary key) or KEY and the associated VALUE into the object.
ARGV is class dependent.
</para>

<para>
We assume an object is composed of a form.
It is similar to RDBMS.
</para>

<para>
The primary key is a mail address. This assumption is correct in the
case of mailing list driver. This is basic data structure.
</para>

</sect2>


<sect2>
	<title>
	delete(KEY)
	</title>

<para>
Delete KEY and the associated VALUE.
</para>

</sect2>


<sect2>
	<title>
	find(KEY) / find(REGEXP)
	</title>

<para>
Search data corresponding with the primary key within an object.
</para>

<para>
The target is specified as regular expression.
Regular expression search is useful.
</para>

<para>
The return value is STR of ARRAY_REF (KEY => [ VALUE, VALUE2, VALUE3 ]).
</para>

</sect2>


<sect2>
	<title>
	get_next_key()
	</title>

<para>
Return the list of primary keys like this:
<screen>
while ($obj->get_next_key()) { ... }
</screen>
</para>

<para>
This operation corresponds to FIRST_KEY() and NEXT_KEY() of perl hash.
</para>

</sect2>

</sect1>


<sect1 id="io.abstraction.discussion">
	<title>
	Discussion
	</title>


<sect2>
	<title>
	What ARRAY_REF return ?
	</title>

<para>
What expected in using ARRAY_REF as the return value ? 
A list of PRIMARY KEY ?
</para>

</sect2>


<sect2>
	<title>
	How To Get All Primary Keys ?
	</title>

<para>
We need to call get_next_keys() again and again to retrieve all
keys. It may be useful to implement special method to return a list of
keys but it is not implemented.
</para>

<para>
get_primary_keys() ?
find('*', { all => 1 }) is used for this purpose.
It is of no use to implement specific method for this.
</para>

</sect2>


<sect2>
	<title>
	HASH_REF As Return Value ?
	</title>

<para>
What expected ?
<screen>
RETURN VALUE = {
	KEY_1 => VALUE_1,
	KEY_2 => VALUE_2,	
}
</screen>
</para>

<para>
If a mail address has several attributes, this method is useful.
For example, consider digest delivery:
<screen>
ADDRESS => {
	internal	=> 	3 hours,
	compression	=>	no,
	format		=>	mime/multipart,
};
</screen>
</para>

<para>
Abstracted Cache IO layer is this type such as:
<screen>
FML::Error -> FML::Error::Cache -> Tie::JournaledDir
</screen>
But ... dependent on Tie::* hmm ..
</para>

</sect2>

</sect1>


</Chapter>