blob: f70bb37c302df657a44d77e0e1f493378b99ddc2 [file] [log] [blame]
Patrick Williams7f664252020-06-04 10:20:56 -05001#include "sdbusplus/server/transaction.hpp"
Adriana Kobylak1afb4e62017-01-31 11:10:01 -06002
3namespace sdbusplus
4{
5namespace server
6{
7namespace transaction
8{
9namespace details
10{
11
12// Transaction Id
13thread_local uint64_t id = 0;
14
15} // namespace details
Patrick Williams32ffb032020-10-12 12:17:48 -050016
17uint64_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
28void set_id(uint64_t value)
29{
30 details::id = value;
31}
32
Patrick Williams10d7aa12021-11-19 11:36:18 -060033void set_id(message_t& msg)
Patrick Williams32ffb032020-10-12 12:17:48 -050034{
35 auto tbus = msg.get_bus();
36 auto t = Transaction(tbus, msg);
37 set_id(std::hash<Transaction>{}(t));
38}
39
Adriana Kobylak1afb4e62017-01-31 11:10:01 -060040} // namespace transaction
41} // namespace server
42} // namespace sdbusplus
Patrick Williams32ffb032020-10-12 12:17:48 -050043
44namespace std
45{
46
Patrick Williams0f282c42021-11-19 11:36:18 -060047size_t hash<sdbusplus::bus_t>::operator()(sdbusplus::bus_t& b) const
Patrick Williams32ffb032020-10-12 12:17:48 -050048{
49 auto name = b.get_unique_name();
50 return std::hash<std::string>{}(name);
51}
52
Patrick Williams10d7aa12021-11-19 11:36:18 -060053size_t hash<sdbusplus::message_t>::operator()(sdbusplus::message_t& m) const
Patrick Williams32ffb032020-10-12 12:17:48 -050054{
55 switch (m.get_type())
56 {
57 // Reply messages will always embed the cookie of the original
58 // message in a separate location. We want to use this cookie
59 // to correlate messages as one transaction.
60 case SD_BUS_MESSAGE_METHOD_RETURN:
61 case SD_BUS_MESSAGE_METHOD_ERROR:
62 return std::hash<uint64_t>{}(m.get_reply_cookie());
63 // Method calls will have the cookie in the header when sealed.
64 // Since we are on the server side that should always be the case.
65 case SD_BUS_MESSAGE_METHOD_CALL:
66 return std::hash<uint64_t>{}(m.get_cookie());
67 // Outgoing signals don't have a cookie so we need to use
68 // something else as an id. Just use a monotonic unique one.
69 case SD_BUS_MESSAGE_SIGNAL:
70 return std::hash<uint64_t>{}(
71 std::chrono::steady_clock::now().time_since_epoch().count());
72 default:
73 throw std::runtime_error("hash message: Unknown message type");
74 }
75}
76
77size_t hash<sdbusplus::server::transaction::Transaction>::operator()(
78 sdbusplus::server::transaction::Transaction const& t) const
79{
Patrick Williams0f282c42021-11-19 11:36:18 -060080 auto hash1 = std::hash<sdbusplus::bus_t>{}(t.bus);
Patrick Williams10d7aa12021-11-19 11:36:18 -060081 auto hash2 = std::hash<sdbusplus::message_t>{}(t.msg);
Patrick Williams32ffb032020-10-12 12:17:48 -050082
83 // boost::hash_combine() algorithm.
84 return static_cast<size_t>(
85 hash1 ^ (hash2 + 0x9e3779b9 + (hash1 << 6) + (hash1 >> 2)));
86}
87
88size_t hash<sdbusplus::server::transaction::details::Transaction>::operator()(
89 sdbusplus::server::transaction::details::Transaction const& t) const
90{
91 auto hash1 = std::hash<int>{}(t.time);
92 auto hash2 = std::hash<std::thread::id>{}(t.thread);
93
94 // boost::hash_combine() algorithm.
95 return static_cast<size_t>(
96 hash1 ^ (hash2 + 0x9e3779b9 + (hash1 << 6) + (hash1 >> 2)));
97}
98} // namespace std