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

#include "base/threading/platform_thread.h"

#include <errno.h>
#include <sched.h>

#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/safe_strerror_posix.h"
#include "base/threading/thread_local.h"
#include "base/threading/thread_restrictions.h"
#include "base/tracked_objects.h"

#if defined(OS_MACOSX)
#include <sys/resource.h>
#include <algorithm>
#endif

#if defined(OS_LINUX)
#include <sys/prctl.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <unistd.h>
#endif

#if defined(OS_ANDROID)
#include "base/android/jni_android.h"
#endif

// TODO(bbudge) Use time.h when NaCl toolchain supports _POSIX_TIMERS
#if defined(OS_NACL)
#include <sys/nacl_syscalls.h>
#endif

namespace base {

#if defined(OS_MACOSX)
void InitThreading();
#endif

namespace {

#if !defined(OS_MACOSX)
// Mac name code is in in platform_thread_mac.mm.
LazyInstance<ThreadLocalPointer<char> >::Leaky
    current_thread_name = LAZY_INSTANCE_INITIALIZER;
#endif

struct ThreadParams {
  PlatformThread::Delegate* delegate;
  bool joinable;
};

void* ThreadFunc(void* params) {
  ThreadParams* thread_params = static_cast<ThreadParams*>(params);
  PlatformThread::Delegate* delegate = thread_params->delegate;
  if (!thread_params->joinable)
    base::ThreadRestrictions::SetSingletonAllowed(false);
  delete thread_params;
  delegate->ThreadMain();
#if defined(OS_ANDROID)
  base::android::DetachFromVM();
#endif
  return NULL;
}

bool CreateThread(size_t stack_size, bool joinable,
                  PlatformThread::Delegate* delegate,
                  PlatformThreadHandle* thread_handle,
                  ThreadPriority priority) {
#if defined(OS_MACOSX)
  base::InitThreading();
#endif  // OS_MACOSX

  bool success = false;
  pthread_attr_t attributes;
  pthread_attr_init(&attributes);

  // Pthreads are joinable by default, so only specify the detached attribute if
  // the thread should be non-joinable.
  if (!joinable) {
    pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED);
  }

#if defined(OS_MACOSX)
  // The Mac OS X default for a pthread stack size is 512kB.
  // Libc-594.1.4/pthreads/pthread.c's pthread_attr_init uses
  // DEFAULT_STACK_SIZE for this purpose.
  //
  // 512kB isn't quite generous enough for some deeply recursive threads that
  // otherwise request the default stack size by specifying 0. Here, adopt
  // glibc's behavior as on Linux, which is to use the current stack size
  // limit (ulimit -s) as the default stack size. See
  // glibc-2.11.1/nptl/nptl-init.c's __pthread_initialize_minimal_internal. To
  // avoid setting the limit below the Mac OS X default or the minimum usable
  // stack size, these values are also considered. If any of these values
  // can't be determined, or if stack size is unlimited (ulimit -s unlimited),
  // stack_size is left at 0 to get the system default.
  //
  // Mac OS X normally only applies ulimit -s to the main thread stack. On
  // contemporary OS X and Linux systems alike, this value is generally 8MB
  // or in that neighborhood.
  if (stack_size == 0) {
    size_t default_stack_size;
    struct rlimit stack_rlimit;
    if (pthread_attr_getstacksize(&attributes, &default_stack_size) == 0 &&
        getrlimit(RLIMIT_STACK, &stack_rlimit) == 0 &&
        stack_rlimit.rlim_cur != RLIM_INFINITY) {
      stack_size = std::max(std::max(default_stack_size,
                                     static_cast<size_t>(PTHREAD_STACK_MIN)),
                            static_cast<size_t>(stack_rlimit.rlim_cur));
    }
  }
#endif  // OS_MACOSX

  if (stack_size > 0)
    pthread_attr_setstacksize(&attributes, stack_size);

  ThreadParams* params = new ThreadParams;
  params->delegate = delegate;
  params->joinable = joinable;
  success = !pthread_create(thread_handle, &attributes, ThreadFunc, params);

  if (priority != kThreadPriority_Normal) {
#if defined(OS_LINUX)
    if (priority == kThreadPriority_RealtimeAudio) {
      // Linux isn't posix compliant with setpriority(2), it will set a thread
      // priority if it is passed a tid, not affecting the rest of the threads
      // in the process.  Setting this priority will only succeed if the user
      // has been granted permission to adjust nice values on the system.
      const int kNiceSetting = -10;
      if (setpriority(PRIO_PROCESS, PlatformThread::CurrentId(), kNiceSetting))
        DVLOG(1) << "Failed to set nice value of thread to " << kNiceSetting;
    } else {
      NOTREACHED() << "Unknown thread priority.";
    }
#else
    PlatformThread::SetThreadPriority(*thread_handle, priority);
#endif
  }

  pthread_attr_destroy(&attributes);
  if (!success)
    delete params;
  return success;
}

}  // namespace

// static
PlatformThreadId PlatformThread::CurrentId() {
  // Pthreads doesn't have the concept of a thread ID, so we have to reach down
  // into the kernel.
#if defined(OS_LINUX)
  return syscall(__NR_gettid);
#elif defined(OS_ANDROID)
  return gettid();
#elif defined(OS_NACL) || defined(OS_SOLARIS)
  return pthread_self();
#elif defined(OS_POSIX)
  return reinterpret_cast<int64>(pthread_self());
#endif
}

// static
void PlatformThread::YieldCurrentThread() {
  sched_yield();
}

// static
void PlatformThread::Sleep(int duration_ms) {
  // NOTE: This function will be supplanted by the other version of Sleep
  // in the future.  See issue 108171 for more information.
  Sleep(TimeDelta::FromMilliseconds(duration_ms));
}

// static
void PlatformThread::Sleep(TimeDelta duration) {
  struct timespec sleep_time, remaining;

  // Break the duration into seconds and nanoseconds.
  // NOTE: TimeDelta's microseconds are int64s while timespec's
  // nanoseconds are longs, so this unpacking must prevent overflow.
  sleep_time.tv_sec = duration.InSeconds();
  duration -= TimeDelta::FromSeconds(sleep_time.tv_sec);
  sleep_time.tv_nsec = duration.InMicroseconds() * 1000;  // nanoseconds

  while (nanosleep(&sleep_time, &remaining) == -1 && errno == EINTR)
    sleep_time = remaining;
}

#if defined(OS_LINUX)
// static
void PlatformThread::SetName(const char* name) {
  // have to cast away const because ThreadLocalPointer does not support const
  // void*
  current_thread_name.Pointer()->Set(const_cast<char*>(name));
  tracked_objects::ThreadData::InitializeThreadContext(name);

  // On linux we can get the thread names to show up in the debugger by setting
  // the process name for the LWP.  We don't want to do this for the main
  // thread because that would rename the process, causing tools like killall
  // to stop working.
  if (PlatformThread::CurrentId() == getpid())
    return;

  // http://0pointer.de/blog/projects/name-your-threads.html
  // Set the name for the LWP (which gets truncated to 15 characters).
  // Note that glibc also has a 'pthread_setname_np' api, but it may not be
  // available everywhere and it's only benefit over using prctl directly is
  // that it can set the name of threads other than the current thread.
  int err = prctl(PR_SET_NAME, name);
  // We expect EPERM failures in sandboxed processes, just ignore those.
  if (err < 0 && errno != EPERM)
    DPLOG(ERROR) << "prctl(PR_SET_NAME)";
}
#elif defined(OS_MACOSX)
// Mac is implemented in platform_thread_mac.mm.
#else
// static
void PlatformThread::SetName(const char* name) {
  // have to cast away const because ThreadLocalPointer does not support const
  // void*
  current_thread_name.Pointer()->Set(const_cast<char*>(name));
  tracked_objects::ThreadData::InitializeThreadContext(name);

  // (This should be relatively simple to implement for the BSDs; I
  // just don't have one handy to test the code on.)
}
#endif  // defined(OS_LINUX)

#if !defined(OS_MACOSX)
// Mac is implemented in platform_thread_mac.mm.
// static
const char* PlatformThread::GetName() {
  return current_thread_name.Pointer()->Get();
}
#endif

// static
bool PlatformThread::Create(size_t stack_size, Delegate* delegate,
                            PlatformThreadHandle* thread_handle) {
  return CreateThread(stack_size, true /* joinable thread */,
                      delegate, thread_handle, kThreadPriority_Normal);
}

// static
bool PlatformThread::CreateWithPriority(size_t stack_size, Delegate* delegate,
                                        PlatformThreadHandle* thread_handle,
                                        ThreadPriority priority) {
  return CreateThread(stack_size, true,  // joinable thread
                      delegate, thread_handle, priority);
}

// static
bool PlatformThread::CreateNonJoinable(size_t stack_size, Delegate* delegate) {
  PlatformThreadHandle unused;

  bool result = CreateThread(stack_size, false /* non-joinable thread */,
                             delegate, &unused, kThreadPriority_Normal);
  return result;
}

// static
void PlatformThread::Join(PlatformThreadHandle thread_handle) {
  // Joining another thread may block the current thread for a long time, since
  // the thread referred to by |thread_handle| may still be running long-lived /
  // blocking tasks.
  base::ThreadRestrictions::AssertIOAllowed();
  pthread_join(thread_handle, NULL);
}

#if !defined(OS_MACOSX)
// Mac OS X uses lower-level mach APIs.

// static
void PlatformThread::SetThreadPriority(PlatformThreadHandle, ThreadPriority) {
  // TODO(crogers): Implement, see http://crbug.com/116172
}
#endif

}  // namespace base
<commit_msg>PPAPI/NaCl: Fix IPC proxy build; pthread_t changed<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/threading/platform_thread.h"

#include <errno.h>
#include <sched.h>

#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/safe_strerror_posix.h"
#include "base/threading/thread_local.h"
#include "base/threading/thread_restrictions.h"
#include "base/tracked_objects.h"

#if defined(OS_MACOSX)
#include <sys/resource.h>
#include <algorithm>
#endif

#if defined(OS_LINUX)
#include <sys/prctl.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <unistd.h>
#endif

#if defined(OS_ANDROID)
#include "base/android/jni_android.h"
#endif

// TODO(bbudge) Use time.h when NaCl toolchain supports _POSIX_TIMERS
#if defined(OS_NACL)
#include <sys/nacl_syscalls.h>
#endif

namespace base {

#if defined(OS_MACOSX)
void InitThreading();
#endif

namespace {

#if !defined(OS_MACOSX)
// Mac name code is in in platform_thread_mac.mm.
LazyInstance<ThreadLocalPointer<char> >::Leaky
    current_thread_name = LAZY_INSTANCE_INITIALIZER;
#endif

struct ThreadParams {
  PlatformThread::Delegate* delegate;
  bool joinable;
};

void* ThreadFunc(void* params) {
  ThreadParams* thread_params = static_cast<ThreadParams*>(params);
  PlatformThread::Delegate* delegate = thread_params->delegate;
  if (!thread_params->joinable)
    base::ThreadRestrictions::SetSingletonAllowed(false);
  delete thread_params;
  delegate->ThreadMain();
#if defined(OS_ANDROID)
  base::android::DetachFromVM();
#endif
  return NULL;
}

bool CreateThread(size_t stack_size, bool joinable,
                  PlatformThread::Delegate* delegate,
                  PlatformThreadHandle* thread_handle,
                  ThreadPriority priority) {
#if defined(OS_MACOSX)
  base::InitThreading();
#endif  // OS_MACOSX

  bool success = false;
  pthread_attr_t attributes;
  pthread_attr_init(&attributes);

  // Pthreads are joinable by default, so only specify the detached attribute if
  // the thread should be non-joinable.
  if (!joinable) {
    pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED);
  }

#if defined(OS_MACOSX)
  // The Mac OS X default for a pthread stack size is 512kB.
  // Libc-594.1.4/pthreads/pthread.c's pthread_attr_init uses
  // DEFAULT_STACK_SIZE for this purpose.
  //
  // 512kB isn't quite generous enough for some deeply recursive threads that
  // otherwise request the default stack size by specifying 0. Here, adopt
  // glibc's behavior as on Linux, which is to use the current stack size
  // limit (ulimit -s) as the default stack size. See
  // glibc-2.11.1/nptl/nptl-init.c's __pthread_initialize_minimal_internal. To
  // avoid setting the limit below the Mac OS X default or the minimum usable
  // stack size, these values are also considered. If any of these values
  // can't be determined, or if stack size is unlimited (ulimit -s unlimited),
  // stack_size is left at 0 to get the system default.
  //
  // Mac OS X normally only applies ulimit -s to the main thread stack. On
  // contemporary OS X and Linux systems alike, this value is generally 8MB
  // or in that neighborhood.
  if (stack_size == 0) {
    size_t default_stack_size;
    struct rlimit stack_rlimit;
    if (pthread_attr_getstacksize(&attributes, &default_stack_size) == 0 &&
        getrlimit(RLIMIT_STACK, &stack_rlimit) == 0 &&
        stack_rlimit.rlim_cur != RLIM_INFINITY) {
      stack_size = std::max(std::max(default_stack_size,
                                     static_cast<size_t>(PTHREAD_STACK_MIN)),
                            static_cast<size_t>(stack_rlimit.rlim_cur));
    }
  }
#endif  // OS_MACOSX

  if (stack_size > 0)
    pthread_attr_setstacksize(&attributes, stack_size);

  ThreadParams* params = new ThreadParams;
  params->delegate = delegate;
  params->joinable = joinable;
  success = !pthread_create(thread_handle, &attributes, ThreadFunc, params);

  if (priority != kThreadPriority_Normal) {
#if defined(OS_LINUX)
    if (priority == kThreadPriority_RealtimeAudio) {
      // Linux isn't posix compliant with setpriority(2), it will set a thread
      // priority if it is passed a tid, not affecting the rest of the threads
      // in the process.  Setting this priority will only succeed if the user
      // has been granted permission to adjust nice values on the system.
      const int kNiceSetting = -10;
      if (setpriority(PRIO_PROCESS, PlatformThread::CurrentId(), kNiceSetting))
        DVLOG(1) << "Failed to set nice value of thread to " << kNiceSetting;
    } else {
      NOTREACHED() << "Unknown thread priority.";
    }
#else
    PlatformThread::SetThreadPriority(*thread_handle, priority);
#endif
  }

  pthread_attr_destroy(&attributes);
  if (!success)
    delete params;
  return success;
}

}  // namespace

// static
PlatformThreadId PlatformThread::CurrentId() {
  // Pthreads doesn't have the concept of a thread ID, so we have to reach down
  // into the kernel.
#if defined(OS_LINUX)
  return syscall(__NR_gettid);
#elif defined(OS_ANDROID)
  return gettid();
#elif defined(OS_SOLARIS)
  return pthread_self();
#elif defined(OS_NACL)
  // Pointers are 32-bits in NaCl.
  return reinterpret_cast<int32>(pthread_self());
#elif defined(OS_POSIX)
  return reinterpret_cast<int64>(pthread_self());
#endif
}

// static
void PlatformThread::YieldCurrentThread() {
  sched_yield();
}

// static
void PlatformThread::Sleep(int duration_ms) {
  // NOTE: This function will be supplanted by the other version of Sleep
  // in the future.  See issue 108171 for more information.
  Sleep(TimeDelta::FromMilliseconds(duration_ms));
}

// static
void PlatformThread::Sleep(TimeDelta duration) {
  struct timespec sleep_time, remaining;

  // Break the duration into seconds and nanoseconds.
  // NOTE: TimeDelta's microseconds are int64s while timespec's
  // nanoseconds are longs, so this unpacking must prevent overflow.
  sleep_time.tv_sec = duration.InSeconds();
  duration -= TimeDelta::FromSeconds(sleep_time.tv_sec);
  sleep_time.tv_nsec = duration.InMicroseconds() * 1000;  // nanoseconds

  while (nanosleep(&sleep_time, &remaining) == -1 && errno == EINTR)
    sleep_time = remaining;
}

#if defined(OS_LINUX)
// static
void PlatformThread::SetName(const char* name) {
  // have to cast away const because ThreadLocalPointer does not support const
  // void*
  current_thread_name.Pointer()->Set(const_cast<char*>(name));
  tracked_objects::ThreadData::InitializeThreadContext(name);

  // On linux we can get the thread names to show up in the debugger by setting
  // the process name for the LWP.  We don't want to do this for the main
  // thread because that would rename the process, causing tools like killall
  // to stop working.
  if (PlatformThread::CurrentId() == getpid())
    return;

  // http://0pointer.de/blog/projects/name-your-threads.html
  // Set the name for the LWP (which gets truncated to 15 characters).
  // Note that glibc also has a 'pthread_setname_np' api, but it may not be
  // available everywhere and it's only benefit over using prctl directly is
  // that it can set the name of threads other than the current thread.
  int err = prctl(PR_SET_NAME, name);
  // We expect EPERM failures in sandboxed processes, just ignore those.
  if (err < 0 && errno != EPERM)
    DPLOG(ERROR) << "prctl(PR_SET_NAME)";
}
#elif defined(OS_MACOSX)
// Mac is implemented in platform_thread_mac.mm.
#else
// static
void PlatformThread::SetName(const char* name) {
  // have to cast away const because ThreadLocalPointer does not support const
  // void*
  current_thread_name.Pointer()->Set(const_cast<char*>(name));
  tracked_objects::ThreadData::InitializeThreadContext(name);

  // (This should be relatively simple to implement for the BSDs; I
  // just don't have one handy to test the code on.)
}
#endif  // defined(OS_LINUX)

#if !defined(OS_MACOSX)
// Mac is implemented in platform_thread_mac.mm.
// static
const char* PlatformThread::GetName() {
  return current_thread_name.Pointer()->Get();
}
#endif

// static
bool PlatformThread::Create(size_t stack_size, Delegate* delegate,
                            PlatformThreadHandle* thread_handle) {
  return CreateThread(stack_size, true /* joinable thread */,
                      delegate, thread_handle, kThreadPriority_Normal);
}

// static
bool PlatformThread::CreateWithPriority(size_t stack_size, Delegate* delegate,
                                        PlatformThreadHandle* thread_handle,
                                        ThreadPriority priority) {
  return CreateThread(stack_size, true,  // joinable thread
                      delegate, thread_handle, priority);
}

// static
bool PlatformThread::CreateNonJoinable(size_t stack_size, Delegate* delegate) {
  PlatformThreadHandle unused;

  bool result = CreateThread(stack_size, false /* non-joinable thread */,
                             delegate, &unused, kThreadPriority_Normal);
  return result;
}

// static
void PlatformThread::Join(PlatformThreadHandle thread_handle) {
  // Joining another thread may block the current thread for a long time, since
  // the thread referred to by |thread_handle| may still be running long-lived /
  // blocking tasks.
  base::ThreadRestrictions::AssertIOAllowed();
  pthread_join(thread_handle, NULL);
}

#if !defined(OS_MACOSX)
// Mac OS X uses lower-level mach APIs.

// static
void PlatformThread::SetThreadPriority(PlatformThreadHandle, ThreadPriority) {
  // TODO(crogers): Implement, see http://crbug.com/116172
}
#endif

}  // namespace base
<|endoftext|>


<commit_before>/*
Copyright (c) 2012, William Magato
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

   1. Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

   2. 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.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the copyright holder(s) or contributors.
*/

#include <iostream>

#include <latency/protocols/llamaNET.h>
#include <latency/parse_args.cpp>
#include <latency/verify.h>
#include <llamaos/api/sleep.h>
#include <llamaos/xen/Hypervisor.h>

using namespace std;
using namespace latency;
using namespace latency::protocols;
using namespace llamaos;
using namespace llamaos::xen;

Protocol *Protocol::create (int argc, char *argv [])
{
   return new llamaNET (argc, argv);
}

static uint32_t seq = 1;

static domid_t get_domd_id (int node)
{
   // for now it's just self minus node % 6
   domid_t self_id = Hypervisor::get_instance ()->domid;

   return (self_id - 1 - (node / 2));
}

llamaNET::llamaNET (int argc, char *argv [])
   :  node(parse<uint32_t>(argc, argv, "--node", 0U)),
      client((node % 2) == 0),
      interface(get_domd_id (node), (node / 2))
{
   cout << "latency-llamaNET" << endl
        << "  node: " << node << endl;
}

llamaNET::~llamaNET ()
{

}

bool llamaNET::root_node ()
{
   return client;
}

bool llamaNET::startup (unsigned long max_msg_size)
{
   return true;
}

bool llamaNET::cleanup ()
{
   api::sleep (2);

   // release interface ?
   return true;
}

bool llamaNET::run_verify (unsigned long msg_size)
{
   // TCP doesn't send anything for a zero length message, so make it 8 bytes
   msg_size = max (8UL, msg_size);

   // llamaNET is configured for 1 page max message and has a 36 byte header, so make it 4060 bytes
   msg_size = min (4060UL, msg_size);

   net::llamaNET::Protocol_header *header;
   unsigned char *data;

   // dalai initiates the trial
   if (client)
   {
      header = interface.get_send_buffer ();
      header->dest = (node % 2) ? (node - 1) : (node + 1);
      header->src = node;
      header->type = 1;
      header->seq = seq++;
      header->len = msg_size;

      // get pointer to data section of buffer
      data = reinterpret_cast<unsigned char *>(header + 1);

      // marks all bytes with alpha chars (a,b,c,...)
      mark_data_alpha (data, msg_size);

      // send/recv and verify the data has been changed to numerals (1,2,3,...)
      interface.send (header);
      header = interface.recv (node);

      // get pointer to data section of buffer
      data = reinterpret_cast<unsigned char *>(header + 1);

      if (verify_data_numeric (data, msg_size))
      {
         interface.release_recv_buffer (header);

         return true;
      }
   }
   else
   {
      header = interface.recv (node);

      // get pointer to data section of buffer
      data = reinterpret_cast<unsigned char *>(header + 1);

      if (verify_data_alpha (data, msg_size))
      {
         interface.release_recv_buffer (header);

         header = interface.get_send_buffer ();
         header->dest = (node % 2) ? (node - 1) : (node + 1);
         header->src = node;
         header->type = 1;
         header->seq = seq++;
         header->len = msg_size;

         // get pointer to data section of buffer
         data = reinterpret_cast<unsigned char *>(header + 1);

         // marks all bytes with numerals and send
         mark_data_numeric (data, msg_size);

         interface.send (header);
         return true;
      }
   }

   return false;
}

bool llamaNET::run_trial (unsigned long msg_size, unsigned long trial_number)
{
   // TCP doesn't send anything for a zero length message, so make it 8 bytes
   msg_size = max (8UL, msg_size);

   // llamaNET is configured for 1 page max message and has a 36 byte header, so make it 4060 bytes
   msg_size = min (4060UL, msg_size);

   net::llamaNET::Protocol_header *header;
   unsigned char *data;

#define COUNT 16

   // dalai initiates the trial
   if (client)
   {
      for (int i = 0; i < COUNT; i++) {
      header = interface.get_send_buffer ();
      header->dest = (node % 2) ? (node - 1) : (node + 1);
      header->src = node;
      header->type = 1;
      header->seq = seq++;
      header->len = msg_size;

      interface.send (header);
      }

      for (int i = 0; i < COUNT; i++) {
      header = interface.recv (node);

      // get pointer to data section of buffer
      data = reinterpret_cast<unsigned char *>(header + 1);

      if (*(reinterpret_cast<unsigned long *>(data)) == trial_number)
      {
         interface.release_recv_buffer (header);
         trial_number++;
         // return true;
      }
      else
      {
         cout << "data error: " << *(reinterpret_cast<unsigned long *>(data))  << " == " << trial_number << endl;
         interface.release_recv_buffer (header);
         return false;
      }
      }

      return true;
   }
   else
   {
      for (int i = 0; i < COUNT; i++) {
      header = interface.recv (node);
      interface.release_recv_buffer (header);
      }

      for (int i = 0; i < COUNT; i++) {
      header = interface.get_send_buffer ();
      header->dest = (node % 2) ? (node - 1) : (node + 1);
      header->src = node;
      header->type = 1;
      header->seq = seq++;
      header->len = msg_size;

      // get pointer to data section of buffer
      data = reinterpret_cast<unsigned char *>(header + 1);

      // place trial number in first "int" for master to verify
      *(reinterpret_cast<unsigned long *>(data)) = trial_number++;

      interface.send (header);
      }
      return true;
   }

   return false;
}
<commit_msg>restore latency normal operation<commit_after>/*
Copyright (c) 2012, William Magato
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

   1. Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

   2. 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.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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 HOLDER(S) 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.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the copyright holder(s) or contributors.
*/

#include <iostream>

#include <latency/protocols/llamaNET.h>
#include <latency/parse_args.cpp>
#include <latency/verify.h>
#include <llamaos/api/sleep.h>
#include <llamaos/xen/Hypervisor.h>

using namespace std;
using namespace latency;
using namespace latency::protocols;
using namespace llamaos;
using namespace llamaos::xen;

Protocol *Protocol::create (int argc, char *argv [])
{
   return new llamaNET (argc, argv);
}

static uint32_t seq = 1;

static domid_t get_domd_id (int node)
{
   // for now it's just self minus node % 6
   domid_t self_id = Hypervisor::get_instance ()->domid;

   return (self_id - 1 - (node / 2));
}

llamaNET::llamaNET (int argc, char *argv [])
   :  node(parse<uint32_t>(argc, argv, "--node", 0U)),
      client((node % 2) == 0),
      interface(get_domd_id (node), (node / 2))
{
   cout << "latency-llamaNET" << endl
        << "  node: " << node << endl;
}

llamaNET::~llamaNET ()
{

}

bool llamaNET::root_node ()
{
   return client;
}

bool llamaNET::startup (unsigned long max_msg_size)
{
   return true;
}

bool llamaNET::cleanup ()
{
   api::sleep (2);

   // release interface ?
   return true;
}

bool llamaNET::run_verify (unsigned long msg_size)
{
   // TCP doesn't send anything for a zero length message, so make it 8 bytes
   msg_size = max (8UL, msg_size);

   // llamaNET is configured for 1 page max message and has a 36 byte header, so make it 4060 bytes
   msg_size = min (4060UL, msg_size);

   net::llamaNET::Protocol_header *header;
   unsigned char *data;

   // dalai initiates the trial
   if (client)
   {
      header = interface.get_send_buffer ();
      header->dest = (node % 2) ? (node - 1) : (node + 1);
      header->src = node;
      header->type = 1;
      header->seq = seq++;
      header->len = msg_size;

      // get pointer to data section of buffer
      data = reinterpret_cast<unsigned char *>(header + 1);

      // marks all bytes with alpha chars (a,b,c,...)
      mark_data_alpha (data, msg_size);

      // send/recv and verify the data has been changed to numerals (1,2,3,...)
      interface.send (header);
      header = interface.recv (node);

      // get pointer to data section of buffer
      data = reinterpret_cast<unsigned char *>(header + 1);

      if (verify_data_numeric (data, msg_size))
      {
         interface.release_recv_buffer (header);

         return true;
      }
   }
   else
   {
      header = interface.recv (node);

      // get pointer to data section of buffer
      data = reinterpret_cast<unsigned char *>(header + 1);

      if (verify_data_alpha (data, msg_size))
      {
         interface.release_recv_buffer (header);

         header = interface.get_send_buffer ();
         header->dest = (node % 2) ? (node - 1) : (node + 1);
         header->src = node;
         header->type = 1;
         header->seq = seq++;
         header->len = msg_size;

         // get pointer to data section of buffer
         data = reinterpret_cast<unsigned char *>(header + 1);

         // marks all bytes with numerals and send
         mark_data_numeric (data, msg_size);

         interface.send (header);
         return true;
      }
   }

   return false;
}

bool llamaNET::run_trial (unsigned long msg_size, unsigned long trial_number)
{
   // TCP doesn't send anything for a zero length message, so make it 8 bytes
   msg_size = max (8UL, msg_size);

   // llamaNET is configured for 1 page max message and has a 36 byte header, so make it 4060 bytes
   msg_size = min (4060UL, msg_size);

   net::llamaNET::Protocol_header *header;
   unsigned char *data;

   // dalai initiates the trial
   if (client)
   {
      header = interface.get_send_buffer ();
      header->dest = (node % 2) ? (node - 1) : (node + 1);
      header->src = node;
      header->type = 1;
      header->seq = seq++;
      header->len = msg_size;

      interface.send (header);

      header = interface.recv (node);

      // get pointer to data section of buffer
      data = reinterpret_cast<unsigned char *>(header + 1);

      if (*(reinterpret_cast<unsigned long *>(data)) != trial_number)
      {
         cout << "data error: " << *(reinterpret_cast<unsigned long *>(data))  << " == " << trial_number << endl;
         interface.release_recv_buffer (header);
         return false;
      }

      interface.release_recv_buffer (header);
      return true;
   }
   else
   {
      header = interface.recv (node);
      interface.release_recv_buffer (header);

      header = interface.get_send_buffer ();
      header->dest = (node % 2) ? (node - 1) : (node + 1);
      header->src = node;
      header->type = 1;
      header->seq = seq++;
      header->len = msg_size;

      // get pointer to data section of buffer
      data = reinterpret_cast<unsigned char *>(header + 1);

      // place trial number in first "int" for master to verify
      *(reinterpret_cast<unsigned long *>(data)) = trial_number++;

      interface.send (header);
      return true;
   }

   return false;
}
<|endoftext|>


<commit_before>/*

  Copyright 2009 University of Helsinki
  Copyright 2015 Tino Didriksen <mail@tinodidriksen.com>
  Code adapted from https://github.com/TinoDidriksen/trie-tools

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

*/

/*
	Tests up to 8 variations of each input token:
	- Verbatim
	- With leading non-alphanumerics removed
	- With trailing non-alphanumerics removed
	- With leading and trailing non-alphanumerics removed
	- Lower-case of all the above
*/

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>
#include <map>
#include <sstream>
#include <stdexcept>
#include <cmath>
#include <cerrno>
#include <cctype>

#define U_CHARSET_IS_UTF8 1
#include <unicode/uclean.h>
#include <unicode/ucnv.h>
#include <unicode/uloc.h>
#include <unicode/uchar.h>
#include <unicode/unistr.h>

#include "ol-exceptions.h"
#include "ospell.h"
#include "ZHfstOspeller.h"

using hfst_ol::ZHfstOspeller;
using hfst_ol::Transducer;

typedef std::map<UnicodeString,bool> valid_words_t;
valid_words_t valid_words;

struct word_t {
	size_t start, count;
	UnicodeString buffer;
};
std::vector<word_t> words(8);
std::string buffer;
UnicodeString ubuffer, uc_buffer;
size_t cw;

bool verbatim = false;
bool uc_first = false;
bool uc_all = true;

bool find_alternatives(ZHfstOspeller& speller, size_t suggs) {
	/* Weights make this entirely pointless
	size_t dist = std::max(static_cast<size_t>(1), static_cast<size_t>(std::log(words[cw-1].buffer.size()) / std::log(2)));
	speller.set_weight_limit(dist);
	speller.set_beam(dist / 2);
	//*/

	for (size_t k=1 ; k <= cw ; ++k) {
		buffer.clear();
		words[cw-k].buffer.toUTF8String(buffer);
		hfst_ol::CorrectionQueue corrections = speller.suggest(buffer);

		if (corrections.size() == 0) {
			continue;
		}

		std::cout << "&";
		// Because speller.set_queue_limit() doesn't actually work, hard limit it here
		for (size_t i=0, e=corrections.size() ; i<e && i<suggs ; ++i) {
			std::cout << "\t";

			buffer.clear();
			if (cw - k != 0) {
				words[0].buffer.tempSubString(0, words[cw-k].start).toUTF8String(buffer);
			}
			if (uc_all) {
				UnicodeString::fromUTF8(corrections.top().first).toUpper().toUTF8String(buffer);
			}
			else if (uc_first) {
				uc_buffer.setTo(UnicodeString::fromUTF8(corrections.top().first));
				ubuffer.setTo(uc_buffer, 0, 1);
				ubuffer.toUpper();
				ubuffer.append(uc_buffer, 1, uc_buffer.length()-1);
				ubuffer.toUTF8String(buffer);
			}
			else {
				buffer.append(corrections.top().first);
			}
			if (cw - k != 0) {
				words[0].buffer.tempSubString(words[cw-k].start + words[cw-k].count).toUTF8String(buffer);
			}

			std::cout << buffer;
			corrections.pop();
		}
		std::cout << std::endl;
		return true;
	}
	return false;
}

bool is_valid_word(ZHfstOspeller& speller, const std::string& word) {
	ubuffer.setTo(UnicodeString::fromUTF8(word));

	uc_first = false;
	uc_all = true;
	bool has_letters = false;
	for (int32_t i=0 ; i<ubuffer.length() ; ++i) {
		if (u_isalpha(ubuffer[i])) {
			has_letters = true;
			if (u_isupper(ubuffer[i]) && uc_all) {
				uc_first = true;
			}
			else if (u_islower(ubuffer[i])) {
				uc_all = false;
				break;
			}
		}
	}

	// If there are no letters in this token, just ignore it
	if (has_letters == false) {
		return true;
	}

	size_t ichStart = 0, cchUse = ubuffer.length();
	const UChar *pwsz = ubuffer.getTerminatedBuffer();

	// Always test the full given input
	words[0].buffer.remove();
	words[0].start = ichStart;
	words[0].count = cchUse;
	words[0].buffer = ubuffer;
	cw = 1;

	if (cchUse > 1 && !verbatim) {
		size_t count = cchUse;
		while (count && !u_isalnum(pwsz[ichStart+count-1])) {
			--count;
		}
		if (count != cchUse) {
			// If the input ended with non-alphanumerics, test input with non-alphanumerics trimmed from the end
			words[cw].buffer.remove();
			words[cw].start = ichStart;
			words[cw].count = count;
			words[cw].buffer.append(pwsz, words[cw].start, words[cw].count);
			++cw;
		}

		size_t start = ichStart, count2 = cchUse;
		while (start < ichStart+cchUse && !u_isalnum(pwsz[start])) {
			++start;
			--count2;
		}
		if (start != ichStart) {
			// If the input started with non-alphanumerics, test input with non-alphanumerics trimmed from the start
			words[cw].buffer.remove();
			words[cw].start = start;
			words[cw].count = count2;
			words[cw].buffer.append(pwsz, words[cw].start, words[cw].count);
			++cw;
		}

		if (start != ichStart && count != cchUse) {
			// If the input both started and ended with non-alphanumerics, test input with non-alphanumerics trimmed from both sides
			words[cw].buffer.remove();
			words[cw].start = start;
			words[cw].count = count - (cchUse - count2);
			words[cw].buffer.append(pwsz, words[cw].start, words[cw].count);
			++cw;
		}
	}

	for (size_t i=0, e=cw ; i<e ; ++i) {
		valid_words_t::iterator it = valid_words.find(words[i].buffer);

		if (it == valid_words.end()) {
			buffer.clear();
			words[i].buffer.toUTF8String(buffer);
			bool valid = speller.spell(buffer);
			it = valid_words.insert(std::make_pair(words[i].buffer,valid)).first;

			if (!valid && !verbatim) {
				// If the word was not valid, fold it to lower case and try again
				buffer.clear();
				ubuffer = words[i].buffer;
				ubuffer.toLower();
				ubuffer.toUTF8String(buffer);

				// Add the lower case variant to the list so that we get suggestions using that, if need be
				words[cw].start = words[i].start;
				words[cw].count = words[i].count;
				words[cw].buffer = ubuffer;
				++cw;

				// Don't try again if the lower cased variant has already been tried
				valid_words_t::iterator itl = valid_words.find(ubuffer);
				if (itl != valid_words.end()) {
					it->second = itl->second;
					it = itl;
				}
				else {
					valid = speller.spell(buffer);
					it->second = valid; // Also mark the original mixed case variant as whatever the lower cased one was
					it = valid_words.insert(std::make_pair(words[i].buffer,valid)).first;
				}
			}
		}

		if (it->second == true) {
			return true;
		}
	}

	return false;
}

int zhfst_spell(const char* zhfst_filename) {
	ZHfstOspeller speller;
	try {
		speller.read_zhfst(zhfst_filename);
	}
	catch (hfst_ol::ZHfstMetaDataParsingError zhmdpe) {
		fprintf(stderr, "cannot finish reading zhfst archive %s:\n%s.\n", zhfst_filename, zhmdpe.what());
		return EXIT_FAILURE;
	}
	catch (hfst_ol::ZHfstZipReadingError zhzre) {
		fprintf(stderr, "cannot read zhfst archive %s:\n%s.\n", zhfst_filename, zhzre.what());
		return EXIT_FAILURE;
	}
	catch (hfst_ol::ZHfstXmlParsingError zhxpe) {
		fprintf(stderr, "Cannot finish reading index.xml from %s:\n%s.\n", zhfst_filename, zhxpe.what());
		return EXIT_FAILURE;
	}

	std::cout << "@@ hfst-ospell-office is alive" << std::endl;

	std::string line;
	std::string word;
	std::istringstream ss;
	while (std::getline(std::cin, line)) {
		while (!line.empty() && std::isspace(line[line.size()-1])) {
			line.resize(line.size()-1);
		}
		if (line.empty()) {
			continue;
		}
		// Just in case anyone decides to use the speller for a minor eternity
		if (valid_words.size() > 20480) {
			valid_words.clear();
		}

		ss.clear();
		ss.str(line);
		size_t suggs = 0;
		char c = 0;
		if (!(ss >> suggs) || !ss.get(c) || !std::getline(ss, line)) {
			std::cout << "!" << std::endl;
			continue;
		}

		if (is_valid_word(speller, line)) {
			std::cout << "*" << std::endl;
			continue;
		}

		if (!suggs || !find_alternatives(speller, suggs)) {
			std::cout << "#" << std::endl;
		}
	}
    return EXIT_SUCCESS;
}

int main(int argc, char **argv) {
	UErrorCode status = U_ZERO_ERROR;
	u_init(&status);
	if (U_FAILURE(status) && status != U_FILE_ACCESS_ERROR) {
		std::cerr << "Error: Cannot initialize ICU. Status = " << u_errorName(status) << std::endl;
		return -1;
	}

	ucnv_setDefaultName("UTF-8");
	uloc_setDefault("en_US_POSIX", &status);

	std::vector<std::string> args(argv, argv+argc);
	for (std::vector<std::string>::iterator it=args.begin() ; it != args.end() ; ) {
		if (*it == "--verbatim") {
			verbatim = true;
			it = args.erase(it);
		}
		else {
			++it;
		}
	}

	if (args.size() < 2) {
		throw std::invalid_argument("Must pass a zhfst as argument");
	}

	int rv = zhfst_spell(args[1].c_str());

	u_cleanup();
	return rv;
}
<commit_msg>If we are looking for suggestions, don't use the cache<commit_after>/*

  Copyright 2009 University of Helsinki
  Copyright 2015 Tino Didriksen <mail@tinodidriksen.com>
  Code adapted from https://github.com/TinoDidriksen/trie-tools

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

*/

/*
	Tests up to 8 variations of each input token:
	- Verbatim
	- With leading non-alphanumerics removed
	- With trailing non-alphanumerics removed
	- With leading and trailing non-alphanumerics removed
	- Lower-case of all the above
*/

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>
#include <map>
#include <sstream>
#include <stdexcept>
#include <cmath>
#include <cerrno>
#include <cctype>

#define U_CHARSET_IS_UTF8 1
#include <unicode/uclean.h>
#include <unicode/ucnv.h>
#include <unicode/uloc.h>
#include <unicode/uchar.h>
#include <unicode/unistr.h>

#include "ol-exceptions.h"
#include "ospell.h"
#include "ZHfstOspeller.h"

using hfst_ol::ZHfstOspeller;
using hfst_ol::Transducer;

typedef std::map<UnicodeString,bool> valid_words_t;
valid_words_t valid_words;

struct word_t {
	size_t start, count;
	UnicodeString buffer;
};
std::vector<word_t> words(8);
std::string buffer;
UnicodeString ubuffer, uc_buffer;
size_t cw;

bool verbatim = false;
bool uc_first = false;
bool uc_all = true;

bool find_alternatives(ZHfstOspeller& speller, size_t suggs) {
	for (size_t k=1 ; k <= cw ; ++k) {
		buffer.clear();
		words[cw-k].buffer.toUTF8String(buffer);
		hfst_ol::CorrectionQueue corrections = speller.suggest(buffer);

		if (corrections.size() == 0) {
			continue;
		}

		std::cout << "&";
		// Because speller.set_queue_limit() doesn't actually work, hard limit it here
		for (size_t i=0, e=corrections.size() ; i<e && i<suggs ; ++i) {
			std::cout << "\t";

			buffer.clear();
			if (cw - k != 0) {
				words[0].buffer.tempSubString(0, words[cw-k].start).toUTF8String(buffer);
			}
			if (uc_all) {
				UnicodeString::fromUTF8(corrections.top().first).toUpper().toUTF8String(buffer);
			}
			else if (uc_first) {
				uc_buffer.setTo(UnicodeString::fromUTF8(corrections.top().first));
				ubuffer.setTo(uc_buffer, 0, 1);
				ubuffer.toUpper();
				ubuffer.append(uc_buffer, 1, uc_buffer.length()-1);
				ubuffer.toUTF8String(buffer);
			}
			else {
				buffer.append(corrections.top().first);
			}
			if (cw - k != 0) {
				words[0].buffer.tempSubString(words[cw-k].start + words[cw-k].count).toUTF8String(buffer);
			}

			std::cout << buffer;
			corrections.pop();
		}
		std::cout << std::endl;
		return true;
	}
	return false;
}

bool is_valid_word(ZHfstOspeller& speller, const std::string& word, size_t suggs) {
	ubuffer.setTo(UnicodeString::fromUTF8(word));

	uc_first = false;
	uc_all = true;
	bool has_letters = false;
	for (int32_t i=0 ; i<ubuffer.length() ; ++i) {
		if (u_isalpha(ubuffer[i])) {
			has_letters = true;
			if (u_isupper(ubuffer[i]) && uc_all) {
				uc_first = true;
			}
			else if (u_islower(ubuffer[i])) {
				uc_all = false;
				break;
			}
		}
	}

	// If there are no letters in this token, just ignore it
	if (has_letters == false) {
		return true;
	}

	size_t ichStart = 0, cchUse = ubuffer.length();
	const UChar *pwsz = ubuffer.getTerminatedBuffer();

	// Always test the full given input
	words[0].buffer.remove();
	words[0].start = ichStart;
	words[0].count = cchUse;
	words[0].buffer = ubuffer;
	cw = 1;

	if (cchUse > 1 && !verbatim) {
		size_t count = cchUse;
		while (count && !u_isalnum(pwsz[ichStart+count-1])) {
			--count;
		}
		if (count != cchUse) {
			// If the input ended with non-alphanumerics, test input with non-alphanumerics trimmed from the end
			words[cw].buffer.remove();
			words[cw].start = ichStart;
			words[cw].count = count;
			words[cw].buffer.append(pwsz, words[cw].start, words[cw].count);
			++cw;
		}

		size_t start = ichStart, count2 = cchUse;
		while (start < ichStart+cchUse && !u_isalnum(pwsz[start])) {
			++start;
			--count2;
		}
		if (start != ichStart) {
			// If the input started with non-alphanumerics, test input with non-alphanumerics trimmed from the start
			words[cw].buffer.remove();
			words[cw].start = start;
			words[cw].count = count2;
			words[cw].buffer.append(pwsz, words[cw].start, words[cw].count);
			++cw;
		}

		if (start != ichStart && count != cchUse) {
			// If the input both started and ended with non-alphanumerics, test input with non-alphanumerics trimmed from both sides
			words[cw].buffer.remove();
			words[cw].start = start;
			words[cw].count = count - (cchUse - count2);
			words[cw].buffer.append(pwsz, words[cw].start, words[cw].count);
			++cw;
		}
	}

	for (size_t i=0, e=cw ; i<e ; ++i) {
		// If we are looking for suggestions, don't use the cache
		valid_words_t::iterator it = suggs ? valid_words.end() : valid_words.find(words[i].buffer);

		if (it == valid_words.end()) {
			buffer.clear();
			words[i].buffer.toUTF8String(buffer);
			bool valid = speller.spell(buffer);
			it = valid_words.insert(std::make_pair(words[i].buffer,valid)).first;

			if (!valid && !verbatim) {
				// If the word was not valid, fold it to lower case and try again
				buffer.clear();
				ubuffer = words[i].buffer;
				ubuffer.toLower();
				ubuffer.toUTF8String(buffer);

				// Add the lower case variant to the list so that we get suggestions using that, if need be
				words[cw].start = words[i].start;
				words[cw].count = words[i].count;
				words[cw].buffer = ubuffer;
				++cw;

				// Don't try again if the lower cased variant has already been tried
				valid_words_t::iterator itl = suggs ? valid_words.end() : valid_words.find(ubuffer);
				if (itl != valid_words.end()) {
					it->second = itl->second;
					it = itl;
				}
				else {
					valid = speller.spell(buffer);
					it->second = valid; // Also mark the original mixed case variant as whatever the lower cased one was
					it = valid_words.insert(std::make_pair(words[i].buffer,valid)).first;
				}
			}
		}

		if (it->second == true) {
			return true;
		}
	}

	return false;
}

int zhfst_spell(const char* zhfst_filename) {
	ZHfstOspeller speller;
	try {
		speller.read_zhfst(zhfst_filename);
	}
	catch (hfst_ol::ZHfstMetaDataParsingError zhmdpe) {
		fprintf(stderr, "cannot finish reading zhfst archive %s:\n%s.\n", zhfst_filename, zhmdpe.what());
		return EXIT_FAILURE;
	}
	catch (hfst_ol::ZHfstZipReadingError zhzre) {
		fprintf(stderr, "cannot read zhfst archive %s:\n%s.\n", zhfst_filename, zhzre.what());
		return EXIT_FAILURE;
	}
	catch (hfst_ol::ZHfstXmlParsingError zhxpe) {
		fprintf(stderr, "Cannot finish reading index.xml from %s:\n%s.\n", zhfst_filename, zhxpe.what());
		return EXIT_FAILURE;
	}

	std::cout << "@@ hfst-ospell-office is alive" << std::endl;

	std::string line;
	std::string word;
	std::istringstream ss;
	while (std::getline(std::cin, line)) {
		while (!line.empty() && std::isspace(line[line.size()-1])) {
			line.resize(line.size()-1);
		}
		if (line.empty()) {
			continue;
		}
		// Just in case anyone decides to use the speller for a minor eternity
		if (valid_words.size() > 20480) {
			valid_words.clear();
		}

		ss.clear();
		ss.str(line);
		size_t suggs = 0;
		char c = 0;
		if (!(ss >> suggs) || !ss.get(c) || !std::getline(ss, line)) {
			std::cout << "!" << std::endl;
			continue;
		}

		if (is_valid_word(speller, line, suggs)) {
			std::cout << "*" << std::endl;
			continue;
		}

		if (!suggs || !find_alternatives(speller, suggs)) {
			std::cout << "#" << std::endl;
		}
	}
    return EXIT_SUCCESS;
}

int main(int argc, char **argv) {
	UErrorCode status = U_ZERO_ERROR;
	u_init(&status);
	if (U_FAILURE(status) && status != U_FILE_ACCESS_ERROR) {
		std::cerr << "Error: Cannot initialize ICU. Status = " << u_errorName(status) << std::endl;
		return -1;
	}

	ucnv_setDefaultName("UTF-8");
	uloc_setDefault("en_US_POSIX", &status);

	std::vector<std::string> args(argv, argv+argc);
	for (std::vector<std::string>::iterator it=args.begin() ; it != args.end() ; ) {
		if (*it == "--verbatim") {
			verbatim = true;
			it = args.erase(it);
		}
		else {
			++it;
		}
	}

	if (args.size() < 2) {
		throw std::invalid_argument("Must pass a zhfst as argument");
	}

	int rv = zhfst_spell(args[1].c_str());

	u_cleanup();
	return rv;
}
<|endoftext|>


<commit_before>/*
 * This file is part of the Electron Orbital Explorer. The Electron
 * Orbital Explorer is distributed under the Simplified BSD License
 * (also called the "BSD 2-Clause License"), in hopes that these
 * rendering techniques might be used by other programmers in
 * applications such as scientific visualization, video gaming, and so
 * on. If you find value in this software and use its technologies for
 * another purpose, I would love to hear back from you at bjthinks (at)
 * gmail (dot) com. If you improve this software and agree to release
 * your modifications under the below license, I encourage you to fork
 * the development tree on github and push your modifications. The
 * Electron Orbital Explorer's development URL is:
 * https://github.com/bjthinks/orbital-explorer
 * (This paragraph is not part of the software license and may be
 * removed.)
 *
 * Copyright (c) 2013, Brian W. Johnson
 * 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.
 *
 * 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 HOLDER 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.
 */

#ifndef OOPENGL_HH
#define OOPENGL_HH

#include <stdexcept>
#include <vector>
#include <GL/glew.h>

void GetGLError_(const char *file, int line);
#define GetGLError() GetGLError_(__FILE__, __LINE__)

class Uncopyable
{
public:
  Uncopyable() {}

private:
  Uncopyable(const Uncopyable &); // DO NOT DEFINE
  Uncopyable &operator=(const Uncopyable &); // DO NOT DEFINE
};

class Timer : public Uncopyable
{
public:
  Timer() {
    glGenQueries(2, id);
    glQueryCounter(id[0], GL_TIMESTAMP);
    glQueryCounter(id[1], GL_TIMESTAMP);
  }
  ~Timer() { glDeleteQueries(2, id); }
  void start() {
    glQueryCounter(id[0], GL_TIMESTAMP);
  }
  void stop() {
    glQueryCounter(id[1], GL_TIMESTAMP);
  }
  long read() {
    GLint timer_good;

    glGetQueryObjectiv(id[0], GL_QUERY_RESULT_AVAILABLE, &timer_good);
    if (!timer_good)
      goto bailout;

    glGetQueryObjectiv(id[1], GL_QUERY_RESULT_AVAILABLE, &timer_good);
    if (!timer_good)
      goto bailout;

    GLuint64 t0, t1;
    glGetQueryObjectui64v(id[0], GL_QUERY_RESULT, &t0);
    glGetQueryObjectui64v(id[1], GL_QUERY_RESULT, &t1);
    return t1 - t0;

  bailout:
    throw std::logic_error("GPU timer not ready");
  }

private:
  GLuint id[2];
};

class Shader : public Uncopyable
{
public:
  Shader(GLenum type) : id(glCreateShader(type)) {}
  void compileSource(const char *);
  ~Shader() { glDeleteShader(id); }
  operator GLuint() { return id; }

private:
  GLuint id;
};

class VertexShader : public Shader
{
public:
  VertexShader() : Shader(GL_VERTEX_SHADER) {}
};

class GeometryShader : public Shader
{
public:
  GeometryShader() : Shader(GL_GEOMETRY_SHADER) {}
};

class FragmentShader : public Shader
{
public:
  FragmentShader() : Shader(GL_FRAGMENT_SHADER) {}
};

template <typename T> class Uniform;

class Program : public Uncopyable
{
public:
  Program() : id(glCreateProgram()) {}
  operator GLuint() { return id; }
  void attach(Shader &shader) { glAttachShader(id, shader); }
  void detach(Shader &shader) { glDetachShader(id, shader); }
  void link();
  void use();
  bool used() { return id == program_in_use; }
  ~Program() { glDeleteProgram(id); }

  // Uniforms
  template <typename T> Uniform<T> uniform(const char *name);

  // Convenience functions to create, compile, and attach a shader
  void vertexShader(const char *source);
  void geometryShader(const char *source);
  void fragmentShader(const char *source);

private:
  GLuint id;
  static GLuint program_in_use;
};

template <typename T>
class Uniform // This class IS copyable
{
public:
  Uniform(Program &program_, const char *name) :
    program(program_),
    location(glGetUniformLocation(program, name))
  {}
  operator GLuint() { return location; }
  void operator=(const T &);

private:
  Program &program;
  GLuint location;

  void verify_used();
};

template <typename T>
inline Uniform<T> Program::uniform(const char *name)
{
  return Uniform<T>(*this, name);
}

class Buffer;
class VertexArrayObject : public Uncopyable
{
public:
  VertexArrayObject();
  void bind()          { glBindVertexArray(id); }
  ~VertexArrayObject() { glDeleteVertexArrays(1, &id); }

  void buffer(GLenum target, const void *data, size_t size);

  template <typename T> void buffer(GLenum target, const std::vector<T> &vec)
  { buffer(target, &vec[0], sizeof(T) * vec.size()); }

private:
  GLuint id;
  Buffer *arrayBuffer, *elementArrayBuffer;
};

class Buffer : public Uncopyable
{
public:
  Buffer()                 { glGenBuffers(1, &id); }
  operator GLuint()        { return id; }
  void bind(GLenum target) { glBindBuffer(target, id); }
  ~Buffer()                { glDeleteBuffers(1, &id); }

private:
  GLuint id;
};

class Texture : public Uncopyable
{
public:
  Texture()                { glGenTextures(1, &id); }
  operator GLuint()        { return id; }
  void bind(GLenum target) { glBindTexture(target, id); }
  ~Texture()               { glDeleteTextures(1, &id); }

private:
  GLuint id;
};

#endif
<commit_msg>Disable Timer class from compiling, which uses OpenGL 3.3 functions<commit_after>/*
 * This file is part of the Electron Orbital Explorer. The Electron
 * Orbital Explorer is distributed under the Simplified BSD License
 * (also called the "BSD 2-Clause License"), in hopes that these
 * rendering techniques might be used by other programmers in
 * applications such as scientific visualization, video gaming, and so
 * on. If you find value in this software and use its technologies for
 * another purpose, I would love to hear back from you at bjthinks (at)
 * gmail (dot) com. If you improve this software and agree to release
 * your modifications under the below license, I encourage you to fork
 * the development tree on github and push your modifications. The
 * Electron Orbital Explorer's development URL is:
 * https://github.com/bjthinks/orbital-explorer
 * (This paragraph is not part of the software license and may be
 * removed.)
 *
 * Copyright (c) 2013, Brian W. Johnson
 * 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.
 *
 * 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 HOLDER 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.
 */

#ifndef OOPENGL_HH
#define OOPENGL_HH

#include <stdexcept>
#include <vector>
#include <GL/glew.h>

void GetGLError_(const char *file, int line);
#define GetGLError() GetGLError_(__FILE__, __LINE__)

class Uncopyable
{
public:
  Uncopyable() {}

private:
  Uncopyable(const Uncopyable &); // DO NOT DEFINE
  Uncopyable &operator=(const Uncopyable &); // DO NOT DEFINE
};

// This uses OpenGL 3.3 features, so it isn't Mac-safe...
#if 0
class Timer : public Uncopyable
{
public:
  Timer() {
    glGenQueries(2, id);
    glQueryCounter(id[0], GL_TIMESTAMP);
    glQueryCounter(id[1], GL_TIMESTAMP);
  }
  ~Timer() { glDeleteQueries(2, id); }
  void start() {
    glQueryCounter(id[0], GL_TIMESTAMP);
  }
  void stop() {
    glQueryCounter(id[1], GL_TIMESTAMP);
  }
  long read() {
    GLint timer_good;

    glGetQueryObjectiv(id[0], GL_QUERY_RESULT_AVAILABLE, &timer_good);
    if (!timer_good)
      goto bailout;

    glGetQueryObjectiv(id[1], GL_QUERY_RESULT_AVAILABLE, &timer_good);
    if (!timer_good)
      goto bailout;

    GLuint64 t0, t1;
    glGetQueryObjectui64v(id[0], GL_QUERY_RESULT, &t0);
    glGetQueryObjectui64v(id[1], GL_QUERY_RESULT, &t1);
    return t1 - t0;

  bailout:
    throw std::logic_error("GPU timer not ready");
  }

private:
  GLuint id[2];
};
#endif

class Shader : public Uncopyable
{
public:
  Shader(GLenum type) : id(glCreateShader(type)) {}
  void compileSource(const char *);
  ~Shader() { glDeleteShader(id); }
  operator GLuint() { return id; }

private:
  GLuint id;
};

class VertexShader : public Shader
{
public:
  VertexShader() : Shader(GL_VERTEX_SHADER) {}
};

class GeometryShader : public Shader
{
public:
  GeometryShader() : Shader(GL_GEOMETRY_SHADER) {}
};

class FragmentShader : public Shader
{
public:
  FragmentShader() : Shader(GL_FRAGMENT_SHADER) {}
};

template <typename T> class Uniform;

class Program : public Uncopyable
{
public:
  Program() : id(glCreateProgram()) {}
  operator GLuint() { return id; }
  void attach(Shader &shader) { glAttachShader(id, shader); }
  void detach(Shader &shader) { glDetachShader(id, shader); }
  void link();
  void use();
  bool used() { return id == program_in_use; }
  ~Program() { glDeleteProgram(id); }

  // Uniforms
  template <typename T> Uniform<T> uniform(const char *name);

  // Convenience functions to create, compile, and attach a shader
  void vertexShader(const char *source);
  void geometryShader(const char *source);
  void fragmentShader(const char *source);

private:
  GLuint id;
  static GLuint program_in_use;
};

template <typename T>
class Uniform // This class IS copyable
{
public:
  Uniform(Program &program_, const char *name) :
    program(program_),
    location(glGetUniformLocation(program, name))
  {}
  operator GLuint() { return location; }
  void operator=(const T &);

private:
  Program &program;
  GLuint location;

  void verify_used();
};

template <typename T>
inline Uniform<T> Program::uniform(const char *name)
{
  return Uniform<T>(*this, name);
}

class Buffer;
class VertexArrayObject : public Uncopyable
{
public:
  VertexArrayObject();
  void bind()          { glBindVertexArray(id); }
  ~VertexArrayObject() { glDeleteVertexArrays(1, &id); }

  void buffer(GLenum target, const void *data, size_t size);

  template <typename T> void buffer(GLenum target, const std::vector<T> &vec)
  { buffer(target, &vec[0], sizeof(T) * vec.size()); }

private:
  GLuint id;
  Buffer *arrayBuffer, *elementArrayBuffer;
};

class Buffer : public Uncopyable
{
public:
  Buffer()                 { glGenBuffers(1, &id); }
  operator GLuint()        { return id; }
  void bind(GLenum target) { glBindBuffer(target, id); }
  ~Buffer()                { glDeleteBuffers(1, &id); }

private:
  GLuint id;
};

class Texture : public Uncopyable
{
public:
  Texture()                { glGenTextures(1, &id); }
  operator GLuint()        { return id; }
  void bind(GLenum target) { glBindTexture(target, id); }
  ~Texture()               { glDeleteTextures(1, &id); }

private:
  GLuint id;
};

#endif
<|endoftext|>


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

#include "kythe/cxx/common/protobuf_metadata_file.h"

#include <sstream>

#include "absl/strings/match.h"
#include "glog/logging.h"
#include "google/protobuf/descriptor.pb.h"
#include "google/protobuf/io/zero_copy_stream.h"
#include "google/protobuf/io/zero_copy_stream_impl.h"
#include "kythe/cxx/common/schema/edges.h"

namespace kythe {

proto::VName ProtobufMetadataSupport::VNameForAnnotation(
    const proto::VName& context_vname,
    const google::protobuf::GeneratedCodeInfo::Annotation& annotation) {
  proto::VName out;
  if (!vname_lookup_(annotation.source_file(), &out)) {
    out.set_corpus(context_vname.corpus());
  }
  out.set_path(annotation.source_file());
  return VNameForProtoPath(out, annotation.path());
}

std::unique_ptr<kythe::MetadataFile> ProtobufMetadataSupport::ParseFile(
    const std::string& raw_filename, const std::string& filename,
    absl::string_view buffer) {
  absl::string_view file_ref(filename);
  if (!(absl::EndsWith(filename, ".pb.h.meta") ||
        absl::EndsWith(filename, ".pb.h") ||
        absl::EndsWith(filename, ".proto.h.meta") ||
        absl::EndsWith(filename, ".proto.h"))) {
    return nullptr;
  }
  proto::VName context_vname;
  if (!vname_lookup_(raw_filename, &context_vname)) {
    LOG(WARNING) << "Failed getting VName for metadata: " << raw_filename;
  }
  google::protobuf::GeneratedCodeInfo info;
  if (!info.ParseFromArray(buffer.data(), buffer.size())) {
    LOG(WARNING) << "Failed ParseFromArray: " << raw_filename;
    return nullptr;
  }
  std::vector<MetadataFile::Rule> rules;
  for (const auto& annotation : info.annotation()) {
    MetadataFile::Rule rule;
    rule.begin = annotation.begin();
    rule.end = annotation.end();
    rule.vname = VNameForAnnotation(context_vname, annotation);
    rule.edge_in = kythe::common::schema::kDefinesBinding;
    rule.edge_out = kythe::common::schema::kGenerates;
    rule.reverse_edge = true;
    rule.generate_anchor = false;
    rule.anchor_begin = 0;
    rule.anchor_end = 0;
    rules.push_back(rule);
  }
  return MetadataFile::LoadFromRules(rules.begin(), rules.end());
}
}  // namespace kythe
<commit_msg>fix(cxx_indexer): allow protobuf metadata in .stubby.h files (#4004)<commit_after>/*
 * Copyright 2016 The Kythe Authors. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "kythe/cxx/common/protobuf_metadata_file.h"

#include <sstream>

#include "absl/strings/match.h"
#include "glog/logging.h"
#include "google/protobuf/descriptor.pb.h"
#include "google/protobuf/io/zero_copy_stream.h"
#include "google/protobuf/io/zero_copy_stream_impl.h"
#include "kythe/cxx/common/schema/edges.h"

namespace kythe {

proto::VName ProtobufMetadataSupport::VNameForAnnotation(
    const proto::VName& context_vname,
    const google::protobuf::GeneratedCodeInfo::Annotation& annotation) {
  proto::VName out;
  if (!vname_lookup_(annotation.source_file(), &out)) {
    out.set_corpus(context_vname.corpus());
  }
  out.set_path(annotation.source_file());
  return VNameForProtoPath(out, annotation.path());
}

std::unique_ptr<kythe::MetadataFile> ProtobufMetadataSupport::ParseFile(
    const std::string& raw_filename, const std::string& filename,
    absl::string_view buffer) {
  absl::string_view file_ref(filename);
  if (!(absl::EndsWith(filename, ".pb.h.meta") ||
        absl::EndsWith(filename, ".pb.h") ||
        absl::EndsWith(filename, ".proto.h.meta") ||
        absl::EndsWith(filename, ".proto.h") ||
        absl::EndsWith(filename, ".stubby.h"))) {
    return nullptr;
  }
  proto::VName context_vname;
  if (!vname_lookup_(raw_filename, &context_vname)) {
    LOG(WARNING) << "Failed getting VName for metadata: " << raw_filename;
  }
  google::protobuf::GeneratedCodeInfo info;
  if (!info.ParseFromArray(buffer.data(), buffer.size())) {
    LOG(WARNING) << "Failed ParseFromArray: " << raw_filename;
    return nullptr;
  }
  std::vector<MetadataFile::Rule> rules;
  for (const auto& annotation : info.annotation()) {
    MetadataFile::Rule rule;
    rule.begin = annotation.begin();
    rule.end = annotation.end();
    rule.vname = VNameForAnnotation(context_vname, annotation);
    rule.edge_in = kythe::common::schema::kDefinesBinding;
    rule.edge_out = kythe::common::schema::kGenerates;
    rule.reverse_edge = true;
    rule.generate_anchor = false;
    rule.anchor_begin = 0;
    rule.anchor_end = 0;
    rules.push_back(rule);
  }
  return MetadataFile::LoadFromRules(rules.begin(), rules.end());
}
}  // namespace kythe
<|endoftext|>


<commit_before>/*
   This file is part of the Nepomuk KDE project.
   Copyright (C) 2011 Sebastian Trueg <trueg@kde.org>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) version 3, or any
   later version accepted by the membership of KDE e.V. (or its
   successor approved by the membership of KDE e.V.), which shall
   act as a proxy defined in Section 6 of version 3 of the license.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "recommendationmanager.h"
#include "recommendationmanageradaptor.h"
#include "recommendation.h"
#include "recommendationaction.h"
#include "locationmanager.h"
#include "kext.h"

#include <kworkspace/kactivityinfo.h>
#include <kworkspace/kactivityconsumer.h>

#include <KRandom>
#include <KRun>
#include <KDebug>

#include <Nepomuk/Query/Query>
#include <Nepomuk/Query/QueryServiceClient>
#include <Nepomuk/Query/ComparisonTerm>
#include <Nepomuk/Query/LiteralTerm>
#include <Nepomuk/Query/AndTerm>
#include <Nepomuk/Query/QueryServiceClient>
#include <Nepomuk/Query/Result>
#include <Nepomuk/Resource>

#include <Soprano/Vocabulary/NAO>

#include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusMetaType>

#include <QtLocation/QLandmark>

using namespace Soprano::Vocabulary;
using namespace Nepomuk::Vocabulary;

QTM_USE_NAMESPACE

//Q_DECLARE_METATYPE(Contour::Recommendation*)

// TODO: act on several changes:
//       * later: triggers from the dms

class Contour::RecommendationManager::Private
{
public:
    KActivityConsumer* m_activityConsumer;
    LocationManager* m_locationManager;

    QList<Recommendation> m_recommendations;
    QHash<QString, RecommendationAction> m_actionHash;
    QHash<QString, Recommendation> m_RecommendationForAction;

    Nepomuk::Query::QueryServiceClient m_queryClient;

    RecommendationManager* q;

    void updateRecommendations();
    void _k_locationChanged(const QList<QLandmark>&);
    void _k_currentActivityChanged(const QString&);
    void _k_newResults(const QList<Nepomuk::Query::Result>&);
    void _k_queryFinished();
};

void Contour::RecommendationManager::Private::updateRecommendations()
{
    // remove old recommendations
    m_recommendations.clear();
    m_actionHash.clear();
    m_RecommendationForAction.clear();

    // get resources that have been touched in the current activity (the dumb way for now)
    const QString query
            = QString::fromLatin1("select ?r count(distinct ?e) as ?cnt where { "
                                  "?e a nuao:DesktopEvent . "
                                  "?e nuao:involves ?r . "
                                  "?e %1 ?a . "
                                  "?a nao:identifier %2 . "
                                  "?e nuao:start ?d . "
                                  "} ORDER BY (?cnt) LIMIT 6")
            .arg(Soprano::Node::resourceToN3(KExt::usedActivity()),
                 Soprano::Node::literalToN3(Soprano::LiteralValue(m_activityConsumer->currentActivity())));

    m_queryClient.sparqlQuery(query);

    // IDEA: for files use usage events
    //       for everything else use changes in data via graph metadata
}

void Contour::RecommendationManager::Private::_k_locationChanged(const QList<QLandmark>&)
{
    updateRecommendations();
}

void Contour::RecommendationManager::Private::_k_currentActivityChanged(const QString&)
{
    updateRecommendations();
}

void Contour::RecommendationManager::Private::_k_newResults(const QList<Nepomuk::Query::Result>& results)
{
    foreach(const Nepomuk::Query::Result& result, results) {
        Recommendation r;
        r.resourceUri = KUrl(result.resource().resourceUri()).url();

        kWarning() << "Got a new result:" << result.excerpt() << result.score();

        // for now we create the one dummy action: open the resource
        QString id;
        do {
            id = KRandom::randomString(5);
        } while(m_actionHash.contains(id));
        RecommendationAction action;
        action.id = id;
        action.text = i18n("Open '%1'", result.resource().genericLabel());
        m_actionHash[id] = action;
        m_RecommendationForAction[id] = r;

        r.actions << action;

        m_recommendations << r;
    }
}

void Contour::RecommendationManager::Private::_k_queryFinished()
{
    emit q->recommendationsChanged();
}

Contour::RecommendationManager::RecommendationManager(QObject *parent)
    : QObject(parent),
      d(new Private())
{
    d->q = this;

    connect(&d->m_queryClient, SIGNAL(newEntries(QList<Nepomuk::Query::Result>)),
            this, SLOT(_k_newResults(QList<Nepomuk::Query::Result>)));

    d->m_activityConsumer = new KActivityConsumer(this);
    connect(d->m_activityConsumer, SIGNAL(currentActivityChanged(QString)),
            this, SLOT(_k_currentActivityChanged(QString)));
    d->m_locationManager = new LocationManager(this);
    connect(d->m_locationManager, SIGNAL(locationChanged(QList<QLandmark>)),
            this, SLOT(_k_locationChanged(QList<QLandmark>)));
    d->updateRecommendations();

    // export via DBus
    qDBusRegisterMetaType<Contour::Recommendation>();
    qDBusRegisterMetaType<QList<Contour::Recommendation> >();
    qDBusRegisterMetaType<Contour::RecommendationAction>();
    (void)new RecommendationManagerAdaptor(this);
    QDBusConnection::sessionBus().registerObject(QLatin1String("/recommendationmanager"), this);
}

Contour::RecommendationManager::~RecommendationManager()
{
    delete d;
}

QList<Contour::Recommendation> Contour::RecommendationManager::recommendations() const
{
    return d->m_recommendations;
}

void Contour::RecommendationManager::executeAction(const QString &actionId)
{
    if(d->m_actionHash.contains(actionId)) {
        RecommendationAction action = d->m_actionHash.value(actionId);

        // FIXME: this is the hacky execution of the action, make it correct
        Recommendation r = d->m_RecommendationForAction.value(actionId);
        (void)new KRun(r.resourceUri, 0);
    }
    else {
        kDebug() << "Invalid action id encountered:" << actionId;
    }
}

#include "recommendationmanager.moc"
<commit_msg>use the new query for the scoring<commit_after>/*
   This file is part of the Nepomuk KDE project.
   Copyright (C) 2011 Sebastian Trueg <trueg@kde.org>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) version 3, or any
   later version accepted by the membership of KDE e.V. (or its
   successor approved by the membership of KDE e.V.), which shall
   act as a proxy defined in Section 6 of version 3 of the license.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "recommendationmanager.h"
#include "recommendationmanageradaptor.h"
#include "recommendation.h"
#include "recommendationaction.h"
#include "locationmanager.h"
#include "kext.h"

#include <kworkspace/kactivityinfo.h>
#include <kworkspace/kactivityconsumer.h>

#include <KRandom>
#include <KRun>
#include <KDebug>

#include <Nepomuk/Query/Query>
#include <Nepomuk/Query/QueryServiceClient>
#include <Nepomuk/Query/ComparisonTerm>
#include <Nepomuk/Query/LiteralTerm>
#include <Nepomuk/Query/AndTerm>
#include <Nepomuk/Query/QueryServiceClient>
#include <Nepomuk/Query/Result>
#include <Nepomuk/Resource>

#include <Soprano/Vocabulary/NAO>

#include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusMetaType>

#include <QtLocation/QLandmark>

using namespace Soprano::Vocabulary;
using namespace Nepomuk::Vocabulary;

QTM_USE_NAMESPACE

//Q_DECLARE_METATYPE(Contour::Recommendation*)

// TODO: act on several changes:
//       * later: triggers from the dms

class Contour::RecommendationManager::Private
{
public:
    KActivityConsumer* m_activityConsumer;
    LocationManager* m_locationManager;

    QList<Recommendation> m_recommendations;
    QHash<QString, RecommendationAction> m_actionHash;
    QHash<QString, Recommendation> m_RecommendationForAction;

    Nepomuk::Query::QueryServiceClient m_queryClient;

    RecommendationManager* q;

    void updateRecommendations();
    void _k_locationChanged(const QList<QLandmark>&);
    void _k_currentActivityChanged(const QString&);
    void _k_newResults(const QList<Nepomuk::Query::Result>&);
    void _k_queryFinished();
};

void Contour::RecommendationManager::Private::updateRecommendations()
{
    // remove old recommendations
    m_recommendations.clear();
    m_actionHash.clear();
    m_RecommendationForAction.clear();

    // get resources that have been touched in the current activity (the dumb way for now)
    const QString query
            = QString::fromLatin1("select distinct ?resource, ?uri, ?cache,"
                    "("
                        "("
                            "?lastScore * bif:exp(-"
                                "bif:datediff('day', ?lastUpdate, \"2011-06-30T13:45:01.996Z\"^^<http://www.w3.org/2001/XMLSchema#dateTime>"
                            ")"
                        ")"
                    "as ?score) where {"
                        "?cache kext:targettedResource ?resource ."
                        "?cache a kext:ResourceScoreCache ."
                        "?cache nao:lastModified ?lastUpdate ."
                        "?cache kext:cachedScore ?lastScore ."
                        "?cache kext:usedActivity %1 ."
                        "OPTIONAL { ?resource nie:url ?uri . } ."
                    "}"
                    "ORDER BY DESC (?score)"
                    "LIMIT 10")
            .arg(Soprano::Node::resourceToN3(Nepomuk::Resource(m_activityConsumer->currentActivity(), KExt::Activity()).resourceUri()) /*Soprano::Node::literalToN3(Soprano::LiteralValue(m_activityConsumer->currentActivity()))*/);

    m_queryClient.sparqlQuery(query);

    // IDEA: for files use usage events
    //       for everything else use changes in data via graph metadata
}

void Contour::RecommendationManager::Private::_k_locationChanged(const QList<QLandmark>&)
{
    updateRecommendations();
}

void Contour::RecommendationManager::Private::_k_currentActivityChanged(const QString&)
{
    updateRecommendations();
}

void Contour::RecommendationManager::Private::_k_newResults(const QList<Nepomuk::Query::Result>& results)
{
    foreach(const Nepomuk::Query::Result& result, results) {
        Recommendation r;
        r.resourceUri = KUrl(result.resource().resourceUri()).url();

        kWarning() << "Got a new result:" << result.excerpt() << result.score();

        // for now we create the one dummy action: open the resource
        QString id;
        do {
            id = KRandom::randomString(5);
        } while(m_actionHash.contains(id));
        RecommendationAction action;
        action.id = id;
        action.text = i18n("Open '%1'", result.resource().genericLabel());
        m_actionHash[id] = action;
        m_RecommendationForAction[id] = r;

        r.actions << action;

        m_recommendations << r;
    }
}

void Contour::RecommendationManager::Private::_k_queryFinished()
{
    emit q->recommendationsChanged();
}

Contour::RecommendationManager::RecommendationManager(QObject *parent)
    : QObject(parent),
      d(new Private())
{
    d->q = this;

    connect(&d->m_queryClient, SIGNAL(newEntries(QList<Nepomuk::Query::Result>)),
            this, SLOT(_k_newResults(QList<Nepomuk::Query::Result>)));

    d->m_activityConsumer = new KActivityConsumer(this);
    connect(d->m_activityConsumer, SIGNAL(currentActivityChanged(QString)),
            this, SLOT(_k_currentActivityChanged(QString)));
    d->m_locationManager = new LocationManager(this);
    connect(d->m_locationManager, SIGNAL(locationChanged(QList<QLandmark>)),
            this, SLOT(_k_locationChanged(QList<QLandmark>)));
    d->updateRecommendations();

    // export via DBus
    qDBusRegisterMetaType<Contour::Recommendation>();
    qDBusRegisterMetaType<QList<Contour::Recommendation> >();
    qDBusRegisterMetaType<Contour::RecommendationAction>();
    (void)new RecommendationManagerAdaptor(this);
    QDBusConnection::sessionBus().registerObject(QLatin1String("/recommendationmanager"), this);
}

Contour::RecommendationManager::~RecommendationManager()
{
    delete d;
}

QList<Contour::Recommendation> Contour::RecommendationManager::recommendations() const
{
    return d->m_recommendations;
}

void Contour::RecommendationManager::executeAction(const QString &actionId)
{
    if(d->m_actionHash.contains(actionId)) {
        RecommendationAction action = d->m_actionHash.value(actionId);

        // FIXME: this is the hacky execution of the action, make it correct
        Recommendation r = d->m_RecommendationForAction.value(actionId);
        (void)new KRun(r.resourceUri, 0);
    }
    else {
        kDebug() << "Invalid action id encountered:" << actionId;
    }
}

#include "recommendationmanager.moc"
<|endoftext|>


<commit_before>//! \file
/*
**  Copyright (C) - Triton
**
**  This program is under the terms of the LGPLv3 License.
*/

#include <stdexcept>
#include <cstring>

#include <api.hpp>
#include <immediateOperand.hpp>
#include <instruction.hpp>

namespace triton {
  namespace arch {

    Instruction::Instruction() {
      this->address         = 0;
      this->branch          = false;
      this->conditionTaken  = false;
      this->controlFlow     = false;
      this->opcodesSize     = 0;
      this->tid             = 0;
      this->type            = 0;
      std::memset(this->opcodes, 0x00, sizeof(this->opcodes));
    }

    Instruction::~Instruction() {
    }

    Instruction::Instruction(const Instruction& other) {
      this->copy(other);
    }

    void Instruction::operator=(const Instruction& other) {
      this->copy(other);
    }

    void Instruction::copy(const Instruction& other) {
      this->address             = other.address;
      this->branch              = other.branch;
      this->conditionTaken      = other.conditionTaken;
      this->controlFlow         = other.controlFlow;
      this->memoryAccess        = other.memoryAccess;
      this->opcodesSize         = other.opcodesSize;
      this->operands            = other.operands;
      this->registerState       = other.registerState;
      this->symbolicExpressions = other.symbolicExpressions;
      this->tid                 = other.tid;
      this->type                = other.type;

      std::memcpy(this->opcodes, other.opcodes, sizeof(this->opcodes));

      this->disassembly.clear();
      this->disassembly.str(other.disassembly.str());
    }

    triton::uint32 Instruction::getThreadId(void) const {
      return this->tid;
    }

    void Instruction::setThreadId(triton::uint32 tid) {
      this->tid = tid;
    }

    triton::__uint Instruction::getAddress(void) const {
      return this->address;
    }

    triton::__uint Instruction::getNextAddress(void) const {
      return this->address + this->opcodesSize;
    }

    void Instruction::setAddress(triton::__uint addr) {
      this->address = addr;
    }

    std::string Instruction::getDisassembly(void) const {
      return this->disassembly.str();
    }

    const triton::uint8* Instruction::getOpcodes(void) const {
      return this->opcodes;
    }

    void Instruction::setOpcodes(triton::uint8* opcodes, triton::uint32 size) {
      if (size >= sizeof(this->opcodes))
       throw std::runtime_error("Instruction::setOpcodes(): Invalid size (too big)");
      std::memcpy(this->opcodes, opcodes, size);
      this->opcodesSize = size;
    }

    triton::uint32 Instruction::getOpcodesSize(void) const {
      return this->opcodesSize;
    }

    triton::uint32 Instruction::getType(void) const {
      return this->type;
    }

    void Instruction::updateContext(triton::arch::MemoryOperand mem) {
      this->memoryAccess.push_back(mem);
    }

    triton::arch::MemoryOperand Instruction::popMemoryAccess(triton::__uint addr, triton::uint32 size, triton::uint128 value) {
      triton::arch::MemoryOperand mem;

      if (addr && size)
        mem = triton::arch::MemoryOperand(addr, size, value);

      if (this->memoryAccess.size() > 0) {
        mem = this->memoryAccess.front();
        triton::api.setLastMemoryValue(mem);
        this->memoryAccess.pop_front();
      }
      return mem;
    }

    /* If there is a concrete value recorded, build the appropriate RegisterOperand. Otherwise, perfrom the analysis on zero. */
    triton::arch::RegisterOperand Instruction::getRegisterState(triton::uint32 regId) {
      triton::arch::RegisterOperand reg(regId);
      if (this->registerState.find(regId) != this->registerState.end())
        reg = this->registerState[regId];
      return reg;
    }

    void Instruction::setType(triton::uint32 type) {
      this->type = type;
    }

    void Instruction::setDisassembly(std::string str) {
      this->disassembly.clear();
      this->disassembly.str(str);
    }

    void Instruction::updateContext(triton::arch::RegisterOperand reg) {
      if (reg.isFlag())
        throw std::runtime_error("Instruction::updateContext(): You cannot update the context on an isolated flag.");
      this->registerState[reg.getId()] = reg;
    }

    void Instruction::addSymbolicExpression(triton::engines::symbolic::SymbolicExpression* expr) {
      if (expr == nullptr)
        throw std::runtime_error("Instruction::addSymbolicExpression(): Cannot add a null expression.");
      this->symbolicExpressions.push_back(expr);
    }

    bool Instruction::isBranch(void) {
      return this->branch;
    }

    bool Instruction::isControlFlow(void) {
      return this->controlFlow;
    }

    bool Instruction::isConditionTaken(void) {
      return this->conditionTaken;
    }

    void Instruction::setBranch(bool flag) {
      this->branch = flag;
    }

    void Instruction::setControlFlow(bool flag) {
      this->controlFlow = flag;
    }

    void Instruction::setConditionTaken(bool flag) {
      this->conditionTaken = flag;
    }

    void Instruction::reset(void) {
      this->partialReset();
      this->memoryAccess.clear();
      this->registerState.clear();
    }

    void Instruction::partialReset(void) {
      this->address         = 0;
      this->branch          = false;
      this->conditionTaken  = false;
      this->controlFlow     = false;
      this->opcodesSize     = 0;
      this->tid             = 0;
      this->type            = 0;

      this->operands.clear();
      this->symbolicExpressions.clear();
      this->disassembly.clear();

      std::memset(this->opcodes, 0x00, sizeof(this->opcodes));
    }

    std::ostream &operator<<(std::ostream &stream, Instruction inst) {
      stream << std::hex << inst.getAddress() << ": " << inst.getDisassembly() << std::dec;
      return stream;
    }

  };
};

<commit_msg>Add comment<commit_after>//! \file
/*
**  Copyright (C) - Triton
**
**  This program is under the terms of the LGPLv3 License.
*/

#include <stdexcept>
#include <cstring>

#include <api.hpp>
#include <immediateOperand.hpp>
#include <instruction.hpp>

namespace triton {
  namespace arch {

    Instruction::Instruction() {
      this->address         = 0;
      this->branch          = false;
      this->conditionTaken  = false;
      this->controlFlow     = false;
      this->opcodesSize     = 0;
      this->tid             = 0;
      this->type            = 0;
      std::memset(this->opcodes, 0x00, sizeof(this->opcodes));
    }

    Instruction::~Instruction() {
    }

    Instruction::Instruction(const Instruction& other) {
      this->copy(other);
    }

    void Instruction::operator=(const Instruction& other) {
      this->copy(other);
    }

    void Instruction::copy(const Instruction& other) {
      this->address             = other.address;
      this->branch              = other.branch;
      this->conditionTaken      = other.conditionTaken;
      this->controlFlow         = other.controlFlow;
      this->memoryAccess        = other.memoryAccess;
      this->opcodesSize         = other.opcodesSize;
      this->operands            = other.operands;
      this->registerState       = other.registerState;
      this->symbolicExpressions = other.symbolicExpressions;
      this->tid                 = other.tid;
      this->type                = other.type;

      std::memcpy(this->opcodes, other.opcodes, sizeof(this->opcodes));

      this->disassembly.clear();
      this->disassembly.str(other.disassembly.str());
    }

    triton::uint32 Instruction::getThreadId(void) const {
      return this->tid;
    }

    void Instruction::setThreadId(triton::uint32 tid) {
      this->tid = tid;
    }

    triton::__uint Instruction::getAddress(void) const {
      return this->address;
    }

    triton::__uint Instruction::getNextAddress(void) const {
      return this->address + this->opcodesSize;
    }

    void Instruction::setAddress(triton::__uint addr) {
      this->address = addr;
    }

    std::string Instruction::getDisassembly(void) const {
      return this->disassembly.str();
    }

    const triton::uint8* Instruction::getOpcodes(void) const {
      return this->opcodes;
    }

    void Instruction::setOpcodes(triton::uint8* opcodes, triton::uint32 size) {
      if (size >= sizeof(this->opcodes))
       throw std::runtime_error("Instruction::setOpcodes(): Invalid size (too big)");
      std::memcpy(this->opcodes, opcodes, size);
      this->opcodesSize = size;
    }

    triton::uint32 Instruction::getOpcodesSize(void) const {
      return this->opcodesSize;
    }

    triton::uint32 Instruction::getType(void) const {
      return this->type;
    }

    void Instruction::updateContext(triton::arch::MemoryOperand mem) {
      this->memoryAccess.push_back(mem);
    }

    triton::arch::MemoryOperand Instruction::popMemoryAccess(triton::__uint addr, triton::uint32 size, triton::uint128 value) {
      /* The default value is zero */
      triton::arch::MemoryOperand mem;

      /* If there is a default value specified, we use it */
      if (addr && size)
        mem = triton::arch::MemoryOperand(addr, size, value);

      /* If there is a memory access recorded, we use it */
      if (this->memoryAccess.size() > 0) {
        mem = this->memoryAccess.front();
        triton::api.setLastMemoryValue(mem);
        this->memoryAccess.pop_front();
      }

      return mem;
    }

    /* If there is a concrete value recorded, build the appropriate RegisterOperand. Otherwise, perfrom the analysis on zero. */
    triton::arch::RegisterOperand Instruction::getRegisterState(triton::uint32 regId) {
      triton::arch::RegisterOperand reg(regId);
      if (this->registerState.find(regId) != this->registerState.end())
        reg = this->registerState[regId];
      return reg;
    }

    void Instruction::setType(triton::uint32 type) {
      this->type = type;
    }

    void Instruction::setDisassembly(std::string str) {
      this->disassembly.clear();
      this->disassembly.str(str);
    }

    void Instruction::updateContext(triton::arch::RegisterOperand reg) {
      if (reg.isFlag())
        throw std::runtime_error("Instruction::updateContext(): You cannot update the context on an isolated flag.");
      this->registerState[reg.getId()] = reg;
    }

    void Instruction::addSymbolicExpression(triton::engines::symbolic::SymbolicExpression* expr) {
      if (expr == nullptr)
        throw std::runtime_error("Instruction::addSymbolicExpression(): Cannot add a null expression.");
      this->symbolicExpressions.push_back(expr);
    }

    bool Instruction::isBranch(void) {
      return this->branch;
    }

    bool Instruction::isControlFlow(void) {
      return this->controlFlow;
    }

    bool Instruction::isConditionTaken(void) {
      return this->conditionTaken;
    }

    void Instruction::setBranch(bool flag) {
      this->branch = flag;
    }

    void Instruction::setControlFlow(bool flag) {
      this->controlFlow = flag;
    }

    void Instruction::setConditionTaken(bool flag) {
      this->conditionTaken = flag;
    }

    void Instruction::reset(void) {
      this->partialReset();
      this->memoryAccess.clear();
      this->registerState.clear();
    }

    void Instruction::partialReset(void) {
      this->address         = 0;
      this->branch          = false;
      this->conditionTaken  = false;
      this->controlFlow     = false;
      this->opcodesSize     = 0;
      this->tid             = 0;
      this->type            = 0;

      this->operands.clear();
      this->symbolicExpressions.clear();
      this->disassembly.clear();

      std::memset(this->opcodes, 0x00, sizeof(this->opcodes));
    }

    std::ostream &operator<<(std::ostream &stream, Instruction inst) {
      stream << std::hex << inst.getAddress() << ": " << inst.getDisassembly() << std::dec;
      return stream;
    }

  };
};

<|endoftext|>