mirror of
https://github.com/FairRootGroup/FairMQ.git
synced 2025-10-16 10:01:47 +00:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d91a7d2361 | ||
|
c3f6d5c11f | ||
|
de7b5767fb | ||
|
7506243e1a | ||
|
03e6cea586 | ||
|
291d00c73f | ||
|
4dc37efc12 | ||
|
5e24fdba8b | ||
|
0cb8f6166a |
@@ -7,13 +7,12 @@
|
|||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.9.4 FATAL_ERROR)
|
cmake_minimum_required(VERSION 3.9.4 FATAL_ERROR)
|
||||||
|
cmake_policy(VERSION 3.9...3.15)
|
||||||
|
|
||||||
# Project ######################################################################
|
# Project ######################################################################
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
|
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
|
||||||
include(FairMQLib)
|
include(FairMQLib)
|
||||||
|
|
||||||
set_fairmq_cmake_policies()
|
|
||||||
get_git_version()
|
get_git_version()
|
||||||
|
|
||||||
project(FairMQ VERSION ${PROJECT_VERSION} LANGUAGES CXX)
|
project(FairMQ VERSION ${PROJECT_VERSION} LANGUAGES CXX)
|
||||||
@@ -49,8 +48,12 @@ find_package(Threads REQUIRED)
|
|||||||
|
|
||||||
if(BUILD_FAIRMQ)
|
if(BUILD_FAIRMQ)
|
||||||
find_package2(PUBLIC Boost VERSION 1.64 REQUIRED
|
find_package2(PUBLIC Boost VERSION 1.64 REQUIRED
|
||||||
COMPONENTS container program_options thread system filesystem regex date_time signals
|
COMPONENTS container program_options thread system filesystem regex date_time
|
||||||
)
|
)
|
||||||
|
# Normalize Boost version
|
||||||
|
if(CMAKE_VERSION VERSION_LESS 3.15)
|
||||||
|
set(Boost_VERSION "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}")
|
||||||
|
endif()
|
||||||
find_package2(PUBLIC FairLogger VERSION 1.2.0 REQUIRED)
|
find_package2(PUBLIC FairLogger VERSION 1.2.0 REQUIRED)
|
||||||
find_package2(PRIVATE ZeroMQ VERSION 4.1.5 REQUIRED)
|
find_package2(PRIVATE ZeroMQ VERSION 4.1.5 REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
@@ -212,7 +215,11 @@ if(PROJECT_PACKAGE_DEPENDENCIES)
|
|||||||
pad("${version_str}${version_req_str}" 25 " " version_padded COLOR 1)
|
pad("${version_str}${version_req_str}" 25 " " version_padded COLOR 1)
|
||||||
endif()
|
endif()
|
||||||
if(${dep} STREQUAL FairLogger)
|
if(${dep} STREQUAL FairLogger)
|
||||||
set(prefix ${FairLogger_ROOT})
|
if(FairLogger_PREFIX)
|
||||||
|
set(prefix ${FairLogger_PREFIX})
|
||||||
|
else()
|
||||||
|
set(prefix ${FairLogger_ROOT})
|
||||||
|
endif()
|
||||||
elseif(${dep} STREQUAL GTest)
|
elseif(${dep} STREQUAL GTest)
|
||||||
get_filename_component(prefix ${GTEST_INCLUDE_DIRS}/.. ABSOLUTE)
|
get_filename_component(prefix ${GTEST_INCLUDE_DIRS}/.. ABSOLUTE)
|
||||||
elseif(${dep} STREQUAL msgpack)
|
elseif(${dep} STREQUAL msgpack)
|
||||||
|
22
Jenkinsfile
vendored
22
Jenkinsfile
vendored
@@ -8,6 +8,9 @@ def jobMatrix(String prefix, List specs, Closure callback) {
|
|||||||
def nodes = [:]
|
def nodes = [:]
|
||||||
for (spec in specs) {
|
for (spec in specs) {
|
||||||
def label = specToLabel(spec)
|
def label = specToLabel(spec)
|
||||||
|
def fairsoft = spec.fairsoft
|
||||||
|
def os = spec.os
|
||||||
|
def compiler = spec.compiler
|
||||||
nodes["${prefix}/${label}"] = {
|
nodes["${prefix}/${label}"] = {
|
||||||
node(label) {
|
node(label) {
|
||||||
githubNotify(context: "${prefix}/${label}", description: 'Building ...', status: 'PENDING')
|
githubNotify(context: "${prefix}/${label}", description: 'Building ...', status: 'PENDING')
|
||||||
@@ -16,22 +19,27 @@ def jobMatrix(String prefix, List specs, Closure callback) {
|
|||||||
checkout scm
|
checkout scm
|
||||||
|
|
||||||
sh """\
|
sh """\
|
||||||
echo "export SIMPATH=\${SIMPATH_PREFIX}${spec.fairsoft}" >> Dart.cfg
|
echo "export SIMPATH=\${SIMPATH_PREFIX}${fairsoft}" >> Dart.cfg
|
||||||
echo "export FAIRSOFT_VERSION=${spec.fairsoft}" >> Dart.cfg
|
echo "export FAIRSOFT_VERSION=${fairsoft}" >> Dart.cfg
|
||||||
"""
|
"""
|
||||||
if ((spec.os == 'Debian8') && (spec.compiler == 'gcc8.1')) {
|
if (os =~ /Debian/ && compiler =~ /gcc8/) {
|
||||||
sh '''\
|
sh '''\
|
||||||
echo "source /etc/profile.d/modules.sh" >> Dart.cfg
|
echo "source /etc/profile.d/modules.sh" >> Dart.cfg
|
||||||
echo "module use /cvmfs/it.gsi.de/modulefiles" >> Dart.cfg
|
echo "module use /cvmfs/it.gsi.de/modulefiles" >> Dart.cfg
|
||||||
echo "module load compiler/gcc/8" >> Dart.cfg
|
echo "module load compiler/gcc/8" >> Dart.cfg
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
|
if (os =~ /MacOS/) {
|
||||||
|
sh "echo \"export EXTRA_FLAGS='-DCMAKE_CXX_COMPILER=clang++'\" >> Dart.cfg"
|
||||||
|
} else {
|
||||||
|
sh "echo \"export EXTRA_FLAGS='-DCMAKE_CXX_COMPILER=g++'\" >> Dart.cfg"
|
||||||
|
}
|
||||||
|
|
||||||
sh '''\
|
sh '''\
|
||||||
echo "export BUILDDIR=$PWD/build" >> Dart.cfg
|
echo "export BUILDDIR=$PWD/build" >> Dart.cfg
|
||||||
echo "export SOURCEDIR=$PWD" >> Dart.cfg
|
echo "export SOURCEDIR=$PWD" >> Dart.cfg
|
||||||
echo "export PATH=\\\$SIMPATH/bin:\\\$PATH" >> Dart.cfg
|
echo "export PATH=\\\$SIMPATH/bin:\\\$PATH" >> Dart.cfg
|
||||||
echo "export GIT_BRANCH=$JOB_BASE_NAME" >> Dart.cfg
|
echo "export GIT_BRANCH=$JOB_BASE_NAME" >> Dart.cfg
|
||||||
echo "export EXTRA_FLAGS='-DCMAKE_CXX_COMPILER=g++'" >> Dart.cfg
|
|
||||||
echo "echo \\\$PATH" >> Dart.cfg
|
echo "echo \\\$PATH" >> Dart.cfg
|
||||||
'''
|
'''
|
||||||
sh 'cat Dart.cfg'
|
sh 'cat Dart.cfg'
|
||||||
@@ -58,14 +66,14 @@ pipeline{
|
|||||||
steps{
|
steps{
|
||||||
script {
|
script {
|
||||||
def build_jobs = jobMatrix('alfa-ci/build', [
|
def build_jobs = jobMatrix('alfa-ci/build', [
|
||||||
[os: 'Debian8', arch: 'x86_64', compiler: 'gcc8.1', fairsoft: 'fairmq_dev'],
|
[os: 'Debian8', arch: 'x86_64', compiler: 'gcc8.1.0', fairsoft: 'fairmq_dev'],
|
||||||
//[os: 'MacOS10.13', arch: 'x86_64', compiler: 'AppleLLVM10.0.0', fairsoft: 'may18'],
|
[os: 'MacOS10.13', arch: 'x86_64', compiler: 'AppleLLVM10.0.0', fairsoft: 'fairmq_dev'],
|
||||||
]) { spec, label ->
|
]) { spec, label ->
|
||||||
sh './Dart.sh alfa_ci Dart.cfg'
|
sh './Dart.sh alfa_ci Dart.cfg'
|
||||||
}
|
}
|
||||||
|
|
||||||
def profile_jobs = jobMatrix('alfa-ci/codecov', [
|
def profile_jobs = jobMatrix('alfa-ci/codecov', [
|
||||||
[os: 'Debian8', arch: 'x86_64', compiler: 'gcc8.1', fairsoft: 'fairmq_dev'],
|
[os: 'Debian8', arch: 'x86_64', compiler: 'gcc8.1.0', fairsoft: 'fairmq_dev'],
|
||||||
]) { spec, label ->
|
]) { spec, label ->
|
||||||
withCredentials([string(credentialsId: 'fairmq_codecov_token', variable: 'CODECOV_TOKEN')]) {
|
withCredentials([string(credentialsId: 'fairmq_codecov_token', variable: 'CODECOV_TOKEN')]) {
|
||||||
sh './Dart.sh codecov Dart.cfg'
|
sh './Dart.sh codecov Dart.cfg'
|
||||||
|
@@ -8,6 +8,9 @@ def buildMatrix(List specs, Closure callback) {
|
|||||||
def nodes = [:]
|
def nodes = [:]
|
||||||
for (spec in specs) {
|
for (spec in specs) {
|
||||||
def label = specToLabel(spec)
|
def label = specToLabel(spec)
|
||||||
|
def fairsoft = spec.fairsoft
|
||||||
|
def os = spec.os
|
||||||
|
def compiler = spec.compiler
|
||||||
nodes[label] = {
|
nodes[label] = {
|
||||||
node(label) {
|
node(label) {
|
||||||
try {
|
try {
|
||||||
@@ -15,22 +18,26 @@ def buildMatrix(List specs, Closure callback) {
|
|||||||
checkout scm
|
checkout scm
|
||||||
|
|
||||||
sh """\
|
sh """\
|
||||||
echo "export SIMPATH=\${SIMPATH_PREFIX}${spec.fairsoft}" >> Dart.cfg
|
echo "export SIMPATH=\${SIMPATH_PREFIX}${fairsoft}" >> Dart.cfg
|
||||||
echo "export FAIRSOFT_VERSION=${spec.fairsoft}" >> Dart.cfg
|
echo "export FAIRSOFT_VERSION=${fairsoft}" >> Dart.cfg
|
||||||
"""
|
"""
|
||||||
if ((spec.os == 'Debian8') && (spec.compiler == 'gcc8.1')) {
|
if (os =~ /Debian/ && compiler =~ /gcc8/) {
|
||||||
sh '''\
|
sh '''\
|
||||||
echo "source /etc/profile.d/modules.sh" >> Dart.cfg
|
echo "source /etc/profile.d/modules.sh" >> Dart.cfg
|
||||||
echo "module use /cvmfs/it.gsi.de/modulefiles" >> Dart.cfg
|
echo "module use /cvmfs/it.gsi.de/modulefiles" >> Dart.cfg
|
||||||
echo "module load compiler/gcc/8" >> Dart.cfg
|
echo "module load compiler/gcc/8" >> Dart.cfg
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
|
if (os =~ /MacOS/) {
|
||||||
|
sh "echo \"export EXTRA_FLAGS='-DCMAKE_CXX_COMPILER=clang++'\" >> Dart.cfg"
|
||||||
|
} else {
|
||||||
|
sh "echo \"export EXTRA_FLAGS='-DCMAKE_CXX_COMPILER=g++'\" >> Dart.cfg"
|
||||||
|
}
|
||||||
sh '''\
|
sh '''\
|
||||||
echo "export BUILDDIR=$PWD/build" >> Dart.cfg
|
echo "export BUILDDIR=$PWD/build" >> Dart.cfg
|
||||||
echo "export SOURCEDIR=$PWD" >> Dart.cfg
|
echo "export SOURCEDIR=$PWD" >> Dart.cfg
|
||||||
echo "export PATH=\\\$SIMPATH/bin:\\\$PATH" >> Dart.cfg
|
echo "export PATH=\\\$SIMPATH/bin:\\\$PATH" >> Dart.cfg
|
||||||
echo "export GIT_BRANCH=dev" >> Dart.cfg
|
echo "export GIT_BRANCH=dev" >> Dart.cfg
|
||||||
echo "export EXTRA_FLAGS='-DCMAKE_CXX_COMPILER=g++'" >> Dart.cfg
|
|
||||||
echo "echo \\\$PATH" >> Dart.cfg
|
echo "echo \\\$PATH" >> Dart.cfg
|
||||||
'''
|
'''
|
||||||
sh 'cat Dart.cfg'
|
sh 'cat Dart.cfg'
|
||||||
@@ -56,8 +63,8 @@ pipeline{
|
|||||||
steps{
|
steps{
|
||||||
script {
|
script {
|
||||||
parallel(buildMatrix([
|
parallel(buildMatrix([
|
||||||
[os: 'Debian8', arch: 'x86_64', compiler: 'gcc8.1', fairsoft: 'fairmq_dev'],
|
[os: 'Debian8', arch: 'x86_64', compiler: 'gcc8.1.0', fairsoft: 'fairmq_dev'],
|
||||||
//[os: 'MacOS10.13', arch: 'x86_64', compiler: 'AppleLLVM10.0.0', fairsoft: 'may18'],
|
[os: 'MacOS10.13', arch: 'x86_64', compiler: 'AppleLLVM10.0.0', fairsoft: 'fairmq_dev'],
|
||||||
]) { spec, label ->
|
]) { spec, label ->
|
||||||
sh './Dart.sh Nightly Dart.cfg'
|
sh './Dart.sh Nightly Dart.cfg'
|
||||||
sh './Dart.sh Profile Dart.cfg'
|
sh './Dart.sh Profile Dart.cfg'
|
||||||
|
@@ -29,25 +29,6 @@ if(NOT WIN32 AND NOT DISABLE_COLOR)
|
|||||||
set(BWhite "${Esc}[1;37m")
|
set(BWhite "${Esc}[1;37m")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# set_fairmq_cmake_policies()
|
|
||||||
#
|
|
||||||
# Sets CMake policies.
|
|
||||||
macro(set_fairmq_cmake_policies)
|
|
||||||
# Find more details to each policy with cmake --help-policy CMPXXXX
|
|
||||||
foreach(policy
|
|
||||||
CMP0025 # Compiler id for Apple Clang is now AppleClang.
|
|
||||||
CMP0028 # Double colon in target name means ALIAS or IMPORTED target.
|
|
||||||
CMP0042 # MACOSX_RPATH is enabled by default.
|
|
||||||
CMP0048 # The ``project()`` command manages VERSION variables.
|
|
||||||
CMP0054 # Only interpret ``if()`` arguments as variables or keywords when unquoted.
|
|
||||||
)
|
|
||||||
if(POLICY ${policy})
|
|
||||||
cmake_policy(SET ${policy} NEW)
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
|
|
||||||
find_package(Git)
|
find_package(Git)
|
||||||
# get_git_version([DEFAULT_VERSION version] [DEFAULT_DATE date] [OUTVAR_PREFIX prefix])
|
# get_git_version([DEFAULT_VERSION version] [DEFAULT_DATE date] [OUTVAR_PREFIX prefix])
|
||||||
#
|
#
|
||||||
|
@@ -11,6 +11,13 @@ find_path(DDS_INCLUDE_DIR
|
|||||||
HINTS ${DDS_ROOT} $ENV{DDS_ROOT}
|
HINTS ${DDS_ROOT} $ENV{DDS_ROOT}
|
||||||
PATH_SUFFIXES include
|
PATH_SUFFIXES include
|
||||||
)
|
)
|
||||||
|
if(NOT DDS_INCLUDE_DIR)
|
||||||
|
find_path(DDS_INCLUDE_DIR
|
||||||
|
NAMES dds_intercom.h
|
||||||
|
HINTS ${DDS_ROOT} $ENV{DDS_ROOT}
|
||||||
|
PATH_SUFFIXES include/DDS
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
find_path(DDS_LIBRARY_DIR
|
find_path(DDS_LIBRARY_DIR
|
||||||
NAMES libdds_intercom_lib.dylib libdds_intercom_lib.so
|
NAMES libdds_intercom_lib.dylib libdds_intercom_lib.so
|
||||||
|
@@ -206,6 +206,9 @@ set_target_properties(${_target} PROPERTIES LABELS coverage)
|
|||||||
if(FAST_BUILD)
|
if(FAST_BUILD)
|
||||||
set_target_properties(${_target} PROPERTIES OUTPUT_NAME FairMQ)
|
set_target_properties(${_target} PROPERTIES OUTPUT_NAME FairMQ)
|
||||||
endif()
|
endif()
|
||||||
|
if(Boost_VERSION VERSION_LESS 1.66)
|
||||||
|
target_compile_definitions(${_target} PUBLIC FAIR_MQ_HAS_NO_ASIO_IO_CONTEXT)
|
||||||
|
endif()
|
||||||
|
|
||||||
#######################
|
#######################
|
||||||
# include directories #
|
# include directories #
|
||||||
@@ -248,7 +251,6 @@ target_link_libraries(${_target}
|
|||||||
Boost::filesystem
|
Boost::filesystem
|
||||||
Boost::regex
|
Boost::regex
|
||||||
Boost::date_time
|
Boost::date_time
|
||||||
Boost::signals
|
|
||||||
FairLogger::FairLogger
|
FairLogger::FairLogger
|
||||||
|
|
||||||
PRIVATE # only libFairMQ links against private dependencies
|
PRIVATE # only libFairMQ links against private dependencies
|
||||||
|
@@ -43,6 +43,7 @@ class FairMQTransportFactory
|
|||||||
|
|
||||||
/// Get a pointer to the associated polymorphic memory resource
|
/// Get a pointer to the associated polymorphic memory resource
|
||||||
fair::mq::ChannelResource* GetMemoryResource() { return &fMemoryResource; }
|
fair::mq::ChannelResource* GetMemoryResource() { return &fMemoryResource; }
|
||||||
|
operator fair::mq::ChannelResource*() { return &fMemoryResource; }
|
||||||
|
|
||||||
/// @brief Create empty FairMQMessage
|
/// @brief Create empty FairMQMessage
|
||||||
/// @return pointer to FairMQMessage
|
/// @return pointer to FairMQMessage
|
||||||
|
@@ -45,15 +45,21 @@ FairMQMessagePtr getMessage(ContainerT &&container_, FairMQMemoryResource *targe
|
|||||||
const_cast<typename std::remove_const<typename ContainerT::value_type>::type *>(
|
const_cast<typename std::remove_const<typename ContainerT::value_type>::type *>(
|
||||||
container.data())));
|
container.data())));
|
||||||
if (message)
|
if (message)
|
||||||
|
{
|
||||||
message->SetUsedSize(containerSizeBytes);
|
message->SetUsedSize(containerSizeBytes);
|
||||||
return message;
|
return message;
|
||||||
} else {
|
} else {
|
||||||
auto message = targetResource->getTransportFactory()->CreateMessage(containerSizeBytes);
|
//container is not required to allocate (like in std::string small string optimization)
|
||||||
std::memcpy(static_cast<fair::mq::byte *>(message->GetData()),
|
//in case we get no message we fall back to default (copy) behaviour)
|
||||||
container.data(),
|
targetResource = resource;
|
||||||
containerSizeBytes);
|
}
|
||||||
return message;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto message = targetResource->getTransportFactory()->CreateMessage(containerSizeBytes);
|
||||||
|
std::memcpy(static_cast<fair::mq::byte *>(message->GetData()),
|
||||||
|
container.data(),
|
||||||
|
containerSizeBytes);
|
||||||
|
return message;
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace mq */
|
} /* namespace mq */
|
||||||
|
@@ -136,6 +136,7 @@ void ChannelParser(const boost::property_tree::ptree& tree, FairMQChannelMap& ch
|
|||||||
commonChannel.UpdateSndKernelSize(q.second.get<int>("sndKernelSize", commonChannel.GetSndKernelSize()));
|
commonChannel.UpdateSndKernelSize(q.second.get<int>("sndKernelSize", commonChannel.GetSndKernelSize()));
|
||||||
commonChannel.UpdateRcvKernelSize(q.second.get<int>("rcvKernelSize", commonChannel.GetRcvKernelSize()));
|
commonChannel.UpdateRcvKernelSize(q.second.get<int>("rcvKernelSize", commonChannel.GetRcvKernelSize()));
|
||||||
commonChannel.UpdateLinger(q.second.get<int>("linger", commonChannel.GetLinger()));
|
commonChannel.UpdateLinger(q.second.get<int>("linger", commonChannel.GetLinger()));
|
||||||
|
commonChannel.UpdateRateLogging(q.second.get<int>("rateLogging", commonChannel.GetRateLogging()));
|
||||||
commonChannel.UpdatePortRangeMin(q.second.get<int>("portRangeMin", commonChannel.GetPortRangeMin()));
|
commonChannel.UpdatePortRangeMin(q.second.get<int>("portRangeMin", commonChannel.GetPortRangeMin()));
|
||||||
commonChannel.UpdatePortRangeMax(q.second.get<int>("portRangeMax", commonChannel.GetPortRangeMax()));
|
commonChannel.UpdatePortRangeMax(q.second.get<int>("portRangeMax", commonChannel.GetPortRangeMax()));
|
||||||
commonChannel.UpdateAutoBind(q.second.get<bool>("autoBind", commonChannel.GetAutoBind()));
|
commonChannel.UpdateAutoBind(q.second.get<bool>("autoBind", commonChannel.GetAutoBind()));
|
||||||
|
@@ -18,8 +18,12 @@ namespace boost
|
|||||||
namespace asio
|
namespace asio
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#ifdef FAIR_MQ_HAS_NO_ASIO_IO_CONTEXT
|
||||||
|
class io_service;
|
||||||
|
#else
|
||||||
class io_context;
|
class io_context;
|
||||||
typedef class io_context io_service;
|
typedef class io_context io_service;
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace asio
|
} // namespace asio
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
|
@@ -127,10 +127,11 @@ TEST(MemoryResources, getMessage_test)
|
|||||||
v.emplace_back(5);
|
v.emplace_back(5);
|
||||||
v.emplace_back(6);
|
v.emplace_back(6);
|
||||||
void* vectorBeginPtr = &v[0];
|
void* vectorBeginPtr = &v[0];
|
||||||
message = getMessage(std::move(v), allocSHM);
|
message = getMessage(std::move(v), *factorySHM);
|
||||||
EXPECT_TRUE(message != nullptr);
|
EXPECT_TRUE(message != nullptr);
|
||||||
EXPECT_TRUE(message->GetData() != vectorBeginPtr);
|
EXPECT_TRUE(message->GetData() != vectorBeginPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_TRUE(message->GetSize() == 3 * sizeof(testData));
|
EXPECT_TRUE(message->GetSize() == 3 * sizeof(testData));
|
||||||
messageArray = static_cast<int*>(message->GetData());
|
messageArray = static_cast<int*>(message->GetData());
|
||||||
EXPECT_TRUE(messageArray[0] == 4 && messageArray[1] == 5 && messageArray[2] == 6);
|
EXPECT_TRUE(messageArray[0] == 4 && messageArray[1] == 5 && messageArray[2] == 6);
|
||||||
|
Reference in New Issue
Block a user