memory_client.h 10.4 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

#ifndef DATASRC_MEMORY_CLIENT_H
#define DATASRC_MEMORY_CLIENT_H 1

18
19
#include <util/memory_segment.h>

20
#include <datasrc/iterator.h>
21
#include <datasrc/client.h>
22
#include <datasrc/memory/zone_table.h>
23
24
25
26
27
28

// for isc::datasrc::ZoneTable::FindResult returned by findZone(). This
// variant of findZone() is not implemented and should be removed
// eventually.
#include <datasrc/zonetable.h>

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <string>

namespace isc {

namespace dns {
class Name;
class RRsetList;
};

namespace datasrc {
namespace memory {

/// \brief A data source client that holds all necessary data in memory.
///
/// The \c InMemoryClient class provides an access to a conceptual data
/// source that maintains all necessary data in a memory image, thereby
/// allowing much faster lookups.  The in memory data is a copy of some
/// real physical source - in the current implementation a list of zones
/// are populated as a result of \c load() calls; zone data is given in
48
49
/// a standard master file, or as an iterator of some other datasource
/// including database backed ones.
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
///
/// The InMemoryClient enforces through its interface that all data
/// loaded to the data source is of the same RR class.  For example, the
/// \c load() method assumes that the zone being loaded belongs to the
/// same RR class as the memory::Client instance.
class InMemoryClient : public DataSourceClient {
public:
    ///
    /// \name Constructors and Destructor.
    ///
    //@{

    /// Default constructor.
    ///
    /// This constructor internally involves resource allocation, and if
    /// it fails, a corresponding standard exception will be thrown.
    /// It never throws an exception otherwise.
67
68
    InMemoryClient(util::MemorySegment& mem_sgmt,
                   isc::dns::RRClass rrclass);
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

    /// The destructor.
    ~InMemoryClient();
    //@}

    /// \brief Returns the class of the data source client.
    virtual isc::dns::RRClass getClass() const;

    /// Return the number of zones stored in the client.
    ///
    /// This method never throws an exception.
    ///
    /// \return The number of zones stored in the client.
    virtual unsigned int getZoneCount() const;

    /// \brief Load zone from masterfile.
    ///
    /// This loads data from masterfile specified by filename. It replaces
    /// current content. The masterfile parsing ability is kind of limited,
    /// see isc::dns::masterLoad.
    ///
    /// This throws isc::dns::MasterLoadError if there is problem with loading
    /// (missing file, malformed, it contains different zone, etc - see
    /// isc::dns::masterLoad for details).
    ///
    /// In case of internal problems, OutOfZone, NullRRset or AssertError could
    /// be thrown, but they should not be expected. Exceptions caused by
    /// allocation may be thrown as well.
    ///
    /// If anything is thrown, the previous content is preserved (so it can
    /// be used to update the data, but if user makes a typo, the old one
    /// is kept).
    ///
    /// \param filename The master file to load.
    ///
    /// \todo We may need to split it to some kind of build and commit/abort.
    ///     This will probably be needed when a better implementation of
    ///     configuration reloading is written.
    result::Result load(const isc::dns::Name& zone_name,
                        const std::string& filename);

    /// \brief Load zone from another data source.
    ///
    /// This is similar to the other version, but zone's RRsets are provided
    /// by an iterator of another data source.  On successful load, the
    /// internal filename will be cleared.
    ///
    /// This implementation assumes the iterator produces combined RRsets,
    /// that is, there should exactly one RRset for the same owner name and
    /// RR type.  This means the caller is expected to create the iterator
    /// with \c separate_rrs being \c false.  This implementation also assumes
    /// RRsets of different names are not mixed; so if the iterator produces
    /// an RRset of a different name than that of the previous RRset, that
    /// previous name must never appear in the subsequent sequence of RRsets.
    /// Note that the iterator API does not ensure this.  If the underlying
    /// implementation does not follow it, load() will fail.  Note, however,
    /// that this whole interface is tentative.  in-memory zone loading will
    /// have to be revisited fundamentally, and at that point this restriction
    /// probably won't matter.
    result::Result load(const isc::dns::Name& zone_name,
Mukund Sivaraman's avatar
Mukund Sivaraman committed
129
                        ZoneIterator& iterator);
130

131
132
133
134
135
136
137
138
139
140
141
142
143
144
    /// Return the master file name of the zone
    ///
    /// This method returns the name of the zone's master file to be loaded.
    /// The returned string will be an empty unless the data source client has
    /// successfully loaded the zone before.
    ///
    /// This method should normally not throw an exception.  But the creation
    /// of the return string may involve a resource allocation, and if it
    /// fails, the corresponding standard exception will be thrown.
    ///
    /// \return The name of the zone file loaded in the client, or an empty
    /// string if the client hasn't loaded any file.
    const std::string getFileName(const isc::dns::Name& zone_name) const;

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
    /// \brief Inserts an rrset into the zone.
    ///
    /// It puts another RRset into the zone.
    ///
    /// In the current implementation, this method doesn't allow an existing
    /// RRset to be updated or overridden.  So the caller must make sure that
    /// all RRs of the same type and name must be given in the form of a
    /// single RRset.  The current implementation will also require that
    /// when an RRSIG is added, the RRset to be covered has already been
    /// added.  These restrictions are probably too strict when this data
    /// source accepts various forms of input, so they should be revisited
    /// later.
    ///
    /// Except for NullRRset and OutOfZone, this method does not guarantee
    /// strong exception safety (it is currently not needed, if it is needed
    /// in future, it should be implemented).
    ///
    /// \throw NullRRset \c rrset is a NULL pointer.
    /// \throw OutOfZone The owner name of \c rrset is outside of the
    /// origin of the zone.
    /// \throw AddError Other general errors.
    /// \throw Others This method might throw standard allocation exceptions.
    ///
    /// \param rrset The set to add.
    /// \return SUCCESS or EXIST (if an rrset for given name and type already
    ///    exists).
    result::Result add(const isc::dns::Name& zone_name,
                       const isc::dns::ConstRRsetPtr& rrset);

    /// \brief RRset is NULL exception.
    ///
    /// This is thrown if the provided RRset parameter is NULL.
    struct NullRRset : public InvalidParameter {
        NullRRset(const char* file, size_t line, const char* what) :
            InvalidParameter(file, line, what)
        { }
    };

183
184
185
186
187
188
189
190
191
192
    /// \brief Zone is empty exception.
    ///
    /// This is thrown if we have an empty zone created as a result of
    /// load().
    struct EmptyZone : public InvalidParameter {
        EmptyZone(const char* file, size_t line, const char* what) :
            InvalidParameter(file, line, what)
        { }
    };

193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
    /// \brief General failure exception for \c add().
    ///
    /// This is thrown against general error cases in adding an RRset
    /// to the zone.
    ///
    /// Note: this exception would cover cases for \c OutOfZone or
    /// \c NullRRset.  We'll need to clarify and unify the granularity
    /// of exceptions eventually.  For now, exceptions are added as
    /// developers see the need for it.
    struct AddError : public InvalidParameter {
        AddError(const char* file, size_t line, const char* what) :
            InvalidParameter(file, line, what)
        { }
    };

    /// Returns a \c ZoneTable result that best matches the given name.
    ///
    /// This derived version of the method never throws an exception.
    /// For other details see \c DataSourceClient::findZone().
212
213
214
215
216
217
218
219
    virtual isc::datasrc::memory::ZoneTable::FindResult
    findZone2(const isc::dns::Name& name) const;

    // This variant of findZone() is not implemented and should be
    // removed eventually. It currently throws an exception. It is
    // required right now to derive from DataSourceClient.
    virtual isc::datasrc::DataSourceClient::FindResult
    findZone(const isc::dns::Name& name) const;
220
221

    /// \brief Implementation of the getIterator method
222
223
    virtual isc::datasrc::ZoneIteratorPtr
    getIterator(const isc::dns::Name& name, bool separate_rrs = false) const;
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

    /// In-memory data source doesn't write back peristently, so this
    /// derived method will result in a NotImplemented exception.
    ///
    /// \note We plan to use a database-based data source as a backend
    /// persistent storage for an in-memory data source.  When it's
    /// implemented we may also want to allow the user of the in-memory client
    /// to update via its updater (this may or may not be a good idea and
    /// is subject to further discussions).
    virtual ZoneUpdaterPtr getUpdater(const isc::dns::Name& name,
                                      bool replace, bool journaling = false)
        const;

    virtual std::pair<ZoneJournalReader::Result, ZoneJournalReaderPtr>
    getJournalReader(const isc::dns::Name& zone, uint32_t begin_serial,
                     uint32_t end_serial) const;

private:
    // TODO: Do we still need the PImpl if nobody should manipulate this class
    // directly any more (it should be handled through DataSourceClient)?
    class InMemoryClientImpl;
    InMemoryClientImpl* impl_;
};

} // namespace memory
} // namespace datasrc
} // namespace isc

#endif // DATASRC_MEMORY_CLIENT_H

// Local Variables:
// mode: c++
// End: