<commit_before>#include <pcl/point_cloud.h>
#include <pcl/octree/octree.h>

#include <iostream>
#include <vector>
#include <ctime>

int
main (int argc, char** argv)
{
  srand ((unsigned int) time (NULL));

  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);

  // Generate pointcloud data
  cloud->width = 1000;
  cloud->height = 1;
  cloud->points.resize (cloud->width * cloud->height);

  for (size_t i = 0; i < cloud->points.size (); ++i)
  {
    cloud->points[i].x = 1024.0f * rand () / (RAND_MAX + 1.0f);
    cloud->points[i].y = 1024.0f * rand () / (RAND_MAX + 1.0f);
    cloud->points[i].z = 1024.0f * rand () / (RAND_MAX + 1.0f);
  }

  float resolution = 128.0f;

  pcl::octree::OctreePointCloud<pcl::PointXYZ> octree (resolution);

  octree.setInputCloud (cloud);
  octree.addPointsFromInputCloud ();

  pcl::PointXYZ searchPoint;

  searchPoint.x = 1024.0f * rand () / (RAND_MAX + 1.0f);
  searchPoint.y = 1024.0f * rand () / (RAND_MAX + 1.0f);
  searchPoint.z = 1024.0f * rand () / (RAND_MAX + 1.0f);

  // Neighbors within voxel search

  std::vector<int> pointIdxVec;

  if (octree.voxelSearch (searchPoint, pointIdxVec))
  {
    std::cout << "Neighbors within voxel search at (" << searchPoint.x
     << " " << searchPoint.y
     << " " << searchPoint.z << ")"
     << std::endl;

    for (size_t i = 0; i < pointIdxVec.size (); ++i)
   std::cout << "    " << cloud->points[pointIdxVec[i]].x
       << " " << cloud->points[pointIdxVec[i]].y
       << " " << cloud->points[pointIdxVec[i]].z << std::endl;
  }

  // K nearest neighbor search

  int K = 10;

  std::vector<int> pointIdxNKNSearch;
  std::vector<float> pointNKNSquaredDistance;

  std::cout << "K nearest neighbor search at (" << searchPoint.x
            << " " << searchPoint.y
            << " " << searchPoint.z
            << ") with K=" << K << std::endl;

  if (octree.nearestKSearch (searchPoint, K, pointIdxNKNSearch, pointNKNSquaredDistance) > 0)
  {
    for (size_t i = 0; i < pointIdxNKNSearch.size (); ++i)
      std::cout << "    "  <<   cloud->points[ pointIdxNKNSearch[i] ].x
                << " " << cloud->points[ pointIdxNKNSearch[i] ].y
                << " " << cloud->points[ pointIdxNKNSearch[i] ].z
                << " (squared distance: " << pointNKNSquaredDistance[i] << ")" << std::endl;
  }

  // Neighbors within radius search

  std::vector<int> pointIdxRadiusSearch;
  std::vector<float> pointRadiusSquaredDistance;

  float radius = 256.0f * rand () / (RAND_MAX + 1.0f);

  std::cout << "Neighbors within radius search at (" << searchPoint.x
      << " " << searchPoint.y
      << " " << searchPoint.z
      << ") with radius=" << radius << std::endl;

  if (octree.radiusSearch (searchPoint, radius, pointIdxRadiusSearch, pointRadiusSquaredDistance) > 0)
  {
    for (size_t i = 0; i < pointIdxRadiusSearch.size (); ++i)
      std::cout << "    "  <<   cloud->points[ pointIdxRadiusSearch[i] ].x
                << " " << cloud->points[ pointIdxRadiusSearch[i] ].y
                << " " << cloud->points[ pointIdxRadiusSearch[i] ].z
                << " (squared distance: " << pointRadiusSquaredDistance[i] << ")" << std::endl;
  }

}
<commit_msg>replace OctreePointCloud with OctreePointCloudSearch<commit_after>#include <pcl/point_cloud.h>
#include <pcl/octree/octree.h>

#include <iostream>
#include <vector>
#include <ctime>

int
main (int argc, char** argv)
{
  srand ((unsigned int) time (NULL));

  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);

  // Generate pointcloud data
  cloud->width = 1000;
  cloud->height = 1;
  cloud->points.resize (cloud->width * cloud->height);

  for (size_t i = 0; i < cloud->points.size (); ++i)
  {
    cloud->points[i].x = 1024.0f * rand () / (RAND_MAX + 1.0f);
    cloud->points[i].y = 1024.0f * rand () / (RAND_MAX + 1.0f);
    cloud->points[i].z = 1024.0f * rand () / (RAND_MAX + 1.0f);
  }

  float resolution = 128.0f;

  pcl::octree::OctreePointCloudSearch<pcl::PointXYZ> octree (resolution);

  octree.setInputCloud (cloud);
  octree.addPointsFromInputCloud ();

  pcl::PointXYZ searchPoint;

  searchPoint.x = 1024.0f * rand () / (RAND_MAX + 1.0f);
  searchPoint.y = 1024.0f * rand () / (RAND_MAX + 1.0f);
  searchPoint.z = 1024.0f * rand () / (RAND_MAX + 1.0f);

  // Neighbors within voxel search

  std::vector<int> pointIdxVec;

  if (octree.voxelSearch (searchPoint, pointIdxVec))
  {
    std::cout << "Neighbors within voxel search at (" << searchPoint.x
     << " " << searchPoint.y
     << " " << searchPoint.z << ")"
     << std::endl;

    for (size_t i = 0; i < pointIdxVec.size (); ++i)
   std::cout << "    " << cloud->points[pointIdxVec[i]].x
       << " " << cloud->points[pointIdxVec[i]].y
       << " " << cloud->points[pointIdxVec[i]].z << std::endl;
  }

  // K nearest neighbor search

  int K = 10;

  std::vector<int> pointIdxNKNSearch;
  std::vector<float> pointNKNSquaredDistance;

  std::cout << "K nearest neighbor search at (" << searchPoint.x
            << " " << searchPoint.y
            << " " << searchPoint.z
            << ") with K=" << K << std::endl;

  if (octree.nearestKSearch (searchPoint, K, pointIdxNKNSearch, pointNKNSquaredDistance) > 0)
  {
    for (size_t i = 0; i < pointIdxNKNSearch.size (); ++i)
      std::cout << "    "  <<   cloud->points[ pointIdxNKNSearch[i] ].x
                << " " << cloud->points[ pointIdxNKNSearch[i] ].y
                << " " << cloud->points[ pointIdxNKNSearch[i] ].z
                << " (squared distance: " << pointNKNSquaredDistance[i] << ")" << std::endl;
  }

  // Neighbors within radius search

  std::vector<int> pointIdxRadiusSearch;
  std::vector<float> pointRadiusSquaredDistance;

  float radius = 256.0f * rand () / (RAND_MAX + 1.0f);

  std::cout << "Neighbors within radius search at (" << searchPoint.x
      << " " << searchPoint.y
      << " " << searchPoint.z
      << ") with radius=" << radius << std::endl;

  if (octree.radiusSearch (searchPoint, radius, pointIdxRadiusSearch, pointRadiusSquaredDistance) > 0)
  {
    for (size_t i = 0; i < pointIdxRadiusSearch.size (); ++i)
      std::cout << "    "  <<   cloud->points[ pointIdxRadiusSearch[i] ].x
                << " " << cloud->points[ pointIdxRadiusSearch[i] ].y
                << " " << cloud->points[ pointIdxRadiusSearch[i] ].z
                << " (squared distance: " << pointRadiusSquaredDistance[i] << ")" << std::endl;
  }

}
<|endoftext|>


<commit_before>#include <L3G.h>
#include <Wire.h>
#include <math.h>

// Defines ////////////////////////////////////////////////////////////////

// The Arduino two-wire interface uses a 7-bit number for the address,
// and sets the last bit correctly based on reads and writes
#define L3G4200D_ADDRESS_SA0_LOW  (0xD0 >> 1)
#define L3G4200D_ADDRESS_SA0_HIGH (0xD2 >> 1)
#define L3GD20_ADDRESS_SA0_LOW    (0xD4 >> 1)
#define L3GD20_ADDRESS_SA0_HIGH   (0xD6 >> 1)

// Public Methods //////////////////////////////////////////////////////////////

bool L3G::init(byte device, byte sa0)
{
  _device = device;
  switch (_device)
  {
    case L3G4200D_DEVICE:
      if (sa0 == L3G_SA0_LOW)
      {
        address = L3G4200D_ADDRESS_SA0_LOW;
        return true;
      }
      else if (sa0 == L3G_SA0_HIGH)
      {
        address = L3G4200D_ADDRESS_SA0_HIGH;
        return true;
      }
      else
        return autoDetectAddress();
      break;

    case L3GD20_DEVICE:
      if (sa0 == L3G_SA0_LOW)
      {
        address = L3GD20_ADDRESS_SA0_LOW;
        return true;
      }
      else if (sa0 == L3G_SA0_HIGH)
      {
        address = L3GD20_ADDRESS_SA0_HIGH;
        return true;
      }
      else
        return autoDetectAddress();
      break;

    default:
      return autoDetectAddress();
  }
}

// Turns on the L3G's gyro and places it in normal mode.
void L3G::enableDefault(void)
{
  // 0x0F = 0b00001111
  // Normal power mode, all axes enabled
  writeReg(L3G_CTRL_REG1, 0x0F);
}

// Writes a gyro register
void L3G::writeReg(byte reg, byte value)
{
  Wire.beginTransmission(address);
  Wire.write(reg);
  Wire.write(value);
  Wire.endTransmission();
}

// Reads a gyro register
byte L3G::readReg(byte reg)
{
  byte value;

  Wire.beginTransmission(address);
  Wire.write(reg);
  Wire.endTransmission();
  Wire.requestFrom(address, (byte)1);
  value = Wire.read();
  Wire.endTransmission();

  return value;
}

// Reads the 3 gyro channels and stores them in vector g
void L3G::read()
{
  Wire.beginTransmission(address);
  // assert the MSB of the address to get the gyro
  // to do slave-transmit subaddress updating.
  Wire.write(L3G_OUT_X_L | (1 << 7));
  Wire.endTransmission();
  Wire.requestFrom(address, (byte)6);

  while (Wire.available() < 6);

  uint8_t xlg = Wire.read();
  uint8_t xhg = Wire.read();
  uint8_t ylg = Wire.read();
  uint8_t yhg = Wire.read();
  uint8_t zlg = Wire.read();
  uint8_t zhg = Wire.read();

  // combine high and low bytes
  g.x = (int16_t)(xhg << 8 | xlg);
  g.y = (int16_t)(yhg << 8 | ylg);
  g.z = (int16_t)(zhg << 8 | zlg);
}

void L3G::vector_cross(const vector *a,const vector *b, vector *out)
{
  out->x = a->y*b->z - a->z*b->y;
  out->y = a->z*b->x - a->x*b->z;
  out->z = a->x*b->y - a->y*b->x;
}

float L3G::vector_dot(const vector *a,const vector *b)
{
  return a->x*b->x+a->y*b->y+a->z*b->z;
}

void L3G::vector_normalize(vector *a)
{
  float mag = sqrt(vector_dot(a,a));
  a->x /= mag;
  a->y /= mag;
  a->z /= mag;
}

// Private Methods //////////////////////////////////////////////////////////////

bool L3G::autoDetectAddress(void)
{
  // try each possible address and stop if reading WHO_AM_I returns the expected response
  address = L3G4200D_ADDRESS_SA0_LOW;
  if (readReg(L3G_WHO_AM_I) == 0xD3) return true;
  address = L3G4200D_ADDRESS_SA0_HIGH;
  if (readReg(L3G_WHO_AM_I) == 0xD3) return true;
  address = L3GD20_ADDRESS_SA0_LOW;
  if (readReg(L3G_WHO_AM_I) == 0xD4 || readReg(L3G_WHO_AM_I) == 0xD7) return true;
  address = L3GD20_ADDRESS_SA0_HIGH;
  if (readReg(L3G_WHO_AM_I) == 0xD4 || readReg(L3G_WHO_AM_I) == 0xD7) return true;

  return false;
}
<commit_msg>L3G: updated library with timeout functions similar to the ones found in the LSM303 library.<commit_after>#include <L3G.h>
#include <Wire.h>
#include <math.h>

// Defines ////////////////////////////////////////////////////////////////

// The Arduino two-wire interface uses a 7-bit number for the address,
// and sets the last bit correctly based on reads and writes
#define L3G4200D_ADDRESS_SA0_LOW  (0xD0 >> 1)
#define L3G4200D_ADDRESS_SA0_HIGH (0xD2 >> 1)
#define L3GD20_ADDRESS_SA0_LOW    (0xD4 >> 1)
#define L3GD20_ADDRESS_SA0_HIGH   (0xD6 >> 1)

// Constructors ////////////////////////////////////////////////////////////////

L3G::L3G(void)
{
  _device = device_auto;

  io_timeout = 0;  // 0 = no timeout
  did_timeout = false;
}

// Public Methods //////////////////////////////////////////////////////////////

// Did a timeout occur in read() since the last call to timeoutOccurred()?
bool L3G::timeoutOccurred()
{
  bool tmp = did_timeout;
  did_timeout = false;
  return tmp;

}

void L3G::setTimeout(unsigned int timeout)
{
  io_timeout = timeout;
}

unsigned int L3G::getTimeout()
{
  return io_timeout;
}

bool L3G::init(byte device, byte sa0)
{
  _device = device;
  switch (_device)
  {
    case L3G4200D_DEVICE:
      if (sa0 == L3G_SA0_LOW)
      {
        address = L3G4200D_ADDRESS_SA0_LOW;
        return true;
      }
      else if (sa0 == L3G_SA0_HIGH)
      {
        address = L3G4200D_ADDRESS_SA0_HIGH;
        return true;
      }
      else
        return autoDetectAddress();
      break;

    case L3GD20_DEVICE:
      if (sa0 == L3G_SA0_LOW)
      {
        address = L3GD20_ADDRESS_SA0_LOW;
        return true;
      }
      else if (sa0 == L3G_SA0_HIGH)
      {
        address = L3GD20_ADDRESS_SA0_HIGH;
        return true;
      }
      else
        return autoDetectAddress();
      break;

    default:
      return autoDetectAddress();
  }
}

// Turns on the L3G's gyro and places it in normal mode.
void L3G::enableDefault(void)
{
  // 0x0F = 0b00001111
  // Normal power mode, all axes enabled
  writeReg(L3G_CTRL_REG1, 0x0F);
}

// Writes a gyro register
void L3G::writeReg(byte reg, byte value)
{
  Wire.beginTransmission(address);
  Wire.write(reg);
  Wire.write(value);
  Wire.endTransmission();
}

// Reads a gyro register
byte L3G::readReg(byte reg)
{
  byte value;

  Wire.beginTransmission(address);
  Wire.write(reg);
  Wire.endTransmission();
  Wire.requestFrom(address, (byte)1);
  value = Wire.read();
  Wire.endTransmission();

  return value;
}

// Reads the 3 gyro channels and stores them in vector g
void L3G::read()
{
  Wire.beginTransmission(address);
  // assert the MSB of the address to get the gyro
  // to do slave-transmit subaddress updating.
  Wire.write(L3G_OUT_X_L | (1 << 7));
  Wire.endTransmission();
  Wire.requestFrom(address, (byte)6);

  unsigned int millis_start = millis();
  while (Wire.available() < 6){
  {
    if (io_timeout > 0 && ((unsigned int)millis() - millis_start) > io_timeout)
    {
      did_timeout = true;
      return;
    }
  }

  uint8_t xlg = Wire.read();
  uint8_t xhg = Wire.read();
  uint8_t ylg = Wire.read();
  uint8_t yhg = Wire.read();
  uint8_t zlg = Wire.read();
  uint8_t zhg = Wire.read();

  // combine high and low bytes
  g.x = (int16_t)(xhg << 8 | xlg);
  g.y = (int16_t)(yhg << 8 | ylg);
  g.z = (int16_t)(zhg << 8 | zlg);
}

void L3G::vector_cross(const vector *a,const vector *b, vector *out)
{
  out->x = a->y*b->z - a->z*b->y;
  out->y = a->z*b->x - a->x*b->z;
  out->z = a->x*b->y - a->y*b->x;
}

float L3G::vector_dot(const vector *a,const vector *b)
{
  return a->x*b->x+a->y*b->y+a->z*b->z;
}

void L3G::vector_normalize(vector *a)
{
  float mag = sqrt(vector_dot(a,a));
  a->x /= mag;
  a->y /= mag;
  a->z /= mag;
}

// Private Methods //////////////////////////////////////////////////////////////

bool L3G::autoDetectAddress(void)
{
  // try each possible address and stop if reading WHO_AM_I returns the expected response
  address = L3G4200D_ADDRESS_SA0_LOW;
  if (readReg(L3G_WHO_AM_I) == 0xD3) return true;
  address = L3G4200D_ADDRESS_SA0_HIGH;
  if (readReg(L3G_WHO_AM_I) == 0xD3) return true;
  address = L3GD20_ADDRESS_SA0_LOW;
  if (readReg(L3G_WHO_AM_I) == 0xD4 || readReg(L3G_WHO_AM_I) == 0xD7) return true;
  address = L3GD20_ADDRESS_SA0_HIGH;
  if (readReg(L3G_WHO_AM_I) == 0xD4 || readReg(L3G_WHO_AM_I) == 0xD7) return true;

  return false;
}
<|endoftext|>


<commit_before>/*
  User Server code for CMPT 276 Group Assignment, Spring 2016.

  This server manages a user’s social networking session.

  This server supports sign on/off, add friend, unfriend, update status,
  get user's friend list.

  This server handles disallowed method malformed request.

  As defined in ServerUrls.h, the URI for this server is
  http://localhost:34572.
*/

#include <exception>
#include <iostream>
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include <string>

#include <cpprest/base_uri.h>
#include <cpprest/http_listener.h>
#include <cpprest/json.h>

#include <pplx/pplxtasks.h>

#include <was/common.h>
#include <was/storage_account.h>
#include <was/table.h>

#include "../include/ClientUtils.h"
#include "../include/ServerUrls.h"
#include "../include/ServerUtils.h"
#include "../include/TableCache.h"

#include "../include/azure_keys.h"

using azure::storage::cloud_storage_account;
using azure::storage::storage_credentials;
using azure::storage::storage_exception;
using azure::storage::cloud_table;
using azure::storage::cloud_table_client;
using azure::storage::edm_type;
using azure::storage::entity_property;
using azure::storage::table_entity;
using azure::storage::table_operation;
using azure::storage::table_query;
using azure::storage::table_query_iterator;
using azure::storage::table_result;

using pplx::extensibility::critical_section_t;
using pplx::extensibility::scoped_critical_section_t;

using std::cin;
using std::cout;
using std::endl;
using std::getline;
using std::make_pair;
using std::pair;
using std::string;
using std::unordered_map;
using std::vector;
using std::get;

using web::http::client::http_client;
using web::http::http_headers;
using web::http::http_request;
using web::http::http_response;
using web::http::method;
using web::http::methods;
using web::http::status_code;
using web::http::status_codes;
using web::http::uri;

using web::json::value;

using web::http::experimental::listener::http_listener;

using prop_vals_t = vector<pair<string,value>>;

const string get_update_data_op {"GetUpdateData"};

const string read_entity_auth_op {"ReadEntityAuth"};
const string update_entity_auth_op {"UpdateEntityAuth"};

const string auth_table_partition {"Userid"};
const string data_table {"DataTable"};

const string sign_on {"SignOn"}; //POST
const string sign_off {"SignOff"}; //POST

const string add_friend {"AddFriend"}; // PUT
const string unfriend {"UnFriend"}; //PUT
const string update_status {"UpdateStatus"}; //PUT
const string push_status {"PushStatus"}; //Post

const string get_friend_list {"ReadFriendList"}; //GET

// Cache of active sessions
std::unordered_map< string, std::tuple<string/*token*/, string/*partition*/, string/*row*/> > sessions;

/*
  Return true if an HTTP request has a JSON body

  This routine can be called multiple times on the same message.
 */
bool has_json_body (http_request message) {
  return message.headers()["Content-type"] == "application/json";
}

/*
  Given an HTTP message with a JSON body, return the JSON
  body as an unordered map of strings to strings.
  get_json_body and get_json_bourne are valid and identical function calls.

  If the message has no JSON body, return an empty map.

  THIS ROUTINE CAN ONLY BE CALLED ONCE FOR A GIVEN MESSAGE
  (see http://microsoft.github.io/cpprestsdk/classweb_1_1http_1_1http__request.html#ae6c3d7532fe943de75dcc0445456cbc7
  for source of this limit).

  Note that all types of JSON values are returned as strings.
  Use C++ conversion utilities to convert to numbers or dates
  as necessary.
 */
unordered_map<string,string> get_json_body(http_request message) {
  unordered_map<string,string> results {};
  const http_headers& headers {message.headers()};
  auto content_type (headers.find("Content-Type"));
  if (content_type == headers.end() ||
      content_type->second != "application/json")
    return results;

  value json{};
  message.extract_json(true)
    .then([&json](value v) -> bool
          {
            json = v;
            return true;
          })
    .wait();

  if (json.is_object()) {
    for (const auto& v : json.as_object()) {
      if (v.second.is_string()) {
        results[v.first] = v.second.as_string();
      }
      else {
        results[v.first] = v.second.serialize();
      }
    }
  }
  return results;
}

unordered_map<string,string> get_json_bourne(http_request message) {
 return get_json_body(message);
}

void handle_post (http_request message){
  string path {uri::decode(message.relative_uri().path())};
  cout << endl << "**** POST " << path << endl;
  auto paths = uri::split_path(path);

  // Operation name and user ID
  if(paths.size() < 2) {
    message.reply(status_codes::BadRequest);
    return;
  }
  else if(paths[0] != sign_on && paths[0] != sign_off) {
    message.reply(status_codes::BadRequest);
  }

  const string operation = paths[0];
  const string userid = paths[1];

  if(operation == sign_on) {
    if(!has_json_body(message)) {
      message.reply(status_codes::BadRequest);
      return;
    }

    unordered_map<string, string> json_body {get_json_bourne(message)};
    if(json_body.size() != 1) {
      message.reply(status_codes::BadRequest);
      return;
    }

    unordered_map<string, string>::const_iterator json_body_password_iterator {json_body.find("Password")};
    // No 'Password' property
    if(json_body_password_iterator == json_body.end()) {
      message.reply(status_codes::BadRequest);
      return;
    }

    vector<pair<string, value>> json_pw;
    json_pw.push_back(make_pair(
        json_body_password_iterator->first,
        value::string(json_body_password_iterator->second)
    ));

    pair<status_code, value> result;
    result = do_request(
      methods::GET,
      string(server_urls::auth_server) + "/" +
      get_update_data_op + "/" +
      userid,
      value::object(json_pw)
    );
    if(result.first != status_codes::OK) {
      message.reply(result.first);
      return;
    }
    else if(result.second.size() != 3) {
      message.reply(status_codes::InternalError);
      return;
    }

    const string token = get_json_object_prop(
      result.second,
      "token"
    );
    const string data_partition = get_json_object_prop(
      result.second,
      "DataPartition"
    );
    const string data_row = get_json_object_prop(
      result.second,
      "DataRow"
    );
    if(token.empty() ||
       data_partition.empty() ||
       data_row.empty() ) {
      message.reply(status_codes::InternalError);
      return;
    }

    std::tuple<string, string, string> tuple_insert(
      token,
      data_partition,
      data_row);
    std::pair<string, std::tuple<string, string, string>> pair_insert(
      userid,
      tuple_insert
    );
    sessions.insert(pair_insert);

    message.reply(status_codes::OK);
    return;
  }

  else if(operation == sign_off) {
    auto session = sessions.find(userid);
    if(session == sessions.end()) {
      message.reply(status_codes::NotFound);
      return;
    }

    sessions.erase(session);
    message.reply(status_codes::OK);
    return;
  }

  else {
    message.reply(status_codes::InternalError);
    return;
  }
}

void handle_put (http_request message) {
  string path {uri::decode(message.relative_uri().path())};
  cout << endl << "**** POST " << path << endl;
  auto paths = uri::split_path(path);

  if (paths.size() != 2 || paths.size() != 4)
  {
    message.reply(status_codes::BadRequest);
    return;
  }
  string user_id {paths[1]};
  if (sessions[user_id] == sessions["empty value"])
  {
    message.reply(status_codes::BadRequest);
    return;
  }
  pair<status_code, value> result;
  string user_token {get<0>(sessions[user_id])};
  string user_partition {get<1>(sessions[user_id])};
  string user_row {get<2>(sessions[user_id])};

  if (paths[0] == add_friend) {
    // TODO: Check validity of the request
      // Invalid path size
    if (paths.size() != 4)
    {
      message.reply(status_codes::BadRequest);
      return;
    }
    // Get current friends list
    result = do_request(
      methods::GET,
      string(server_urls::basic_server) + "/" +
      read_entity_auth_op + "/" +
      data_table + "/" +
      user_token + "/" +
      user_partition + "/" +
      user_row
      );
    // TODO: Check status code
    // Parse JSON body
    unordered_map<string,string> json_body = unpack_json_object(result.second);
    friends_list_t user_friends = parse_friends_list(json_body["Friends"]);
    // Add new friend to list
    user_friends.push_back(make_pair(paths[2],paths[3]));
    // Rebuild json body
    string user_friends_string = friends_list_to_string(user_friends);
    result.second = build_json_value("Friends", user_friends_string);
    // Put new friends list
    do_request(
      methods::PUT,
      string(server_urls::basic_server) + "/" +
      update_entity_auth_op + "/" +
      data_table + "/" +
      user_token + "/" +
      user_partition + "/" +
      user_row,
      result.second
      );
    // TODO: Check return results
    message.reply(status_codes::OK);
    return;
  }
  /*
   * UnFriend
   */
  else if (paths[0] == unfriend) {
    // TODO: Check validity of request
    if (paths.size() != 4)
    {
      message.reply(status_codes::BadRequest);
      return;
    }
    // Get current friends list
    result = do_request(
      methods::GET,
      string(server_urls::basic_server) + "/" +
      read_entity_auth_op + "/" +
      data_table + "/" +
      user_token + "/" +
      user_partition + "/" +
      user_row
      );
    // TODO: Check status code
    // Parse Json body
    unordered_map<string,string> json_body = unpack_json_object(result.second);
    friends_list_t user_friends = parse_friends_list(json_body["Friends"]);
    // Remove friend from list
    friends_list_t new_user_friends;
    for (int i = 0; i < user_friends.size(); ++i)
    {
      if (user_friends[i].first != paths[2] || user_friends[i].second != paths[3])
      {
        new_user_friends.push_back(user_friends[i]);
      }
    }
    // Rebuild json body
    string user_friends_string = friends_list_to_string(new_user_friends);
    result.second = build_json_value("Friends", user_friends_string);
    // Put new friends list
    do_request(
      methods::PUT,
      string(server_urls::basic_server) + "/" +
      update_entity_auth_op + "/" +
      data_table + "/" +
      user_token + "/" +
      user_partition + "/" +
      user_row,
      result.second
      );
    // TODO: Check return results
    message.reply(status_codes::OK);
    return;
  }
  else if (paths[0] == update_status)
  {
    // Check validity of request
    if (paths.size() != 3)
    {
      message.reply(status_codes::BadRequest);
      return;
    }
    result.second = build_json_value("Status", string(paths[2]));
    // Edit entity
    result = do_request(
      methods::PUT,
      string(server_urls::basic_server) + "/" +
      update_entity_auth_op + "/" +
      data_table + "/" +
      user_partition + "/" +
      user_row,
      result.second
      );
    // Call Pushserver
    result = do_request(
      methods::POST,
      string(server_urls::push_server) + "/" +
      push_status + "/" +
      user_partition + "/" +
      user_row + "/" +
      paths[3]
      );
  }
  else {
    // malformed request
    vector<value> vec;
    message.reply(status_codes::BadRequest, value::array(vec));
    return;
  }
}

void handle_get (http_request message) {
  string path {uri::decode(message.relative_uri().path())};
  cout << endl << "**** POST " << path << endl;
  auto paths = uri::split_path(path);

  if(true/*basic criteria*/){}
  else if (paths[0] == get_friend_list) {}
  else {
    // malformed request
    vector<value> vec;
    message.reply(status_codes::BadRequest, value::array(vec));
    return;
  }
}

int main (int argc, char const * argv[]) {
  cout << "Opening listener" << endl;
  http_listener listener {server_urls::user_server};
  listener.support(methods::GET, &handle_get); // Get user's friend list
  listener.support(methods::POST, &handle_post); // SignOn, SignOff
  listener.support(methods::PUT, &handle_put); // Add friend, Unfriend, Update Status
  /*TO DO: Disallowed method*/
  listener.open().wait(); // Wait for listener to complete starting

  cout << "Enter carriage return to stop server." << endl;
  string line;
  getline(std::cin, line);

  // Shut it down
  listener.close().wait();
  cout << "Closed" << endl;
}
<commit_msg>update edge cases<commit_after>/*
  User Server code for CMPT 276 Group Assignment, Spring 2016.

  This server manages a user’s social networking session.

  This server supports sign on/off, add friend, unfriend, update status,
  get user's friend list.

  This server handles disallowed method malformed request.

  As defined in ServerUrls.h, the URI for this server is
  http://localhost:34572.
*/

#include <exception>
#include <iostream>
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include <string>

#include <cpprest/base_uri.h>
#include <cpprest/http_listener.h>
#include <cpprest/json.h>

#include <pplx/pplxtasks.h>

#include <was/common.h>
#include <was/storage_account.h>
#include <was/table.h>

#include "../include/ClientUtils.h"
#include "../include/ServerUrls.h"
#include "../include/ServerUtils.h"
#include "../include/TableCache.h"

#include "../include/azure_keys.h"

using azure::storage::cloud_storage_account;
using azure::storage::storage_credentials;
using azure::storage::storage_exception;
using azure::storage::cloud_table;
using azure::storage::cloud_table_client;
using azure::storage::edm_type;
using azure::storage::entity_property;
using azure::storage::table_entity;
using azure::storage::table_operation;
using azure::storage::table_query;
using azure::storage::table_query_iterator;
using azure::storage::table_result;

using pplx::extensibility::critical_section_t;
using pplx::extensibility::scoped_critical_section_t;

using std::cin;
using std::cout;
using std::endl;
using std::getline;
using std::make_pair;
using std::pair;
using std::string;
using std::unordered_map;
using std::vector;
using std::get;

using web::http::client::http_client;
using web::http::http_headers;
using web::http::http_request;
using web::http::http_response;
using web::http::method;
using web::http::methods;
using web::http::status_code;
using web::http::status_codes;
using web::http::uri;

using web::json::value;

using web::http::experimental::listener::http_listener;

using prop_vals_t = vector<pair<string,value>>;

const string get_update_data_op {"GetUpdateData"};

const string read_entity_auth_op {"ReadEntityAuth"};
const string update_entity_auth_op {"UpdateEntityAuth"};

const string auth_table_partition {"Userid"};
const string data_table {"DataTable"};

const string sign_on {"SignOn"}; //POST
const string sign_off {"SignOff"}; //POST

const string add_friend {"AddFriend"}; // PUT
const string unfriend {"UnFriend"}; //PUT
const string update_status {"UpdateStatus"}; //PUT
const string push_status {"PushStatus"}; //Post

const string get_friend_list {"ReadFriendList"}; //GET

// Cache of active sessions
std::unordered_map< string, std::tuple<string/*token*/, string/*partition*/, string/*row*/> > sessions;

/*
  Return true if an HTTP request has a JSON body

  This routine can be called multiple times on the same message.
 */
bool has_json_body (http_request message) {
  return message.headers()["Content-type"] == "application/json";
}

/*
  Given an HTTP message with a JSON body, return the JSON
  body as an unordered map of strings to strings.
  get_json_body and get_json_bourne are valid and identical function calls.

  If the message has no JSON body, return an empty map.

  THIS ROUTINE CAN ONLY BE CALLED ONCE FOR A GIVEN MESSAGE
  (see http://microsoft.github.io/cpprestsdk/classweb_1_1http_1_1http__request.html#ae6c3d7532fe943de75dcc0445456cbc7
  for source of this limit).

  Note that all types of JSON values are returned as strings.
  Use C++ conversion utilities to convert to numbers or dates
  as necessary.
 */
unordered_map<string,string> get_json_body(http_request message) {
  unordered_map<string,string> results {};
  const http_headers& headers {message.headers()};
  auto content_type (headers.find("Content-Type"));
  if (content_type == headers.end() ||
      content_type->second != "application/json")
    return results;

  value json{};
  message.extract_json(true)
    .then([&json](value v) -> bool
          {
            json = v;
            return true;
          })
    .wait();

  if (json.is_object()) {
    for (const auto& v : json.as_object()) {
      if (v.second.is_string()) {
        results[v.first] = v.second.as_string();
      }
      else {
        results[v.first] = v.second.serialize();
      }
    }
  }
  return results;
}

unordered_map<string,string> get_json_bourne(http_request message) {
 return get_json_body(message);
}

void handle_post (http_request message){
  string path {uri::decode(message.relative_uri().path())};
  cout << endl << "**** POST " << path << endl;
  auto paths = uri::split_path(path);

  // Operation name and user ID
  if(paths.size() < 2) {
    message.reply(status_codes::BadRequest);
    return;
  }
  else if(paths[0] != sign_on && paths[0] != sign_off) {
    message.reply(status_codes::BadRequest);
  }

  const string operation = paths[0];
  const string userid = paths[1];

  if(operation == sign_on) {
    if(!has_json_body(message)) {
      message.reply(status_codes::BadRequest);
      return;
    }

    unordered_map<string, string> json_body {get_json_bourne(message)};
    if(json_body.size() != 1) {
      message.reply(status_codes::BadRequest);
      return;
    }

    unordered_map<string, string>::const_iterator json_body_password_iterator {json_body.find("Password")};
    // No 'Password' property
    if(json_body_password_iterator == json_body.end()) {
      message.reply(status_codes::BadRequest);
      return;
    }

    vector<pair<string, value>> json_pw;
    json_pw.push_back(make_pair(
        json_body_password_iterator->first,
        value::string(json_body_password_iterator->second)
    ));

    pair<status_code, value> result;
    result = do_request(
      methods::GET,
      string(server_urls::auth_server) + "/" +
      get_update_data_op + "/" +
      userid,
      value::object(json_pw)
    );
    if(result.first != status_codes::OK) {
      message.reply(result.first);
      return;
    }
    else if(result.second.size() != 3) {
      message.reply(status_codes::InternalError);
      return;
    }

    const string token = get_json_object_prop(
      result.second,
      "token"
    );
    const string data_partition = get_json_object_prop(
      result.second,
      "DataPartition"
    );
    const string data_row = get_json_object_prop(
      result.second,
      "DataRow"
    );
    if(token.empty() ||
       data_partition.empty() ||
       data_row.empty() ) {
      message.reply(status_codes::InternalError);
      return;
    }

    std::tuple<string, string, string> tuple_insert(
      token,
      data_partition,
      data_row);
    std::pair<string, std::tuple<string, string, string>> pair_insert(
      userid,
      tuple_insert
    );
    sessions.insert(pair_insert);

    message.reply(status_codes::OK);
    return;
  }

  else if(operation == sign_off) {
    auto session = sessions.find(userid);
    if(session == sessions.end()) {
      message.reply(status_codes::NotFound);
      return;
    }

    sessions.erase(session);
    message.reply(status_codes::OK);
    return;
  }

  else {
    message.reply(status_codes::InternalError);
    return;
  }
}

void handle_put (http_request message) {
  string path {uri::decode(message.relative_uri().path())};
  cout << endl << "**** POST " << path << endl;
  auto paths = uri::split_path(path);

  if (paths.size() != 2 || paths.size() != 4)
  {
    message.reply(status_codes::BadRequest);
    return;
  }
  string user_id {paths[1]};
  if (sessions[user_id] == sessions["empty value"])
  {
    message.reply(status_codes::Forbidden);
    return;
  }
  pair<status_code, value> result;
  string user_token {get<0>(sessions[user_id])};
  string user_partition {get<1>(sessions[user_id])};
  string user_row {get<2>(sessions[user_id])};

  if (paths[0] == add_friend) {
    // TODO: Check validity of the request
      // Invalid path size
    if (paths.size() != 4)
    {
      message.reply(status_codes::BadRequest);
      return;
    }
    // Get current friends list
    result = do_request(
      methods::GET,
      string(server_urls::basic_server) + "/" +
      read_entity_auth_op + "/" +
      data_table + "/" +
      user_token + "/" +
      user_partition + "/" +
      user_row
      );
    if (result.first != status_codes::OK)
    {
      message.reply(result.first);
      return;
    }
    // TODO: Check status code
    // Parse JSON body
    unordered_map<string,string> json_body = unpack_json_object(result.second);
    friends_list_t user_friends = parse_friends_list(json_body["Friends"]);
    // Add new friend to list
    user_friends.push_back(make_pair(paths[2],paths[3]));
    // Rebuild json body
    string user_friends_string = friends_list_to_string(user_friends);
    result.second = build_json_value("Friends", user_friends_string);
    // Put new friends list
    result = do_request(
      methods::PUT,
      string(server_urls::basic_server) + "/" +
      update_entity_auth_op + "/" +
      data_table + "/" +
      user_token + "/" +
      user_partition + "/" +
      user_row,
      result.second
      );
    if (result.first != status_codes::OK)
    {
      message.reply(result.first);
      return;
    }
    // TODO: Check return results
    message.reply(status_codes::OK);
    return;
  }
  /*
   * UnFriend
   */
  else if (paths[0] == unfriend) {
    // TODO: Check validity of request
    if (paths.size() != 4)
    {
      message.reply(status_codes::BadRequest);
      return;
    }
    // Get current friends list
    result = do_request(
      methods::GET,
      string(server_urls::basic_server) + "/" +
      read_entity_auth_op + "/" +
      data_table + "/" +
      user_token + "/" +
      user_partition + "/" +
      user_row
      );
    if (result.first != status_codes::OK)
    {
      message.reply(result.first);
      return;
    }
    // TODO: Check status code
    // Parse Json body
    unordered_map<string,string> json_body = unpack_json_object(result.second);
    friends_list_t user_friends = parse_friends_list(json_body["Friends"]);
    // Remove friend from list
    friends_list_t new_user_friends;
    for (int i = 0; i < user_friends.size(); ++i)
    {
      if (user_friends[i].first != paths[2] || user_friends[i].second != paths[3])
      {
        new_user_friends.push_back(user_friends[i]);
      }
    }
    // Rebuild json body
    string user_friends_string = friends_list_to_string(new_user_friends);
    result.second = build_json_value("Friends", user_friends_string);
    // Put new friends list
    result = do_request(
      methods::PUT,
      string(server_urls::basic_server) + "/" +
      update_entity_auth_op + "/" +
      data_table + "/" +
      user_token + "/" +
      user_partition + "/" +
      user_row,
      result.second
      );
    if (result.first != status_codes::OK)
    {
      message.reply(result.first);
      return;
    }
    // TODO: Check return results
    message.reply(status_codes::OK);
    return;
  }
  else if (paths[0] == update_status)
  {
    // Check validity of request
    if (paths.size() != 3)
    {
      message.reply(status_codes::BadRequest);
      return;
    }
    result.second = build_json_value("Status", string(paths[2]));
    // Edit entity
    result = do_request(
      methods::PUT,
      string(server_urls::basic_server) + "/" +
      update_entity_auth_op + "/" +
      data_table + "/" +
      user_partition + "/" +
      user_row,
      result.second
      );
    if (result.first != status_codes::OK)
    {
      message.reply(result.first);
      return;
    }
    // Call Pushserver
    result = do_request(
      methods::POST,
      string(server_urls::push_server) + "/" +
      push_status + "/" +
      user_partition + "/" +
      user_row + "/" +
      paths[3]
      );
    if (result.first != status_codes::OK)
    {
      message.reply(result.first);
      return;
    }
  }
  else {
    // malformed request
    vector<value> vec;
    message.reply(status_codes::BadRequest, value::array(vec));
    return;
  }
}

void handle_get (http_request message) {
  string path {uri::decode(message.relative_uri().path())};
  cout << endl << "**** POST " << path << endl;
  auto paths = uri::split_path(path);

  if(true/*basic criteria*/){}
  else if (paths[0] == get_friend_list) {}
  else {
    // malformed request
    vector<value> vec;
    message.reply(status_codes::BadRequest, value::array(vec));
    return;
  }
}

int main (int argc, char const * argv[]) {
  cout << "Opening listener" << endl;
  http_listener listener {server_urls::user_server};
  listener.support(methods::GET, &handle_get); // Get user's friend list
  listener.support(methods::POST, &handle_post); // SignOn, SignOff
  listener.support(methods::PUT, &handle_put); // Add friend, Unfriend, Update Status
  /*TO DO: Disallowed method*/
  listener.open().wait(); // Wait for listener to complete starting

  cout << "Enter carriage return to stop server." << endl;
  string line;
  getline(std::cin, line);

  // Shut it down
  listener.close().wait();
  cout << "Closed" << endl;
}
<|endoftext|>


<commit_before>/*
 *
 *  Copyright 2013 Mario Alviano, Carmine Dodaro, and Francesco Ricca.
 *
 *  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 "WaspFacade.h"

#include "Restart.h"

#include "input/GringoNumericFormat.h"

#include "outputBuilders/WaspOutputBuilder.h"
#include "outputBuilders/SilentOutputBuilder.h"
#include "outputBuilders/ThirdCompetitionOutputBuilder.h"
#include "outputBuilders/CompetitionOutputBuilder.h"
#include "outputBuilders/DimacsOutputBuilder.h"

#include "outputBuilders/MultiOutputBuilder.h"
#include "QueryInterface.h"
#include "outputBuilders/IdOutputBuilder.h"
#include "outputBuilders/NoopOutputBuilder.h"
#include "Enumeration.h"

void
WaspFacade::readInput(
    istream& in )
{
    char tmp;
    in >> tmp;

    if( !in.good() && !in.eof() )
        WaspErrorMessage::errorDuringParsing( "Unexpected symbol." );

    in.putback( tmp );
    switch ( tmp )
    {
        case COMMENT_DIMACS:
        case FORMULA_INFO_DIMACS:
        {
            DimacsOutputBuilder* d = new DimacsOutputBuilder();
            solver.setOutputBuilder( d );
            Dimacs dimacs( solver );
            dimacs.parse();
            if( dimacs.isMaxsat() )
                d->setMaxsat();
            delete outputBuilder;
            outputBuilder = d;
            greetings();
            break;
        }

        default:
        {
            GringoNumericFormat gringo( solver );
            gringo.parse( in );
//            solver.setOutputBuilder( new WaspOutputBuilder() );
            greetings();
            break;
        }
    }
}

void
WaspFacade::solve()
{
    if(runtime_) { WaspErrorMessage::errorGeneric("Calling method solve twice."); return; }
    runtime_ = true;

    if(disableVE_) solver.disableVariableElimination();
    if(!solver.preprocessing()) { solver.foundIncoherence(); return; }

    statistics( &solver, startSolving() );
    solver.onStartingSolver();

    if(wasp::Options::queryAlgorithm != NO_QUERY) { QueryInterface queryInterface( solver ); queryInterface.solve(); }
    else if(!solver.isOptimizationProblem() && !wasp::Options::useLazyWeakConstraints) { Enumeration enumeration(solver); enumeration.solve(); }
    else handleWeakConstraints();

    return;
}

void WaspFacade::handleWeakConstraints() {
    NoopOutputBuilder* tmp = new NoopOutputBuilder();
    if( wasp::Options::printOnlyOptimum || wasp::Options::maxModels > 1 )
        solver.setOutputBuilder( tmp );
    unsigned int result = solveWithWeakConstraints();
    switch( result ) {
        case COHERENT:
            cerr << "ERROR";
            break;

        case INCOHERENT:
            if( wasp::Options::printOnlyOptimum || wasp::Options::maxModels > 1 )
                solver.setOutputBuilder( outputBuilder );
            solver.foundIncoherence();
            break;

        case OPTIMUM_FOUND:
        default:
            if( wasp::Options::maxModels > 1 ) {
                solver.unrollToZero();
                solver.clearConflictStatus();
                if( wasp::Options::printOnlyOptimum )
                    solver.setOutputBuilder( outputBuilder );
                solver.setMinimizeUnsatCore(false);
                Enumeration enumeration(solver);
                enumeration.solve();
                if( wasp::Options::printOnlyOptimum )
                    tmp->print();
                solver.optimumFound();
            }
            else
                solver.optimumFound();
            break;
    }
    delete tmp;
}

void
WaspFacade::setOutputPolicy(
    OUTPUT_POLICY outputPolicy )
{
    delete outputBuilder;
    switch( outputPolicy )
    {
        case COMPETITION_OUTPUT:
            outputBuilder = new CompetitionOutputBuilder();
            break;

        case DIMACS_OUTPUT:
            outputBuilder = new DimacsOutputBuilder();
            break;

        case SILENT_OUTPUT:
            outputBuilder = new SilentOutputBuilder();
            break;

        case THIRD_COMPETITION_OUTPUT:
            outputBuilder = new ThirdCompetitionOutputBuilder();
            break;

        case MULTI:
            outputBuilder = new MultiOutputBuilder();
            break;

        case ID_OUTPUT:
            outputBuilder = new IdOutputBuilder();
            break;

        case WASP_OUTPUT:
        default:
            outputBuilder = new WaspOutputBuilder();
            break;
    }
    solver.setOutputBuilder( outputBuilder );
}

void
WaspFacade::setRestartsPolicy(
    RESTARTS_POLICY restartsPolicy,
    unsigned int threshold )
{
    assert( threshold > 0 );
    Restart* restart;
    switch( restartsPolicy )
    {
        case GEOMETRIC_RESTARTS_POLICY:
            restart = new Restart( threshold, false );
            solver.setRestart( restart );
            break;

        case SEQUENCE_BASED_RESTARTS_POLICY:
        default:
            restart = new Restart( threshold, true );
            solver.setRestart( restart );
            break;
    }
}

void merge(int left,int center,int right,vector<Literal>& literals,vector<uint64_t>& weights)
{
    Literal* auxLiterals = new Literal[right+1];
    uint64_t* auxWeights = new uint64_t[right+1];

    int i, j;
    for(i=center+1; i>left; i--) { auxLiterals[i-1]=literals[i-1]; auxWeights[i-1]=weights[i-1]; }
    for(j=center; j<right; j++) { auxLiterals[right+center-j]=literals[j+1]; auxWeights[right+center-j]=weights[j+1]; }
    for( int k = left; k <= right; k++ ) {
        if(auxWeights[j]>auxWeights[i]) { literals[k]=auxLiterals[j]; weights[k]=auxWeights[j--]; }
        else { literals[k]=auxLiterals[i]; weights[k]=auxWeights[i++]; }
    }

    delete [] auxWeights; delete [] auxLiterals;
}

void mergesort(int left,int right,vector<Literal>& literals,vector<uint64_t>& weights )
{
    if( left < right ) {
        int center = (left+right)/2;
        mergesort(left,center,literals,weights);
        mergesort(center+1,right,literals,weights);
        merge(left,center,right,literals,weights);
    }
}

bool
WaspFacade::addPseudoBooleanConstraint(
    vector<Literal>& lits,
    vector<uint64_t>& weights,
    uint64_t bound)
{
    if(solver.conflictDetected() || !ok_) return false;
    solver.unrollToZero();
    if(lits.size() != weights.size())
        WaspErrorMessage::errorGeneric("The size of literals must be equal to the size of weights in pseudoBoolean constraints.");

    if(bound == 0) return true;
    uint64_t differentWeights = UINT64_MAX;
    uint64_t sumOfWeights = 0;
    unsigned int j = 0;
    for(unsigned int i = 0; i < lits.size(); i++) {
        lits[i]=lits[j];    weights[i]=weights[j];
        addVariables(lits[i].getVariable());
        if(solver.hasBeenEliminated(lits[i].getVariable())) WaspErrorMessage::errorGeneric("Trying to add a deleted variable to aggregate.");
        if(solver.isFalse(lits[i]) || weights[i] == 0) continue;
        if(solver.isTrue(lits[i])) {
            if(bound <= weights[i]) return true;
            bound -= weights[i];
            continue;
        }

        if(weights[i] > bound) { weights[i] = bound; }
        if(differentWeights == UINT64_MAX)
            differentWeights = weights[i];
        else if(differentWeights != weights[i])
            differentWeights = UINT64_MAX-1;
        sumOfWeights += weights[i];
        j++;
    }
    lits.resize(j);    weights.resize(j);
    if(sumOfWeights < bound) { ok_ = false; return false; }
    if(differentWeights < UINT64_MAX-1 && differentWeights >= bound) { return addClause(lits); }

    mergesort(0, lits.size()-1, lits, weights);

    if(runtime_) solver.addVariableRuntime();
    else solver.addVariable();
    Var aggrId = solver.numberOfVariables();
    solver.setFrozen( aggrId );
    Aggregate* aggregate = new Aggregate();
    Literal aggregateLiteral = solver.getLiteral( aggrId );
    aggregate->addLiteral(aggregateLiteral.getOppositeLiteral(), 0);
    #ifndef NDEBUG
    uint64_t previousWeight = UINT64_MAX;
    #endif
    for( unsigned int i = 0; i < lits.size(); i++ ) {
        assert(lits[i].getVariable() <= solver.numberOfVariables());
        assert(solver.isUndefined(lits[i].getVariable()));
        assert(!solver.hasBeenEliminated(lits[i].getVariable()));
        aggregate->addLiteral( lits[i], weights[i] );
        solver.setFrozen( lits[i].getVariable() );
        assert_msg( previousWeight >= weights[i], "Literals must be sorted in increasing order" );
        assert( previousWeight = weights[i] );
    }
    assert( aggregate->size() >= 1 );
    bool res = solver.addClauseRuntime(aggregateLiteral);
    if(!res) { ok_ = false; return false; }

    if( !aggregate->updateBound( solver, bound ) ) { delete aggregate; ok_ = false; return false; }

    solver.attachAggregate( *aggregate );
    solver.addAggregate( aggregate );

    assert( solver.isTrue( aggregateLiteral ) );
    aggregate->onLiteralFalse( solver, aggregateLiteral.getOppositeLiteral(), 1 );

    if( solver.conflictDetected() ) { ok_ = false; return false; }
    return ok_;
}

unsigned int
WaspFacade::solve(const vector<Literal>& assumptions, vector<Literal>& conflict)
{
    if(!ok_) { return INCOHERENT; }
    nbCalls++;
    //First call
    if(!runtime_) {
        runtime_ = true;
        if(disableVE_) solver.disableVariableElimination();
        if(!solver.preprocessing()) { ok_ = false; return INCOHERENT; }
        solver.turnOffSimplifications();
        solver.setComputeUnsatCores(true);
        statistics(&solver, startSolving());
        solver.onStartingSolver();
    }
    conflict.clear();
    solver.unrollToZero();
    vector<Literal> assumptions_;
    for(unsigned int i = 0; i < assumptions.size(); i++) {
        if(solver.hasBeenEliminated(assumptions[i].getVariable())) WaspErrorMessage::errorGeneric("Assumption literal has been eliminated. (Assumptions must be frozen).");
        assumptions_.push_back(assumptions[i]);
    }

    unsigned int res = solver.solve(assumptions_);
    if( res == INCOHERENT ) {
        assert(solver.getUnsatCore() != NULL);
        const Clause& core = *solver.getUnsatCore();
        for( unsigned int i = 0; i < core.size(); i++ )
            conflict.push_back(core.getAt(i));
        if(core.size() == 0) ok_ = false;
        solver.unrollToZero();
        solver.clearConflictStatus();
    }
    return res;
}
<commit_msg>Unrolled previous commit.<commit_after>/*
 *
 *  Copyright 2013 Mario Alviano, Carmine Dodaro, and Francesco Ricca.
 *
 *  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 "WaspFacade.h"

#include "Restart.h"

#include "input/GringoNumericFormat.h"

#include "outputBuilders/WaspOutputBuilder.h"
#include "outputBuilders/SilentOutputBuilder.h"
#include "outputBuilders/ThirdCompetitionOutputBuilder.h"
#include "outputBuilders/CompetitionOutputBuilder.h"
#include "outputBuilders/DimacsOutputBuilder.h"

#include "outputBuilders/MultiOutputBuilder.h"
#include "QueryInterface.h"
#include "outputBuilders/IdOutputBuilder.h"
#include "outputBuilders/NoopOutputBuilder.h"
#include "Enumeration.h"

void
WaspFacade::readInput(
    istream& in )
{
    char tmp;
    in >> tmp;

    if( !in.good() && !in.eof() )
        WaspErrorMessage::errorDuringParsing( "Unexpected symbol." );

    in.putback( tmp );
    switch ( tmp )
    {
        case COMMENT_DIMACS:
        case FORMULA_INFO_DIMACS:
        {
            DimacsOutputBuilder* d = new DimacsOutputBuilder();
            solver.setOutputBuilder( d );
            Dimacs dimacs( solver );
            dimacs.parse();
            if( dimacs.isMaxsat() )
                d->setMaxsat();
            delete outputBuilder;
            outputBuilder = d;
            greetings();
            break;
        }

        default:
        {
            GringoNumericFormat gringo( solver );
            gringo.parse( in );
//            solver.setOutputBuilder( new WaspOutputBuilder() );
            greetings();
            break;
        }
    }
}

void
WaspFacade::solve()
{
    if(runtime_) { WaspErrorMessage::errorGeneric("Calling method solve twice."); return; }
    runtime_ = true;

    if(disableVE_) solver.disableVariableElimination();
    if(!solver.preprocessing()) { solver.foundIncoherence(); return; }

    statistics( &solver, startSolving() );
    solver.onStartingSolver();

    if(wasp::Options::queryAlgorithm != NO_QUERY) { QueryInterface queryInterface( solver ); queryInterface.solve(); }
    else if(!solver.isOptimizationProblem() && !wasp::Options::useLazyWeakConstraints) { Enumeration enumeration(solver); enumeration.solve(); }
    else handleWeakConstraints();

    return;
}

void WaspFacade::handleWeakConstraints() {
    NoopOutputBuilder* tmp = new NoopOutputBuilder();
    if( wasp::Options::printOnlyOptimum && wasp::Options::maxModels > 1 )
        solver.setOutputBuilder( tmp );
    unsigned int result = solveWithWeakConstraints();
    switch( result ) {
        case COHERENT:
            cerr << "ERROR";
            break;

        case INCOHERENT:
            if( wasp::Options::printOnlyOptimum && wasp::Options::maxModels > 1 )
                solver.setOutputBuilder( outputBuilder );
            solver.foundIncoherence();
            break;

        case OPTIMUM_FOUND:
        default:
            if( wasp::Options::maxModels > 1 ) {
                solver.unrollToZero();
                solver.clearConflictStatus();
                if( wasp::Options::printOnlyOptimum )
                    solver.setOutputBuilder( outputBuilder );
                solver.setMinimizeUnsatCore(false);
                Enumeration enumeration(solver);
                enumeration.solve();
                if( wasp::Options::printOnlyOptimum )
                    tmp->print();
                solver.optimumFound();
            }
            else
                solver.optimumFound();
            break;
    }
    delete tmp;
}

void
WaspFacade::setOutputPolicy(
    OUTPUT_POLICY outputPolicy )
{
    delete outputBuilder;
    switch( outputPolicy )
    {
        case COMPETITION_OUTPUT:
            outputBuilder = new CompetitionOutputBuilder();
            break;

        case DIMACS_OUTPUT:
            outputBuilder = new DimacsOutputBuilder();
            break;

        case SILENT_OUTPUT:
            outputBuilder = new SilentOutputBuilder();
            break;

        case THIRD_COMPETITION_OUTPUT:
            outputBuilder = new ThirdCompetitionOutputBuilder();
            break;

        case MULTI:
            outputBuilder = new MultiOutputBuilder();
            break;

        case ID_OUTPUT:
            outputBuilder = new IdOutputBuilder();
            break;

        case WASP_OUTPUT:
        default:
            outputBuilder = new WaspOutputBuilder();
            break;
    }
    solver.setOutputBuilder( outputBuilder );
}

void
WaspFacade::setRestartsPolicy(
    RESTARTS_POLICY restartsPolicy,
    unsigned int threshold )
{
    assert( threshold > 0 );
    Restart* restart;
    switch( restartsPolicy )
    {
        case GEOMETRIC_RESTARTS_POLICY:
            restart = new Restart( threshold, false );
            solver.setRestart( restart );
            break;

        case SEQUENCE_BASED_RESTARTS_POLICY:
        default:
            restart = new Restart( threshold, true );
            solver.setRestart( restart );
            break;
    }
}

void merge(int left,int center,int right,vector<Literal>& literals,vector<uint64_t>& weights)
{
    Literal* auxLiterals = new Literal[right+1];
    uint64_t* auxWeights = new uint64_t[right+1];

    int i, j;
    for(i=center+1; i>left; i--) { auxLiterals[i-1]=literals[i-1]; auxWeights[i-1]=weights[i-1]; }
    for(j=center; j<right; j++) { auxLiterals[right+center-j]=literals[j+1]; auxWeights[right+center-j]=weights[j+1]; }
    for( int k = left; k <= right; k++ ) {
        if(auxWeights[j]>auxWeights[i]) { literals[k]=auxLiterals[j]; weights[k]=auxWeights[j--]; }
        else { literals[k]=auxLiterals[i]; weights[k]=auxWeights[i++]; }
    }

    delete [] auxWeights; delete [] auxLiterals;
}

void mergesort(int left,int right,vector<Literal>& literals,vector<uint64_t>& weights )
{
    if( left < right ) {
        int center = (left+right)/2;
        mergesort(left,center,literals,weights);
        mergesort(center+1,right,literals,weights);
        merge(left,center,right,literals,weights);
    }
}

bool
WaspFacade::addPseudoBooleanConstraint(
    vector<Literal>& lits,
    vector<uint64_t>& weights,
    uint64_t bound)
{
    if(solver.conflictDetected() || !ok_) return false;
    solver.unrollToZero();
    if(lits.size() != weights.size())
        WaspErrorMessage::errorGeneric("The size of literals must be equal to the size of weights in pseudoBoolean constraints.");

    if(bound == 0) return true;
    uint64_t differentWeights = UINT64_MAX;
    uint64_t sumOfWeights = 0;
    unsigned int j = 0;
    for(unsigned int i = 0; i < lits.size(); i++) {
        lits[i]=lits[j];    weights[i]=weights[j];
        addVariables(lits[i].getVariable());
        if(solver.hasBeenEliminated(lits[i].getVariable())) WaspErrorMessage::errorGeneric("Trying to add a deleted variable to aggregate.");
        if(solver.isFalse(lits[i]) || weights[i] == 0) continue;
        if(solver.isTrue(lits[i])) {
            if(bound <= weights[i]) return true;
            bound -= weights[i];
            continue;
        }

        if(weights[i] > bound) { weights[i] = bound; }
        if(differentWeights == UINT64_MAX)
            differentWeights = weights[i];
        else if(differentWeights != weights[i])
            differentWeights = UINT64_MAX-1;
        sumOfWeights += weights[i];
        j++;
    }
    lits.resize(j);    weights.resize(j);
    if(sumOfWeights < bound) { ok_ = false; return false; }
    if(differentWeights < UINT64_MAX-1 && differentWeights >= bound) { return addClause(lits); }

    mergesort(0, lits.size()-1, lits, weights);

    if(runtime_) solver.addVariableRuntime();
    else solver.addVariable();
    Var aggrId = solver.numberOfVariables();
    solver.setFrozen( aggrId );
    Aggregate* aggregate = new Aggregate();
    Literal aggregateLiteral = solver.getLiteral( aggrId );
    aggregate->addLiteral(aggregateLiteral.getOppositeLiteral(), 0);
    #ifndef NDEBUG
    uint64_t previousWeight = UINT64_MAX;
    #endif
    for( unsigned int i = 0; i < lits.size(); i++ ) {
        assert(lits[i].getVariable() <= solver.numberOfVariables());
        assert(solver.isUndefined(lits[i].getVariable()));
        assert(!solver.hasBeenEliminated(lits[i].getVariable()));
        aggregate->addLiteral( lits[i], weights[i] );
        solver.setFrozen( lits[i].getVariable() );
        assert_msg( previousWeight >= weights[i], "Literals must be sorted in increasing order" );
        assert( previousWeight = weights[i] );
    }
    assert( aggregate->size() >= 1 );
    bool res = solver.addClauseRuntime(aggregateLiteral);
    if(!res) { ok_ = false; return false; }

    if( !aggregate->updateBound( solver, bound ) ) { delete aggregate; ok_ = false; return false; }

    solver.attachAggregate( *aggregate );
    solver.addAggregate( aggregate );

    assert( solver.isTrue( aggregateLiteral ) );
    aggregate->onLiteralFalse( solver, aggregateLiteral.getOppositeLiteral(), 1 );

    if( solver.conflictDetected() ) { ok_ = false; return false; }
    return ok_;
}

unsigned int
WaspFacade::solve(const vector<Literal>& assumptions, vector<Literal>& conflict)
{
    if(!ok_) { return INCOHERENT; }
    nbCalls++;
    //First call
    if(!runtime_) {
        runtime_ = true;
        if(disableVE_) solver.disableVariableElimination();
        if(!solver.preprocessing()) { ok_ = false; return INCOHERENT; }
        solver.turnOffSimplifications();
        solver.setComputeUnsatCores(true);
        statistics(&solver, startSolving());
        solver.onStartingSolver();
    }
    conflict.clear();
    solver.unrollToZero();
    vector<Literal> assumptions_;
    for(unsigned int i = 0; i < assumptions.size(); i++) {
        if(solver.hasBeenEliminated(assumptions[i].getVariable())) WaspErrorMessage::errorGeneric("Assumption literal has been eliminated. (Assumptions must be frozen).");
        assumptions_.push_back(assumptions[i]);
    }

    unsigned int res = solver.solve(assumptions_);
    if( res == INCOHERENT ) {
        assert(solver.getUnsatCore() != NULL);
        const Clause& core = *solver.getUnsatCore();
        for( unsigned int i = 0; i < core.size(); i++ )
            conflict.push_back(core.getAt(i));
        if(core.size() == 0) ok_ = false;
        solver.unrollToZero();
        solver.clearConflictStatus();
    }
    return res;
}
<|endoftext|>


<commit_before>/*
 * author: Max Kellermann <mk@cm4all.com>
 */

#ifndef BENG_ABORT_FLAG_HXX
#define BENG_ABORT_FLAG_HXX

#include "async.hxx"

/**
 * An async_operation implementation which sets a flag.  This can be
 * used by libraries which don't have their own implementation, but
 * need to know whether the operation has been aborted.
 */
class AbortFlag {
    struct async_operation operation;

public:
    bool aborted = false;

    AbortFlag(async_operation_ref &async_ref) {
        operation.Init2<AbortFlag, &AbortFlag::operation, &AbortFlag::Abort>();
        async_ref.Set(operation);
    }

private:
    void Abort() {
        assert(!aborted);

        aborted = true;
    }
};

#endif
<commit_msg>abort_flag: migrate to class Cancellable<commit_after>/*
 * author: Max Kellermann <mk@cm4all.com>
 */

#ifndef BENG_ABORT_FLAG_HXX
#define BENG_ABORT_FLAG_HXX

#include "async.hxx"

/**
 * An async_operation implementation which sets a flag.  This can be
 * used by libraries which don't have their own implementation, but
 * need to know whether the operation has been aborted.
 */
class AbortFlag final : Cancellable {
public:
    bool aborted = false;

    AbortFlag(async_operation_ref &async_ref) {
        async_ref = *this;
    }

private:
    /* virtual methods from class Cancellable */
    void Cancel() override {
        assert(!aborted);

        aborted = true;
    }
};

#endif
<|endoftext|>


<commit_before>#include "bufferAgent.h"

using boost::shared_ptr;
using boost::thread;
using boost::bind;

using std::string;

namespace veil {
namespace helpers {

BufferAgent::BufferAgent(write_fun w, read_fun r)
  : m_agentActive(false),
    doWrite(w),
    doRead(r)
{
    agentStart();
}
BufferAgent::~BufferAgent()
{
    agentStop();
}

int BufferAgent::onOpen(std::string path, ffi_type ffi)
{
    unique_lock guard(m_loopMutex);
    m_cacheMap.erase(ffi->fh);

    buffer_ptr lCache(new LockableCache());
    lCache->fileName = path;
    lCache->buffer = newFileCache();
    lCache->ffi = *ffi;

    m_cacheMap[ffi->fh] = lCache;

    return 0;
}

int BufferAgent::onWrite(std::string path, const std::string &buf, size_t size, off_t offset, ffi_type ffi)
{
    unique_lock guard(m_loopMutex);
        buffer_ptr wrapper = m_cacheMap[ffi->fh];
    guard.unlock();

    {
        if(wrapper->buffer->byteSize() > 1024 * 1024 * 64) {
            if(int fRet = onFlush(path, ffi)) {
                return fRet;
            }
        }

        if(wrapper->buffer->byteSize() > 1024 * 1024 * 64) {
            return doWrite(path, buf, size, offset, ffi);
        }

        wrapper->buffer->writeData(offset, buf);
    }

    unique_lock buffGuard(wrapper->mutex);
    guard.lock();
    if(!wrapper->opPending)
    {
        wrapper->opPending = true;
        m_jobQueue.push_back(ffi->fh);
        m_loopCond.notify_one();
    }

    return size;
}

int BufferAgent::onRead(std::string path, std::string &buf, size_t size, off_t offset, ffi_type ffi)
{
    boost::unique_lock<boost::recursive_mutex> guard(m_loopMutex);
    return EOPNOTSUPP;
}

int BufferAgent::onFlush(std::string path, ffi_type ffi)
{
    unique_lock guard(m_loopMutex);
        buffer_ptr wrapper = m_cacheMap[ffi->fh];
    guard.unlock();

    unique_lock sendGuard(wrapper->sendMutex);
    unique_lock buff_guard(wrapper->mutex);

    while(wrapper->buffer->blockCount() > 0)
    {
        block_ptr block = wrapper->buffer->removeOldestBlock();
        int res = doWrite(wrapper->fileName, block->data, block->data.size(), block->offset, &wrapper->ffi);
        if(res < 0)
        {
            while(wrapper->buffer->blockCount() > 0)
            {
                (void) wrapper->buffer->removeOldestBlock();
            }
            return res;
        }
    }

    guard.lock();
    m_jobQueue.remove(ffi->fh);

    return 0;
}

int BufferAgent::onRelease(std::string path, ffi_type ffi)
{
    boost::unique_lock<boost::recursive_mutex> guard(m_loopMutex);
    m_cacheMap.erase(ffi->fh);
    m_jobQueue.remove(ffi->fh);

    return 0;
}

void BufferAgent::agentStart(int worker_count)
{
    m_workers.clear();
    m_agentActive = true;

    while(worker_count--)
    {
        m_workers.push_back(shared_ptr<thread>(new thread(bind(&BufferAgent::workerLoop, this))));
    }
}

void BufferAgent::agentStop()
{
    m_agentActive = false;
    m_loopCond.notify_all();
    while(m_workers.size() > 0)
    {
        m_workers.back()->join();
        m_workers.pop_back();
    }
}

void BufferAgent::workerLoop()
{
    unique_lock guard(m_loopMutex);
    while(m_agentActive)
    {
        while(m_jobQueue.empty() && m_agentActive)
            m_loopCond.wait(guard);

        if(!m_agentActive)
            return;

        fd_type file = m_jobQueue.front();
        buffer_ptr wrapper = m_cacheMap[file];
        m_jobQueue.pop_front();
        m_loopCond.notify_one();

        if(!wrapper)
            continue;

        guard.unlock();

        {
            unique_lock sendGuard(wrapper->sendMutex);

            block_ptr block;
            {
                unique_lock buff_guard(wrapper->mutex);
                block = wrapper->buffer->removeOldestBlock();
            }

            if(block)
            {
                //int res = doWrite(wrapper->fileName, block->data, block->data.size(), block->offset, &wrapper->ffi);

                wrapper->cond.notify_all();
            }

            {
                unique_lock buff_guard(wrapper->mutex);
                guard.lock();
                if(wrapper->buffer->blockCount() > 0)
                {
                    m_jobQueue.push_back(file);
                }
                else
                {
                    wrapper->opPending = false;
                }
            }
        }

        wrapper->cond.notify_all();
    }
}

boost::shared_ptr<FileCache> BufferAgent::newFileCache()
{
    return boost::shared_ptr<FileCache>(new FileCache(1024 * 1024));
}

} // namespace helpers
} // namespace veil

<commit_msg>VFS-292: improve write speed<commit_after>#include "bufferAgent.h"

using boost::shared_ptr;
using boost::thread;
using boost::bind;

using std::string;

namespace veil {
namespace helpers {

BufferAgent::BufferAgent(write_fun w, read_fun r)
  : m_agentActive(false),
    doWrite(w),
    doRead(r)
{
    agentStart();
}
BufferAgent::~BufferAgent()
{
    agentStop();
}

int BufferAgent::onOpen(std::string path, ffi_type ffi)
{
    unique_lock guard(m_loopMutex);
    m_cacheMap.erase(ffi->fh);

    buffer_ptr lCache(new LockableCache());
    lCache->fileName = path;
    lCache->buffer = newFileCache();
    lCache->ffi = *ffi;

    m_cacheMap[ffi->fh] = lCache;

    return 0;
}

int BufferAgent::onWrite(std::string path, const std::string &buf, size_t size, off_t offset, ffi_type ffi)
{
    unique_lock guard(m_loopMutex);
        buffer_ptr wrapper = m_cacheMap[ffi->fh];
    guard.unlock();

    {
        if(wrapper->buffer->byteSize() > 1024 * 1024 * 64) {
            if(int fRet = onFlush(path, ffi)) {
                return fRet;
            }
        }

        if(wrapper->buffer->byteSize() > 1024 * 1024 * 64) {
            return doWrite(path, buf, size, offset, ffi);
        }

        wrapper->buffer->writeData(offset, buf);
    }

    unique_lock buffGuard(wrapper->mutex);
    guard.lock();
    if(!wrapper->opPending)
    {
        wrapper->opPending = true;
        m_jobQueue.push_back(ffi->fh);
        m_loopCond.notify_one();
    }

    return size;
}

int BufferAgent::onRead(std::string path, std::string &buf, size_t size, off_t offset, ffi_type ffi)
{
    boost::unique_lock<boost::recursive_mutex> guard(m_loopMutex);
    return EOPNOTSUPP;
}

int BufferAgent::onFlush(std::string path, ffi_type ffi)
{
    unique_lock guard(m_loopMutex);
        buffer_ptr wrapper = m_cacheMap[ffi->fh];
    guard.unlock();

    unique_lock sendGuard(wrapper->sendMutex);
    unique_lock buff_guard(wrapper->mutex);

    while(wrapper->buffer->blockCount() > 0)
    {
        block_ptr block = wrapper->buffer->removeOldestBlock();
        int res = doWrite(wrapper->fileName, block->data, block->data.size(), block->offset, &wrapper->ffi);
        if(res < 0)
        {
            while(wrapper->buffer->blockCount() > 0)
            {
                (void) wrapper->buffer->removeOldestBlock();
            }
            return res;
        }
    }

    guard.lock();
    m_jobQueue.remove(ffi->fh);

    return 0;
}

int BufferAgent::onRelease(std::string path, ffi_type ffi)
{
    boost::unique_lock<boost::recursive_mutex> guard(m_loopMutex);
    m_cacheMap.erase(ffi->fh);
    m_jobQueue.remove(ffi->fh);

    return 0;
}

void BufferAgent::agentStart(int worker_count)
{
    m_workers.clear();
    m_agentActive = true;

    while(worker_count--)
    {
        m_workers.push_back(shared_ptr<thread>(new thread(bind(&BufferAgent::workerLoop, this))));
    }
}

void BufferAgent::agentStop()
{
    m_agentActive = false;
    m_loopCond.notify_all();
    while(m_workers.size() > 0)
    {
        m_workers.back()->join();
        m_workers.pop_back();
    }
}

void BufferAgent::workerLoop()
{
    unique_lock guard(m_loopMutex);
    while(m_agentActive)
    {
        while(m_jobQueue.empty() && m_agentActive)
            m_loopCond.wait(guard);

        if(!m_agentActive)
            return;

        fd_type file = m_jobQueue.front();
        buffer_ptr wrapper = m_cacheMap[file];
        m_jobQueue.pop_front();
        m_loopCond.notify_one();

        if(!wrapper)
            continue;

        guard.unlock();

        {
            unique_lock sendGuard(wrapper->sendMutex);

            block_ptr block;
            {
                unique_lock buff_guard(wrapper->mutex);
                block = wrapper->buffer->removeOldestBlock();
            }

            if(block)
            {
                int res = doWrite(wrapper->fileName, block->data, block->data.size(), block->offset, &wrapper->ffi);

                wrapper->cond.notify_all();
            }

            {
                unique_lock buff_guard(wrapper->mutex);
                guard.lock();
                if(wrapper->buffer->blockCount() > 0)
                {
                    m_jobQueue.push_back(file);
                }
                else
                {
                    wrapper->opPending = false;
                }
            }
        }

        wrapper->cond.notify_all();
    }
}

boost::shared_ptr<FileCache> BufferAgent::newFileCache()
{
    return boost::shared_ptr<FileCache>(new FileCache(1024 * 1024));
}

} // namespace helpers
} // namespace veil

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013, Roland Bock
 * 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.
 */

#include <iostream>
#include <sqlpp11/exception.h>
#include <sqlpp11/sqlite3/connection.h>
#include "detail/prepared_statement_handle.h"
#include "detail/connection_handle.h"

namespace sqlpp
{
	namespace sqlite3
	{
		namespace
		{
			detail::prepared_statement_handle_t prepare_statement(detail::connection_handle& handle, const std::string& statement)
			{
				if (handle.config->debug)
					std::cerr << "Sqlite3 debug: Preparing: '" << statement << "'" << std::endl;

				detail::prepared_statement_handle_t result(nullptr, handle.config->debug);

				auto rc = sqlite3_prepare_v2(
						handle.sqlite,
						statement.c_str(),
						statement.size(),
						&result.sqlite_statement,
						nullptr);

				if (rc != SQLITE_OK)
        {
					throw sqlpp::exception("Sqlite3 error: Could not prepare statement: " + std::string(sqlite3_errmsg(handle.sqlite)) + " (statement was >>" + statement + "<<\n");
        }

				return result;
			}

			void execute_statement(detail::connection_handle& handle, detail::prepared_statement_handle_t& prepared)
			{
				auto rc = sqlite3_step(prepared.sqlite_statement);
				switch(rc)
				{
				case SQLITE_OK:
				case SQLITE_DONE:
					return;
				default:
					std::cerr << "Sqlite3 debug: sqlite3_step return code: " << rc << std::endl;
					throw sqlpp::exception("Sqlite3 error: Could not execute statement: " + std::string(sqlite3_errmsg(handle.sqlite)));
				}
			}
		}

		connection::connection(const std::shared_ptr<connection_config>& config):
			_handle(new detail::connection_handle(config))
		{
		}

		connection::~connection()
		{
		}

		bind_result_t connection::select_impl(const std::string& statement)
		{
			std::unique_ptr<detail::prepared_statement_handle_t> prepared(new detail::prepared_statement_handle_t(prepare_statement(*_handle, statement)));
			if (!prepared)
			{
				throw sqlpp::exception("Sqlite3 error: Could not store result set");
			}

			return {std::move(prepared)};
		}

		bind_result_t connection::run_prepared_select_impl(prepared_statement_t& prepared_statement)
		{
			return { prepared_statement._handle };
		}

		size_t connection::insert_impl(const std::string& statement)
		{
			auto prepared = prepare_statement(*_handle, statement);
			execute_statement(*_handle, prepared);

			return sqlite3_last_insert_rowid(_handle->sqlite);
		}

		prepared_statement_t connection::prepare_impl(const std::string& statement)
		{
			return { std::unique_ptr<detail::prepared_statement_handle_t>(new detail::prepared_statement_handle_t(prepare_statement(*_handle, statement))) };
		}

		size_t connection::run_prepared_insert_impl(prepared_statement_t& prepared_statement)
		{
			execute_statement(*_handle, *prepared_statement._handle.get());

			return sqlite3_last_insert_rowid(_handle->sqlite);
		}

		void connection::execute(const std::string& statement)
		{
			auto prepared = prepare_statement(*_handle, statement);
			execute_statement(*_handle, prepared);
		}

		size_t connection::update_impl(const std::string& statement)
		{
			auto prepared = prepare_statement(*_handle, statement);
			execute_statement(*_handle, prepared);
			return sqlite3_changes(_handle->sqlite);
		}

		size_t connection::run_prepared_update_impl(prepared_statement_t& prepared_statement)
		{
			execute_statement(*_handle, *prepared_statement._handle.get());

			return sqlite3_changes(_handle->sqlite);
		}

		size_t connection::remove_impl(const std::string& statement)
		{
			auto prepared = prepare_statement(*_handle, statement);
			execute_statement(*_handle, prepared);
			return sqlite3_changes(_handle->sqlite);
		}

		size_t connection::run_prepared_remove_impl(prepared_statement_t& prepared_statement)
		{
			execute_statement(*_handle, *prepared_statement._handle.get());

			return sqlite3_changes(_handle->sqlite);
		}

		std::string connection::escape(const std::string& s) const
		{
			std::string t;
			t.reserve(s.size());

			for (const char c : s)
			{
				if (c == '\'')
					t.push_back(c);
				t.push_back(c);
			}

			return t;
		}

		void connection::start_transaction()
		{
			if (_transaction_active)
			{
				throw sqlpp::exception("Sqlite3 error: Cannot have more than one open transaction per connection");
			}
			auto prepared = prepare_statement(*_handle, "BEGIN");
			execute_statement(*_handle, prepared);
			_transaction_active = true;
		}

		void connection::commit_transaction()
		{
			if (not _transaction_active)
			{
				throw sqlpp::exception("Sqlite3 error: Cannot commit a finished or failed transaction");
			}
			_transaction_active = false;
			auto prepared = prepare_statement(*_handle, "COMMIT");
			execute_statement(*_handle, prepared);
		}

		void connection::rollback_transaction(bool report)
		{
			if (not _transaction_active)
			{
				throw sqlpp::exception("Sqlite3 error: Cannot rollback a finished or failed transaction");
			}
			if (report)
			{
				std::cerr << "Sqlite3 warning: Rolling back unfinished transaction" << std::endl;
			}
			_transaction_active = false;
			auto prepared = prepare_statement(*_handle, "ROLLBACK");
			execute_statement(*_handle, prepared);
		}

		void connection::report_rollback_failure(const std::string message) noexcept
		{
			std::cerr << "Sqlite3 message:" << message << std::endl;
		}
	}
}

<commit_msg>Allow ROW results for execute statements<commit_after>/*
 * Copyright (c) 2013, Roland Bock
 * 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.
 */

#include <iostream>
#include <sqlpp11/exception.h>
#include <sqlpp11/sqlite3/connection.h>
#include "detail/prepared_statement_handle.h"
#include "detail/connection_handle.h"

namespace sqlpp
{
	namespace sqlite3
	{
		namespace
		{
			detail::prepared_statement_handle_t prepare_statement(detail::connection_handle& handle, const std::string& statement)
			{
				if (handle.config->debug)
					std::cerr << "Sqlite3 debug: Preparing: '" << statement << "'" << std::endl;

				detail::prepared_statement_handle_t result(nullptr, handle.config->debug);

				auto rc = sqlite3_prepare_v2(
						handle.sqlite,
						statement.c_str(),
						statement.size(),
						&result.sqlite_statement,
						nullptr);

				if (rc != SQLITE_OK)
        {
					throw sqlpp::exception("Sqlite3 error: Could not prepare statement: " + std::string(sqlite3_errmsg(handle.sqlite)) + " (statement was >>" + statement + "<<\n");
        }

				return result;
			}

			void execute_statement(detail::connection_handle& handle, detail::prepared_statement_handle_t& prepared)
			{
				auto rc = sqlite3_step(prepared.sqlite_statement);
				switch(rc)
				{
				case SQLITE_OK:
				case SQLITE_ROW: // might occur if execute is called with a select
				case SQLITE_DONE:
					return;
				default:
					std::cerr << "Sqlite3 debug: sqlite3_step return code: " << rc << std::endl;
					throw sqlpp::exception("Sqlite3 error: Could not execute statement: " + std::string(sqlite3_errmsg(handle.sqlite)));
				}
			}
		}

		connection::connection(const std::shared_ptr<connection_config>& config):
			_handle(new detail::connection_handle(config))
		{
		}

		connection::~connection()
		{
		}

		bind_result_t connection::select_impl(const std::string& statement)
		{
			std::unique_ptr<detail::prepared_statement_handle_t> prepared(new detail::prepared_statement_handle_t(prepare_statement(*_handle, statement)));
			if (!prepared)
			{
				throw sqlpp::exception("Sqlite3 error: Could not store result set");
			}

			return {std::move(prepared)};
		}

		bind_result_t connection::run_prepared_select_impl(prepared_statement_t& prepared_statement)
		{
			return { prepared_statement._handle };
		}

		size_t connection::insert_impl(const std::string& statement)
		{
			auto prepared = prepare_statement(*_handle, statement);
			execute_statement(*_handle, prepared);

			return sqlite3_last_insert_rowid(_handle->sqlite);
		}

		prepared_statement_t connection::prepare_impl(const std::string& statement)
		{
			return { std::unique_ptr<detail::prepared_statement_handle_t>(new detail::prepared_statement_handle_t(prepare_statement(*_handle, statement))) };
		}

		size_t connection::run_prepared_insert_impl(prepared_statement_t& prepared_statement)
		{
			execute_statement(*_handle, *prepared_statement._handle.get());

			return sqlite3_last_insert_rowid(_handle->sqlite);
		}

		void connection::execute(const std::string& statement)
		{
			auto prepared = prepare_statement(*_handle, statement);
			execute_statement(*_handle, prepared);
		}

		size_t connection::update_impl(const std::string& statement)
		{
			auto prepared = prepare_statement(*_handle, statement);
			execute_statement(*_handle, prepared);
			return sqlite3_changes(_handle->sqlite);
		}

		size_t connection::run_prepared_update_impl(prepared_statement_t& prepared_statement)
		{
			execute_statement(*_handle, *prepared_statement._handle.get());

			return sqlite3_changes(_handle->sqlite);
		}

		size_t connection::remove_impl(const std::string& statement)
		{
			auto prepared = prepare_statement(*_handle, statement);
			execute_statement(*_handle, prepared);
			return sqlite3_changes(_handle->sqlite);
		}

		size_t connection::run_prepared_remove_impl(prepared_statement_t& prepared_statement)
		{
			execute_statement(*_handle, *prepared_statement._handle.get());

			return sqlite3_changes(_handle->sqlite);
		}

		std::string connection::escape(const std::string& s) const
		{
			std::string t;
			t.reserve(s.size());

			for (const char c : s)
			{
				if (c == '\'')
					t.push_back(c);
				t.push_back(c);
			}

			return t;
		}

		void connection::start_transaction()
		{
			if (_transaction_active)
			{
				throw sqlpp::exception("Sqlite3 error: Cannot have more than one open transaction per connection");
			}
			auto prepared = prepare_statement(*_handle, "BEGIN");
			execute_statement(*_handle, prepared);
			_transaction_active = true;
		}

		void connection::commit_transaction()
		{
			if (not _transaction_active)
			{
				throw sqlpp::exception("Sqlite3 error: Cannot commit a finished or failed transaction");
			}
			_transaction_active = false;
			auto prepared = prepare_statement(*_handle, "COMMIT");
			execute_statement(*_handle, prepared);
		}

		void connection::rollback_transaction(bool report)
		{
			if (not _transaction_active)
			{
				throw sqlpp::exception("Sqlite3 error: Cannot rollback a finished or failed transaction");
			}
			if (report)
			{
				std::cerr << "Sqlite3 warning: Rolling back unfinished transaction" << std::endl;
			}
			_transaction_active = false;
			auto prepared = prepare_statement(*_handle, "ROLLBACK");
			execute_statement(*_handle, prepared);
		}

		void connection::report_rollback_failure(const std::string message) noexcept
		{
			std::cerr << "Sqlite3 message:" << message << std::endl;
		}
	}
}

<|endoftext|>