d15b721bf25f2e6740d75eb59c64fbbb8cde1020
[debian/amanda] / xfer-src / source-random.c
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 2008 Zmanda Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19
20 #include "amxfer.h"
21 #include "amanda.h"
22 #include "simpleprng.h"
23
24 /*
25  * Class declaration
26  *
27  * This declaration is entirely private; nothing but xfer_source_random() references
28  * it directly.
29  */
30
31 GType xfer_source_random_get_type(void);
32 #define XFER_SOURCE_RANDOM_TYPE (xfer_source_random_get_type())
33 #define XFER_SOURCE_RANDOM(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), xfer_source_random_get_type(), XferSourceRandom)
34 #define XFER_SOURCE_RANDOM_CONST(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), xfer_source_random_get_type(), XferSourceRandom const)
35 #define XFER_SOURCE_RANDOM_CLASS(klass) G_TYPE_CHECK_CLASS_CAST((klass), xfer_source_random_get_type(), XferSourceRandomClass)
36 #define IS_XFER_SOURCE_RANDOM(obj) G_TYPE_CHECK_INSTANCE_TYPE((obj), xfer_source_random_get_type ())
37 #define XFER_SOURCE_RANDOM_GET_CLASS(obj) G_TYPE_INSTANCE_GET_CLASS((obj), xfer_source_random_get_type(), XferSourceRandomClass)
38
39 static GObjectClass *parent_class = NULL;
40
41 /*
42  * Main object structure
43  */
44
45 typedef struct XferSourceRandom {
46     XferElement __parent__;
47
48     gboolean limited_length;
49     guint64 length;
50     simpleprng_state_t prng;
51 } XferSourceRandom;
52
53 /*
54  * Class definition
55  */
56
57 typedef struct {
58     XferElementClass __parent__;
59 } XferSourceRandomClass;
60
61 /*
62  * Implementation
63  */
64
65 static gpointer
66 pull_buffer_impl(
67     XferElement *elt,
68     size_t *size)
69 {
70     XferSourceRandom *self = (XferSourceRandom *)elt;
71     char *buf;
72
73     if (elt->cancelled || (self->limited_length && self->length == 0)) {
74         *size = 0;
75         return NULL;
76     }
77
78     if (self->limited_length) {
79         *size = MIN(10240, self->length);
80         self->length -= *size;
81     } else {
82         *size = 10240;
83     }
84
85     buf = g_malloc(*size);
86     simpleprng_fill_buffer(&self->prng, buf, *size);
87
88     return buf;
89 }
90
91 static void
92 instance_init(
93     XferElement *elt)
94 {
95     elt->can_generate_eof = TRUE;
96 }
97
98 static void
99 class_init(
100     XferSourceRandomClass * selfc)
101 {
102     XferElementClass *klass = XFER_ELEMENT_CLASS(selfc);
103     static xfer_element_mech_pair_t mech_pairs[] = {
104         { XFER_MECH_NONE, XFER_MECH_PULL_BUFFER, 1, 0},
105         { XFER_MECH_NONE, XFER_MECH_NONE, 0, 0},
106     };
107
108     klass->pull_buffer = pull_buffer_impl;
109
110     klass->perl_class = "Amanda::Xfer::Source::Random";
111     klass->mech_pairs = mech_pairs;
112
113     parent_class = g_type_class_peek_parent(selfc);
114 }
115
116 GType
117 xfer_source_random_get_type (void)
118 {
119     static GType type = 0;
120
121     if G_UNLIKELY(type == 0) {
122         static const GTypeInfo info = {
123             sizeof (XferSourceRandomClass),
124             (GBaseInitFunc) NULL,
125             (GBaseFinalizeFunc) NULL,
126             (GClassInitFunc) class_init,
127             (GClassFinalizeFunc) NULL,
128             NULL /* class_data */,
129             sizeof (XferSourceRandom),
130             0 /* n_preallocs */,
131             (GInstanceInitFunc) instance_init,
132             NULL
133         };
134
135         type = g_type_register_static (XFER_ELEMENT_TYPE, "XferSourceRandom", &info, 0);
136     }
137
138     return type;
139 }
140
141 /* create an element of this class; prototype is in xfer-element.h */
142 XferElement *
143 xfer_source_random(
144     guint64 length,
145     guint32 prng_seed)
146 {
147     XferSourceRandom *xsr = (XferSourceRandom *)g_object_new(XFER_SOURCE_RANDOM_TYPE, NULL);
148     XferElement *elt = XFER_ELEMENT(xsr);
149
150     xsr->length = length;
151     xsr->limited_length = (length != 0);
152     simpleprng_seed(&xsr->prng, prng_seed);
153
154     return elt;
155 }