1 #include "sdbusplus/server/transaction.hpp" 2 3 namespace sdbusplus 4 { 5 namespace server 6 { 7 namespace transaction 8 { 9 namespace details 10 { 11 12 // Transaction Id 13 thread_local uint64_t id = 0; 14 15 } // namespace details 16 17 uint64_t get_id() 18 { 19 // If the transaction id has not been initialized, generate one. 20 if (!details::id) 21 { 22 details::Transaction t; 23 details::id = std::hash<details::Transaction>{}(t); 24 } 25 return details::id; 26 } 27 28 void set_id(uint64_t value) 29 { 30 details::id = value; 31 } 32 33 void set_id(message::message& msg) 34 { 35 auto tbus = msg.get_bus(); 36 auto t = Transaction(tbus, msg); 37 set_id(std::hash<Transaction>{}(t)); 38 } 39 40 } // namespace transaction 41 } // namespace server 42 } // namespace sdbusplus 43 44 namespace std 45 { 46 47 size_t hash<sdbusplus::bus::bus>::operator()(sdbusplus::bus::bus& b) const 48 { 49 auto name = b.get_unique_name(); 50 return std::hash<std::string>{}(name); 51 } 52 53 size_t hash<sdbusplus::message::message>::operator()( 54 sdbusplus::message::message& m) const 55 { 56 switch (m.get_type()) 57 { 58 // Reply messages will always embed the cookie of the original 59 // message in a separate location. We want to use this cookie 60 // to correlate messages as one transaction. 61 case SD_BUS_MESSAGE_METHOD_RETURN: 62 case SD_BUS_MESSAGE_METHOD_ERROR: 63 return std::hash<uint64_t>{}(m.get_reply_cookie()); 64 // Method calls will have the cookie in the header when sealed. 65 // Since we are on the server side that should always be the case. 66 case SD_BUS_MESSAGE_METHOD_CALL: 67 return std::hash<uint64_t>{}(m.get_cookie()); 68 // Outgoing signals don't have a cookie so we need to use 69 // something else as an id. Just use a monotonic unique one. 70 case SD_BUS_MESSAGE_SIGNAL: 71 return std::hash<uint64_t>{}( 72 std::chrono::steady_clock::now().time_since_epoch().count()); 73 default: 74 throw std::runtime_error("hash message: Unknown message type"); 75 } 76 } 77 78 size_t hash<sdbusplus::server::transaction::Transaction>::operator()( 79 sdbusplus::server::transaction::Transaction const& t) const 80 { 81 auto hash1 = std::hash<sdbusplus::bus::bus>{}(t.bus); 82 auto hash2 = std::hash<sdbusplus::message::message>{}(t.msg); 83 84 // boost::hash_combine() algorithm. 85 return static_cast<size_t>( 86 hash1 ^ (hash2 + 0x9e3779b9 + (hash1 << 6) + (hash1 >> 2))); 87 } 88 89 size_t hash<sdbusplus::server::transaction::details::Transaction>::operator()( 90 sdbusplus::server::transaction::details::Transaction const& t) const 91 { 92 auto hash1 = std::hash<int>{}(t.time); 93 auto hash2 = std::hash<std::thread::id>{}(t.thread); 94 95 // boost::hash_combine() algorithm. 96 return static_cast<size_t>( 97 hash1 ^ (hash2 + 0x9e3779b9 + (hash1 << 6) + (hash1 >> 2))); 98 } 99 } // namespace std 100