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