Skip to content

Commit dbbc155

Browse files
ifplusorShannonDing
authored andcommitted
remove boost from StringIdMaker, and fix some bugs. (#183)
1 parent e237d8b commit dbbc155

File tree

5 files changed

+133
-195
lines changed

5 files changed

+133
-195
lines changed

src/message/BatchMessage.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,17 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17-
1817
#include "BatchMessage.h"
18+
1919
#include "MQDecoder.h"
2020
#include "StringIdMaker.h"
2121

22-
using namespace std;
2322
namespace rocketmq {
2423

2524
std::string BatchMessage::encode(std::vector<MQMessage>& msgs) {
26-
string encodedBody;
25+
std::string encodedBody;
2726
for (auto message : msgs) {
28-
string unique_id = StringIdMaker::get_mutable_instance().get_unique_id();
27+
std::string unique_id = StringIdMaker::getInstance().createUniqID();
2928
message.setProperty(MQMessage::PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX, unique_id);
3029
encodedBody.append(encode(message));
3130
}
@@ -59,4 +58,5 @@ std::string BatchMessage::encode(MQMessage& message) {
5958
encodeMsg.append(properties.c_str(), propertiesLength);
6059
return encodeMsg;
6160
}
62-
}
61+
62+
} // namespace rocketmq

src/producer/DefaultMQProducer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ SendResult DefaultMQProducer::sendKernelImpl(MQMessage& msg,
395395
bool isBatchMsg = std::type_index(typeid(msg)) == std::type_index(typeid(BatchMessage));
396396
// msgId is produced by client, offsetMsgId produced by broker. (same with java sdk)
397397
if (!isBatchMsg) {
398-
string unique_id = StringIdMaker::get_mutable_instance().get_unique_id();
398+
string unique_id = StringIdMaker::getInstance().createUniqID();
399399
msg.setProperty(MQMessage::PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX, unique_id);
400400

401401
// batch does not support compressing right now,

src/producer/StringIdMaker.cpp

Lines changed: 87 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -16,175 +16,121 @@
1616
*/
1717
#include "StringIdMaker.h"
1818

19+
#include <cstdio>
20+
#include <cstdlib>
21+
#include <cstring>
22+
#include <ctime>
23+
24+
#include "ByteOrder.h"
25+
#include "UtilAll.h"
26+
1927
namespace rocketmq {
2028

21-
#ifdef WIN32
22-
int gettimeofdayWin(struct timeval* tp, void* tzp) {
23-
time_t clock;
24-
struct tm tm;
25-
SYSTEMTIME wtm;
26-
GetLocalTime(&wtm);
27-
tm.tm_year = wtm.wYear - 1900;
28-
tm.tm_mon = wtm.wMonth - 1;
29-
tm.tm_mday = wtm.wDay;
30-
tm.tm_hour = wtm.wHour;
31-
tm.tm_min = wtm.wMinute;
32-
tm.tm_sec = wtm.wSecond;
33-
tm.tm_isdst = -1;
34-
clock = mktime(&tm);
35-
tp->tv_sec = clock;
36-
tp->tv_usec = wtm.wMilliseconds * 1000;
37-
return (0);
38-
}
39-
#endif
29+
const char StringIdMaker::sHexAlphabet[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
30+
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
4031

4132
StringIdMaker::StringIdMaker() {
42-
memset(_buff, 0, sizeof(_buff));
43-
memset(_0x_buff, 0, sizeof(_0x_buff));
44-
srand((uint32_t)time(NULL));
45-
init_prefix();
46-
}
47-
StringIdMaker::~StringIdMaker() {}
33+
std::srand((uint32_t)std::time(NULL));
4834

49-
void StringIdMaker::init_prefix() {
50-
uint32_t pid = getpid();
51-
uint32_t ip = get_ip();
52-
uint32_t random_num = (rand() % 0xFFFF);
35+
uint32_t pid = ByteOrder::swapIfLittleEndian(static_cast<uint32_t>(getpid()));
36+
uint32_t ip = ByteOrder::swapIfLittleEndian(getIP());
37+
uint32_t random_num = ByteOrder::swapIfLittleEndian(static_cast<uint32_t>(std::rand()));
5338

54-
memcpy(_buff + 2, &pid, 4);
55-
memcpy(_buff, &ip, 4);
56-
memcpy(_buff + 6, &random_num, 4);
39+
unsigned char bin_buf[10];
40+
std::memcpy(bin_buf + 2, &pid, 4);
41+
std::memcpy(bin_buf, &ip, 4);
42+
std::memcpy(bin_buf + 6, &random_num, 4);
5743

58-
hexdump(_buff, _0x_buff, 10);
44+
hexdump(bin_buf, kFixString, 10);
45+
kFixString[20] = '\0';
5946

60-
set_start_and_next_tm();
47+
setStartTime(UtilAll::currentTimeMillis());
48+
49+
mCounter = 0;
6150
}
6251

63-
uint32_t StringIdMaker::get_ip() {
64-
char name[1024];
65-
boost::system::error_code ec;
66-
if (boost::asio::detail::socket_ops::gethostname(name, sizeof(name), ec) != 0) {
67-
return 0;
68-
}
52+
StringIdMaker::~StringIdMaker() {}
6953

70-
boost::asio::io_service io_service;
71-
boost::asio::ip::tcp::resolver resolver(io_service);
72-
boost::asio::ip::tcp::resolver::query query(name, "");
73-
boost::system::error_code error;
74-
boost::asio::ip::tcp::resolver::iterator iter = resolver.resolve(query, error);
75-
if (error) {
54+
uint32_t StringIdMaker::getIP() {
55+
std::string ip = UtilAll::getLocalAddress();
56+
if (ip.empty()) {
7657
return 0;
7758
}
78-
boost::asio::ip::tcp::resolver::iterator end; // End marker.
79-
boost::asio::ip::tcp::endpoint ep;
80-
while (iter != end) {
81-
ep = *iter++;
82-
}
83-
std::string s_localIpAddress = ep.address().to_string();
84-
85-
int a[4];
86-
std::string IP = s_localIpAddress;
87-
std::string strTemp;
88-
size_t pos;
89-
size_t i = 3;
90-
91-
do {
92-
pos = IP.find(".");
93-
94-
if (pos != std::string::npos) {
95-
strTemp = IP.substr(0, pos);
96-
a[i] = atoi(strTemp.c_str());
97-
i--;
98-
IP.erase(0, pos + 1);
99-
} else {
100-
strTemp = IP;
101-
a[i] = atoi(strTemp.c_str());
102-
break;
103-
}
104-
105-
} while (1);
106-
107-
uint32_t nResult = (a[3] << 24) + (a[2] << 16) + (a[1] << 8) + a[0];
108-
return nResult;
109-
}
11059

111-
uint64_t StringIdMaker::get_curr_ms() {
112-
struct timeval time_now;
113-
// windows and linux use the same function name, windows's defination as begining this file
114-
#ifdef WIN32
115-
gettimeofdayWin(&time_now, NULL); // WIN32
116-
#else
117-
gettimeofday(&time_now, NULL); // LINUX
118-
#endif
119-
120-
uint64_t ms_time = time_now.tv_sec * 1000 + time_now.tv_usec / 1000;
121-
return ms_time;
122-
}
60+
char* ip_str = new char[ip.length() + 1];
61+
std::strncpy(ip_str, ip.c_str(), ip.length());
62+
ip_str[ip.length()] = '\0';
12363

124-
void StringIdMaker::set_start_and_next_tm() {
125-
time_t tmNow = time(NULL);
126-
tm* ptmNow = localtime(&tmNow);
127-
tm mon_begin;
128-
mon_begin.tm_year = ptmNow->tm_year;
129-
mon_begin.tm_mon = ptmNow->tm_mon;
130-
mon_begin.tm_mday = 0;
131-
mon_begin.tm_hour = 0;
132-
mon_begin.tm_min = 0;
133-
mon_begin.tm_sec = 0;
134-
135-
tm mon_next_begin;
136-
if (ptmNow->tm_mon == 12) {
137-
mon_next_begin.tm_year = ptmNow->tm_year + 1;
138-
mon_next_begin.tm_mon = 1;
139-
} else {
140-
mon_next_begin.tm_year = ptmNow->tm_year;
141-
mon_next_begin.tm_mon = ptmNow->tm_mon + 1;
64+
int i = 3;
65+
uint32_t nResult = 0;
66+
for (char* token = std::strtok(ip_str, "."); token != nullptr && i >= 0; token = std::strtok(nullptr, ".")) {
67+
uint32_t n = std::atoi(token);
68+
nResult |= n << (8 * i--);
14269
}
143-
mon_next_begin.tm_mday = 0;
144-
mon_next_begin.tm_hour = 0;
145-
mon_next_begin.tm_min = 0;
146-
mon_next_begin.tm_sec = 0;
14770

148-
time_t mon_begin_tm = mktime(&mon_begin);
149-
time_t mon_end_tm = mktime(&mon_next_begin);
71+
delete[] ip_str;
15072

151-
_start_tm = mon_begin_tm * 1000;
152-
_next_start_tm = mon_end_tm * 1000;
73+
return nResult;
15374
}
15475

155-
int StringIdMaker::atomic_incr(int id) {
156-
#ifdef WIN32
157-
InterlockedIncrement((LONG*)&id);
158-
#else
159-
__sync_add_and_fetch(&id, 1);
160-
#endif
161-
return id;
76+
void StringIdMaker::setStartTime(uint64_t millis) {
77+
// std::time_t
78+
// Although not defined, this is almost always an integral value holding the number of seconds
79+
// (not counting leap seconds) since 00:00, Jan 1 1970 UTC, corresponding to POSIX time.
80+
std::time_t tmNow = millis / 1000;
81+
std::tm* ptmNow = std::localtime(&tmNow); // may not be thread-safe
82+
83+
std::tm curMonthBegin = {0};
84+
curMonthBegin.tm_year = ptmNow->tm_year; // since 1900
85+
curMonthBegin.tm_mon = ptmNow->tm_mon; // [0, 11]
86+
curMonthBegin.tm_mday = 1; // [1, 31]
87+
curMonthBegin.tm_hour = 0; // [0, 23]
88+
curMonthBegin.tm_min = 0; // [0, 59]
89+
curMonthBegin.tm_sec = 0; // [0, 60]
90+
91+
std::tm nextMonthBegin = {0};
92+
if (ptmNow->tm_mon >= 11) {
93+
nextMonthBegin.tm_year = ptmNow->tm_year + 1;
94+
nextMonthBegin.tm_mon = 0;
95+
} else {
96+
nextMonthBegin.tm_year = ptmNow->tm_year;
97+
nextMonthBegin.tm_mon = ptmNow->tm_mon + 1;
98+
}
99+
nextMonthBegin.tm_mday = 1;
100+
nextMonthBegin.tm_hour = 0;
101+
nextMonthBegin.tm_min = 0;
102+
nextMonthBegin.tm_sec = 0;
103+
104+
mStartTime = std::mktime(&curMonthBegin) * 1000;
105+
mNextStartTime = std::mktime(&nextMonthBegin) * 1000;
162106
}
163-
std::string StringIdMaker::get_unique_id() {
164-
uint64_t now_time = get_curr_ms();
165107

166-
if (now_time > _next_start_tm) {
167-
set_start_and_next_tm();
108+
std::string StringIdMaker::createUniqID() {
109+
uint64_t current = UtilAll::currentTimeMillis();
110+
if (current >= mNextStartTime) {
111+
setStartTime(current);
112+
current = UtilAll::currentTimeMillis();
168113
}
169-
uint32_t tm_period = now_time - _start_tm;
170-
seqid = atomic_incr(seqid) & 0xFF;
171114

172-
std::size_t prifix_len = 10; // 10 = prefix len
173-
unsigned char* write_index = _buff + prifix_len;
115+
uint32_t period = ByteOrder::swapIfLittleEndian(static_cast<uint32_t>(current - mStartTime));
116+
uint16_t seqid = ByteOrder::swapIfLittleEndian(mCounter++);
174117

175-
memcpy(write_index, &tm_period, 4);
176-
write_index += 4;
118+
unsigned char bin_buf[6];
119+
std::memcpy(bin_buf, &period, 4);
120+
std::memcpy(bin_buf + 4, &seqid, 2);
177121

178-
memcpy(write_index, &seqid, 2);
122+
char hex_buf[12];
123+
hexdump(bin_buf, hex_buf, 6);
179124

180-
hexdump(_buff + prifix_len, (_0x_buff + (2 * prifix_len)), 6);
181-
_0x_buff[32] = '\0';
182-
return std::string(_0x_buff);
125+
return std::string(kFixString, 20) + std::string(hex_buf, 12);
183126
}
184127

185-
void StringIdMaker::hexdump(unsigned char* buffer, char* out_buff, unsigned long index) {
186-
for (unsigned long i = 0; i < index; i++) {
187-
sprintf(out_buff + 2 * i, "%02X ", buffer[i]);
128+
void StringIdMaker::hexdump(unsigned char* in, char* out, std::size_t len) {
129+
for (std::size_t i = 0; i < len; i++) {
130+
unsigned char v = in[i];
131+
out[i * 2] = sHexAlphabet[v >> 4];
132+
out[i * 2 + 1] = sHexAlphabet[v & 0x0FU];
188133
}
189134
}
190-
}
135+
136+
} // namespace rocketmq

src/producer/StringIdMaker.h

Lines changed: 33 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -14,61 +14,51 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17-
18-
/*
19-
ip: 4
20-
pid: 4
21-
随机数 :2
22-
时间:4
23-
自增数:2
24-
*/
2517
#ifndef __STRINGID_MAKER_H__
2618
#define __STRINGID_MAKER_H__
2719

28-
#include <stdint.h>
29-
#include <stdio.h>
30-
#include <stdlib.h>
31-
#include <time.h>
32-
#include <boost/serialization/singleton.hpp>
20+
#include <atomic>
21+
#include <cstdint>
3322
#include <string>
34-
#include <boost/asio.hpp>
35-
36-
#ifdef WIN32
37-
#include <windows.h>
38-
#else
39-
#include <unistd.h>
40-
#include <sys/time.h>
41-
#endif
42-
43-
#ifdef WIN32
44-
#include <windows.h>
45-
#else
46-
#include <unistd.h>
47-
#include <sys/time.h>
48-
#endif
4923

5024
namespace rocketmq {
51-
class StringIdMaker : public boost::serialization::singleton<StringIdMaker> {
52-
public:
25+
26+
class StringIdMaker {
27+
private:
5328
StringIdMaker();
5429
~StringIdMaker();
55-
std::string get_unique_id();
30+
31+
public:
32+
static StringIdMaker& getInstance() {
33+
// After c++11, the initialization occurs exactly once
34+
static StringIdMaker singleton_;
35+
return singleton_;
36+
}
37+
38+
/* ID format:
39+
* ip: 4 bytes
40+
* pid: 2 bytes
41+
* random: 4 bytes
42+
* time: 4 bytes
43+
* auto num: 2 bytes
44+
*/
45+
std::string createUniqID();
5646

5747
private:
58-
uint32_t get_ip();
59-
void init_prefix();
60-
uint64_t get_curr_ms();
61-
int atomic_incr(int id);
62-
void set_start_and_next_tm();
48+
void setStartTime(uint64_t millis);
6349

64-
void hexdump(unsigned char* buffer, char* out_buff, unsigned long index);
50+
static uint32_t getIP();
51+
static void hexdump(unsigned char* buffer, char* out_buff, unsigned long index);
6552

6653
private:
67-
uint64_t _start_tm;
68-
uint64_t _next_start_tm;
69-
unsigned char _buff[16];
70-
char _0x_buff[33];
71-
int16_t seqid;
54+
uint64_t mStartTime;
55+
uint64_t mNextStartTime;
56+
std::atomic<uint16_t> mCounter;
57+
58+
char kFixString[21];
59+
60+
static const char sHexAlphabet[16];
7261
};
73-
}
62+
63+
} // namespace rocketmq
7464
#endif

0 commit comments

Comments
 (0)