LCOV - code coverage report
Current view: top level - src/UniqueIdService - UniqueIdHandler.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 67 80 83.8 %
Date: 2025-11-03 23:12:34 Functions: 5 7 71.4 %

          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

Generated by: LCOV version 1.12