Line data Source code
1 : /* 2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #ifndef ctrlplane_db_entry_h 6 : #define ctrlplane_db_entry_h 7 : 8 : #include <map> 9 : #include <atomic> 10 : 11 : #include "db/db_table.h" 12 : 13 : #include <boost/intrusive/list.hpp> 14 : #include <boost/intrusive/set.hpp> 15 : 16 : struct DBState { 17 3096591 : virtual ~DBState() { } 18 : }; 19 : 20 : // Generic database entry 21 : class DBEntryBase { 22 : public: 23 : typedef DBTableBase::ListenerId ListenerId; 24 : typedef std::unique_ptr<DBRequestKey> KeyPtr; 25 : 26 : DBEntryBase(); 27 : virtual ~DBEntryBase(); 28 : virtual std::string ToString() const = 0; 29 : virtual KeyPtr GetDBRequestKey() const = 0; 30 13 : virtual bool IsMoreSpecific(const std::string &match) const { 31 13 : return false; 32 : } 33 10 : virtual bool IsLessSpecific(const std::string &match) const { 34 10 : return false; 35 : } 36 : 37 : void SetState(DBTableBase *tbl_base, ListenerId listener, DBState *state); 38 : void ClearState(DBTableBase *tbl_base, ListenerId listener); 39 : DBState *GetState(DBTableBase *tbl_base, ListenerId listener) const; 40 : const DBState *GetState(const DBTableBase *tbl_base, 41 : ListenerId listener) const; 42 : bool is_state_empty(DBTablePartBase *tpart); 43 : bool is_state_empty_unlocked(DBTablePartBase *tpart); 44 : 45 : void Delete(); 46 856606 : void MarkDelete() { flags |= DeleteMarked; } 47 767379 : void ClearDelete() { flags &= ~DeleteMarked; } 48 15161686 : bool IsDeleted() const { return (flags & DeleteMarked) != 0; } 49 : 50 2512325 : void set_onlist() { flags |= Onlist; } 51 2507202 : void clear_onlist() { flags &= ~Onlist; } 52 6298440 : bool is_onlist() { return (flags & Onlist); } 53 : 54 513655 : void SetOnRemoveQ() { 55 513655 : onremoveq_.exchange(true); 56 513809 : } 57 1035766 : bool IsOnRemoveQ() { return (onremoveq_); } 58 41 : void ClearOnRemoveQ() { 59 41 : onremoveq_.exchange(false); 60 41 : } 61 : 62 : //member hook in change list 63 : boost::intrusive::list_member_hook<> chg_list_; 64 : 65 : void set_last_change_at(uint64_t time); 66 : void set_last_change_at_to_now(); 67 6322 : const uint64_t last_change_at() const { return last_change_at_; } 68 : const std::string last_change_at_str() const; 69 : void set_last_update_at(uint64_t time); 70 : void set_last_update_at_to_now(); 71 1984506 : const uint64_t last_update_at() const { return last_update_at_; } 72 : DBTablePartBase *get_table_partition() const; 73 : void set_table_partition(DBTablePartBase *tpart); 74 : DBTableBase *get_table() const; 75 : void Notify(); 76 : 77 : private: 78 : enum DbEntryFlags { 79 : Onlist = 1 << 0, 80 : DeleteMarked = 1 << 1, 81 : }; 82 : typedef std::map<ListenerId, DBState *> StateMap; 83 : DBTablePartBase *tpart_; 84 : StateMap state_; 85 : uint8_t flags; 86 : std::atomic<bool> onremoveq_; 87 : uint64_t last_change_at_; // time at which entry was last 'changed' 88 : uint64_t last_update_at_; // time at which entry was last 'updated' 89 : DISALLOW_COPY_AND_ASSIGN(DBEntryBase); 90 : }; 91 : 92 : // An implementation of DBEntryBase that uses boost::set as data-store 93 : // Most of the DB Table implementations should derive from here instead of 94 : // DBEntryBase directly. 95 : // Derive directly from DBEntryBase only if there is a strong reason to do so 96 : class DBEntry : public DBEntryBase { 97 : public: 98 4605036 : DBEntry() { }; 99 4604719 : virtual ~DBEntry() { }; 100 : 101 : // Set key fields in the DBEntry 102 : virtual void SetKey(const DBRequestKey *key) = 0; 103 : 104 : // Comparator used in Tree management 105 : virtual bool IsLess(const DBEntry &rhs) const = 0; 106 : 107 30687958 : bool operator<(const DBEntry &rhs) const { 108 30687958 : return IsLess(rhs); 109 : } 110 : 111 : private: 112 : friend class DBTablePartition; 113 : boost::intrusive::set_member_hook<> node_; 114 : DISALLOW_COPY_AND_ASSIGN(DBEntry); 115 : }; 116 : 117 : #endif