Ack with minor comment marked [AndersW].

regards,

Anders Widell


On 10/22/2016 02:53 PM, Hans Nordeback wrote:
>   osaf/libs/core/cplusplus/base/Makefile.am    |    2 +
>   osaf/libs/core/cplusplus/base/file_notify.cc |  188 
> +++++++++++++++++++++++++++
>   osaf/libs/core/cplusplus/base/file_notify.h  |  103 ++++++++++++++
>   3 files changed, 293 insertions(+), 0 deletions(-)
>
>
> diff --git a/osaf/libs/core/cplusplus/base/Makefile.am 
> b/osaf/libs/core/cplusplus/base/Makefile.am
> --- a/osaf/libs/core/cplusplus/base/Makefile.am
> +++ b/osaf/libs/core/cplusplus/base/Makefile.am
> @@ -24,6 +24,7 @@ SUBDIRS = tests
>   
>   noinst_HEADERS = \
>       buffer.h \
> +     file_notify.h \
>       getenv.h \
>       log_message.h \
>       macros.h \
> @@ -43,6 +44,7 @@ libbase_la_CPPFLAGS = \
>   libbase_la_LDFLAGS = -static
>   
>   libbase_la_SOURCES = \
> +     file_notify.cc \
>       getenv.cc \
>       log_message.cc \
>       process.cc \
> diff --git a/osaf/libs/core/cplusplus/base/file_notify.cc 
> b/osaf/libs/core/cplusplus/base/file_notify.cc
> new file mode 100644
> --- /dev/null
> +++ b/osaf/libs/core/cplusplus/base/file_notify.cc
> @@ -0,0 +1,188 @@
> +/*      -*- OpenSAF  -*-
> + *
> + * (C) Copyright 2016 The OpenSAF Foundation
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
> + * under the GNU Lesser General Public License Version 2.1, February 1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#include "base/file_notify.h"
> +#include <libgen.h>
> +#include <cerrno>
> +#include <cstdlib>
> +#include <cstring>
> +#include "time.h"
> +#include "osaf_poll.h"
> +#include "logtrace.h"
> +
> +namespace base {
> +
> +FileNotify::FileNotify() {
> +  if ((inotify_fd_ = inotify_init()) == -1) {
> +    LOG_NO("inotify_init failed: %s", strerror(errno));
> +  }
> +}
> +
> +FileNotify::~FileNotify() {
> +  close(inotify_fd_);
> +}
> +
> +void FileNotify::SplitFileName(const std::string &file_name) {
> +  char *tmp1 = strdup(file_name.c_str());
> +  char *tmp2 = strdup(file_name.c_str());
> +  file_path_ = dirname(tmp1);
> +  file_name_ = basename(tmp2);
> +  free(tmp1);
> +  free(tmp2);
> +}
> +
> +FileNotify::FileNotifyErrors
> +FileNotify::WaitForFileCreation(const std::string &file_name,
> +                                int timeout, const std::vector<int>& 
> user_fds) {
> +  FileNotify::FileNotifyErrors rc {FileNotifyErrors::kOK};
> +  SplitFileName(file_name);
> +
> +  if ((inotify_wd_ =
> +       inotify_add_watch(inotify_fd_, file_path_.c_str(), IN_CREATE)) == -1) 
> {
> +    LOG_NO("inotify_add_watch failed: %s", strerror(errno));
> +    return FileNotifyErrors::kError;
> +  }
> +
> +  if (FileExists(file_name)) {
> +    TRACE("File already created: %s", file_name.c_str());
> +    inotify_rm_watch(inotify_fd_, inotify_wd_);
> +    return FileNotifyErrors::kOK;
> +  }
> +
> +  rc = ProcessEvents(timeout, user_fds);
> +  inotify_rm_watch(inotify_fd_, inotify_wd_);
> +  return rc;
> +}
> +
> +FileNotify::FileNotifyErrors
> +FileNotify::WaitForFileDeletion(const std::string &file_name,
> +                                int timeout,
> +                                const std::vector<int>& user_fds) {
> +  FileNotify::FileNotifyErrors rc { FileNotifyErrors::kOK };
> +
> +  if ((inotify_wd_ = inotify_add_watch(inotify_fd_, file_name.c_str(),
> +                                       IN_DELETE_SELF)) == -1) {
> +    if (errno == ENOENT) {
> +      TRACE("File already deleted: %s", file_name.c_str());
> +      return FileNotifyErrors::kOK;
> +    } else {
> +      LOG_NO("inotify_add_watch failed: %s", strerror(errno));
> +      return FileNotifyErrors::kError;
> +    }
> +  }
> +
> +  rc = ProcessEvents(timeout, user_fds);
> +  inotify_rm_watch(inotify_fd_, inotify_wd_);
> +  return rc;
> +}
> +
> +FileNotify::FileNotifyErrors
> +FileNotify::ProcessEvents(int timeout, const std::vector<int>& user_fds) {
> +  enum {
> +    FD_INOTIFY = 0,
> +  };
> +
> +  timespec start_time {0};
> +  timespec time_left_ts {0};
> +  timespec timeout_ts {0};
> +
> +  int num_of_fds = user_fds.size() + 1;
> +  pollfd* fds = new pollfd[num_of_fds];
> +
> +  fds[FD_INOTIFY].fd = inotify_fd_;
> +  fds[FD_INOTIFY].events = POLLIN;
> +  for (int i = 1; i < num_of_fds; ++i) {
> +    fds[i].fd = user_fds[i-1];
[AndersW] Missing spaces around binary operator on the line above.
> +    fds[i].events = POLLIN;
> +  }
> +
> +  timeout_ts = base::MillisToTimespec(timeout);
> +  start_time = base::ReadMonotonicClock();
> +
> +  while (true) {
> +    TRACE("remaining timeout: %d", timeout);
> +    unsigned rc = osaf_poll(fds, num_of_fds, timeout);
> +
> +    if (rc > 0) {
> +      if (fds[FD_INOTIFY].revents & POLLIN) {
> +        ssize_t num_read = read(inotify_fd_, buf_, kBufferSize);
> +
> +        if (num_read == 0) {
> +          LOG_WA("read returned zero");
> +          delete [] fds;
> +          return FileNotifyErrors::kError;
> +        } else if (num_read == -1) {
> +          if (errno == EINTR) {
> +            continue;
> +          } else {
> +            LOG_WA("read error: %s", strerror(errno));
> +            delete [] fds;
> +            return FileNotifyErrors::kError;
> +          }
> +        } else {
> +          timespec current_time {0};
> +          timespec elapsed_time {0};
> +          for (char *p = buf_; p < buf_ + num_read;) {
> +            inotify_event *event = reinterpret_cast<inotify_event*> (p);
> +            if (event->mask & IN_DELETE_SELF) {
> +              TRACE("file name: %s deleted", file_name_.c_str());
> +              delete [] fds;
> +              return FileNotifyErrors::kOK;
> +            }
> +            if (event->mask & IN_CREATE) {
> +              if (file_name_ == event->name) {
> +                TRACE("file name: %s created", file_name_.c_str());
> +                delete [] fds;
> +                return FileNotifyErrors::kOK;
> +              }
> +            }
> +            if (event->mask & IN_IGNORED) {
> +              TRACE("IN_IGNORE received, (ignored)");
> +            }
> +            p += sizeof(inotify_event) + event->len;
> +          }
> +          // calculate remaining timeout
> +          current_time = base::ReadMonotonicClock();
> +
> +          if (current_time >= start_time) {
> +            elapsed_time = current_time - start_time;
> +          }
> +          if (elapsed_time >= timeout_ts) {
> +            return FileNotifyErrors::kTimeOut;
> +          }
> +          time_left_ts = timeout_ts - elapsed_time;
> +
> +          timeout = base::TimespecToMillis(time_left_ts);
> +        }
> +      }
> +      // Check user file descriptors
> +      for (int i = 1; i < num_of_fds; i++) {
> +        if ((fds[i].revents & POLLIN) ||
> +            (fds[i].revents & POLLHUP) ||
> +            (fds[i].revents & POLLERR)) {
> +          delete [] fds;
> +          return FileNotifyErrors::kUserFD;
> +        }
> +      }
> +    } else if (rc == 0) {
> +      TRACE("timeout");
> +      delete [] fds;
> +      return FileNotifyErrors::kTimeOut;
> +    }
> +  }
> +}
> +}  // namespace base
> diff --git a/osaf/libs/core/cplusplus/base/file_notify.h 
> b/osaf/libs/core/cplusplus/base/file_notify.h
> new file mode 100644
> --- /dev/null
> +++ b/osaf/libs/core/cplusplus/base/file_notify.h
> @@ -0,0 +1,103 @@
> +/*      -*- OpenSAF  -*-
> + *
> + * (C) Copyright 2016 The OpenSAF Foundation
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
> + * under the GNU Lesser General Public License Version 2.1, February 1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#include <unistd.h>
> +#include <sys/stat.h>
> +#include <limits.h>
> +#include <sys/inotify.h>
> +#include <string>
> +#include <vector>
> +#include "base/macros.h"
> +
> +#ifndef OSAF_LIBS_CORE_CPLUSPLUS_BASE_FILE_NOTIFY_H_
> +#define OSAF_LIBS_CORE_CPLUSPLUS_BASE_FILE_NOTIFY_H_
> +
> +namespace base {
> +
> +class FileNotify {
> + public:
> +  enum class FileNotifyErrors {
> +    kOK = 0,
> +    kTimeOut,
> +    kError,
> +    kUserFD
> +  };
> +
> +  FileNotify();
> +  virtual ~FileNotify();
> +
> +  /**
> +   * @brief Wait for a file to be created with a timeout.
> +   *
> +   * @a file name in format /path/file.
> +   * This function blocks until the file has been created or until the @a 
> timeout expires,
> +   * whichever happens first.
> +   *
> +   */
> +  FileNotifyErrors
> +  WaitForFileCreation(const std::string &file_name,
> +                      int timeout, const std::vector<int>& user_fds);
> +
> +  FileNotifyErrors
> +  WaitForFileCreation(const std::string &file_name, int timeout) {
> +    std::vector<int> empty_user_fds;
> +    return WaitForFileCreation(file_name, timeout, empty_user_fds);
> +  }
> +
> +  /**
> +   * @brief Wait for a file to be deleted.
> +   *
> +   * @a file name in format /path/file.
> +   * This function blocks until the file has been deleted or until the @a 
> timeout expires,
> +   * whichever happens first.
> +   *
> +   */
> +  FileNotifyErrors
> +  WaitForFileDeletion(const std::string &file_name,
> +                      int timeout, const std::vector<int>& user_fds);
> +
> +  FileNotifyErrors
> +    WaitForFileDeletion(const std::string &file_name, int timeout) {
> +    std::vector<int> empty_user_fds;
> +    return WaitForFileDeletion(file_name, timeout, empty_user_fds);
> +  }
> +
> +
> + private:
> +  static const int kBufferSize = 10 * (sizeof (inotify_event) + NAME_MAX + 
> 1);
> +
> +  FileNotifyErrors ProcessEvents(int timeout, const std::vector<int>& 
> user_fds);
> +
> +  bool FileExists(const std::string& file_name) const {
> +    struct stat buffer;
> +    return stat(file_name.c_str(), &buffer) == 0;
> +  }
> +
> +  void SplitFileName(const std::string &file_name);
> +
> +  char buf_[kBufferSize] __attribute__((aligned(8))) = {};
> +  std::string file_path_;
> +  std::string file_name_;
> +
> +  int inotify_fd_{-1};
> +  int inotify_wd_{-1};
> +  DELETE_COPY_AND_MOVE_OPERATORS(FileNotify);
> +};
> +
> +}  // namespace base
> +
> +#endif  // OSAF_LIBS_CORE_CPLUSPLUS_BASE_FILE_NOTIFY_H_


------------------------------------------------------------------------------
The Command Line: Reinvented for Modern Developers
Did the resurgence of CLI tooling catch you by surprise?
Reconnect with the command line and become more productive. 
Learn the new .NET and ASP.NET CLI. Get your free copy!
http://sdm.link/telerik
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to