summaryrefslogtreecommitdiffstats
path: root/src/lib/dhcpsrv/host_mgr.h
blob: e22146f4b61071940d21eb7df169facfe82b13fe (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
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
// Copyright (C) 2014-2020 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef HOST_MGR_H
#define HOST_MGR_H

#include <asiolink/io_service.h>
#include <database/database_connection.h>
#include <dhcpsrv/base_host_data_source.h>
#include <dhcpsrv/cache_host_data_source.h>
#include <dhcpsrv/host.h>
#include <dhcpsrv/subnet_id.h>
#include <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>
#include <string>

namespace isc {
namespace dhcp {

/// @brief Host Manager.
///
/// This is a singleton class which provides access to multiple sources of
/// information about static host reservations. These sources are also referred
/// to as host data sources. Each source derives (directly or indirectly) from
/// the @c BaseHostDataSource.
///
/// The @c HostMgr is a central point for providing information about the host
/// reservations. Internally, it relays the queries (calls to the appropriate
/// methods declared in the @c BaseHostDataSource) to the data sources it is
/// connected to. The @c HostMgr is always connected to the server's
/// configuration, accessible through the @c CfgHosts object in the @c CfgMgr.
/// The @c CfgHosts object holds all reservations specified in the DHCP server
/// configuration file. If a particular reservation is not found in the
/// @c CfgHosts object, the @c HostMgr will try to find it using alternate
/// host data storages. An alternate host data storage is usually a database
/// (e.g. SQL database), accessible through a dedicated host data source
/// object (a.k.a. database backend). This datasource is responsible for
/// managing the connection with the database and forming appropriate queries
/// to retrieve (or update) the information about the reservations.
///
/// The use of alternate host data sources is optional and usually requires
/// additional configuration to be specified by the server administrator.
/// For example, for the SQL database the user's credentials, database address,
/// and database name are required. The @c HostMgr passes these parameters
/// to an appropriate datasource which is responsible for opening a connection
/// and maintaining it.
///
/// It is possible to switch to different alternate data sources or disable
/// the use of alternate datasources, e.g. as a result of server's
/// reconfiguration. However, the use of the primary host data source (i.e.
/// reservations specified in the configuration file) can't be disabled.
class HostMgr : public boost::noncopyable, public BaseHostDataSource {
public:

    /// @brief Creates new instance of the @c HostMgr.
    ///
    /// If an instance of the @c HostMgr already exists, it will be replaced
    /// by the new instance. Thus, any instances of alternate host data
    /// sources will be dropped.
    ///
    static void create();

    /// @brief Add an alternate host backend (aka host data source).
    ///
    /// @param access Host backend access parameters for the alternate
    /// host backend. It holds "keyword=value" pairs, separated by spaces.
    ///
    /// The supported values are specific to the alternate backend in use.
    /// However, the "type" parameter will be common and it will specify which
    /// backend is to be used. Currently, no parameters are supported
    /// and the parameter is ignored.
    static void addBackend(const std::string& access);

    /// @brief Delete an alternate host backend (aka host data source).
    ///
    /// @param db_type database backend type.
    /// @return true when found and removed, false when not found.
    static bool delBackend(const std::string& db_type);

    /// @brief Delete an alternate host backend (aka host data source).
    ///
    /// @param db_type database backend type.
    /// @param access Host backend access parameters for the alternate
    /// host backend. It holds "keyword=value" pairs, separated by spaces.
    /// @param if_unusable flag which indicates if the host data source should
    /// be deleted only if it is unusable.
    /// @return true when found and removed, false when not found.
    static bool delBackend(const std::string& db_type,
                           const std::string& access,
                           bool if_unusable = false);

    /// @brief Delete all alternate backends.
    static void delAllBackends();

    /// @brief Check for the cache host backend.
    ///
    /// Checks if the first host backend implements
    /// the cache abstract class and sets cache_ptr_.
    ///
    /// @param logging When true (not the default) emit an informational log.
    /// @return true if the first host backend is a cache.
    static bool checkCacheBackend(bool logging = false);

    /// @brief Returns a sole instance of the @c HostMgr.
    ///
    /// This method should be used to retrieve an instance of the @c HostMgr
    /// to be used to gather/manage host reservations. It returns an instance
    /// of the @c HostMgr created by the @c create method. If such instance
    /// doesn't exist yet, it is created using the @c create method with the
    /// default value of the data access string, which configures the host
    /// manager to not use the alternate host data source.
    static HostMgr& instance();

    /// @brief Return all hosts connected to any subnet for which reservations
    /// have been made using a specified identifier.
    ///
    /// This method returns all @c Host objects representing reservations for
    /// a specified identifier as documented in the
    /// @c BaseHostDataSource::getAll.
    ///
    /// It retrieves reservations from both primary and alternate host data
    /// source as a single collection of @c Host objects, i.e. if matching
    /// reservations are in both sources, all of them are returned. The
    /// reservations from the primary data source are placed before the
    /// reservations from the alternate source.
    ///
    /// @param identifier_type Identifier type.
    /// @param identifier_begin Pointer to a beginning of a buffer containing
    /// an identifier.
    /// @param identifier_len Identifier length.
    ///
    /// @return Collection of const @c Host objects.
    virtual ConstHostCollection
    getAll(const Host::IdentifierType& identifier_type,
           const uint8_t* identifier_begin,
           const size_t identifier_len) const;

    /// @brief Return all hosts in a DHCPv4 subnet.
    ///
    /// This method returns all @c Host objects representing reservations
    /// in a specified subnet as documented in the
    /// @c BaseHostDataSource::getAll4
    ///
    /// It retrieves reservations from both primary and alternate host data
    /// source as a single collection of @c Host objects, i.e. if matching
    /// reservations are in both sources, all of them are returned. The
    /// reservations from the primary data source are placed before the
    /// reservations from the alternate source.
    ///
    /// @param subnet_id Subnet identifier.
    ///
    /// @return Collection of const @c Host objects.
    virtual ConstHostCollection
    getAll4(const SubnetID& subnet_id) const;

    /// @brief Return all hosts in a DHCPv6 subnet.
    ///
    /// This method returns all @c Host objects representing reservations
    /// in a specified subnet as documented in the
    /// @c BaseHostDataSource::getAll6
    ///
    /// It retrieves reservations from both primary and alternate host data
    /// source as a single collection of @c Host objects, i.e. if matching
    /// reservations are in both sources, all of them are returned. The
    /// reservations from the primary data source are placed before the
    /// reservations from the alternate source.
    ///
    /// @param subnet_id Subnet identifier.
    ///
    /// @return Collection of const @c Host objects.
    virtual ConstHostCollection
    getAll6(const SubnetID& subnet_id) const;

    /// @brief Return all hosts with a hostname.
    ///
    /// This method returns all @c Host objects which represent reservations
    /// using a specified hostname.
    ///
    /// @param hostname The lower case hostname.
    ///
    /// @return Collection of const @c Host objects.
    virtual ConstHostCollection
    getAllbyHostname(const std::string& hostname) const;

    /// @brief Return all hosts with a hostname in a DHCPv4 subnet.
    ///
    /// This method returns all @c Host objects which represent reservations
    /// using a specified hostname in a specified subnet.
    ///
    /// @param hostname The lower case hostname.
    /// @param subnet_id Subnet identifier.
    ///
    /// @return Collection of const @c Host objects.
    virtual ConstHostCollection
    getAllbyHostname4(const std::string& hostname, const SubnetID& subnet_id) const;

    /// @brief Return all hosts with a hostname in a DHCPv6 subnet.
    ///
    /// This method returns all @c Host objects which represent reservations
    /// using a specified hostname in a specified subnet.
    ///
    /// @param hostname The lower case hostname.
    /// @param subnet_id Subnet identifier.
    ///
    /// @return Collection of const @c Host objects.
    virtual ConstHostCollection
    getAllbyHostname6(const std::string& hostname, const SubnetID& subnet_id) const;

    /// @brief Returns range of hosts in a DHCPv4 subnet.
    ///
    /// This method returns a page of @c Host objects representing
    /// reservations in a specified subnet as documented in the
    /// @c BaseHostDataSource::getPage4
    ///
    /// The typical usage of this method is as follows:
    /// - Get the first page of hosts by specifying zero index and id
    ///   as the beginning of the range.
    /// - Index and last id of the returned range should be used as
    ///   starting index and id for the next page in the subsequent call.
    /// - All returned hosts are from the same source so if the number of
    ///   hosts returned is lower than the page size, it does not indicate
    ///   that the last page has been retrieved.
    /// - If there are no hosts returned it indicates that the previous page
    ///   was the last page.
    ///
    /// @param subnet_id Subnet identifier.
    /// @param source_index Index of the source.
    /// @param lower_host_id Host identifier used as lower bound for the
    /// returned range.
    /// @param page_size maximum size of the page returned.
    ///
    /// @return Host collection (may be empty).
    virtual ConstHostCollection
    getPage4(const SubnetID& subnet_id,
             size_t& source_index,
             uint64_t lower_host_id,
             const HostPageSize& page_size) const;

    /// @brief Returns range of hosts in a DHCPv6 subnet.
    ///
    /// This method returns a page of @c Host objects representing
    /// reservations in a specified subnet as documented in the
    /// @c BaseHostDataSource::getPage6
    ///
    /// The typical usage of this method is as follows:
    /// - Get the first page of hosts by specifying zero index and id
    ///   as the beginning of the range.
    /// - Index and last id of the returned range should be used as
    ///   starting index and id for the next page in the subsequent call.
    /// - All returned hosts are from the same source so if the number of
    ///   hosts returned is lower than the page size, it does not indicate
    ///   that the last page has been retrieved.
    /// - If there are no hosts returned it indicates that the previous page
    ///   was the last page.
    ///
    /// @param subnet_id Subnet identifier.
    /// @param source_index Index of the source.
    /// @param lower_host_id Host identifier used as lower bound for the
    /// returned range.
    /// @param page_size maximum size of the page returned.
    ///
    /// @return Host collection (may be empty).
    virtual ConstHostCollection
    getPage6(const SubnetID& subnet_id,
             size_t& source_index,
             uint64_t lower_host_id,
             const HostPageSize& page_size) const;

    /// @brief Returns range of hosts.
    ///
    /// This method returns a page of @c Host objects representing
    /// reservations as documented in the @c BaseHostDataSource::getPage4
    ///
    /// The typical usage of this method is as follows:
    /// - Get the first page of hosts by specifying zero index and id
    ///   as the beginning of the range.
    /// - Index and last id of the returned range should be used as
    ///   starting index and id for the next page in the subsequent call.
    /// - All returned hosts are from the same source so if the number of
    ///   hosts returned is lower than the page size, it does not indicate
    ///   that the last page has been retrieved.
    /// - If there are no hosts returned it indicates that the previous page
    ///   was the last page.
    ///
    /// @param source_index Index of the source.
    /// @param lower_host_id Host identifier used as lower bound for the
    /// returned range.
    /// @param page_size maximum size of the page returned.
    ///
    /// @return Host collection (may be empty).
    virtual ConstHostCollection
    getPage4(size_t& source_index,
             uint64_t lower_host_id,
             const HostPageSize& page_size) const;

    /// @brief Returns range of hosts.
    ///
    /// This method returns a page of @c Host objects representing
    /// reservations as documented in the @c BaseHostDataSource::getPage6
    ///
    /// The typical usage of this method is as follows:
    /// - Get the first page of hosts by specifying zero index and id
    ///   as the beginning of the range.
    /// - Index and last id of the returned range should be used as
    ///   starting index and id for the next page in the subsequent call.
    /// - All returned hosts are from the same source so if the number of
    ///   hosts returned is lower than the page size, it does not indicate
    ///   that the last page has been retrieved.
    /// - If there are no hosts returned it indicates that the previous page
    ///   was the last page.
    ///
    /// @param source_index Index of the source.
    /// @param lower_host_id Host identifier used as lower bound for the
    /// returned range.
    /// @param page_size maximum size of the page returned.
    ///
    /// @return Host collection (may be empty).
    virtual ConstHostCollection
    getPage6(size_t& source_index,
             uint64_t lower_host_id,
             const HostPageSize& page_size) const;

    /// @brief Returns a collection of hosts using the specified IPv4 address.
    ///
    /// This method may return multiple @c Host objects if they are connected to
    /// different subnets.
    ///
    /// If matching reservations are both in the primary and the alternate
    /// data source, all of them are returned. The reservations from the
    /// primary data source are placed before the reservations from the
    /// alternate source.
    ///
    /// @param address IPv4 address for which the @c Host object is searched.
    ///
    /// @return Collection of const @c Host objects.
    virtual ConstHostCollection
    getAll4(const asiolink::IOAddress& address) const;

    /// @brief Returns any host connected to the IPv4 subnet.
    ///
    /// This method returns a single reservation for a particular host as
    /// documented in the @c BaseHostDataSource::get4 even when the
    /// reservation is marked as from negative caching. This allows to
    /// monitor negative caching.
    ///
    /// @param subnet_id Subnet identifier.
    /// @param identifier_type Identifier type.
    /// @param identifier_begin Pointer to a beginning of a buffer containing
    /// an identifier.
    /// @param identifier_len Identifier length.
    ///
    /// @return Const @c Host object for which reservation has been made using
    /// the specified identifier.
    virtual ConstHostPtr
    get4Any(const SubnetID& subnet_id,
            const Host::IdentifierType& identifier_type,
            const uint8_t* identifier_begin,
            const size_t identifier_len) const;

    /// @brief Returns a host connected to the IPv4 subnet.
    ///
    /// This method returns a single reservation for a particular host as
    /// documented in the @c BaseHostDataSource::get4.
    ///
    /// @param subnet_id Subnet identifier.
    /// @param identifier_type Identifier type.
    /// @param identifier_begin Pointer to a beginning of a buffer containing
    /// an identifier.
    /// @param identifier_len Identifier length.
    ///
    /// @return Const @c Host object for which reservation has been made using
    /// the specified identifier.
    virtual ConstHostPtr
    get4(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
         const uint8_t* identifier_begin, const size_t identifier_len) const;

    /// @brief Returns a host connected to the IPv4 subnet and having
    /// a reservation for a specified IPv4 address.
    ///
    /// This method returns a single reservation for the particular host
    /// (identified by the HW address or DUID) as documented in the
    /// @c BaseHostDataSource::get4.
    ///
    /// @param subnet_id Subnet identifier.
    /// @param address reserved IPv4 address.
    ///
    /// @return Const @c Host object using a specified IPv4 address.
    virtual ConstHostPtr
    get4(const SubnetID& subnet_id, const asiolink::IOAddress& address) const;

    /// @brief Returns all hosts connected to the IPv4 subnet and having
    /// a reservation for a specified address.
    ///
    /// In most cases it is desired that there is at most one reservation
    /// for a given IPv4 address within a subnet. In a default configuration,
    /// the backend does not allow for inserting more than one host with
    /// the same IPv4 reservation. In that case, the number of hosts returned
    /// by this function is 0 or 1.
    ///
    /// If the backend is configured to allow multiple hosts with reservations
    /// for the same IPv4 address in the given subnet, this method can return
    /// more than one host.
    ///
    /// The typical use case when a single IPv4 address is reserved for multiple
    /// hosts is when these hosts represent different interfaces of the same
    /// machine and each interface comes with a different MAC address. In that
    /// case, the same IPv4 address is assigned regardless of which interface is
    /// used by the DHCP client to communicate with the server.
    ///
    /// @param subnet_id Subnet identifier.
    /// @param address reserved IPv4 address.
    ///
    /// @return Collection of const @c Host objects.
    virtual ConstHostCollection
    getAll4(const SubnetID& subnet_id,
            const asiolink::IOAddress& address) const;

    /// @brief Returns any host connected to the IPv6 subnet.
    ///
    /// This method returns a host connected to the IPv6 subnet as described
    /// in the @c BaseHostDataSource::get6 even when the
    /// reservation is marked as from negative caching. This allows to
    /// monitor negative caching.
    ///
    /// @param subnet_id Subnet identifier.
    /// @param identifier_type Identifier type.
    /// @param identifier_begin Pointer to a beginning of a buffer containing
    /// an identifier.
    /// @param identifier_len Identifier length.
    ///
    /// @return Const @c Host object for which reservation has been made using
    /// the specified identifier.
    virtual ConstHostPtr
    get6Any(const SubnetID& subnet_id,
            const Host::IdentifierType& identifier_type,
            const uint8_t* identifier_begin,
            const size_t identifier_len) const;

    /// @brief Returns a host connected to the IPv6 subnet.
    ///
    /// This method returns a host connected to the IPv6 subnet as described
    /// in the @c BaseHostDataSource::get6.
    ///
    /// @param subnet_id Subnet identifier.
    /// @param identifier_type Identifier type.
    /// @param identifier_begin Pointer to a beginning of a buffer containing
    /// an identifier.
    /// @param identifier_len Identifier length.
    ///
    /// @return Const @c Host object for which reservation has been made using
    /// the specified identifier.
    virtual ConstHostPtr
    get6(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
         const uint8_t* identifier_begin, const size_t identifier_len) const;

    /// @brief Returns a host using the specified IPv6 prefix.
    ///
    /// This method returns a host using specified IPv6 prefix, as described
    /// in the @c BaseHostDataSource::get6.
    ///
    /// @param prefix IPv6 prefix for which the @c Host object is searched.
    /// @param prefix_len IPv6 prefix length.
    ///
    /// @return Const @c Host object using a specified IPv6 prefix.
    virtual ConstHostPtr
    get6(const asiolink::IOAddress& prefix, const uint8_t prefix_len) const;

    /// @brief Returns a host from specific subnet and reserved address.
    ///
    /// @param subnet_id subnet identifier.
    /// @param addr specified address.
    ///
    /// @return Const @c host object that has a reservation for specified address.
    virtual ConstHostPtr
    get6(const SubnetID& subnet_id, const asiolink::IOAddress& addr) const;

    /// @brief Returns all hosts connected to the IPv6 subnet and having
    /// a reservation for a specified address or delegated prefix (lease).
    ///
    /// In most cases it is desired that there is at most one reservation
    /// for a given IPv6 lease within a subnet. In a default configuration,
    /// the backend does not allow for inserting more than one host with
    /// the same IPv6 address or prefix. In that case, the number of hosts
    /// returned by this function is 0 or 1.
    ///
    /// If the backend is configured to allow multiple hosts with reservations
    /// for the same IPv6 lease in the given subnet, this method can return
    /// more than one host.
    ///
    /// The typical use case when a single IPv6 lease is reserved for multiple
    /// hosts is when these hosts represent different interfaces of the same
    /// machine and each interface comes with a different MAC address. In that
    /// case, the same IPv6 lease is assigned regardless of which interface is
    /// used by the DHCP client to communicate with the server.
    ///
    /// @param subnet_id Subnet identifier.
    /// @param address reserved IPv6 address/prefix.
    ///
    /// @return Collection of const @c Host objects.
    virtual ConstHostCollection
    getAll6(const SubnetID& subnet_id,
            const asiolink::IOAddress& address) const;

    /// @brief Adds a new host to the alternate data source.
    ///
    /// This method will throw an exception if no alternate data source is
    /// in use.
    ///
    /// @param host Pointer to the new @c Host object being added.
    virtual void add(const HostPtr& host);

    /// @brief Attempts to delete hosts by address.
    ///
    /// It deletes hosts from the first alternate source in which at least
    /// one matching host is found. In unlikely case that the hosts having
    /// the same IP address exist in other alternate sources, the hosts
    /// from these other sources are not deleted.
    ///
    /// This method supports both v4 and v6.
    ///
    /// @param subnet_id subnet identifier.
    /// @param addr specified address.
    /// @return true if deletion was successful, false otherwise.
    virtual bool del(const SubnetID& subnet_id, const asiolink::IOAddress& addr);

    /// @brief Attempts to delete a host by (subnet4-id, identifier, identifier-type)
    ///
    /// This method supports v4 only.
    ///
    /// @param subnet_id IPv4 Subnet identifier.
    /// @param identifier_type Identifier type.
    /// @param identifier_begin Pointer to a beginning of a buffer containing
    /// an identifier.
    /// @param identifier_len Identifier length.
    /// @return true if deletion was successful, false otherwise.
    virtual bool
    del4(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
         const uint8_t* identifier_begin, const size_t identifier_len);

    /// @brief Attempts to delete a host by (subnet6-id, identifier, identifier-type)
    ///
    /// This method supports v6 only.
    ///
    /// @param subnet_id IPv6 Subnet identifier.
    /// @param identifier_type Identifier type.
    /// @param identifier_begin Pointer to a beginning of a buffer containing
    /// an identifier.
    /// @param identifier_len Identifier length.
    /// @return true if deletion was successful, false otherwise.
    virtual bool
    del6(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
         const uint8_t* identifier_begin, const size_t identifier_len);

    /// @brief Return backend type
    ///
    /// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
    ///
    /// @return Type of the backend.
    virtual std::string getType() const {
        return (std::string("host_mgr"));
    }

    /// @brief Returns the host data source list.
    ///
    /// @return reference to the host data source list.
    HostDataSourceList& getHostDataSourceList() {
        return (alternate_sources_);
    }

    /// @brief Returns the first host data source.
    ///
    /// May return NULL if the host data source list is empty.
    /// @return pointer to the first host data source (or NULL).
    HostDataSourcePtr getHostDataSource() const;

    /// @brief Returns the negative caching flag.
    ///
    /// @return the negative caching flag.
    bool getNegativeCaching() const {
        return (negative_caching_);
    }

    /// @brief Sets the negative caching flag.
    ///
    void setNegativeCaching(bool negative_caching) {
        negative_caching_ = negative_caching;
    }

    /// @brief Returns the disable single query flag.
    ///
    /// @return the disable single query flag.
    bool getDisableSingleQuery() const {
        return (disable_single_query_);
    }

    /// @brief Sets the disable single query flag.
    ///
    void setDisableSingleQuery(bool disable_single_query) {
        disable_single_query_ = disable_single_query;
    }

    /// @brief Controls whether IP reservations are unique or non-unique.
    ///
    /// In a typical case, the IP reservations are unique and backends verify
    /// prior to adding a host reservation to the database that the reservation
    /// for a given IP address/subnet does not exist. In some cases it may be
    /// required to allow non-unique IP reservations, e.g. in the case when a
    /// host has several interfaces and independently of which interface is used
    /// by this host to communicate with the DHCP server the same IP address
    /// should be assigned. In this case the @c unique value should be set to
    /// false to disable the checks for uniqueness on the backend side.
    ///
    /// Calling this function on @c HostMgr causes the manager to attempt to
    /// set this flag on all backends in use.
    ///
    /// @param unique boolean flag indicating if the IP reservations must be
    /// unique or can be non-unique.
    /// @return true if the new setting was accepted by the backend or false
    /// otherwise.
    virtual bool setIPReservationsUnique(const bool unique);

    /// @brief Returns the boolean flag indicating if the IP reservations
    /// must be unique or can be non-unique.
    ///
    /// @return true if IP reservations must be unique or false if IP
    /// reservations can be non-unique.
    bool getIPReservationsUnique() const {
        return (ip_reservations_unique_);
    }

    /// @brief Sets IO service to be used by the Host Manager.
    ///
    /// @param IOService object, used for all ASIO operations.
    static void setIOService(const isc::asiolink::IOServicePtr& io_service) {
        io_service_ = io_service;
    }

    /// @brief Returns pointer to the IO service.
    static isc::asiolink::IOServicePtr& getIOService() {
        return (io_service_);
    }

protected:

    /// @brief The negative caching flag.
    ///
    /// When true and the first backend is a cache
    /// negative answers are inserted in the cache.
    /// This works for get[46] for a subnet and an identifier.
    bool negative_caching_;

    /// @brief The disable single query flag.
    ///
    /// When true prevent the use of lookup methods returning a collection
    /// aka single queries when methods returning a host object are usable
    /// instead.
    bool disable_single_query_;

    /// @brief Cache an answer.
    ///
    /// @param host Pointer to the missed host.
    virtual void cache(ConstHostPtr host) const;

    /// @brief Cache a negative answer.
    ///
    /// @param ipv4_subnet_id Identifier of the IPv4 subnet.
    /// @param ipv6_subnet_id Identifier of the IPv6 subnet.
    /// @param identifier_type Identifier type.
    /// @param identifier_begin Pointer to a beginning of the Identifier.
    /// @param identifier_len Identifier length.
    virtual void cacheNegative(const SubnetID& ipv4_subnet_id,
                               const SubnetID& ipv6_subnet_id,
                               const Host::IdentifierType& identifier_type,
                               const uint8_t* identifier_begin,
                               const size_t identifier_len) const;

private:

    /// @brief Indicates if backends are running in the mode in which IP
    /// reservations must be unique (true) or non-unique (false).
    ///
    /// This flag is set to false only after calling @c setIPReservationsUnique
    /// with the @c unique value set to false and after this setting was
    /// successfully applied to all backends.
    bool ip_reservations_unique_;

    /// @brief Private default constructor.
    HostMgr() : negative_caching_(false), disable_single_query_(false),
                ip_reservations_unique_(true) { }

    /// @brief List of alternate host data sources.
    HostDataSourceList alternate_sources_;

    /// @brief Pointer to the cache.
    CacheHostDataSourcePtr cache_ptr_;

    /// @brief Returns a pointer to the currently used instance of the
    /// @c HostMgr.
    static boost::scoped_ptr<HostMgr>& getHostMgrPtr();

    /// The IOService object, used for all ASIO operations.
    static isc::asiolink::IOServicePtr io_service_;
};

}  // namespace dhcp
}  // namespace isc

#endif // HOST_MGR_H