<commit_before>#include <arpc.h>
#include <../devel/rpclib.h>
#include <comm.h>

#include <dhash_prot.h>
#include <locationtable.h>
#include <location.h>
#include <merkle_tree.h>
#include <merkle_syncer.h>

#include <syncer.h>

static int sync_trace (getenv ("SYNC_TRACE") ? atoi (getenv ("SYNC_TRACE")) : 0);

syncer::syncer (ptr<locationtable> locations,
		ptr<location> h,
		str dbpath,
		str dbname,
		dhash_ctype ctype,
		u_int dfrags, u_int efrags)
  : locations (locations), ctype (ctype), dfrags (dfrags), efrags (efrags),
    tmptree (NULL), host_loc (h),
    db (New refcounted<adb> (dbpath, dbname)),
    cur_succ (0),
    replica_timer (300)
{

  warn << "new syncer: \n"
       << "   dbpath: " << dbpath << "\n"
       << "    dbext: " << dbname << "\n"
       << "    ctype: " << ctype << "\n"
       << " d/efrags: " << dfrags << "/" << efrags << "\n";

  locations->insert (h);
  locations->pin (h->id ());

  if (sync_trace >= 10)
    replica_timer = sync_trace;

  // Initially randomize a little.
  int delay = random_getword () % replica_timer;
  delaycb (delay, wrap(this, &syncer::sync_replicas));
}

syncer::~syncer ()
{
  delete tmptree;
  tmptree = NULL;
  replica_syncer = NULL;
  db = NULL;
}

void
syncer::doRPC (const rpc_program &prog,
		int procno, const void *in, void *out, aclnt_cb cb)
{
  chord_node dst;
  host_loc->fill_node (dst);
  ::doRPC (dst, prog, procno, in, out, cb);
}

void
syncer::update_pred (cb_location cb)
{
  ptr<chordID> id = New refcounted<chordID> (host_loc->id ());

  chord_noderes *res = New chord_noderes ();
  doRPC (chord_program_1, CHORDPROC_GETPREDECESSOR,
	 id, res,
	 wrap (this, &syncer::update_pred_cb, cb, res) );
}

void
syncer::update_pred_cb (cb_location cb, chord_noderes *res, clnt_stat err)
{
  if (err) {
    warn << "my local node is down?\n";
    (*cb) (NULL);
  } else {
    chord_node n = make_chord_node (*res->resok);
    ptr<location> x = locations->lookup_or_create (n);
    locations->insert (x);
    cb (x);
  }
  delete res;
}

void
syncer::get_succlist (cb_locationlist cb)
{
  ptr<chordID> ga = New refcounted<chordID> (host_loc->id ());
  chord_nodelistres *lst = New chord_nodelistres ();
  doRPC (chord_program_1,
	 CHORDPROC_GETSUCCLIST,
	 ga, lst, wrap (this, &syncer::get_succlist_cb, lst, cb));
}

void
syncer::get_succlist_cb (chord_nodelistres *res,
		 cb_locationlist cb,
		 clnt_stat status)
{
  vec<ptr<location> > ret;
  if (!status) {
    size_t sz = res->resok->nlist.size ();
    for (size_t i = 0; i < sz; i++) {
      chord_node n = make_chord_node (res->resok->nlist[i]);
      ptr<location> s = locations->lookup_or_create (n);
      locations->insert (s);
      ret.push_back (s);
    }
  }

  cb (ret);
  delete res;
}

void
syncer::sync_replicas ()
{
  if (replica_syncer && !replica_syncer->done ()) {
    // still working on the last sync
    delaycb (replica_timer, wrap(this, &syncer::sync_replicas));
  } else {
    warn << "sync_replicas: starting (ctype = " << ctype << ")\n";
    update_pred (wrap (this, &syncer::sync_replicas_predupdated));
  }
}

void
syncer::sync_replicas_predupdated (ptr<location> pred)
{
  if (!pred) {
    delaycb (replica_timer, wrap (this, &syncer::sync_replicas));
    return;
  }
  warn << "sync_replicas: my pred is " << pred << "\n";
  get_succlist (wrap (this, &syncer::sync_replicas_gotsucclist, pred));
}

void
syncer::sync_replicas_gotsucclist (ptr<location> pred,
			   vec<ptr<location> > succs)
{
  if (succs.size () == 0) {
    delaycb (replica_timer, wrap (this, &syncer::sync_replicas));
    return;
  }

  // succs[0] is the vnode we are working for
  // pred = locations->closestpredloc (succs[0]);
  assert (pred);
  assert (succs[0]);
  assert (host_loc);

  cur_succ++; // start at 1 (0 is me)
  if (efrags > 0 && cur_succ >= efrags) cur_succ = 1;
  else if (cur_succ >= succs.size ()) cur_succ = 1;

  assert(succs[cur_succ]);

  //sync with the next node
  if (tmptree) {
    delete tmptree;
  }
  u_int64_t start = getusec ();

  tmptree = New merkle_tree ();
  db->getkeyson (succs[cur_succ], pred->id (), succs[0]->id (),
      wrap (this, &syncer::populate_tree, start, pred, succs));
}

void
syncer::populate_tree (u_int64_t start,
    ptr<location> pred, vec<ptr<location> > succs,
    adb_status astat, vec<chordID> blocks, vec<u_int32_t> aux)
{
  if (astat != ADB_OK && astat != ADB_COMPLETE) {
    warn << "syncer adbd error: " << astat << "\n";
    delete tmptree; tmptree = NULL;
    delaycb (replica_timer, wrap (this, &syncer::sync_replicas));
    return;
  }

  // XXX ugh
  switch (ctype) {
  case DHASH_CONTENTHASH:
    for (size_t i = 0; i < blocks.size (); i++) {
      tmptree->insert (blocks[i]);
    }
    break;
  case DHASH_KEYHASH:
  case DHASH_NOAUTH:
    for (size_t i = 0; i < blocks.size (); i++) {
      tmptree->insert (blocks[i], aux[i]);
    }
    break;
  default:
    fatal << "syncer::populate_tree: unexpected ctype " << ctype << "\n";
    break;
  }
  if (astat != ADB_COMPLETE) {
    // Get more, picking up from where we left off
    const chordID last (blocks.back ());
    db->getkeyson (succs[cur_succ], incID(last), succs[0]->id (),
	wrap (this, &syncer::populate_tree, start, pred, succs));
    return;
  }
  // move on to tree done
  warn << host_loc->id () << " tree build: "
       << getusec () - start << " usecs\n";

  replica_syncer = New refcounted<merkle_syncer>
    (ctype, tmptree,
     wrap (this, &syncer::doRPC_unbundler, succs[cur_succ]),
     wrap (this, &syncer::missing, succs[cur_succ]));

  bigint rngmin = pred->id ();
  bigint rngmax = succs[0]->id ();

  warn << host_loc->id () << " syncing with " << succs[cur_succ]
       << " (succ #" << cur_succ << ")"
       << " for range [ " << rngmin << ", " << rngmax << " ]\n";

  replica_syncer->sync (rngmin, rngmax);

  delaycb (replica_timer, wrap (this, &syncer::sync_replicas));
}

void
syncer::doRPC_unbundler (ptr<location> dst, RPC_delay_args *args)
{
  chord_node n;
  dst->fill_node (n);
  ::doRPC (n, args->prog, args->procno, args->in, args->out, args->cb);
}

void
syncer::missing (ptr<location> from,
		 bigint key, bool missing_local,
		 bool round_over)
{
  if (round_over) return;
  // if he tells us that we're missing it, then he has it.
  // otherwise, we found out he doesn't have it.
  // XXX this switch business is kinda gross.
  switch (ctype) {
  case DHASH_CONTENTHASH:
    db->update (key, from, missing_local, true);
    break;
  case DHASH_KEYHASH:
  case DHASH_NOAUTH:
    {
      chordID aux = (key & 0xFFFFFFFF);
      chordID dbkey = (key >> 32) << 32;
      db->update (dbkey, from, aux.getui (), missing_local, true);
    }
    break;
  default:
    fatal << "syncer::missing: unexpected ctype " << ctype << "\n";
    break;
  }
}
<commit_msg>Use new merkle_tree API to disable hashing until tree build is complete.<commit_after>#include <arpc.h>
#include <../devel/rpclib.h>
#include <comm.h>

#include <dhash_prot.h>
#include <locationtable.h>
#include <location.h>
#include <merkle_tree.h>
#include <merkle_syncer.h>

#include <syncer.h>

static int sync_trace (getenv ("SYNC_TRACE") ? atoi (getenv ("SYNC_TRACE")) : 0);

syncer::syncer (ptr<locationtable> locations,
		ptr<location> h,
		str dbpath,
		str dbname,
		dhash_ctype ctype,
		u_int dfrags, u_int efrags)
  : locations (locations), ctype (ctype), dfrags (dfrags), efrags (efrags),
    tmptree (NULL), host_loc (h),
    db (New refcounted<adb> (dbpath, dbname)),
    cur_succ (0),
    replica_timer (300)
{

  warn << "new syncer: \n"
       << "   dbpath: " << dbpath << "\n"
       << "    dbext: " << dbname << "\n"
       << "    ctype: " << ctype << "\n"
       << " d/efrags: " << dfrags << "/" << efrags << "\n";

  locations->insert (h);
  locations->pin (h->id ());

  if (sync_trace >= 10)
    replica_timer = sync_trace;

  // Initially randomize a little.
  int delay = random_getword () % replica_timer;
  delaycb (delay, wrap(this, &syncer::sync_replicas));
}

syncer::~syncer ()
{
  delete tmptree;
  tmptree = NULL;
  replica_syncer = NULL;
  db = NULL;
}

void
syncer::doRPC (const rpc_program &prog,
		int procno, const void *in, void *out, aclnt_cb cb)
{
  chord_node dst;
  host_loc->fill_node (dst);
  ::doRPC (dst, prog, procno, in, out, cb);
}

void
syncer::update_pred (cb_location cb)
{
  ptr<chordID> id = New refcounted<chordID> (host_loc->id ());

  chord_noderes *res = New chord_noderes ();
  doRPC (chord_program_1, CHORDPROC_GETPREDECESSOR,
	 id, res,
	 wrap (this, &syncer::update_pred_cb, cb, res) );
}

void
syncer::update_pred_cb (cb_location cb, chord_noderes *res, clnt_stat err)
{
  if (err) {
    warn << "my local node is down?\n";
    (*cb) (NULL);
  } else {
    chord_node n = make_chord_node (*res->resok);
    ptr<location> x = locations->lookup_or_create (n);
    locations->insert (x);
    cb (x);
  }
  delete res;
}

void
syncer::get_succlist (cb_locationlist cb)
{
  ptr<chordID> ga = New refcounted<chordID> (host_loc->id ());
  chord_nodelistres *lst = New chord_nodelistres ();
  doRPC (chord_program_1,
	 CHORDPROC_GETSUCCLIST,
	 ga, lst, wrap (this, &syncer::get_succlist_cb, lst, cb));
}

void
syncer::get_succlist_cb (chord_nodelistres *res,
		 cb_locationlist cb,
		 clnt_stat status)
{
  vec<ptr<location> > ret;
  if (!status) {
    size_t sz = res->resok->nlist.size ();
    for (size_t i = 0; i < sz; i++) {
      chord_node n = make_chord_node (res->resok->nlist[i]);
      ptr<location> s = locations->lookup_or_create (n);
      locations->insert (s);
      ret.push_back (s);
    }
  }

  cb (ret);
  delete res;
}

void
syncer::sync_replicas ()
{
  if (replica_syncer && !replica_syncer->done ()) {
    // still working on the last sync
    delaycb (replica_timer, wrap(this, &syncer::sync_replicas));
  } else {
    warn << "sync_replicas: starting (ctype = " << ctype << ")\n";
    update_pred (wrap (this, &syncer::sync_replicas_predupdated));
  }
}

void
syncer::sync_replicas_predupdated (ptr<location> pred)
{
  if (!pred) {
    delaycb (replica_timer, wrap (this, &syncer::sync_replicas));
    return;
  }
  warn << "sync_replicas: my pred is " << pred << "\n";
  get_succlist (wrap (this, &syncer::sync_replicas_gotsucclist, pred));
}

void
syncer::sync_replicas_gotsucclist (ptr<location> pred,
			   vec<ptr<location> > succs)
{
  if (succs.size () == 0) {
    delaycb (replica_timer, wrap (this, &syncer::sync_replicas));
    return;
  }

  // succs[0] is the vnode we are working for
  // pred = locations->closestpredloc (succs[0]);
  assert (pred);
  assert (succs[0]);
  assert (host_loc);

  cur_succ++; // start at 1 (0 is me)
  if (efrags > 0 && cur_succ >= efrags) cur_succ = 1;
  else if (cur_succ >= succs.size ()) cur_succ = 1;

  assert(succs[cur_succ]);

  //sync with the next node
  if (tmptree) {
    delete tmptree;
  }
  u_int64_t start = getusec ();

  tmptree = New merkle_tree ();
  tmptree->set_rehash_on_modification (false);
  db->getkeyson (succs[cur_succ], pred->id (), succs[0]->id (),
      wrap (this, &syncer::populate_tree, start, pred, succs));
}

void
syncer::populate_tree (u_int64_t start,
    ptr<location> pred, vec<ptr<location> > succs,
    adb_status astat, vec<chordID> blocks, vec<u_int32_t> aux)
{
  if (astat != ADB_OK && astat != ADB_COMPLETE) {
    warn << "syncer adbd error: " << astat << "\n";
    delete tmptree; tmptree = NULL;
    delaycb (replica_timer, wrap (this, &syncer::sync_replicas));
    return;
  }

  // XXX ugh
  switch (ctype) {
  case DHASH_CONTENTHASH:
    for (size_t i = 0; i < blocks.size (); i++) {
      tmptree->insert (blocks[i]);
    }
    break;
  case DHASH_KEYHASH:
  case DHASH_NOAUTH:
    for (size_t i = 0; i < blocks.size (); i++) {
      tmptree->insert (blocks[i], aux[i]);
    }
    break;
  default:
    fatal << "syncer::populate_tree: unexpected ctype " << ctype << "\n";
    break;
  }
  if (astat != ADB_COMPLETE) {
    // Get more, picking up from where we left off
    const chordID last (blocks.back ());
    db->getkeyson (succs[cur_succ], incID(last), succs[0]->id (),
	wrap (this, &syncer::populate_tree, start, pred, succs));
    return;
  }
  // move on to tree done
  tmptree->hash_tree ();
  tmptree->set_rehash_on_modification (true);
  warn << host_loc->id () << " tree build: "
       << getusec () - start << " usecs\n";

  replica_syncer = New refcounted<merkle_syncer>
    (ctype, tmptree,
     wrap (this, &syncer::doRPC_unbundler, succs[cur_succ]),
     wrap (this, &syncer::missing, succs[cur_succ]));

  bigint rngmin = pred->id ();
  bigint rngmax = succs[0]->id ();

  warn << host_loc->id () << " syncing with " << succs[cur_succ]
       << " (succ #" << cur_succ << ")"
       << " for range [ " << rngmin << ", " << rngmax << " ]\n";

  replica_syncer->sync (rngmin, rngmax);

  delaycb (replica_timer, wrap (this, &syncer::sync_replicas));
}

void
syncer::doRPC_unbundler (ptr<location> dst, RPC_delay_args *args)
{
  chord_node n;
  dst->fill_node (n);
  ::doRPC (n, args->prog, args->procno, args->in, args->out, args->cb);
}

void
syncer::missing (ptr<location> from,
		 bigint key, bool missing_local,
		 bool round_over)
{
  if (round_over) return;
  // if he tells us that we're missing it, then he has it.
  // otherwise, we found out he doesn't have it.
  // XXX this switch business is kinda gross.
  switch (ctype) {
  case DHASH_CONTENTHASH:
    db->update (key, from, missing_local, true);
    break;
  case DHASH_KEYHASH:
  case DHASH_NOAUTH:
    {
      chordID aux = (key & 0xFFFFFFFF);
      chordID dbkey = (key >> 32) << 32;
      db->update (dbkey, from, aux.getui (), missing_local, true);
    }
    break;
  default:
    fatal << "syncer::missing: unexpected ctype " << ctype << "\n";
    break;
  }
}
<|endoftext|>


<commit_before>//===--------------------------- new.cpp ----------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#define _LIBCPP_BUILDING_NEW

#include <stdlib.h>

#include "new"

#ifndef __has_include
#define __has_include(inc) 0
#endif

#ifdef __APPLE__
    #include <cxxabi.h>

    #ifndef _LIBCPPABI_VERSION
        // On Darwin, there are two STL shared libraries and a lower level ABI
        // shared library.  The global holding the current new handler is
        // in the ABI library and named __cxa_new_handler.
        #define __new_handler __cxxabiapple::__cxa_new_handler
    #endif
#else  // __APPLE__
    #if defined(LIBCXXRT) || __has_include(<cxxabi.h>)
        #include <cxxabi.h>
    #endif  // __has_include(<cxxabi.h>)
    #if !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
        static std::new_handler __new_handler;
    #endif  // _LIBCPPABI_VERSION
#endif

#ifndef __GLIBCXX__

// Implement all new and delete operators as weak definitions
// in this shared library, so that they can be overriden by programs
// that define non-weak copies of the functions.

_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
void *
operator new(std::size_t size)
#if !__has_feature(cxx_noexcept)
    throw(std::bad_alloc)
#endif
{
    if (size == 0)
        size = 1;
    void* p;
    while ((p = ::malloc(size)) == 0)
    {
        // If malloc fails and there is a new_handler,
        // call it to try free up memory.
        std::new_handler nh = std::get_new_handler();
        if (nh)
            nh();
        else
#ifndef _LIBCPP_NO_EXCEPTIONS
            throw std::bad_alloc();
#else
            break;
#endif
    }
    return p;
}

_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
void*
operator new(size_t size, const std::nothrow_t&) _NOEXCEPT
{
    void* p = 0;
#ifndef _LIBCPP_NO_EXCEPTIONS
    try
    {
#endif  // _LIBCPP_NO_EXCEPTIONS
        p = ::operator new(size);
#ifndef _LIBCPP_NO_EXCEPTIONS
    }
    catch (...)
    {
    }
#endif  // _LIBCPP_NO_EXCEPTIONS
    return p;
}

_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
void*
operator new[](size_t size)
#if !__has_feature(cxx_noexcept)
    throw(std::bad_alloc)
#endif
{
    return ::operator new(size);
}

_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
void*
operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT
{
    void* p = 0;
#ifndef _LIBCPP_NO_EXCEPTIONS
    try
    {
#endif  // _LIBCPP_NO_EXCEPTIONS
        p = ::operator new[](size);
#ifndef _LIBCPP_NO_EXCEPTIONS
    }
    catch (...)
    {
    }
#endif  // _LIBCPP_NO_EXCEPTIONS
    return p;
}

_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
void
operator delete(void* ptr) _NOEXCEPT
{
    if (ptr)
        ::free(ptr);
}

_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
void
operator delete(void* ptr, const std::nothrow_t&) _NOEXCEPT
{
    ::operator delete(ptr);
}

_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
void
operator delete[] (void* ptr) _NOEXCEPT
{
    ::operator delete (ptr);
}

_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
void
operator delete[] (void* ptr, const std::nothrow_t&) _NOEXCEPT
{
    ::operator delete[](ptr);
}

#endif // !__GLIBCXX__

namespace std
{

#ifndef __GLIBCXX__
const nothrow_t nothrow = {};
#endif

#ifndef _LIBCPPABI_VERSION

#ifndef __GLIBCXX__

new_handler
set_new_handler(new_handler handler) _NOEXCEPT
{
    return __sync_lock_test_and_set(&__new_handler, handler);
}

new_handler
get_new_handler() _NOEXCEPT
{
    return __sync_fetch_and_add(&__new_handler, nullptr);
}

#endif // !__GLIBCXX__

#ifndef LIBCXXRT

bad_alloc::bad_alloc() _NOEXCEPT
{
}

#ifndef __GLIBCXX__

bad_alloc::~bad_alloc() _NOEXCEPT
{
}

const char*
bad_alloc::what() const _NOEXCEPT
{
    return "std::bad_alloc";
}

#endif // !__GLIBCXX__

#endif //LIBCXXRT

bad_array_new_length::bad_array_new_length() _NOEXCEPT
{
}

bad_array_new_length::~bad_array_new_length() _NOEXCEPT
{
}

const char*
bad_array_length::what() const _NOEXCEPT
{
    return "bad_array_length";
}

bad_array_length::bad_array_length() _NOEXCEPT
{
}

bad_array_length::~bad_array_length() _NOEXCEPT
{
}

const char*
bad_array_new_length::what() const _NOEXCEPT
{
    return "bad_array_new_length";
}

#endif // _LIBCPPABI_VERSION

#ifndef LIBSTDCXX

void
__throw_bad_alloc()
{
#ifndef _LIBCPP_NO_EXCEPTIONS
    throw bad_alloc();
#endif
}

#endif // !LIBSTDCXX

}  // std
<commit_msg>libcxxrt now implements bad_array_new_length and need to gaurd against multiple defines. Patch from Baptiste Daroussin.<commit_after>//===--------------------------- new.cpp ----------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#define _LIBCPP_BUILDING_NEW

#include <stdlib.h>

#include "new"

#ifndef __has_include
#define __has_include(inc) 0
#endif

#ifdef __APPLE__
    #include <cxxabi.h>

    #ifndef _LIBCPPABI_VERSION
        // On Darwin, there are two STL shared libraries and a lower level ABI
        // shared library.  The global holding the current new handler is
        // in the ABI library and named __cxa_new_handler.
        #define __new_handler __cxxabiapple::__cxa_new_handler
    #endif
#else  // __APPLE__
    #if defined(LIBCXXRT) || __has_include(<cxxabi.h>)
        #include <cxxabi.h>
    #endif  // __has_include(<cxxabi.h>)
    #if !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
        static std::new_handler __new_handler;
    #endif  // _LIBCPPABI_VERSION
#endif

#ifndef __GLIBCXX__

// Implement all new and delete operators as weak definitions
// in this shared library, so that they can be overriden by programs
// that define non-weak copies of the functions.

_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
void *
operator new(std::size_t size)
#if !__has_feature(cxx_noexcept)
    throw(std::bad_alloc)
#endif
{
    if (size == 0)
        size = 1;
    void* p;
    while ((p = ::malloc(size)) == 0)
    {
        // If malloc fails and there is a new_handler,
        // call it to try free up memory.
        std::new_handler nh = std::get_new_handler();
        if (nh)
            nh();
        else
#ifndef _LIBCPP_NO_EXCEPTIONS
            throw std::bad_alloc();
#else
            break;
#endif
    }
    return p;
}

_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
void*
operator new(size_t size, const std::nothrow_t&) _NOEXCEPT
{
    void* p = 0;
#ifndef _LIBCPP_NO_EXCEPTIONS
    try
    {
#endif  // _LIBCPP_NO_EXCEPTIONS
        p = ::operator new(size);
#ifndef _LIBCPP_NO_EXCEPTIONS
    }
    catch (...)
    {
    }
#endif  // _LIBCPP_NO_EXCEPTIONS
    return p;
}

_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
void*
operator new[](size_t size)
#if !__has_feature(cxx_noexcept)
    throw(std::bad_alloc)
#endif
{
    return ::operator new(size);
}

_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
void*
operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT
{
    void* p = 0;
#ifndef _LIBCPP_NO_EXCEPTIONS
    try
    {
#endif  // _LIBCPP_NO_EXCEPTIONS
        p = ::operator new[](size);
#ifndef _LIBCPP_NO_EXCEPTIONS
    }
    catch (...)
    {
    }
#endif  // _LIBCPP_NO_EXCEPTIONS
    return p;
}

_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
void
operator delete(void* ptr) _NOEXCEPT
{
    if (ptr)
        ::free(ptr);
}

_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
void
operator delete(void* ptr, const std::nothrow_t&) _NOEXCEPT
{
    ::operator delete(ptr);
}

_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
void
operator delete[] (void* ptr) _NOEXCEPT
{
    ::operator delete (ptr);
}

_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
void
operator delete[] (void* ptr, const std::nothrow_t&) _NOEXCEPT
{
    ::operator delete[](ptr);
}

#endif // !__GLIBCXX__

namespace std
{

#ifndef __GLIBCXX__
const nothrow_t nothrow = {};
#endif

#ifndef _LIBCPPABI_VERSION

#ifndef __GLIBCXX__

new_handler
set_new_handler(new_handler handler) _NOEXCEPT
{
    return __sync_lock_test_and_set(&__new_handler, handler);
}

new_handler
get_new_handler() _NOEXCEPT
{
    return __sync_fetch_and_add(&__new_handler, nullptr);
}

#endif // !__GLIBCXX__

#ifndef LIBCXXRT

bad_alloc::bad_alloc() _NOEXCEPT
{
}

#ifndef __GLIBCXX__

bad_alloc::~bad_alloc() _NOEXCEPT
{
}

const char*
bad_alloc::what() const _NOEXCEPT
{
    return "std::bad_alloc";
}

#endif // !__GLIBCXX__

bad_array_new_length::bad_array_new_length() _NOEXCEPT
{
}

bad_array_new_length::~bad_array_new_length() _NOEXCEPT
{
}

#endif //LIBCXXRT

const char*
bad_array_length::what() const _NOEXCEPT
{
    return "bad_array_length";
}

bad_array_length::bad_array_length() _NOEXCEPT
{
}

bad_array_length::~bad_array_length() _NOEXCEPT
{
}

const char*
bad_array_new_length::what() const _NOEXCEPT
{
    return "bad_array_new_length";
}

#endif // _LIBCPPABI_VERSION

#ifndef LIBSTDCXX

void
__throw_bad_alloc()
{
#ifndef _LIBCPP_NO_EXCEPTIONS
    throw bad_alloc();
#endif
}

#endif // !LIBSTDCXX

}  // std
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 Fondazione Istituto Italiano di Tecnologia
 * Authors: Silvio Traversaro
 * CopyPolicy: Released under the terms of the LGPLv2.1 or later, see LGPL.TXT
 *
 */

#include <iDynTree/Model/Model.h>
#include <iDynTree/Model/Traversal.h>

#include <cassert>
#include <deque>

namespace iDynTree
{

Model::Model(): defaultBaseLink(LINK_INVALID_INDEX), nrOfPosCoords(0), nrOfDOFs(0)
{

}

void Model::copy(const Model& other)
{
    // Add all the links, preserving the numbering
    for(unsigned int lnk=0; lnk < other.getNrOfLinks(); lnk++ )
    {
        this->addLink(other.linkNames[lnk],other.links[lnk]);
    }

    // Add all joints, preserving the numbering

    // reset the nrOfDOFs (it will be then update in addJoint
    nrOfPosCoords = 0;
    nrOfDOFs = 0;

    for(unsigned int jnt=0; jnt < other.getNrOfJoints(); jnt++ )
    {
        this->addJoint(other.jointNames[jnt],other.joints[jnt]);
    }

    // Copy the default base link
    this->setDefaultBaseLink(other.getDefaultBaseLink());
}

Model::Model(const Model& other)
{
    copy(other);
}

Model& Model::operator=(const Model& other)
{
    if( &other != this )
    {
        destroy();
        copy(other);
    }

    return *this;
}

void Model::destroy()
{
    links.resize(0);
    linkNames.resize(0);
    for(unsigned int jnt=0; jnt < this->getNrOfJoints(); jnt++ )
    {
        delete this->joints[jnt];
        this->joints[jnt] = 0;
    }
    joints.resize(0);
    nrOfPosCoords = 0;
    nrOfDOFs = 0;
    jointNames.resize(0);
    additionalFrames.resize(0);
    additionalFramesLinks.resize(0);
    frameNames.resize(0);
    neighbors.resize(0);
}

Model::~Model()
{
    destroy();
}

size_t Model::getNrOfLinks() const
{
    return links.size();
}

LinkIndex Model::getLinkIndex(const std::string& linkName) const
{
    for(size_t i=0; i < this->getNrOfLinks(); i++ )
    {
        if( linkName == linkNames[i] )
        {
            return i;
        }
    }

    return LINK_INVALID_INDEX;
}

std::string Model::getLinkName(const LinkIndex linkIndex) const
{
    if( linkIndex >= 0 && linkIndex < (LinkIndex) this->getNrOfLinks() )
    {
        return linkNames[linkIndex];
    }
    else
    {
        return LINK_INVALID_NAME;
    }
}

Link* Model::getLink(const LinkIndex linkIndex)
{
    return &(links[linkIndex]);
}

const Link* Model::getLink(const LinkIndex linkIndex) const
{
    return &(links[linkIndex]);
}

size_t Model::getNrOfJoints() const
{
    return joints.size();
}

JointIndex Model::getJointIndex(const std::string& jointName) const
{
    for(size_t i=0; i < this->getNrOfJoints(); i++ )
    {
        if( jointName == jointNames[i] )
        {
            return i;
        }
    }

    return JOINT_INVALID_INDEX;
}

std::string Model::getJointName(const JointIndex jointIndex) const
{
    if( jointIndex >= 0 && jointIndex < (JointIndex)this->getNrOfJoints() )
    {
        return jointNames[jointIndex];
    }
    else
    {
        return JOINT_INVALID_NAME;
    }
}

IJoint* Model::getJoint(const JointIndex jointIndex)
{
    return (joints[jointIndex]);
}

const IJoint* Model::getJoint(const JointIndex jointIndex) const
{
    return (joints[jointIndex]);
}

bool Model::isLinkNameUsed(const std::string linkName)
{
    return (LINK_INVALID_INDEX != getLinkIndex(linkName));
}

LinkIndex Model::addLink(const std::string& name, const Link& link)
{
    // Check that the name is not already used by a link or frame
    if(isFrameNameUsed(name))
    {
        std::string error = "a link or frame of name " + name + " is already present in the model";
        reportError("Model","addLink",error.c_str());
        return LINK_INVALID_INDEX;
    }

    // Add the link to the vector of names and of links
    assert(links.size() == linkNames.size());
    linkNames.push_back(name);
    links.push_back(link);

    // add an empty adjacency list to the neighbors members
    neighbors.push_back(std::vector<Neighbor>());

    LinkIndex newLinkIndex = (LinkIndex)(links.size()-1);

    links[newLinkIndex].setIndex(newLinkIndex);

    // if this is the first link added to the model
    // and the defaultBaseLink has not been setted,
    // set the defaultBaseLink to be this link
    if( newLinkIndex == 0 && getDefaultBaseLink() == LINK_INVALID_INDEX )
    {
        setDefaultBaseLink(newLinkIndex);
    }

    return newLinkIndex;
}

bool Model::isJointNameUsed(const std::string jointName)
{
    return (JOINT_INVALID_INDEX != getJointIndex(jointName));
}

JointIndex Model::addJoint(const std::string& jointName, IJointConstPtr joint)
{
    assert(joint->getFirstAttachedLink() != joint->getSecondAttachedLink());

    if(isJointNameUsed(jointName))
    {
        std::string error = "a joint of name " + jointName + " is already present in the model";
        reportError("Model","addJoint",error.c_str());
        return JOINT_INVALID_INDEX;
    }

    // Check that the joint is referring to links that are in the model
    LinkIndex firstLink = joint->getFirstAttachedLink();
    LinkIndex secondLink = joint->getSecondAttachedLink();
    if( firstLink < 0 || firstLink >= (LinkIndex)this->getNrOfLinks() ||
        secondLink < 0 || secondLink >= (LinkIndex)this->getNrOfLinks() )
    {
        std::string error = "joint " + jointName + " is attached to a link that does not exist";
        reportError("Model","addJoint",error.c_str());
        return JOINT_INVALID_INDEX;
    }

    // Check that the joint is not connecting a link to itself
    if( firstLink == secondLink )
    {
        std::string error = "joint " + jointName + " is connecting link " + this->getLinkName(firstLink) + " to itself";
        reportError("Model","addJoint",error.c_str());
        return JOINT_INVALID_INDEX;
    }

    // Update the joints and jointNames structure
    jointNames.push_back(jointName);
    joints.push_back(joint->clone());

    JointIndex thisJointIndex = (JointIndex)(joints.size()-1);

    // Update the adjacency list
    Neighbor firstLinkNeighbor;
    firstLinkNeighbor.neighborLink = secondLink;
    firstLinkNeighbor.neighborJoint = thisJointIndex;
    this->neighbors[firstLink].push_back(firstLinkNeighbor);

    Neighbor secondLinkNeighbor;
    secondLinkNeighbor.neighborLink = firstLink;
    secondLinkNeighbor.neighborJoint = thisJointIndex;
    this->neighbors[secondLink].push_back(secondLinkNeighbor);

    // Set the joint index and dof offset
    this->joints[thisJointIndex]->setIndex(thisJointIndex);
    this->joints[thisJointIndex]->setPosCoordsOffset(this->nrOfPosCoords);
    this->joints[thisJointIndex]->setDOFsOffset(this->nrOfDOFs);

    // Update the number of dofs
    this->nrOfPosCoords += this->joints[thisJointIndex]->getNrOfPosCoords();
    this->nrOfDOFs += this->joints[thisJointIndex]->getNrOfDOFs();

    return thisJointIndex;
}

size_t Model::getNrOfPosCoords() const
{
    return nrOfDOFs;
}

size_t Model::getNrOfDOFs() const
{
    return nrOfDOFs;
}

/////////////////////////////////////////////////////////////////////
///// Frame Related functions
/////////////////////////////////////////////////////////////////////
size_t Model::getNrOfFrames() const
{
    return (size_t)getNrOfLinks() + this->additionalFrames.size();
}

std::string Model::getFrameName(const FrameIndex frameIndex) const
{
    if( frameIndex >= 0 && frameIndex < (FrameIndex)this->getNrOfLinks() )
    {
        return linkNames[frameIndex];
    }
    else if( frameIndex >= this->getNrOfLinks() && frameIndex < (FrameIndex)this->getNrOfFrames() )
    {
        return frameNames[frameIndex-getNrOfLinks()];
    }
    else
    {
        return FRAME_INVALID_NAME;
    }
}

FrameIndex Model::getFrameIndex(const std::string& frameName) const
{
    for(int i=0; i < this->getNrOfLinks(); i++ )
    {
        if( frameName == linkNames[i] )
        {
            return (FrameIndex)i;
        }
    }

    for(int i=this->getNrOfLinks(); i < this->getNrOfFrames(); i++ )
    {
        if( frameName == this->frameNames[i-getNrOfLinks()] )
        {
            return (FrameIndex)i;
        }
    }

    return FRAME_INVALID_INDEX;
}

bool Model::isFrameNameUsed(const std::string frameName)
{
    return (FRAME_INVALID_INDEX != getFrameIndex(frameName));
}

bool Model::addAdditionalFrameToLink(const std::string& linkName,
                                     const std::string& frameName,
                                     Transform link_H_frame)
{
    // Check that the link actually exist
    LinkIndex linkIndex = this->getLinkIndex(linkName);
    if( linkIndex == LINK_INVALID_INDEX )
    {
        std::string error = "error adding frame " + frameName + " : a link of name "
                            + linkName + " is not present in the model";
        reportError("Model","addAdditionalFrameToLink",error.c_str());
        return false;
    }

    // Check that the frame name is not already used by a link or frame
    if(isFrameNameUsed(frameName))
    {
        std::string error = "a link or frame of name " + frameName + " is already present in the model";
        reportError("Model","addAdditionalFrameToLink",error.c_str());
        return false;
    }

    // If all error has passed, actually add the frame
    this->additionalFrames.push_back(link_H_frame);
    this->additionalFramesLinks.push_back(linkIndex);
    this->frameNames.push_back(frameName);

    return true;
}

Transform Model::getFrameTransform(const FrameIndex frameIndex) const
{
    // The link_H_frame transform for the link
    // main frame is the identity
    if( frameIndex < this->getNrOfLinks() ||
        frameIndex >= this->getNrOfFrames() )
    {
        return Transform::Identity();
    }

    // For an additonal frame the transform is instead stored
    // in the additionalFrames vector
    return this->additionalFrames[frameIndex-getNrOfLinks()];
}

LinkIndex Model::getFrameLink(const FrameIndex frameIndex) const
{
    // The link_H_frame transform for the link
    // main frame is the link it self
    if( frameIndex >= 0 &&
        frameIndex < this->getNrOfLinks() )
    {
        return (LinkIndex)frameIndex;
    }

    if( frameIndex >= this->getNrOfLinks() &&
        frameIndex < this->getNrOfFrames() )
    {
        // For an additonal frame the link index is instead stored
        // in the additionalFramesLinks vector
        return this->additionalFramesLinks[frameIndex-getNrOfLinks()];
    }

    // If the frameIndex is out of bounds, return an invalid index
    return LINK_INVALID_INDEX;
}

unsigned int Model::getNrOfNeighbors(const LinkIndex link) const
{
    assert(link < this->neighbors.size());
    return this->neighbors[link].size();
}

Neighbor Model::getNeighbor(const LinkIndex link, unsigned int neighborIndex) const
{
    assert(link < this->getNrOfLinks());
    assert(neighborIndex < this->getNrOfNeighbors(link));
    return this->neighbors[link][neighborIndex];
}

bool Model::setDefaultBaseLink(const LinkIndex linkIndex)
{
    if( linkIndex < 0 || linkIndex >= this->getNrOfLinks() )
    {
        return false;
    }
    else
    {
        defaultBaseLink = linkIndex;
        return true;
    }
}

LinkIndex Model::getDefaultBaseLink() const
{
    return defaultBaseLink;
}

bool Model::computeFullTreeTraversal(Traversal & traversal) const
{
    return computeFullTreeTraversal(traversal,this->getDefaultBaseLink());
}

struct stackEl { LinkConstPtr link; LinkConstPtr parent;};

void  addBaseLinkToTraversal(const Model & model, Traversal & traversal, int & traversalFirstEmptySlot,
                                    LinkIndex linkToAdd, std::deque<stackEl> & linkToVisit)
{
    assert(traversalFirstEmptySlot == 0);
    traversal.setTraversalElement(traversalFirstEmptySlot,
                                  model.getLink(linkToAdd),
                                  0,
                                  0);

    traversalFirstEmptySlot++;

    stackEl el;
    el.link = model.getLink(linkToAdd);
    el.parent = 0;

    linkToVisit.push_back(el);
}

void addLinkToTraversal(const Model & model, Traversal & traversal, int & traversalFirstEmptySlot,
                        LinkIndex linkToAdd, JointIndex parentJointToAdd, LinkIndex parentLinkToAdd,
                        std::deque<stackEl> & linkToVisit)
{
    traversal.setTraversalElement(traversalFirstEmptySlot,
                                  model.getLink(linkToAdd),
                                  model.getJoint(parentJointToAdd),
                                  model.getLink(parentLinkToAdd));

    traversalFirstEmptySlot++;

    stackEl el;
    el.link = model.getLink(linkToAdd);
    el.parent = model.getLink(parentLinkToAdd);

    linkToVisit.push_back(el);
}

bool Model::computeFullTreeTraversal(Traversal & traversal, const LinkIndex traversalBase) const
{
    if( traversalBase < 0 || traversalBase >= this->getNrOfLinks() )
    {
        reportError("Model","computeFullTreeTraversal","requested traversalBase is out of bounds");
        return false;
    }

    // The full tree traversal is a traversal spanning all the links
    // of a model, so it include getNrOfLinks() visited links
    traversal.reset(this->getNrOfLinks(),this->getNrOfLinks());

    // A link is considered visit when all its child (given the traversalBase)
    // have been added to the traversal
    std::deque<stackEl> linkToVisit;

    // We add as first link the requested traversalBase
    int traversalFirstEmptySlot = 0;
    addBaseLinkToTraversal(*this,traversal,traversalFirstEmptySlot,traversalBase,linkToVisit);

    // while there is some link still to visit
    unsigned int visitNumber=0;
    while( linkToVisit.size() > 0 )
    {
        assert(linkToVisit.size() <= this->getNrOfLinks());

        // DPS : we use linkToVisit as a stack
        LinkConstPtr visitedLink = linkToVisit.back().link;
        LinkConstPtr visitedLinkParent = linkToVisit.back().parent;
        LinkIndex visitedLinkIndex = visitedLink->getIndex();
        linkToVisit.pop_back();

        for(unsigned int neigh_i=0; neigh_i < this->getNrOfNeighbors(visitedLinkIndex); neigh_i++ )
        {
            // add to the stack all the neighbors, except for parent link
            // (if the visited link is the base one, add all the neighbors)
            // the visited link is already in the Traversal, so we can use it
            // to check for its parent
            Neighbor neighb = this->getNeighbor(visitedLinkIndex,neigh_i);
            if( visitedLinkParent == 0 || neighb.neighborLink != visitedLinkParent->getIndex() )
            {
                addLinkToTraversal(*this,traversal,traversalFirstEmptySlot,neighb.neighborLink,
                    neighb.neighborJoint,visitedLink->getIndex(),linkToVisit);
            }
        }
    }

    return true;
}

}
<commit_msg>[model] Fix use of initialized memory in Model copy constructor<commit_after>/*
 * Copyright (C) 2015 Fondazione Istituto Italiano di Tecnologia
 * Authors: Silvio Traversaro
 * CopyPolicy: Released under the terms of the LGPLv2.1 or later, see LGPL.TXT
 *
 */

#include <iDynTree/Model/Model.h>
#include <iDynTree/Model/Traversal.h>

#include <cassert>
#include <deque>

namespace iDynTree
{

Model::Model(): defaultBaseLink(LINK_INVALID_INDEX), nrOfPosCoords(0), nrOfDOFs(0)
{

}

void Model::copy(const Model& other)
{
    // reset the base link, the real one will be copied later
    this->defaultBaseLink = LINK_INVALID_INDEX;

    // Add all the links, preserving the numbering
    for(unsigned int lnk=0; lnk < other.getNrOfLinks(); lnk++ )
    {
        this->addLink(other.linkNames[lnk],other.links[lnk]);
    }

    // Add all joints, preserving the numbering
    // reset the nrOfDOFs (it will be then update in addJoint)
    nrOfPosCoords = 0;
    nrOfDOFs = 0;

    for(unsigned int jnt=0; jnt < other.getNrOfJoints(); jnt++ )
    {
        this->addJoint(other.jointNames[jnt],other.joints[jnt]);
    }

    // Copy the default base link
    this->setDefaultBaseLink(other.getDefaultBaseLink());
}

Model::Model(const Model& other)
{
    copy(other);
}

Model& Model::operator=(const Model& other)
{
    if( &other != this )
    {
        destroy();
        copy(other);
    }

    return *this;
}

void Model::destroy()
{
    links.resize(0);
    linkNames.resize(0);
    for(unsigned int jnt=0; jnt < this->getNrOfJoints(); jnt++ )
    {
        delete this->joints[jnt];
        this->joints[jnt] = 0;
    }
    joints.resize(0);
    nrOfPosCoords = 0;
    nrOfDOFs = 0;
    jointNames.resize(0);
    additionalFrames.resize(0);
    additionalFramesLinks.resize(0);
    frameNames.resize(0);
    neighbors.resize(0);
}

Model::~Model()
{
    destroy();
}

size_t Model::getNrOfLinks() const
{
    return links.size();
}

LinkIndex Model::getLinkIndex(const std::string& linkName) const
{
    for(size_t i=0; i < this->getNrOfLinks(); i++ )
    {
        if( linkName == linkNames[i] )
        {
            return i;
        }
    }

    return LINK_INVALID_INDEX;
}

std::string Model::getLinkName(const LinkIndex linkIndex) const
{
    if( linkIndex >= 0 && linkIndex < (LinkIndex) this->getNrOfLinks() )
    {
        return linkNames[linkIndex];
    }
    else
    {
        return LINK_INVALID_NAME;
    }
}

Link* Model::getLink(const LinkIndex linkIndex)
{
    return &(links[linkIndex]);
}

const Link* Model::getLink(const LinkIndex linkIndex) const
{
    return &(links[linkIndex]);
}

size_t Model::getNrOfJoints() const
{
    return joints.size();
}

JointIndex Model::getJointIndex(const std::string& jointName) const
{
    for(size_t i=0; i < this->getNrOfJoints(); i++ )
    {
        if( jointName == jointNames[i] )
        {
            return i;
        }
    }

    return JOINT_INVALID_INDEX;
}

std::string Model::getJointName(const JointIndex jointIndex) const
{
    if( jointIndex >= 0 && jointIndex < (JointIndex)this->getNrOfJoints() )
    {
        return jointNames[jointIndex];
    }
    else
    {
        return JOINT_INVALID_NAME;
    }
}

IJoint* Model::getJoint(const JointIndex jointIndex)
{
    return (joints[jointIndex]);
}

const IJoint* Model::getJoint(const JointIndex jointIndex) const
{
    return (joints[jointIndex]);
}

bool Model::isLinkNameUsed(const std::string linkName)
{
    return (LINK_INVALID_INDEX != getLinkIndex(linkName));
}

LinkIndex Model::addLink(const std::string& name, const Link& link)
{
    // Check that the name is not already used by a link or frame
    if(isFrameNameUsed(name))
    {
        std::string error = "a link or frame of name " + name + " is already present in the model";
        reportError("Model","addLink",error.c_str());
        return LINK_INVALID_INDEX;
    }

    // Add the link to the vector of names and of links
    assert(links.size() == linkNames.size());
    linkNames.push_back(name);
    links.push_back(link);

    // add an empty adjacency list to the neighbors members
    neighbors.push_back(std::vector<Neighbor>());

    LinkIndex newLinkIndex = (LinkIndex)(links.size()-1);

    links[newLinkIndex].setIndex(newLinkIndex);

    // if this is the first link added to the model
    // and the defaultBaseLink has not been setted,
    // set the defaultBaseLink to be this link
    if( newLinkIndex == 0 && getDefaultBaseLink() == LINK_INVALID_INDEX )
    {
        setDefaultBaseLink(newLinkIndex);
    }

    return newLinkIndex;
}

bool Model::isJointNameUsed(const std::string jointName)
{
    return (JOINT_INVALID_INDEX != getJointIndex(jointName));
}

JointIndex Model::addJoint(const std::string& jointName, IJointConstPtr joint)
{
    assert(joint->getFirstAttachedLink() != joint->getSecondAttachedLink());

    if(isJointNameUsed(jointName))
    {
        std::string error = "a joint of name " + jointName + " is already present in the model";
        reportError("Model","addJoint",error.c_str());
        return JOINT_INVALID_INDEX;
    }

    // Check that the joint is referring to links that are in the model
    LinkIndex firstLink = joint->getFirstAttachedLink();
    LinkIndex secondLink = joint->getSecondAttachedLink();
    if( firstLink < 0 || firstLink >= (LinkIndex)this->getNrOfLinks() ||
        secondLink < 0 || secondLink >= (LinkIndex)this->getNrOfLinks() )
    {
        std::string error = "joint " + jointName + " is attached to a link that does not exist";
        reportError("Model","addJoint",error.c_str());
        return JOINT_INVALID_INDEX;
    }

    // Check that the joint is not connecting a link to itself
    if( firstLink == secondLink )
    {
        std::string error = "joint " + jointName + " is connecting link " + this->getLinkName(firstLink) + " to itself";
        reportError("Model","addJoint",error.c_str());
        return JOINT_INVALID_INDEX;
    }

    // Update the joints and jointNames structure
    jointNames.push_back(jointName);
    joints.push_back(joint->clone());

    JointIndex thisJointIndex = (JointIndex)(joints.size()-1);

    // Update the adjacency list
    Neighbor firstLinkNeighbor;
    firstLinkNeighbor.neighborLink = secondLink;
    firstLinkNeighbor.neighborJoint = thisJointIndex;
    this->neighbors[firstLink].push_back(firstLinkNeighbor);

    Neighbor secondLinkNeighbor;
    secondLinkNeighbor.neighborLink = firstLink;
    secondLinkNeighbor.neighborJoint = thisJointIndex;
    this->neighbors[secondLink].push_back(secondLinkNeighbor);

    // Set the joint index and dof offset
    this->joints[thisJointIndex]->setIndex(thisJointIndex);
    this->joints[thisJointIndex]->setPosCoordsOffset(this->nrOfPosCoords);
    this->joints[thisJointIndex]->setDOFsOffset(this->nrOfDOFs);

    // Update the number of dofs
    this->nrOfPosCoords += this->joints[thisJointIndex]->getNrOfPosCoords();
    this->nrOfDOFs += this->joints[thisJointIndex]->getNrOfDOFs();

    return thisJointIndex;
}

size_t Model::getNrOfPosCoords() const
{
    return nrOfDOFs;
}

size_t Model::getNrOfDOFs() const
{
    return nrOfDOFs;
}

/////////////////////////////////////////////////////////////////////
///// Frame Related functions
/////////////////////////////////////////////////////////////////////
size_t Model::getNrOfFrames() const
{
    return (size_t)getNrOfLinks() + this->additionalFrames.size();
}

std::string Model::getFrameName(const FrameIndex frameIndex) const
{
    if( frameIndex >= 0 && frameIndex < (FrameIndex)this->getNrOfLinks() )
    {
        return linkNames[frameIndex];
    }
    else if( frameIndex >= this->getNrOfLinks() && frameIndex < (FrameIndex)this->getNrOfFrames() )
    {
        return frameNames[frameIndex-getNrOfLinks()];
    }
    else
    {
        return FRAME_INVALID_NAME;
    }
}

FrameIndex Model::getFrameIndex(const std::string& frameName) const
{
    for(int i=0; i < this->getNrOfLinks(); i++ )
    {
        if( frameName == linkNames[i] )
        {
            return (FrameIndex)i;
        }
    }

    for(int i=this->getNrOfLinks(); i < this->getNrOfFrames(); i++ )
    {
        if( frameName == this->frameNames[i-getNrOfLinks()] )
        {
            return (FrameIndex)i;
        }
    }

    return FRAME_INVALID_INDEX;
}

bool Model::isFrameNameUsed(const std::string frameName)
{
    return (FRAME_INVALID_INDEX != getFrameIndex(frameName));
}

bool Model::addAdditionalFrameToLink(const std::string& linkName,
                                     const std::string& frameName,
                                     Transform link_H_frame)
{
    // Check that the link actually exist
    LinkIndex linkIndex = this->getLinkIndex(linkName);
    if( linkIndex == LINK_INVALID_INDEX )
    {
        std::string error = "error adding frame " + frameName + " : a link of name "
                            + linkName + " is not present in the model";
        reportError("Model","addAdditionalFrameToLink",error.c_str());
        return false;
    }

    // Check that the frame name is not already used by a link or frame
    if(isFrameNameUsed(frameName))
    {
        std::string error = "a link or frame of name " + frameName + " is already present in the model";
        reportError("Model","addAdditionalFrameToLink",error.c_str());
        return false;
    }

    // If all error has passed, actually add the frame
    this->additionalFrames.push_back(link_H_frame);
    this->additionalFramesLinks.push_back(linkIndex);
    this->frameNames.push_back(frameName);

    return true;
}

Transform Model::getFrameTransform(const FrameIndex frameIndex) const
{
    // The link_H_frame transform for the link
    // main frame is the identity
    if( frameIndex < this->getNrOfLinks() ||
        frameIndex >= this->getNrOfFrames() )
    {
        return Transform::Identity();
    }

    // For an additonal frame the transform is instead stored
    // in the additionalFrames vector
    return this->additionalFrames[frameIndex-getNrOfLinks()];
}

LinkIndex Model::getFrameLink(const FrameIndex frameIndex) const
{
    // The link_H_frame transform for the link
    // main frame is the link it self
    if( frameIndex >= 0 &&
        frameIndex < this->getNrOfLinks() )
    {
        return (LinkIndex)frameIndex;
    }

    if( frameIndex >= this->getNrOfLinks() &&
        frameIndex < this->getNrOfFrames() )
    {
        // For an additonal frame the link index is instead stored
        // in the additionalFramesLinks vector
        return this->additionalFramesLinks[frameIndex-getNrOfLinks()];
    }

    // If the frameIndex is out of bounds, return an invalid index
    return LINK_INVALID_INDEX;
}

unsigned int Model::getNrOfNeighbors(const LinkIndex link) const
{
    assert(link < this->neighbors.size());
    return this->neighbors[link].size();
}

Neighbor Model::getNeighbor(const LinkIndex link, unsigned int neighborIndex) const
{
    assert(link < this->getNrOfLinks());
    assert(neighborIndex < this->getNrOfNeighbors(link));
    return this->neighbors[link][neighborIndex];
}

bool Model::setDefaultBaseLink(const LinkIndex linkIndex)
{
    if( linkIndex < 0 || linkIndex >= this->getNrOfLinks() )
    {
        return false;
    }
    else
    {
        defaultBaseLink = linkIndex;
        return true;
    }
}

LinkIndex Model::getDefaultBaseLink() const
{
    return defaultBaseLink;
}

bool Model::computeFullTreeTraversal(Traversal & traversal) const
{
    return computeFullTreeTraversal(traversal,this->getDefaultBaseLink());
}

struct stackEl { LinkConstPtr link; LinkConstPtr parent;};

void  addBaseLinkToTraversal(const Model & model, Traversal & traversal, int & traversalFirstEmptySlot,
                                    LinkIndex linkToAdd, std::deque<stackEl> & linkToVisit)
{
    assert(traversalFirstEmptySlot == 0);
    traversal.setTraversalElement(traversalFirstEmptySlot,
                                  model.getLink(linkToAdd),
                                  0,
                                  0);

    traversalFirstEmptySlot++;

    stackEl el;
    el.link = model.getLink(linkToAdd);
    el.parent = 0;

    linkToVisit.push_back(el);
}

void addLinkToTraversal(const Model & model, Traversal & traversal, int & traversalFirstEmptySlot,
                        LinkIndex linkToAdd, JointIndex parentJointToAdd, LinkIndex parentLinkToAdd,
                        std::deque<stackEl> & linkToVisit)
{
    traversal.setTraversalElement(traversalFirstEmptySlot,
                                  model.getLink(linkToAdd),
                                  model.getJoint(parentJointToAdd),
                                  model.getLink(parentLinkToAdd));

    traversalFirstEmptySlot++;

    stackEl el;
    el.link = model.getLink(linkToAdd);
    el.parent = model.getLink(parentLinkToAdd);

    linkToVisit.push_back(el);
}

bool Model::computeFullTreeTraversal(Traversal & traversal, const LinkIndex traversalBase) const
{
    if( traversalBase < 0 || traversalBase >= this->getNrOfLinks() )
    {
        reportError("Model","computeFullTreeTraversal","requested traversalBase is out of bounds");
        return false;
    }

    // The full tree traversal is a traversal spanning all the links
    // of a model, so it include getNrOfLinks() visited links
    traversal.reset(this->getNrOfLinks(),this->getNrOfLinks());

    // A link is considered visit when all its child (given the traversalBase)
    // have been added to the traversal
    std::deque<stackEl> linkToVisit;

    // We add as first link the requested traversalBase
    int traversalFirstEmptySlot = 0;
    addBaseLinkToTraversal(*this,traversal,traversalFirstEmptySlot,traversalBase,linkToVisit);

    // while there is some link still to visit
    unsigned int visitNumber=0;
    while( linkToVisit.size() > 0 )
    {
        assert(linkToVisit.size() <= this->getNrOfLinks());

        // DPS : we use linkToVisit as a stack
        LinkConstPtr visitedLink = linkToVisit.back().link;
        LinkConstPtr visitedLinkParent = linkToVisit.back().parent;
        LinkIndex visitedLinkIndex = visitedLink->getIndex();
        linkToVisit.pop_back();

        for(unsigned int neigh_i=0; neigh_i < this->getNrOfNeighbors(visitedLinkIndex); neigh_i++ )
        {
            // add to the stack all the neighbors, except for parent link
            // (if the visited link is the base one, add all the neighbors)
            // the visited link is already in the Traversal, so we can use it
            // to check for its parent
            Neighbor neighb = this->getNeighbor(visitedLinkIndex,neigh_i);
            if( visitedLinkParent == 0 || neighb.neighborLink != visitedLinkParent->getIndex() )
            {
                addLinkToTraversal(*this,traversal,traversalFirstEmptySlot,neighb.neighborLink,
                    neighb.neighborJoint,visitedLink->getIndex(),linkToVisit);
            }
        }
    }

    return true;
}

}
<|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 "chrome/browser/browser_main.h"
#include "chrome/browser/browser_main_win.h"

#include <windows.h>
#include <shellapi.h>

#include <algorithm>

#include "app/l10n_util.h"
#include "app/l10n_util_win.h"
#include "app/win_util.h"
#include "base/command_line.h"
#include "base/environment.h"
#include "base/i18n/rtl.h"
#include "base/nss_util.h"
#include "base/path_service.h"
#include "base/scoped_ptr.h"
#include "base/utf_string_conversions.h"
#include "base/win/windows_version.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/first_run/first_run.h"
#include "chrome/browser/metrics/metrics_service.h"
#include "chrome/browser/views/uninstall_view.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/env_vars.h"
#include "chrome/common/main_function_params.h"
#include "chrome/common/result_codes.h"
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/helper.h"
#include "chrome/installer/util/install_util.h"
#include "chrome/installer/util/shell_util.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "net/base/winsock_init.h"
#include "net/socket/ssl_client_socket_nss_factory.h"
#include "views/focus/accelerator_handler.h"
#include "views/window/window.h"

void DidEndMainMessageLoop() {
  OleUninitialize();
}

void RecordBreakpadStatusUMA(MetricsService* metrics) {
  DWORD len = ::GetEnvironmentVariableW(
      ASCIIToWide(env_vars::kNoOOBreakpad).c_str() , NULL, 0);
  metrics->RecordBreakpadRegistration((len == 0));
  metrics->RecordBreakpadHasDebugger(TRUE == ::IsDebuggerPresent());
}

void WarnAboutMinimumSystemRequirements() {
  if (base::win::GetVersion() < base::win::VERSION_XP) {
    // Display a warning message if the user is running chrome on Windows 2000.
    const std::wstring text =
        l10n_util::GetString(IDS_UNSUPPORTED_OS_PRE_WIN_XP);
    const std::wstring caption = l10n_util::GetString(IDS_PRODUCT_NAME);
    win_util::MessageBox(NULL, text, caption,
                         MB_OK | MB_ICONWARNING | MB_TOPMOST);
  }
}

int AskForUninstallConfirmation() {
  int ret = ResultCodes::NORMAL_EXIT;
  views::Window::CreateChromeWindow(NULL, gfx::Rect(),
                                    new UninstallView(ret))->Show();
  views::AcceleratorHandler accelerator_handler;
  MessageLoopForUI::current()->Run(&accelerator_handler);
  return ret;
}

void ShowCloseBrowserFirstMessageBox() {
  const std::wstring text = l10n_util::GetString(IDS_UNINSTALL_CLOSE_APP);
  const std::wstring caption = l10n_util::GetString(IDS_PRODUCT_NAME);
  const UINT flags = MB_OK | MB_ICONWARNING | MB_TOPMOST;
  win_util::MessageBox(NULL, text, caption, flags);
}

int DoUninstallTasks(bool chrome_still_running) {
  // We want to show a warning to user (and exit) if Chrome is already running
  // *before* we show the uninstall confirmation dialog box. But while the
  // uninstall confirmation dialog is up, user might start Chrome, so we
  // check once again after user acknowledges Uninstall dialog.
  if (chrome_still_running) {
    ShowCloseBrowserFirstMessageBox();
    return ResultCodes::UNINSTALL_CHROME_ALIVE;
  }
  int ret = AskForUninstallConfirmation();
  if (Upgrade::IsBrowserAlreadyRunning()) {
    ShowCloseBrowserFirstMessageBox();
    return ResultCodes::UNINSTALL_CHROME_ALIVE;
  }

  if (ret != ResultCodes::UNINSTALL_USER_CANCEL) {
    // The following actions are just best effort.
    VLOG(1) << "Executing uninstall actions";
    if (!FirstRun::RemoveSentinel())
      VLOG(1) << "Failed to delete sentinel file.";
    // We want to remove user level shortcuts and we only care about the ones
    // created by us and not by the installer so |alternate| is false.
    BrowserDistribution* dist = BrowserDistribution::GetDistribution();
    if (!ShellUtil::RemoveChromeDesktopShortcut(dist, ShellUtil::CURRENT_USER,
                                                false))
      VLOG(1) << "Failed to delete desktop shortcut.";
    if (!ShellUtil::RemoveChromeQuickLaunchShortcut(dist,
                                                    ShellUtil::CURRENT_USER))
      VLOG(1) << "Failed to delete quick launch shortcut.";
  }
  return ret;
}

// Prepares the localized strings that are going to be displayed to
// the user if the browser process dies. These strings are stored in the
// environment block so they are accessible in the early stages of the
// chrome executable's lifetime.
void PrepareRestartOnCrashEnviroment(const CommandLine &parsed_command_line) {
  // Clear this var so child processes don't show the dialog by default.
  scoped_ptr<base::Environment> env(base::Environment::Create());
  env->UnSetVar(env_vars::kShowRestart);

  // For non-interactive tests we don't restart on crash.
  if (env->HasVar(env_vars::kHeadless))
    return;

  // If the known command-line test options are used we don't create the
  // environment block which means we don't get the restart dialog.
  if (parsed_command_line.HasSwitch(switches::kBrowserCrashTest) ||
      parsed_command_line.HasSwitch(switches::kBrowserAssertTest) ||
      parsed_command_line.HasSwitch(switches::kNoErrorDialogs))
    return;

  // The encoding we use for the info is "title|context|direction" where
  // direction is either env_vars::kRtlLocale or env_vars::kLtrLocale depending
  // on the current locale.
  string16 dlg_strings(l10n_util::GetStringUTF16(IDS_CRASH_RECOVERY_TITLE));
  dlg_strings.push_back('|');
  string16 adjusted_string(
      l10n_util::GetStringUTF16(IDS_CRASH_RECOVERY_CONTENT));
  base::i18n::AdjustStringForLocaleDirection(&adjusted_string);
  dlg_strings.append(adjusted_string);
  dlg_strings.push_back('|');
  dlg_strings.append(ASCIIToUTF16(
      base::i18n::IsRTL() ? env_vars::kRtlLocale : env_vars::kLtrLocale));

  env->SetVar(env_vars::kRestartInfo, UTF16ToUTF8(dlg_strings));
}

// This method handles the --hide-icons and --show-icons command line options
// for chrome that get triggered by Windows from registry entries
// HideIconsCommand & ShowIconsCommand. Chrome doesn't support hide icons
// functionality so we just ask the users if they want to uninstall Chrome.
int HandleIconsCommands(const CommandLine &parsed_command_line) {
  if (parsed_command_line.HasSwitch(switches::kHideIcons)) {
    std::wstring cp_applet;
    base::win::Version version = base::win::GetVersion();
    if (version >= base::win::VERSION_VISTA) {
      cp_applet.assign(L"Programs and Features");  // Windows Vista and later.
    } else if (version >= base::win::VERSION_XP) {
      cp_applet.assign(L"Add/Remove Programs");  // Windows XP.
    } else {
      return ResultCodes::UNSUPPORTED_PARAM;  // Not supported
    }

    const std::wstring msg = l10n_util::GetStringF(IDS_HIDE_ICONS_NOT_SUPPORTED,
                                                   cp_applet);
    const std::wstring caption = l10n_util::GetString(IDS_PRODUCT_NAME);
    const UINT flags = MB_OKCANCEL | MB_ICONWARNING | MB_TOPMOST;
    if (IDOK == win_util::MessageBox(NULL, msg, caption, flags))
      ShellExecute(NULL, NULL, L"appwiz.cpl", NULL, NULL, SW_SHOWNORMAL);
    return ResultCodes::NORMAL_EXIT;  // Exit as we are not launching browser.
  }
  // We don't hide icons so we shouldn't do anything special to show them
  return ResultCodes::UNSUPPORTED_PARAM;
}

// Check if there is any machine level Chrome installed on the current
// machine. If yes and the current Chrome process is user level, we do not
// allow the user level Chrome to run. So we notify the user and uninstall
// user level Chrome.
bool CheckMachineLevelInstall() {
  // TODO(tommi): Check if using the default distribution is always the right
  // thing to do.
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  scoped_ptr<installer::Version> version(InstallUtil::GetChromeVersion(dist,
                                                                       true));
  if (version.get()) {
    FilePath exe_path;
    PathService::Get(base::DIR_EXE, &exe_path);
    std::wstring exe = exe_path.value();
    FilePath user_exe_path(installer::GetChromeInstallPath(false, dist));
    if (FilePath::CompareEqualIgnoreCase(exe, user_exe_path.value())) {
      const std::wstring text =
          l10n_util::GetString(IDS_MACHINE_LEVEL_INSTALL_CONFLICT);
      const std::wstring caption = l10n_util::GetString(IDS_PRODUCT_NAME);
      const UINT flags = MB_OK | MB_ICONERROR | MB_TOPMOST;
      win_util::MessageBox(NULL, text, caption, flags);
      FilePath uninstall_path(InstallUtil::GetChromeUninstallCmd(false, dist));
      CommandLine uninstall_cmd(uninstall_path);
      if (!uninstall_cmd.GetProgram().value().empty()) {
        uninstall_cmd.AppendSwitch(installer_util::switches::kForceUninstall);
        uninstall_cmd.AppendSwitch(
            installer_util::switches::kDoNotRemoveSharedItems);
        base::LaunchApp(uninstall_cmd, false, false, NULL);
      }
      return true;
    }
  }
  return false;
}

// BrowserMainPartsWin ---------------------------------------------------------

class BrowserMainPartsWin : public BrowserMainParts {
 public:
  explicit BrowserMainPartsWin(const MainFunctionParams& parameters)
      : BrowserMainParts(parameters) {}

 protected:
  virtual void PreEarlyInitialization() {
    // Initialize Winsock.
    net::EnsureWinsockInit();
  }

  virtual void PreMainMessageLoopStart() {
    OleInitialize(NULL);

    // If we're running tests (ui_task is non-null), then the ResourceBundle
    // has already been initialized.
    if (!parameters().ui_task) {
      // Override the configured locale with the user's preferred UI language.
      l10n_util::OverrideLocaleWithUILanguageList();
    }
  }

 private:
  virtual void InitializeSSL() {
    // Use NSS for SSL by default.
    // Because of a build system issue (http://crbug.com/43461), the default
    // client socket factory uses SChannel (the system SSL library) for SSL by
    // default on Windows.
    if (!parsed_command_line().HasSwitch(switches::kUseSystemSSL)) {
      net::ClientSocketFactory::SetSSLClientSocketFactory(
          net::SSLClientSocketNSSFactory);
      // We want to be sure to init NSPR on the main thread.
      base::EnsureNSPRInit();
    }
  }
};

// static
BrowserMainParts* BrowserMainParts::CreateBrowserMainParts(
    const MainFunctionParams& parameters) {
  return new BrowserMainPartsWin(parameters);
}
<commit_msg>Use SChannel for Windows.<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 "chrome/browser/browser_main.h"
#include "chrome/browser/browser_main_win.h"

#include <windows.h>
#include <shellapi.h>

#include <algorithm>

#include "app/l10n_util.h"
#include "app/l10n_util_win.h"
#include "app/win_util.h"
#include "base/command_line.h"
#include "base/environment.h"
#include "base/i18n/rtl.h"
#include "base/nss_util.h"
#include "base/path_service.h"
#include "base/scoped_ptr.h"
#include "base/utf_string_conversions.h"
#include "base/win/windows_version.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/first_run/first_run.h"
#include "chrome/browser/metrics/metrics_service.h"
#include "chrome/browser/views/uninstall_view.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/env_vars.h"
#include "chrome/common/main_function_params.h"
#include "chrome/common/result_codes.h"
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/helper.h"
#include "chrome/installer/util/install_util.h"
#include "chrome/installer/util/shell_util.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "net/base/winsock_init.h"
#include "net/socket/ssl_client_socket_nss_factory.h"
#include "views/focus/accelerator_handler.h"
#include "views/window/window.h"

void DidEndMainMessageLoop() {
  OleUninitialize();
}

void RecordBreakpadStatusUMA(MetricsService* metrics) {
  DWORD len = ::GetEnvironmentVariableW(
      ASCIIToWide(env_vars::kNoOOBreakpad).c_str() , NULL, 0);
  metrics->RecordBreakpadRegistration((len == 0));
  metrics->RecordBreakpadHasDebugger(TRUE == ::IsDebuggerPresent());
}

void WarnAboutMinimumSystemRequirements() {
  if (base::win::GetVersion() < base::win::VERSION_XP) {
    // Display a warning message if the user is running chrome on Windows 2000.
    const std::wstring text =
        l10n_util::GetString(IDS_UNSUPPORTED_OS_PRE_WIN_XP);
    const std::wstring caption = l10n_util::GetString(IDS_PRODUCT_NAME);
    win_util::MessageBox(NULL, text, caption,
                         MB_OK | MB_ICONWARNING | MB_TOPMOST);
  }
}

int AskForUninstallConfirmation() {
  int ret = ResultCodes::NORMAL_EXIT;
  views::Window::CreateChromeWindow(NULL, gfx::Rect(),
                                    new UninstallView(ret))->Show();
  views::AcceleratorHandler accelerator_handler;
  MessageLoopForUI::current()->Run(&accelerator_handler);
  return ret;
}

void ShowCloseBrowserFirstMessageBox() {
  const std::wstring text = l10n_util::GetString(IDS_UNINSTALL_CLOSE_APP);
  const std::wstring caption = l10n_util::GetString(IDS_PRODUCT_NAME);
  const UINT flags = MB_OK | MB_ICONWARNING | MB_TOPMOST;
  win_util::MessageBox(NULL, text, caption, flags);
}

int DoUninstallTasks(bool chrome_still_running) {
  // We want to show a warning to user (and exit) if Chrome is already running
  // *before* we show the uninstall confirmation dialog box. But while the
  // uninstall confirmation dialog is up, user might start Chrome, so we
  // check once again after user acknowledges Uninstall dialog.
  if (chrome_still_running) {
    ShowCloseBrowserFirstMessageBox();
    return ResultCodes::UNINSTALL_CHROME_ALIVE;
  }
  int ret = AskForUninstallConfirmation();
  if (Upgrade::IsBrowserAlreadyRunning()) {
    ShowCloseBrowserFirstMessageBox();
    return ResultCodes::UNINSTALL_CHROME_ALIVE;
  }

  if (ret != ResultCodes::UNINSTALL_USER_CANCEL) {
    // The following actions are just best effort.
    VLOG(1) << "Executing uninstall actions";
    if (!FirstRun::RemoveSentinel())
      VLOG(1) << "Failed to delete sentinel file.";
    // We want to remove user level shortcuts and we only care about the ones
    // created by us and not by the installer so |alternate| is false.
    BrowserDistribution* dist = BrowserDistribution::GetDistribution();
    if (!ShellUtil::RemoveChromeDesktopShortcut(dist, ShellUtil::CURRENT_USER,
                                                false))
      VLOG(1) << "Failed to delete desktop shortcut.";
    if (!ShellUtil::RemoveChromeQuickLaunchShortcut(dist,
                                                    ShellUtil::CURRENT_USER))
      VLOG(1) << "Failed to delete quick launch shortcut.";
  }
  return ret;
}

// Prepares the localized strings that are going to be displayed to
// the user if the browser process dies. These strings are stored in the
// environment block so they are accessible in the early stages of the
// chrome executable's lifetime.
void PrepareRestartOnCrashEnviroment(const CommandLine &parsed_command_line) {
  // Clear this var so child processes don't show the dialog by default.
  scoped_ptr<base::Environment> env(base::Environment::Create());
  env->UnSetVar(env_vars::kShowRestart);

  // For non-interactive tests we don't restart on crash.
  if (env->HasVar(env_vars::kHeadless))
    return;

  // If the known command-line test options are used we don't create the
  // environment block which means we don't get the restart dialog.
  if (parsed_command_line.HasSwitch(switches::kBrowserCrashTest) ||
      parsed_command_line.HasSwitch(switches::kBrowserAssertTest) ||
      parsed_command_line.HasSwitch(switches::kNoErrorDialogs))
    return;

  // The encoding we use for the info is "title|context|direction" where
  // direction is either env_vars::kRtlLocale or env_vars::kLtrLocale depending
  // on the current locale.
  string16 dlg_strings(l10n_util::GetStringUTF16(IDS_CRASH_RECOVERY_TITLE));
  dlg_strings.push_back('|');
  string16 adjusted_string(
      l10n_util::GetStringUTF16(IDS_CRASH_RECOVERY_CONTENT));
  base::i18n::AdjustStringForLocaleDirection(&adjusted_string);
  dlg_strings.append(adjusted_string);
  dlg_strings.push_back('|');
  dlg_strings.append(ASCIIToUTF16(
      base::i18n::IsRTL() ? env_vars::kRtlLocale : env_vars::kLtrLocale));

  env->SetVar(env_vars::kRestartInfo, UTF16ToUTF8(dlg_strings));
}

// This method handles the --hide-icons and --show-icons command line options
// for chrome that get triggered by Windows from registry entries
// HideIconsCommand & ShowIconsCommand. Chrome doesn't support hide icons
// functionality so we just ask the users if they want to uninstall Chrome.
int HandleIconsCommands(const CommandLine &parsed_command_line) {
  if (parsed_command_line.HasSwitch(switches::kHideIcons)) {
    std::wstring cp_applet;
    base::win::Version version = base::win::GetVersion();
    if (version >= base::win::VERSION_VISTA) {
      cp_applet.assign(L"Programs and Features");  // Windows Vista and later.
    } else if (version >= base::win::VERSION_XP) {
      cp_applet.assign(L"Add/Remove Programs");  // Windows XP.
    } else {
      return ResultCodes::UNSUPPORTED_PARAM;  // Not supported
    }

    const std::wstring msg = l10n_util::GetStringF(IDS_HIDE_ICONS_NOT_SUPPORTED,
                                                   cp_applet);
    const std::wstring caption = l10n_util::GetString(IDS_PRODUCT_NAME);
    const UINT flags = MB_OKCANCEL | MB_ICONWARNING | MB_TOPMOST;
    if (IDOK == win_util::MessageBox(NULL, msg, caption, flags))
      ShellExecute(NULL, NULL, L"appwiz.cpl", NULL, NULL, SW_SHOWNORMAL);
    return ResultCodes::NORMAL_EXIT;  // Exit as we are not launching browser.
  }
  // We don't hide icons so we shouldn't do anything special to show them
  return ResultCodes::UNSUPPORTED_PARAM;
}

// Check if there is any machine level Chrome installed on the current
// machine. If yes and the current Chrome process is user level, we do not
// allow the user level Chrome to run. So we notify the user and uninstall
// user level Chrome.
bool CheckMachineLevelInstall() {
  // TODO(tommi): Check if using the default distribution is always the right
  // thing to do.
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  scoped_ptr<installer::Version> version(InstallUtil::GetChromeVersion(dist,
                                                                       true));
  if (version.get()) {
    FilePath exe_path;
    PathService::Get(base::DIR_EXE, &exe_path);
    std::wstring exe = exe_path.value();
    FilePath user_exe_path(installer::GetChromeInstallPath(false, dist));
    if (FilePath::CompareEqualIgnoreCase(exe, user_exe_path.value())) {
      const std::wstring text =
          l10n_util::GetString(IDS_MACHINE_LEVEL_INSTALL_CONFLICT);
      const std::wstring caption = l10n_util::GetString(IDS_PRODUCT_NAME);
      const UINT flags = MB_OK | MB_ICONERROR | MB_TOPMOST;
      win_util::MessageBox(NULL, text, caption, flags);
      FilePath uninstall_path(InstallUtil::GetChromeUninstallCmd(false, dist));
      CommandLine uninstall_cmd(uninstall_path);
      if (!uninstall_cmd.GetProgram().value().empty()) {
        uninstall_cmd.AppendSwitch(installer_util::switches::kForceUninstall);
        uninstall_cmd.AppendSwitch(
            installer_util::switches::kDoNotRemoveSharedItems);
        base::LaunchApp(uninstall_cmd, false, false, NULL);
      }
      return true;
    }
  }
  return false;
}

// BrowserMainPartsWin ---------------------------------------------------------

class BrowserMainPartsWin : public BrowserMainParts {
 public:
  explicit BrowserMainPartsWin(const MainFunctionParams& parameters)
      : BrowserMainParts(parameters) {}

 protected:
  virtual void PreEarlyInitialization() {
    // Initialize Winsock.
    net::EnsureWinsockInit();
  }

  virtual void PreMainMessageLoopStart() {
    OleInitialize(NULL);

    // If we're running tests (ui_task is non-null), then the ResourceBundle
    // has already been initialized.
    if (!parameters().ui_task) {
      // Override the configured locale with the user's preferred UI language.
      l10n_util::OverrideLocaleWithUILanguageList();
    }
  }

 private:
  virtual void InitializeSSL() {
    // Use NSS for SSL by default.
    // Because of a build system issue (http://crbug.com/43461), the default
    // client socket factory uses SChannel (the system SSL library) for SSL by
    // default on Windows.

    // Disabling this temporarily to test out if NSS is causing heap corruption.
#if 0
    if (!parsed_command_line().HasSwitch(switches::kUseSystemSSL)) {
      net::ClientSocketFactory::SetSSLClientSocketFactory(
          net::SSLClientSocketNSSFactory);
      // We want to be sure to init NSPR on the main thread.
      base::EnsureNSPRInit();
    }
#endif
  }
};

// static
BrowserMainParts* BrowserMainParts::CreateBrowserMainParts(
    const MainFunctionParams& parameters) {
  return new BrowserMainPartsWin(parameters);
}
<|endoftext|>


<commit_before>#include "../../includes/linux/InotifyEventLoop.h"

InotifyEventLoop::InotifyEventLoop(
  int inotifyInstance,
  InotifyService *inotifyService
) :
  mInotifyInstance(inotifyInstance),
  mInotifyService(inotifyService)
{
  mStarted = !pthread_create(
    &mEventLoop,
    NULL,
    [](void *eventLoop)->void * {
      ((InotifyEventLoop *)eventLoop)->work();
      return NULL;
    },
    (void *)this
  );
    if (mStarted) { mLoopingSemaphore.wait(); }
}

bool InotifyEventLoop::isLooping() {
  return mStarted;
}

void InotifyEventLoop::work() {
  char buffer[BUFFER_SIZE];
  inotify_event *event = NULL;
  unsigned int bytesRead, position = 0;
  bool isDirectoryEvent = false, isDirectoryRemoval = false;
  InotifyService *inotifyService = mInotifyService;
  InotifyRenameEvent renameEvent;
  renameEvent.isStarted = false;

  auto create = [&event, &isDirectoryEvent, &inotifyService]() {
    if (event == NULL) {
      return;
    }

    if (isDirectoryEvent) {
      inotifyService->createDirectory(event->wd, strdup(event->name));
    } else {
      inotifyService->create(event->wd, strdup(event->name));
    }
  };

  auto modify = [&event, &isDirectoryEvent, &inotifyService]() {
    if (event == NULL) {
      return;
    }

    inotifyService->modify(event->wd, strdup(event->name));
  };

  auto remove = [&event, &isDirectoryRemoval, &inotifyService]() {
    if (event == NULL) {
      return;
    }

    if (isDirectoryRemoval) {
      inotifyService->removeDirectory(event->wd);
    } else {
      inotifyService->remove(event->wd, strdup(event->name));
    }
  };

  auto renameStart = [&event, &isDirectoryEvent, &renameEvent]() {
    renameEvent.cookie = event->cookie;
    renameEvent.isDirectory = isDirectoryEvent;
    renameEvent.name = event->name;
    renameEvent.wd = event->wd;
    renameEvent.isStarted = true;
  };

  auto renameEnd = [&create, &event, &inotifyService, &isDirectoryEvent, &renameEvent]() {
    if (!renameEvent.isStarted) {
      create();
      return;
    }

    if (renameEvent.cookie != event->cookie) {
      if (renameEvent.isDirectory) {
        inotifyService->removeDirectory(renameEvent.wd);
      } else {
        inotifyService->remove(renameEvent.wd, renameEvent.name);
      }
      create();
    } else {
      if (renameEvent.isDirectory) {
        inotifyService->renameDirectory(renameEvent.wd, renameEvent.name, event->wd, event->name);
      } else {
        inotifyService->rename(renameEvent.wd, renameEvent.name, event->wd, event->name);
      }
    }
    renameEvent.isStarted = false;
  };

  mLoopingSemaphore.signal();
  while((bytesRead = read(mInotifyInstance, &buffer, BUFFER_SIZE)) > 0) {
    std::lock_guard<std::mutex> syncWithDestructor(mMutex);
    do {
      event = (struct inotify_event *)(buffer + position);

      if (renameEvent.isStarted && event->cookie != renameEvent.cookie) {
        renameEnd();
      }

      isDirectoryRemoval = event->mask & (uint32_t)(IN_IGNORED | IN_DELETE_SELF);
      isDirectoryEvent = event->mask & (uint32_t)(IN_ISDIR);

      if (!isDirectoryRemoval && *event->name <= 31) {
        continue;
      }

      if (event->mask & (uint32_t)(IN_ATTRIB | IN_MODIFY)) {
        modify();
      } else if (event->mask & (uint32_t)IN_CREATE) {
        create();
      } else if (event->mask & (uint32_t)(IN_DELETE | IN_DELETE_SELF)) {
        remove();
      } else if (event->mask & (uint32_t)IN_MOVED_TO) {
        if (event->cookie == 0) {
          create();
          continue;
        }

        renameEnd();
      } else if (event->mask & (uint32_t)IN_MOVED_FROM) {
        if (event->cookie == 0) {
          remove();
          continue;
        }

        renameStart();
      } else if (event->mask & (uint32_t)IN_MOVE_SELF) {
        inotifyService->remove(event->wd, strdup(event->name));
        inotifyService->removeDirectory(event->wd);
      }
    } while((position += sizeof(struct inotify_event) + event->len) < bytesRead);
    if (renameEvent.isStarted) {
      remove();
      renameEvent.isStarted = false;
    }
    position = 0;
  }
  mStarted = false;
}

InotifyEventLoop::~InotifyEventLoop() {
  if (!mStarted) {
    return;
  }

  {
    std::lock_guard<std::mutex> syncWithWork(mMutex);
    pthread_cancel(mEventLoop);
  }

  pthread_join(mEventLoop, NULL);
}
<commit_msg>Fix memory leaks caused by unneeded strdup()<commit_after>#include "../../includes/linux/InotifyEventLoop.h"

InotifyEventLoop::InotifyEventLoop(
  int inotifyInstance,
  InotifyService *inotifyService
) :
  mInotifyInstance(inotifyInstance),
  mInotifyService(inotifyService)
{
  mStarted = !pthread_create(
    &mEventLoop,
    NULL,
    [](void *eventLoop)->void * {
      ((InotifyEventLoop *)eventLoop)->work();
      return NULL;
    },
    (void *)this
  );
    if (mStarted) { mLoopingSemaphore.wait(); }
}

bool InotifyEventLoop::isLooping() {
  return mStarted;
}

void InotifyEventLoop::work() {
  char buffer[BUFFER_SIZE];
  inotify_event *event = NULL;
  unsigned int bytesRead, position = 0;
  bool isDirectoryEvent = false, isDirectoryRemoval = false;
  InotifyService *inotifyService = mInotifyService;
  InotifyRenameEvent renameEvent;
  renameEvent.isStarted = false;

  auto create = [&event, &isDirectoryEvent, &inotifyService]() {
    if (event == NULL) {
      return;
    }

    if (isDirectoryEvent) {
      inotifyService->createDirectory(event->wd, event->name);
    } else {
      inotifyService->create(event->wd, event->name);
    }
  };

  auto modify = [&event, &isDirectoryEvent, &inotifyService]() {
    if (event == NULL) {
      return;
    }

    inotifyService->modify(event->wd, event->name);
  };

  auto remove = [&event, &isDirectoryRemoval, &inotifyService]() {
    if (event == NULL) {
      return;
    }

    if (isDirectoryRemoval) {
      inotifyService->removeDirectory(event->wd);
    } else {
      inotifyService->remove(event->wd, event->name);
    }
  };

  auto renameStart = [&event, &isDirectoryEvent, &renameEvent]() {
    renameEvent.cookie = event->cookie;
    renameEvent.isDirectory = isDirectoryEvent;
    renameEvent.name = event->name;
    renameEvent.wd = event->wd;
    renameEvent.isStarted = true;
  };

  auto renameEnd = [&create, &event, &inotifyService, &isDirectoryEvent, &renameEvent]() {
    if (!renameEvent.isStarted) {
      create();
      return;
    }

    if (renameEvent.cookie != event->cookie) {
      if (renameEvent.isDirectory) {
        inotifyService->removeDirectory(renameEvent.wd);
      } else {
        inotifyService->remove(renameEvent.wd, renameEvent.name);
      }
      create();
    } else {
      if (renameEvent.isDirectory) {
        inotifyService->renameDirectory(renameEvent.wd, renameEvent.name, event->wd, event->name);
      } else {
        inotifyService->rename(renameEvent.wd, renameEvent.name, event->wd, event->name);
      }
    }
    renameEvent.isStarted = false;
  };

  mLoopingSemaphore.signal();
  while((bytesRead = read(mInotifyInstance, &buffer, BUFFER_SIZE)) > 0) {
    std::lock_guard<std::mutex> syncWithDestructor(mMutex);
    do {
      event = (struct inotify_event *)(buffer + position);

      if (renameEvent.isStarted && event->cookie != renameEvent.cookie) {
        renameEnd();
      }

      isDirectoryRemoval = event->mask & (uint32_t)(IN_IGNORED | IN_DELETE_SELF);
      isDirectoryEvent = event->mask & (uint32_t)(IN_ISDIR);

      if (!isDirectoryRemoval && *event->name <= 31) {
        continue;
      }

      if (event->mask & (uint32_t)(IN_ATTRIB | IN_MODIFY)) {
        modify();
      } else if (event->mask & (uint32_t)IN_CREATE) {
        create();
      } else if (event->mask & (uint32_t)(IN_DELETE | IN_DELETE_SELF)) {
        remove();
      } else if (event->mask & (uint32_t)IN_MOVED_TO) {
        if (event->cookie == 0) {
          create();
          continue;
        }

        renameEnd();
      } else if (event->mask & (uint32_t)IN_MOVED_FROM) {
        if (event->cookie == 0) {
          remove();
          continue;
        }

        renameStart();
      } else if (event->mask & (uint32_t)IN_MOVE_SELF) {
        inotifyService->remove(event->wd, event->name);
        inotifyService->removeDirectory(event->wd);
      }
    } while((position += sizeof(struct inotify_event) + event->len) < bytesRead);
    if (renameEvent.isStarted) {
      remove();
      renameEvent.isStarted = false;
    }
    position = 0;
  }
  mStarted = false;
}

InotifyEventLoop::~InotifyEventLoop() {
  if (!mStarted) {
    return;
  }

  {
    std::lock_guard<std::mutex> syncWithWork(mMutex);
    pthread_cancel(mEventLoop);
  }

  pthread_join(mEventLoop, NULL);
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2004-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Lisa Hsu
 *          Nathan Binkert
 */

#include <string>

#include "base/trace.hh"
#include "cpu/thread_context.hh"
#include "kern/base_kernel_stats.hh"
#include "kern/tru64/tru64_syscalls.hh"
#include "sim/system.hh"

using namespace std;
using namespace Stats;

namespace Kernel {

Statistics::Statistics(System *system)
    : iplLast(0), iplLastTick(0)
{
}

void
Statistics::regStats(const string &_name)
{
    myname = _name;

    _arm
        .name(name() + ".inst.arm")
        .desc("number of arm instructions executed")
        ;

    _quiesce
        .name(name() + ".inst.quiesce")
        .desc("number of quiesce instructions executed")
        ;

    _iplCount
        .init(32)
        .name(name() + ".ipl_count")
        .desc("number of times we switched to this ipl")
        .flags(total | pdf | nozero | nonan)
        ;

    _iplGood
        .init(32)
        .name(name() + ".ipl_good")
        .desc("number of times we switched to this ipl from a different ipl")
        .flags(total | pdf | nozero | nonan)
        ;

    _iplTicks
        .init(32)
        .name(name() + ".ipl_ticks")
        .desc("number of cycles we spent at this ipl")
        .flags(total | pdf | nozero | nonan)
        ;

    _iplUsed
        .name(name() + ".ipl_used")
        .desc("fraction of swpipl calls that actually changed the ipl")
        .flags(total | nozero | nonan)
        ;

    _iplUsed = _iplGood / _iplCount;

    _syscall
        .init(SystemCalls<Tru64>::Number)
        .name(name() + ".syscall")
        .desc("number of syscalls executed")
        .flags(total | pdf | nozero | nonan)
        ;

    for (int i = 0; i < SystemCalls<Tru64>::Number; ++i) {
        const char *str = "Please fix me";//SystemCalls<Tru64>::name(i);
        if (str) {
            _syscall.subname(i, str);
        }
    }
}

void
Statistics::swpipl(int ipl)
{
    assert(ipl >= 0 && ipl <= 0x1f && "invalid IPL\n");

    _iplCount[ipl]++;

    if (ipl == iplLast)
        return;

    _iplGood[ipl]++;
    _iplTicks[iplLast] += curTick - iplLastTick;
    iplLastTick = curTick;
    iplLast = ipl;
}

void
Statistics::serialize(ostream &os)
{
    SERIALIZE_SCALAR(iplLast);
    SERIALIZE_SCALAR(iplLastTick);
}

void
Statistics::unserialize(Checkpoint *cp, const string &section)
{
    UNSERIALIZE_SCALAR(iplLast);
    UNSERIALIZE_SCALAR(iplLastTick);
}

/* end namespace Kernel */ }
<commit_msg>A cleaner hack.<commit_after>/*
 * Copyright (c) 2004-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Lisa Hsu
 *          Nathan Binkert
 */

#include <string>

#include "base/trace.hh"
#include "cpu/thread_context.hh"
#include "kern/base_kernel_stats.hh"
#include "kern/tru64/tru64_syscalls.hh"
#include "sim/system.hh"

using namespace std;
using namespace Stats;

namespace Kernel {

Statistics::Statistics(System *system)
    : iplLast(0), iplLastTick(0)
{
}

void
Statistics::regStats(const string &_name)
{
    myname = _name;

    _arm
        .name(name() + ".inst.arm")
        .desc("number of arm instructions executed")
        ;

    _quiesce
        .name(name() + ".inst.quiesce")
        .desc("number of quiesce instructions executed")
        ;

    _iplCount
        .init(32)
        .name(name() + ".ipl_count")
        .desc("number of times we switched to this ipl")
        .flags(total | pdf | nozero | nonan)
        ;

    _iplGood
        .init(32)
        .name(name() + ".ipl_good")
        .desc("number of times we switched to this ipl from a different ipl")
        .flags(total | pdf | nozero | nonan)
        ;

    _iplTicks
        .init(32)
        .name(name() + ".ipl_ticks")
        .desc("number of cycles we spent at this ipl")
        .flags(total | pdf | nozero | nonan)
        ;

    _iplUsed
        .name(name() + ".ipl_used")
        .desc("fraction of swpipl calls that actually changed the ipl")
        .flags(total | nozero | nonan)
        ;

    _iplUsed = _iplGood / _iplCount;

    _syscall
        .init(SystemCalls<Tru64>::Number)
        .name(name() + ".syscall")
        .desc("number of syscalls executed")
        .flags(total | pdf | nozero | nonan)
        ;

    //@todo This needs to get the names of syscalls from an appropriate place.
#if 0
    for (int i = 0; i < SystemCalls<Tru64>::Number; ++i) {
        const char *str = SystemCalls<Tru64>::name(i);
        if (str) {
            _syscall.subname(i, str);
        }
    }
#endif
}

void
Statistics::swpipl(int ipl)
{
    assert(ipl >= 0 && ipl <= 0x1f && "invalid IPL\n");

    _iplCount[ipl]++;

    if (ipl == iplLast)
        return;

    _iplGood[ipl]++;
    _iplTicks[iplLast] += curTick - iplLastTick;
    iplLastTick = curTick;
    iplLast = ipl;
}

void
Statistics::serialize(ostream &os)
{
    SERIALIZE_SCALAR(iplLast);
    SERIALIZE_SCALAR(iplLastTick);
}

void
Statistics::unserialize(Checkpoint *cp, const string &section)
{
    UNSERIALIZE_SCALAR(iplLast);
    UNSERIALIZE_SCALAR(iplLastTick);
}

/* end namespace Kernel */ }
<|endoftext|>


<commit_before>#include <sys/types.h>
#include <sys/epoll.h>
#include <sys/errno.h>
#include <sys/time.h>
#include <unistd.h>

#include <common/buffer.h>

#include <event/event_callback.h>
#include <event/event_poll.h>

#define	EPOLL_EVENT_COUNT	128

struct EventPollState {
	int ep_;
};

EventPoll::EventPoll(void)
: log_("/event/poll"),
  read_poll_(),
  write_poll_(),
  state_(new EventPollState())
{
	state_->ep_ = epoll_create(EPOLL_EVENT_COUNT);
	ASSERT(state_->ep_ != -1);
}

EventPoll::~EventPoll()
{
	ASSERT(read_poll_.empty());
	ASSERT(write_poll_.empty());

	if (state_ != NULL) {
		if (state_->ep_ != -1) {
			close(state_->ep_);
			state_->ep_ = -1;
		}
		delete state_;
		state_ = NULL;
	}
}

Action *
EventPoll::poll(const Type& type, int fd, EventCallback *cb)
{
	ASSERT(fd != -1);

	EventPoll::PollHandler *poll_handler;
	struct epoll_event eev;
	bool unique = true;
	eev.data.fd = fd;
	switch (type) {
	case EventPoll::Readable:
		ASSERT(read_poll_.find(fd) == read_poll_.end());
		unique = write_poll_.find(fd) == write_poll_.end();
		poll_handler = &read_poll_[fd];
		eev.events = EPOLLIN | (unique ? 0 : EPOLLOUT);
		break;
	case EventPoll::Writable:
		ASSERT(write_poll_.find(fd) == write_poll_.end());
		unique = read_poll_.find(fd) == read_poll_.end();
		poll_handler = &write_poll_[fd];
		eev.events = EPOLLOUT | (unique ? 0 : EPOLLIN);
		break;
	default:
		NOTREACHED();
	}
	int rv = ::epoll_ctl(state_->ep_, unique ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd, &eev);
	if (rv == -1)
		HALT(log_) << "Could not add event to epoll.";
	ASSERT(rv == 0);
	ASSERT(poll_handler->action_ == NULL);
	poll_handler->callback_ = cb;
	Action *a = new EventPoll::PollAction(this, type, fd);
	return (a);
}

void
EventPoll::cancel(const Type& type, int fd)
{
	EventPoll::PollHandler *poll_handler;

	struct epoll_event eev;
	bool unique = true;
	eev.data.fd = fd;
	switch (type) {
	case EventPoll::Readable:
		ASSERT(read_poll_.find(fd) != read_poll_.end());
		unique = write_poll_.find(fd) == write_poll_.end();
		poll_handler = &read_poll_[fd];
		poll_handler->cancel();
		read_poll_.erase(fd);
		eev.events = unique ? 0 : EPOLLOUT;
		break;
	case EventPoll::Writable:
		ASSERT(write_poll_.find(fd) != write_poll_.end());
		unique = read_poll_.find(fd) == read_poll_.end();
		poll_handler = &write_poll_[fd];
		poll_handler->cancel();
		write_poll_.erase(fd);
		eev.events = unique ? 0 : EPOLLIN;
		break;
	}
	int rv = ::epoll_ctl(state_->ep_, unique ? EPOLL_CTL_DEL : EPOLL_CTL_MOD, fd, &eev);
	if (rv == -1)
		HALT(log_) << "Could not delete event from epoll.";
	ASSERT(rv == 0);
}

void
EventPoll::wait(int ms)
{
	struct timespec ts;

	ts.tv_sec = ms / 1000;
	ts.tv_nsec = (ms % 1000) * 1000000;

	if (idle()) {
		if (ms != -1) {
			int rv;

			rv = nanosleep(&ts, NULL);
			ASSERT(rv != -1);
		}
		return;
	}

	struct epoll_event eev[EPOLL_EVENT_COUNT];
	int evcnt = ::epoll_wait(state_->ep_, eev, EPOLL_EVENT_COUNT, ms);
	if (evcnt == -1) {
		if (errno == EINTR) {
			INFO(log_) << "Received interrupt, ceasing polling until stop handlers have run.";
			return;
		}
		HALT(log_) << "Could not poll epoll.";
	}

	int i;
	for (i = 0; i < evcnt; i++) {
		struct epoll_event *ev = &eev[i];
		EventPoll::PollHandler *poll_handler;
		if ((ev->events & EPOLLIN) != 0) {
			ASSERT(read_poll_.find(ev->data.fd) != read_poll_.end());
			poll_handler = &read_poll_[ev->data.fd];
			poll_handler->callback(Event::Done);
		}

		if ((ev->events & EPOLLOUT) != 0) {
			ASSERT(write_poll_.find(ev->data.fd) != write_poll_.end());
			poll_handler = &write_poll_[ev->data.fd];
			poll_handler->callback(Event::Done);
		}

		if ((ev->events & EPOLLIN) == 0 && (ev->events & EPOLLOUT) == 0) {
			if (read_poll_.find(ev->data.fd) != read_poll_.end()) {
				poll_handler = &read_poll_[ev->data.fd];
			} else if (write_poll_.find(ev->data.fd) != write_poll_.end()) {
				poll_handler = &write_poll_[ev->data.fd];
			} else {
				HALT(log_) << "Unexpected poll fd.";
				continue;
			}

			if ((ev->events & EPOLLERR) != 0) {
				poll_handler->callback(Event::Error);
				continue;
			}

			if ((ev->events & EPOLLHUP) != 0) {
				poll_handler->callback(Event::EOS);
				continue;
			}

			HALT(log_) << "Unexpected poll events: " << ev->events;
		}
	}
}
<commit_msg>Ignore hangup on write polls.<commit_after>#include <sys/types.h>
#include <sys/epoll.h>
#include <sys/errno.h>
#include <sys/time.h>
#include <unistd.h>

#include <common/buffer.h>

#include <event/event_callback.h>
#include <event/event_poll.h>

#define	EPOLL_EVENT_COUNT	128

struct EventPollState {
	int ep_;
};

EventPoll::EventPoll(void)
: log_("/event/poll"),
  read_poll_(),
  write_poll_(),
  state_(new EventPollState())
{
	state_->ep_ = epoll_create(EPOLL_EVENT_COUNT);
	ASSERT(state_->ep_ != -1);
}

EventPoll::~EventPoll()
{
	ASSERT(read_poll_.empty());
	ASSERT(write_poll_.empty());

	if (state_ != NULL) {
		if (state_->ep_ != -1) {
			close(state_->ep_);
			state_->ep_ = -1;
		}
		delete state_;
		state_ = NULL;
	}
}

Action *
EventPoll::poll(const Type& type, int fd, EventCallback *cb)
{
	ASSERT(fd != -1);

	EventPoll::PollHandler *poll_handler;
	struct epoll_event eev;
	bool unique = true;
	eev.data.fd = fd;
	switch (type) {
	case EventPoll::Readable:
		ASSERT(read_poll_.find(fd) == read_poll_.end());
		unique = write_poll_.find(fd) == write_poll_.end();
		poll_handler = &read_poll_[fd];
		eev.events = EPOLLIN | (unique ? 0 : EPOLLOUT);
		break;
	case EventPoll::Writable:
		ASSERT(write_poll_.find(fd) == write_poll_.end());
		unique = read_poll_.find(fd) == read_poll_.end();
		poll_handler = &write_poll_[fd];
		eev.events = EPOLLOUT | (unique ? 0 : EPOLLIN);
		break;
	default:
		NOTREACHED();
	}
	int rv = ::epoll_ctl(state_->ep_, unique ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd, &eev);
	if (rv == -1)
		HALT(log_) << "Could not add event to epoll.";
	ASSERT(rv == 0);
	ASSERT(poll_handler->action_ == NULL);
	poll_handler->callback_ = cb;
	Action *a = new EventPoll::PollAction(this, type, fd);
	return (a);
}

void
EventPoll::cancel(const Type& type, int fd)
{
	EventPoll::PollHandler *poll_handler;

	struct epoll_event eev;
	bool unique = true;
	eev.data.fd = fd;
	switch (type) {
	case EventPoll::Readable:
		ASSERT(read_poll_.find(fd) != read_poll_.end());
		unique = write_poll_.find(fd) == write_poll_.end();
		poll_handler = &read_poll_[fd];
		poll_handler->cancel();
		read_poll_.erase(fd);
		eev.events = unique ? 0 : EPOLLOUT;
		break;
	case EventPoll::Writable:
		ASSERT(write_poll_.find(fd) != write_poll_.end());
		unique = read_poll_.find(fd) == read_poll_.end();
		poll_handler = &write_poll_[fd];
		poll_handler->cancel();
		write_poll_.erase(fd);
		eev.events = unique ? 0 : EPOLLIN;
		break;
	}
	int rv = ::epoll_ctl(state_->ep_, unique ? EPOLL_CTL_DEL : EPOLL_CTL_MOD, fd, &eev);
	if (rv == -1)
		HALT(log_) << "Could not delete event from epoll.";
	ASSERT(rv == 0);
}

void
EventPoll::wait(int ms)
{
	struct timespec ts;

	ts.tv_sec = ms / 1000;
	ts.tv_nsec = (ms % 1000) * 1000000;

	if (idle()) {
		if (ms != -1) {
			int rv;

			rv = nanosleep(&ts, NULL);
			ASSERT(rv != -1);
		}
		return;
	}

	struct epoll_event eev[EPOLL_EVENT_COUNT];
	int evcnt = ::epoll_wait(state_->ep_, eev, EPOLL_EVENT_COUNT, ms);
	if (evcnt == -1) {
		if (errno == EINTR) {
			INFO(log_) << "Received interrupt, ceasing polling until stop handlers have run.";
			return;
		}
		HALT(log_) << "Could not poll epoll.";
	}

	int i;
	for (i = 0; i < evcnt; i++) {
		struct epoll_event *ev = &eev[i];
		EventPoll::PollHandler *poll_handler;
		if ((ev->events & EPOLLIN) != 0) {
			ASSERT(read_poll_.find(ev->data.fd) != read_poll_.end());
			poll_handler = &read_poll_[ev->data.fd];
			poll_handler->callback(Event::Done);
		}

		if ((ev->events & EPOLLOUT) != 0) {
			ASSERT(write_poll_.find(ev->data.fd) != write_poll_.end());
			poll_handler = &write_poll_[ev->data.fd];
			poll_handler->callback(Event::Done);
		}

		if ((ev->events & EPOLLIN) == 0 && (ev->events & EPOLLOUT) == 0) {
			if (read_poll_.find(ev->data.fd) != read_poll_.end()) {
				poll_handler = &read_poll_[ev->data.fd];
			} else if (write_poll_.find(ev->data.fd) != write_poll_.end()) {
				poll_handler = &write_poll_[ev->data.fd];

				if ((ev->events & (EPOLLERR | EPOLLHUP)) == EPOLLHUP) {
					DEBUG(log_) << "Got EPOLLHUP on write poll.";
					continue;
				}
			} else {
				HALT(log_) << "Unexpected poll fd.";
				continue;
			}

			if ((ev->events & EPOLLERR) != 0) {
				poll_handler->callback(Event::Error);
				continue;
			}

			if ((ev->events & EPOLLHUP) != 0) {
				poll_handler->callback(Event::EOS);
				continue;
			}

			HALT(log_) << "Unexpected poll events: " << ev->events;
		}
	}
}
<|endoftext|>