<commit_before>/*
**  Copyright (C) 2012 <NAME>
**  See COPYING for the license
*/
#include "servicedirectoryclient.hpp"
#include <qitype/objecttypebuilder.hpp>
#include "servicedirectory_p.hpp"
#include "tcptransportsocket.hpp"

qiLogCategory("qimessaging.servicedirectoryclient");

namespace qi {


  ServiceDirectoryClient::ServiceDirectoryClient()
    : _remoteObject(qi::Message::Service_ServiceDirectory)
    , _addLink(0)
    , _removeLink(0)
  {
    _object = makeDynamicObjectPtr(&_remoteObject, false);
  }

  ServiceDirectoryClient::~ServiceDirectoryClient()
  {
    close();
  }

 void ServiceDirectoryClient::onSDEventConnected(qi::Future<unsigned int> ret,
   qi::Promise<bool> fco, bool isAdd)
 {
   if (fco.future().wait(-1))
     return;
   if (ret.hasError())
   {
     fco.setError(ret.error());
     return;
   }
   if (isAdd)
     _addLink = ret.value();
   else
     _removeLink = ret.value();
   if (_addLink && _removeLink)
   {
     fco.setValue(true);
     connected();
   }
 }

  void ServiceDirectoryClient::onMetaObjectFetched(qi::Future<void> future, qi::Promise<bool> promise) {
    if (future.hasError()) {
      promise.setError(future.error());
      return;
    }
    boost::function<void (unsigned int, std::string)> f;

    f = boost::bind<void>(&ServiceDirectoryClient::onServiceAdded, this, _1, _2);
    qi::Future<unsigned int> fut1 = _object->connect("serviceAdded", f);

    f = boost::bind<void>(&ServiceDirectoryClient::onServiceRemoved, this, _1, _2);
    qi::Future<unsigned int> fut2 = _object->connect("serviceRemoved", f);

    fut1.connect(boost::bind<void>(&ServiceDirectoryClient::onSDEventConnected, this, _1, promise, true));
    fut2.connect(boost::bind<void>(&ServiceDirectoryClient::onSDEventConnected, this, _1, promise, false));
  }

  void ServiceDirectoryClient::onSocketConnected(qi::FutureSync<bool> future, qi::Promise<bool> promise) {
    if (future.hasError()) {
      promise.setError(future.error());
      return;
    }
    if (future.value() == false) {
      promise.setValue(false);
      return;
    }
    qi::Future<void> fut = _remoteObject.fetchMetaObject();
    fut.connect(boost::bind<void>(&ServiceDirectoryClient::onMetaObjectFetched, this, _1, promise));
  }

  //we ensure in that function that connect to all events are already setup when we said we are connect.
  //that way we cant be connected without being fully ready.
  qi::FutureSync<bool> ServiceDirectoryClient::connect(const qi::Url &serviceDirectoryURL) {
    if (isConnected()) {
      qiLogInfo() << "Session is already connected";
      return qi::Future<bool>(false);
    }
    _sdSocket = qi::makeTransportSocket(serviceDirectoryURL.protocol());
    if (!_sdSocket)
      return qi::Future<bool>(false);
    _sdSocketDisconnectedLink = _sdSocket->disconnected.connect(boost::bind<void>(&ServiceDirectoryClient::onSocketDisconnected, this, _1));
    _remoteObject.setTransportSocket(_sdSocket);

    qi::Promise<bool> promise;
    qi::Future<bool> fut = _sdSocket->connect(serviceDirectoryURL);
    fut.connect(boost::bind<void>(&ServiceDirectoryClient::onSocketConnected, this, _1, promise));
    return promise.future();
  }

  static void sharedPtrHolder(TransportSocketPtr ptr)
  {
  }

  qi::FutureSync<void> ServiceDirectoryClient::close() {
    if (!_sdSocket)
      return qi::Future<void>(0);
    qi::Future<void> fut = _sdSocket->disconnect();
    // Hold the socket shared ptr alive until the future returns.
    // otherwise, the destructor will block us until disconnect terminates
    fut.connect(boost::bind(&sharedPtrHolder, _sdSocket));
    _sdSocket->disconnected.disconnect(_sdSocketDisconnectedLink);<commit_msg>ServiceDirectoryClient: Fix shared_ptr loop preventing socket destruction.<commit_after>/*
**  Copyright (C) 2012 <NAME>
**  See COPYING for the license
*/
#include "servicedirectoryclient.hpp"
#include <qitype/objecttypebuilder.hpp>
#include "servicedirectory_p.hpp"
#include "tcptransportsocket.hpp"

qiLogCategory("qimessaging.servicedirectoryclient");

namespace qi {


  ServiceDirectoryClient::ServiceDirectoryClient()
    : _remoteObject(qi::Message::Service_ServiceDirectory)
    , _addLink(0)
    , _removeLink(0)
  {
    _object = makeDynamicObjectPtr(&_remoteObject, false);
  }

  ServiceDirectoryClient::~ServiceDirectoryClient()
  {
    close();
  }

 void ServiceDirectoryClient::onSDEventConnected(qi::Future<unsigned int> ret,
   qi::Promise<bool> fco, bool isAdd)
 {
   if (fco.future().wait(-1))
     return;
   if (ret.hasError())
   {
     fco.setError(ret.error());
     return;
   }
   if (isAdd)
     _addLink = ret.value();
   else
     _removeLink = ret.value();
   if (_addLink && _removeLink)
   {
     fco.setValue(true);
     connected();
   }
 }

  void ServiceDirectoryClient::onMetaObjectFetched(qi::Future<void> future, qi::Promise<bool> promise) {
    if (future.hasError()) {
      promise.setError(future.error());
      return;
    }
    boost::function<void (unsigned int, std::string)> f;

    f = boost::bind<void>(&ServiceDirectoryClient::onServiceAdded, this, _1, _2);
    qi::Future<unsigned int> fut1 = _object->connect("serviceAdded", f);

    f = boost::bind<void>(&ServiceDirectoryClient::onServiceRemoved, this, _1, _2);
    qi::Future<unsigned int> fut2 = _object->connect("serviceRemoved", f);

    fut1.connect(boost::bind<void>(&ServiceDirectoryClient::onSDEventConnected, this, _1, promise, true));
    fut2.connect(boost::bind<void>(&ServiceDirectoryClient::onSDEventConnected, this, _1, promise, false));
  }

  void ServiceDirectoryClient::onSocketConnected(qi::FutureSync<bool> future, qi::Promise<bool> promise) {
    if (future.hasError()) {
      promise.setError(future.error());
      return;
    }
    if (future.value() == false) {
      promise.setValue(false);
      return;
    }
    qi::Future<void> fut = _remoteObject.fetchMetaObject();
    fut.connect(boost::bind<void>(&ServiceDirectoryClient::onMetaObjectFetched, this, _1, promise));
  }

  //we ensure in that function that connect to all events are already setup when we said we are connect.
  //that way we cant be connected without being fully ready.
  qi::FutureSync<bool> ServiceDirectoryClient::connect(const qi::Url &serviceDirectoryURL) {
    if (isConnected()) {
      qiLogInfo() << "Session is already connected";
      return qi::Future<bool>(false);
    }
    _sdSocket = qi::makeTransportSocket(serviceDirectoryURL.protocol());
    if (!_sdSocket)
      return qi::Future<bool>(false);
    _sdSocketDisconnectedLink = _sdSocket->disconnected.connect(boost::bind<void>(&ServiceDirectoryClient::onSocketDisconnected, this, _1));
    _remoteObject.setTransportSocket(_sdSocket);

    qi::Promise<bool> promise;
    qi::Future<bool> fut = _sdSocket->connect(serviceDirectoryURL);
    fut.connect(boost::bind<void>(&ServiceDirectoryClient::onSocketConnected, this, _1, promise));
    return promise.future();
  }

  static void sharedPtrHolder(TransportSocketPtr* ptr)
  {
    delete ptr;
  }

  qi::FutureSync<void> ServiceDirectoryClient::close() {
    if (!_sdSocket)
      return qi::Future<void>(0);
    qi::Future<void> fut = _sdSocket->disconnect();
    // Hold the socket shared ptr alive until the future returns.
    // otherwise, the destructor will block us until disconnect terminates
    // Nasty glitch: socket is reusing promises, so this future hook will stay
    // So pass shared pointer by pointer: that way a single delete statement
    // will end all copies.
    fut.connect(boost::bind(&sharedPtrHolder, new TransportSocketPtr(_sdSocket)));
    _sdSocket->disconnected.disconnect(_sdSocketDisconnectedLink);
{'fraction_non_alphanumeric': 0.13471095997907404, 'fraction_numerical': 0.005493068270991368, 'mean_word_length': 4.61041819515774, 'pattern_counts': {'":': 0, '<': 61, '<?xml version=': 0, '>': 69, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '643331', 'n_tokens_mistral': 2376, 'n_tokens_neox': 2327, 'n_words': 478}