Google Test under Fedora 17 64b : No VERSION specified for WRITE_BASIC_CONFIG_VERSION_FILE()

J’ai donc voulu faire l’installation de gtest : https://github.com/google/googletest sur un serveur en Fédora 17 mais sans succès.

# wget https://github.com/google/googletest/archive/master.zip 

# unzip master.zip

# cd googletest-master/

# mkdir mybuild

# cat ../CMakeLists.txt
cmake_minimum_required(VERSION 2.8.8)
 
if (CMAKE_VERSION VERSION_LESS "3.1")
  add_definitions(-std=c++11)
else()
  set(CMAKE_CXX_STANDARD 11)
  set(CMAKE_CXX_STANDARD_REQUIRED ON)
  set(CMAKE_CXX_EXTENSIONS OFF)
endif()
 
if (POLICY CMP0048)
  cmake_policy(SET CMP0048 NEW)
endif (POLICY CMP0048)
 
project(googletest-distribution)
set(GOOGLETEST_VERSION 1.9.0)
 
enable_testing()
 
include(CMakeDependentOption)
include(GNUInstallDirs)
 
#Note that googlemock target already builds googletest
option(BUILD_GMOCK "Builds the googlemock subproject" ON)
option(INSTALL_GTEST "Enable installation of googletest. (Projects embedding googletest may want to turn this OFF.)" ON)
 
if(BUILD_GMOCK)
  add_subdirectory( googlemock )
else()
  add_subdirectory( googletest )
endif()
 
# uname -a
Linux fedora17-64b 3.3.4-5.fc17.x86_64 #1 SMP Mon May 7 17:29:34 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
 
# rpm -qa | grep "cmake"
cmake-2.8.9-1.fc17.x86_64
 
# cmake -G"Unix Makefiles" ..
-- The C compiler identification is GNU 4.7.2
-- The CXX compiler identification is GNU 4.7.2
-- Check for working C compiler: /bin/gcc
-- Check for working C compiler: /bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /bin/c++
-- Check for working CXX compiler: /bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Found PythonInterp: /bin/python (found version "2.7.3")
-- Looking for include file pthread.h
-- Looking for include file pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found.
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
CMake Error at /usr/share/cmake/Modules/WriteBasicConfigVersionFile.cmake:39 (message):
  No VERSION specified for WRITE_BASIC_CONFIG_VERSION_FILE()
Call Stack (most recent call first):
  /usr/share/cmake/Modules/CMakePackageConfigHelpers.cmake:152 (write_basic_config_version_file)
  googletest/CMakeLists.txt:96 (write_basic_package_version_file)
 
 
-- Configuring incomplete, errors occurred!

# cat ../CMakeLists.txt 
cmake_minimum_required(VERSION 2.8.8)
 
if (CMAKE_VERSION VERSION_LESS "3.1")
  add_definitions(-std=c++11)
else()
  set(CMAKE_CXX_STANDARD 11)
  set(CMAKE_CXX_STANDARD_REQUIRED ON)
  set(CMAKE_CXX_EXTENSIONS OFF)
endif()
 
if (POLICY CMP0048)
  cmake_policy(SET CMP0048 NEW)
endif (POLICY CMP0048)
 
project(googletest-distribution)
#set(CMAKE_PROJECT_VERSION_SET_BY_PROJECT_COMMAND FALSE)
set(GOOGLETEST_VERSION 1.9.0)
 
if("${CVF_VERSION}" STREQUAL "")
    if ("${GOOGLETEST_VERSION}" STREQUAL "")
      message(FATAL_ERROR "No VERSION specified for WRITE_BASIC_CONFIG_VERSION_FILE()")
    else()
      set(CVF_VERSION "${GOOGLETEST_VERSION}")
    endif()
endif()
 
if("${CVF_VERSION}" STREQUAL "")
    message(FATAL_ERROR "No VERSION specified for WRITE_BASIC_CONFIG_VERSION_FILE()")
else()

 
endif()
 
enable_testing()
 
include(CMakeDependentOption)
include(GNUInstallDirs)
 
#Note that googlemock target already builds googletest
option(BUILD_GMOCK "Builds the googlemock subproject" ON)
option(INSTALL_GTEST "Enable installation of googletest. (Projects embedding googletest may want to turn this OFF.)" ON)
 
if(BUILD_GMOCK)
  add_subdirectory( googlemock )
else()
  add_subdirectory( googletest )
endif()

Dans le fichier la version minimum semble être 2.8.8 et j’ai la version 2.8.9-1. J’ai essayé de forcer la variable mais sans succès. 

J’ai donc essayé de faire une « build » avec seulement GMOCK mais sans succès.

# cmake -DBUILD_GTEST=OFF -DBUILD_GMOCK=ON -DINSTALL_GTEST=OFF -DINSTALL_GMOCK=ON
-- Configuring done
-- Generating done
CMake Warning:
  Manually-specified variables were not used by the project:
 
    BUILD_GTEST
    INSTALL_GMOCK
 
 
-- Build files have been written to: /root/googletest-master

# make
Scanning dependencies of target gtest
[  5%] Building CXX object googlemock/gtest/CMakeFiles/gtest.dir/src/gtest-all.cc.o
In file included from /root/googletest-master/googletest/include/gtest/internal/gtest-internal.h:40:0,
                 from /root/googletest-master/googletest/include/gtest/gtest.h:60,
                 from /root/googletest-master/googletest/src/gtest-all.cc:38:
/root/googletest-master/googletest/include/gtest/internal/gtest-port.h:2307:1: error: expected unqualified-id before ‘[’ token
In file included from /root/googletest-master/googletest/include/gtest/gtest.h:60:0,
                 from /root/googletest-master/googletest/src/gtest-all.cc:38:
/root/googletest-master/googletest/include/gtest/internal/gtest-internal.h: In member function ‘bool testing::internal::TypedTestCasePState::AddTestName(const char*, int, const char*, const char*)’:
/root/googletest-master/googletest/include/gtest/internal/gtest-internal.h:554:7: error: ‘Abort’ is not a member of ‘testing::internal::posix’
/root/googletest-master/googletest/include/gtest/internal/gtest-internal.h: In static member function ‘static bool testing::internal::TypeParameterizedTestCase<Fixture, Tests, Types>::Register(const char*, testing::internal::CodeLocation, const testing::internal::TypedTestCasePState*, const char*, const char*, const std::vector<std::basic_string<char> >&)’:
/root/googletest-master/googletest/include/gtest/internal/gtest-internal.h:718:7: error: ‘Abort’ is not a member of ‘testing::internal::posix’
In file included from /root/googletest-master/googletest/include/gtest/gtest-param-test.h:188:0,
                 from /root/googletest-master/googletest/include/gtest/gtest.h:65,
                 from /root/googletest-master/googletest/src/gtest-all.cc:38:
/root/googletest-master/googletest/include/gtest/internal/gtest-param-util.h: In member function ‘testing::internal::ParameterizedTestCaseInfo<TestCase>* testing::internal::ParameterizedTestCaseRegistry::GetTestCasePatternHolder(const char*, testing::internal::CodeLocation)’:
/root/googletest-master/googletest/include/gtest/internal/gtest-param-util.h:686:11: error: ‘Abort’ is not a member of ‘testing::internal::posix’
In file included from /root/googletest-master/googletest/src/gtest-all.cc:41:0:
/root/googletest-master/googletest/src/gtest.cc: In member function ‘const testing::TestPartResult& testing::TestResult::GetTestPartResult(int) const’:
/root/googletest-master/googletest/src/gtest.cc:2070:5: error: ‘Abort’ is not a member of ‘testing::internal::posix’
/root/googletest-master/googletest/src/gtest.cc: In member function ‘const testing::TestProperty& testing::TestResult::GetTestProperty(int) const’:
/root/googletest-master/googletest/src/gtest.cc:2079:5: error: ‘Abort’ is not a member of ‘testing::internal::posix’
In file included from /root/googletest-master/googletest/src/gtest-all.cc:42:0:
/root/googletest-master/googletest/src/gtest-death-test.cc: In function ‘void testing::internal::DeathTestAbort(const string&)’:
/root/googletest-master/googletest/src/gtest-death-test.cc:301:5: error: ‘Abort’ is not a member of ‘testing::internal::posix’
In file included from /root/googletest-master/googletest/src/gtest-all.cc:45:0:
/root/googletest-master/googletest/src/gtest-port.cc: In destructor ‘testing::internal::GTestLog::~GTestLog()’:
/root/googletest-master/googletest/src/gtest-port.cc:983:5: error: ‘Abort’ is not a member of ‘testing::internal::posix’
In file included from /root/googletest-master/googletest/src/gtest-all.cc:47:0:
/root/googletest-master/googletest/src/gtest-test-part.cc: In member function ‘const testing::TestPartResult& testing::TestPartResultArray::GetTestPartResult(int) const’:
/root/googletest-master/googletest/src/gtest-test-part.cc:70:5: error: ‘Abort’ is not a member of ‘testing::internal::posix’
In file included from /root/googletest-master/googletest/src/gtest-all.cc:48:0:
/root/googletest-master/googletest/src/gtest-typed-test.cc: In member function ‘const char* testing::internal::TypedTestCasePState::VerifyRegisteredTestNames(const char*, int, const char*)’:
/root/googletest-master/googletest/src/gtest-typed-test.cc:109:5: error: ‘Abort’ is not a member of ‘testing::internal::posix’
make[2]: *** [googlemock/gtest/CMakeFiles/gtest.dir/src/gtest-all.cc.o] Error 1
make[1]: *** [googlemock/gtest/CMakeFiles/gtest.dir/all] Error 2
make: *** [all] Error 2

Sniff.

Développement en C sous Linux : pthread et la fonction sleep().

Un petit exemple vaut mieux que de grands discours, voici le source en C :

#include 
#include 
#include 
#include <sys/time.h>
#include <sys/types.h>
#include 
static long debut = 0;
void* longue_pause(void* a){
        pid_t t = getpid();
        printf("pid = %d\n",(int)t);
        printf("thread longue_pause %d debut : %ld\n",(int)pthread_self(),time(0)-debut);
        sleep(10);
        printf("thread longue_pause %d fin : %ld\n",(int)pthread_self(),time(0)-debut);
}
void* petites_pauses(void* a){
	int i = 0;
        pid_t t = getpid();
        printf("pid = %d\n",t);
        printf("thread petites_pauses %d debut : %ld \n",(int)pthread_self(), time(0)-debut);
        for(; i < 10 ;++i){
                printf("thread petites_pauses %d en cours : %ld \n",(int)pthread_self(), time(0)-debut);
                sleep(1);
        }
}
int main(){
        pthread_t longue;
        pthread_t petit1;
        pthread_t petit2;
        debut = time(0);
        pthread_create(&longue,NULL,longue_pause,NULL);
        pthread_create(&petit1,NULL,petites_pauses,NULL);
        pthread_create(&petit2,NULL,petites_pauses,NULL);
	sleep(8);
	printf("Debut join: %ld\n",time(0)-debut);
        pthread_join(longue,NULL);
        printf("fin long : %ld\n",time(0)-debut); 
        pthread_join(petit1,NULL);
	printf("fin petit1 : %ld\n",time(0)-debut);	
        pthread_join(petit2,NULL);
	printf("fin petit2 : %ld\n",time(0)-debut);
}

Pour la compilation :

$ gcc test_pthread_test.c -lpthread -o test2

On lance le test :

$ ./test2 
pid = 324
thread longue_pause 1078445824 debut : 0
pid = 324
thread petites_pauses 1070053120 debut : 0 
thread petites_pauses 1070053120 en cours : 0 
pid = 324
thread petites_pauses 1061660416 debut : 0 
thread petites_pauses 1061660416 en cours : 0 
thread petites_pauses 1070053120 en cours : 1 
thread petites_pauses 1061660416 en cours : 1 
thread petites_pauses 1070053120 en cours : 2 
thread petites_pauses 1061660416 en cours : 2 
thread petites_pauses 1070053120 en cours : 3 
thread petites_pauses 1061660416 en cours : 3 
thread petites_pauses 1070053120 en cours : 4 
thread petites_pauses 1061660416 en cours : 4 
thread petites_pauses 1061660416 en cours : 5 
thread petites_pauses 1070053120 en cours : 5 
thread petites_pauses 1061660416 en cours : 6 
thread petites_pauses 1070053120 en cours : 6 
thread petites_pauses 1070053120 en cours : 7 
thread petites_pauses 1061660416 en cours : 7 
Debut join: 8
thread petites_pauses 1070053120 en cours : 8 
thread petites_pauses 1061660416 en cours : 8 
thread petites_pauses 1070053120 en cours : 9 
thread petites_pauses 1061660416 en cours : 9 
thread longue_pause 1078445824 fin : 10
fin long : 10
fin petit1 : 10
fin petit2 : 10

Le petit exemple nous montre bien qu’aucun sleep() ne fait une attente sur les autres pthreads, même celui dans le main().

J’ai pu voir sur des forums :

Effectivement sur le POSIX il est marqué : http://pubs.opengroup.org/onlinepubs/9699919799/functions/sleep.html :

The sleep() function shall cause the calling thread to be suspended from execution until either the number of realtime seconds specified by the argument seconds has elapsed or a signal is delivered to the calling thread and its action is to invoke a signal-catching function or to terminate the process.

Mais si beaucoup de personne se pose la question c’est que cela n’a pas toujours été le cas. Sauf problème de mémoire j’ai vu le changement entre la Redhat 8.0 et la Fédora 9.0.

Mes OS de développement ont été (dans l’ordre) :

  • Redhat 5.2 ( la seule version que j’ai acheté, misère – pour information la date de release est : 2 novembre 1998 ) : A l’université de Toulouse.
  • SuSE ? : Chez Centre Océanographique de Marseille.
  • Debian ? : Chez Cyber-workers / Alias .
  • Redhat ? : Chez Rightvision
  • Redhat 7.2 : Chez Honeywell / SeCOM
  • Redhat 8.0 : Chez Honeywell / SeCOM
  • Fédora 9.0 : Chez Honeywell / SeCOM
  • Fédora 14.0 : Chez Honeywell / SeCOM
  • Fédora 17.0 : Chez Honeywell / SeCOM
  • Oracle 7.0 : Chez Honeywell / SeCOM
  • Oracle 7.2 : Chez Honeywell / SeCOM
  • Oracle 7.3 : Chez Honeywell / SeCOM
  • Oracle 7.4 : Chez Honeywell / SeCOM
  • Oracle 7.5 & Fédora 26 sous Docker : Chez Honeywell / SeCOM
  • Ubuntu 16.04 :  Chez Honeywell / SeCOM

Chez moi c’est plutôt Raspbian STRETCH ( Débian )  : https://www.raspberrypi.org/downloads/raspbian/ .

Bref, cela fait seulement 20 ans que je suis sous Linux.

Ma version de Linux Ubuntu :

$ uname -a
Linux VirtualBox 4.15.0-36-generic #39~16.04.1-Ubuntu SMP Tue Sep 25 08:59:23 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

Au passage on peut aussi voir l’impact des directives de compilation sur la taille :

$ gcc test_pthread_test.c -lpthread -o test2
$ gcc test_pthread_test.c -lpthread -O2 -o test2-O2
$ gcc test_pthread_test.c -lpthread -O3 -o test2-O3
$ gcc test_pthread_test.c -lpthread -O -o test2-O
$ gcc test_pthread_test.c -lpthread -g -o test2-g
$ gcc test_pthread_test.c -lpthread -g -O3 -o test2-g-03
$ ls -l test2*
13208  test2
15024  test2-g
14880  test2-g-03
9120   test2-O
9120   test2-O2
9120   test2-O3

Voila.

(Bisous à Luc)

MYSQL : Portage de vieux code en C … misère.

Quelle misère ce portage sur une Fédora 14 :

# make
…
/usr/bin/ld: cannot find -lmysqlclient
 
# ldconfig -v | grep "mysql"
/usr/lib/mysql:
        libmysqlclient.so.16 -> libmysqlclient.so.16.0.0
        libmysqlclient_r.so.16 -> libmysqlclient_r.so.16.0.0
 
# rpm -qa | grep mysql
mysql-devel-5.1.58-1.fc14.i686
mysql-5.1.58-1.fc14.i686
mysql-libs-5.1.58-1.fc14.i686
 
# ld -lmysqlclient --verbose
GNU ld version 2.20.51.0.7-5.fc14 20100318
  Supported emulations:
   elf_i386
   i386linux
   elf_x86_64
   elf_l1om
using internal linker script:
==================================================
/* Script for -z combreloc: combine and sort reloc sections */
OUTPUT_FORMAT("elf32-i386", "elf32-i386",
              "elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(_start)
SEARCH_DIR("/usr/i686-redhat-linux/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");
SECTIONS
{
  /* Read-only sections, merged into text segment: */
  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x08048000)); . = SEGMENT_START("text-segment", 0x08048000) + SIZEOF_HEADERS;
  .interp         : { *(.interp) }
  .note.gnu.build-id : { *(.note.gnu.build-id) }
  .hash           : { *(.hash) }
  .gnu.hash       : { *(.gnu.hash) }
  .dynsym         : { *(.dynsym) }
  .dynstr         : { *(.dynstr) }
  .gnu.version    : { *(.gnu.version) }
  .gnu.version_d  : { *(.gnu.version_d) }
  .gnu.version_r  : { *(.gnu.version_r) }
  .rel.dyn        :
    {
      *(.rel.init)
      *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)
      *(.rel.fini)
      *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)
      *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*)
      *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
      *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)
      *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)
      *(.rel.ctors)
      *(.rel.dtors)
      *(.rel.got)
      *(.rel.sharable_data .rel.sharable_data.* .rel.gnu.linkonce.shrd.*)
      *(.rel.sharable_bss .rel.sharable_bss.* .rel.gnu.linkonce.shrb.*)
      *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)
      *(.rel.ifunc)
    }
  .rel.plt        :
    {
      *(.rel.plt)
      PROVIDE_HIDDEN (__rel_iplt_start = .);
      *(.rel.iplt)
      PROVIDE_HIDDEN (__rel_iplt_end = .);
    }
  .init           :
  {
    KEEP (*(.init))
  } =0x90909090
  .plt            : { *(.plt) *(.iplt) }
  .text           :
  {
    *(.text.unlikely .text.*_unlikely)
    *(.text .stub .text.* .gnu.linkonce.t.*)
    /* .gnu.warning sections are handled specially by elf32.em.  */
    *(.gnu.warning)
  } =0x90909090
  .fini           :
  {
    KEEP (*(.fini))
  } =0x90909090
  PROVIDE (__etext = .);
  PROVIDE (_etext = .);
  PROVIDE (etext = .);
  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
  .rodata1        : { *(.rodata1) }
  .eh_frame_hdr : { *(.eh_frame_hdr) }
  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }
  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
  /* Adjust the address for the data segment.  We want to adjust up to
     the same address within the page on the next page up.  */
  . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
  /* Exception handling  */
  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }
  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
  /* Thread Local Storage sections  */
  .tdata          : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
  .tbss           : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
  .preinit_array     :
  {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  }
  .init_array     :
  {
     PROVIDE_HIDDEN (__init_array_start = .);
     KEEP (*(SORT(.init_array.*)))
     KEEP (*(.init_array))
     PROVIDE_HIDDEN (__init_array_end = .);
  }
  .fini_array     :
  {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array))
    PROVIDE_HIDDEN (__fini_array_end = .);
  }
  .ctors          :
  {
    /* gcc uses crtbegin.o to find the start of
       the constructors, so we make sure it is
       first.  Because this is a wildcard, it
       doesn't matter if the user does not
       actually link against crtbegin.o; the
       linker won't look for a file to match a
       wildcard.  The wildcard also means that it
       doesn't matter which directory crtbegin.o
       is in.  */
    KEEP (*crtbegin.o(.ctors))
    KEEP (*crtbegin?.o(.ctors))
    /* We don't want to include the .ctor section from
       the crtend.o file until after the sorted ctors.
       The .ctor section from the crtend file contains the
       end of ctors marker and it must be last */
    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
    KEEP (*(SORT(.ctors.*)))
    KEEP (*(.ctors))
  }
  .dtors          :
  {
    KEEP (*crtbegin.o(.dtors))
    KEEP (*crtbegin?.o(.dtors))
    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
    KEEP (*(SORT(.dtors.*)))
    KEEP (*(.dtors))
  }
  .jcr            : { KEEP (*(.jcr)) }
  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
  .dynamic        : { *(.dynamic) }
  .got            : { *(.got) *(.igot) }
  . = DATA_SEGMENT_RELRO_END (12, .);
  .got.plt        : { *(.got.plt)  *(.igot.plt) }
  .data           :
  {
    *(.data .data.* .gnu.linkonce.d.*)
    SORT(CONSTRUCTORS)
  }
  .data1          : { *(.data1) }
  /* Sharable data sections.  */
  .sharable_data   : ALIGN(CONSTANT (MAXPAGESIZE))
  {
    PROVIDE_HIDDEN (__sharable_data_start = .);
    *(.sharable_data .sharable_data.* .gnu.linkonce.shrd.*)
    /* Align here to ensure that the sharable data section ends at the
       page boundary.  */
    . = ALIGN(. != 0 ? CONSTANT (MAXPAGESIZE) : 1);
    PROVIDE_HIDDEN (__sharable_data_end = .);
  }
  _edata = .; PROVIDE (edata = .);
  __bss_start = .;
  .bss            :
  {
   *(.dynbss)
   *(.bss .bss.* .gnu.linkonce.b.*)
   *(COMMON)
   /* Align here to ensure that the .bss section occupies space up to
      _end.  Align after .bss to ensure correct alignment even if the
      .bss section disappears because there are no input sections.
      FIXME: Why do we need it? When there is no .bss section, we don't
      pad the .data section.  */
   . = ALIGN(. != 0 ? 32 / 8 : 1);
  }
  /* Sharable bss sections  */
  .sharable_bss   : ALIGN(CONSTANT (MAXPAGESIZE))
  {
    PROVIDE_HIDDEN (__sharable_bss_start = .);
    *(.dynsharablebss)
    *(.sharable_bss .sharable_bss.* .gnu.linkonce.shrb.*)
    *(SHARABLE_COMMON)
    /* Align here to ensure that the sharable bss section ends at the
       page boundary.  */
    . = ALIGN(. != 0 ? CONSTANT (MAXPAGESIZE) : 1);
    PROVIDE_HIDDEN (__sharable_bss_end = .);
  }
  . = ALIGN(32 / 8);
  . = ALIGN(32 / 8);
  _end = .; PROVIDE (end = .);
  . = DATA_SEGMENT_END (.);
  /* Stabs debugging sections.  */
  .stab          0 : { *(.stab) }
  .stabstr       0 : { *(.stabstr) }
  .stab.excl     0 : { *(.stab.excl) }
  .stab.exclstr  0 : { *(.stab.exclstr) }
  .stab.index    0 : { *(.stab.index) }
  .stab.indexstr 0 : { *(.stab.indexstr) }
  .comment       0 : { *(.comment) }
  /* DWARF debug sections.
     Symbols in the DWARF debugging sections are relative to the beginning
     of the section so we begin them at 0.  */
  /* DWARF 1 */
  .debug          0 : { *(.debug) }
  .line           0 : { *(.line) }
  /* GNU DWARF 1 extensions */
  .debug_srcinfo  0 : { *(.debug_srcinfo) }
  .debug_sfnames  0 : { *(.debug_sfnames) }
  /* DWARF 1.1 and DWARF 2 */
  .debug_aranges  0 : { *(.debug_aranges) }
  .debug_pubnames 0 : { *(.debug_pubnames) }
  /* DWARF 2 */
  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
  .debug_abbrev   0 : { *(.debug_abbrev) }
  .debug_line     0 : { *(.debug_line) }
  .debug_frame    0 : { *(.debug_frame) }
  .debug_str      0 : { *(.debug_str) }
  .debug_loc      0 : { *(.debug_loc) }
  .debug_macinfo  0 : { *(.debug_macinfo) }
  /* SGI/MIPS DWARF 2 extensions */
  .debug_weaknames 0 : { *(.debug_weaknames) }
  .debug_funcnames 0 : { *(.debug_funcnames) }
  .debug_typenames 0 : { *(.debug_typenames) }
  .debug_varnames  0 : { *(.debug_varnames) }
  /* DWARF 3 */
  .debug_pubtypes 0 : { *(.debug_pubtypes) }
  .debug_ranges   0 : { *(.debug_ranges) }
  .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
}
 
 
==================================================
attempt to open /usr/i686-redhat-linux/lib/libmysqlclient.so failed
attempt to open /usr/i686-redhat-linux/lib/libmysqlclient.a failed
attempt to open /usr/local/lib/libmysqlclient.so failed
attempt to open /usr/local/lib/libmysqlclient.a failed
attempt to open /lib/libmysqlclient.so failed
attempt to open /lib/libmysqlclient.a failed
attempt to open /usr/lib/libmysqlclient.so failed
attempt to open /usr/lib/libmysqlclient.a failed
 
# locate /libmysqlclient.so
/usr/lib/mysql/libmysqlclient.so
/usr/lib/mysql/libmysqlclient.so.16
/usr/lib/mysql/libmysqlclient.so.16.0.0
 
# ln -s /usr/lib/mysql/libmysqlclient.so /lib/libmysqlclient.so
 
# make
: undefined reference to `mysql_connect'
 

Ensuite il a fallu changer les fonctions mysql_connect par mysql_real_connect :

mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long client_flag);

Il faut retenir que le ‘ld’ permet de voir où doivent être les librairies.

Frédéric.

Redis : Configuration et performance sous Fédora & Redhat

Je fais un petit article pour mettre mes configurations de Redis (de l’anglais REmote DIctionary Server qui peut-être traduit par « serveur de dictionnaire distant ») sous Linux, afin de partager et aussi de corriger si nécessaire. Redis est développé en C AINSI comme tous les bons logiciels, il fait partie des NoSQL ( https://fr.wikipedia.org/wiki/NoSQL ). Les plus intéressant à connaitre sont : REDIS, MongoDB ( https://www.mongodb.com/fr ) , CouchDB ( http://couchdb.apache.org ) .

Le site officiel de Redis est : https://redis.io , la dernière version stable est la 4.0.1 (Jul 24 CEST 2017). La Release Note est disponible : https://raw.githubusercontent.com/antirez/redis/4.0/00-RELEASENOTES . La version que j’utilise est la 2.8.4 (13 Jan CEST 2014). La Release Note est disponible : https://raw.githubusercontent.com/antirez/redis/2.8/00-RELEASENOTES . Sur Twitter il faut suivre : @redisfeed .

Configuration et performance sous Redhat 7.2 (64b) :

Voici donc ma configuration de Redis sous Redhat 7.2 :

[root@]# cat /etc/redhat-release
Red Hat Enterprise Linux Server release 7.2 (Maipo)

Ensuite la configuration du service :

[root@]# cat /etc/systemd/system/multi-user.target.wants/redis.service

[Unit]
Description=A persistent key-value database
After=network.target
[Service]
Type=forking
User=root
Group=root
PIDFile=/var/run/redis_6379.pid
ExecStart=/usr/local/bin/redis-server /etc/redis/6379.conf
ExecStop=/usr/local/bin/redis-cli shutdown
LimitCORE=infinity
Restart=always
RestartSec=50
TimeoutStartSec=30

[Install]
WantedBy=multi-user.target

La configuration de Redis :

[root@]# cat /etc/redis/6379.conf

aof-rewrite-incremental-fsync yes
daemonize yes
pidfile /var/run/redis_6379.pid
port 6379
maxclients 6000
timeout 0
tcp-keepalive 0
loglevel notice
logfile /var/log/redis_6379.log
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /var/lib/redis/6379
slave-serve-stale-data yes
slave-read-only yes
repl-disable-tcp-nodelay no
slave-priority 100
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes

La configuration de sysctl.conf ( l’OS ) :

[root@]# cat /etc/sysctl.conf

net.ipv4.ip_forward = 0
vm.overcommit_memory = 1
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_tw_reuse = 1
net.netfilter.nf_conntrack_max = 1048576
net.ipv4.tcp_max_tw_buckets = 2000000
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
fs.file-max = 100000
net.ipv4.ip_local_port_range = 1025 65535
net.ipv4.tcp_syncookies = 1
vm.swappiness = 10
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 16777216
net.core.wmem_default = 16777216
net.core.optmem_max = 40960
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_max_syn_backlog = 999999999
net.core.netdev_max_backlog = 25000
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216

Voici la version de Redis que j’utilise: 2.8.4

                _._
          _.-``__ ''-._
      _.-``    `.  `_.  ''-._           Redis 2.8.4 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._
(    '      ,       .-`  | `,    )     Running in stand alone mode
|`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
|    `-._   `._    /     _.-'    |     PID: 28796
  `-._    `-._  `-./  _.-'    _.-'
|`-._`-._    `-.__.-'    _.-'_.-'|
|    `-._`-._        _.-'_.-'    |           http://redis.io
  `-._    `-._`-.__.-'_.-'    _.-'
|`-._`-._    `-.__.-'    _.-'_.-'|
|    `-._`-._        _.-'_.-'    |
  `-._    `-._`-.__.-'_.-'    _.-'
      `-._    `-.__.-'    _.-'
          `-._        _.-'
              `-.__.-'


[28796] 06 Sep 09:26:49.382 # Server started, Redis version 2.8.4
[28796] 06 Sep 09:26:49.386 * DB loaded from disk: 0.005 seconds
[28796] 06 Sep 09:26:49.386 * The server is now ready to accept connections on port 6379

Les performances de Redis dépendent des processeurs, du nombre de processeur, de la RAM, de la vitesse d’écriture sur le disque dur, de l’OS, de la configuration de Redis, de la configuration de l’OS.

[root@]# cat /proc/cpuinfo | grep "model name"
model name      : Intel(R) Xeon(R) CPU E5-2620 v4 @ 2.10GHz
[root@]# cat /proc/meminfo | head -4
MemTotal:        3785880 kB
MemFree:         3541916 kB
Buffers:               0 kB
Cached:           101008 kB
[root@]# dd if=/dev/zero of=tempfile bs=1M count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 0.678386 s, 1.6 GB/s

L’outil de benchmark de redis indique donc :

[root@]# redis-benchmark
====== PING_INLINE ======
10000 requests completed in 0.12 seconds
50 parallel clients
3 bytes payload
keep alive: 1

99.51% <= 2 milliseconds
100.00% <= 2 milliseconds
86206.90 requests per second

====== PING_BULK ======
10000 requests completed in 0.09 seconds
50 parallel clients
3 bytes payload
keep alive: 1

99.51% <= 1 milliseconds
100.00% <= 1 milliseconds
106382.98 requests per second

====== SET ======
10000 requests completed in 0.10 seconds
50 parallel clients
3 bytes payload
keep alive: 1

99.51% <= 1 milliseconds
100.00% <= 1 milliseconds
103092.78 requests per second

====== GET ======
10000 requests completed in 0.09 seconds
50 parallel clients
3 bytes payload
keep alive: 1

99.51% <= 1 milliseconds
100.00% <= 1 milliseconds
106382.98 requests per second

====== INCR ======
10000 requests completed in 0.10 seconds
50 parallel clients
3 bytes payload
keep alive: 1

99.51% <= 1 milliseconds
100.00% <= 1 milliseconds
103092.78 requests per second

====== LPUSH ======
10000 requests completed in 0.09 seconds
50 parallel clients
3 bytes payload
keep alive: 1

99.51% <= 1 milliseconds
100.00% <= 1 milliseconds
106382.98 requests per second

====== LPOP ======
10000 requests completed in 0.10 seconds
50 parallel clients
3 bytes payload
keep alive: 1

99.51% <= 1 milliseconds
100.00% <= 1 milliseconds
99009.90 requests per second

====== SADD ======
10000 requests completed in 0.09 seconds
50 parallel clients
3 bytes payload
keep alive: 1

99.51% <= 1 milliseconds
100.00% <= 1 milliseconds
105263.16 requests per second

====== SPOP ======
10000 requests completed in 0.10 seconds
50 parallel clients
3 bytes payload
keep alive: 1

99.51% <= 1 milliseconds
100.00% <= 1 milliseconds
101010.10 requests per second

====== LPUSH (needed to benchmark LRANGE) ======
10000 requests completed in 0.09 seconds
50 parallel clients
3 bytes payload
keep alive: 1

99.51% <= 1 milliseconds
100.00% <= 1 milliseconds
107526.88 requests per second

====== LRANGE_100 (first 100 elements) ======
10000 requests completed in 0.22 seconds
50 parallel clients
3 bytes payload
keep alive: 1

96.40% <= 1 milliseconds
99.99% <= 2 milliseconds
100.00% <= 2 milliseconds
44444.45 requests per second

====== LRANGE_300 (first 300 elements) ======
10000 requests completed in 0.54 seconds
50 parallel clients
3 bytes payload
keep alive: 1

2.04% <= 1 milliseconds
66.86% <= 2 milliseconds
99.63% <= 3 milliseconds
100.00% <= 3 milliseconds
18518.52 requests per second

====== LRANGE_500 (first 450 elements) ======
10000 requests completed in 0.81 seconds
50 parallel clients
3 bytes payload
keep alive: 1

0.01% <= 1 milliseconds
27.58% <= 2 milliseconds
68.13% <= 3 milliseconds
96.15% <= 4 milliseconds
99.91% <= 5 milliseconds
100.00% <= 5 milliseconds
12406.95 requests per second

====== LRANGE_600 (first 600 elements) ======
10000 requests completed in 1.02 seconds
50 parallel clients
3 bytes payload
keep alive: 1

0.01% <= 1 milliseconds
12.17% <= 2 milliseconds
42.39% <= 3 milliseconds
73.16% <= 4 milliseconds
97.02% <= 5 milliseconds
99.87% <= 6 milliseconds
100.00% <= 6 milliseconds
9765.62 requests per second

====== MSET (10 keys) ======
10000 requests completed in 0.13 seconds
50 parallel clients
3 bytes payload
keep alive: 1

99.51% <= 1 milliseconds
100.00% <= 1 milliseconds
76923.08 requests per second

Configuration et performance sous Fédora 17 (64b) :

Voici donc les mêmes informations sur Fédora 17 :

[root@]# cat /etc/redhat-release
Fedora release 17 (Beefy Miracle)

Configuration du service ( à noter le Type qui est « simple », et le ExecStop qui est un simple « kill »:

[root@]# cat /usr/lib/systemd/system/redis_6379.service
[Unit]
Description=A persistent key-value database
After=network.target

[Service]
Type=simple
User=root
Group=root
Environment=TERM=linux
Environment=LANG= LANGUAGE= LC_CTYPE= LC_NUMERIC= LC_TIME= LC_COLLATE= LC_MONETARY= LC_MESSAGES= LC_PAPER= LC_NAME= LC_ADDRESS= LC_TELEPHONE= LC_MEASUREMENT= LC_IDENTIFICATION=
WorkingDirectory=/tmp/
RootDirectoryStartOnly=yes

PIDFile=/var/run/redis_6379.pid
ExecStart=/usr/local/bin/redis-server /etc/redis/6379.conf --loglevel verbose
ExecStop=/bin/kill -15 $MAINPID
LimitCORE=infinity
Restart=always
RestartSec=50

[Install]
WantedBy=multi-user.target

Configuration de Redis :

[root@]# cat /etc/redis/6379.conf | grep -v "^#"  | grep -v "^$"
daemonize yes
pidfile /var/run/redis_6379.pid
port 6379
timeout 0
tcp-keepalive 0
loglevel notice
logfile /var/log/redis_6379.log
databases 16
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /var/lib/redis/6379
slave-serve-stale-data yes
slave-read-only yes
repl-disable-tcp-nodelay no
slave-priority 100
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes

Configuration de l’OS :

[root@]# cat /etc/sysctl.conf | grep -v "^#"  | grep -v "^$"
net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0
kernel.shmmax = 134217728
vm.swappiness = 10
vm.overcommit_memory = 1
vm.dirty_background_ratio = 5
vm.dirty_ratio = 50
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = "20000 65535"
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_intvl = 15
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 4096
net.ipv4.tcp_max_syn_backlog = 1024
net.core.rmem_default = 16777216
net.core.wmem_default = 16777216
net.core.rmem_max = 8388608
net.core.wmem_max = 8388608
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_tw_recycle = 1
kernel.sched_migration_cost_ns = 5000000
kernel.sched_autogroup_enabled = 0

Mémoire :

[root@ ]# cat /proc/meminfo | head -4
MemTotal:        2051388 kB
MemFree:           64672 kB
Buffers:            5140 kB
Cached:          1483944 kB

Nombre de processeur et modèle :

[root@]# cat /proc/cpuinfo | grep "model name"
model name      : Intel(R) Xeon(R) CPU E5-2620 v4 @ 2.10GHz
model name      : Intel(R) Xeon(R) CPU E5-2620 v4 @ 2.10GHz
model name      : Intel(R) Xeon(R) CPU E5-2620 v4 @ 2.10GHz
model name      : Intel(R) Xeon(R) CPU E5-2620 v4 @ 2.10GHz

Performance du disque dur :

[root@]# dd if=/dev/zero of=tempfile bs=1M count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 1.24509 s, 862 MB/s

Les performances :

[root@]# redis-benchmark
====== PING_INLINE ======
  10000 requests completed in 0.07 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

100.00% <= 0 milliseconds
135135.14 requests per second
====== PING_BULK ======
  10000 requests completed in 0.07 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

100.00% <= 0 milliseconds
140845.06 requests per second
====== SET ======
  10000 requests completed in 0.07 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

100.00% <= 0 milliseconds
142857.14 requests per second
====== GET ======
  10000 requests completed in 0.08 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

99.73% <= 1 milliseconds
100.00% <= 1 milliseconds
131578.95 requests per second

====== INCR ======
  10000 requests completed in 0.09 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

99.91% <= 1 milliseconds
100.00% <= 1 milliseconds
114942.53 requests per second
====== LPUSH ======
  10000 requests completed in 0.07 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

99.98% <= 1 milliseconds
100.00% <= 1 milliseconds
147058.81 requests per second
====== LPOP ======
  10000 requests completed in 0.09 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

99.99% <= 1 milliseconds
100.00% <= 1 milliseconds
117647.05 requests per second
====== SADD ======
  10000 requests completed in 0.07 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

100.00% <= 0 milliseconds
142857.14 requests per second
====== SPOP ======
  10000 requests completed in 0.07 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

100.00% <= 0 milliseconds
142857.14 requests per second
====== LPUSH (needed to benchmark LRANGE) ======
  10000 requests completed in 0.07 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

100.00% <= 0 milliseconds
144927.55 requests per second
====== LRANGE_100 (first 100 elements) ======
  10000 requests completed in 0.17 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

98.87% <= 1 milliseconds
100.00% <= 1 milliseconds
59523.81 requests per second
====== LRANGE_300 (first 300 elements) ======
  10000 requests completed in 0.47 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

14.92% <= 1 milliseconds
99.27% <= 2 milliseconds
100.00% <= 2 milliseconds
21413.28 requests per second
====== LRANGE_500 (first 450 elements) ======
  10000 requests completed in 0.65 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

0.15% <= 1 milliseconds
93.53% <= 2 milliseconds
99.51% <= 3 milliseconds
99.96% <= 4 milliseconds
100.00% <= 4 milliseconds
15337.42 requests per second
====== LRANGE_600 (first 600 elements) ======
  10000 requests completed in 0.95 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

0.10% <= 1 milliseconds
35.34% <= 2 milliseconds
84.92% <= 3 milliseconds
92.32% <= 4 milliseconds
99.36% <= 5 milliseconds
99.97% <= 6 milliseconds
100.00% <= 6 milliseconds
10537.41 requests per second

====== MSET (10 keys) ======
  10000 requests completed in 0.10 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

99.70% <= 1 milliseconds
99.92% <= 2 milliseconds
99.97% <= 3 milliseconds
100.00% <= 3 milliseconds
97087.38 requests per second