Skip to content

Commit

Permalink
Merge pull request #73 from nacos-group/develop
Browse files Browse the repository at this point in the history
Bugfix #70 , to comply with Nacos 2.x, the client won't check instanceId got from the server and will automatically create an instanceId when registering a new service
Testcase order adjust to avoid test failures
  • Loading branch information
TTTTTAAAAAKKKKEEEENNNN authored Jun 18, 2021
2 parents cdbf474 + 6fb9f49 commit c3f4668
Show file tree
Hide file tree
Showing 20 changed files with 221 additions and 22 deletions.
1 change: 1 addition & 0 deletions include/NacosExceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class NacosException : public std::exception {
static const int UNABLE_TO_GET_HOST_IP = 1008;
static const int UNABLE_TO_CREATE_SOCKET = 1009;
static const int INVALID_CONFIG_PARAM = 1010;
static const int UNABLE_TO_GET_HOST_NAME = 1011;

};

Expand Down
4 changes: 4 additions & 0 deletions include/constant/PropertyKeyConst.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ class PropertyKeyConst {

static const int NACOS_DEFAULT_PORT = 8848;

static const NacosString INSTANCE_ID_SEQ_FILE;

static const NacosString INSTANCE_ID_PREFIX;

/*public static class SystemEnv {
static const NacosString ALIBABA_ALIWARE_ENDPOINT_PORT = "ALIBABA_ALIWARE_ENDPOINT_PORT";
Expand Down
2 changes: 1 addition & 1 deletion include/listen/Listener.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace nacos{
class Listener {
private:
NacosString listenerName;
AtomicInt refCount;
AtomicInt<int> refCount;
public:
Listener() {
this->listenerName = "theListener";
Expand Down
2 changes: 1 addition & 1 deletion include/naming/subscribe/EventListener.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace nacos{
class EventListener {
private:
NacosString listenerName;
AtomicInt refCount;
AtomicInt<int> refCount;
public:
EventListener() {
this->listenerName = "theListener";
Expand Down
20 changes: 14 additions & 6 deletions include/thread/AtomicInt.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,30 @@
#define __ATOMIC_INT_H_

namespace nacos{
template<typename T>
class AtomicInt {
private:
volatile int _intval;
volatile T _curval;
public:
AtomicInt(int initval = 0) : _intval(initval) {};
AtomicInt(T curval = 0) : _curval(curval) {};

int inc(int incval = 1) {
int oldValue = __sync_fetch_and_add(&_intval, incval);
void set(T val) { _curval = val; };

T inc(T incval = 1) {
T oldValue = getAndInc(incval);
return incval + oldValue;
};

int dec(int decval = 1) {
T getAndInc(T incval = 1) {
T oldValue = __sync_fetch_and_add(&_curval, incval);
return oldValue;
}

T dec(int decval = 1) {
return inc(-decval);
};

int get() const { return _intval; };
T get() const { return _curval; };
};
}//namespace nacos

Expand Down
2 changes: 2 additions & 0 deletions src/config/AppConfigManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ void AppConfigManager::initDefaults() {

NacosString homedir = DirUtils::getHome();

set(PropertyKeyConst::INSTANCE_ID_PREFIX, NetUtils::getHostName());
set(PropertyKeyConst::INSTANCE_ID_SEQ_FILE, homedir + ConfigConstant::FILE_SEPARATOR + "nacos" + ConfigConstant::FILE_SEPARATOR + "instance_seq.dat");
set(PropertyKeyConst::NACOS_SNAPSHOT_PATH, homedir + ConfigConstant::FILE_SEPARATOR + "nacos" + ConfigConstant::FILE_SEPARATOR + "snapshot");
log_info("[AppConfigManager]-initDefaults:DEFAULT_SNAPSHOT_PATH:%s\n", appConfig[PropertyKeyConst::NACOS_SNAPSHOT_PATH].c_str());
}
Expand Down
2 changes: 2 additions & 0 deletions src/constant/PropertyKeyConst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,6 @@ const NacosString PropertyKeyConst::CLIENT_NAME = "nacos.client.name";
const NacosString PropertyKeyConst::AUTH_USERNAME = "nacos.auth.username";
const NacosString PropertyKeyConst::AUTH_PASSWORD = "nacos.auth.password";
const NacosString PropertyKeyConst::LOCAL_IP = "nacos.client.ip";
const NacosString PropertyKeyConst::INSTANCE_ID_SEQ_FILE = "nacos.instId.seq.file";
const NacosString PropertyKeyConst::INSTANCE_ID_PREFIX = "nacos.instId.prefix";
}//namespace nacos
5 changes: 5 additions & 0 deletions src/factory/NacosServiceFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "src/naming/subscribe/HostReactor.h"
#include "src/security/SecurityManager.h"
#include "src/utils/ConfigParserUtils.h"
#include "src/utils/SequenceProvider.h"
#include "utils/DirUtils.h"

//Unlike Java, in cpp, there's no container, no spring to do the ORM job, so I have to handle it myself
Expand Down Expand Up @@ -114,6 +115,10 @@ NamingService *NacosServiceFactory::CreateNamingService() NACOS_THROW(NacosExcep
HostReactor *hostReactor = new HostReactor(objectConfigData);
objectConfigData->_hostReactor = hostReactor;

const NacosString &seqConfile = appConfigManager->get(PropertyKeyConst::INSTANCE_ID_SEQ_FILE);
SequenceProvider<int64_t> *sequenceProvider = new SequenceProvider<int64_t>(seqConfile, 1, 10);
objectConfigData->_sequenceProvider = sequenceProvider;

objectConfigData->checkAssembledObject();
NamingService *instance = new NacosNamingService(objectConfigData);

Expand Down
8 changes: 8 additions & 0 deletions src/factory/ObjectConfigData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "src/listen/ClientWorker.h"
#include "src/security/SecurityManager.h"
#include "utils/UuidUtils.h"
#include "src/utils/SequenceProvider.h"

namespace nacos{

Expand Down Expand Up @@ -44,6 +45,7 @@ void ObjectConfigData::checkNamingService() NACOS_THROW(NacosException) {
NACOS_ASSERT(_serverListManager != NULL);
NACOS_ASSERT(_udpNamingServiceListener != NULL);
NACOS_ASSERT(_udpNamingServiceListener != NULL);
NACOS_ASSERT(_sequenceProvider != NULL);
}

void ObjectConfigData::checkConfigService() NACOS_THROW(NacosException) {
Expand Down Expand Up @@ -206,6 +208,12 @@ void ObjectConfigData::destroyNamingService() {
delete _appConfigManager;
_appConfigManager = NULL;
}

if (_sequenceProvider != NULL)
{
delete _sequenceProvider;
_sequenceProvider = NULL;
}
}

void ObjectConfigData::destroyMaintainService() {
Expand Down
2 changes: 2 additions & 0 deletions src/factory/ObjectConfigData.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class LocalSnapshotManager;
class SecurityManager;
class UdpNamingServiceListener;
class HostReactor;
template <typename T>class SequenceProvider;

enum FactoryType {
CONFIG = 0,
Expand Down Expand Up @@ -58,6 +59,7 @@ class ObjectConfigData {
SecurityManager *_securityManager;
UdpNamingServiceListener *_udpNamingServiceListener;
HostReactor *_hostReactor;
SequenceProvider<int64_t> *_sequenceProvider;
};
}//namespace nacos

Expand Down
7 changes: 4 additions & 3 deletions src/json/JSON.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,10 @@ long JSON::getLong(const NacosString &jsonString, const NacosString &fieldname)
Instance JSON::Json2Instance(const Value &host) NACOS_THROW(NacosException) {
Instance theinstance;

markRequired(host, "instanceId");
const Value &instanceId = host["instanceId"];
theinstance.instanceId = instanceId.GetString();
if (host.HasMember("instanceId")) {
const Value &instanceId = host["instanceId"];
theinstance.instanceId = instanceId.GetString();
}

markRequired(host, "port");
const Value &port = host["port"];
Expand Down
4 changes: 3 additions & 1 deletion src/naming/NacosNamingService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "src/naming/subscribe/SubscriptionPoller.h"
#include "src/naming/subscribe/UdpNamingServiceListener.h"
#include "src/naming/beat/BeatReactor.h"
#include "src/utils/SequenceProvider.h"
#include "utils/NamingUtils.h"
#include "constant/UtilAndComs.h"
#include "utils/ParamUtils.h"
Expand Down Expand Up @@ -88,7 +89,8 @@ void NacosNamingService::registerInstance
const NacosString &groupName,
Instance &instance
) NACOS_THROW(NacosException) {

const NacosString &instanceIdPrefix = _objectConfigData->_appConfigManager->get(PropertyKeyConst::INSTANCE_ID_PREFIX);
instance.instanceId = instanceIdPrefix + NacosStringOps::valueOf(_objectConfigData->_sequenceProvider->next());
if (instance.ephemeral) {
BeatInfo beatInfo;
beatInfo.serviceName = NamingUtils::getGroupedName(serviceName, groupName);
Expand Down
17 changes: 17 additions & 0 deletions src/utils/NetUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>
#include <ifaddrs.h>
#include <src/log/Logger.h>
#include <string.h>
#include <unistd.h>

#define HOST_AND_LEN 250

namespace nacos{

Expand Down Expand Up @@ -44,4 +48,17 @@ NacosString NetUtils::getHostIp() NACOS_THROW(NacosException){
//Usually the program will not run to here
throw NacosException(NacosException::UNABLE_TO_GET_HOST_IP, "Failed to get IF address");
}

NacosString NetUtils::getHostName() NACOS_THROW(NacosException)
{
char hostname[HOST_AND_LEN];

int res = gethostname(hostname, HOST_AND_LEN);
if (res == 0) {
return NacosString(hostname);
}

throw NacosException(NacosException::UNABLE_TO_GET_HOST_NAME, "Failed to get hostname, errno = " + NacosStringOps::valueOf(errno));
}

}//namespace nacos
3 changes: 3 additions & 0 deletions src/utils/NetUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ class NetUtils {
public:
//Get IP address (best guess)
static NacosString getHostIp() NACOS_THROW(NacosException);

//Get hostname
static NacosString getHostName() NACOS_THROW(NacosException);
};
}//namespace nacos

Expand Down
82 changes: 82 additions & 0 deletions src/utils/SequenceProvider.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include "NacosString.h"
#include "NacosExceptions.h"
#include "thread/AtomicInt.h"
#include "src/thread/Mutex.h"
#include "src/config/IOUtils.h"

namespace nacos
{

template<typename T>
class SequenceProvider {
private:
NacosString _fileName;
AtomicInt<T> _current;
Mutex _acquireMutex;
T _nr_to_preserve;
T _initSequence;
volatile T _hwm;//high water mark

void ensureWrite(int fd, T data) {
size_t bytes_written = 0;
while (bytes_written < sizeof(T)) {
bytes_written += write(fd, (char*)&data + bytes_written, sizeof(T) - bytes_written);
}
}

T preserve() {
T current;
int fd;
bool newFile = false;
if (IOUtils::checkNotExistOrNotFile(_fileName)) {
newFile = true;
}
mode_t mode = S_IRUSR | S_IWUSR | S_IRWXG | S_IWGRP;
fd = open(_fileName.c_str(), O_RDWR | O_CREAT, mode);
if (fd <= 0) {
throw new NacosException(NacosException::UNABLE_TO_OPEN_FILE, _fileName);
}

if (newFile) {
ensureWrite(fd, _initSequence);
lseek(fd, 0, SEEK_SET);//read from the beginning
}

size_t bytes_read = 0;
while (bytes_read < sizeof(T))
{
bytes_read += read(fd, (char*)&current + bytes_read, sizeof(T) - bytes_read);
}
lseek(fd, 0, SEEK_SET);//write from the beginning

ensureWrite(fd, current + _nr_to_preserve);
close(fd);
_hwm = current + _nr_to_preserve;
return current;
};
public:
SequenceProvider(const NacosString &fileName, T initSequence, T nr_to_preserve) {
_fileName = fileName;
_initSequence = initSequence;
_nr_to_preserve = nr_to_preserve;
_current.set(preserve());
};

T next(int step = 1) {
T res = _current.getAndInc(step);
while (res >= _hwm) {
_acquireMutex.lock();
if (res >= _hwm) {
preserve();
}
_acquireMutex.unlock();
}
return res;
};
};

} // namespace nacos
8 changes: 5 additions & 3 deletions test/allinone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,14 +130,15 @@ bool testNamingServiceAndDeRegisterActively();

bool testThreadPoolConcurrentWithAtomicCounter();

bool testSequenceProvider();

TestData disabledTestList[] =
TEST_ITEM_START
TEST_ITEM_END

TestData
testList[] =
TEST_ITEM_START

TEST_ITEM("Normal http test", testNormalHttpRequest)
TEST_ITEM("No server request, should fail", testNoServerRequest)
TEST_ITEM("Publish config to server", testPublishConfig)
Expand All @@ -152,6 +153,7 @@ TEST_ITEM_START
TEST_ITEM("Test for string characteristics", testStringEqual)
TEST_ITEM("Read&Write file test", testReadWriteFile)
TEST_ITEM("GetFileSize, should work well", testGetFileSize)
TEST_ITEM("Test get instances with predicate(testRandomByWeightSelector)", testRandomByWeightSelector)
TEST_ITEM("Check whether file exists or not", testFileExists)
TEST_ITEM("Create&Remove file", testCreateAndRemove)
TEST_ITEM("Create a directory with subdirectories, and clean it", testCleanDirectory)
Expand All @@ -170,6 +172,7 @@ TEST_ITEM_START
TEST_ITEM("Smoke test for ThreadPool", testThreadPoolSmoke)
TEST_ITEM("Test basic function of NacosNamingService's registerService", testNamingServiceRegister)
TEST_ITEM("Test serialization/deserialization of Business Object", testString2ServiceInfo)
TEST_ITEM("Test get instances with predicate(Randomly)", testInstanceSelectors)
TEST_ITEM("Test serialization/deserialization of malformed Business Object", testMalformedJson2ServiceInfo)
TEST_ITEM("Test serialization/deserialization of malformed Business Object (Double)", testMalformedDouble2ServiceInfo)
TEST_ITEM("Test serialization/deserialization of malformed Business Object (no cacheMillis)", testLackcacheMillisServiceInfo)
Expand All @@ -184,8 +187,6 @@ TEST_ITEM_START
TEST_ITEM("Register many services and get one", testGetAllInstances)
TEST_ITEM("Subscribe & unsubscribe services", testListenService)
TEST_ITEM("Test get all service names", testGetServiceNames)
TEST_ITEM("Test get instances with predicate(Randomly)", testInstanceSelectors)
TEST_ITEM("Test get instances with predicate(testRandomByWeightSelector)", testRandomByWeightSelector)
TEST_ITEM("Smoking test of ThreadLocal", testThreadLocal)
TEST_ITEM("Smoking test of ThreadLocal(pointer)", testThreadLocalPtr)
TEST_ITEM("Smoking test of ThreadLocal(pointer with initializer)", testThreadLocalPtrWithInitializer)
Expand All @@ -200,6 +201,7 @@ TEST_ITEM_START
TEST_ITEM("Test delayed task pool - multiple tasks triggered at the same time", testDelayedThread2)
TEST_ITEM("Register a service instance and remove it actively", testNamingServiceAndDeRegisterActively)
TEST_ITEM("thread pool with concurrent add & atomic operation", testThreadPoolConcurrentWithAtomicCounter)
TEST_ITEM("Test sequence provider", testSequenceProvider)
TEST_ITEM_END

int main() {
Expand Down
2 changes: 1 addition & 1 deletion test/testcase/testDelayedThreadPool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class DelayedTask : public Task {
if (executor == NULL) {
throw NacosException(NacosException::INVALID_CONFIG_PARAM, "no executor");
}
printf(">>>>>>>>>>>>>>>>>>Task %s triggered, time =%lu (%lu), interval = %lu\n", getTaskName().c_str(), now_ms/1000, now_ms, interval_calc);
printf(">>>>>>>>>>>>>>>>>>Task %s triggered, time =%llu (%llu), interval = %llu\n", getTaskName().c_str(), now_ms/1000, now_ms, interval_calc);

sleep(1);
}
Expand Down
6 changes: 4 additions & 2 deletions test/testcase/testNamingService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,10 @@ bool testNamingProxySmokeTest() {
for (int i = 0; i < 10; i++) {
NacosString serviceName = "TestServiceName" + NacosStringOps::valueOf(i);
NacosString serverlist = namingProxy->queryList(serviceName, ConfigConstant::DEFAULT_GROUP, "TestCluster", 0, false);

if (serverlist.find("\"serviceName\":\"" + serviceName + "\"") == string::npos) {
cout << serverlist << endl;
if (serverlist.find("\"serviceName\":\"" + serviceName + "\"") == string::npos &&
//nacos 2.x compatibility
serverlist.find("\"serviceName\":\"DEFAULT_GROUP@@" + serviceName + "\"") == string::npos) {
cout << "Failed to get data for:" << serviceName << endl;
return false;
}
Expand Down
Loading

0 comments on commit c3f4668

Please sign in to comment.