blob: 52f9043d6305e49cbd0c5ec779c5365be52a3715 [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
33void 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
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
47size_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
53size_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
78size_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
89size_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