<commit_before>// Copyright 2014 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef ROSIDL_TYPESUPPORT_INTROSPECTION_CPP__MESSAGE_INTROSPECTION_HPP_
#define ROSIDL_TYPESUPPORT_INTROSPECTION_CPP__MESSAGE_INTROSPECTION_HPP_

#include <cstddef>
#include <cstdint>

#include "rosidl_generator_c/message_type_support.h"

#include "rosidl_typesupport_introspection_cpp/visibility_control.h"

namespace rosidl_typesupport_introspection_cpp
{

struct ROSIDL_TYPESUPPORT_INTROSPECTION_CPP_PUBLIC MessageMembers;

typedef struct ROSIDL_TYPESUPPORT_INTROSPECTION_CPP_PUBLIC MessageMember
{
  const char * name_;
  uint8_t type_id_;
  size_t string_upper_bound_;
  const rosidl_message_type_support_t * members_;
  bool is_array_;
  size_t array_size_;
  bool is_upper_bound_;
  unsigned long offset_;
  const void * default_value_;
  size_t (* size_function)(const void *);
  const void * (*get_const_function)(const void *, size_t index);
  void * (*get_function)(void *, size_t index);
  void (* resize_function)(void *, size_t size);
} MessageMember;

typedef struct ROSIDL_TYPESUPPORT_INTROSPECTION_CPP_PUBLIC MessageMembers
{
  const char * package_name_;
  const char * message_name_;
  unsigned long member_count_;
  const MessageMember * members_;
} MessageMembers;

}  // namespace rosidl_typesupport_introspection_cpp

#endif  // ROSIDL_TYPESUPPORT_INTROSPECTION_CPP__MESSAGE_INTROSPECTION_HPP_
<commit_msg>Replace unsigned long with uint32_t<commit_after>// Copyright 2014 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef ROSIDL_TYPESUPPORT_INTROSPECTION_CPP__MESSAGE_INTROSPECTION_HPP_
#define ROSIDL_TYPESUPPORT_INTROSPECTION_CPP__MESSAGE_INTROSPECTION_HPP_

#include <cstddef>
#include <cstdint>

#include "rosidl_generator_c/message_type_support.h"

#include "rosidl_typesupport_introspection_cpp/visibility_control.h"

namespace rosidl_typesupport_introspection_cpp
{

struct ROSIDL_TYPESUPPORT_INTROSPECTION_CPP_PUBLIC MessageMembers;

typedef struct ROSIDL_TYPESUPPORT_INTROSPECTION_CPP_PUBLIC MessageMember
{
  const char * name_;
  uint8_t type_id_;
  size_t string_upper_bound_;
  const rosidl_message_type_support_t * members_;
  bool is_array_;
  size_t array_size_;
  bool is_upper_bound_;
  uint32_t offset_;
  const void * default_value_;
  size_t (* size_function)(const void *);
  const void * (*get_const_function)(const void *, size_t index);
  void * (*get_function)(void *, size_t index);
  void (* resize_function)(void *, size_t size);
} MessageMember;

typedef struct ROSIDL_TYPESUPPORT_INTROSPECTION_CPP_PUBLIC MessageMembers
{
  const char * package_name_;
  const char * message_name_;
  uint32_t member_count_;
  const MessageMember * members_;
} MessageMembers;

}  // namespace rosidl_typesupport_introspection_cpp

#endif  // ROSIDL_TYPESUPPORT_INTROSPECTION_CPP__MESSAGE_INTROSPECTION_HPP_
<|endoftext|>


<commit_before>// Copyright (c) 2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/message_pump_libevent.h"

#include <errno.h>
#include <fcntl.h>

#include "base/logging.h"
#include "base/scoped_nsautorelease_pool.h"
#include "base/time.h"
#include "third_party/libevent/event.h"

namespace base {

// Return 0 on success
// Too small a function to bother putting in a library?
static int SetNonBlocking(int fd) {
  int flags = fcntl(fd, F_GETFL, 0);
  if (flags == -1)
    flags = 0;
  return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}

MessagePumpLibevent::FileDescriptorWatcher::FileDescriptorWatcher()
    : is_persistent_(false),
      event_(NULL) {
}

MessagePumpLibevent::FileDescriptorWatcher::~FileDescriptorWatcher() {
  if (event_.get()) {
    StopWatchingFileDescriptor();
  }
}

void MessagePumpLibevent::FileDescriptorWatcher::Init(event *e,
                                                      bool is_persistent) {
  DCHECK(e);
  DCHECK(event_.get() == NULL);

  is_persistent_ = is_persistent;
  event_.reset(e);
}

event *MessagePumpLibevent::FileDescriptorWatcher::ReleaseEvent() {
  return event_.release();
}

bool MessagePumpLibevent::FileDescriptorWatcher::StopWatchingFileDescriptor() {
  if (event_.get() == NULL) {
    return true;
  }

  // event_del() is a no-op of the event isn't active.
  return (event_del(event_.get()) == 0);
}

// Called if a byte is received on the wakeup pipe.
void MessagePumpLibevent::OnWakeup(int socket, short flags, void* context) {
  base::MessagePumpLibevent* that =
              static_cast<base::MessagePumpLibevent*>(context);
  DCHECK(that->wakeup_pipe_out_ == socket);

  // Remove and discard the wakeup byte.
  char buf;
  int nread = read(socket, &buf, 1);
  DCHECK(nread == 1);
  // Tell libevent to break out of inner loop.
  event_base_loopbreak(that->event_base_);
}

MessagePumpLibevent::MessagePumpLibevent()
    : keep_running_(true),
      in_run_(false),
      event_base_(event_base_new()),
      wakeup_pipe_in_(-1),
      wakeup_pipe_out_(-1) {
  if (!Init())
     NOTREACHED();
}

bool MessagePumpLibevent::Init() {
  int fds[2];
  if (pipe(fds)) {
    DLOG(ERROR) << "pipe() failed, errno: " << errno;
    return false;
  }
  if (SetNonBlocking(fds[0])) {
    DLOG(ERROR) << "SetNonBlocking for pipe fd[0] failed, errno: " << errno;
    return false;
  }
  if (SetNonBlocking(fds[1])) {
    DLOG(ERROR) << "SetNonBlocking for pipe fd[1] failed, errno: " << errno;
    return false;
  }
  wakeup_pipe_out_ = fds[0];
  wakeup_pipe_in_ = fds[1];

  wakeup_event_ = new event;
  event_set(wakeup_event_, wakeup_pipe_out_, EV_READ | EV_PERSIST,
            OnWakeup, this);
  event_base_set(event_base_, wakeup_event_);

  if (event_add(wakeup_event_, 0))
    return false;
  return true;
}

MessagePumpLibevent::~MessagePumpLibevent() {
  DCHECK(wakeup_event_);
  DCHECK(event_base_);
  event_del(wakeup_event_);
  delete wakeup_event_;
  event_base_free(event_base_);
}

bool MessagePumpLibevent::WatchFileDescriptor(int fd,
                                              bool persistent,
                                              Mode mode,
                                              FileDescriptorWatcher *controller,
                                              Watcher *delegate) {
  DCHECK(fd > 0);
  DCHECK(controller);
  DCHECK(delegate);
  DCHECK(mode == WATCH_READ || mode == WATCH_WRITE || mode == WATCH_READ_WRITE);

  int event_mask = persistent ? EV_PERSIST : 0;
  if ((mode & WATCH_READ) != 0) {
    event_mask |= EV_READ;
  }
  if ((mode & WATCH_WRITE) != 0) {
    event_mask |= EV_WRITE;
  }

  // |should_delete_event| is true if we're modifying an event that's currently
  // active in |controller|.
  // If we're modifying an existing event and there's an error then we need to
  // tell libevent to clean it up via event_delete() before returning.
  bool should_delete_event = true;
  scoped_ptr<event> evt(controller->ReleaseEvent());
  if (evt.get() == NULL) {
    should_delete_event = false;
    // Ownership is transferred to the controller.
    evt.reset(new event);
  }

  // Set current interest mask and message pump for this event.
  event_set(evt.get(), fd, event_mask, OnLibeventNotification,
            delegate);

  // Tell libevent which message pump this socket will belong to when we add it.
  if (event_base_set(event_base_, evt.get()) != 0) {
    if (should_delete_event) {
      event_del(evt.get());
    }
    return false;
  }

  // Add this socket to the list of monitored sockets.
  if (event_add(evt.get(), NULL) != 0) {
    if (should_delete_event) {
      event_del(evt.get());
    }
    return false;
  }

  // Transfer ownership of e to controller.
  controller->Init(evt.release(), persistent);
  return true;
}

void MessagePumpLibevent::OnLibeventNotification(int fd, short flags,
                                                 void* context) {
  Watcher* watcher = static_cast<Watcher*>(context);

  if (flags & EV_WRITE) {
    watcher->OnFileCanWriteWithoutBlocking(fd);
  }
  if (flags & EV_READ) {
    watcher->OnFileCanReadWithoutBlocking(fd);
  }
}

// Reentrant!
void MessagePumpLibevent::Run(Delegate* delegate) {
  DCHECK(keep_running_) << "Quit must have been called outside of Run!";

  bool old_in_run = in_run_;
  in_run_ = true;

  for (;;) {
    ScopedNSAutoreleasePool autorelease_pool;

    bool did_work = delegate->DoWork();
    if (!keep_running_)
      break;

    did_work |= delegate->DoDelayedWork(&delayed_work_time_);
    if (!keep_running_)
      break;

    if (did_work)
      continue;

    did_work = delegate->DoIdleWork();
    if (!keep_running_)
      break;

    if (did_work)
      continue;

    // EVLOOP_ONCE tells libevent to only block once,
    // but to service all pending events when it wakes up.
    if (delayed_work_time_.is_null()) {
      event_base_loop(event_base_, EVLOOP_ONCE);
    } else {
      TimeDelta delay = delayed_work_time_ - Time::Now();
      if (delay > TimeDelta()) {
        struct timeval poll_tv;
        poll_tv.tv_sec = delay.InSeconds();
        poll_tv.tv_usec = delay.InMicroseconds() % Time::kMicrosecondsPerSecond;
        event_base_loopexit(event_base_, &poll_tv);
        event_base_loop(event_base_, EVLOOP_ONCE);
      } else {
        // It looks like delayed_work_time_ indicates a time in the past, so we
        // need to call DoDelayedWork now.
        delayed_work_time_ = Time();
      }
    }
  }

  keep_running_ = true;
  in_run_ = old_in_run;
}

void MessagePumpLibevent::Quit() {
  DCHECK(in_run_);
  // Tell both libevent and Run that they should break out of their loops.
  keep_running_ = false;
  ScheduleWork();
}

void MessagePumpLibevent::ScheduleWork() {
  // Tell libevent (in a threadsafe way) that it should break out of its loop.
  char buf = 0;
  int nwrite = write(wakeup_pipe_in_, &buf, 1);
  DCHECK(nwrite == 1);
}

void MessagePumpLibevent::ScheduleDelayedWork(const Time& delayed_work_time) {
  // We know that we can't be blocked on Wait right now since this method can
  // only be called on the same thread as Run, so we only need to update our
  // record of how long to sleep when we do sleep.
  delayed_work_time_ = delayed_work_time;
}

}  // namespace base
<commit_msg>The dtor wasn't actually cleaning up the fds from the pipe, so close them down   during shutdown. (this w/ the zombies was what caused the bots to run out of   fds) Review URL: http://codereview.chromium.org/20006<commit_after>// Copyright (c) 2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/message_pump_libevent.h"

#include <errno.h>
#include <fcntl.h>

#include "base/logging.h"
#include "base/scoped_nsautorelease_pool.h"
#include "base/time.h"
#include "third_party/libevent/event.h"

namespace base {

// Return 0 on success
// Too small a function to bother putting in a library?
static int SetNonBlocking(int fd) {
  int flags = fcntl(fd, F_GETFL, 0);
  if (flags == -1)
    flags = 0;
  return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}

MessagePumpLibevent::FileDescriptorWatcher::FileDescriptorWatcher()
    : is_persistent_(false),
      event_(NULL) {
}

MessagePumpLibevent::FileDescriptorWatcher::~FileDescriptorWatcher() {
  if (event_.get()) {
    StopWatchingFileDescriptor();
  }
}

void MessagePumpLibevent::FileDescriptorWatcher::Init(event *e,
                                                      bool is_persistent) {
  DCHECK(e);
  DCHECK(event_.get() == NULL);

  is_persistent_ = is_persistent;
  event_.reset(e);
}

event *MessagePumpLibevent::FileDescriptorWatcher::ReleaseEvent() {
  return event_.release();
}

bool MessagePumpLibevent::FileDescriptorWatcher::StopWatchingFileDescriptor() {
  if (event_.get() == NULL) {
    return true;
  }

  // event_del() is a no-op of the event isn't active.
  return (event_del(event_.get()) == 0);
}

// Called if a byte is received on the wakeup pipe.
void MessagePumpLibevent::OnWakeup(int socket, short flags, void* context) {
  base::MessagePumpLibevent* that =
              static_cast<base::MessagePumpLibevent*>(context);
  DCHECK(that->wakeup_pipe_out_ == socket);

  // Remove and discard the wakeup byte.
  char buf;
  int nread = read(socket, &buf, 1);
  DCHECK(nread == 1);
  // Tell libevent to break out of inner loop.
  event_base_loopbreak(that->event_base_);
}

MessagePumpLibevent::MessagePumpLibevent()
    : keep_running_(true),
      in_run_(false),
      event_base_(event_base_new()),
      wakeup_pipe_in_(-1),
      wakeup_pipe_out_(-1) {
  if (!Init())
     NOTREACHED();
}

bool MessagePumpLibevent::Init() {
  int fds[2];
  if (pipe(fds)) {
    DLOG(ERROR) << "pipe() failed, errno: " << errno;
    return false;
  }
  if (SetNonBlocking(fds[0])) {
    DLOG(ERROR) << "SetNonBlocking for pipe fd[0] failed, errno: " << errno;
    return false;
  }
  if (SetNonBlocking(fds[1])) {
    DLOG(ERROR) << "SetNonBlocking for pipe fd[1] failed, errno: " << errno;
    return false;
  }
  wakeup_pipe_out_ = fds[0];
  wakeup_pipe_in_ = fds[1];

  wakeup_event_ = new event;
  event_set(wakeup_event_, wakeup_pipe_out_, EV_READ | EV_PERSIST,
            OnWakeup, this);
  event_base_set(event_base_, wakeup_event_);

  if (event_add(wakeup_event_, 0))
    return false;
  return true;
}

MessagePumpLibevent::~MessagePumpLibevent() {
  DCHECK(wakeup_event_);
  DCHECK(event_base_);
  event_del(wakeup_event_);
  delete wakeup_event_;
  if (wakeup_pipe_in_ >= 0)
    close(wakeup_pipe_in_);
  if (wakeup_pipe_out_ >= 0)
    close(wakeup_pipe_out_);
  event_base_free(event_base_);
}

bool MessagePumpLibevent::WatchFileDescriptor(int fd,
                                              bool persistent,
                                              Mode mode,
                                              FileDescriptorWatcher *controller,
                                              Watcher *delegate) {
  DCHECK(fd > 0);
  DCHECK(controller);
  DCHECK(delegate);
  DCHECK(mode == WATCH_READ || mode == WATCH_WRITE || mode == WATCH_READ_WRITE);

  int event_mask = persistent ? EV_PERSIST : 0;
  if ((mode & WATCH_READ) != 0) {
    event_mask |= EV_READ;
  }
  if ((mode & WATCH_WRITE) != 0) {
    event_mask |= EV_WRITE;
  }

  // |should_delete_event| is true if we're modifying an event that's currently
  // active in |controller|.
  // If we're modifying an existing event and there's an error then we need to
  // tell libevent to clean it up via event_delete() before returning.
  bool should_delete_event = true;
  scoped_ptr<event> evt(controller->ReleaseEvent());
  if (evt.get() == NULL) {
    should_delete_event = false;
    // Ownership is transferred to the controller.
    evt.reset(new event);
  }

  // Set current interest mask and message pump for this event.
  event_set(evt.get(), fd, event_mask, OnLibeventNotification,
            delegate);

  // Tell libevent which message pump this socket will belong to when we add it.
  if (event_base_set(event_base_, evt.get()) != 0) {
    if (should_delete_event) {
      event_del(evt.get());
    }
    return false;
  }

  // Add this socket to the list of monitored sockets.
  if (event_add(evt.get(), NULL) != 0) {
    if (should_delete_event) {
      event_del(evt.get());
    }
    return false;
  }

  // Transfer ownership of e to controller.
  controller->Init(evt.release(), persistent);
  return true;
}

void MessagePumpLibevent::OnLibeventNotification(int fd, short flags,
                                                 void* context) {
  Watcher* watcher = static_cast<Watcher*>(context);

  if (flags & EV_WRITE) {
    watcher->OnFileCanWriteWithoutBlocking(fd);
  }
  if (flags & EV_READ) {
    watcher->OnFileCanReadWithoutBlocking(fd);
  }
}

// Reentrant!
void MessagePumpLibevent::Run(Delegate* delegate) {
  DCHECK(keep_running_) << "Quit must have been called outside of Run!";

  bool old_in_run = in_run_;
  in_run_ = true;

  for (;;) {
    ScopedNSAutoreleasePool autorelease_pool;

    bool did_work = delegate->DoWork();
    if (!keep_running_)
      break;

    did_work |= delegate->DoDelayedWork(&delayed_work_time_);
    if (!keep_running_)
      break;

    if (did_work)
      continue;

    did_work = delegate->DoIdleWork();
    if (!keep_running_)
      break;

    if (did_work)
      continue;

    // EVLOOP_ONCE tells libevent to only block once,
    // but to service all pending events when it wakes up.
    if (delayed_work_time_.is_null()) {
      event_base_loop(event_base_, EVLOOP_ONCE);
    } else {
      TimeDelta delay = delayed_work_time_ - Time::Now();
      if (delay > TimeDelta()) {
        struct timeval poll_tv;
        poll_tv.tv_sec = delay.InSeconds();
        poll_tv.tv_usec = delay.InMicroseconds() % Time::kMicrosecondsPerSecond;
        event_base_loopexit(event_base_, &poll_tv);
        event_base_loop(event_base_, EVLOOP_ONCE);
      } else {
        // It looks like delayed_work_time_ indicates a time in the past, so we
        // need to call DoDelayedWork now.
        delayed_work_time_ = Time();
      }
    }
  }

  keep_running_ = true;
  in_run_ = old_in_run;
}

void MessagePumpLibevent::Quit() {
  DCHECK(in_run_);
  // Tell both libevent and Run that they should break out of their loops.
  keep_running_ = false;
  ScheduleWork();
}

void MessagePumpLibevent::ScheduleWork() {
  // Tell libevent (in a threadsafe way) that it should break out of its loop.
  char buf = 0;
  int nwrite = write(wakeup_pipe_in_, &buf, 1);
  DCHECK(nwrite == 1);
}

void MessagePumpLibevent::ScheduleDelayedWork(const Time& delayed_work_time) {
  // We know that we can't be blocked on Wait right now since this method can
  // only be called on the same thread as Run, so we only need to update our
  // record of how long to sleep when we do sleep.
  delayed_work_time_ = delayed_work_time;
}

}  // namespace base
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/path_service.h"

#include "base/basictypes.h"
#include "base/file_util.h"
#include "base/file_path.h"
#if defined(OS_WIN)
#include "base/win/windows_version.h"
#endif
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gtest/include/gtest/gtest-spi.h"
#include "testing/platform_test.h"

namespace {

// Returns true if PathService::Get returns true and sets the path parameter
// to non-empty for the given PathService::DirType enumeration value.
bool ReturnsValidPath(int dir_type) {
  FilePath path;
  bool result = PathService::Get(dir_type, &path);
  return result && !path.value().empty() && file_util::PathExists(path);
}

#if defined(OS_WIN)
// Function to test DIR_LOCAL_APP_DATA_LOW on Windows XP. Make sure it fails.
bool ReturnsInvalidPath(int dir_type) {
  FilePath path;
  bool result = PathService::Get(base::DIR_LOCAL_APP_DATA_LOW, &path);
  return !result && path.empty();
}
#endif

}  // namespace

// On the Mac this winds up using some autoreleased objects, so we need to
// be a PlatformTest.
typedef PlatformTest PathServiceTest;

// Test that all PathService::Get calls return a value and a true result
// in the development environment.  (This test was created because a few
// later changes to Get broke the semantics of the function and yielded the
// correct value while returning false.)
TEST_F(PathServiceTest, Get) {
  for (int key = base::DIR_CURRENT; key < base::PATH_END; ++key) {
    EXPECT_PRED1(ReturnsValidPath, key);
  }
#if defined(OS_WIN)
  for (int key = base::PATH_WIN_START + 1; key < base::PATH_WIN_END; ++key) {
    if (key == base::DIR_LOCAL_APP_DATA_LOW &&
        base::win::GetVersion() < base::win::VERSION_VISTA) {
      // DIR_LOCAL_APP_DATA_LOW is not supported prior Vista and is expected to
      // fail.
      EXPECT_TRUE(ReturnsInvalidPath(key)) << key;
    } else {
      EXPECT_TRUE(ReturnsValidPath(key)) << key;
    }
  }
#elif defined(OS_MACOSX)
  for (int key = base::PATH_MAC_START + 1; key < base::PATH_MAC_END; ++key) {
      EXPECT_PRED1(ReturnsValidPath, key);
  }
#endif
}
<commit_msg>If chromium has not been started yet, the cache path will not exist.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/path_service.h"

#include "base/basictypes.h"
#include "base/file_util.h"
#include "base/file_path.h"
#if defined(OS_WIN)
#include "base/win/windows_version.h"
#endif
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gtest/include/gtest/gtest-spi.h"
#include "testing/platform_test.h"

namespace {

// Returns true if PathService::Get returns true and sets the path parameter
// to non-empty for the given PathService::DirType enumeration value.
bool ReturnsValidPath(int dir_type) {
  FilePath path;
  bool result = PathService::Get(dir_type, &path);
#if defined(OS_POSIX)
  // If chromium has never been started on this account, the cache path will not
  // exist.
  if (dir_type == base::DIR_USER_CACHE)
    return result && !path.value().empty();
#endif
  return result && !path.value().empty() && file_util::PathExists(path);
}

#if defined(OS_WIN)
// Function to test DIR_LOCAL_APP_DATA_LOW on Windows XP. Make sure it fails.
bool ReturnsInvalidPath(int dir_type) {
  FilePath path;
  bool result = PathService::Get(base::DIR_LOCAL_APP_DATA_LOW, &path);
  return !result && path.empty();
}
#endif

}  // namespace

// On the Mac this winds up using some autoreleased objects, so we need to
// be a PlatformTest.
typedef PlatformTest PathServiceTest;

// Test that all PathService::Get calls return a value and a true result
// in the development environment.  (This test was created because a few
// later changes to Get broke the semantics of the function and yielded the
// correct value while returning false.)
TEST_F(PathServiceTest, Get) {
  for (int key = base::DIR_CURRENT; key < base::PATH_END; ++key) {
    EXPECT_PRED1(ReturnsValidPath, key);
  }
#if defined(OS_WIN)
  for (int key = base::PATH_WIN_START + 1; key < base::PATH_WIN_END; ++key) {
    if (key == base::DIR_LOCAL_APP_DATA_LOW &&
        base::win::GetVersion() < base::win::VERSION_VISTA) {
      // DIR_LOCAL_APP_DATA_LOW is not supported prior Vista and is expected to
      // fail.
      EXPECT_TRUE(ReturnsInvalidPath(key)) << key;
    } else {
      EXPECT_TRUE(ReturnsValidPath(key)) << key;
    }
  }
#elif defined(OS_MACOSX)
  for (int key = base::PATH_MAC_START + 1; key < base::PATH_MAC_END; ++key) {
      EXPECT_PRED1(ReturnsValidPath, key);
  }
#endif
}
<|endoftext|>


<commit_before>// @(#)root/base:$Name:  $:$Id: TVirtualProofMgr.cxx,v 1.7 2006/06/02 15:14:35 rdm Exp $
// Author: G. Ganis, Nov 2005

/*************************************************************************
 * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TVirtualProofMgr                                                     //
//                                                                      //
// Abstract interface to the manager for PROOF sessions.                //
// The PROOF manager interacts with the PROOF server coordinator to     //
// create or destroy a PROOF session, attach to or detach from          //
// existing one, and to monitor any client activity on the cluster.     //
// At most one manager instance per server is allowed.                  //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#ifdef HAVE_CONFIG
#include "config.h"
#endif
#include "TError.h"
#include "TInetAddress.h"
#include "TList.h"
#include "TROOT.h"
#include "TSystem.h"
#include "TVirtualMutex.h"
#include "TVirtualProof.h"
#include "TVirtualProofMgr.h"

ClassImp(TVirtualProofMgr)

// Sub-list of TROOT::fProofs with managers
TList TVirtualProofMgr::fgListOfManagers;
TVirtualProofMgr_t TVirtualProofMgr::fgTProofMgrHook[2] = { 0, 0 };

//______________________________________________________________________________
TVirtualProofMgr::TVirtualProofMgr(const char *url, Int_t, const char *)
                 : TNamed("",""), fRemoteProtocol(-1),
                   fServType(kXProofd), fSessions(0)
{
   // Constructor

   // AVoid problems with empty URLs
   fUrl = (!url || strlen(url) <= 0) ? TUrl("proof://localhost") : TUrl(url);
}

//______________________________________________________________________________
TVirtualProofMgr::~TVirtualProofMgr()
{
   // Destroy a TVirtualProofMgr instance

   SafeDelete(fSessions);

   fgListOfManagers.Remove(this);
   gROOT->GetListOfProofs()->Remove(this);
}

//______________________________________________________________________________
void TVirtualProofMgr::ShowWorkers()
{
   // Show available workers

   AbstractMethod("ShowWorkers");
}

//______________________________________________________________________________
TVirtualProofDesc *TVirtualProofMgr::GetProofDesc(Int_t id)
{
   // Get TVirtualProof instance corresponding to 'id'.

   if (id > 0) {
      TVirtualProofDesc *d = 0;
      // Retrieve an updated list
      QuerySessions("");
      if (fSessions) {
         TIter nxd(fSessions);
         while ((d = (TVirtualProofDesc *)nxd())) {
            if (d->MatchId(id))
               return d;
         }
      }
   }

   return 0;
}

//______________________________________________________________________________
void TVirtualProofMgr::ShutdownSession(TVirtualProof *p)
{
   // Discard PROOF session 'p'

   if (p) {
      TVirtualProofDesc *d = 0;
      if (fSessions) {
         TIter nxd(fSessions);
         while ((d = (TVirtualProofDesc *)nxd())) {
            if (p == d->GetProof()) {
               fSessions->Remove(d);
               delete d;
               break;
            }
         }
      }
   }
}

//______________________________________________________________________________
TVirtualProof *TVirtualProofMgr::CreateSession(const char *cfg,
                                               const char *cfgdir, Int_t loglevel)
{
   // Create a new remote session (master and associated workers).

   // Create
   if (IsProofd())
      fUrl.SetOptions("std");

   TProof_t proofhook = TVirtualProof::GetTProofHook();
   if (!proofhook) {

      // Load the library containing TProof ...
#ifdef ROOTLIBDIR
      TString prooflib = TString(ROOTLIBDIR) + "/libProof";
#else
#ifndef WIN32
      TString prooflib = TString(gRootDir) + "/lib/libProof";
#else
      TString prooflib = TString(gRootDir) + "/bin/libProof";
#endif
#endif
      char *p = 0;
      if ((p = gSystem->DynamicPathName(prooflib, kTRUE))) {
         delete[] p;
         if (gSystem->Load(prooflib) == -1)
            Error("CreateSession", "can't load %s", prooflib.Data());
         proofhook = TVirtualProof::GetTProofHook();
      } else
         Error("CreateSession", "can't locate %s", prooflib.Data());
   }
   if (!proofhook) {
      Error("CreateSession", "hook for TVirtualProof could not be loaded");
      return 0;
   }
   // Create the instance
   TVirtualProof *p =
     (TVirtualProof*) (*proofhook)(fUrl.GetUrl(), cfg, cfgdir, loglevel, 0);

   if (p && p->IsValid()) {

      // Set reference manager
      p->SetManager(this);

      // Save record about this session
      Int_t ns = 1;
      if (fSessions) {
         // To avoid ambiguities in case of removal of some elements
         if (fSessions->Last())
            ns = ((TVirtualProofDesc *)(fSessions->Last()))->GetLocalId() + 1;
      } else {
         // Create the list
         fSessions = new TList;
      }

      // Create the description class
      Int_t st = (p->IsIdle()) ? TVirtualProofDesc::kIdle : TVirtualProofDesc::kRunning ;
      TVirtualProofDesc *d =
         new TVirtualProofDesc(p->GetName(), p->GetTitle(), p->GetUrl(),
                               ns, p->GetSessionID(), st, p);
      fSessions->Add(d);

   } else {
      // Session creation failed
      Error("CreateSession", "creating PROOF session");
      SafeDelete(p);
   }

   // We are done
   return p;
}

//______________________________________________________________________________
Bool_t TVirtualProofMgr::MatchUrl(const char *url)
{
   // Checks if 'url' refers to the same 'user@host:port' entity as the URL
   // in memory

   TUrl u(url);

   // Correct URL protocol
   if (!strcmp(u.GetProtocol(), TUrl("a").GetProtocol()))
      u.SetProtocol("proof");

   // Correct port
   if (u.GetPort() == TUrl("a").GetPort()) {
      Int_t port = gSystem->GetServiceByName("rootd");
      if (port < 0)
         port = 1094;
      u.SetPort(port);
   }

   // Now we can check
   if (!strcmp(u.GetHostFQDN(), fUrl.GetHostFQDN()))
      if (u.GetPort() == fUrl.GetPort())
         if (strlen(u.GetUser()) <= 0 || !strcmp(u.GetUser(),fUrl.GetUser()))
            return kTRUE;

   // Match failed
   return kFALSE;
}

//________________________________________________________________________
TList *TVirtualProofMgr::GetListOfManagers()
{
   // Extract pointers to PROOF managers from TROOT::fProofs.

   // Update the list with new entries
   if (gROOT->GetListOfProofs()) {
      TIter nxp(gROOT->GetListOfProofs());
      TVirtualProofMgr *p = 0;
      while ((p = dynamic_cast<TVirtualProofMgr *> (nxp())))
         if (!fgListOfManagers.FindObject(p))
            fgListOfManagers.Add(p);
   }

   // Get rid of invalid entries and notify
   if (fgListOfManagers.GetSize() > 0) {
      TIter nxp(&fgListOfManagers);
      TObject *o = 0;
      Int_t nm = 0;
      while ((o = nxp())) {
         if (!(gROOT->GetListOfProofs()->FindObject(o))) {
            fgListOfManagers.Remove(o);
         } else {
            TVirtualProofMgr *p = (TVirtualProofMgr *)o;
            Printf("// #%d: \"%s\" (%s)", ++nm, p->GetName(), p->GetTitle());
         }
      }
   } else {
      if (gDebug > 0)
         Printf("No managers found");
   }

   // We are done
   return &fgListOfManagers;
}

//______________________________________________________________________________
TVirtualProofMgr *TVirtualProofMgr::Create(const char *url, Int_t loglevel,
                                           const char *alias, Bool_t xpd)
{
   // Static method returning the appropriate TProofMgr object using
   // the plugin manager.
   TVirtualProofMgr *m= 0;

   // Make sure we do not have already a manager for this URL
   TList *lm = TVirtualProofMgr::GetListOfManagers();
   if (lm) {
      TIter nxm(lm);
      while ((m = (TVirtualProofMgr *)nxm()))
         if (m->MatchUrl(url))
            if (m->IsValid()) {
               return m;
            } else {
               fgListOfManagers.Remove(m);
               SafeDelete(m);
               break;
            }
   }

   m = 0;
   Bool_t trystd = kTRUE;

   // If required, we assume first that the remote server is based on XrdProofd
   if (xpd) {
      TVirtualProofMgr_t cm = TVirtualProofMgr::GetProofMgrHook("xpd");
      if (cm) {
         m = (TVirtualProofMgr *) (*cm)(url, loglevel, alias);
         // Update trystd flag
         trystd = (m && !(m->IsValid()) && m->IsProofd()) ? kTRUE : kFALSE;
      }
   }

   // If the first attempt failed, we instantiate an old interface
   if (trystd) {
      SafeDelete(m);
      TVirtualProofMgr_t cm = TVirtualProofMgr::GetProofMgrHook("std");
      if (cm)
         m = (TVirtualProofMgr *) (*cm)(url, loglevel, alias);
   }

   // Record the new manager, if any
   if (m) {
      fgListOfManagers.Add(m);
      if (m->IsValid() && !(m->IsProofd())) {
         R__LOCKGUARD2(gROOTMutex);
         gROOT->GetListOfProofs()->Add(m);
         gROOT->GetListOfSockets()->Add(m);
      }
   }

   // We are done
   return m;
}

//________________________________________________________________________
TVirtualProofMgr_t TVirtualProofMgr::GetProofMgrHook(const char *type)
{
   // Get the specified constructor hook.
   // We do this without the plugin manager because it blocks the
   // CINT mutex breaking the parallel startup.

   static const char *libs[] = { "/libProof", "/libProofx" };

   // Find index (default: classic)
   Int_t idx = (type && !strncmp(type,"xpd",3)) ? 1 : 0;

   if (!fgTProofMgrHook[idx]) {
      // Load the appropriate library ...
#ifdef ROOTLIBDIR
      TString prooflib = TString(ROOTLIBDIR);
#else
#ifndef WIN32
      TString prooflib = TString(gRootDir) + "/lib";
#else
      TString prooflib = TString(gRootDir) + "/bin";
#endif
#endif
      prooflib += libs[idx];
      char *p = 0;
      if ((p = gSystem->DynamicPathName(prooflib, kTRUE))) {
         delete[] p;
         if (gSystem->Load(prooflib) == -1)
            ::Error("TVirtualProofMgr::GetProofMgrCtor",
                       "can't load %s", prooflib.Data());
      } else
         ::Error("TVirtualProofMgr::GetProofMgrCtor",
                 "can't locate %s", prooflib.Data());
   }

   // Done
   return fgTProofMgrHook[idx];
}

//_____________________________________________________________________________
void TVirtualProofMgr::SetTProofMgrHook(TVirtualProofMgr_t pmh, const char *t)
{
   // Set hook to TProofMgr ctor

   // Find index (default: classic)
   Int_t idx = (t && !strncmp(t,"xpd",3)) ? 1 : 0;

   fgTProofMgrHook[idx] = pmh;
}

ClassImp(TVirtualProofDesc)

//________________________________________________________________________
void TVirtualProofDesc::Print(Option_t *) const
{
   // Dump the content to the screen.
   const char *st[] = { "unknown", "idle", "processsing", "shutting down"};

   Printf("// # %d", fLocalId);
   Printf("// alias: %s, url: \"%s\"", GetTitle(), GetUrl());
   Printf("// tag: %s", GetName());
   Printf("// status: %s, attached: %s (remote ID: %d)",
          st[fStatus+1], (fProof ? "YES" : "NO"), fRemoteId);
}
<commit_msg>Fix coding convention violation<commit_after>// @(#)root/base:$Name:  $:$Id: TVirtualProofMgr.cxx,v 1.8 2006/06/21 16:18:26 rdm Exp $
// Author: G. Ganis, Nov 2005

/*************************************************************************
 * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TVirtualProofMgr                                                     //
//                                                                      //
// Abstract interface to the manager for PROOF sessions.                //
// The PROOF manager interacts with the PROOF server coordinator to     //
// create or destroy a PROOF session, attach to or detach from          //
// existing one, and to monitor any client activity on the cluster.     //
// At most one manager instance per server is allowed.                  //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#ifdef HAVE_CONFIG
#include "config.h"
#endif
#include "TError.h"
#include "TInetAddress.h"
#include "TList.h"
#include "TROOT.h"
#include "TSystem.h"
#include "TVirtualMutex.h"
#include "TVirtualProof.h"
#include "TVirtualProofMgr.h"

ClassImp(TVirtualProofMgr)

// Sub-list of TROOT::fProofs with managers
TList TVirtualProofMgr::fgListOfManagers;
TVirtualProofMgr_t TVirtualProofMgr::fgTProofMgrHook[2] = { 0, 0 };

//______________________________________________________________________________
TVirtualProofMgr::TVirtualProofMgr(const char *url, Int_t, const char *)
                 : TNamed("",""), fRemoteProtocol(-1),
                   fServType(kXProofd), fSessions(0)
{
   // Constructor

   // AVoid problems with empty URLs
   fUrl = (!url || strlen(url) <= 0) ? TUrl("proof://localhost") : TUrl(url);
}

//______________________________________________________________________________
TVirtualProofMgr::~TVirtualProofMgr()
{
   // Destroy a TVirtualProofMgr instance

   SafeDelete(fSessions);

   fgListOfManagers.Remove(this);
   gROOT->GetListOfProofs()->Remove(this);
}

//______________________________________________________________________________
void TVirtualProofMgr::ShowWorkers()
{
   // Show available workers

   AbstractMethod("ShowWorkers");
}

//______________________________________________________________________________
TVirtualProofDesc *TVirtualProofMgr::GetProofDesc(Int_t id)
{
   // Get TVirtualProof instance corresponding to 'id'.

   if (id > 0) {
      TVirtualProofDesc *d = 0;
      // Retrieve an updated list
      QuerySessions("");
      if (fSessions) {
         TIter nxd(fSessions);
         while ((d = (TVirtualProofDesc *)nxd())) {
            if (d->MatchId(id))
               return d;
         }
      }
   }

   return 0;
}

//______________________________________________________________________________
void TVirtualProofMgr::ShutdownSession(TVirtualProof *p)
{
   // Discard PROOF session 'p'

   if (p) {
      TVirtualProofDesc *d = 0;
      if (fSessions) {
         TIter nxd(fSessions);
         while ((d = (TVirtualProofDesc *)nxd())) {
            if (p == d->GetProof()) {
               fSessions->Remove(d);
               delete d;
               break;
            }
         }
      }
   }
}

//______________________________________________________________________________
TVirtualProof *TVirtualProofMgr::CreateSession(const char *cfg,
                                               const char *cfgdir, Int_t loglevel)
{
   // Create a new remote session (master and associated workers).

   // Create
   if (IsProofd())
      fUrl.SetOptions("std");

   TProof_t proofhook = TVirtualProof::GetTProofHook();
   if (!proofhook) {

      // Load the library containing TProof ...
#ifdef ROOTLIBDIR
      TString prooflib = TString(ROOTLIBDIR) + "/libProof";
#else
#ifndef WIN32
      TString prooflib = TString(gRootDir) + "/lib/libProof";
#else
      TString prooflib = TString(gRootDir) + "/bin/libProof";
#endif
#endif
      char *p = 0;
      if ((p = gSystem->DynamicPathName(prooflib, kTRUE))) {
         delete[] p;
         if (gSystem->Load(prooflib) == -1)
            Error("CreateSession", "can't load %s", prooflib.Data());
         proofhook = TVirtualProof::GetTProofHook();
      } else
         Error("CreateSession", "can't locate %s", prooflib.Data());
   }
   if (!proofhook) {
      Error("CreateSession", "hook for TVirtualProof could not be loaded");
      return 0;
   }
   // Create the instance
   TVirtualProof *p =
     (TVirtualProof*) (*proofhook)(fUrl.GetUrl(), cfg, cfgdir, loglevel, 0);

   if (p && p->IsValid()) {

      // Set reference manager
      p->SetManager(this);

      // Save record about this session
      Int_t ns = 1;
      if (fSessions) {
         // To avoid ambiguities in case of removal of some elements
         if (fSessions->Last())
            ns = ((TVirtualProofDesc *)(fSessions->Last()))->GetLocalId() + 1;
      } else {
         // Create the list
         fSessions = new TList;
      }

      // Create the description class
      Int_t st = (p->IsIdle()) ? TVirtualProofDesc::kIdle : TVirtualProofDesc::kRunning ;
      TVirtualProofDesc *d =
         new TVirtualProofDesc(p->GetName(), p->GetTitle(), p->GetUrl(),
                               ns, p->GetSessionID(), st, p);
      fSessions->Add(d);

   } else {
      // Session creation failed
      Error("CreateSession", "creating PROOF session");
      SafeDelete(p);
   }

   // We are done
   return p;
}

//______________________________________________________________________________
Bool_t TVirtualProofMgr::MatchUrl(const char *url)
{
   // Checks if 'url' refers to the same 'user@host:port' entity as the URL
   // in memory

   TUrl u(url);

   // Correct URL protocol
   if (!strcmp(u.GetProtocol(), TUrl("a").GetProtocol()))
      u.SetProtocol("proof");

   // Correct port
   if (u.GetPort() == TUrl("a").GetPort()) {
      Int_t port = gSystem->GetServiceByName("rootd");
      if (port < 0)
         port = 1094;
      u.SetPort(port);
   }

   // Now we can check
   if (!strcmp(u.GetHostFQDN(), fUrl.GetHostFQDN()))
      if (u.GetPort() == fUrl.GetPort())
         if (strlen(u.GetUser()) <= 0 || !strcmp(u.GetUser(),fUrl.GetUser()))
            return kTRUE;

   // Match failed
   return kFALSE;
}

//________________________________________________________________________
TList *TVirtualProofMgr::GetListOfManagers()
{
   // Extract pointers to PROOF managers from TROOT::fProofs.

   // Update the list with new entries
   if (gROOT->GetListOfProofs()) {
      TIter nxp(gROOT->GetListOfProofs());
      TVirtualProofMgr *p = 0;
      while ((p = dynamic_cast<TVirtualProofMgr *> (nxp())))
         if (!fgListOfManagers.FindObject(p))
            fgListOfManagers.Add(p);
   }

   // Get rid of invalid entries and notify
   if (fgListOfManagers.GetSize() > 0) {
      TIter nxp(&fgListOfManagers);
      TObject *o = 0;
      Int_t nm = 0;
      while ((o = nxp())) {
         if (!(gROOT->GetListOfProofs()->FindObject(o))) {
            fgListOfManagers.Remove(o);
         } else {
            TVirtualProofMgr *p = (TVirtualProofMgr *)o;
            Printf("// #%d: \"%s\" (%s)", ++nm, p->GetName(), p->GetTitle());
         }
      }
   } else {
      if (gDebug > 0)
         Printf("No managers found");
   }

   // We are done
   return &fgListOfManagers;
}

//______________________________________________________________________________
TVirtualProofMgr *TVirtualProofMgr::Create(const char *url, Int_t loglevel,
                                           const char *alias, Bool_t xpd)
{
   // Static method returning the appropriate TProofMgr object using
   // the plugin manager.
   TVirtualProofMgr *m= 0;

   // Make sure we do not have already a manager for this URL
   TList *lm = TVirtualProofMgr::GetListOfManagers();
   if (lm) {
      TIter nxm(lm);
      while ((m = (TVirtualProofMgr *)nxm()))
         if (m->MatchUrl(url))
            if (m->IsValid()) {
               return m;
            } else {
               fgListOfManagers.Remove(m);
               SafeDelete(m);
               break;
            }
   }

   m = 0;
   Bool_t trystd = kTRUE;

   // If required, we assume first that the remote server is based on XrdProofd
   if (xpd) {
      TVirtualProofMgr_t cm = TVirtualProofMgr::GetProofMgrHook("xpd");
      if (cm) {
         m = (TVirtualProofMgr *) (*cm)(url, loglevel, alias);
         // Update trystd flag
         trystd = (m && !(m->IsValid()) && m->IsProofd()) ? kTRUE : kFALSE;
      }
   }

   // If the first attempt failed, we instantiate an old interface
   if (trystd) {
      SafeDelete(m);
      TVirtualProofMgr_t cm = TVirtualProofMgr::GetProofMgrHook("std");
      if (cm)
         m = (TVirtualProofMgr *) (*cm)(url, loglevel, alias);
   }

   // Record the new manager, if any
   if (m) {
      fgListOfManagers.Add(m);
      if (m->IsValid() && !(m->IsProofd())) {
         R__LOCKGUARD2(gROOTMutex);
         gROOT->GetListOfProofs()->Add(m);
         gROOT->GetListOfSockets()->Add(m);
      }
   }

   // We are done
   return m;
}

//________________________________________________________________________
TVirtualProofMgr_t TVirtualProofMgr::GetProofMgrHook(const char *type)
{
   // Get the specified constructor hook.
   // We do this without the plugin manager because it blocks the
   // CINT mutex breaking the parallel startup.

   static const char *libs[] = { "/libProof", "/libProofx" };

   // Find index (default: classic)
   Int_t idx = (type && !strncmp(type,"xpd",3)) ? 1 : 0;

   if (!fgTProofMgrHook[idx]) {
      // Load the appropriate library ...
#ifdef ROOTLIBDIR
      TString prooflib = TString(ROOTLIBDIR);
#else
#ifndef WIN32
      TString prooflib = TString(gRootDir) + "/lib";
#else
      TString prooflib = TString(gRootDir) + "/bin";
#endif
#endif
      prooflib += libs[idx];
      char *p = 0;
      if ((p = gSystem->DynamicPathName(prooflib, kTRUE))) {
         delete[] p;
         if (gSystem->Load(prooflib) == -1)
            ::Error("TVirtualProofMgr::GetProofMgrCtor",
                       "can't load %s", prooflib.Data());
      } else
         ::Error("TVirtualProofMgr::GetProofMgrCtor",
                 "can't locate %s", prooflib.Data());
   }

   // Done
   return fgTProofMgrHook[idx];
}

//_____________________________________________________________________________
void TVirtualProofMgr::SetTProofMgrHook(TVirtualProofMgr_t pmh, const char *t)
{
   // Set hook to TProofMgr ctor

   // Find index (default: classic)
   Int_t idx = (t && !strncmp(t,"xpd",3)) ? 1 : 0;

   fgTProofMgrHook[idx] = pmh;
}

ClassImp(TVirtualProofDesc)

//________________________________________________________________________
void TVirtualProofDesc::Print(Option_t *) const
{
   // Dump the content to the screen.
   const char *st[] = { "unknown", "idle", "processsing", "shutting down"};

   Printf("// # %d", fLocalId);
   Printf("// alias: %s, url: \"%s\"", GetTitle(), GetUrl());
   Printf("// tag: %s", GetName());
   Printf("// status: %s, attached: %s (remote ID: %d)",st[fStatus+1], (fProof ? "YES" : "NO"), fRemoteId);
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief client connection
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2013 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "ClientConnection.h"

#ifdef TRI_HAVE_LINUX_SOCKETS
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <sys/socket.h>
#endif

#ifdef TRI_HAVE_WINSOCK2_H
#include <WinSock2.h>
#include <WS2tcpip.h>
#endif

#include <sys/types.h>

using namespace triagens::basics;
using namespace triagens::httpclient;
using namespace triagens::rest;
using namespace std;

// -----------------------------------------------------------------------------
// --SECTION--                                        constructors / destructors
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup httpclient
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief creates a new client connection
////////////////////////////////////////////////////////////////////////////////

ClientConnection::ClientConnection (Endpoint* endpoint,
                                    double requestTimeout,
                                    double connectTimeout,
                                    size_t connectRetries) :
  GeneralClientConnection(endpoint, requestTimeout, connectTimeout, connectRetries) {
}

////////////////////////////////////////////////////////////////////////////////
/// @brief destroys a client connection
////////////////////////////////////////////////////////////////////////////////

ClientConnection::~ClientConnection () {
  disconnect();
}

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

// -----------------------------------------------------------------------------
// --SECTION--                                                   private methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup httpclient
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief check whether the socket is still alive
////////////////////////////////////////////////////////////////////////////////

bool ClientConnection::checkSocket () {
  int so_error = -1;
  socklen_t len = sizeof so_error;

  assert(TRI_isvalidsocket(_socket));

  int res = TRI_getsockopt(_socket, SOL_SOCKET, SO_ERROR, (void*)(&so_error), &len);

  if (res != TRI_ERROR_NO_ERROR) {
    TRI_set_errno(errno);
    _isConnected = false;
    return false;
  }

  if (so_error == 0) {
    return true;
  }

  TRI_set_errno(so_error);
  _isConnected = false;

  return false;
}

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

// -----------------------------------------------------------------------------
// --SECTION--                                         protected virtual methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup httpclient
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief connect
////////////////////////////////////////////////////////////////////////////////

bool ClientConnection::connectSocket () {
  assert(_endpoint != 0);

  if (_endpoint->isConnected()) {
    _endpoint->disconnect();
  }
  _socket = _endpoint->connect(_connectTimeout, _requestTimeout);

  if (!TRI_isvalidsocket(_socket)) {
    return false;
  }

  if (checkSocket()) {
    return _endpoint->isConnected();
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief disconnect
////////////////////////////////////////////////////////////////////////////////

void ClientConnection::disconnectSocket () {
  if (_endpoint) {
    _endpoint->disconnect();
  }
  TRI_invalidatesocket(&_socket);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief prepare connection for read/write I/O
////////////////////////////////////////////////////////////////////////////////

bool ClientConnection::prepare (const double timeout, const bool isWrite) const {
  struct timeval tv;
  fd_set fdset;

  assert(TRI_isvalidsocket(_socket));

  tv.tv_sec = (long) timeout;
  tv.tv_usec = ((long) (timeout * 1000000.0)) % 1000000;

  FD_ZERO(&fdset);
  FD_SET(TRI_get_fd_or_handle_of_socket(_socket), &fdset);

  fd_set* readFds = NULL;
  fd_set* writeFds = NULL;

  if (isWrite) {
    writeFds = &fdset;
  }
  else {
    readFds = &fdset;
  }

  int sockn = (int) (TRI_get_fd_or_handle_of_socket(_socket) + 1);
  int res = select(sockn, readFds, writeFds, NULL, &tv);

  if (res > 0) {
    return true;
  }

  if (res == 0) {
    if (isWrite) {
      TRI_set_errno(TRI_SIMPLE_CLIENT_COULD_NOT_WRITE);
    }
    else {
      TRI_set_errno(TRI_SIMPLE_CLIENT_COULD_NOT_READ);
    }
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief write data to the connection
////////////////////////////////////////////////////////////////////////////////

bool ClientConnection::writeClientConnection (void* buffer, size_t length, size_t* bytesWritten) {
  if (! checkSocket()) {
    return false;
  }

#if defined(__APPLE__)
  // MSG_NOSIGNAL not supported on apple platform
  int status = TRI_send(_socket, buffer, length, 0);
#elif defined(_WIN32)
  // MSG_NOSIGNAL not supported on windows platform
  int status = TRI_send(_socket, buffer, length, 0);
#else
  int status = TRI_send(_socket, buffer, length, MSG_NOSIGNAL);
#endif

  if (status < 0) {
    TRI_set_errno(errno);
    return false;
  }

  *bytesWritten = (size_t) status;

  return true;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief read data from the connection
////////////////////////////////////////////////////////////////////////////////

bool ClientConnection::readClientConnection (StringBuffer& stringBuffer) {
  if (! checkSocket()) {
    return false;
  }

  assert(TRI_isvalidsocket(_socket));

  do {
    // reserve some memory for reading
    if (stringBuffer.reserve(READBUFFER_SIZE) == TRI_ERROR_OUT_OF_MEMORY) {
      // out of memory
      TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
      return false;
    }

    int lenRead = TRI_READ_SOCKET(_socket, stringBuffer.end(), READBUFFER_SIZE - 1, 0);

    if (lenRead == -1) {
      // error occurred
      return false;
    }

    if (lenRead == 0) {
      // nothing more to read
      _isConnected = false;
      break;
    }

    stringBuffer.increaseLength(lenRead);
  }
  while (readable());

  return true;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief return whether the connection is readable
////////////////////////////////////////////////////////////////////////////////

bool ClientConnection::readable () {
  if (prepare(0.0, false)) {
    return checkSocket();
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

<commit_msg>Fix a deadlock situation in the SimpleHttpClient if the server dies.<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief client connection
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2013 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "ClientConnection.h"

#ifdef TRI_HAVE_LINUX_SOCKETS
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <sys/socket.h>
#endif

#ifdef TRI_HAVE_WINSOCK2_H
#include <WinSock2.h>
#include <WS2tcpip.h>
#endif

#include <sys/types.h>

using namespace triagens::basics;
using namespace triagens::httpclient;
using namespace triagens::rest;
using namespace std;

// -----------------------------------------------------------------------------
// --SECTION--                                        constructors / destructors
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup httpclient
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief creates a new client connection
////////////////////////////////////////////////////////////////////////////////

ClientConnection::ClientConnection (Endpoint* endpoint,
                                    double requestTimeout,
                                    double connectTimeout,
                                    size_t connectRetries) :
  GeneralClientConnection(endpoint, requestTimeout, connectTimeout, connectRetries) {
}

////////////////////////////////////////////////////////////////////////////////
/// @brief destroys a client connection
////////////////////////////////////////////////////////////////////////////////

ClientConnection::~ClientConnection () {
  disconnect();
}

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

// -----------------------------------------------------------------------------
// --SECTION--                                                   private methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup httpclient
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief check whether the socket is still alive
////////////////////////////////////////////////////////////////////////////////

bool ClientConnection::checkSocket () {
  int so_error = -1;
  socklen_t len = sizeof so_error;

  assert(TRI_isvalidsocket(_socket));

  int res = TRI_getsockopt(_socket, SOL_SOCKET, SO_ERROR, (void*)(&so_error), &len);

  if (res != TRI_ERROR_NO_ERROR) {
    TRI_set_errno(errno);
    _isConnected = false;
    return false;
  }

  if (so_error == 0) {
    return true;
  }

  TRI_set_errno(so_error);
  _isConnected = false;

  return false;
}

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

// -----------------------------------------------------------------------------
// --SECTION--                                         protected virtual methods
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup httpclient
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief connect
////////////////////////////////////////////////////////////////////////////////

bool ClientConnection::connectSocket () {
  assert(_endpoint != 0);

  if (_endpoint->isConnected()) {
    _endpoint->disconnect();
  }
  _socket = _endpoint->connect(_connectTimeout, _requestTimeout);

  if (!TRI_isvalidsocket(_socket)) {
    return false;
  }

  if (checkSocket()) {
    return _endpoint->isConnected();
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief disconnect
////////////////////////////////////////////////////////////////////////////////

void ClientConnection::disconnectSocket () {
  if (_endpoint) {
    _endpoint->disconnect();
  }
  TRI_invalidatesocket(&_socket);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief prepare connection for read/write I/O
////////////////////////////////////////////////////////////////////////////////

bool ClientConnection::prepare (const double timeout, const bool isWrite) const {
  struct timeval tv;
  fd_set fdset;

  assert(TRI_isvalidsocket(_socket));

  tv.tv_sec = (long) timeout;
  tv.tv_usec = ((long) (timeout * 1000000.0)) % 1000000;

  FD_ZERO(&fdset);
  FD_SET(TRI_get_fd_or_handle_of_socket(_socket), &fdset);

  fd_set* readFds = NULL;
  fd_set* writeFds = NULL;

  if (isWrite) {
    writeFds = &fdset;
  }
  else {
    readFds = &fdset;
  }

  int sockn = (int) (TRI_get_fd_or_handle_of_socket(_socket) + 1);
  int res = select(sockn, readFds, writeFds, NULL, &tv);

  if (res > 0) {
    return true;
  }

  if (res == 0) {
    if (isWrite) {
      TRI_set_errno(TRI_SIMPLE_CLIENT_COULD_NOT_WRITE);
    }
    else {
      TRI_set_errno(TRI_SIMPLE_CLIENT_COULD_NOT_READ);
    }
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief write data to the connection
////////////////////////////////////////////////////////////////////////////////

bool ClientConnection::writeClientConnection (void* buffer, size_t length, size_t* bytesWritten) {
  if (! checkSocket()) {
    return false;
  }

#if defined(__APPLE__)
  // MSG_NOSIGNAL not supported on apple platform
  int status = TRI_send(_socket, buffer, length, 0);
#elif defined(_WIN32)
  // MSG_NOSIGNAL not supported on windows platform
  int status = TRI_send(_socket, buffer, length, 0);
#else
  int status = TRI_send(_socket, buffer, length, MSG_NOSIGNAL);
#endif

  if (status < 0) {
    TRI_set_errno(errno);
    return false;
  }

  *bytesWritten = (size_t) status;

  return true;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief read data from the connection
////////////////////////////////////////////////////////////////////////////////

bool ClientConnection::readClientConnection (StringBuffer& stringBuffer) {
  if (! checkSocket()) {
    return false;
  }

  assert(TRI_isvalidsocket(_socket));

  do {
    // reserve some memory for reading
    if (stringBuffer.reserve(READBUFFER_SIZE) == TRI_ERROR_OUT_OF_MEMORY) {
      // out of memory
      TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
      return false;
    }

    int lenRead = TRI_READ_SOCKET(_socket, stringBuffer.end(), READBUFFER_SIZE - 1, 0);

    if (lenRead == -1) {
      // error occurred
      return false;
    }

    if (lenRead == 0) {
      // nothing more to read
      // since we come from a call to select which indicated that there
      // is something to read and we are reading from a socket, this is
      // an error condition. Therefore we return false
      _isConnected = false;
      return false;
    }

    stringBuffer.increaseLength(lenRead);
  }
  while (readable());

  return true;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief return whether the connection is readable
////////////////////////////////////////////////////////////////////////////////

bool ClientConnection::readable () {
  if (prepare(0.0, false)) {
    return checkSocket();
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

<|endoftext|>


<commit_before>/***********************************************************************
 cpool.cpp - Implements the ConnectionPool class.

 Copyright (c) 2007 by Educational Technology Resources, Inc. and
 (c) 2007 by Jonathan Wakely.  Others may also hold copyrights on
 code in this file.  See the CREDITS file in the top directory of
 the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ 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.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cpool.h"

#include "connection.h"

#include <algorithm>
#include <functional>

namespace mysqlpp {

/// \brief Functor to test whether a given ConnectionInfo object is
/// "too old".
///
/// This is a template only because ConnectionInfo is private.  Making
/// it a template means the private type is only used at the point of
/// instantiation, where it is accessible.

template <typename ConnInfoT>
class TooOld : std::unary_function<ConnInfoT, bool>
{
public:
	TooOld(unsigned int tmax) :
	min_age_(time(0) - tmax)
	{
	}

	bool operator()(const ConnInfoT& conn_info) const
	{
		return !conn_info.in_use && conn_info.last_used <= min_age_;
	}

private:
	time_t min_age_;
};

//// clear /////////////////////////////////////////////////////////////
// Destroy all connections in the pool and drain pool.

void
ConnectionPool::clear()
{
	ScopedLock lock(mutex_);	// ensure we're not interfered with

	for (PoolIt it = pool_.begin(); it != pool_.end(); ++it) {
		destroy(it->conn);
	}
	pool_.clear();
}

//// find_mru //////////////////////////////////////////////////////////
// Find most recently used available connection.  Uses operator< for
// ConnectionInfo to order pool with MRU connection last.  Returns 0 if
// there are no connections not in use.

Connection*
ConnectionPool::find_mru()
{
	PoolIt mru = std::max_element(pool_.begin(), pool_.end());
	if (mru != pool_.end() && !mru->in_use) {
		mru->in_use = true;
		return mru->conn;
	}
	else {
		return 0;
	}
}

//// grab //////////////////////////////////////////////////////////////

Connection*
ConnectionPool::grab()
{
	ScopedLock lock(mutex_);	// ensure we're not interfered with
	remove_old_connections();
	if (Connection* mru = find_mru()) {
		return mru;
	}
	else {
		// No free connections, so create and return a new one.
		pool_.push_back(ConnectionInfo(create()));
		return pool_.back().conn;
	}
}

//// release ///////////////////////////////////////////////////////////

void
ConnectionPool::release(const Connection* pc)
{
	ScopedLock lock(mutex_);	// ensure we're not interfered with

	for (PoolIt it = pool_.begin(); it != pool_.end(); ++it) {
		if (it->conn == pc) {
			it->in_use = false;
			it->last_used = time(0);
			break;
		}
	}
}

//// remove_old_connections ////////////////////////////////////////////
// Remove connections that were last used too long ago.

void
ConnectionPool::remove_old_connections()
{
	PoolIt it = pool_.begin(), doomed;
	TooOld<ConnectionInfo> too_old(max_idle_time());

	while ((it = std::find_if(it, pool_.end(), too_old)) != pool_.end()) {
		doomed = it++;
		destroy(doomed->conn);
		pool_.erase(doomed);
	}
}

} // end namespace mysqlpp

<commit_msg>Small improvement, reverting a change I made to Jonathan's cpool work to make it more paranoid, which isn't actually an improvement.<commit_after>/***********************************************************************
 cpool.cpp - Implements the ConnectionPool class.

 Copyright (c) 2007 by Educational Technology Resources, Inc. and
 (c) 2007 by Jonathan Wakely.  Others may also hold copyrights on
 code in this file.  See the CREDITS file in the top directory of
 the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ 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.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cpool.h"

#include "connection.h"

#include <algorithm>
#include <functional>

namespace mysqlpp {

/// \brief Functor to test whether a given ConnectionInfo object is
/// "too old".
///
/// This is a template only because ConnectionInfo is private.  Making
/// it a template means the private type is only used at the point of
/// instantiation, where it is accessible.

template <typename ConnInfoT>
class TooOld : std::unary_function<ConnInfoT, bool>
{
public:
	TooOld(unsigned int tmax) :
	min_age_(time(0) - tmax)
	{
	}

	bool operator()(const ConnInfoT& conn_info) const
	{
		return !conn_info.in_use && conn_info.last_used <= min_age_;
	}

private:
	time_t min_age_;
};

//// clear /////////////////////////////////////////////////////////////
// Destroy all connections in the pool and drain pool.

void
ConnectionPool::clear()
{
	ScopedLock lock(mutex_);	// ensure we're not interfered with

	for (PoolIt it = pool_.begin(); it != pool_.end(); ++it) {
		destroy(it->conn);
	}
	pool_.clear();
}

//// find_mru //////////////////////////////////////////////////////////
// Find most recently used available connection.  Uses operator< for
// ConnectionInfo to order pool with MRU connection last.  Returns 0 if
// there are no connections not in use.

Connection*
ConnectionPool::find_mru()
{
	PoolIt mru = std::max_element(pool_.begin(), pool_.end());
	if (mru != pool_.end() && !mru->in_use) {
		mru->in_use = true;
		return mru->conn;
	}
	else {
		return 0;
	}
}

//// grab //////////////////////////////////////////////////////////////

Connection*
ConnectionPool::grab()
{
	ScopedLock lock(mutex_);	// ensure we're not interfered with
	remove_old_connections();
	if (Connection* mru = find_mru()) {
		return mru;
	}
	else {
		// No free connections, so create and return a new one.
		pool_.push_back(ConnectionInfo(create()));
		return pool_.back().conn;
	}
}

//// release ///////////////////////////////////////////////////////////

void
ConnectionPool::release(const Connection* pc)
{
	ScopedLock lock(mutex_);	// ensure we're not interfered with

	for (PoolIt it = pool_.begin(); it != pool_.end(); ++it) {
		if (it->conn == pc) {
			it->in_use = false;
			it->last_used = time(0);
			break;
		}
	}
}

//// remove_old_connections ////////////////////////////////////////////
// Remove connections that were last used too long ago.

void
ConnectionPool::remove_old_connections()
{
	TooOld<ConnectionInfo> too_old(max_idle_time());

	PoolIt it = pool_.begin();
	while ((it = std::find_if(it, pool_.end(), too_old)) != pool_.end()) {
		destroy(it->conn);
		pool_.erase(it++);
	}
}

} // end namespace mysqlpp

<|endoftext|>


<commit_before>/**
 * A class which describes the properties of a MySQL database connection.
 *
 * @date                    Jul 21, 2013
 * @author                  Joeri HERMANS
 * @version                 0.1
 *
 * Copyright 2013 Joeri HERMANS
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// BEGIN Includes. ///////////////////////////////////////////////////

// System dependencies.
#include <assert.h>
#include <stdio.h>
#include <syslog.h>

// Application dependencies.
#include <ias/database/interface/database_connection.h>
#include <ias/database/mysql/mysql_connection.h>
#include <ias/database/mysql/mysql_statement.h>
#include <ias/database/mysql/mysql_driver.h>

// END Includes. /////////////////////////////////////////////////////

inline void MySqlConnection::initialize( void ) {
    // Initialize the members of the class.
    mConnection = mysql_init( nullptr );
}

MySqlConnection::MySqlConnection( const std::string & username,
                                  const std::string & password,
                                  const std::string & schema,
                                  const std::string & host )
    : DatabaseConnection(username,password,schema,host) {
    // Nothing to do here.
    initialize();
}

MySqlConnection::~MySqlConnection( void ) {
    mysql_close( mConnection );
    mysql_library_end();
}

bool MySqlConnection::isConnected( void ) const
{
    return ( mConnection != nullptr );
}

bool MySqlConnection::connect( void ) {
    bool connected;
    my_bool argument;

    // Enable automatic reconnection by default.
    argument = 1;
    // Enable the automatic reconnect option.
    mysql_options(mConnection,MYSQL_OPT_RECONNECT,&argument);
    // Try to connect to the MySQL server.
    connected = ( mysql_real_connect(mConnection,
                                     getHost().c_str(),
                                     getUsername().c_str(),
                                     getPassword().c_str(),
                                     getSchema().c_str(),
                                     3306,nullptr,0) != nullptr );

    return ( connected );
}

DatabaseStatement * MySqlConnection::createStatement( const std::string & sql ) {
    DatabaseStatement * statement;

    // Checking the precondition.
    assert( sql.length() > 0 );

    // Check if the connection with the server is still active.
    if( mysql_ping(mConnection) == 0 )
        // Allocate a new mysql statement.
        statement = new MySqlStatement(this,sql);
    else
        // No statement should be allocated.
        statement = nullptr;

    return ( statement );
}

DatabasePreparedStatement * MySqlConnection::prepareStatement(
    const std::string & sql ) {
    // Checking the precondition.
    assert( sql.length() > 0 );

    // TODO Implement.
    return ( nullptr );
}

void * MySqlConnection::getLink( void )
{
    return ( static_cast<void *>(mConnection) );
}
<commit_msg>Test possible bug.<commit_after>/**
 * A class which describes the properties of a MySQL database connection.
 *
 * @date                    Jul 21, 2013
 * @author                  Joeri HERMANS
 * @version                 0.1
 *
 * Copyright 2013 Joeri HERMANS
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// BEGIN Includes. ///////////////////////////////////////////////////

// System dependencies.
#include <assert.h>
#include <stdio.h>
#include <syslog.h>

// Application dependencies.
#include <ias/database/interface/database_connection.h>
#include <ias/database/mysql/mysql_connection.h>
#include <ias/database/mysql/mysql_statement.h>
#include <ias/database/mysql/mysql_driver.h>

// END Includes. /////////////////////////////////////////////////////

inline void MySqlConnection::initialize( void ) {
    // Initialize the members of the class.
    mConnection = mysql_init( nullptr );
}

MySqlConnection::MySqlConnection( const std::string & username,
                                  const std::string & password,
                                  const std::string & schema,
                                  const std::string & host )
    : DatabaseConnection(username,password,schema,host) {
    // Nothing to do here.
    initialize();
}

MySqlConnection::~MySqlConnection( void ) {
    mysql_close( mConnection );
    mysql_library_end();
}

bool MySqlConnection::isConnected( void ) const
{
    return ( mConnection != nullptr );
}

bool MySqlConnection::connect( void ) {
    bool connected;
    my_bool argument;

    // Enable automatic reconnection by default.
    argument = 1;
    // Enable the automatic reconnect option.
    mysql_options(mConnection,MYSQL_OPT_RECONNECT,&argument);
    // Try to connect to the MySQL server.
    connected = ( mysql_real_connect(mConnection,
                                     getHost().c_str(),
                                     getUsername().c_str(),
                                     getPassword().c_str(),
                                     getSchema().c_str(),
                                     3306,nullptr,0) != nullptr );

    return ( connected );
}

DatabaseStatement * MySqlConnection::createStatement( const std::string & sql ) {
    DatabaseStatement * statement;

    // Checking the precondition.
    assert( sql.length() > 0 );

//    // Check if the connection with the server is still active.
//    if( mysql_ping(mConnection) == 0 )
        // Allocate a new mysql statement.
        statement = new MySqlStatement(this,sql);
//    else
        // No statement should be allocated.
//        statement = nullptr;

    return ( statement );
}

DatabasePreparedStatement * MySqlConnection::prepareStatement(
    const std::string & sql ) {
    // Checking the precondition.
    assert( sql.length() > 0 );

    // TODO Implement.
    return ( nullptr );
}

void * MySqlConnection::getLink( void )
{
    return ( static_cast<void *>(mConnection) );
}
<|endoftext|>