Kea  1.9.9-git
cql_host_data_source.cc
Go to the documentation of this file.
1 // Copyright (C) 2018-2021 Internet Systems Consortium, Inc. ("ISC")
2 // Copyright (C) 2016-2017 Deutsche Telekom AG.
3 //
4 // Author: Andrei Pavel <andrei.pavel@qualitance.com>
5 //
6 // Licensed under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 // You may obtain a copy of the License at
9 //
10 // http://www.apache.org/licenses/LICENSE-2.0
11 //
12 // Unless required by applicable law or agreed to in writing, software
13 // distributed under the License is distributed on an "AS IS" BASIS,
14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 // See the License for the specific language governing permissions and
16 // limitations under the License.
17 
18 #include <config.h>
19 
20 #include <cql/cql_exchange.h>
21 #include <database/db_exceptions.h>
23 #include <dhcp/duid.h>
24 #include <dhcp/libdhcp++.h>
25 #include <dhcp/option.h>
26 #include <dhcp/option_definition.h>
27 #include <dhcpsrv/cfg_option.h>
28 #include <dhcpsrv/cfgmgr.h>
29 #include <dhcpsrv/dhcpsrv_log.h>
30 #include <util/buffer.h>
31 #include <util/hash.h>
32 #include <util/optional.h>
33 #include <asiolink/io_address.h>
34 
35 #include <stdint.h> // for uint64_t
36 
37 #include <boost/algorithm/string/classification.hpp> // for boost::is_any_of
38 #include <boost/algorithm/string/split.hpp> // for split
39 #include <boost/assert.hpp> // for BOOST_ASSERT
40 #include <boost/unordered_map.hpp> // for std::unordered_map
41 
42 #include <iosfwd> // for size_t, std::stringstream
43 #include <memory> // for std::unique_ptr
44 #include <string> // for std::string
45 
46 using namespace isc::asiolink;
47 using namespace isc::db;
48 using namespace isc::dhcp;
49 using namespace isc::util;
50 using namespace isc::data;
51 
52 namespace {
53 
55 typedef std::vector<uint8_t> HostIdentifier;
56 
60 typedef std::
61  tuple<HostIdentifier, Host::IdentifierType, SubnetID, SubnetID, IOAddress> HostKey;
62 
65  HOST_IDENTIFIER,
66  HOST_IDENTIFIER_TYPE,
67  IPv4_SUBNET_ID,
68  IPv6_SUBNET_ID,
69  IPv4_RESERVATION
70 };
71 
74 typedef std::unordered_map<HostKey, HostPtr, boost::hash<HostKey>> HostMap;
75 
77 typedef std::pair<HostKey, HostPtr> HostPair;
78 
80 struct OptionWrapper {
81  OptionWrapper(OptionDescriptorPtr option_descriptor, std::string option_space)
82  : option_descriptor_(option_descriptor), option_space_(option_space) {
83  }
84  OptionDescriptorPtr option_descriptor_;
85  std::string option_space_;
86 };
87 
91 static constexpr cass_int32_t MAX_IDENTIFIER_TYPE = static_cast<cass_int32_t>(Host::IDENT_FLEX);
92 
95 static constexpr char NULL_DHCP4_SERVER_HOSTNAME[] = "";
96 static constexpr char NULL_DHCP4_BOOT_FILE_NAME[] = "";
97 static constexpr char NULL_USER_CONTEXT[] = "";
98 static constexpr char NULL_RESERVED_IPV6_PREFIX_ADDRESS[] = "::";
99 static constexpr cass_int32_t NULL_RESERVED_IPV6_PREFIX_LENGTH = 0;
100 static constexpr cass_int32_t NULL_RESERVED_IPV6_PREFIX_ADDRESS_TYPE = -1;
101 static constexpr cass_int32_t NULL_IAID = -1;
102 static constexpr cass_int32_t NULL_OPTION_UNIVERSE = -1;
103 static constexpr cass_int32_t NULL_OPTION_CODE = -1;
104 static const CassBlob NULL_OPTION_VALUE = CassBlob();
105 static constexpr char NULL_OPTION_FORMATTED_VALUE[] = "";
106 static constexpr char NULL_OPTION_SPACE[] = "";
107 static constexpr cass_bool_t NULL_OPTION_IS_PERSISTENT = cass_false;
108 static constexpr char NULL_OPTION_CLIENT_CLASS[] = "";
109 static constexpr cass_int32_t NULL_OPTION_SUBNET_ID = -1;
110 static constexpr char NULL_OPTION_USER_CONTEXT[] = "";
111 static constexpr cass_int32_t NULL_OPTION_SCOPE_ID = -1;
113 
116 static const IPv6Resrv NULL_IPV6_RESERVATION =
117  IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("::"), 128);
118 
119 } // namespace
120 
121 namespace isc {
122 namespace dhcp {
123 
126 class CqlHostExchange : public virtual CqlExchange {
127 public:
131  CqlHostExchange();
132 
134  virtual ~CqlHostExchange();
135 
146  virtual void
147  createBindForSelect(AnyArray& data, StatementTag statement_tag = NULL) override;
148 
158  void prepareExchange(const HostPtr& host,
159  const Optional<SubnetID>& subnet_id,
160  const IPv6Resrv* const reservation,
161  const std::string& option_space,
162  const OptionDescriptor& option_descriptor);
163 
177  void createBindForMutation(const HostPtr& host,
178  const Optional<SubnetID>& subnet_id,
179  const IPv6Resrv* const reservation,
180  const std::string& option_space,
181  const OptionDescriptor& option_descriptor,
182  StatementTag statement_tag,
183  AnyArray& data);
184 
198  void createBindForDelete(const HostPtr& host,
199  const Optional<SubnetID>& subnet_id,
200  const IPv6Resrv* const reservation,
201  const std::string& option_space,
202  const OptionDescriptor& option_descriptor,
203  StatementTag statement_tag,
204  AnyArray& data);
205 
216  uint64_t hashIntoId() const;
217 
223  uint64_t hashIntoKey() const;
224 
230  std::string hostKey() const;
231 
239  virtual boost::any retrieve() override;
240 
247  const IPv6Resrv retrieveReservation() const;
248 
255  const OptionWrapper retrieveOption() const;
256 
259  // Inserts all parameters belonging to any reservation from a single host.
260  static constexpr StatementTag INSERT_HOST = "INSERT_HOST";
261 
262  // Retrieves host information, IPv6 reservations and both IPv4 and IPv6
263  // options associated with it.
264  static constexpr StatementTag GET_HOST = "GET_HOST";
265 
266  // Retrieves host information, IPv6 reservations and both IPv4 and IPv6
267  // options associated with it.
268  static constexpr StatementTag GET_HOST_BY_HOST_ID = "GET_HOST_BY_HOST_ID";
269 
270  // Retrieves host information along with the IPv4 options associated
271  // with it.
272  static constexpr StatementTag GET_HOST_BY_IPV4_ADDRESS = "GET_HOST_BY_IPV4_ADDRESS";
273 
274  // Retrieves host information and IPv4 options using subnet identifier
275  // and client's identifier (i.e. hardware address or DUID).
276  static constexpr StatementTag GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID =
277  "GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID";
278 
279  // Retrieves host information; IPv6 reservations and IPv6 options
280  // associated with it using subnet identifier and client's
281  // identifier (i.e. hardware address or DUID).
282  static constexpr StatementTag GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID =
283  "GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID";
284 
285  // Retrieves host information and IPv4 options for the host using subnet
286  // identifier and IPv4 reservation.
287  static constexpr StatementTag GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS =
288  "GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS";
289 
290  // Retrieves host information, IPv6 reservations and IPv6 options
291  // associated with it using prefix and prefix length. The query returns
292  // host information for a single host. However, multiple rows are returned
293  // due to left joining IPv6 reservations and IPv6 options. The number of
294  // rows returned is multiplication of number of existing IPv6 reservations
295  // and IPv6 options.
296  static constexpr StatementTag GET_HOST_BY_IPV6_PREFIX = "GET_HOST_BY_IPV6_PREFIX";
297 
298  // Retrieves host information and IPv6 options for the host using subnet
299  // identifier and IPv6 reservation.
300  static constexpr StatementTag GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS =
301  "GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS";
302 
303  // Deletes a host reservation.
304  static constexpr StatementTag DELETE_HOST =
305  "DELETE_HOST";
306 
307  // Retrieves host information along with the IPv4 options associated
308  // with it using a subnet identifier.
309  static constexpr StatementTag GET_HOST_BY_IPV4_SUBNET_ID =
310  "GET_HOST_BY_IPV4_SUBNET_ID";
311 
312  // Retrieves host information; IPv6 reservations and IPv6 options
313  // associated with a host using subnet identifier.
314  static constexpr StatementTag GET_HOST_BY_IPV6_SUBNET_ID =
315  "GET_HOST_BY_IPV6_SUBNET_ID";
316 
317  // Retrieves host information, IPv6 reservations and both IPv4 and IPv6
318  // options associated with it using hostname.
319  static constexpr StatementTag GET_HOST_BY_HOST_NAME =
320  "GET_HOST_BY_HOST_NAME";
321 
322  // Retrieves host information along with the IPv4 options associated
323  // with it using hostname and subnet identifier.
324  static constexpr StatementTag GET_HOST_BY_HOST_NAME_AND_IPV4_SUBNET_ID =
325  "GET_HOST_BY_HOST_NAME_AND_IPV4_SUBNET_ID";
326 
327  // Retrieves host information; IPv6 reservations and IPv6 options
328  // associated with it using hostname and subnet identifier.
329  static constexpr StatementTag GET_HOST_BY_HOST_NAME_AND_IPV6_SUBNET_ID =
330  "GET_HOST_BY_HOST_NAME_AND_IPV6_SUBNET_ID";
331 
332  // Retrieves host information along with the IPv4 options associated
333  // with it using a subnet identifier from first host (paging).
334  static constexpr StatementTag GET_HOST_BY_IPV4_SUBNET_ID_LIMIT =
335  "GET_HOST_BY_IPV4_SUBNET_ID_LIMIT";
336 
337  // Retrieves host information along with the IPv4 options associated
338  // with it using a subnet identifier from next host (paging).
339  static constexpr StatementTag GET_HOST_BY_IPV4_SUBNET_ID_NEXT_KEY =
340  "GET_HOST_BY_IPV4_SUBNET_ID_NEXT_KEY";
341 
342  // Retrieves host information along with the IPv4 options associated
343  // with it using a subnet identifier from host with a limit (paging).
344  static constexpr StatementTag GET_HOST_BY_IPV4_SUBNET_ID_PAGE =
345  "GET_HOST_BY_IPV4_SUBNET_ID_PAGE";
346 
347  // Retrieves host information; IPv6 reservations and IPv6 options
348  // associated with it using subnet identifier from first host (paging).
349  static constexpr StatementTag GET_HOST_BY_IPV6_SUBNET_ID_LIMIT =
350  "GET_HOST_BY_IPV6_SUBNET_ID_LIMIT";
351 
352  // Retrieves host information; IPv6 reservations and IPv6 options
353  // associated with it using subnet identifier from next host (paging).
354  static constexpr StatementTag GET_HOST_BY_IPV6_SUBNET_ID_NEXT_KEY =
355  "GET_HOST_BY_IPV6_SUBNET_ID_NEXT_KEY";
356 
357  // Retrieves host information; IPv6 reservations and IPv6 options
358  // associated with it using subnet identifier from host with a limit
359  // (paging).
360  static constexpr StatementTag GET_HOST_BY_IPV6_SUBNET_ID_PAGE =
361  "GET_HOST_BY_IPV6_SUBNET_ID_PAGE";
362 
363  // Retrieves host information; reservations and options associated
364  // with it from first host (paging).
365  static constexpr StatementTag GET_HOST_LIMIT = "GET_HOST_LIMIT";
366 
367  // Retrieves host information; reservations and options associated
368  // with it from host (paging).
369  static constexpr StatementTag GET_HOST_KEY = "GET_HOST_KEY";
370 
371  // Retrieves host information; reservations and options associated
372  // with it from next host (paging).
373  static constexpr StatementTag GET_HOST_NEXT_KEY = "GET_HOST_NEXT_KEY";
374 
375  // Retrieves host information; reservations and options associated
376  // with it from host with a limit (paging).
377  static constexpr StatementTag GET_HOST_PAGE = "GET_HOST_PAGE";
379 
382 
383 private:
385  HostPtr host_;
386 
390  cass_int64_t key_;
391 
395  cass_int64_t id_;
396 
398  CassBlob host_identifier_;
399 
402  cass_int32_t host_identifier_type_;
403 
405  cass_int32_t host_ipv4_subnet_id_;
406 
408  cass_int32_t host_ipv6_subnet_id_;
409 
411  cass_int32_t host_ipv4_address_;
412 
414  cass_int32_t host_ipv4_next_server_;
415 
417  std::string host_ipv4_server_hostname_;
418 
420  std::string host_ipv4_boot_file_name_;
421 
423  std::string auth_key_;
424 
426  std::string hostname_;
427 
429  std::string lower_case_hostname_;
430 
432  std::string user_context_;
433 
435  std::string host_ipv4_client_classes_;
436 
438  std::string host_ipv6_client_classes_;
439 
441  std::string reserved_ipv6_prefix_address_;
442 
444  cass_int32_t reserved_ipv6_prefix_length_;
445 
448  cass_int32_t reserved_ipv6_prefix_address_type_;
449 
451  cass_int32_t iaid_;
452 
455  cass_int32_t option_universe_;
456 
458  cass_int32_t option_code_;
459 
461  CassBlob option_value_;
462 
464  std::string option_formatted_value_;
465 
467  std::string option_space_;
468 
470  cass_bool_t option_is_persistent_;
471 
473  std::string option_client_class_;
474 
476  cass_int32_t option_subnet_id_;
477 
479  std::string option_user_context_;
480 
482  cass_int32_t option_scope_id_;
483 }; // CqlHostExchange
484 
485 constexpr StatementTag CqlHostExchange::INSERT_HOST;
486 constexpr StatementTag CqlHostExchange::GET_HOST;
487 constexpr StatementTag CqlHostExchange::GET_HOST_BY_HOST_ID;
488 constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV4_ADDRESS;
489 constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID;
490 constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID;
491 constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS;
492 constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV6_PREFIX;
493 constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS;
494 constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID;
495 constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID;
496 constexpr StatementTag CqlHostExchange::GET_HOST_BY_HOST_NAME;
497 constexpr StatementTag CqlHostExchange::GET_HOST_BY_HOST_NAME_AND_IPV4_SUBNET_ID;
498 constexpr StatementTag CqlHostExchange::GET_HOST_BY_HOST_NAME_AND_IPV6_SUBNET_ID;
499 constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_LIMIT;
500 constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_LIMIT;
501 constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_NEXT_KEY;
502 constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_NEXT_KEY;
503 constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_PAGE;
504 constexpr StatementTag CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_PAGE;
505 constexpr StatementTag CqlHostExchange::GET_HOST_LIMIT;
506 constexpr StatementTag CqlHostExchange::GET_HOST_NEXT_KEY;
507 constexpr StatementTag CqlHostExchange::GET_HOST_KEY;
508 constexpr StatementTag CqlHostExchange::GET_HOST_PAGE;
509 constexpr StatementTag CqlHostExchange::DELETE_HOST;
510 
511 StatementMap CqlHostExchange::tagged_statements_ = {
512  {INSERT_HOST,
513  {INSERT_HOST,
514  "INSERT INTO hosts ( "
515  "key, "
516  "id, "
517  "host_identifier, "
518  "host_identifier_type, "
519  "host_ipv4_subnet_id, "
520  "host_ipv6_subnet_id, "
521  "host_ipv4_address, "
522  "host_ipv4_next_server, "
523  "host_ipv4_server_hostname, "
524  "host_ipv4_boot_file_name, "
525  "auth_key, "
526  "hostname, "
527  "lower_case_hostname, "
528  "user_context, "
529  "host_ipv4_client_classes, "
530  "host_ipv6_client_classes, "
531  "reserved_ipv6_prefix_address, "
532  "reserved_ipv6_prefix_length, "
533  "reserved_ipv6_prefix_address_type, "
534  "iaid, "
535  "option_universe, "
536  "option_code, "
537  "option_value, "
538  "option_formatted_value, "
539  "option_space, "
540  "option_is_persistent, "
541  "option_client_class, "
542  "option_subnet_id, "
543  "option_user_context, "
544  "option_scope_id "
545  ") VALUES ( "
546  // key
547  "?, "
548  // id
549  "?, "
550  // host
551  "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, "
552  // denormalized reservation, option
553  "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? "
554  ") "
555  "IF NOT EXISTS "
556  }},
557 
558  {GET_HOST,
559  {GET_HOST,
560  "SELECT "
561  "key, "
562  "id, "
563  "host_identifier, "
564  "host_identifier_type, "
565  "host_ipv4_subnet_id, "
566  "host_ipv6_subnet_id, "
567  "host_ipv4_address, "
568  "host_ipv4_next_server, "
569  "host_ipv4_server_hostname, "
570  "host_ipv4_boot_file_name, "
571  "auth_key, "
572  "hostname, "
573  "user_context, "
574  "host_ipv4_client_classes, "
575  "host_ipv6_client_classes, "
576  "reserved_ipv6_prefix_address, "
577  "reserved_ipv6_prefix_length, "
578  "reserved_ipv6_prefix_address_type, "
579  "iaid, "
580  "option_universe, "
581  "option_code, "
582  "option_value, "
583  "option_formatted_value, "
584  "option_space, "
585  "option_is_persistent, "
586  "option_client_class, "
587  "option_subnet_id, "
588  "option_user_context, "
589  "option_scope_id "
590  "FROM hosts "
591  }},
592 
593  {GET_HOST_BY_HOST_ID,
594  {GET_HOST_BY_HOST_ID,
595  "SELECT "
596  "key, "
597  "id, "
598  "host_identifier, "
599  "host_identifier_type, "
600  "host_ipv4_subnet_id, "
601  "host_ipv6_subnet_id, "
602  "host_ipv4_address, "
603  "host_ipv4_next_server, "
604  "host_ipv4_server_hostname, "
605  "host_ipv4_boot_file_name, "
606  "auth_key, "
607  "hostname, "
608  "user_context, "
609  "host_ipv4_client_classes, "
610  "host_ipv6_client_classes, "
611  "reserved_ipv6_prefix_address, "
612  "reserved_ipv6_prefix_length, "
613  "reserved_ipv6_prefix_address_type, "
614  "iaid, "
615  "option_universe, "
616  "option_code, "
617  "option_value, "
618  "option_formatted_value, "
619  "option_space, "
620  "option_is_persistent, "
621  "option_client_class, "
622  "option_subnet_id, "
623  "option_user_context, "
624  "option_scope_id "
625  "FROM hosts "
626  "WHERE host_identifier = ? "
627  "AND host_identifier_type = ? "
628  "ALLOW FILTERING "
629  }},
630 
631  {GET_HOST_BY_IPV4_ADDRESS,
632  {GET_HOST_BY_IPV4_ADDRESS,
633  "SELECT "
634  "key, "
635  "id, "
636  "host_identifier, "
637  "host_identifier_type, "
638  "host_ipv4_subnet_id, "
639  "host_ipv6_subnet_id, "
640  "host_ipv4_address, "
641  "host_ipv4_next_server, "
642  "host_ipv4_server_hostname, "
643  "host_ipv4_boot_file_name, "
644  "auth_key, "
645  "hostname, "
646  "user_context, "
647  "host_ipv4_client_classes, "
648  "host_ipv6_client_classes, "
649  "reserved_ipv6_prefix_address, "
650  "reserved_ipv6_prefix_length, "
651  "reserved_ipv6_prefix_address_type, "
652  "iaid, "
653  "option_universe, "
654  "option_code, "
655  "option_value, "
656  "option_formatted_value, "
657  "option_space, "
658  "option_is_persistent, "
659  "option_client_class, "
660  "option_subnet_id, "
661  "option_user_context, "
662  "option_scope_id "
663  "FROM hosts "
664  "WHERE host_ipv4_address = ? "
665  "ALLOW FILTERING "
666  }},
667 
668  {GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID,
669  {GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID,
670  "SELECT "
671  "key, "
672  "id, "
673  "host_identifier, "
674  "host_identifier_type, "
675  "host_ipv4_subnet_id, "
676  "host_ipv6_subnet_id, "
677  "host_ipv4_address, "
678  "host_ipv4_next_server, "
679  "host_ipv4_server_hostname, "
680  "host_ipv4_boot_file_name, "
681  "auth_key, "
682  "hostname, "
683  "user_context, "
684  "host_ipv4_client_classes, "
685  "host_ipv6_client_classes, "
686  "reserved_ipv6_prefix_address, "
687  "reserved_ipv6_prefix_length, "
688  "reserved_ipv6_prefix_address_type, "
689  "iaid, "
690  "option_universe, "
691  "option_code, "
692  "option_value, "
693  "option_formatted_value, "
694  "option_space, "
695  "option_is_persistent, "
696  "option_client_class, "
697  "option_subnet_id, "
698  "option_user_context, "
699  "option_scope_id "
700  "FROM hosts "
701  "WHERE host_ipv4_subnet_id = ? "
702  "AND host_identifier = ? "
703  "AND host_identifier_type = ? "
704  "ALLOW FILTERING "
705  }},
706 
707  {GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID,
708  {GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID,
709  "SELECT "
710  "key, "
711  "id, "
712  "host_identifier, "
713  "host_identifier_type, "
714  "host_ipv4_subnet_id, "
715  "host_ipv6_subnet_id, "
716  "host_ipv4_address, "
717  "host_ipv4_next_server, "
718  "host_ipv4_server_hostname, "
719  "host_ipv4_boot_file_name, "
720  "auth_key, "
721  "hostname, "
722  "user_context, "
723  "host_ipv4_client_classes, "
724  "host_ipv6_client_classes, "
725  "reserved_ipv6_prefix_address, "
726  "reserved_ipv6_prefix_length, "
727  "reserved_ipv6_prefix_address_type, "
728  "iaid, "
729  "option_universe, "
730  "option_code, "
731  "option_value, "
732  "option_formatted_value, "
733  "option_space, "
734  "option_is_persistent, "
735  "option_client_class, "
736  "option_subnet_id, "
737  "option_user_context, "
738  "option_scope_id "
739  "FROM hosts "
740  "WHERE host_ipv6_subnet_id = ? "
741  "AND host_identifier = ? "
742  "AND host_identifier_type = ? "
743  "ALLOW FILTERING "
744  }},
745 
746  {GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS,
747  {GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS,
748  "SELECT "
749  "key, "
750  "id, "
751  "host_identifier, "
752  "host_identifier_type, "
753  "host_ipv4_subnet_id, "
754  "host_ipv6_subnet_id, "
755  "host_ipv4_address, "
756  "host_ipv4_next_server, "
757  "host_ipv4_server_hostname, "
758  "host_ipv4_boot_file_name, "
759  "auth_key, "
760  "hostname, "
761  "user_context, "
762  "host_ipv4_client_classes, "
763  "host_ipv6_client_classes, "
764  "reserved_ipv6_prefix_address, "
765  "reserved_ipv6_prefix_length, "
766  "reserved_ipv6_prefix_address_type, "
767  "iaid, "
768  "option_universe, "
769  "option_code, "
770  "option_value, "
771  "option_formatted_value, "
772  "option_space, "
773  "option_is_persistent, "
774  "option_client_class, "
775  "option_subnet_id, "
776  "option_user_context, "
777  "option_scope_id "
778  "FROM hosts "
779  "WHERE host_ipv4_subnet_id = ? "
780  "AND host_ipv4_address = ? "
781  "ALLOW FILTERING "
782  }},
783 
784  {GET_HOST_BY_IPV6_PREFIX,
785  {GET_HOST_BY_IPV6_PREFIX,
786  "SELECT "
787  "key, "
788  "id, "
789  "host_identifier, "
790  "host_identifier_type, "
791  "host_ipv4_subnet_id, "
792  "host_ipv6_subnet_id, "
793  "host_ipv4_address, "
794  "host_ipv4_next_server, "
795  "host_ipv4_server_hostname, "
796  "host_ipv4_boot_file_name, "
797  "auth_key, "
798  "hostname, "
799  "user_context, "
800  "host_ipv4_client_classes, "
801  "host_ipv6_client_classes, "
802  "reserved_ipv6_prefix_address, "
803  "reserved_ipv6_prefix_length, "
804  "reserved_ipv6_prefix_address_type, "
805  "iaid, "
806  "option_universe, "
807  "option_code, "
808  "option_value, "
809  "option_formatted_value, "
810  "option_space, "
811  "option_is_persistent, "
812  "option_client_class, "
813  "option_subnet_id, "
814  "option_user_context, "
815  "option_scope_id "
816  "FROM hosts "
817  "WHERE reserved_ipv6_prefix_address = ? "
818  "AND reserved_ipv6_prefix_length = ? "
819  "ALLOW FILTERING "
820  }},
821 
822  {GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS,
823  {GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS,
824  "SELECT "
825  "key, "
826  "id, "
827  "host_identifier, "
828  "host_identifier_type, "
829  "host_ipv4_subnet_id, "
830  "host_ipv6_subnet_id, "
831  "host_ipv4_address, "
832  "host_ipv4_next_server, "
833  "host_ipv4_server_hostname, "
834  "host_ipv4_boot_file_name, "
835  "auth_key, "
836  "hostname, "
837  "user_context, "
838  "host_ipv4_client_classes, "
839  "host_ipv6_client_classes, "
840  "reserved_ipv6_prefix_address, "
841  "reserved_ipv6_prefix_length, "
842  "reserved_ipv6_prefix_address_type, "
843  "iaid, "
844  "option_universe, "
845  "option_code, "
846  "option_value, "
847  "option_formatted_value, "
848  "option_space, "
849  "option_is_persistent, "
850  "option_client_class, "
851  "option_subnet_id, "
852  "option_user_context, "
853  "option_scope_id "
854  "FROM hosts "
855  "WHERE host_ipv6_subnet_id = ? "
856  "AND reserved_ipv6_prefix_address = ? "
857  "ALLOW FILTERING "
858  }},
859 
860  {GET_HOST_BY_IPV4_SUBNET_ID,
861  {GET_HOST_BY_IPV4_SUBNET_ID,
862  "SELECT "
863  "key, "
864  "id, "
865  "host_identifier, "
866  "host_identifier_type, "
867  "host_ipv4_subnet_id, "
868  "host_ipv6_subnet_id, "
869  "host_ipv4_address, "
870  "host_ipv4_next_server, "
871  "host_ipv4_server_hostname, "
872  "host_ipv4_boot_file_name, "
873  "auth_key, "
874  "hostname, "
875  "user_context, "
876  "host_ipv4_client_classes, "
877  "host_ipv6_client_classes, "
878  "reserved_ipv6_prefix_address, "
879  "reserved_ipv6_prefix_length, "
880  "reserved_ipv6_prefix_address_type, "
881  "iaid, "
882  "option_universe, "
883  "option_code, "
884  "option_value, "
885  "option_formatted_value, "
886  "option_space, "
887  "option_is_persistent, "
888  "option_client_class, "
889  "option_subnet_id, "
890  "option_user_context, "
891  "option_scope_id "
892  "FROM hosts "
893  "WHERE host_ipv4_subnet_id = ? "
894  "ALLOW FILTERING "
895  }},
896 
897  {GET_HOST_BY_IPV6_SUBNET_ID,
898  {GET_HOST_BY_IPV6_SUBNET_ID,
899  "SELECT "
900  "key, "
901  "id, "
902  "host_identifier, "
903  "host_identifier_type, "
904  "host_ipv4_subnet_id, "
905  "host_ipv6_subnet_id, "
906  "host_ipv4_address, "
907  "host_ipv4_next_server, "
908  "host_ipv4_server_hostname, "
909  "host_ipv4_boot_file_name, "
910  "auth_key, "
911  "hostname, "
912  "user_context, "
913  "host_ipv4_client_classes, "
914  "host_ipv6_client_classes, "
915  "reserved_ipv6_prefix_address, "
916  "reserved_ipv6_prefix_length, "
917  "reserved_ipv6_prefix_address_type, "
918  "iaid, "
919  "option_universe, "
920  "option_code, "
921  "option_value, "
922  "option_formatted_value, "
923  "option_space, "
924  "option_is_persistent, "
925  "option_client_class, "
926  "option_subnet_id, "
927  "option_user_context, "
928  "option_scope_id "
929  "FROM hosts "
930  "WHERE host_ipv6_subnet_id = ? "
931  "ALLOW FILTERING "
932  }},
933 
934  {GET_HOST_BY_HOST_NAME,
935  {GET_HOST_BY_HOST_NAME,
936  "SELECT "
937  "key, "
938  "id, "
939  "host_identifier, "
940  "host_identifier_type, "
941  "host_ipv4_subnet_id, "
942  "host_ipv6_subnet_id, "
943  "host_ipv4_address, "
944  "host_ipv4_next_server, "
945  "host_ipv4_server_hostname, "
946  "host_ipv4_boot_file_name, "
947  "auth_key, "
948  "hostname, "
949  "user_context, "
950  "host_ipv4_client_classes, "
951  "host_ipv6_client_classes, "
952  "reserved_ipv6_prefix_address, "
953  "reserved_ipv6_prefix_length, "
954  "reserved_ipv6_prefix_address_type, "
955  "iaid, "
956  "option_universe, "
957  "option_code, "
958  "option_value, "
959  "option_formatted_value, "
960  "option_space, "
961  "option_is_persistent, "
962  "option_client_class, "
963  "option_subnet_id, "
964  "option_user_context, "
965  "option_scope_id "
966  "FROM hosts "
967  "WHERE lower_case_hostname = ? "
968  "ALLOW FILTERING "
969  }},
970 
971  {GET_HOST_BY_HOST_NAME_AND_IPV4_SUBNET_ID,
972  {GET_HOST_BY_HOST_NAME_AND_IPV4_SUBNET_ID,
973  "SELECT "
974  "key, "
975  "id, "
976  "host_identifier, "
977  "host_identifier_type, "
978  "host_ipv4_subnet_id, "
979  "host_ipv6_subnet_id, "
980  "host_ipv4_address, "
981  "host_ipv4_next_server, "
982  "host_ipv4_server_hostname, "
983  "host_ipv4_boot_file_name, "
984  "auth_key, "
985  "hostname, "
986  "user_context, "
987  "host_ipv4_client_classes, "
988  "host_ipv6_client_classes, "
989  "reserved_ipv6_prefix_address, "
990  "reserved_ipv6_prefix_length, "
991  "reserved_ipv6_prefix_address_type, "
992  "iaid, "
993  "option_universe, "
994  "option_code, "
995  "option_value, "
996  "option_formatted_value, "
997  "option_space, "
998  "option_is_persistent, "
999  "option_client_class, "
1000  "option_subnet_id, "
1001  "option_user_context, "
1002  "option_scope_id "
1003  "FROM hosts "
1004  "WHERE lower_case_hostname = ? "
1005  "AND host_ipv4_subnet_id = ? "
1006  "ALLOW FILTERING "
1007  }},
1008 
1009  {GET_HOST_BY_HOST_NAME_AND_IPV6_SUBNET_ID,
1010  {GET_HOST_BY_HOST_NAME_AND_IPV6_SUBNET_ID,
1011  "SELECT "
1012  "key, "
1013  "id, "
1014  "host_identifier, "
1015  "host_identifier_type, "
1016  "host_ipv4_subnet_id, "
1017  "host_ipv6_subnet_id, "
1018  "host_ipv4_address, "
1019  "host_ipv4_next_server, "
1020  "host_ipv4_server_hostname, "
1021  "host_ipv4_boot_file_name, "
1022  "auth_key, "
1023  "hostname, "
1024  "user_context, "
1025  "host_ipv4_client_classes, "
1026  "host_ipv6_client_classes, "
1027  "reserved_ipv6_prefix_address, "
1028  "reserved_ipv6_prefix_length, "
1029  "reserved_ipv6_prefix_address_type, "
1030  "iaid, "
1031  "option_universe, "
1032  "option_code, "
1033  "option_value, "
1034  "option_formatted_value, "
1035  "option_space, "
1036  "option_is_persistent, "
1037  "option_client_class, "
1038  "option_subnet_id, "
1039  "option_user_context, "
1040  "option_scope_id "
1041  "FROM hosts "
1042  "WHERE lower_case_hostname = ? "
1043  "AND host_ipv6_subnet_id = ? "
1044  "ALLOW FILTERING "
1045  }},
1046 
1047  {GET_HOST_BY_IPV4_SUBNET_ID_LIMIT,
1048  {GET_HOST_BY_IPV4_SUBNET_ID_LIMIT,
1049  "SELECT "
1050  "key, "
1051  "id, "
1052  "host_identifier, "
1053  "host_identifier_type, "
1054  "host_ipv4_subnet_id, "
1055  "host_ipv6_subnet_id, "
1056  "host_ipv4_address, "
1057  "host_ipv4_next_server, "
1058  "host_ipv4_server_hostname, "
1059  "host_ipv4_boot_file_name, "
1060  "auth_key, "
1061  "hostname, "
1062  "user_context, "
1063  "host_ipv4_client_classes, "
1064  "host_ipv6_client_classes, "
1065  "reserved_ipv6_prefix_address, "
1066  "reserved_ipv6_prefix_length, "
1067  "reserved_ipv6_prefix_address_type, "
1068  "iaid, "
1069  "option_universe, "
1070  "option_code, "
1071  "option_value, "
1072  "option_formatted_value, "
1073  "option_space, "
1074  "option_is_persistent, "
1075  "option_client_class, "
1076  "option_subnet_id, "
1077  "option_user_context, "
1078  "option_scope_id "
1079  "FROM hosts "
1080  "WHERE host_ipv4_subnet_id = ? "
1081  "LIMIT 1 "
1082  "ALLOW FILTERING "
1083  }},
1084 
1085  {GET_HOST_BY_IPV4_SUBNET_ID_NEXT_KEY,
1086  {GET_HOST_BY_IPV4_SUBNET_ID_NEXT_KEY,
1087  "SELECT "
1088  "key, "
1089  "id, "
1090  "host_identifier, "
1091  "host_identifier_type, "
1092  "host_ipv4_subnet_id, "
1093  "host_ipv6_subnet_id, "
1094  "host_ipv4_address, "
1095  "host_ipv4_next_server, "
1096  "host_ipv4_server_hostname, "
1097  "host_ipv4_boot_file_name, "
1098  "auth_key, "
1099  "hostname, "
1100  "user_context, "
1101  "host_ipv4_client_classes, "
1102  "host_ipv6_client_classes, "
1103  "reserved_ipv6_prefix_address, "
1104  "reserved_ipv6_prefix_length, "
1105  "reserved_ipv6_prefix_address_type, "
1106  "iaid, "
1107  "option_universe, "
1108  "option_code, "
1109  "option_value, "
1110  "option_formatted_value, "
1111  "option_space, "
1112  "option_is_persistent, "
1113  "option_client_class, "
1114  "option_subnet_id, "
1115  "option_user_context, "
1116  "option_scope_id "
1117  "FROM hosts "
1118  "WHERE host_ipv4_subnet_id = ? "
1119  "AND TOKEN(key) > TOKEN(?) "
1120  "LIMIT 1 "
1121  "ALLOW FILTERING "
1122  }},
1123 
1124  {GET_HOST_BY_IPV4_SUBNET_ID_PAGE,
1125  {GET_HOST_BY_IPV4_SUBNET_ID_PAGE,
1126  "SELECT "
1127  "key, "
1128  "id, "
1129  "host_identifier, "
1130  "host_identifier_type, "
1131  "host_ipv4_subnet_id, "
1132  "host_ipv6_subnet_id, "
1133  "host_ipv4_address, "
1134  "host_ipv4_next_server, "
1135  "host_ipv4_server_hostname, "
1136  "host_ipv4_boot_file_name, "
1137  "auth_key, "
1138  "hostname, "
1139  "user_context, "
1140  "host_ipv4_client_classes, "
1141  "host_ipv6_client_classes, "
1142  "reserved_ipv6_prefix_address, "
1143  "reserved_ipv6_prefix_length, "
1144  "reserved_ipv6_prefix_address_type, "
1145  "iaid, "
1146  "option_universe, "
1147  "option_code, "
1148  "option_value, "
1149  "option_formatted_value, "
1150  "option_space, "
1151  "option_is_persistent, "
1152  "option_client_class, "
1153  "option_subnet_id, "
1154  "option_user_context, "
1155  "option_scope_id "
1156  "FROM hosts "
1157  "WHERE host_ipv4_subnet_id = ? "
1158  "AND id = ? "
1159  "LIMIT 1 "
1160  "ALLOW FILTERING "
1161  }},
1162 
1163  {GET_HOST_BY_IPV6_SUBNET_ID_LIMIT,
1164  {GET_HOST_BY_IPV6_SUBNET_ID_LIMIT,
1165  "SELECT "
1166  "key, "
1167  "id, "
1168  "host_identifier, "
1169  "host_identifier_type, "
1170  "host_ipv4_subnet_id, "
1171  "host_ipv6_subnet_id, "
1172  "host_ipv4_address, "
1173  "host_ipv4_next_server, "
1174  "host_ipv4_server_hostname, "
1175  "host_ipv4_boot_file_name, "
1176  "auth_key, "
1177  "hostname, "
1178  "user_context, "
1179  "host_ipv4_client_classes, "
1180  "host_ipv6_client_classes, "
1181  "reserved_ipv6_prefix_address, "
1182  "reserved_ipv6_prefix_length, "
1183  "reserved_ipv6_prefix_address_type, "
1184  "iaid, "
1185  "option_universe, "
1186  "option_code, "
1187  "option_value, "
1188  "option_formatted_value, "
1189  "option_space, "
1190  "option_is_persistent, "
1191  "option_client_class, "
1192  "option_subnet_id, "
1193  "option_user_context, "
1194  "option_scope_id "
1195  "FROM hosts "
1196  "WHERE host_ipv6_subnet_id = ? "
1197  "LIMIT 1 "
1198  "ALLOW FILTERING "
1199  }},
1200 
1201  {GET_HOST_BY_IPV6_SUBNET_ID_NEXT_KEY,
1202  {GET_HOST_BY_IPV6_SUBNET_ID_NEXT_KEY,
1203  "SELECT "
1204  "key, "
1205  "id, "
1206  "host_identifier, "
1207  "host_identifier_type, "
1208  "host_ipv4_subnet_id, "
1209  "host_ipv6_subnet_id, "
1210  "host_ipv4_address, "
1211  "host_ipv4_next_server, "
1212  "host_ipv4_server_hostname, "
1213  "host_ipv4_boot_file_name, "
1214  "auth_key, "
1215  "hostname, "
1216  "user_context, "
1217  "host_ipv4_client_classes, "
1218  "host_ipv6_client_classes, "
1219  "reserved_ipv6_prefix_address, "
1220  "reserved_ipv6_prefix_length, "
1221  "reserved_ipv6_prefix_address_type, "
1222  "iaid, "
1223  "option_universe, "
1224  "option_code, "
1225  "option_value, "
1226  "option_formatted_value, "
1227  "option_space, "
1228  "option_is_persistent, "
1229  "option_client_class, "
1230  "option_subnet_id, "
1231  "option_user_context, "
1232  "option_scope_id "
1233  "FROM hosts "
1234  "WHERE host_ipv6_subnet_id = ? "
1235  "AND TOKEN(key) > TOKEN(?) "
1236  "LIMIT 1 "
1237  "ALLOW FILTERING "
1238  }},
1239 
1240  {GET_HOST_BY_IPV6_SUBNET_ID_PAGE,
1241  {GET_HOST_BY_IPV6_SUBNET_ID_PAGE,
1242  "SELECT "
1243  "key, "
1244  "id, "
1245  "host_identifier, "
1246  "host_identifier_type, "
1247  "host_ipv4_subnet_id, "
1248  "host_ipv6_subnet_id, "
1249  "host_ipv4_address, "
1250  "host_ipv4_next_server, "
1251  "host_ipv4_server_hostname, "
1252  "host_ipv4_boot_file_name, "
1253  "auth_key, "
1254  "hostname, "
1255  "user_context, "
1256  "host_ipv4_client_classes, "
1257  "host_ipv6_client_classes, "
1258  "reserved_ipv6_prefix_address, "
1259  "reserved_ipv6_prefix_length, "
1260  "reserved_ipv6_prefix_address_type, "
1261  "iaid, "
1262  "option_universe, "
1263  "option_code, "
1264  "option_value, "
1265  "option_formatted_value, "
1266  "option_space, "
1267  "option_is_persistent, "
1268  "option_client_class, "
1269  "option_subnet_id, "
1270  "option_user_context, "
1271  "option_scope_id "
1272  "FROM hosts "
1273  "WHERE host_ipv6_subnet_id = ? "
1274  "AND id = ? "
1275  "LIMIT 1 "
1276  "ALLOW FILTERING "
1277  }},
1278 
1279  {GET_HOST_LIMIT,
1280  {GET_HOST_LIMIT,
1281  "SELECT "
1282  "key, "
1283  "id, "
1284  "host_identifier, "
1285  "host_identifier_type, "
1286  "host_ipv4_subnet_id, "
1287  "host_ipv6_subnet_id, "
1288  "host_ipv4_address, "
1289  "host_ipv4_next_server, "
1290  "host_ipv4_server_hostname, "
1291  "host_ipv4_boot_file_name, "
1292  "auth_key, "
1293  "hostname, "
1294  "user_context, "
1295  "host_ipv4_client_classes, "
1296  "host_ipv6_client_classes, "
1297  "reserved_ipv6_prefix_address, "
1298  "reserved_ipv6_prefix_length, "
1299  "reserved_ipv6_prefix_address_type, "
1300  "iaid, "
1301  "option_universe, "
1302  "option_code, "
1303  "option_value, "
1304  "option_formatted_value, "
1305  "option_space, "
1306  "option_is_persistent, "
1307  "option_client_class, "
1308  "option_subnet_id, "
1309  "option_user_context, "
1310  "option_scope_id "
1311  "FROM hosts "
1312  "LIMIT 1 "
1313  "ALLOW FILTERING "
1314  }},
1315 
1316  {GET_HOST_NEXT_KEY,
1317  {GET_HOST_NEXT_KEY,
1318  "SELECT "
1319  "key, "
1320  "id, "
1321  "host_identifier, "
1322  "host_identifier_type, "
1323  "host_ipv4_subnet_id, "
1324  "host_ipv6_subnet_id, "
1325  "host_ipv4_address, "
1326  "host_ipv4_next_server, "
1327  "host_ipv4_server_hostname, "
1328  "host_ipv4_boot_file_name, "
1329  "auth_key, "
1330  "hostname, "
1331  "user_context, "
1332  "host_ipv4_client_classes, "
1333  "host_ipv6_client_classes, "
1334  "reserved_ipv6_prefix_address, "
1335  "reserved_ipv6_prefix_length, "
1336  "reserved_ipv6_prefix_address_type, "
1337  "iaid, "
1338  "option_universe, "
1339  "option_code, "
1340  "option_value, "
1341  "option_formatted_value, "
1342  "option_space, "
1343  "option_is_persistent, "
1344  "option_client_class, "
1345  "option_subnet_id, "
1346  "option_user_context, "
1347  "option_scope_id "
1348  "FROM hosts "
1349  "WHERE TOKEN(key) > TOKEN(?) "
1350  "LIMIT 1 "
1351  "ALLOW FILTERING "
1352  }},
1353 
1354  {GET_HOST_KEY,
1355  {GET_HOST_KEY,
1356  "SELECT "
1357  "key, "
1358  "id, "
1359  "host_identifier, "
1360  "host_identifier_type, "
1361  "host_ipv4_subnet_id, "
1362  "host_ipv6_subnet_id, "
1363  "host_ipv4_address, "
1364  "host_ipv4_next_server, "
1365  "host_ipv4_server_hostname, "
1366  "host_ipv4_boot_file_name, "
1367  "auth_key, "
1368  "hostname, "
1369  "user_context, "
1370  "host_ipv4_client_classes, "
1371  "host_ipv6_client_classes, "
1372  "reserved_ipv6_prefix_address, "
1373  "reserved_ipv6_prefix_length, "
1374  "reserved_ipv6_prefix_address_type, "
1375  "iaid, "
1376  "option_universe, "
1377  "option_code, "
1378  "option_value, "
1379  "option_formatted_value, "
1380  "option_space, "
1381  "option_is_persistent, "
1382  "option_client_class, "
1383  "option_subnet_id, "
1384  "option_user_context, "
1385  "option_scope_id "
1386  "FROM hosts "
1387  "WHERE key = ? "
1388  "ALLOW FILTERING "
1389  }},
1390 
1391  {GET_HOST_PAGE,
1392  {GET_HOST_PAGE,
1393  "SELECT "
1394  "key, "
1395  "id, "
1396  "host_identifier, "
1397  "host_identifier_type, "
1398  "host_ipv4_subnet_id, "
1399  "host_ipv6_subnet_id, "
1400  "host_ipv4_address, "
1401  "host_ipv4_next_server, "
1402  "host_ipv4_server_hostname, "
1403  "host_ipv4_boot_file_name, "
1404  "auth_key, "
1405  "hostname, "
1406  "user_context, "
1407  "host_ipv4_client_classes, "
1408  "host_ipv6_client_classes, "
1409  "reserved_ipv6_prefix_address, "
1410  "reserved_ipv6_prefix_length, "
1411  "reserved_ipv6_prefix_address_type, "
1412  "iaid, "
1413  "option_universe, "
1414  "option_code, "
1415  "option_value, "
1416  "option_formatted_value, "
1417  "option_space, "
1418  "option_is_persistent, "
1419  "option_client_class, "
1420  "option_subnet_id, "
1421  "option_user_context, "
1422  "option_scope_id "
1423  "FROM hosts "
1424  "WHERE id = ? "
1425  "LIMIT 1 "
1426  "ALLOW FILTERING "
1427  }},
1428 
1429  {DELETE_HOST,
1430  {DELETE_HOST,
1431  "DELETE FROM hosts WHERE key = ? AND id = ? "
1432  "IF EXISTS "
1433  }}
1434 };
1435 
1436 CqlHostExchange::CqlHostExchange()
1437  : host_(NULL), id_(0), host_identifier_type_(0), host_ipv4_subnet_id_(0),
1438  host_ipv6_subnet_id_(0), host_ipv4_address_(0), host_ipv4_next_server_(0),
1439  host_ipv4_server_hostname_(NULL_DHCP4_SERVER_HOSTNAME),
1440  host_ipv4_boot_file_name_(NULL_DHCP4_BOOT_FILE_NAME),
1441  auth_key_(""),
1442  user_context_(NULL_USER_CONTEXT),
1443  reserved_ipv6_prefix_length_(NULL_RESERVED_IPV6_PREFIX_LENGTH),
1444  reserved_ipv6_prefix_address_type_(NULL_RESERVED_IPV6_PREFIX_ADDRESS_TYPE),
1445  iaid_(NULL_IAID), option_universe_(NULL_OPTION_UNIVERSE),
1446  option_code_(NULL_OPTION_CODE),
1447  option_is_persistent_(NULL_OPTION_IS_PERSISTENT),
1448  option_subnet_id_(NULL_OPTION_SUBNET_ID),
1449  option_user_context_(NULL_OPTION_USER_CONTEXT),
1450  option_scope_id_(NULL_OPTION_SCOPE_ID) {
1451 }
1452 
1454 }
1455 
1456 void
1458  // Start with a fresh array.
1459  data.clear();
1460 
1461  // key: bigint
1462  data.add(&key_);
1463  // id: bigint
1464  data.add(&id_);
1465  // host_identifier: blob
1466  data.add(&host_identifier_);
1467  // host_identifier_type: int
1468  data.add(&host_identifier_type_);
1469  // host_ipv4_subnet_id: int
1470  data.add(&host_ipv4_subnet_id_);
1471  // host_ipv6_subnet_id: int
1472  data.add(&host_ipv6_subnet_id_);
1473  // host_ipv4_address: int
1474  data.add(&host_ipv4_address_);
1475  // host_ipv4_next_server: int
1476  data.add(&host_ipv4_next_server_);
1477  // host_ipv4_server_hostname: text
1478  data.add(&host_ipv4_server_hostname_);
1479  // host_ipv4_boot_file_name: text
1480  data.add(&host_ipv4_boot_file_name_);
1481  // auth_key: text
1482  data.add(&auth_key_);
1483  // hostname: text
1484  data.add(&hostname_);
1485  // user_context: text
1486  data.add(&user_context_);
1487  // host_ipv4_client_classes: text
1488  data.add(&host_ipv4_client_classes_);
1489  // host_ipv6_client_classes: text
1490  data.add(&host_ipv6_client_classes_);
1493  // reserved_ipv6_prefix_address: text
1494  data.add(&reserved_ipv6_prefix_address_);
1495  // reserved_ipv6_prefix_length: int
1496  data.add(&reserved_ipv6_prefix_length_);
1497  // reserved_ipv6_prefix_address_type: int
1498  data.add(&reserved_ipv6_prefix_address_type_);
1499  // iaid: int
1500  data.add(&iaid_);
1504  // option_universe: int
1505  data.add(&option_universe_);
1506  // option_code: int
1507  data.add(&option_code_);
1508  // option_value: blob
1509  data.add(&option_value_);
1510  // option_formatted_value: text
1511  data.add(&option_formatted_value_);
1512  // option_space: text
1513  data.add(&option_space_);
1514  // option_is_persistent: boolean
1515  data.add(&option_is_persistent_);
1516  // option_client_class: text
1517  data.add(&option_client_class_);
1518  // option_subnet_id: int
1519  data.add(&option_subnet_id_);
1520  // option_user_context: text
1521  data.add(&option_user_context_);
1522  // option_scope_id: int
1523  data.add(&option_scope_id_);
1525 }
1526 
1527 void
1529  const Optional<SubnetID>& subnet_id,
1530  const IPv6Resrv* const reservation,
1531  const std::string& option_space,
1532  const OptionDescriptor& option_descriptor) {
1533 
1534  // Store host object to ensure it remains valid.
1535  host_ = host;
1536 
1537  // Set up the structures for the various components of the host
1538  // structure.
1539  try {
1540  // host_identifier: blob
1541  // Convert from std::vector<uint8_t> to
1542  // std::vector<cass_byte_t>.
1543  HostIdentifier host_identifier = host->getIdentifier();
1544  host_identifier_ = CassBlob(host_identifier.begin(), host_identifier.end());
1545  if (host_identifier_.size() > DUID::MAX_DUID_LEN) {
1546  isc_throw(BadValue, "CqlHostExchange::prepareExchange(): host identifier "
1547  << host_identifier_.data() << " of length " << host_identifier_.size()
1548  << " is greater than allowed of " << DUID::MAX_DUID_LEN);
1549  }
1550 
1551  // host_identifier_type: tinyint
1552  host_identifier_type_ = static_cast<cass_int32_t>(host->getIdentifierType());
1553  if (host_identifier_type_ > MAX_IDENTIFIER_TYPE) {
1554  isc_throw(BadValue, "CqlHostExchange::prepareExchange(): invalid "
1555  "host identifier type returned: " << host_identifier_type_);
1556  }
1557 
1558  // host_ipv4_subnet_id: int
1559  host_ipv4_subnet_id_ = static_cast<cass_int32_t>(host->getIPv4SubnetID());
1560 
1561  // host_ipv6_subnet_id: int
1562  host_ipv6_subnet_id_ = static_cast<cass_int32_t>(host->getIPv6SubnetID());
1563 
1564  // host_ipv4_address: int
1565  host_ipv4_address_ = static_cast<cass_int32_t>(host->getIPv4Reservation().toUint32());
1566 
1567  // host_ipv4_next_server: int
1568  host_ipv4_next_server_ = static_cast<cass_int32_t>(host->getNextServer().toUint32());
1569 
1570  // host_ipv4_server_hostname: text
1571  host_ipv4_server_hostname_ = host->getServerHostname();
1572 
1573  // host_ipv4_boot_file_name: text
1574  host_ipv4_boot_file_name_ = host->getBootFileName();
1575 
1576  // auth_key: varchar
1577  auth_key_ = host->getKey().toText();
1578 
1579  // hostname: text
1580  hostname_ = host->getHostname();
1581  if (hostname_.size() > HOSTNAME_MAX_LEN) {
1582  isc_throw(BadValue, "CqlHostExchange::prepareExchange(): hostname "
1583  << hostname_ << " of length " << hostname_.size()
1584  << " is greater than allowed of " << HOSTNAME_MAX_LEN);
1585  }
1586 
1587  // lower_case_hostname: text
1588  lower_case_hostname_ = host->getLowerHostname();
1589  if (lower_case_hostname_.size() > HOSTNAME_MAX_LEN) {
1590  // Should never happen...
1591  isc_throw(BadValue, "CqlHostExchange::prepareExchange(): lower "
1592  "case hostname " << lower_case_hostname_ << " of length "
1593  << lower_case_hostname_.size()
1594  << " is greater than allowed of " << HOSTNAME_MAX_LEN);
1595  }
1596 
1597  // user_context: text
1598  ConstElementPtr ctx = host->getContext();
1599  if (ctx) {
1600  user_context_ = ctx->str();
1601  } else {
1602  user_context_ = NULL_USER_CONTEXT;
1603  }
1604 
1605  // host_ipv4_client_classes: text
1606  host_ipv4_client_classes_ = host->getClientClasses4().toText(",");
1607  if (host_ipv4_client_classes_.size() > CLIENT_CLASSES_MAX_LEN) {
1608  isc_throw(BadValue, "CqlHostExchange::prepareExchange(): "
1609  "IPv4 client classes " << host_ipv4_client_classes_ << " of length "
1610  << host_ipv4_client_classes_.size() << " is greater than allowed of "
1612  }
1613 
1614  // host_ipv6_client_classes: text
1615  host_ipv6_client_classes_ = host->getClientClasses6().toText(",");
1616  if (host_ipv6_client_classes_.size() > CLIENT_CLASSES_MAX_LEN) {
1617  isc_throw(BadValue, "CqlHostExchange::prepareExchange(): "
1618  "IPv6 client classes " << host_ipv6_client_classes_ << " of length "
1619  << host_ipv6_client_classes_.size() << " is greater than allowed of "
1621  }
1622 
1623  if (reservation == NULL) {
1624  // reserved_ipv6_prefix_address: text
1625  reserved_ipv6_prefix_address_ = NULL_RESERVED_IPV6_PREFIX_ADDRESS;
1626  // reserved_ipv6_prefix_length: int
1627  reserved_ipv6_prefix_length_ = NULL_RESERVED_IPV6_PREFIX_LENGTH;
1628  // reserved_ipv6_prefix_address_type: int
1629  reserved_ipv6_prefix_address_type_ = NULL_RESERVED_IPV6_PREFIX_ADDRESS_TYPE;
1630  iaid_ = NULL_IAID;
1631  } else {
1632  // reserved_ipv6_prefix_address: text
1633  reserved_ipv6_prefix_address_ = reservation->getPrefix().toText();
1634 
1635  // reserved_ipv6_prefix_length: int
1636  reserved_ipv6_prefix_length_ = static_cast<cass_int32_t>(reservation->getPrefixLen());
1637 
1638  // reserved_ipv6_prefix_address_type: int
1639  reserved_ipv6_prefix_address_type_ =
1640  reservation->getType() == IPv6Resrv::TYPE_NA ? 0 : 2;
1641 
1642  // iaid: int
1644  iaid_ = 0;
1645  }
1646 
1647  if (option_descriptor.option_ == NULL) {
1648  option_universe_ = NULL_OPTION_UNIVERSE;
1649  option_code_ = NULL_OPTION_CODE;
1650  option_value_ = NULL_OPTION_VALUE;
1651  option_formatted_value_ = NULL_OPTION_FORMATTED_VALUE;
1652  option_space_ = NULL_OPTION_SPACE;
1653  option_is_persistent_ = NULL_OPTION_IS_PERSISTENT;
1654  option_client_class_ = NULL_OPTION_CLIENT_CLASS;
1655  option_subnet_id_ = NULL_OPTION_SUBNET_ID;
1656  option_user_context_ = NULL_OPTION_USER_CONTEXT;
1657  option_scope_id_ = NULL_OPTION_SCOPE_ID;
1658  } else {
1659  // option_universe: int
1660  option_universe_ = option_descriptor.option_->getUniverse();
1661 
1662  // option_code: int
1663  option_code_ = option_descriptor.option_->getType();
1664 
1665  // option_value: blob
1666  // option_formatted_value: text
1667  if (option_descriptor.formatted_value_.empty()) {
1668  if (option_descriptor.option_->len() >
1669  option_descriptor.option_->getHeaderLen()) {
1670  // The formatted_value is empty and the option value
1671  // is not empty so we need to prepare on-wire format
1672  // for the option and store it in the database as a
1673  // blob.
1674  OutputBuffer buffer(option_descriptor.option_->len());
1675  option_descriptor.option_->pack(buffer);
1676  const char* buffer_ptr = static_cast<const char*>(buffer.getData());
1677  option_value_.assign(buffer_ptr + option_descriptor.option_->getHeaderLen(),
1678  buffer_ptr + buffer.getLength());
1679  } else {
1680  option_value_.clear();
1681  }
1682  option_formatted_value_.clear();
1683  } else {
1684  option_value_.clear();
1685  option_formatted_value_ = option_descriptor.formatted_value_;
1686  }
1687 
1688  // option_space: text
1689  option_space_ = option_space;
1690 
1691  // option_is_persistent: boolean
1692  option_is_persistent_ = option_descriptor.persistent_ ? cass_true : cass_false;
1693 
1694  // option_client_class: text
1696  option_client_class_.clear();
1697 
1698  // option_subnet_id: int
1699  if (!subnet_id.unspecified()) {
1700  option_subnet_id_ = subnet_id;
1701  } else {
1702  option_subnet_id_ = 0;
1703  }
1704 
1705  // option_user_context: text
1706  ConstElementPtr ctx = option_descriptor.getContext();
1707  if (ctx) {
1708  option_user_context_ = ctx->str();
1709  } else {
1710  option_user_context_ = NULL_OPTION_USER_CONTEXT;
1711  }
1712 
1713  // option_scope_id: int
1714  // Using fixed scope_id = 3, which associates an option with host.
1715  option_scope_id_ = 3;
1716  }
1717 
1718  // id: bigint
1719  id_ = static_cast<cass_int64_t>(hashIntoId());
1720 
1721  // key: bigint
1722  key_ = static_cast<cass_int64_t>(hashIntoKey());
1723  } catch (const Exception& ex) {
1725  "CqlHostExchange::prepareExchange(): "
1726  "could not copy data from host "
1727  << host->getHostname() << ", reason: " << ex.what());
1728  }
1729 }
1730 
1731 void
1733  const Optional<SubnetID>& subnet_id,
1734  const IPv6Resrv* const reservation,
1735  const std::string& option_space,
1736  const OptionDescriptor& option_descriptor,
1737  StatementTag statement_tag, AnyArray& data) {
1738  prepareExchange(host, subnet_id, reservation, option_space, option_descriptor);
1739 
1740  try {
1741  // Add all parameters to bind array.
1742  data.clear();
1743 
1744  if (statement_tag == CqlHostExchange::INSERT_HOST) {
1745  data.add(&key_);
1746  data.add(&id_);
1747  data.add(&host_identifier_);
1748  data.add(&host_identifier_type_);
1749  data.add(&host_ipv4_subnet_id_);
1750  data.add(&host_ipv6_subnet_id_);
1751  data.add(&host_ipv4_address_);
1752  data.add(&host_ipv4_next_server_);
1753  data.add(&host_ipv4_server_hostname_);
1754  data.add(&host_ipv4_boot_file_name_);
1755  data.add(&auth_key_);
1756  data.add(&hostname_);
1757  data.add(&lower_case_hostname_);
1758  data.add(&user_context_);
1759  data.add(&host_ipv4_client_classes_);
1760  data.add(&host_ipv6_client_classes_);
1761  }
1762 
1763  // Reservation
1764  data.add(&reserved_ipv6_prefix_address_);
1765  data.add(&reserved_ipv6_prefix_length_);
1766  data.add(&reserved_ipv6_prefix_address_type_);
1767  data.add(&iaid_);
1768 
1769  // Option
1770  data.add(&option_universe_);
1771  data.add(&option_code_);
1772  data.add(&option_value_);
1773  data.add(&option_formatted_value_);
1774  data.add(&option_space_);
1775  data.add(&option_is_persistent_);
1776  data.add(&option_client_class_);
1777  data.add(&option_subnet_id_);
1778  data.add(&option_user_context_);
1779  data.add(&option_scope_id_);
1780 
1781  } catch (const Exception& ex) {
1783  "CqlHostExchange::createBindForMutation(): "
1784  "could not create bind array from host "
1785  << host->getHostname() << ", reason: " << ex.what());
1786  }
1787 }
1788 
1789 void
1791  const Optional<SubnetID>& subnet_id,
1792  const IPv6Resrv* const reservation,
1793  const std::string& option_space,
1794  const OptionDescriptor& option_descriptor,
1795  StatementTag statement_tag, AnyArray& data) {
1796  prepareExchange(host, subnet_id, reservation, option_space, option_descriptor);
1797 
1798  try {
1799  // Add all parameters to bind array.
1800  data.clear();
1801 
1802  if (statement_tag == CqlHostExchange::DELETE_HOST) {
1803  data.add(&key_);
1804  data.add(&id_);
1805  }
1806 
1807  } catch (const Exception& ex) {
1809  "CqlHostExchange::createBindForDelete(): "
1810  "could not create bind array from host "
1811  << host->getHostname() << ", reason: " << ex.what());
1812  }
1813 }
1814 
1815 uint64_t
1817  // Add a separator between aggregated field to avoid collisions
1818  // between distinct entries.
1819 
1820  // Get key.
1821  std::stringstream key_stream;
1822  key_stream << hostKey();
1823  key_stream << std::setw(V6ADDRESS_TEXT_MAX_LEN) << std::setfill('-')
1824  << reserved_ipv6_prefix_address_;
1825  key_stream << std::setw(4) << std::setfill('-')
1826  << reserved_ipv6_prefix_length_;
1827  key_stream << std::setw(4) << std::setfill('-') << option_code_;
1828  key_stream << std::setw(OPTION_SPACE_MAX_LEN) << std::setfill('-')
1829  << option_space_;
1830  const std::string key = key_stream.str();
1831 
1832  return (Hash64::hash(key));
1833 }
1834 
1835 uint64_t
1837  const std::string key = hostKey();
1838 
1839  return (Hash64::hash(key));
1840 }
1841 
1842 std::string
1844  // Add a separator between aggregated field to avoid collisions
1845  // between distinct entries.
1846  // Get key.
1847  std::stringstream key_stream;
1848  if (host_ipv4_address_) {
1849  key_stream << std::setw(3 * DUID::MAX_DUID_LEN - 1) << std::setfill('-')
1850  << "-";
1851  key_stream << std::setw(10) << std::setfill('-') << "-";
1852  } else {
1853  key_stream << std::setw(3 * DUID::MAX_DUID_LEN - 1) << std::setfill('-')
1854  << DUID(host_identifier_).toText();
1855  key_stream << std::setw(10) << std::setfill('-') << host_identifier_type_;
1856  }
1857  key_stream << std::setw(10) << std::setfill('-') << host_ipv4_subnet_id_;
1858  key_stream << std::setw(10) << std::setfill('-') << host_ipv6_subnet_id_;
1859  key_stream << std::setw(V4ADDRESS_TEXT_MAX_LEN) << std::setfill('-')
1860  << host_ipv4_address_;
1861  return key_stream.str();
1862 }
1863 
1864 boost::any
1866  const uint64_t id = static_cast<uint64_t>(id_);
1867 
1868  HostIdentifier host_identifier =
1869  HostIdentifier(host_identifier_.begin(), host_identifier_.end());
1870 
1871  // Set the host identifier type in a variable of the appropriate
1872  // data type.
1873  Host::IdentifierType host_identifier_type =
1874  static_cast<Host::IdentifierType>(host_identifier_type_);
1875 
1876  // Set IPv4 subnet ID to the value returned.
1877  SubnetID ipv4_subnet_id = static_cast<SubnetID>(host_ipv4_subnet_id_);
1878 
1879  // Set IPv6 subnet ID to the value returned.
1880  SubnetID ipv6_subnet_id = static_cast<SubnetID>(host_ipv6_subnet_id_);
1881 
1882  // Set IPv4 address reservation.
1883  asiolink::IOAddress ipv4_reservation =
1884  asiolink::IOAddress(static_cast<uint32_t>(host_ipv4_address_));
1885 
1886  Host* host = new Host(host_identifier.data(), host_identifier.size(),
1887  host_identifier_type, ipv4_subnet_id, ipv6_subnet_id,
1888  ipv4_reservation, hostname_,
1889  host_ipv4_client_classes_, host_ipv6_client_classes_,
1890  static_cast<uint32_t>(host_ipv4_next_server_),
1891  host_ipv4_server_hostname_, host_ipv4_boot_file_name_,
1892  AuthKey(auth_key_));
1893 
1894  // Set the user context if there is one.
1895  if (!user_context_.empty()) {
1896  try {
1897  ConstElementPtr ctx = Element::fromJSON(user_context_);
1898  if (!ctx || (ctx->getType() != Element::map)) {
1899  isc_throw(BadValue, "user context '" << user_context_
1900  << "' is not a JSON map");
1901  }
1902  host->setContext(ctx);
1903  } catch (const isc::data::JSONError& ex) {
1904  isc_throw(BadValue, "user context '" << user_context_
1905  << "' is invalid JSON: " << ex.what());
1906  }
1907  }
1908 
1909  host->setHostId(id);
1910 
1911  const IPv6Resrv reservation = retrieveReservation();
1912  if (reservation != NULL_IPV6_RESERVATION &&
1913  !host->hasReservation(reservation)) {
1914  host->addReservation(reservation);
1915  }
1916 
1917  OptionWrapper option_wrapper = retrieveOption();
1918  if (option_wrapper.option_descriptor_) {
1919  if (option_wrapper.option_descriptor_->option_->getUniverse() == Option::V4) {
1920  host->getCfgOption4()->add(*option_wrapper.option_descriptor_,
1921  option_wrapper.option_space_);
1922  } else if (option_wrapper.option_descriptor_->option_->getUniverse() == Option::V6) {
1923  host->getCfgOption6()->add(*option_wrapper.option_descriptor_,
1924  option_wrapper.option_space_);
1925  }
1926  }
1927 
1928  return (host);
1929 }
1930 
1931 const IPv6Resrv
1933  // Set the IPv6 Reservation type (0 = IA_NA, 2 = IA_PD).
1934  IPv6Resrv::Type type;
1935  switch (reserved_ipv6_prefix_address_type_) {
1936  case 0:
1937  type = IPv6Resrv::TYPE_NA;
1938  break;
1939  case 2:
1940  type = IPv6Resrv::TYPE_PD;
1941  break;
1942  case NULL_RESERVED_IPV6_PREFIX_ADDRESS_TYPE:
1943  return (NULL_IPV6_RESERVATION);
1944  default:
1945  isc_throw(BadValue, "CqlHostExchange::retrieveReservation(): invalid IPv6 "
1946  "reservation type returned: " << reserved_ipv6_prefix_address_type_
1947  << ". Only 0 (IA_NA) or 2 (IA_PD) are allowed.");
1948  }
1949 
1950  return (IPv6Resrv(type, IOAddress(reserved_ipv6_prefix_address_),
1951  reserved_ipv6_prefix_length_));
1952 }
1953 
1954 const OptionWrapper
1956  // Options are held in a binary or textual format in the database.
1957  // This is similar to having an option specified in a server
1958  // configuration file. Such option is converted to appropriate C++
1959  // class, using option definition. Thus, we need to find the
1960  // option definition for this option code and option space.
1961 
1962  // If the option space is a standard DHCPv4 or DHCPv6 option space,
1963  // this is most likely a standard option, for which we have a
1964  // definition created within libdhcp++.
1965  if (option_space_.empty() || option_universe_ == NULL_OPTION_UNIVERSE) {
1966  return (OptionWrapper(OptionDescriptorPtr(), ""));
1967  }
1968 
1969  OptionDefinitionPtr option_definition_ptr =
1970  LibDHCP::getOptionDef(option_space_, option_code_);
1971 
1972  // Otherwise, we may check if this an option encapsulated within the
1973  // vendor space.
1974  if (!option_definition_ptr && option_space_ != DHCP4_OPTION_SPACE &&
1975  option_space_ != DHCP6_OPTION_SPACE) {
1976  uint32_t vendor_id = LibDHCP::optionSpaceToVendorId(option_space_);
1977  if (vendor_id > 0) {
1978  option_definition_ptr = LibDHCP::getVendorOptionDef(
1979  static_cast<Option::Universe>(option_universe_), vendor_id,
1980  option_code_);
1981  }
1982  }
1983 
1984  // In all other cases, we use runtime option definitions, which
1985  // should be also registered within the libdhcp++.
1986  if (!option_definition_ptr) {
1987  option_definition_ptr =
1988  LibDHCP::getRuntimeOptionDef(option_space_, option_code_);
1989  }
1990 
1991  OptionPtr option;
1992  if (!option_definition_ptr) {
1993  // If no definition found, we use generic option type.
1994  OptionBuffer option_buffer(option_value_.begin(), option_value_.end());
1995  option = boost::make_shared<Option>(static_cast<Option::Universe>(option_universe_),
1996  static_cast<uint16_t>(option_code_),
1997  option_buffer.begin(), option_buffer.end());
1998  } else {
1999  // The option value may be specified in textual or binary format
2000  // in the
2001  // database. If formatted_value is empty, the binary format is
2002  // used.
2003  // Depending on the format we use a different variant of @ref
2004  // optionFactory().
2005  if (option_formatted_value_.empty()) {
2006  OptionBuffer option_buffer(option_value_.begin(),
2007  option_value_.end());
2008  option = option_definition_ptr->optionFactory(
2009  static_cast<Option::Universe>(option_universe_),
2010  static_cast<uint16_t>(option_code_), option_buffer.begin(),
2011  option_buffer.end());
2012  } else {
2013  // Spit the value specified in comma separated values
2014  // format.
2015  std::vector<std::string> split_vector;
2016  boost::split(split_vector, option_formatted_value_,
2017  boost::is_any_of(","));
2018  option = option_definition_ptr->optionFactory(
2019  static_cast<Option::Universe>(option_universe_),
2020  static_cast<uint16_t>(option_code_), split_vector);
2021  }
2022  }
2023 
2024  OptionWrapper result(boost::make_shared<OptionDescriptor>(option, option_is_persistent_,
2025  option_formatted_value_),
2026  option_space_);
2027  // Set the user context if there is one into the option descriptor.
2028  if (!option_user_context_.empty()) {
2029  try {
2030  ConstElementPtr ctx = Element::fromJSON(option_user_context_);
2031  if (!ctx || (ctx->getType() != Element::map)) {
2032  isc_throw(BadValue, "option user context '" << option_user_context_
2033  << "' is no a JSON map");
2034  }
2035  result.option_descriptor_->setContext(ctx);
2036  } catch (const isc::data::JSONError& ex) {
2037  isc_throw(BadValue, "option user context '" << option_user_context_
2038  << "' is invalid JSON: " << ex.what());
2039  }
2040  }
2041 
2042  return result;
2043 }
2044 
2049 public:
2055  explicit CqlHostDataSourceImpl(const DatabaseConnection::ParameterMap& parameters);
2056 
2058  virtual ~CqlHostDataSourceImpl();
2059 
2066  virtual bool insertOrDelete(const HostPtr& host, bool insert);
2067 
2074  virtual ConstHostPtr get4(const SubnetID& subnet_id,
2075  const asiolink::IOAddress& address) const;
2076 
2085  virtual ConstHostPtr get4(const SubnetID& subnet_id,
2086  const Host::IdentifierType& identifier_type,
2087  const uint8_t* identifier_begin,
2088  const size_t identifier_len) const;
2089 
2096  virtual ConstHostPtr get6(const asiolink::IOAddress& prefix,
2097  const uint8_t prefix_len) const;
2098 
2107  virtual ConstHostPtr get6(const SubnetID& subnet_id,
2108  const Host::IdentifierType& identifier_type,
2109  const uint8_t* identifier_begin,
2110  const size_t identifier_len) const;
2111 
2118  virtual ConstHostPtr get6(const SubnetID& subnet_id,
2119  const asiolink::IOAddress& address) const;
2120 
2128  virtual ConstHostCollection
2129  getAll(const Host::IdentifierType& identifier_type,
2130  const uint8_t* identifier_begin,
2131  const size_t identifier_len) const;
2132 
2138  virtual ConstHostCollection getAll4(const SubnetID& subnet_id) const;
2139 
2145  virtual ConstHostCollection getAll6(const SubnetID& subnet_id) const;
2146 
2152  virtual ConstHostCollection
2153  getAllbyHostname(const std::string& hostname) const;
2154 
2161  virtual ConstHostCollection
2162  getAllbyHostname4(const std::string& hostname, const SubnetID& subnet_id) const;
2163 
2170  virtual ConstHostCollection
2171  getAllbyHostname6(const std::string& hostname, const SubnetID& subnet_id) const;
2172 
2181  virtual ConstHostCollection
2182  getPage4(const SubnetID& subnet_id,
2183  uint64_t lower_host_id,
2184  const HostPageSize& page_size) const;
2185 
2194  virtual ConstHostCollection
2195  getPage6(const SubnetID& subnet_id,
2196  uint64_t lower_host_id,
2197  const HostPageSize& page_size) const;
2198 
2206  virtual ConstHostCollection
2207  getPage4(uint64_t lower_host_id,
2208  const HostPageSize& page_size) const;
2209 
2217  virtual ConstHostCollection
2218  getPage6(uint64_t lower_host_id,
2219  const HostPageSize& page_size) const;
2220 
2226  virtual ConstHostCollection
2227  getAll4(const asiolink::IOAddress& address) const;
2228 
2232  virtual ConstHostCollection
2233  getAllHosts() const;
2234 
2236  virtual std::string getName() const;
2237 
2239  virtual VersionPair getVersion() const;
2240 
2241 protected:
2252  virtual bool insertOrDeleteHostWithOptions(bool insert,
2253  const HostPtr& host,
2254  const IPv6Resrv* const reservation = NULL,
2255  const std::list<std::string>& option_spaces = std::list<std::string>(),
2256  const ConstCfgOptionPtr cfg_option = ConstCfgOptionPtr());
2257 
2272  virtual bool insertOrDeleteHostWithReservations(bool insert,
2273  const HostPtr& host,
2274  const IPv6Resrv* const reservation,
2275  const std::list<std::string>& option_spaces4,
2276  const ConstCfgOptionPtr cfg_option4,
2277  const std::list<std::string>& option_spaces6,
2278  const ConstCfgOptionPtr cfg_option6);
2279 
2292  virtual ConstHostPtr getHost(StatementTag statement_tag,
2293  AnyArray& where_values) const;
2294 
2303  virtual ConstHostCollection getHostCollection(StatementTag statement_tag,
2304  AnyArray& where_values) const;
2305 
2314  virtual ConstHostCollection getHostCollectionPage4(const SubnetID& subnet_id,
2315  uint64_t lower_host_id,
2316  size_t count = 0) const;
2317 
2326  virtual ConstHostCollection getHostCollectionPage6(const SubnetID& subnet_id,
2327  uint64_t lower_host_id,
2328  size_t count = 0) const;
2329 
2337  virtual ConstHostCollection getHostCollectionPage4(uint64_t lower_host_id,
2338  size_t count = 0) const;
2339 
2347  virtual ConstHostCollection getHostCollectionPage6(uint64_t lower_host_id,
2348  size_t count = 0) const;
2349 
2355  virtual ConstHostPtr getHostByKey(uint64_t key) const;
2356 
2369  virtual bool getHostKey4(const SubnetID& subnet_id,
2370  uint64_t lower_host_id,
2371  uint64_t& key) const;
2372 
2385  virtual bool getHostKey6(const SubnetID& subnet_id,
2386  uint64_t lower_host_id,
2387  uint64_t& key) const;
2388 
2400  virtual bool getHostKey(uint64_t lower_host_id,
2401  uint64_t& key) const;
2402 
2410  virtual bool getNextHostKey4(const SubnetID& subnet_id,
2411  uint64_t& key) const;
2412 
2420  virtual bool getNextHostKey6(const SubnetID& subnet_id,
2421  uint64_t& key) const;
2422 
2429  virtual bool getNextHostKey(uint64_t& key) const;
2430 
2445  virtual bool insertOrDeleteHost(bool insert,
2446  const HostPtr& host,
2447  const Optional<SubnetID>& subnet_id = Optional<SubnetID>(),
2448  const IPv6Resrv* const reservation = NULL,
2449  const std::string& option_space = NULL_OPTION_SPACE,
2450  const OptionDescriptor& option_descriptor = OptionDescriptor(false));
2451 
2460  virtual void mergeHosts(const ConstHostPtr& source_host,
2461  HostPtr& target_host) const;
2462 
2463 private:
2466 
2468  mutable CqlConnection dbconn_;
2469 }; // class CqlHostDataSourceImpl
2470 
2479 std::size_t
2480 hash_value(const HostKey& key) {
2481  // Get key.
2482  std::stringstream key_stream;
2483  HostIdentifier host_identifier = std::get<HOST_IDENTIFIER>(key);
2484  key_stream << DUID(host_identifier).toText() << "-";
2485  key_stream << std::get<HOST_IDENTIFIER_TYPE>(key) << "-";
2486  key_stream << std::get<IPv4_SUBNET_ID>(key) << "-";
2487  key_stream << std::get<IPv6_SUBNET_ID>(key) << "-";
2488  key_stream << std::get<IPv4_RESERVATION>(key);
2489  const std::string key_string = key_stream.str();
2490 
2491  const uint64_t hash = Hash64::hash(key_string);
2492 
2493  return (static_cast<std::size_t>(hash));
2494 }
2495 
2502 bool
2503 operator==(const HostKey& key1, const HostKey& key2) {
2504  return (std::get<HOST_IDENTIFIER>(key1) == std::get<HOST_IDENTIFIER>(key2) &&
2505  std::get<HOST_IDENTIFIER_TYPE>(key1) ==
2506  std::get<HOST_IDENTIFIER_TYPE>(key2) &&
2507  std::get<IPv4_SUBNET_ID>(key1) == std::get<IPv4_SUBNET_ID>(key2) &&
2508  std::get<IPv6_SUBNET_ID>(key1) == std::get<IPv6_SUBNET_ID>(key2) &&
2509  std::get<IPv4_RESERVATION>(key1) == std::get<IPv4_RESERVATION>(key2));
2510 }
2511 
2513  : parameters_(parameters), dbconn_(parameters) {
2514  // Validate the schema version first.
2515  std::pair<uint32_t, uint32_t> code_version(CQL_SCHEMA_VERSION_MAJOR,
2517  std::pair<uint32_t, uint32_t> db_version = getVersion();
2518  if (code_version != db_version) {
2519  isc_throw(DbOpenError, "Cassandra schema version mismatch: need version: "
2520  << code_version.first << "." << code_version.second
2521  << " found version: " << db_version.first << "."
2522  << db_version.second);
2523  }
2524 
2525  // Open the database.
2526  dbconn_.openDatabase();
2527 
2528  // Prepare all possible statements.
2529  dbconn_.prepareStatements(CqlHostExchange::tagged_statements_);
2530 }
2531 
2533  // There is no need to close the database in this destructor: it is
2534  // closed in the destructor of the dbconn_ member variable.
2535 }
2536 
2537 bool
2539  // If there is no host, there is nothing to do.
2540  if (!host) {
2541  return (false);
2542  }
2543 
2544  // Get option space names and vendor space names and combine them within a
2545  // single list.
2546 
2547  // For IPv4:
2548  ConstCfgOptionPtr cfg_option4 = host->getCfgOption4();
2549  std::list<std::string> option_spaces4 = cfg_option4->getOptionSpaceNames();
2550  std::list<std::string> vendor_spaces4 = cfg_option4->getVendorIdsSpaceNames();
2551  option_spaces4.insert(option_spaces4.end(), vendor_spaces4.begin(),
2552  vendor_spaces4.end());
2553 
2554  // For IPv6:
2555  ConstCfgOptionPtr cfg_option6 = host->getCfgOption6();
2556  std::list<std::string> option_spaces6 = cfg_option6->getOptionSpaceNames();
2557  std::list<std::string> vendor_spaces6 = cfg_option6->getVendorIdsSpaceNames();
2558  option_spaces6.insert(option_spaces6.end(), vendor_spaces6.begin(),
2559  vendor_spaces6.end());
2560 
2561  bool result = true;
2562 
2563  // For every IPv6 reservation, add each of their options to the
2564  // database.
2565  IPv6ResrvRange reservations = host->getIPv6Reservations();
2566  if (std::distance(reservations.first, reservations.second) > 0) {
2567  for (IPv6ResrvIterator it = reservations.first; result && it != reservations.second; ++it) {
2568  result = insertOrDeleteHostWithReservations(insert, host, &it->second, option_spaces4, cfg_option4,
2569  option_spaces6, cfg_option6);
2570  }
2571  } else {
2572  // If host has no reservation, add entries with null
2573  // reservation. Options could still be present.
2574  result = insertOrDeleteHostWithReservations(insert, host, NULL, option_spaces4, cfg_option4,
2575  option_spaces6, cfg_option6);
2576  }
2577 
2578  return (result);
2579 }
2580 
2582 CqlHostDataSourceImpl::get4(const SubnetID& subnet_id, const asiolink::IOAddress& address) const {
2583  if (!address.isV4()) {
2584  isc_throw(BadValue, "CqlHostDataSource::get4(2): wrong address type, "
2585  "address supplied is not an IPv4 address");
2586  }
2587 
2588  // Convert to CQL data types.
2589  cass_int32_t host_ipv4_subnet_id = static_cast<cass_int32_t>(subnet_id);
2590  cass_int32_t host_ipv4_address = static_cast<cass_int32_t>(address.toUint32());
2591 
2592  // Bind to array.
2593  AnyArray where_values;
2594  where_values.add(&host_ipv4_subnet_id);
2595  where_values.add(&host_ipv4_address);
2596 
2597  // Run statement.
2598  ConstHostPtr result = getHost(CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS,
2599  where_values);
2600 
2601  return (result);
2602 }
2603 
2606  const Host::IdentifierType& identifier_type,
2607  const uint8_t* identifier_begin,
2608  const size_t identifier_len) const {
2609  // Convert to CQL data types.
2610  CassBlob host_identifier(identifier_begin, identifier_begin + identifier_len);
2611  cass_int32_t host_identifier_type = static_cast<cass_int32_t>(identifier_type);
2612  cass_int32_t host_ipv4_subnet_id = static_cast<cass_int32_t>(subnet_id);
2613 
2614  // Bind to array.
2615  AnyArray where_values;
2616  where_values.add(&host_ipv4_subnet_id);
2617  where_values.add(&host_identifier);
2618  where_values.add(&host_identifier_type);
2619 
2620  // Run statement.
2621  ConstHostPtr result = getHost(CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID,
2622  where_values);
2623 
2624  return (result);
2625 }
2626 
2629  const uint8_t prefix_len) const {
2630  // Convert to CQL data types.
2631  std::string reserved_ipv6_prefix_address = prefix.toText();
2632  cass_int32_t reserved_ipv6_prefix_length = prefix_len;
2633 
2634  ConstHostPtr host;
2635  // Bind to array.
2636  AnyArray where_values;
2637  where_values.add(&reserved_ipv6_prefix_address);
2638  where_values.add(&reserved_ipv6_prefix_length);
2639 
2640  // Get host id.
2641  host = getHost(CqlHostExchange::GET_HOST_BY_IPV6_PREFIX, where_values);
2642 
2643  if (!host) {
2644  return ConstHostPtr();
2645  }
2646 
2647  // Get host.
2648  HostIdentifier host_identifier = host->getIdentifier();
2649  // Delegate to getAll(3).
2650  ConstHostCollection collection = getAll(host->getIdentifierType(), host_identifier.data(),
2651  host_identifier.size());
2652 
2653  if (collection.empty()) {
2654  return (ConstHostPtr());
2655  }
2656 
2657  if (collection.size() >= 2u) {
2659  "CqlHostDataSource::get6(2): multiple records were "
2660  "found in the "
2661  "database where only one was expected for statement "
2662  << CqlHostExchange::GET_HOST_BY_IPV6_PREFIX);
2663  }
2664 
2665  ConstHostPtr result = *collection.begin();
2666 
2667  return (result);
2668 }
2669 
2672  const Host::IdentifierType& identifier_type,
2673  const uint8_t* identifier_begin,
2674  const size_t identifier_len) const {
2675  // Convert to CQL data types.
2676  cass_int32_t host_ipv6_subnet_id = static_cast<cass_int32_t>(subnet_id);
2677  CassBlob host_identifier(identifier_begin, identifier_begin + identifier_len);
2678  cass_int32_t host_identifier_type = static_cast<cass_int32_t>(identifier_type);
2679 
2680  // Bind to array.
2681  AnyArray where_values;
2682  where_values.add(&host_ipv6_subnet_id);
2683  where_values.add(&host_identifier);
2684  where_values.add(&host_identifier_type);
2685 
2686  // Run statement.
2687  ConstHostPtr result = getHost(CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID,
2688  where_values);
2689 
2690  return (result);
2691 }
2692 
2694 CqlHostDataSourceImpl::get6(const SubnetID& subnet_id, const IOAddress& address) const {
2695  // Convert to CQL data types.
2696  cass_int32_t host_ipv6_subnet_id = static_cast<cass_int32_t>(subnet_id);
2697  std::string reserved_ipv6_prefix_address = address.toText();
2698 
2699  // Bind to array.
2700  AnyArray where_values;
2701  where_values.add(&host_ipv6_subnet_id);
2702  where_values.add(&reserved_ipv6_prefix_address);
2703 
2704  // Run statement.
2705  ConstHostPtr result = getHost(CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS,
2706  where_values);
2707 
2708  return (result);
2709 }
2710 
2713  const uint8_t* identifier_begin,
2714  const size_t identifier_len) const {
2715  // Convert to CQL data types.
2716  CassBlob host_identifier(identifier_begin, identifier_begin + identifier_len);
2717  cass_int32_t host_identifier_type = static_cast<cass_int32_t>(identifier_type);
2718 
2719  // Bind to array.
2720  AnyArray where_values;
2721  where_values.add(&host_identifier);
2722  where_values.add(&host_identifier_type);
2723 
2724  // Run statement.
2725  ConstHostCollection result = getHostCollection(CqlHostExchange::GET_HOST_BY_HOST_ID,
2726  where_values);
2727 
2728  return (result);
2729 }
2730 
2732 CqlHostDataSourceImpl::getAll4(const SubnetID& subnet_id) const {
2733  // Convert to CQL data types.
2734  cass_int32_t host_ipv4_subnet_id = static_cast<cass_int32_t>(subnet_id);
2735 
2736  // Bind to array.
2737  AnyArray where_values;
2738  where_values.add(&host_ipv4_subnet_id);
2739 
2740  // Run statement.
2741  ConstHostCollection result =
2742  getHostCollection(CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID,
2743  where_values);
2744 
2745  return (result);
2746 }
2747 
2749 CqlHostDataSourceImpl::getAll6(const SubnetID& subnet_id) const {
2750  // Convert to CQL data types.
2751  cass_int32_t host_ipv6_subnet_id = static_cast<cass_int32_t>(subnet_id);
2752 
2753  // Bind to array.
2754  AnyArray where_values;
2755  where_values.add(&host_ipv6_subnet_id);
2756 
2757  // Run statement.
2758  ConstHostCollection result =
2759  getHostCollection(CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID,
2760  where_values);
2761 
2762  return (result);
2763 }
2764 
2766 CqlHostDataSourceImpl::getAllbyHostname(const std::string& hostname) const {
2767  // Convert to CQL data types.
2768  std::string hostname_ = hostname;
2769 
2770  // Bind to array.
2771  AnyArray where_values;
2772  where_values.add(&hostname_);
2773 
2774  // Run statement.
2775  ConstHostCollection result =
2776  getHostCollection(CqlHostExchange::GET_HOST_BY_HOST_NAME,
2777  where_values);
2778 
2779  return (result);
2780 }
2781 
2783 CqlHostDataSourceImpl::getAllbyHostname4(const std::string& hostname,
2784  const SubnetID& subnet_id) const {
2785  // Convert to CQL data types.
2786  std::string hostname_ = hostname;
2787  cass_int32_t host_ipv4_subnet_id = static_cast<cass_int32_t>(subnet_id);
2788 
2789  // Bind to array.
2790  AnyArray where_values;
2791  where_values.add(&hostname_);
2792  where_values.add(&host_ipv4_subnet_id);
2793 
2794  // Run statement.
2795  ConstHostCollection result =
2796  getHostCollection(CqlHostExchange::GET_HOST_BY_HOST_NAME_AND_IPV4_SUBNET_ID,
2797  where_values);
2798 
2799  return (result);
2800 }
2801 
2803 CqlHostDataSourceImpl::getAllbyHostname6(const std::string& hostname,
2804  const SubnetID& subnet_id) const {
2805  // Convert to CQL data types.
2806  std::string hostname_ = hostname;
2807  cass_int32_t host_ipv6_subnet_id = static_cast<cass_int32_t>(subnet_id);
2808 
2809  // Bind to array.
2810  AnyArray where_values;
2811  where_values.add(&hostname_);
2812  where_values.add(&host_ipv6_subnet_id);
2813 
2814  // Run statement.
2815  ConstHostCollection result =
2816  getHostCollection(CqlHostExchange::GET_HOST_BY_HOST_NAME_AND_IPV6_SUBNET_ID,
2817  where_values);
2818 
2819  return (result);
2820 }
2821 
2822 // There are some problems implementing this for Cassandra.
2823 // Attempts show the per page ordering does not work and
2824 // it is not possible to order by TOKEN(host_id).
2825 // If the issue solved by paging is the Kea API overhead then
2826 // a solution is to get and cache all reservations and to handle
2827 // paging at the API level.
2828 
2831  uint64_t lower_host_id,
2832  const HostPageSize& page_size) const {
2833  // Run statement.
2834  ConstHostCollection result =
2835  getHostCollectionPage4(subnet_id, lower_host_id, page_size.page_size_);
2836 
2837  return (result);
2838 }
2839 
2842  uint64_t lower_host_id,
2843  const HostPageSize& page_size) const {
2844  // Run statement.
2845  ConstHostCollection result =
2846  getHostCollectionPage6(subnet_id, lower_host_id, page_size.page_size_);
2847 
2848  return (result);
2849 }
2850 
2852 CqlHostDataSourceImpl::getPage4(uint64_t lower_host_id,
2853  const HostPageSize& page_size) const {
2854  // Run statement.
2855  ConstHostCollection result =
2856  getHostCollectionPage4(lower_host_id, page_size.page_size_);
2857 
2858  return (result);
2859 }
2860 
2862 CqlHostDataSourceImpl::getPage6(uint64_t lower_host_id,
2863  const HostPageSize& page_size) const {
2864  // Run statement.
2865  ConstHostCollection result =
2866  getHostCollectionPage6(lower_host_id, page_size.page_size_);
2867 
2868  return (result);
2869 }
2870 
2873  // Convert to CQL data types.
2874  cass_int32_t host_ipv4_address = static_cast<cass_int32_t>(address.toUint32());
2875 
2876  // Bind to array.
2877  AnyArray where_values;
2878  where_values.add(&host_ipv4_address);
2879 
2880  // Run statement.
2881  ConstHostCollection result = getHostCollection(CqlHostExchange::GET_HOST_BY_IPV4_ADDRESS,
2882  where_values);
2883 
2884  return (result);
2885 }
2886 
2889 
2890  // Bind to array.
2891  AnyArray where_values;
2892 
2893  // Run statement.
2894  ConstHostCollection result = getHostCollection(CqlHostExchange::GET_HOST, where_values);
2895 
2896  return (result);
2897 }
2898 
2899 std::string
2901  std::string name;
2902  try {
2903  name = dbconn_.getParameter("name");
2904  } catch (...) {
2905  // Return an empty name.
2906  }
2907  return (name);
2908 }
2909 
2912  return CqlConnection::getVersion(parameters_);
2913 }
2914 
2915 bool
2917  const HostPtr& host,
2918  const IPv6Resrv* const reservation,
2919  const std::list<std::string>& option_spaces,
2920  const ConstCfgOptionPtr cfg_option) {
2921  // If there is no host, there is nothing to do.
2922  if (!host) {
2923  return (false);
2924  }
2925 
2926  bool result = true;
2927 
2928  // For each option space retrieve all options and insert them into
2929  // the database.
2930  bool option_found = false;
2931  for (const std::string& space : option_spaces) {
2932  if (!result) {
2933  break;
2934  }
2935  OptionContainerPtr options = cfg_option->getAll(space);
2936  if (options && !options->empty()) {
2937  for (const OptionDescriptor& option : *options) {
2938  if (!result) {
2939  break;
2940  }
2941  option_found = true;
2943  result = insertOrDeleteHost(insert, host, Optional<SubnetID>(), reservation,
2944  space, option);
2945  }
2946  }
2947  }
2948  if (result && !option_found) {
2949  // @todo: Assign actual value to subnet id.
2950  result = insertOrDeleteHost(insert, host, Optional<SubnetID>(), reservation);
2951  }
2952 
2953  return (result);
2954 }
2955 
2956 bool
2958  const HostPtr& host,
2959  const IPv6Resrv* const reservation,
2960  const std::list<std::string>& option_spaces4,
2961  const ConstCfgOptionPtr cfg_option4,
2962  const std::list<std::string>& option_spaces6,
2963  const ConstCfgOptionPtr cfg_option6) {
2964  // If there is no host, there is nothing to do.
2965  if (!host) {
2966  return (false);
2967  }
2968 
2969  bool result = true;
2970 
2971  // If host has no reservation, add entries with null reservation.
2972  // Options could still be present.
2973  if (result && cfg_option4 && !cfg_option4->empty()) {
2974  result = insertOrDeleteHostWithOptions(insert, host, reservation, option_spaces4, cfg_option4);
2975  }
2976  if (result && cfg_option6 && !cfg_option6->empty()) {
2977  result = insertOrDeleteHostWithOptions(insert, host, reservation, option_spaces6, cfg_option6);
2978  }
2979  if (result &&
2980  (!cfg_option4 || cfg_option4->empty()) &&
2981  (!cfg_option6 || cfg_option6->empty())) {
2982  result = insertOrDeleteHostWithOptions(insert, host, reservation);
2983  }
2984 
2985  return (result);
2986 }
2987 
2990  AnyArray& where_values) const {
2991  ConstHostCollection collection = getHostCollection(statement_tag, where_values);
2992 
2993  if (collection.empty()) {
2994  return (ConstHostPtr());
2995  }
2996 
2997  if (collection.size() >= 2u) {
2998  isc_throw(MultipleRecords, "CqlHostDataSourceImpl::getHost(): multiple records were "
2999  "found in the database where only one was expected for statement "
3000  << statement_tag);
3001  }
3002 
3003  return (*collection.begin());
3004 }
3005 
3008  AnyArray& where_values) const {
3009  // Run statement.
3010  std::unique_ptr<CqlHostExchange> host_exchange(new CqlHostExchange());
3011  AnyArray collection = host_exchange->executeSelect(dbconn_, where_values,
3012  statement_tag, false);
3013 
3014  // Create HostPtr objects.
3015  HostCollection host_collection;
3016  for (boost::any& host : collection) {
3017  host_collection.push_back(HostPtr(boost::any_cast<Host*>(host)));
3018  }
3019 
3020  // Merge the denormalized table entries that belong to the same host into a single host.
3021  HostMap map;
3022  for (HostPtr& host : host_collection) {
3023  HostKey key = HostKey(host->getIdentifier(), host->getIdentifierType(),
3024  host->getIPv4SubnetID(), host->getIPv6SubnetID(),
3025  host->getIPv4Reservation());
3026  if (map.find(key) == map.end()) {
3027  map[key] = host;
3028  } else {
3029  mergeHosts(host, map[key]);
3030  }
3031  }
3032 
3033  ConstHostCollection result_collection;
3034 
3035  for (HostPtr& host : host_collection) {
3036  HostKey key = HostKey(host->getIdentifier(), host->getIdentifierType(),
3037  host->getIPv4SubnetID(), host->getIPv6SubnetID(),
3038  host->getIPv4Reservation());
3039  if (map.find(key) != map.end()) {
3040  result_collection.push_back(map[key]);
3041  map.erase(key);
3042  }
3043  }
3044  return (result_collection);
3045 }
3046 
3049  // Bind to array.
3050  AnyArray where_values;
3051  cass_int64_t key_data = static_cast<cass_int64_t>(key);
3052  where_values.add(&key_data);
3053 
3054  // Run statement.
3055  ConstHostCollection collection =
3056  getHostCollection(CqlHostExchange::GET_HOST_KEY,
3057  where_values);
3058 
3059  if (collection.empty()) {
3060  return (ConstHostPtr());
3061  }
3062 
3063  if (collection.size() >= 2u) {
3064  isc_throw(MultipleRecords, "CqlHostDataSourceImpl::getHost(): multiple records were "
3065  "found in the database where only one was expected for statement "
3066  << CqlHostExchange::GET_HOST_KEY);
3067  }
3068 
3069  return (*collection.begin());
3070 }
3071 
3074  uint64_t lower_host_id,
3075  size_t count) const {
3076  ConstHostCollection result_collection;
3077  for (; count; count--) {
3078  uint64_t key;
3079  bool valid_key = getHostKey4(subnet_id, lower_host_id, key);
3080 
3081  if (!valid_key) {
3082  break;
3083  }
3084 
3085  ConstHostPtr host = getHostByKey(key);
3086  result_collection.push_back(host);
3087  lower_host_id = host->getHostId();
3088  }
3089 
3090  return (result_collection);
3091 }
3092 
3095  uint64_t lower_host_id,
3096  size_t count) const {
3097  ConstHostCollection result_collection;
3098  for (; count; count--) {
3099  uint64_t key;
3100  bool valid_key = getHostKey6(subnet_id, lower_host_id, key);
3101 
3102  if (!valid_key) {
3103  break;
3104  }
3105 
3106  ConstHostPtr host = getHostByKey(key);
3107  result_collection.push_back(host);
3108  lower_host_id = host->getHostId();
3109  }
3110 
3111  return (result_collection);
3112 }
3113 
3116  size_t count) const {
3117  ConstHostCollection result_collection;
3118  for (; count; count--) {
3119  uint64_t key;
3120  bool valid_key = getHostKey(lower_host_id, key);
3121 
3122  if (!valid_key) {
3123  break;
3124  }
3125 
3126  ConstHostPtr host = getHostByKey(key);
3127  result_collection.push_back(host);
3128  lower_host_id = host->getHostId();
3129  }
3130 
3131  return (result_collection);
3132 }
3133 
3136  size_t count) const {
3137  ConstHostCollection result_collection;
3138  for (; count; count--) {
3139  uint64_t key;
3140  bool valid_key = getHostKey(lower_host_id, key);
3141 
3142  if (!valid_key) {
3143  break;
3144  }
3145 
3146  ConstHostPtr host = getHostByKey(key);
3147  result_collection.push_back(host);
3148  lower_host_id = host->getHostId();
3149  }
3150 
3151  return (result_collection);
3152 }
3153 
3154 bool
3156  uint64_t lower_host_id,
3157  uint64_t& key) const {
3158  // Convert to CQL data types.
3159  cass_int32_t host_subnet_id = static_cast<cass_int32_t>(subnet_id);
3160 
3161  // Bind to array.
3162  AnyArray where_values;
3163  where_values.add(&host_subnet_id);
3164 
3165  cass_int64_t host_data = 0;
3166  if (lower_host_id) {
3167  host_data = static_cast<cass_int64_t>(lower_host_id);
3168  where_values.add(&host_data);
3169  }
3170 
3171  // Run statement.
3172  // This will retrieve first row of the first host (lower_host_id == 0)
3173  // or the first row of the host (lower_host_id != 0)
3174  std::unique_ptr<CqlHostExchange> host_exchange(new CqlHostExchange());
3175  AnyArray collection;
3176  if (lower_host_id) {
3177  collection = host_exchange->executeSelect(dbconn_, where_values,
3178  CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_PAGE, false);
3179  } else {
3180  collection = host_exchange->executeSelect(dbconn_, where_values,
3181  CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_LIMIT, false);
3182  }
3183 
3184  // Create HostPtr objects.
3185  HostCollection host_collection;
3186  for (boost::any& host : collection) {
3187  host_collection.push_back(HostPtr(boost::any_cast<Host*>(host)));
3188  }
3189 
3190  // If there is no host, just exit
3191  if (host_collection.empty()) {
3192  return false;
3193  }
3194 
3195  key = host_exchange->hashIntoKey();
3196 
3197  if (lower_host_id) {
3198  return getNextHostKey4(subnet_id, key);
3199  }
3200 
3201  return true;
3202 }
3203 
3204 bool
3206  uint64_t lower_host_id,
3207  uint64_t& key) const {
3208  // Convert to CQL data types.
3209  cass_int32_t host_subnet_id = static_cast<cass_int32_t>(subnet_id);
3210 
3211  // Bind to array.
3212  AnyArray where_values;
3213  where_values.add(&host_subnet_id);
3214 
3215  cass_int64_t host_data = 0;
3216  if (lower_host_id) {
3217  host_data = static_cast<cass_int64_t>(lower_host_id);
3218  where_values.add(&host_data);
3219  }
3220 
3221  // Run statement.
3222  // This will retrieve first row of the first host (lower_host_id == 0)
3223  // or the first row of the host (lower_host_id != 0)
3224  std::unique_ptr<CqlHostExchange> host_exchange(new CqlHostExchange());
3225  AnyArray collection;
3226  if (lower_host_id) {
3227  collection = host_exchange->executeSelect(dbconn_, where_values,
3228  CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_PAGE, false);
3229  } else {
3230  collection = host_exchange->executeSelect(dbconn_, where_values,
3231  CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_LIMIT, false);
3232  }
3233 
3234  // Create HostPtr objects.
3235  HostCollection host_collection;
3236  for (boost::any& host : collection) {
3237  host_collection.push_back(HostPtr(boost::any_cast<Host*>(host)));
3238  }
3239 
3240  // If there is no host, just exit
3241  if (host_collection.empty()) {
3242  return false;
3243  }
3244 
3245  key = host_exchange->hashIntoKey();
3246 
3247  if (lower_host_id) {
3248  return getNextHostKey6(subnet_id, key);
3249  }
3250 
3251  return true;
3252 }
3253 
3254 bool
3255 CqlHostDataSourceImpl::getHostKey(uint64_t lower_host_id,
3256  uint64_t& key) const {
3257  // Bind to array.
3258  AnyArray where_values;
3259  cass_int64_t host_data = 0;
3260  if (lower_host_id) {
3261  host_data = static_cast<cass_int64_t>(lower_host_id);
3262  where_values.add(&host_data);
3263  }
3264 
3265  // Run statement.
3266  // This will retrieve first row of the first host (lower_host_id == 0)
3267  // or the first row of the host (lower_host_id != 0)
3268  std::unique_ptr<CqlHostExchange> host_exchange(new CqlHostExchange());
3269  AnyArray collection;
3270  if (lower_host_id) {
3271  collection = host_exchange->executeSelect(dbconn_, where_values,
3272  CqlHostExchange::GET_HOST_PAGE, false);
3273  } else {
3274  collection = host_exchange->executeSelect(dbconn_, where_values,
3275  CqlHostExchange::GET_HOST_LIMIT, false);
3276  }
3277 
3278  // Create HostPtr objects.
3279  HostCollection host_collection;
3280  for (boost::any& host : collection) {
3281  host_collection.push_back(HostPtr(boost::any_cast<Host*>(host)));
3282  }
3283 
3284  // If there is no host, just exit
3285  if (host_collection.empty()) {
3286  return false;
3287  }
3288 
3289  key = host_exchange->hashIntoKey();
3290 
3291  if (lower_host_id) {
3292  return getNextHostKey(key);
3293  }
3294 
3295  return true;
3296 }
3297 
3298 bool
3300  uint64_t& key) const {
3301  // Convert to CQL data types.
3302  cass_int32_t host_subnet_id = static_cast<cass_int32_t>(subnet_id);
3303  cass_int64_t key_data = static_cast<cass_int64_t>(key);
3304 
3305  // Bind to array.
3306  AnyArray where_values;
3307  where_values.add(&host_subnet_id);
3308  where_values.add(&key_data);
3309 
3310  // This will retrieve first row of the next host (lower_host_id != 0)
3311  std::unique_ptr<CqlHostExchange> host_exchange(new CqlHostExchange());
3312  AnyArray collection = host_exchange->executeSelect(dbconn_, where_values,
3313  CqlHostExchange::GET_HOST_BY_IPV4_SUBNET_ID_NEXT_KEY, false);
3314 
3315  // Create HostPtr objects.
3316  HostCollection host_collection;
3317  for (boost::any& host : collection) {
3318  host_collection.push_back(HostPtr(boost::any_cast<Host*>(host)));
3319  }
3320 
3321  if (host_collection.empty()) {
3322  return false;
3323  }
3324 
3325  key = host_exchange->hashIntoKey();
3326  return true;
3327 }
3328 
3329 bool
3331  uint64_t& key) const {
3332  // Convert to CQL data types.
3333  cass_int32_t host_subnet_id = static_cast<cass_int32_t>(subnet_id);
3334  cass_int64_t key_data = static_cast<cass_int64_t>(key);
3335 
3336  // Bind to array.
3337  AnyArray where_values;
3338  where_values.add(&host_subnet_id);
3339  where_values.add(&key_data);
3340 
3341  // This will retrieve first row of the next host (lower_host_id != 0)
3342  std::unique_ptr<CqlHostExchange> host_exchange(new CqlHostExchange());
3343  AnyArray collection = host_exchange->executeSelect(dbconn_, where_values,
3344  CqlHostExchange::GET_HOST_BY_IPV6_SUBNET_ID_NEXT_KEY, false);
3345 
3346  // Create HostPtr objects.
3347  HostCollection host_collection;
3348  for (boost::any& host : collection) {
3349  host_collection.push_back(HostPtr(boost::any_cast<Host*>(host)));
3350  }
3351 
3352  if (host_collection.empty()) {
3353  return false;
3354  }
3355 
3356  key = host_exchange->hashIntoKey();
3357  return true;
3358 }
3359 
3360 bool
3362  // Convert to CQL data types.
3363  cass_int64_t key_data = static_cast<cass_int64_t>(key);
3364 
3365  // Bind to array.
3366  AnyArray where_values;
3367  where_values.add(&key_data);
3368 
3369  // This will retrieve first row of the next host (lower_host_id != 0)
3370  std::unique_ptr<CqlHostExchange> host_exchange(new CqlHostExchange());
3371  AnyArray collection = host_exchange->executeSelect(dbconn_, where_values,
3372  CqlHostExchange::GET_HOST_NEXT_KEY, false);
3373 
3374  // Create HostPtr objects.
3375  HostCollection host_collection;
3376  for (boost::any& host : collection) {
3377  host_collection.push_back(HostPtr(boost::any_cast<Host*>(host)));
3378  }
3379 
3380  if (host_collection.empty()) {
3381  return false;
3382  }
3383 
3384  key = host_exchange->hashIntoKey();
3385  return true;
3386 }
3387 
3388 bool
3390  const HostPtr& host,
3391  const Optional<SubnetID>& subnet_id,
3392  const IPv6Resrv* const reservation,
3393  const std::string& option_space,
3394  const OptionDescriptor& option_descriptor) {
3395  // If there is no host, there is nothing to do.
3396  if (!host) {
3397  return (false);
3398  }
3399 
3400  AnyArray assigned_values;
3401 
3402  std::unique_ptr<CqlHostExchange> host_exchange(new CqlHostExchange());
3403 
3404  try {
3405  if (insert) {
3406  host_exchange->createBindForMutation(host, subnet_id, reservation, option_space,
3407  option_descriptor, CqlHostExchange::INSERT_HOST, assigned_values);
3408 
3409  host_exchange->executeMutation(dbconn_, assigned_values, CqlHostExchange::INSERT_HOST);
3410  } else {
3411  host_exchange->createBindForDelete(host, subnet_id, reservation, option_space,
3412  option_descriptor, CqlHostExchange::DELETE_HOST, assigned_values);
3413 
3414  host_exchange->executeMutation(dbconn_, assigned_values, CqlHostExchange::DELETE_HOST);
3415  }
3416  } catch (const StatementNotApplied& exception) {
3417  if (insert) {
3418  isc_throw(DuplicateEntry, exception.what());
3419  } else {
3420  return (false);
3421  }
3422  }
3423 
3424  return (true);
3425 }
3426 
3427 void
3429  HostPtr& target_host) const {
3430  // Merge reservations.
3431  const IPv6ResrvRange reservations_range =
3432  source_host->getIPv6Reservations();
3433  if (std::distance(reservations_range.first, reservations_range.second) > 0) {
3434  for (IPv6ResrvIterator reservations_iterator = reservations_range.first;
3435  reservations_iterator != reservations_range.second;
3436  ++reservations_iterator) {
3437  if (!target_host->hasReservation(reservations_iterator->second)) {
3438  target_host->addReservation(reservations_iterator->second);
3439  }
3440  }
3441  }
3442 
3443  // Merge DHCPv4 options.
3444  source_host->getCfgOption4()->mergeTo(*target_host->getCfgOption4());
3445 
3446  // Merge DHCPv6 options.
3447  source_host->getCfgOption6()->mergeTo(*target_host->getCfgOption6());
3448 }
3449 
3451  : impl_(new CqlHostDataSourceImpl(parameters)) {
3452 }
3453 
3455  delete impl_;
3456 }
3457 
3458 void
3461 
3462  impl_->insertOrDelete(host, true);
3463 }
3464 
3465 bool
3466 CqlHostDataSource::del(const SubnetID& subnet_id, const asiolink::IOAddress& address) {
3467  HostPtr host = boost::const_pointer_cast<Host>(impl_->get4(subnet_id, address));
3468 
3469  return (host ? impl_->insertOrDelete(host, false) : false);
3470 }
3471 
3472 bool
3473 CqlHostDataSource::del4(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
3474  const uint8_t* identifier_begin, const size_t identifier_len) {
3475  HostPtr host = boost::const_pointer_cast<Host>(impl_->get4(subnet_id, identifier_type,
3476  identifier_begin, identifier_len));
3477 
3478  return (host ? impl_->insertOrDelete(host, false) : false);
3479 }
3480 
3481 bool
3482 CqlHostDataSource::del6(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
3483  const uint8_t* identifier_begin, const size_t identifier_len) {
3484  HostPtr host = boost::const_pointer_cast<Host>(impl_->get6(subnet_id, identifier_type,
3485  identifier_begin, identifier_len));
3486 
3487  return (host ? impl_->insertOrDelete(host, false) : false);
3488 }
3489 
3492  const uint8_t* identifier_begin,
3493  const size_t identifier_len) const {
3495 
3496  return (impl_->getAll(identifier_type, identifier_begin, identifier_len));
3497 }
3498 
3500 CqlHostDataSource::getAll4(const SubnetID& subnet_id) const {
3502 
3503  return (impl_->getAll4(subnet_id));
3504 }
3505 
3507 CqlHostDataSource::getAll6(const SubnetID& subnet_id) const {
3509 
3510  return (impl_->getAll6(subnet_id));
3511 }
3512 
3514 CqlHostDataSource::getAllbyHostname(const std::string& hostname) const {
3516 
3517  return (impl_->getAllbyHostname(hostname));
3518 }
3519 
3521 CqlHostDataSource::getAllbyHostname4(const std::string& hostname,
3522  const SubnetID& subnet_id) const {
3524 
3525  return (impl_->getAllbyHostname4(hostname, subnet_id));
3526 }
3527 
3529 CqlHostDataSource::getAllbyHostname6(const std::string& hostname,
3530  const SubnetID& subnet_id) const {
3532 
3533  return (impl_->getAllbyHostname6(hostname, subnet_id));
3534 }
3535 
3538  size_t& /*source_index*/,
3539  uint64_t lower_host_id,
3540  const HostPageSize& page_size) const {
3542 
3543  return (impl_->getPage4(subnet_id, lower_host_id, page_size));
3544 }
3545 
3548  size_t& /*source_index*/,
3549  uint64_t lower_host_id,
3550  const HostPageSize& page_size) const {
3552 
3553  return (impl_->getPage6(subnet_id, lower_host_id, page_size));
3554 }
3555 
3557 CqlHostDataSource::getPage4(size_t& /*source_index*/,
3558  uint64_t lower_host_id,
3559  const HostPageSize& page_size) const {
3561 
3562  return (impl_->getPage4(lower_host_id, page_size));
3563 }
3564 
3566 CqlHostDataSource::getPage6(size_t& /*source_index*/,
3567  uint64_t lower_host_id,
3568  const HostPageSize& page_size) const {
3570 
3571  return (impl_->getPage6(lower_host_id, page_size));
3572 }
3573 
3577 
3578  return (impl_->getAll4(address));
3579 }
3580 
3583  const Host::IdentifierType& identifier_type,
3584  const uint8_t* identifier_begin,
3585  const size_t identifier_len) const {
3587 
3588  return (impl_->get4(subnet_id, identifier_type, identifier_begin,
3589  identifier_len));
3590 }
3591 
3594  const asiolink::IOAddress& address) const {
3596 
3597  return (impl_->get4(subnet_id, address));
3598 }
3599 
3602  const asiolink::IOAddress& address) const {
3603  ConstHostCollection hosts;
3604  auto host = get4(subnet_id, address);
3605  if (host) {
3606  hosts.push_back(host);
3607  }
3608  return (hosts);
3609 }
3610 
3613  const Host::IdentifierType& identifier_type,
3614  const uint8_t* identifier_begin,
3615  const size_t identifier_len) const {
3617 
3618  return (impl_->get6(subnet_id, identifier_type, identifier_begin, identifier_len));
3619 }
3620 
3623  const uint8_t prefix_len) const {
3625 
3626  return (impl_->get6(prefix, prefix_len));
3627 }
3628 
3631  const asiolink::IOAddress& address) const {
3633 
3634  return (impl_->get6(subnet_id, address));
3635 }
3636 
3639  const asiolink::IOAddress& address) const {
3640  ConstHostCollection hosts;
3641  auto host = get6(subnet_id, address);
3642  if (host) {
3643  hosts.push_back(host);
3644  }
3645  return (hosts);
3646 }
3647 
3650  return (impl_->getAllHosts());
3651 }
3652 
3653 std::string
3655  return std::string("cql");
3656 }
3657 
3658 std::string
3660  return (impl_->getName());
3661 }
3662 
3663 std::string
3665  return std::string("Host data source that stores host information in the CQL database");
3666 }
3667 
3671 
3672  return impl_->getVersion();
3673 }
3674 
3675 void
3678 }
3679 
3680 void
3683 }
3684 
3685 bool
3687  // This backend does not support the mode in which multiple reservations
3688  // for the same IP address are created. If selecting this mode is
3689  // attempted this function returns false to indicate that this is
3690  // not allowed.
3691  return (unique);
3692 }
3693 
3694 } // namespace dhcp
3695 } // namespace isc
Database statement not applied.
Definition: db_exceptions.h:20
virtual bool del(const SubnetID &subnet_id, const asiolink::IOAddress &addr) override
Attempts to delete hosts by (subnet-id, address)
virtual ~CqlHostExchange()
Virtual destructor.
virtual bool del6(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) override
Attempts to delete a host by (subnet-id6, identifier-type, identifier).
static OptionDefinitionPtr getRuntimeOptionDef(const std::string &space, const uint16_t code)
Returns runtime (non-standard) option definition by space and option code.
Definition: libdhcp++.cc:185
const isc::log::MessageID DHCPSRV_CQL_COMMIT
Option descriptor.
Definition: cfg_option.h:42
void unspecified(bool unspecified)
Modifies the flag that indicates whether the value is specified or unspecified.
Definition: optional.h:121
void setContext(const data::ConstElementPtr &ctx)
Sets user context.
Definition: user_context.h:30
void executeMutation(const CqlConnection &connection, const AnyArray &assigned_values, StatementTag statement_tag)
Executes INSERT, UPDATE or DELETE statements.
static std::pair< uint32_t, uint32_t > getVersion(const ParameterMap &parameters)
Get the schema version.
virtual boost::any retrieve() override
Copy received data into Host object.
virtual ConstHostCollection getAll(const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const
Implementation of CqlHostDataSource::getAll()
Wraps value holding size of the page with host reservations.
virtual ConstHostCollection getAll6(const SubnetID &subnet_id) const
Implementation of CqlHostDataSource::getAll6()
virtual bool getNextHostKey4(const SubnetID &subnet_id, uint64_t &key) const
Retrieves next valid host key.
const size_t CLIENT_CLASSES_MAX_LEN
Maximum length of classes stored in a dhcp4/6_client_classes columns.
Definition: host.h:36
boost::shared_ptr< OptionDescriptor > OptionDescriptorPtr
A pointer to option descriptor.
Definition: cfg_option.h:31
Structure used to bind C++ input values to dynamic CQL parameters.
Definition: cql_exchange.h:50
virtual ConstHostCollection getAllbyHostname(const std::string &hostname) const
Implementation of CqlHostDataSource::getAllbyHostname()
virtual std::string getName() const
Implementation of CqlHostDataSource::getName()
virtual bool insertOrDeleteHost(bool insert, const HostPtr &host, const Optional< SubnetID > &subnet_id=Optional< SubnetID >(), const IPv6Resrv *const reservation=NULL, const std::string &option_space=NULL_OPTION_SPACE, const OptionDescriptor &option_descriptor=OptionDescriptor(false))
Inserts or deletes a single host.
A standard Data module exception that is thrown if a parse error is encountered when constructing an ...
Definition: data.h:43
virtual ConstHostCollection getAll4(const SubnetID &subnet_id) const
Implementation of CqlHostDataSource::getAll4()
boost::shared_ptr< Host > HostPtr
Pointer to the Host object.
Definition: host.h:785
const IPv6Resrv retrieveReservation() const
Creates IPv6 reservation from the data contained in the currently processed row.
const asiolink::IOAddress & getPrefix() const
Returns prefix for the reservation.
Definition: host.h:190
boost::shared_ptr< const CfgOption > ConstCfgOptionPtr
Const pointer.
Definition: cfg_option.h:709
CqlHostDataSourceImpl(const DatabaseConnection::ParameterMap &parameters)
Constructor.
virtual ConstHostPtr getHost(StatementTag statement_tag, AnyArray &where_values) const
Retrieves a single host.
const size_t page_size_
Holds page size.
boost::shared_ptr< Option > OptionPtr
Definition: option.h:36
virtual void createBindForSelect(AnyArray &data, StatementTag statement_tag=NULL) override
Binds member variables to data array to receive Host data.
void prepareStatements(StatementMap &statements)
Prepare statements.
Universe
defines option universe DHCPv4 or DHCPv6
Definition: option.h:82
virtual ConstHostCollection getAllbyHostname6(const std::string &hostname, const SubnetID &subnet_id) const
Implementation of CqlHostDataSource::getAllbyHostname6()
void openDatabase()
Open database.
virtual ConstHostCollection getAllbyHostname4(const std::string &hostname, const SubnetID &subnet_id) const override
Return all hosts with a hostname in a DHCPv4 subnet.
virtual ConstHostCollection getAll6(const SubnetID &subnet_id) const override
Return all hosts in a DHCPv6 subnet.
virtual ConstHostCollection getAllbyHostname4(const std::string &hostname, const SubnetID &subnet_id) const
Implementation of CqlHostDataSource::getAllbyHostname4()
std::vector< HostPtr > HostCollection
Collection of the Host objects.
Definition: host.h:794
const isc::log::MessageID DHCPSRV_CQL_HOST_GET6
virtual ConstHostPtr get4(const SubnetID &subnet_id, const asiolink::IOAddress &address) const
Implementation of CqlHostDataSource::get4()
static StatementMap tagged_statements_
Cassandra statements.
IPv6 reservation for a host.
Definition: host.h:161
const size_t OPTION_SPACE_MAX_LEN
Maximum length of option space name.
Definition: host.h:51
CfgOptionPtr getCfgOption6()
Returns pointer to the DHCPv6 option data configuration for this host.
Definition: host.h:655
const isc::log::MessageID DHCPSRV_CQL_HOST_GET_ALL
Cassandra Exchange.
Definition: cql_exchange.h:142
virtual ConstHostCollection getPage4(const SubnetID &subnet_id, size_t &source_index, uint64_t lower_host_id, const HostPageSize &page_size) const override
Returns range of hosts in a DHCPv4 subnet.
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Definition: option.h:24
Holds DUID (DHCPv6 Unique Identifier)
Definition: duid.h:27
Exception thrown on failure to open database.
char const *const StatementTag
Statement index representing the statement name.
bool hasReservation(const IPv6Resrv &reservation) const
Checks if specified IPv6 reservation exists for the host.
Definition: host.cc:408
virtual ConstHostCollection getPage6(const SubnetID &subnet_id, uint64_t lower_host_id, const HostPageSize &page_size) const
Implementation of CqlHostDataSource::getPage6()
uint64_t hashIntoKey() const
Create unique key for storage in table key.
Multiple lease records found where one expected.
Definition: db_exceptions.h:28
virtual ConstHostCollection getPage6(const SubnetID &subnet_id, size_t &source_index, uint64_t lower_host_id, const HostPageSize &page_size) const override
Returns range of hosts in a DHCPv6 subnet.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
std::string formatted_value_
Option value in textual (CSV) format.
Definition: cfg_option.h:66
virtual VersionPair getVersion() const
Implementation of CqlHostDataSource::getVersion()
virtual void mergeHosts(const ConstHostPtr &source_host, HostPtr &target_host) const
Merge denormalized table entries that belong to the same host into a single host, one by one...
void setHostId(HostID id)
Sets Host ID (primary key in MySQL, PostgreSQL and Cassandra backends)
Definition: host.h:670
Definition: edns.h:19
std::pair< IPv6ResrvIterator, IPv6ResrvIterator > IPv6ResrvRange
Definition: host.h:243
virtual ConstHostPtr getHostByKey(uint64_t key) const
Retrieves a host by key.
virtual bool setIPReservationsUnique(const bool unique) override
Controls whether IP reservations are unique or non-unique.
const isc::log::MessageID DHCPSRV_CQL_HOST_DB_GET_VERSION
void add(const boost::any &value)
Add a value at the end of the vector.
const int DHCPSRV_DBG_TRACE_DETAIL
Additional information.
Definition: dhcpsrv_log.h:38
std::vector< ConstHostPtr > ConstHostCollection
Collection of the const Host objects.
Definition: host.h:791
std::string hostKey() const
Create unique key string for a host.
virtual ConstHostCollection getAllHosts() const
Implementation of CqlHostDataSource::getAllHosts()
bool persistent_
Persistence flag.
Definition: cfg_option.h:51
std::vector< cass_byte_t > CassBlob
Host identifier converted to Cassandra data type.
Definition: cql_exchange.h:37
Implementation of the CqlHostDataSource.
virtual bool insertOrDeleteHostWithOptions(bool insert, const HostPtr &host, const IPv6Resrv *const reservation=NULL, const std::list< std::string > &option_spaces=std::list< std::string >(), const ConstCfgOptionPtr cfg_option=ConstCfgOptionPtr())
Adds/deletes any options found in the Host object to/from a separate table entry. ...
virtual void commit() override
Commit Transactions.
virtual bool getNextHostKey(uint64_t &key) const
Retrieves next valid host key.
virtual ConstHostPtr get6(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const override
Returns a Host connected to an IPv6 subnet.
virtual bool del4(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) override
Attempts to delete a host by (subnet-id4, identifier-type, identifier).
virtual void rollback() override
Rollback Transactions.
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:23
const isc::log::MessageID DHCPSRV_CQL_HOST_ADD
boost::shared_ptr< const Host > ConstHostPtr
Const pointer to the Host object.
Definition: host.h:788
Provides mechanisms for sending and retrieving data from the hosts table.
void createBindForDelete(const HostPtr &host, const Optional< SubnetID > &subnet_id, const IPv6Resrv *const reservation, const std::string &option_space, const OptionDescriptor &option_descriptor, StatementTag statement_tag, AnyArray &data)
Binds Host to data array to send data to the Cassandra database.
std::pair< uint32_t, uint32_t > VersionPair
Pair containing major and minor versions.
bool operator==(const HostKey &key1, const HostKey &key2)
equals operator for HostKey
data::ConstElementPtr getContext() const
Returns const pointer to the user context.
Definition: user_context.h:24
Represents a device with IPv4 and/or IPv6 reservations.
Definition: host.h:297
virtual bool getHostKey6(const SubnetID &subnet_id, uint64_t lower_host_id, uint64_t &key) const
Retrieves a valid host key.
Type
Type of the reservation.
Definition: host.h:167
CqlHostDataSource(const db::DatabaseConnection::ParameterMap &parameters)
Constructor.
std::string toText() const
Returns textual representation of a DUID (e.g. 00:01:02:03:ff)
Definition: duid.cc:75
void createBindForMutation(const HostPtr &host, const Optional< SubnetID > &subnet_id, const IPv6Resrv *const reservation, const std::string &option_space, const OptionDescriptor &option_descriptor, StatementTag statement_tag, AnyArray &data)
Binds Host to data array to send data to the Cassandra database.
static OptionDefinitionPtr getOptionDef(const std::string &space, const uint16_t code)
Return the first option definition matching a particular option code.
Definition: libdhcp++.cc:122
IPv6ResrvCollection::const_iterator IPv6ResrvIterator
Definition: host.h:241
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
Definition: buffer.h:294
virtual bool insertOrDeleteHostWithReservations(bool insert, const HostPtr &host, const IPv6Resrv *const reservation, const std::list< std::string > &option_spaces4, const ConstCfgOptionPtr cfg_option4, const std::list< std::string > &option_spaces6, const ConstCfgOptionPtr cfg_option6)
Adds/deletes any reservations found in the Host object to/from a separate table entry.
OptionPtr option_
Option instance.
Definition: cfg_option.h:45
virtual void add(const HostPtr &host) override
Adds a new host to the collection.
const isc::log::MessageID DHCPSRV_CQL_ROLLBACK
virtual ConstHostCollection getPage4(const SubnetID &subnet_id, uint64_t lower_host_id, const HostPageSize &page_size) const
Implementation of CqlHostDataSource::getPage4()
uint64_t hashIntoId() const
Create unique hash for storage in table id.
Authentication keys.
Definition: host.h:75
This is a base class for exceptions thrown from the DNS library module.
virtual std::string getName() const
Returns the name of the database.
constexpr uint32_t CQL_SCHEMA_VERSION_MAJOR
Define CQL schema version: 5.0.
Defines the logger used by the top-level component of kea-dhcp-ddns.
virtual ConstHostCollection getAll(const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const override
Return all hosts connected to any subnet for which reservations have been made using a specified iden...
std::string getParameter(const std::string &name) const
Returns value of a connection parameter.
static const size_t MAX_DUID_LEN
maximum duid size As defined in RFC 8415, section 11.1
Definition: duid.h:31
const isc::log::MessageID DHCPSRV_CQL_HOST_GET4
virtual bool getNextHostKey6(const SubnetID &subnet_id, uint64_t &key) const
Retrieves next valid host key.
virtual db::VersionPair getVersion() const
Retrieves schema version from the DB.
void addReservation(const IPv6Resrv &reservation)
Adds new IPv6 reservation.
Definition: host.cc:380
Type getType() const
Returns reservation type.
Definition: host.h:204
#define DHCP6_OPTION_SPACE
std::unordered_map< StatementTag, CqlTaggedStatement, StatementTagHash, StatementTagEqual > StatementMap
A container for all statements.
virtual bool getHostKey(uint64_t lower_host_id, uint64_t &key) const
Retrieves a valid host key.
AnyArray executeSelect(const CqlConnection &connection, const AnyArray &where_values, StatementTag statement_tag, const bool &single=false)
Executes SELECT statements.
#define DHCP4_OPTION_SPACE
global std option spaces
constexpr uint32_t CQL_SCHEMA_VERSION_MINOR
virtual ~CqlHostDataSourceImpl()
Destructor.
boost::shared_ptr< OptionContainer > OptionContainerPtr
Pointer to the OptionContainer object.
Definition: cfg_option.h:272
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
virtual std::string getDescription() const
Returns textual description of the backend.
virtual ConstHostCollection getHostCollectionPage6(const SubnetID &subnet_id, uint64_t lower_host_id, size_t count=0) const
Retrieves a page of hosts.
virtual ConstHostCollection getAllbyHostname6(const std::string &hostname, const SubnetID &subnet_id) const override
Return all hosts with a hostname in a DHCPv6 subnet.
virtual ConstHostCollection getHostCollection(StatementTag statement_tag, AnyArray &where_values) const
Retrieves a collection of hosts.
boost::shared_ptr< OptionDefinition > OptionDefinitionPtr
Pointer to option definition object.
virtual bool insertOrDelete(const HostPtr &host, bool insert)
Implementation of CqlHostDataSource::add() and del()
virtual bool getHostKey4(const SubnetID &subnet_id, uint64_t lower_host_id, uint64_t &key) const
Retrieves a valid host key.
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition: dhcpsrv_log.h:56
static uint32_t optionSpaceToVendorId(const std::string &option_space)
Converts option space name to vendor id.
Definition: libdhcp++.cc:925
IdentifierType
Type of the host identifier.
Definition: host.h:307
Common CQL connector pool.
std::map< std::string, std::string > ParameterMap
Database configuration parameter map.
uint8_t getPrefixLen() const
Returns prefix length.
Definition: host.h:195
HostKeyComponent
Identifies components of the host key.
const OptionWrapper retrieveOption() const
Retrieves option from members.
virtual ConstHostCollection getHostCollectionPage4(const SubnetID &subnet_id, uint64_t lower_host_id, size_t count=0) const
Retrieves a page of hosts.
std::size_t hash_value(const HostKey &key)
hash function for HostMap
virtual ConstHostPtr get6(const asiolink::IOAddress &prefix, const uint8_t prefix_len) const
Retrieves a host by its reserved IPv6 address or prefix.
virtual ~CqlHostDataSource()
Virtual destructor.
A template representing an optional value.
Definition: optional.h:36
virtual std::string getType() const override
Return backend type.
virtual ConstHostCollection getAllHosts() const
Returns a collection of all the hosts.
virtual ConstHostCollection getAllbyHostname(const std::string &hostname) const override
Return all hosts with a hostname.
Exception thrown on failure to execute a database function.
CfgOptionPtr getCfgOption4()
Returns pointer to the DHCPv4 option data configuration for this host.
Definition: host.h:640
Database duplicate entry error.
Definition: db_exceptions.h:42
static OptionDefinitionPtr getVendorOptionDef(const Option::Universe u, const uint32_t vendor_id, const uint16_t code)
Returns vendor option definition for a given vendor-id and code.
Definition: libdhcp++.cc:164
uint32_t SubnetID
Unique identifier for a subnet (both v4 and v6)
Definition: lease.h:24
virtual ConstHostCollection getAll4(const SubnetID &subnet_id) const override
Return all hosts in a DHCPv4 subnet.
void prepareExchange(const HostPtr &host, const Optional< SubnetID > &subnet_id, const IPv6Resrv *const reservation, const std::string &option_space, const OptionDescriptor &option_descriptor)
Sets the exchange members with data of Host.
virtual ConstHostPtr get4(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const override
Retrieves a Host connected to an IPv4 subnet.