changeset 16:6086194b2867

Bug 1467: Full mode log archiving does not work when using fifo pipe for gc log reviewed-by: ykubota, shintak
author Yasumasa Suenaga <suenaga.yasumasa@lab.ntt.co.jp>
date Mon, 17 Mar 2014 19:52:45 +0900
parents 6c73e9d7876c
children bfde41acb148
files agent/ChangeLog agent/src/fsUtil.cpp agent/src/fsUtil.hpp agent/src/logManager.cpp agent/src/util.hpp
diffstat 5 files changed, 198 insertions(+), 227 deletions(-) [+]
line wrap: on
line diff
--- a/agent/ChangeLog	Wed Mar 12 18:54:11 2014 +0900
+++ b/agent/ChangeLog	Mon Mar 17 19:52:45 2014 +0900
@@ -1,3 +1,11 @@
+2014-03-17  Yasumasa Suenaga  <suenaga.yasumasa@lab.ntt.co.jp>
+
+	* Bug 1647: Full mode log archiving does not work when using fifo pipe for gc log
+
+2014-03-12  KUBOTA Yuji  <kubota.yuji@lab.ntt.co.jp>
+
+	* Bug 1696: The SNMP settings are changed unexpectedly when HeapStats agent reloads the configuration.
+
 2014-03-03  Yasumasa Suenaga  <suenaga.yasumasa@lab.ntt.co.jp>
 
 	* Bug 1691: Update HeapStats logos
--- a/agent/src/fsUtil.cpp	Wed Mar 12 18:54:11 2014 +0900
+++ b/agent/src/fsUtil.cpp	Mon Mar 17 19:52:45 2014 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file fsUtil.cpp
  * \brief This file is utilities to access file system.
- * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2014 Nippon Telegraph and Telephone Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -27,6 +27,7 @@
 #include <unistd.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <sys/sendfile.h>
 
 #include "fsUtil.hpp"
 #include "util.hpp"
@@ -45,85 +46,88 @@
  * \return Value is zero, if process is succeed.<br />
  *         Value is error number a.k.a. "errno", if process is failure.
  */
-int copyFile(char const* sourceFile, char const* destPath, char const* destName) {
-    int result = 0;
-    /* Make file name. */
-    char *newFile = NULL;
-    if (destName == NULL) {
-        newFile = createFilename(destPath, (char*)sourceFile);
-    } else {
-        newFile = createFilename(destPath, (char*)destName);
-    }
-    
-    /* Failure make filename. */
-    if (unlikely(newFile == NULL)) {
-        PRINT_WARN_MSG("Couldn't allocate copy source file path.");
-        
-        /*
-         * Because exist below two pattern when "createFilename" return NULL.
-         * 1, Illegal argument. "errno" don't change.
-         * 2, No usable memory. "errno" maybe "ENOMEM".
-         */
-        return (errno != 0) ? errno : EINVAL;
-    }
-    
-    /* Get uniq file name. */
-    char *destFile = createUniquePath(newFile, false);
-    if (unlikely(destFile == NULL)) {
-        PRINT_WARN_MSG("Couldn't allocate unique destination file name.");
-        free(newFile);
-        return ENOMEM;
-    }
+int copyFile(char const* sourceFile, char const* destPath, char const* destName){
+  char rpath[PATH_MAX];
+
+  if(unlikely(!isCopiablePath(sourceFile, rpath))){
+    return EINVAL;
+  }
+
+  int result = 0;
+  /* Make file name. */
+  char *newFile = destName == NULL ? createFilename(destPath, (char*)sourceFile)
+                                   : createFilename(destPath, (char*)destName);
+
+  /* Failure make filename. */
+  if(unlikely(newFile == NULL)){
+    PRINT_WARN_MSG("Couldn't allocate copy source file path.");
+ 
+    /*
+     * Because exist below two pattern when "createFilename" return NULL.
+     * 1, Illegal argument. "errno" don't change.
+     * 2, No usable memory. "errno" maybe "ENOMEM".
+     */
+    return (errno != 0) ? errno : EINVAL;
+  }
     
-    /* Open copy source file. */
-    int sourceFd = open(sourceFile, O_RDONLY);
-    if (unlikely(sourceFd < 0)) {
-        result = errno;
-        PRINT_WARN_MSG("Couldn't open copy source file.");
-        free(newFile);
-        free(destFile);
-        return result;
-    }
-    
-    /* Open destination file. */
-    int destFd = open(destFile, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
-    if (unlikely(destFd < 0)) {
-        result = errno;
-        PRINT_WARN_MSG("Couldn't open copy destination file.");
-        free(newFile);
-        free(destFile);
-        close(sourceFd);
-        return result;
-    }
+  /* Get uniq file name. */
+  char *destFile = createUniquePath(newFile, false);
+  if(unlikely(destFile == NULL)){
+    PRINT_WARN_MSG("Couldn't allocate unique destination file name.");
+    free(newFile);
+    return ENOMEM;
+  }
     
-    /* Fetch advise. */
-    posix_fadvise(sourceFd, 0, 0, POSIX_FADV_SEQUENTIAL);
-    posix_fadvise(sourceFd, 0, 0, POSIX_FADV_NOREUSE);
-    posix_fadvise(destFd, 0, 0, POSIX_FADV_NOREUSE);
-    
-    /* Copy buffer. */
-    ssize_t readSize = 0;
-    char buff[1024];
-    /* Read from source file. */
-    while ((readSize = read(sourceFd, buff, sizeof(buff))) > 0) {
-        /* Write destination file. */
-        if (unlikely(write(destFd, buff, readSize) < 0)) {
-            result = errno;
-            PRINT_WARN_MSG("Couldn't write copy file data.");
-            break;
-        }
-    }
-    
-    /* Cleanup. */
-    
-    close(sourceFd);
-    if (unlikely(close(destFd) < 0 && result == 0)) {
-        result = errno;
-        PRINT_WARN_MSG("Couldn't write copy file data.");
-    }
+  /* Open copy source file. */
+  int sourceFd = open(sourceFile, O_RDONLY);
+  if(unlikely(sourceFd < 0)){
+    result = errno;
+    PRINT_WARN_MSG("Couldn't open copy source file.");
     free(newFile);
     free(destFile);
     return result;
+  }
+    
+  /* Get source file size */
+  struct stat st;
+  if(unlikely(fstat(sourceFd, &st) != 0)){
+    result = errno;
+    PRINT_WARN_MSG("Couldn't open copy destination file.");
+    free(newFile);
+    free(destFile);
+    close(sourceFd);
+    return result;
+  }
+
+  /* Open destination file. */
+  int destFd = open(destFile, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
+  if(unlikely(destFd < 0)){
+    result = errno;
+    PRINT_WARN_MSG("Couldn't open copy destination file.");
+    free(newFile);
+    free(destFile);
+    close(sourceFd);
+    return result;
+  }
+
+  /* Copy data */
+  if(unlikely(sendfile64(destFd, sourceFd, NULL, st.st_size) == -1)){
+    result = errno;
+    PRINT_WARN_MSG("Couldn't write copy file data.");
+  }
+
+  /* Clean up */
+  close(sourceFd);
+
+  if(unlikely((close(destFd) != 0) && (result == 0))){
+    result = errno;
+    PRINT_WARN_MSG("Couldn't write copy file data.");
+  }
+
+  free(newFile);
+  free(destFile);
+
+  return result;
 }
 
 /*!
@@ -183,49 +187,28 @@
 }
 
 /*!
- * \brief Check link is regular file.
- * \param linkPath [in]  Path of link file.
- * \param filePath [out] Path of file is linked by link file.
- * \param pathSize [in]  Max size of paramter "filePath".
- * \return Value is true, if link is linked regular file.<br>
- *         Value is false, if link is linked directory or other.
+ * \brief Resolve canonicalized path path and check regular file or not.
+ * \param path [in]  Path of the target file.
+ * \param rpath [out] Real path which is pointed at "path".
+ *        Buffer size must be enough to store path (we recommend PATH_MAX).
+ * \return If "path" is copiable, this function returns true.
  */
-bool isCopyableLink(char const* linkPath, char *filePath,
-  size_t pathSize) {
-    struct stat st = {0};
-    char unlinkPath[PATH_MAX + 1] = {0};
-    
-    /* Get real path and check file kind. */
-    if (unlikely(readlink(linkPath, unlinkPath, PATH_MAX) < 0)) {
-        
-        /* Failure read link. Maybe raised error. */
-        int raisedErrNum = errno;
-        PRINT_WARN_MSG_AND_ERRNO("Failure read information about link.",
-            raisedErrNum);
-        return false;
-        
-    } else if (unlikely(stat(linkPath, &st) != 0)) {
-        
-        /* Failure get file information. */
-        int raisedErrNum = errno;
-        PRINT_WARN_MSG_AND_ERRNO("Failure get file information.",
-            raisedErrNum);
-        return false;
-        
-    } else if ((st.st_mode & S_IFMT) != S_IFREG) {
-        
-        /* File isn't regular file. This route is not error. */
-        return false;
-    }
-    
-    /* Calculate copy size. */
-    size_t copyStrSize = strlen(unlinkPath);
-    copyStrSize = (copyStrSize > pathSize) ? pathSize : copyStrSize;
-    /* Copy real path. */
-    strncpy(filePath, unlinkPath, copyStrSize);
-    
-    /* File is able copy. */
-    return true;
+bool isCopiablePath(const char *path, char *rpath){
+  realpath(path, rpath);
+
+  struct stat st;
+  if(unlikely(stat(rpath, &st) != 0)){
+    /* Failure get file information. */
+    PRINT_WARN_MSG_AND_ERRNO("Failure get file information (stat).", errno);
+    return false;
+  }
+ 
+  if((st.st_mode & S_IFMT) != S_IFREG){
+    /* File isn't regular file. This route is not error. */
+    return false;
+  }
+
+  return true;
 }
 
 /*!
--- a/agent/src/fsUtil.hpp	Wed Mar 12 18:54:11 2014 +0900
+++ b/agent/src/fsUtil.hpp	Mon Mar 17 19:52:45 2014 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file fsUtil.hpp
  * \brief This file is utilities to access file system.
- * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2014 Nippon Telegraph and Telephone Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -49,15 +49,13 @@
 char *createFilename(char const* basePath, char const* filename);
 
 /*!
- * \brief Check link is regular file.
- * \param linkPath [in]  Path of link file.
- * \param filePath [out] Path of file is linked by link file.
- * \param pathSize [in]  Max size of paramter "filePath".
- * \return Value is true, if link is linked regular file.<br>
- *         Value is false, if link is linked directory or other.
+ * \brief Resolve canonicalized path path and check regular file or not.
+ * \param path [in]  Path of the target file.
+ * \param rpath [out] Real path which is pointed at "path".
+ *        Buffer size must be enough to store path (we recommend PATH_MAX).
+ * \return If "path" is copiable, this function returns true.
  */
-bool isCopyableLink(char const* linkPath, char *filePath,
-    size_t pathSize);
+bool isCopiablePath(const char *path, char *rpath);
 
 /*!
  * \brief Create temporary directory in designated directory.
--- a/agent/src/logManager.cpp	Wed Mar 12 18:54:11 2014 +0900
+++ b/agent/src/logManager.cpp	Mon Mar 17 19:52:45 2014 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file logManager.cpp
  * \brief This file is used collect log information.
- * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2014 Nippon Telegraph and Telephone Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -1201,11 +1201,11 @@
  * \return Value is zero, if process is succeed.<br />
  *         Value is error number a.k.a. "errno", if process is failure.
  */
-int TLogManager::copyInfoFiles(char const* basePath) {
-    
-    int result = 0;
-    /* Copy distribution file list. */
-    const char distFileList[][255] = {
+int TLogManager::copyInfoFiles(char const* basePath){
+  int result = 0;
+
+  /* Copy distribution file list. */
+  const char distFileList[][255] = {
         /* Distribution release. */
         "/etc/redhat-release",
         /* For other distribution. */
@@ -1217,35 +1217,36 @@
         "/etc/issue",
         /* End flag. */
         {0}
-    };
-    bool flagCopyedDistFile = false;
-    
-    /* Copy distribution file. */
-    for (int i = 0; strlen(distFileList[i]) > 0; i++) {
-        
-        result = copyFile(distFileList[i], basePath);
-        if (result == 0 || isRaisedDiskFull(result)) {
-            flagCopyedDistFile = (result == 0);
-            break;
-        }
+  };
+  bool flagCopyedDistFile = false;
+
+  /* Copy distribution file. */
+  for(int i = 0; strlen(distFileList[i]) > 0; i++){
+    result = copyFile(distFileList[i], basePath);
+
+    if((result == 0) || isRaisedDiskFull(result)){
+      flagCopyedDistFile = (result == 0);
+      break;
     }
-    
-    /* If failure copy distribution file. */
-    if (unlikely(!flagCopyedDistFile)) {
-        PRINT_WARN_MSG_AND_ERRNO(
-            "Failure copy file. path:\"distribution file\"", result);
-    }
-    
-    /* If disk is full. */
-    if (unlikely(isRaisedDiskFull(result))) {
-        return result;
-    }
-    
-    /* Copy file list. */
-    const char copyFileList[][255] = {
+
+  }
+
+  /* If failure copy distribution file. */
+  if(unlikely(!flagCopyedDistFile)){
+    PRINT_WARN_MSG_AND_ERRNO(
+                  "Failure copy file. path:\"distribution file\"", result);
+  }
+
+  /* If disk is full. */
+  if(unlikely(isRaisedDiskFull(result))){
+    return result;
+  }
+
+  /* Copy file list. */
+  const char copyFileList[][255] = {
         /* Process information. */
-        "/proc/%d/smaps",   "/proc/%d/limits",
-        "/proc/%d/cmdline", "/proc/%d/status",
+        "/proc/self/smaps",   "/proc/self/limits",
+        "/proc/self/cmdline", "/proc/self/status",
         /* Netstat infomation. */
         "/proc/net/tcp", "/proc/net/tcp6",
         "/proc/net/udp", "/proc/net/udp6",
@@ -1253,76 +1254,55 @@
         "/var/log/messages",
         /* End flag. */
         {0}
-    };
-    
-    /* Copy files in list. */
-    for (int i = 0; strlen(copyFileList[i]) > 0; i++) {
-        
-        /* Make copy file path. */
-        char buff[256] = {0};
-        snprintf(buff, 255, copyFileList[i], getpid());
-        
-        /* Copy file. */
-        result = copyFile(buff, basePath);
-        if (unlikely(result != 0)) {
-            PRINT_WARN_MSG_HEADER << "Failure copy file."
-                << " path:\"" << buff << "\""
-                << " cause:\"" << strerror(result) << "\"" 
+  };
+
+  /* Copy files in list. */
+  for(int i = 0; strlen(copyFileList[i]) > 0; i++){
+    /* Copy file. */
+    result = copyFile(copyFileList[i], basePath);
+    if(unlikely(result != 0)){
+      char error_string[1024];
+      strerror_r(result, error_string, 1024);
+
+      PRINT_WARN_MSG_HEADER << "Failure copy file."
+                << " path:\"" << copyFileList[i] << "\""
+                << " cause:\"" << error_string << "\"" 
                 << NEWLINE;
-            
-            /* If disk is full. */
-            if (unlikely(isRaisedDiskFull(result))) {
-                return result;
-            }
-        }
+
+      /* If disk is full. */
+      if(unlikely(isRaisedDiskFull(result))){
+        return result;
+      }
+
     }
-    
-    /* Copy file /proc/<pid>/fd/{1,2} */
-    char stdOutPath[256] = {0};
-    char stdErrPath[256] = {0};
-    snprintf(stdOutPath, 255, "/proc/%d/fd/1", getpid());
-    snprintf(stdErrPath, 255, "/proc/%d/fd/2", getpid());
-    char stdOutRealPath[PATH_MAX + 1] = {0};
-    char stdErrRealPath[PATH_MAX + 1] = {0};
-    
-    /* Check file is copyable. */
-    bool copyableStdOut = false;
-    bool copyableStdErr = false;
-    
-    copyableStdOut = isCopyableLink((char*)stdOutPath, (char*)stdOutRealPath,
-        PATH_MAX);
-    copyableStdErr = isCopyableLink((char*)stdErrPath, (char*)stdErrRealPath,
-        PATH_MAX);
-    
-    /* Copy stdout. */
-    if (unlikely(copyableStdOut)) {
-        result = copyFile(stdOutRealPath, basePath, "fd1");
-        
-        if (unlikely(result != 0)) {
-            PRINT_WARN_MSG_AND_ERRNO(
-                "Failure copy file. path:\"stdout\"", result);
-            
-            /* If disk is full. */
-            if (unlikely(isRaisedDiskFull(result))) {
-                return result;
-            }
-        }
+
+  }
+ 
+  /* Copy stdout */
+  result = copyFile("/proc/self/fd/1", basePath, "fd1");
+  if(unlikely(result != 0)){
+    PRINT_WARN_MSG_AND_ERRNO("Failure copy file. path:\"stdout\"", result);
+
+    /* If disk is full. */
+    if(unlikely(isRaisedDiskFull(result))){
+      return result;
     }
-    
-    /* If stdout is not equal stderr. */
-    if (strncmp(stdOutRealPath, stdErrRealPath, PATH_MAX) != 0) {
-        
-        /* Copy stderr. */
-        if (unlikely(copyableStdErr)) {
-            result = copyFile(stdErrRealPath, basePath, "fd2");
-            
-            if (unlikely(result != 0)) {
-                PRINT_WARN_MSG_AND_ERRNO(
-                    "Failure copy file. path:\"stderr\"", result);
-            }
-        }
+
+  }
+
+  /* Copy stderr */
+  result = copyFile("/proc/self/fd/2", basePath, "fd2");
+  if(unlikely(result != 0)){
+    PRINT_WARN_MSG_AND_ERRNO("Failure copy file. path:\"stderr\"", result);
+
+    /* If disk is full. */
+    if(unlikely(isRaisedDiskFull(result))){
+      return result;
     }
-    return result;
+
+  }
+
+  return result;
 }
 
 /*!
--- a/agent/src/util.hpp	Wed Mar 12 18:54:11 2014 +0900
+++ b/agent/src/util.hpp	Mon Mar 17 19:52:45 2014 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file util.hpp
  * \brief This file is utilities.
- * Copyright (C) 2011-2013 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2014 Nippon Telegraph and Telephone Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -114,8 +114,10 @@
  * \brief Warning message and errno macro.
  */
 #define PRINT_WARN_MSG_AND_ERRNO(msg, errnum) \
+    char error_string[1024]; \
+    strerror_r(errnum, error_string, 1024); \
     PRINT_WARN_MSG_HEADER << (msg) \
-        << " cause:\"" << strerror((errnum)) << "\"" << NEWLINE
+        << " cause:\"" << error_string << "\"" << NEWLINE
 
 /* Info message. */