1a8ae730175eb68587fd1b11ef6cd4cc175e06e3
[pspp-builds.git] / src / data / casewriter.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2007 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18
19 #include <data/casewriter.h>
20 #include <data/casewriter-provider.h>
21
22 #include <assert.h>
23 #include <stdlib.h>
24
25 #include <data/casereader.h>
26 #include <data/casereader-provider.h>
27 #include <data/casewindow.h>
28 #include <data/settings.h>
29 #include <libpspp/compiler.h>
30 #include <libpspp/taint.h>
31
32 #include "xalloc.h"
33
34 /* A casewriter. */
35 struct casewriter
36   {
37     struct taint *taint;
38     casenumber case_cnt;
39     const struct casewriter_class *class;
40     void *aux;
41   };
42
43 static struct casewriter *create_casewriter_window (size_t value_cnt,
44                                                     casenumber max_in_core);
45
46 /* Writes case C to WRITER. */
47 void
48 casewriter_write (struct casewriter *writer, struct ccase *c)
49 {
50   writer->class->write (writer, writer->aux, c);
51 }
52
53 /* Destroys WRITER.
54    Returns true if successful, false if an I/O error was
55    encountered on WRITER or on some object on which WRITER has a
56    dependency. */
57 bool
58 casewriter_destroy (struct casewriter *writer)
59 {
60   bool ok = true;
61   if (writer != NULL)
62     {
63       writer->class->destroy (writer, writer->aux);
64       ok = taint_destroy (writer->taint);
65       free (writer);
66     }
67   return ok;
68 }
69
70 /* Destroys WRITER and in its place returns a casereader that can
71    be used to read back the data written to WRITER.  WRITER must
72    not be used again after calling this function, even as an
73    argument to casewriter_destroy.
74
75    Not all casewriters implement this function.  Behavior is
76    undefined if it is called on one that does not.
77
78    If an I/O error was encountered on WRITER or on some object on
79    which WRITER has a dependency, then the error will be
80    propagated to the new casereader. */
81 struct casereader *
82 casewriter_make_reader (struct casewriter *writer)
83 {
84   struct casereader *reader;
85   reader = writer->class->convert_to_reader (writer, writer->aux);
86   taint_propagate (writer->taint, casereader_get_taint (reader));
87   taint_destroy (writer->taint);
88   free (writer);
89   return reader;
90 }
91
92 /* Returns a copy of WRITER, which is itself destroyed.
93    Useful for taking over ownership of a casewriter, to enforce
94    preventing the original owner from accessing the casewriter
95    again. */
96 struct casewriter *
97 casewriter_rename (struct casewriter *writer)
98 {
99   struct casewriter *new = xmemdup (writer, sizeof *writer);
100   free (writer);
101   return new;
102 }
103
104 /* Returns true if an I/O error or another hard error has
105    occurred on WRITER, a clone of WRITER, or on some object on
106    which WRITER's data has a dependency, false otherwise. */
107 bool
108 casewriter_error (const struct casewriter *writer)
109 {
110   return taint_is_tainted (writer->taint);
111 }
112
113 /* Marks WRITER as having encountered an error.
114
115    Ordinarily, this function should be called by the
116    implementation of a casewriter, not by the casewriter's
117    client.  Instead, casewriter clients should usually ensure
118    that a casewriter's error state is correct by using
119    taint_propagate to propagate to the casewriter's taint
120    structure, which may be obtained via casewriter_get_taint. */
121 void
122 casewriter_force_error (struct casewriter *writer)
123 {
124   taint_set_taint (writer->taint);
125 }
126
127 /* Returns WRITER's associate taint object, for use with
128    taint_propagate and other taint functions. */
129 const struct taint *
130 casewriter_get_taint (const struct casewriter *writer)
131 {
132   return writer->taint;
133 }
134
135 /* Creates and returns a new casewriter with the given CLASS and
136    auxiliary data AUX. */
137 struct casewriter *
138 casewriter_create (const struct casewriter_class *class, void *aux)
139 {
140   struct casewriter *writer = xmalloc (sizeof *writer);
141   writer->taint = taint_create ();
142   writer->case_cnt = 0;
143   writer->class = class;
144   writer->aux = aux;
145   return writer;
146 }
147
148 /* Returns a casewriter for cases with VALUE_CNT struct values
149    per case.  The cases written to the casewriter will be kept in
150    memory, unless the amount of memory used grows too large, in
151    which case they will be written to disk.
152
153    A casewriter created with this function may be passed to
154    casewriter_make_reader.
155
156    This is usually the right kind of casewriter to use. */
157 struct casewriter *
158 autopaging_writer_create (size_t value_cnt)
159 {
160   return create_casewriter_window (value_cnt, get_workspace_cases (value_cnt));
161 }
162
163 /* Returns a casewriter for cases with VALUE_CNT struct values
164    per case.  The cases written to the casewriter will be kept in
165    memory.
166
167    A casewriter created with this function may be passed to
168    casewriter_make_reader. */
169 struct casewriter *
170 mem_writer_create (size_t value_cnt)
171 {
172   return create_casewriter_window (value_cnt, CASENUMBER_MAX);
173 }
174
175 /* Returns a casewriter for cases with VALUE_CNT struct values
176    per case.  The cases written to the casewriter will be written
177    to disk.
178
179    A casewriter created with this function may be passed to
180    casewriter_make_reader. */
181 struct casewriter *
182 tmpfile_writer_create (size_t value_cnt)
183 {
184   return create_casewriter_window (value_cnt, 0);
185 }
186 \f
187 static const struct casewriter_class casewriter_window_class;
188 static const struct casereader_random_class casereader_window_class;
189
190 /* Creates and returns a new casewriter based on a casewindow.
191    Each of the casewriter's cases are composed of VALUE_CNT
192    struct values.  The casewriter's cases will be maintained in
193    memory until MAX_IN_CORE_CASES have been written, at which
194    point they will be written to disk. */
195 static struct casewriter *
196 create_casewriter_window (size_t value_cnt, casenumber max_in_core_cases)
197 {
198   struct casewindow *window = casewindow_create (value_cnt, max_in_core_cases);
199   struct casewriter *writer = casewriter_create (&casewriter_window_class,
200                                                  window);
201   taint_propagate (casewindow_get_taint (window),
202                    casewriter_get_taint (writer));
203   return writer;
204 }
205
206 /* Writes case C to casewindow writer WINDOW. */
207 static void
208 casewriter_window_write (struct casewriter *writer UNUSED, void *window_,
209                          struct ccase *c)
210 {
211   struct casewindow *window = window_;
212   casewindow_push_head (window, c);
213 }
214
215 /* Destroys casewindow writer WINDOW. */
216 static void
217 casewriter_window_destroy (struct casewriter *writer UNUSED, void *window_)
218 {
219   struct casewindow *window = window_;
220   casewindow_destroy (window);
221 }
222
223 /* Converts casewindow writer WINDOW to a casereader and returns
224    the casereader. */
225 static struct casereader *
226 casewriter_window_convert_to_reader (struct casewriter *writer UNUSED,
227                                      void *window_)
228 {
229   struct casewindow *window = window_;
230   struct casereader *reader;
231   reader = casereader_create_random (casewindow_get_value_cnt (window),
232                                      casewindow_get_case_cnt (window),
233                                      &casereader_window_class, window);
234   taint_propagate (casewindow_get_taint (window),
235                    casereader_get_taint (reader));
236   return reader;
237 }
238
239 /* Reads the case at the given 0-based OFFSET from the front of
240    WINDOW into C.  Returns true if successful, false if
241    OFFSET is beyond the end of file or upon I/O error. */
242 static bool
243 casereader_window_read (struct casereader *reader UNUSED, void *window_,
244                         casenumber offset, struct ccase *c)
245 {
246   struct casewindow *window = window_;
247   if (offset >= casewindow_get_case_cnt (window))
248     return false;
249   else
250     return casewindow_get_case (window, offset, c);
251 }
252
253 /* Destroys casewindow reader WINDOW. */
254 static void
255 casereader_window_destroy (struct casereader *reader UNUSED, void *window_)
256 {
257   struct casewindow *window = window_;
258   casewindow_destroy (window);
259 }
260
261 /* Discards CASE_CNT cases from the front of WINDOW. */
262 static void
263 casereader_window_advance (struct casereader *reader UNUSED, void *window_,
264                            casenumber case_cnt)
265 {
266   struct casewindow *window = window_;
267   casewindow_pop_tail (window, case_cnt);
268 }
269
270 /* Class for casewindow writer. */
271 static const struct casewriter_class casewriter_window_class =
272   {
273     casewriter_window_write,
274     casewriter_window_destroy,
275     casewriter_window_convert_to_reader,
276   };
277
278 /* Class for casewindow reader. */
279 static const struct casereader_random_class casereader_window_class =
280   {
281     casereader_window_read,
282     casereader_window_destroy,
283     casereader_window_advance,
284   };
285 \f