Line data Source code
1 : #ifndef SOCIAL_NETWORK_MICROSERVICES_UNIQUEIDHANDLER_H
2 : #define SOCIAL_NETWORK_MICROSERVICES_UNIQUEIDHANDLER_H
3 :
4 : #include <chrono>
5 : #include <iomanip>
6 : #include <iostream>
7 : #include <mutex>
8 : #include <sstream>
9 : #include <string>
10 :
11 : #include "../../gen-cpp/UniqueIdService.h"
12 : #include "../../gen-cpp/social_network_types.h"
13 : #include "../logger.h"
14 : #include "../tracing.h"
15 :
16 : // Custom Epoch (January 1, 2018 Midnight GMT = 2018-01-01T00:00:00Z)
17 : #define CUSTOM_EPOCH 1514764800000
18 :
19 : namespace social_network {
20 :
21 : using std::chrono::duration_cast;
22 : using std::chrono::milliseconds;
23 : using std::chrono::system_clock;
24 :
25 : static int64_t current_timestamp = -1;
26 : static int counter = 0;
27 :
28 200 : static int GetCounter(int64_t timestamp) {
29 200 : if (current_timestamp > timestamp) {
30 0 : LOG(fatal) << "Timestamps are not incremental.";
31 0 : exit(EXIT_FAILURE);
32 : }
33 200 : if (current_timestamp == timestamp) {
34 0 : return counter++;
35 : } else {
36 200 : current_timestamp = timestamp;
37 200 : counter = 0;
38 200 : return counter++;
39 : }
40 : }
41 :
42 : class UniqueIdHandler : public UniqueIdServiceIf {
43 : public:
44 0 : ~UniqueIdHandler() override = default;
45 : UniqueIdHandler(std::mutex *, const std::string &);
46 :
47 : int64_t ComposeUniqueId(int64_t, PostType::type,
48 : const std::map<std::string, std::string> &) override;
49 :
50 : private:
51 : std::mutex *_thread_lock;
52 : std::string _machine_id;
53 : };
54 :
55 1 : UniqueIdHandler::UniqueIdHandler(std::mutex *thread_lock,
56 1 : const std::string &machine_id) {
57 1 : _thread_lock = thread_lock;
58 1 : _machine_id = machine_id;
59 1 : }
60 :
61 200 : int64_t UniqueIdHandler::ComposeUniqueId(
62 : int64_t req_id, PostType::type post_type,
63 : const std::map<std::string, std::string> &carrier) {
64 : // 新增:记录收到的 ComposeUniqueId 请求
65 400 : LOG(info) << "Received ComposeUniqueId request [req_id=" << req_id << ", post_type=" << post_type << "]";
66 :
67 : // Initialize a span
68 400 : TextMapReader reader(carrier);
69 400 : std::map<std::string, std::string> writer_text_map;
70 400 : TextMapWriter writer(writer_text_map);
71 400 : auto parent_span = opentracing::Tracer::Global()->Extract(reader);
72 400 : auto span = opentracing::Tracer::Global()->StartSpan(
73 800 : "compose_unique_id_server", {opentracing::ChildOf(parent_span->get())});
74 200 : opentracing::Tracer::Global()->Inject(span->context(), writer);
75 :
76 200 : _thread_lock->lock();
77 : int64_t timestamp =
78 400 : duration_cast<milliseconds>(system_clock::now().time_since_epoch())
79 200 : .count() -
80 200 : CUSTOM_EPOCH;
81 200 : int idx = GetCounter(timestamp);
82 200 : _thread_lock->unlock();
83 :
84 : // 新增:记录时间戳和计数器
85 400 : LOG(info) << "ComposeUniqueId timestamp and counter [req_id=" << req_id << ", timestamp=" << timestamp << ", counter=" << idx << "]";
86 :
87 400 : std::stringstream sstream;
88 200 : sstream << std::hex << timestamp;
89 400 : std::string timestamp_hex(sstream.str());
90 :
91 200 : if (timestamp_hex.size() > 10) {
92 0 : timestamp_hex.erase(0, timestamp_hex.size() - 10);
93 200 : } else if (timestamp_hex.size() < 10) {
94 0 : timestamp_hex = std::string(10 - timestamp_hex.size(), '0') + timestamp_hex;
95 : }
96 :
97 : // Empty the sstream buffer.
98 200 : sstream.clear();
99 200 : sstream.str(std::string());
100 :
101 200 : sstream << std::hex << idx;
102 400 : std::string counter_hex(sstream.str());
103 :
104 200 : if (counter_hex.size() > 3) {
105 0 : counter_hex.erase(0, counter_hex.size() - 3);
106 200 : } else if (counter_hex.size() < 3) {
107 200 : counter_hex = std::string(3 - counter_hex.size(), '0') + counter_hex;
108 : }
109 400 : std::string post_id_str = _machine_id + timestamp_hex + counter_hex;
110 200 : int64_t post_id = stoul(post_id_str, nullptr, 16) & 0x7FFFFFFFFFFFFFFF;
111 200 : LOG(debug) << "The post_id of the request " << req_id << " is " << post_id;
112 :
113 200 : span->Finish();
114 400 : return post_id;
115 : }
116 :
117 : /*
118 : * The following code which obtaines machine ID from machine's MAC address was
119 : * inspired from https://stackoverflow.com/a/16859693.
120 : *
121 : * MAC address is obtained from /sys/class/net/<netif>/address
122 : */
123 1 : u_int16_t HashMacAddressPid(const std::string &mac) {
124 1 : u_int16_t hash = 0;
125 2 : std::string mac_pid = mac + std::to_string(getpid());
126 19 : for (unsigned int i = 0; i < mac_pid.size(); i++) {
127 18 : hash += (mac[i] << ((i & 1) * 8));
128 : }
129 2 : return hash;
130 : }
131 :
132 1 : std::string GetMachineId(std::string &netif) {
133 2 : std::string mac_hash;
134 :
135 2 : std::string mac_addr_filename = "/sys/class/net/" + netif + "/address";
136 2 : std::ifstream mac_addr_file;
137 1 : mac_addr_file.open(mac_addr_filename);
138 1 : if (!mac_addr_file) {
139 0 : LOG(fatal) << "Cannot read MAC address from net interface " << netif;
140 0 : return "";
141 : }
142 2 : std::string mac;
143 1 : mac_addr_file >> mac;
144 1 : if (mac == "") {
145 0 : LOG(fatal) << "Cannot read MAC address from net interface " << netif;
146 0 : return "";
147 : }
148 1 : mac_addr_file.close();
149 :
150 2 : LOG(info) << "MAC address = " << mac;
151 :
152 2 : std::stringstream stream;
153 1 : stream << std::hex << HashMacAddressPid(mac);
154 1 : mac_hash = stream.str();
155 :
156 1 : if (mac_hash.size() > 3) {
157 1 : mac_hash.erase(0, mac_hash.size() - 3);
158 0 : } else if (mac_hash.size() < 3) {
159 0 : mac_hash = std::string(3 - mac_hash.size(), '0') + mac_hash;
160 : }
161 1 : return mac_hash;
162 : }
163 :
164 : } // namespace social_network
165 :
166 : #endif // SOCIAL_NETWORK_MICROSERVICES_UNIQUEIDHANDLER_H
|