<commit_before>#include "messagehub/message.h"

JSONMessage::JSONMessage(const std::string &s): handler(std::shared_ptr<JSONMessage>(this)) {
    parseString(s);
}

JSONMessage::JSONMessage(zmq::message_t &zmsg): handler(std::shared_ptr<JSONMessage>(this)) {
    std::string s = std::string(static_cast<char*>(zmsg.data()), zmsg.size());
    parseString(s);
}

JSONMessage JSONMessage::empty() {
    return JSONMessage("{header: {}, body:{}}");
}

void JSONMessage::parseString(const std::string & s) {
    rapidjson::Document msg;
    msg.Parse(s);
    // Some message requirements
    if (!msg.IsObject())
        throw MessageFormatException("Message JSON is not an object");
    if (!msg.HasMember("header"))
        throw MessageFormatException("Message is missing header", s);
    if (!msg["header"].IsObject())
        throw MessageFormatException("Message's header is not an object", s);
    if (!msg.HasMember("body"))
        throw MessageFormatException("Message is missing an body", s);
    if (!msg["body"].IsObject())
        throw MessageFormatException("Message's body is not an object", s);
    msg.Accept(handler);
}

zmq::message_t JSONMessage::toZmqMsg() const {
    const std::string s = toString();
    zmq::message_t msg(s.size());
    std::copy(s.begin(), s.end(), static_cast<char *>(msg.data()));
    return msg;
}

std::string JSONMessage::toString() const {
    rapidjson::StringBuffer buffer;
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
    writer.StartObject();
    writer.Key("header");
    writer.StartObject();
    for (std::pair<std::string, std::string> const elem : header) {
        writer.Key(elem.first.c_str());
        writer.String(elem.second);
    }
    writer.EndObject();
    writer.Key("body");
    writer.StartObject();
    for (std::pair<std::string, std::string> const elem : body) {
        writer.Key(elem.first.c_str());
        writer.String(elem.second);
    }
    writer.EndObject();
    writer.EndObject();
    std::cout << buffer.GetString() << "\n";
    return buffer.GetString();
}

std::string JSONMessage::getFromHeader(const std::string &key) const {
    if (header.find(key) != header.end())
        return header.at(key);
    else
        return "";
}

std::string JSONMessage::getFromBody(const std::string &key) const {
    if (body.find(key) != body.end())
        return body.at(key);
    else
        return "";
}

void JSONMessage::setHeader(const std::string &key, const std::string &val) {
    if (header.find(key) == header.end()) {
        header.insert(std::make_pair(key, val));
    } else {
        header[key] = val;
    }
}

void JSONMessage::setBody(const std::string &key, const std::string &val) {
    if (body.find(key) == header.end()) {
        body.insert(std::make_pair(key, val));
    } else {
        body[key] = val;
    }
}

int JSONMessage::getPriority() const {
    return 1;
}
 std::string JSONMessage::returnAddr() const {
     return getFromHeader("returnAddr");
 }
<commit_msg>Fix for empty<commit_after>#include "messagehub/message.h"

JSONMessage::JSONMessage(const std::string &s): handler(std::shared_ptr<JSONMessage>(this)) {
    parseString(s);
}

JSONMessage::JSONMessage(zmq::message_t &zmsg): handler(std::shared_ptr<JSONMessage>(this)) {
    std::string s = std::string(static_cast<char*>(zmsg.data()), zmsg.size());
    parseString(s);
}

JSONMessage JSONMessage::empty() {
    return JSONMessage("{\"header\": {}, \"body\":{}}");
}

void JSONMessage::parseString(const std::string & s) {
    rapidjson::Document msg;
    msg.Parse(s);
    // Some message requirements
    if (!msg.IsObject())
        throw MessageFormatException("Message JSON is not an object");
    if (!msg.HasMember("header"))
        throw MessageFormatException("Message is missing header", s);
    if (!msg["header"].IsObject())
        throw MessageFormatException("Message's header is not an object", s);
    if (!msg.HasMember("body"))
        throw MessageFormatException("Message is missing an body", s);
    if (!msg["body"].IsObject())
        throw MessageFormatException("Message's body is not an object", s);
    msg.Accept(handler);
}

zmq::message_t JSONMessage::toZmqMsg() const {
    const std::string s = toString();
    zmq::message_t msg(s.size());
    std::copy(s.begin(), s.end(), static_cast<char *>(msg.data()));
    return msg;
}

std::string JSONMessage::toString() const {
    rapidjson::StringBuffer buffer;
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
    writer.StartObject();
    writer.Key("header");
    writer.StartObject();
    for (std::pair<std::string, std::string> const elem : header) {
        writer.Key(elem.first.c_str());
        writer.String(elem.second);
    }
    writer.EndObject();
    writer.Key("body");
    writer.StartObject();
    for (std::pair<std::string, std::string> const elem : body) {
        writer.Key(elem.first.c_str());
        writer.String(elem.second);
    }
    writer.EndObject();
    writer.EndObject();
    std::cout << buffer.GetString() << "\n";
    return buffer.GetString();
}

std::string JSONMessage::getFromHeader(const std::string &key) const {
    if (header.find(key) != header.end())
        return header.at(key);
    else
        return "";
}

std::string JSONMessage::getFromBody(const std::string &key) const {
    if (body.find(key) != body.end())
        return body.at(key);
    else
        return "";
}

void JSONMessage::setHeader(const std::string &key, const std::string &val) {
    if (header.find(key) == header.end()) {
        header.insert(std::make_pair(key, val));
    } else {
        header[key] = val;
    }
}

void JSONMessage::setBody(const std::string &key, const std::string &val) {
    if (body.find(key) == header.end()) {
        body.insert(std::make_pair(key, val));
    } else {
        body[key] = val;
    }
}

int JSONMessage::getPriority() const {
    return 1;
}
 std::string JSONMessage::returnAddr() const {
     return getFromHeader("returnAddr");
 }
<|endoftext|>


<commit_before>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab

#include "include/types.h"

#include "Ager.h"
#include "os/ObjectStore.h"

#include "config.h"
#include "common/Clock.h"

// ick
#include "ebofs/Ebofs.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#ifdef DARWIN
#include <sys/param.h>
#include <sys/mount.h>
#endif // DARWIN

int myrand()
{
  if (0)
    return rand();
  else {
    static int n = 0;
    srand(n++);
    return rand();
  }
}

pobject_t Ager::age_get_oid() {
  if (!age_free_oids.empty()) {
    pobject_t o = age_free_oids.front();
    age_free_oids.pop_front();
    return o;
  }
  pobject_t last = age_cur_oid;
  ++age_cur_oid.oid.bno;
  return last;
}

ssize_t Ager::age_pick_size() {
  ssize_t max = file_size_distn.sample() * 1024;
  return max/2 + (myrand() % 100) * max/200 + 1;
}

bool start_debug = false;

uint64_t Ager::age_fill(float pc, utime_t until) {
  int max = 1024*1024;
  bufferptr bp(max);
  bp.zero();
  bufferlist bl;
  bl.push_back(bp);
  uint64_t wrote = 0;
  while (1) {
    if (g_clock.now() > until) break;

    struct statfs st;
    store->statfs(&st);
    float free = 1.0 - ((float)(st.f_bfree) / (float)st.f_blocks);
    float avail = 1.0 - ((float)(st.f_bavail) / (float)st.f_blocks);  // to write to
    //float a = (float)(st.f_bfree) / (float)st.f_blocks;
    //dout(10) << "age_fill at " << a << " / " << pc << " .. " << st.f_blocks << " " << st.f_bavail << dendl;
    if (free >= pc) {
      generic_dout(2) << "age_fill at " << free << " / " << avail << " / " << " / " << pc << " stopping" << dendl;
      break;
    }

    // make sure we can write to it..
    if (avail > .98 ||
        avail - free > .02)
      store->sync();

    pobject_t poid = age_get_oid();

    int b = myrand() % 10;
    age_objects[b].push_back(poid);

    ssize_t s = age_pick_size();
    wrote += (s + 4095) / 4096;

    generic_dout(2) << "age_fill at " << free << " / " << avail << " / " << pc << " creating " << hex << poid << dec << " sz " << s << dendl;

    if (false && !g_conf.ebofs_verify && start_debug && wrote > 1000000ULL) {
      /*

      1005700
?
1005000
1005700
      1005710
      1005725ULL
      1005750ULL
      1005800
      1006000

//  99  1000500 ? 1000750 1006000
*/
      g_conf.debug_ebofs = 30;
      g_conf.ebofs_verify = true;
    }

    off_t off = 0;
    while (s) {
      ssize_t t = MIN(s, max);
      bufferlist sbl;
      sbl.substr_of(bl, 0, t);
      ObjectStore::Transaction tr;
      tr.write(0, poid, off, t, sbl);
      store->apply_transaction(tr);
      off += t;
      s -= t;
    }
    poid.oid.bno++;
  }

  return wrote*4; // KB
}

void Ager::age_empty(float pc) {
  int nper = 20;
  int n = nper;

  //g_conf.ebofs_verify = true;

  while (1) {
    struct statfs st;
    store->statfs(&st);
    float free = 1.0 - ((float)(st.f_bfree) / (float)st.f_blocks);
    float avail = 1.0 - ((float)(st.f_bavail) / (float)st.f_blocks);  // to write to
    generic_dout(2) << "age_empty at " << free << " / " << avail << " / " << pc << dendl;//" stopping" << dendl;
    if (free <= pc) {
      generic_dout(2) << "age_empty at " << free << " / " << avail << " / " << pc << " stopping" << dendl;
      break;
    }

    int b = myrand() % 10;
    n--;
    if (n == 0 || age_objects[b].empty()) {
      generic_dout(2) << "age_empty sync" << dendl;
      //sync();
      //sync();
      n = nper;
      continue;
    }
    pobject_t poid = age_objects[b].front();
    age_objects[b].pop_front();

    generic_dout(2) << "age_empty at " << free << " / " << avail << " / " << pc << " removing " << hex << poid << dec << dendl;

    ObjectStore::Transaction t;
    t.remove(0, poid);
    store->apply_transaction(t);
    age_free_oids.push_back(poid);
  }

  g_conf.ebofs_verify = false;
}

void pfrag(uint64_t written, ObjectStore::FragmentationStat &st)
{
  cout << "#gb wr\ttotal\tn x\tavg x\tavg per\tavg j\tfree\tn fr\tavg fr\tnum<2\tsum<2\tnum<4\tsum<4\t..."
       << std::endl;
  cout << written
       << "\t" << st.total
       << "\t" << st.num_extent
       << "\t" << st.avg_extent
       << "\t" << st.avg_extent_per_object
       << "\t" << st.avg_extent_jump
       << "\t" << st.total_free
       << "\t" << st.num_free_extent
       << "\t" << st.avg_free_extent;

  int n = st.num_extent;
  for (uint64_t i=1; i <= 30; i += 1) {
    cout << "\t" << st.extent_dist[i];
    cout << "\t" << st.extent_dist_sum[i];
    //cout << "\ta " << (st.extent_dist[i] ? (st.extent_dist_sum[i] / st.extent_dist[i]):0);
    n -= st.extent_dist[i];
    if (n == 0) break;
  }
  cout << std::endl;
}

void Ager::age(int time,
               float high_water,    // fill to this %
               float low_water,     // then empty to this %
               int count,         // this many times
               float final_water,   // and end here ( <= low_water)
               int fake_size_mb) {

  store->_fake_writes(true);
  srand(0);

  utime_t start = g_clock.now();
  utime_t until = start;
  until.sec_ref() += time;

  int elapsed = 0;
  int freelist_inc = 60;
  utime_t nextfl = start;
  nextfl.sec_ref() += freelist_inc;

  while (age_objects.size() < 10) age_objects.push_back( list<pobject_t>() );

  if (fake_size_mb) {
    int fake_bl = fake_size_mb * 256;
    struct statfs st;
    store->statfs(&st);
    float f = (float)fake_bl / (float)st.f_blocks;
    high_water = (float)high_water * f;
    low_water = (float)low_water * f;
    final_water = (float)final_water * f;
    generic_dout(2) << "fake " << fake_bl << " / " << st.f_blocks << " is " << f << ", high " << high_water << " low " << low_water << " final " << final_water << dendl;
  }

  // init size distn (once)
  if (!did_distn) {
    did_distn = true;
    age_cur_oid = pobject_t(0, 0, object_t(0,1));
    file_size_distn.add(1, 19.0758125+0.65434375);
    file_size_distn.add(512, 35.6566);
    file_size_distn.add(1024, 27.7271875);
    file_size_distn.add(2*1024, 16.63503125);
    //file_size_distn.add(4*1024, 106.82384375);
    //file_size_distn.add(8*1024, 81.493375);
    //file_size_distn.add(16*1024, 14.13553125);
    //file_size_distn.add(32*1024, 2.176);
    //file_size_distn.add(256*1024, 0.655938);
    //file_size_distn.add(512*1024, 0.1480625);
    //file_size_distn.add(1*1024*1024, 0.020125); // actually 2, but 32bit
    file_size_distn.normalize();
  }

  // clear
  for (int i=0; i<10; i++)
    age_objects[i].clear();

  ObjectStore::FragmentationStat st;

  uint64_t wrote = 0;

  for (int c=1; c<=count; c++) {
    if (g_clock.now() > until) break;

    //if (c == 7) start_debug = true;

    generic_dout(1) << "#age " << c << "/" << count << " filling to " << high_water << dendl;
    uint64_t w = age_fill(high_water, until);
    //dout(1) << "age wrote " << w << dendl;
    wrote += w;
    //store->sync();
    //store->_get_frag_stat(st);
    //pfrag(st);

    if (c == count) {
      generic_dout(1) << "#age final empty to " << final_water << dendl;
      age_empty(final_water);
    } else {
      generic_dout(1) << "#age " << c << "/" << count << " emptying to " << low_water << dendl;
      age_empty(low_water);
    }
    //store->sync();
    //store->sync();

    // show frag state
    store->_get_frag_stat(st);
    pfrag(wrote / (1024ULL*1024ULL) ,  // GB
          st);

    // dump freelist?
    if (g_clock.now() > nextfl) {
      elapsed += freelist_inc;
      save_freelist(elapsed);
      nextfl.sec_ref() += freelist_inc;
    }
  }

  // dump the freelist
  save_freelist(0);
  exit(0);   // hack

  // ok!
  store->_fake_writes(false);
  store->sync();
  store->sync();
  generic_dout(1) << "age finished" << dendl;
}

void Ager::load_freelist()
{
  generic_dout(1) << "load_freelist" << dendl;

  struct stat st;

  int r = ::stat("ebofs.freelist", &st);
  assert(r == 0);

  bufferptr bp(st.st_size);
  bufferlist bl;
  bl.push_back(bp);
  int fd = ::open("ebofs.freelist", O_RDONLY);
  ::read(fd, bl.c_str(), st.st_size);
  ::close(fd);

  ((Ebofs*)store)->_import_freelist(bl);
  store->sync();
  store->sync();
}

void Ager::save_freelist(int el)
{
  generic_dout(1) << "save_freelist " << el << dendl;
  char s[100];
  sprintf(s, "ebofs.freelist.%d", el);
  bufferlist bl;
  ((Ebofs*)store)->_export_freelist(bl);
  ::unlink(s);
  int fd = ::open(s, O_CREAT|O_WRONLY);
  ::fchmod(fd, 0644);
  ::write(fd, bl.c_str(), bl.length());
  ::close(fd);
}
<commit_msg>osd: fix ager missing open() arg<commit_after>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab

#include "include/types.h"

#include "Ager.h"
#include "os/ObjectStore.h"

#include "config.h"
#include "common/Clock.h"

// ick
#include "ebofs/Ebofs.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#ifdef DARWIN
#include <sys/param.h>
#include <sys/mount.h>
#endif // DARWIN

int myrand()
{
  if (0)
    return rand();
  else {
    static int n = 0;
    srand(n++);
    return rand();
  }
}

pobject_t Ager::age_get_oid() {
  if (!age_free_oids.empty()) {
    pobject_t o = age_free_oids.front();
    age_free_oids.pop_front();
    return o;
  }
  pobject_t last = age_cur_oid;
  ++age_cur_oid.oid.bno;
  return last;
}

ssize_t Ager::age_pick_size() {
  ssize_t max = file_size_distn.sample() * 1024;
  return max/2 + (myrand() % 100) * max/200 + 1;
}

bool start_debug = false;

uint64_t Ager::age_fill(float pc, utime_t until) {
  int max = 1024*1024;
  bufferptr bp(max);
  bp.zero();
  bufferlist bl;
  bl.push_back(bp);
  uint64_t wrote = 0;
  while (1) {
    if (g_clock.now() > until) break;

    struct statfs st;
    store->statfs(&st);
    float free = 1.0 - ((float)(st.f_bfree) / (float)st.f_blocks);
    float avail = 1.0 - ((float)(st.f_bavail) / (float)st.f_blocks);  // to write to
    //float a = (float)(st.f_bfree) / (float)st.f_blocks;
    //dout(10) << "age_fill at " << a << " / " << pc << " .. " << st.f_blocks << " " << st.f_bavail << dendl;
    if (free >= pc) {
      generic_dout(2) << "age_fill at " << free << " / " << avail << " / " << " / " << pc << " stopping" << dendl;
      break;
    }

    // make sure we can write to it..
    if (avail > .98 ||
        avail - free > .02)
      store->sync();

    pobject_t poid = age_get_oid();

    int b = myrand() % 10;
    age_objects[b].push_back(poid);

    ssize_t s = age_pick_size();
    wrote += (s + 4095) / 4096;

    generic_dout(2) << "age_fill at " << free << " / " << avail << " / " << pc << " creating " << hex << poid << dec << " sz " << s << dendl;

    if (false && !g_conf.ebofs_verify && start_debug && wrote > 1000000ULL) {
      /*

      1005700
?
1005000
1005700
      1005710
      1005725ULL
      1005750ULL
      1005800
      1006000

//  99  1000500 ? 1000750 1006000
*/
      g_conf.debug_ebofs = 30;
      g_conf.ebofs_verify = true;
    }

    off_t off = 0;
    while (s) {
      ssize_t t = MIN(s, max);
      bufferlist sbl;
      sbl.substr_of(bl, 0, t);
      ObjectStore::Transaction tr;
      tr.write(0, poid, off, t, sbl);
      store->apply_transaction(tr);
      off += t;
      s -= t;
    }
    poid.oid.bno++;
  }

  return wrote*4; // KB
}

void Ager::age_empty(float pc) {
  int nper = 20;
  int n = nper;

  //g_conf.ebofs_verify = true;

  while (1) {
    struct statfs st;
    store->statfs(&st);
    float free = 1.0 - ((float)(st.f_bfree) / (float)st.f_blocks);
    float avail = 1.0 - ((float)(st.f_bavail) / (float)st.f_blocks);  // to write to
    generic_dout(2) << "age_empty at " << free << " / " << avail << " / " << pc << dendl;//" stopping" << dendl;
    if (free <= pc) {
      generic_dout(2) << "age_empty at " << free << " / " << avail << " / " << pc << " stopping" << dendl;
      break;
    }

    int b = myrand() % 10;
    n--;
    if (n == 0 || age_objects[b].empty()) {
      generic_dout(2) << "age_empty sync" << dendl;
      //sync();
      //sync();
      n = nper;
      continue;
    }
    pobject_t poid = age_objects[b].front();
    age_objects[b].pop_front();

    generic_dout(2) << "age_empty at " << free << " / " << avail << " / " << pc << " removing " << hex << poid << dec << dendl;

    ObjectStore::Transaction t;
    t.remove(0, poid);
    store->apply_transaction(t);
    age_free_oids.push_back(poid);
  }

  g_conf.ebofs_verify = false;
}

void pfrag(uint64_t written, ObjectStore::FragmentationStat &st)
{
  cout << "#gb wr\ttotal\tn x\tavg x\tavg per\tavg j\tfree\tn fr\tavg fr\tnum<2\tsum<2\tnum<4\tsum<4\t..."
       << std::endl;
  cout << written
       << "\t" << st.total
       << "\t" << st.num_extent
       << "\t" << st.avg_extent
       << "\t" << st.avg_extent_per_object
       << "\t" << st.avg_extent_jump
       << "\t" << st.total_free
       << "\t" << st.num_free_extent
       << "\t" << st.avg_free_extent;

  int n = st.num_extent;
  for (uint64_t i=1; i <= 30; i += 1) {
    cout << "\t" << st.extent_dist[i];
    cout << "\t" << st.extent_dist_sum[i];
    //cout << "\ta " << (st.extent_dist[i] ? (st.extent_dist_sum[i] / st.extent_dist[i]):0);
    n -= st.extent_dist[i];
    if (n == 0) break;
  }
  cout << std::endl;
}

void Ager::age(int time,
               float high_water,    // fill to this %
               float low_water,     // then empty to this %
               int count,         // this many times
               float final_water,   // and end here ( <= low_water)
               int fake_size_mb) {

  store->_fake_writes(true);
  srand(0);

  utime_t start = g_clock.now();
  utime_t until = start;
  until.sec_ref() += time;

  int elapsed = 0;
  int freelist_inc = 60;
  utime_t nextfl = start;
  nextfl.sec_ref() += freelist_inc;

  while (age_objects.size() < 10) age_objects.push_back( list<pobject_t>() );

  if (fake_size_mb) {
    int fake_bl = fake_size_mb * 256;
    struct statfs st;
    store->statfs(&st);
    float f = (float)fake_bl / (float)st.f_blocks;
    high_water = (float)high_water * f;
    low_water = (float)low_water * f;
    final_water = (float)final_water * f;
    generic_dout(2) << "fake " << fake_bl << " / " << st.f_blocks << " is " << f << ", high " << high_water << " low " << low_water << " final " << final_water << dendl;
  }

  // init size distn (once)
  if (!did_distn) {
    did_distn = true;
    age_cur_oid = pobject_t(0, 0, object_t(0,1));
    file_size_distn.add(1, 19.0758125+0.65434375);
    file_size_distn.add(512, 35.6566);
    file_size_distn.add(1024, 27.7271875);
    file_size_distn.add(2*1024, 16.63503125);
    //file_size_distn.add(4*1024, 106.82384375);
    //file_size_distn.add(8*1024, 81.493375);
    //file_size_distn.add(16*1024, 14.13553125);
    //file_size_distn.add(32*1024, 2.176);
    //file_size_distn.add(256*1024, 0.655938);
    //file_size_distn.add(512*1024, 0.1480625);
    //file_size_distn.add(1*1024*1024, 0.020125); // actually 2, but 32bit
    file_size_distn.normalize();
  }

  // clear
  for (int i=0; i<10; i++)
    age_objects[i].clear();

  ObjectStore::FragmentationStat st;

  uint64_t wrote = 0;

  for (int c=1; c<=count; c++) {
    if (g_clock.now() > until) break;

    //if (c == 7) start_debug = true;

    generic_dout(1) << "#age " << c << "/" << count << " filling to " << high_water << dendl;
    uint64_t w = age_fill(high_water, until);
    //dout(1) << "age wrote " << w << dendl;
    wrote += w;
    //store->sync();
    //store->_get_frag_stat(st);
    //pfrag(st);

    if (c == count) {
      generic_dout(1) << "#age final empty to " << final_water << dendl;
      age_empty(final_water);
    } else {
      generic_dout(1) << "#age " << c << "/" << count << " emptying to " << low_water << dendl;
      age_empty(low_water);
    }
    //store->sync();
    //store->sync();

    // show frag state
    store->_get_frag_stat(st);
    pfrag(wrote / (1024ULL*1024ULL) ,  // GB
          st);

    // dump freelist?
    if (g_clock.now() > nextfl) {
      elapsed += freelist_inc;
      save_freelist(elapsed);
      nextfl.sec_ref() += freelist_inc;
    }
  }

  // dump the freelist
  save_freelist(0);
  exit(0);   // hack

  // ok!
  store->_fake_writes(false);
  store->sync();
  store->sync();
  generic_dout(1) << "age finished" << dendl;
}

void Ager::load_freelist()
{
  generic_dout(1) << "load_freelist" << dendl;

  struct stat st;

  int r = ::stat("ebofs.freelist", &st);
  assert(r == 0);

  bufferptr bp(st.st_size);
  bufferlist bl;
  bl.push_back(bp);
  int fd = ::open("ebofs.freelist", O_RDONLY);
  ::read(fd, bl.c_str(), st.st_size);
  ::close(fd);

  ((Ebofs*)store)->_import_freelist(bl);
  store->sync();
  store->sync();
}

void Ager::save_freelist(int el)
{
  generic_dout(1) << "save_freelist " << el << dendl;
  char s[100];
  sprintf(s, "ebofs.freelist.%d", el);
  bufferlist bl;
  ((Ebofs*)store)->_export_freelist(bl);
  ::unlink(s);
  int fd = ::open(s, O_CREAT|O_WRONLY, 0644);
  ::fchmod(fd, 0644);
  ::write(fd, bl.c_str(), bl.length());
  ::close(fd);
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * 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 "thread.h"

#include <sys/syscall.h>
#include <sys/types.h>

#include "asm_support.h"
#include "macros.h"
#include "thread_list.h"

#if defined(__APPLE__)
#include <architecture/i386/table.h>
#include <i386/user_ldt.h>
#else
#include <asm/ldt.h>
#endif

namespace art {

void Thread::InitCpu() {
#if defined(__APPLE__)
  UNIMPLEMENTED(WARNING);
#else
  static Mutex modify_ldt_lock("modify_ldt lock");
  MutexLock mu(modify_ldt_lock);

  // Read LDT
  CHECK_EQ((size_t)LDT_ENTRY_SIZE, sizeof(uint64_t));
  std::vector<uint64_t> ldt(LDT_ENTRIES);
  size_t ldt_size(sizeof(uint64_t) * ldt.size());
  memset(&ldt[0], 0, ldt_size);
  syscall(__NR_modify_ldt, 0, &ldt[0], ldt_size);
  // Create empty slot to point at current Thread*
  user_desc ldt_entry;
  memset(&ldt_entry, 0, sizeof(ldt_entry));
  ldt_entry.entry_number = -1;
  ldt_entry.base_addr = (unsigned int)this;
  ldt_entry.limit = kPageSize;
  ldt_entry.seg_32bit = 1;
  ldt_entry.contents = MODIFY_LDT_CONTENTS_DATA;
  ldt_entry.read_exec_only = 0;
  ldt_entry.limit_in_pages = 0;
  ldt_entry.seg_not_present = 0;
  ldt_entry.useable = 1;
  for (int i = 0; i < LDT_ENTRIES; i++) {
    if (ldt[i] == 0) {
      ldt_entry.entry_number = i;
      break;
    }
  }
  if (ldt_entry.entry_number >= LDT_ENTRIES) {
    LOG(FATAL) << "Failed to find available LDT slot";
  }
  // Update LDT
  CHECK_EQ(0, syscall(__NR_modify_ldt, 1, &ldt_entry, sizeof(ldt_entry)));
  // Change FS to be new LDT entry
  uint16_t table_indicator = 1 << 2;  // LDT
  uint16_t rpl = 3;  // Requested privilege level
  uint16_t selector = (ldt_entry.entry_number << 3) | table_indicator | rpl;
  // TODO: use our assembler to generate code
  asm volatile("movw %w0, %%fs"
      :    // output
      : "q"(selector)  // input
      :);  // clobber
  // Allow easy indirection back to Thread*
  self_ = this;
  // Sanity check reads from FS goes to this Thread*
  Thread* self_check;
  // TODO: use our assembler to generate code
  CHECK_EQ(THREAD_SELF_OFFSET, OFFSETOF_MEMBER(Thread, self_));
  asm volatile("movl %%fs:(%1), %0"
      : "=r"(self_check)  // output
      : "r"(THREAD_SELF_OFFSET)  // input
      :);  // clobber
  CHECK_EQ(self_check, this);
#endif
}

}  // namespace art
<commit_msg>Support LDT modification on Mac OS.<commit_after>/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * 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 "thread.h"

#include <sys/syscall.h>
#include <sys/types.h>

#include "asm_support.h"
#include "macros.h"
#include "thread_list.h"

#if defined(__APPLE__)
#include <architecture/i386/table.h>
#include <i386/user_ldt.h>
struct descriptor_table_entry_t {
  uint16_t limit0;
  uint16_t base0;
  unsigned base1: 8, type: 4, s: 1, dpl: 2, p: 1;
  unsigned limit: 4, avl: 1, l: 1, d: 1, g: 1, base2: 8;
} __attribute__((packed));
#define MODIFY_LDT_CONTENTS_DATA 0
#else
#include <asm/ldt.h>
#endif

namespace art {

void Thread::InitCpu() {
  static Mutex modify_ldt_lock("modify_ldt lock");
  MutexLock mu(modify_ldt_lock);

  const uintptr_t base = reinterpret_cast<uintptr_t>(this);
  const size_t limit = kPageSize;

  const int contents = MODIFY_LDT_CONTENTS_DATA;
  const int seg_32bit = 1;
  const int read_exec_only = 0;
  const int limit_in_pages = 0;
  const int seg_not_present = 0;
  const int useable = 1;

  int entry_number = -1;

#if defined(__APPLE__)
  descriptor_table_entry_t entry;
  memset(&entry, 0, sizeof(entry));
  entry.limit0 = (limit & 0x0ffff);
  entry.limit  = (limit & 0xf0000) >> 16;
  entry.base0 = (base & 0x0000ffff);
  entry.base1 = (base & 0x00ff0000) >> 16;
  entry.base2 = (base & 0xff000000) >> 24;
  entry.type = ((read_exec_only ^ 1) << 1) | (contents << 2);
  entry.s = 1;
  entry.dpl = 0x3;
  entry.p = seg_not_present ^ 1;
  entry.avl = useable;
  entry.l = 0;
  entry.d = seg_32bit;
  entry.g = limit_in_pages;

  entry_number = i386_set_ldt(LDT_AUTO_ALLOC, (ldt_entry*)(void*)(&entry), 1);
  if (entry_number == -1) {
    PLOG(FATAL) << "i386_set_ldt failed";
  }
#else
  // Read current LDT entries.
  CHECK_EQ((size_t)LDT_ENTRY_SIZE, sizeof(uint64_t));
  std::vector<uint64_t> ldt(LDT_ENTRIES);
  size_t ldt_size(sizeof(uint64_t) * ldt.size());
  memset(&ldt[0], 0, ldt_size);
  // TODO: why doesn't this return LDT_ENTRY_SIZE * LDT_ENTRIES for the main thread?
  syscall(__NR_modify_ldt, 0, &ldt[0], ldt_size);

  // Find the first empty slot.
  for (entry_number = 0; entry_number < LDT_ENTRIES && ldt[entry_number] != 0; ++entry_number) {
  }
  if (entry_number >= LDT_ENTRIES) {
    LOG(FATAL) << "Failed to find a free LDT slot";
  }

  // Update LDT entry.
  user_desc ldt_entry;
  memset(&ldt_entry, 0, sizeof(ldt_entry));
  ldt_entry.entry_number = entry_number;
  ldt_entry.base_addr = base;
  ldt_entry.limit = limit;
  ldt_entry.seg_32bit = seg_32bit;
  ldt_entry.contents = contents;
  ldt_entry.read_exec_only = read_exec_only;
  ldt_entry.limit_in_pages = limit_in_pages;
  ldt_entry.seg_not_present = seg_not_present;
  ldt_entry.useable = useable;
  CHECK_EQ(0, syscall(__NR_modify_ldt, 1, &ldt_entry, sizeof(ldt_entry)));
  entry_number = ldt_entry.entry_number;
#endif

  // Change %fs to be new LDT entry.
  uint16_t table_indicator = 1 << 2;  // LDT
  uint16_t rpl = 3;  // Requested privilege level
  uint16_t selector = (entry_number << 3) | table_indicator | rpl;
  // TODO: use our assembler to generate code
  asm volatile("movw %w0, %%fs"
      :    // output
      : "q"(selector)  // input
      :);  // clobber

  // Allow easy indirection back to Thread*.
  self_ = this;

  // Sanity check that reads from %fs point to this Thread*.
  Thread* self_check;
  // TODO: use our assembler to generate code
  CHECK_EQ(THREAD_SELF_OFFSET, OFFSETOF_MEMBER(Thread, self_));
  asm volatile("movl %%fs:(%1), %0"
      : "=r"(self_check)  // output
      : "r"(THREAD_SELF_OFFSET)  // input
      :);  // clobber
  CHECK_EQ(self_check, this);
}

}  // namespace art
<|endoftext|>


<commit_before>#include "DcConfiguration.hpp"

namespace Telegram {

int DcConfiguration::dcCount() const
{
    QVector<quint32> dcs;

    for (const DcOption &opt : dcOptions) {
        const quint32 dcId = opt.id;
        if (dcs.contains(dcId)) {
            continue;
        }
        dcs.append(dcId);
    }
    return dcs.count();
}

DcOption DcConfiguration::getOption(const ConnectionSpec spec) const
{
    DcOption result;

    for (const DcOption &opt : dcOptions) {
        if (opt.id != spec.dcId) {
            continue;
        }
        if (spec.flags & ConnectionSpec::RequestFlag::Ipv4Only) {
            if (opt.flags & DcOption::Ipv6) {
                continue;
            }
        }
        if (spec.flags & ConnectionSpec::RequestFlag::Ipv6Only) {
            if (!(opt.flags & DcOption::Ipv6)) {
                continue;
            }
        }
        if (opt.flags & DcOption::MediaOnly) {
            if (spec.flags & ConnectionSpec::RequestFlag::MediaOnly) {
                // Best match
                return opt;
            }
            continue;
        }
        // The Option meet the requirements, but maybe there is a better one
        result = opt;
    }
    return result;
}

} // Telegram
<commit_msg>DcConfiguration: Return DC Option actually with the requested flags<commit_after>#include "DcConfiguration.hpp"

namespace Telegram {

int DcConfiguration::dcCount() const
{
    QVector<quint32> dcs;

    for (const DcOption &opt : dcOptions) {
        const quint32 dcId = opt.id;
        if (dcs.contains(dcId)) {
            continue;
        }
        dcs.append(dcId);
    }
    return dcs.count();
}

DcOption DcConfiguration::getOption(const ConnectionSpec spec) const
{
    DcOption result;

    for (const DcOption &opt : dcOptions) {
        if (opt.id != spec.dcId) {
            continue;
        }
        if (spec.flags & ConnectionSpec::RequestFlag::Ipv4Only) {
            if (opt.flags & DcOption::Ipv6) {
                continue;
            }
        }
        if (spec.flags & ConnectionSpec::RequestFlag::Ipv6Only) {
            if (!(opt.flags & DcOption::Ipv6)) {
                continue;
            }
        }
        if (opt.flags & DcOption::MediaOnly) {
            if (spec.flags & ConnectionSpec::RequestFlag::MediaOnly) {
                // Best match
                return opt;
            }
            continue;
        }

        // The Option meet the requirements, but maybe there is a better one
        result = opt;
        if (spec.flags & ConnectionSpec::RequestFlag::MediaOnly) {
            result.flags |= DcOption::MediaOnly;
        }
    }
    return result;
}

} // Telegram
<|endoftext|>


<commit_before>//
// Name:     app.cpp
// Purpose:  Example GLUT/vtlib application.
//
// Copyright (c) 2001-2003 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

#ifdef __DARWIN_OSX__
 #import <GLUT/glut.h>
#else
 #include <GL/glut.h>
#endif

#ifdef __FreeBSD__
#  include <ieeefp.h>
#endif

#include "vtlib/vtlib.h"
#include "vtlib/core/Terrain.h"
#include "vtlib/core/TerrainScene.h"
#include "vtlib/core/NavEngines.h"
#include "vtdata/vtLog.h"

void redraw();
void reshape(int w, int h);
void keyboard(unsigned char key, int x, int y);
void mouse(int button, int state, int x, int y);
void motion(int x, int y);

/*
  The GLUT window reshape event
*/
void reshape(int w, int h )
{
	glViewport(0, 0, w, h);
	vtGetScene()->SetWindowSize(w, h);
}

/*
  The GLUT keyboard event
*/
void keyboard(unsigned char key, int x, int y)
{
	if ( key == 27 /* ESC */ || key == 'q' || key == 'Q' )
		exit(0);

	vtGetScene()->OnKey(key, 0);
}

#ifndef GLUT_LEFT_BUTTON
 /* Mouse buttons. */
 #define GLUT_LEFT_BUTTON		0
 #define GLUT_MIDDLE_BUTTON		1
 #define GLUT_RIGHT_BUTTON		2

 /* Mouse button  state. */
 #define GLUT_DOWN			0
 #define GLUT_UP				1
#endif

int last_button_state;

/*
  The GLUT mouse event
*/
void mouse(int button, int state, int x, int y)
{
	// turn GLUT mouse event into a VT mouse event
	vtMouseEvent event;
	event.type = (state == GLUT_DOWN) ? VT_DOWN : VT_UP;

	if (button == GLUT_LEFT_BUTTON)
		event.button = VT_LEFT;
	else if (button == GLUT_MIDDLE_BUTTON)
		event.button = VT_MIDDLE;
	else if (button == GLUT_RIGHT_BUTTON)
		event.button = VT_RIGHT;

	event.flags = 0;
	event.pos.Set(x, y);

	vtGetScene()->OnMouse(event);
}

void motion(int x, int y)
{
	vtMouseEvent event;
	event.type = VT_MOVE;
	event.button = VT_NONE;
	event.flags = 0;
	event.pos.Set(x, y);

	vtGetScene()->OnMouse(event);
}

/*
  The GLUT redraw event
*/
void redraw()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	vtGetScene()->DoUpdate();

	glutPostRedisplay();
	glutSwapBuffers();
}

void InitGLUT()
{
	int   fake_argc = 1;
	char *fake_argv[3];
	fake_argv[0] = "glutSimple";
	fake_argv[1] = "Example Program";
	fake_argv[2] = NULL;

	/*
	Initialise GLUT
	*/
	glutInitWindowPosition(0, 0);
	glutInitWindowSize(800, 600);
	glutInit          (&fake_argc, fake_argv);
	glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
	glutCreateWindow  (fake_argv[1]);
	glutDisplayFunc   (redraw);
	glutReshapeFunc   (reshape);
	glutKeyboardFunc  (keyboard);
	glutMouseFunc     (mouse);
	glutMotionFunc    (motion);
}

//
// Create the 3d scene
//
bool CreateScene()
{
	// Get a handle to the vtScene - one is already created for you
	vtScene *pScene = vtGetScene();
	pScene->Init();

	// Log messages to make troubleshooting easier
	VTSTARTLOG("debug.txt");
	VTLOG("glutSimple\n");

	// Look up the camera
	vtCamera *pCamera = pScene->GetCamera();
	pCamera->SetHither(10);
	pCamera->SetYon(100000);

	// The  terrain scene will contain all the terrains that are created.
	vtTerrainScene *ts = new vtTerrainScene;

	// Set the global data path
	vtStringArray paths;
	paths.push_back(vtString("Data/"));
	ts->SetDataPath(paths);

	// Begin creating the scene, including the sun and sky
	vtGroup *pTopGroup = ts->BeginTerrainScene();

	// Tell the scene graph to point to this terrain scene
	pScene->SetRoot(pTopGroup);

	// Create a new vtTerrain, read its parameters from a file
	vtTerrain *pTerr = new vtTerrain;
	pTerr->SetParamFile("Data/Simple.xml");

	// Add the terrain to the scene, and contruct it
	ts->AppendTerrain(pTerr);
	if (!ts->BuildTerrain(pTerr))
	{
		printf("Terrain creation failed: %s\n",
			(const char *)pTerr->GetLastError());
		return false;
	}
	ts->SetCurrentTerrain(pTerr);

	// Create a navigation engine to move around on the terrain
	// Get flight speed from terrain parameters
	float fSpeed = pTerr->GetParams().GetValueFloat(STR_NAVSPEED);

	vtTerrainFlyer *pFlyer = new vtTerrainFlyer(fSpeed);
	pFlyer->SetTarget(pCamera);
	pFlyer->SetHeightField(pTerr->GetHeightField());
	pScene->AddEngine(pFlyer);

	// Minimum height over terrain is 100 m
	vtHeightConstrain *pConstrain = new vtHeightConstrain(100);
	pConstrain->SetTarget(pCamera);
	pConstrain->SetHeightField(pTerr->GetHeightField());
	pScene->AddEngine(pConstrain);

	return true;
}

/*
  The works.
*/
int main(int, char ** )
{
#ifdef __FreeBSD__
	/*  FreeBSD is more stringent with FP ops by default, and OSG is doing  */
	/*    silly things sqrt(Inf) (computing lengths of MAXFLOAT and NaN     */
	/*    Vec3's).   This turns off FP bug core dumps, ignoring the error   */
	/*    like most platforms do by default.                                */
	fpsetmask(0);
#endif

	printf("Initializing GLUT..\n");
	InitGLUT();

	printf("Creating the terrain..\n");
	CreateScene();

	printf("Running..\n");
	glutMainLoop();

	return 0;
}

<commit_msg>removed extra glClear, added some reference lines<commit_after>//
// Name:     app.cpp
// Purpose:  Example GLUT/vtlib application.
//
// Copyright (c) 2001-2003 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

#ifdef __DARWIN_OSX__
 #import <GLUT/glut.h>
#else
 #include <GL/glut.h>
#endif

#ifdef __FreeBSD__
#  include <ieeefp.h>
#endif

#include "vtlib/vtlib.h"
#include "vtlib/core/Terrain.h"
#include "vtlib/core/TerrainScene.h"
#include "vtlib/core/NavEngines.h"
#include "vtdata/vtLog.h"

void redraw();
void reshape(int w, int h);
void keyboard(unsigned char key, int x, int y);
void mouse(int button, int state, int x, int y);
void motion(int x, int y);

/*
  The GLUT window reshape event
*/
void reshape(int w, int h )
{
	glViewport(0, 0, w, h);
	vtGetScene()->SetWindowSize(w, h);
}

/*
  The GLUT keyboard event
*/
void keyboard(unsigned char key, int x, int y)
{
	if ( key == 27 /* ESC */ || key == 'q' || key == 'Q' )
		exit(0);

	vtGetScene()->OnKey(key, 0);
}

#ifndef GLUT_LEFT_BUTTON
 /* Mouse buttons. */
 #define GLUT_LEFT_BUTTON		0
 #define GLUT_MIDDLE_BUTTON		1
 #define GLUT_RIGHT_BUTTON		2

 /* Mouse button  state. */
 #define GLUT_DOWN			0
 #define GLUT_UP				1
#endif

int last_button_state;

/*
  The GLUT mouse event
*/
void mouse(int button, int state, int x, int y)
{
	// turn GLUT mouse event into a VT mouse event
	vtMouseEvent event;
	event.type = (state == GLUT_DOWN) ? VT_DOWN : VT_UP;

	if (button == GLUT_LEFT_BUTTON)
		event.button = VT_LEFT;
	else if (button == GLUT_MIDDLE_BUTTON)
		event.button = VT_MIDDLE;
	else if (button == GLUT_RIGHT_BUTTON)
		event.button = VT_RIGHT;

	event.flags = 0;
	event.pos.Set(x, y);

	vtGetScene()->OnMouse(event);
}

void motion(int x, int y)
{
	vtMouseEvent event;
	event.type = VT_MOVE;
	event.button = VT_NONE;
	event.flags = 0;
	event.pos.Set(x, y);

	vtGetScene()->OnMouse(event);
}

/*
  The GLUT redraw event
*/
void redraw()
{
	vtGetScene()->DoUpdate();

	glutPostRedisplay();
	glutSwapBuffers();
}

void InitGLUT()
{
	int   fake_argc = 1;
	char *fake_argv[3];
	fake_argv[0] = "glutSimple";
	fake_argv[1] = "Example Program";
	fake_argv[2] = NULL;

	/*
	Initialise GLUT
	*/
	glutInitWindowPosition(0, 0);
	glutInitWindowSize(800, 600);
	glutInit          (&fake_argc, fake_argv);
	glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
	glutCreateWindow  (fake_argv[1]);
	glutDisplayFunc   (redraw);
	glutReshapeFunc   (reshape);
	glutKeyboardFunc  (keyboard);
	glutMouseFunc     (mouse);
	glutMotionFunc    (motion);
}

//
// Create the 3d scene
//
bool CreateScene()
{
	// Get a handle to the vtScene - one is already created for you
	vtScene *pScene = vtGetScene();
	pScene->Init();

	// Log messages to make troubleshooting easier
	VTSTARTLOG("debug.txt");
	VTLOG("glutSimple\n");

	// Look up the camera
	vtCamera *pCamera = pScene->GetCamera();
	pCamera->SetHither(10);
	pCamera->SetYon(100000);

	// The  terrain scene will contain all the terrains that are created.
	vtTerrainScene *ts = new vtTerrainScene;

	// Set the global data path
	vtStringArray paths;
	paths.push_back(vtString("Data/"));
	ts->SetDataPath(paths);

	// Begin creating the scene, including the sun and sky
	vtGroup *pTopGroup = ts->BeginTerrainScene();

	// Tell the scene graph to point to this terrain scene
	pScene->SetRoot(pTopGroup);

	// Create a new vtTerrain, read its parameters from a file
	vtTerrain *pTerr = new vtTerrain;
	pTerr->SetParamFile("Data/Simple.xml");

	// Add the terrain to the scene, and contruct it
	ts->AppendTerrain(pTerr);
	if (!ts->BuildTerrain(pTerr))
	{
		printf("Terrain creation failed: %s\n",
			(const char *)pTerr->GetLastError());
		return false;
	}
	ts->SetCurrentTerrain(pTerr);

	// Create a navigation engine to move around on the terrain
	// Get flight speed from terrain parameters
	float fSpeed = pTerr->GetParams().GetValueFloat(STR_NAVSPEED);

	vtTerrainFlyer *pFlyer = new vtTerrainFlyer(fSpeed);
	pFlyer->SetTarget(pCamera);
	pFlyer->SetHeightField(pTerr->GetHeightField());
	pScene->AddEngine(pFlyer);

	// Minimum height over terrain is 100 m
	vtHeightConstrain *pConstrain = new vtHeightConstrain(100);
	pConstrain->SetTarget(pCamera);
	pConstrain->SetHeightField(pTerr->GetHeightField());
	pScene->AddEngine(pConstrain);

#if 1
	vtHeightFieldGrid3d *grid = pTerr->GetHeightFieldGrid3d();
	FRECT ext = grid->m_WorldExtents;
	float minh, maxh;
	grid->GetHeightExtents(minh, maxh);
	FBox3 box(0,				   minh, ext.top,
		ext.right, minh, ext.bottom);

	vtMaterialArray *pMats = new vtMaterialArray;
	pMats->AddRGBMaterial1(RGBf(1.0f, 0.0f, 0.0f), true, false, true);
	pMats->AddRGBMaterial1(RGBf(0.0f, 1.0f, 0.0f), true, false, true);
	pMats->AddRGBMaterial1(RGBf(0.0f, 0.0f, 1.0f), true, false, true);
	vtGeom *pGeom = CreateLineGridGeom(pMats, 0,
						   box.min, box.max, 32);
	vtMesh *mesh1 = new vtMesh(vtMesh::LINES, 0, 6);
	mesh1->AddLine(FPoint3(0,0,0), FPoint3(0,maxh,0));
	pGeom->AddMesh(mesh1, 1);
	vtMesh *mesh2 = new vtMesh(vtMesh::LINES, 0, 6);
	mesh2->AddLine(FPoint3(-1000,0,0), FPoint3(1000,0,0));
	pGeom->AddMesh(mesh2, 2);
	pTopGroup->AddChild(pGeom);
#endif

	return true;
}

/*
  The works.
*/
int main(int, char ** )
{
#ifdef __FreeBSD__
	/*  FreeBSD is more stringent with FP ops by default, and OSG is doing  */
	/*    silly things sqrt(Inf) (computing lengths of MAXFLOAT and NaN     */
	/*    Vec3's).   This turns off FP bug core dumps, ignoring the error   */
	/*    like most platforms do by default.                                */
	fpsetmask(0);
#endif

	printf("Initializing GLUT..\n");
	InitGLUT();

	printf("Creating the terrain..\n");
	CreateScene();

	printf("Running..\n");
	glutMainLoop();

	return 0;
}

<|endoftext|>


<commit_before>#include "ATKSD1.h"
#include "IPlug_include_in_plug_src.h"
#include "IControl.h"
#include "resource.h"

const int kNumPrograms = 1;

enum EParams
{
  kDrive = 0,
  kTone,
  kLevel,
  kNumParams
};

enum ELayout
{
  kWidth = GUI_WIDTH,
  kHeight = GUI_HEIGHT,

  kDriveX = 55,
  kDriveY = 38,
  kToneX = 125,
  kToneY = 95,
  kLevelX = 193,
  kLevelY = 38,
  kKnobFrames = 60
};

ATKSD1::ATKSD1(IPlugInstanceInfo instanceInfo)
  :	IPLUG_CTOR(kNumParams, kNumPrograms, instanceInfo), mDrive(0.), mTone(50), mLevel(100),
    inFilter(NULL, 1, 0, false), outFilter(NULL, 1, 0, false)
{
  TRACE;

  //arguments are: name, defaultVal, minVal, maxVal, step, label
  GetParam(kDrive)->InitDouble("Drive", 0., 0., 100.0, 0.01, "%");
  GetParam(kDrive)->SetShape(2.);
  GetParam(kTone)->InitDouble("Tone", 0, -100., 100.0, 0.01, "%");
  GetParam(kTone)->SetShape(1.);
  GetParam(kLevel)->InitDouble("Level", 100., 0., 100.0, 0.01, "%");
  GetParam(kLevel)->SetShape(2.);

  IGraphics* pGraphics = MakeGraphics(this, kWidth, kHeight);
  pGraphics->AttachBackground(SD1_ID, SD1_FN);

  IBitmap knob = pGraphics->LoadIBitmap(KNOB_ID, KNOB_FN, kKnobFrames);

  pGraphics->AttachControl(new IKnobMultiControl(this, kDriveX, kDriveY, kDrive, &knob));
  pGraphics->AttachControl(new IKnobMultiControl(this, kToneX, kToneY, kTone, &knob));
  pGraphics->AttachControl(new IKnobMultiControl(this, kLevelX, kLevelY, kLevel, &knob));

  AttachGraphics(pGraphics);

  //MakePreset("preset 1", ... );
  MakeDefaultPreset((char *) "-", kNumPrograms);

  //SetLatency(3);

  oversamplingFilter.set_input_port(0, &inFilter, 0);
  overdriveFilter.set_input_port(0, &oversamplingFilter, 0);
  lowpassFilter.set_input_port(0, &overdriveFilter, 0);
  decimationFilter.set_input_port(0, &lowpassFilter, 0);
  toneFilter.set_input_port(0, &decimationFilter, 0);
  highpassFilter.set_input_port(0, &toneFilter, 0);
  volumeFilter.set_input_port(0, &highpassFilter, 0);
  outFilter.set_input_port(0, &volumeFilter, 0);

  lowpassFilter.set_order(8);
  lowpassFilter.set_cut_frequency(20000);
  highpassFilter.select(2);
  highpassFilter.set_cut_frequency(20);
  highpassFilter.set_attenuation(1);

  Reset();
}

ATKSD1::~ATKSD1() {}

void ATKSD1::ProcessDoubleReplacing(double** inputs, double** outputs, int nFrames)
{
  // Mutex is already locked for us.

  inFilter.set_pointer(inputs[0], nFrames);
  outFilter.set_pointer(outputs[0], nFrames);
  outFilter.process(nFrames);
}

void ATKSD1::Reset()
{
  TRACE;
  IMutexLock lock(this);

  int sampling_rate = GetSampleRate();

  inFilter.set_input_sampling_rate(sampling_rate);
  inFilter.set_output_sampling_rate(sampling_rate);
  oversamplingFilter.set_input_sampling_rate(sampling_rate);
  oversamplingFilter.set_output_sampling_rate(sampling_rate * 32);
  overdriveFilter.set_input_sampling_rate(sampling_rate*32);
  overdriveFilter.set_output_sampling_rate(sampling_rate * 32);
  lowpassFilter.set_input_sampling_rate(sampling_rate*32);
  lowpassFilter.set_output_sampling_rate(sampling_rate * 32);
  decimationFilter.set_input_sampling_rate(sampling_rate*32);
  decimationFilter.set_output_sampling_rate(sampling_rate);
  toneFilter.set_input_sampling_rate(sampling_rate);
  toneFilter.set_output_sampling_rate(sampling_rate);
  highpassFilter.set_input_sampling_rate(sampling_rate);
  highpassFilter.set_output_sampling_rate(sampling_rate);
  volumeFilter.set_input_sampling_rate(sampling_rate);
  volumeFilter.set_output_sampling_rate(sampling_rate);
  outFilter.set_input_sampling_rate(sampling_rate);
  outFilter.set_output_sampling_rate(sampling_rate);
  //reset setup
}

void ATKSD1::OnParamChange(int paramIdx)
{
  IMutexLock lock(this);

  switch (paramIdx)
  {
    case kDrive:
      overdriveFilter.set_drive(GetParam(kDrive)->Value() / 100.);
      break;
    case kTone:
      toneFilter.set_tone((GetParam(kTone)->Value() + 100) / 200.);
      break;
    case kLevel:
      volumeFilter.set_volume(GetParam(kLevel)->Value() / 150.);
      break;

    default:
      break;
  }
}
<commit_msg>Wrong coordinates for the knobs<commit_after>#include "ATKSD1.h"
#include "IPlug_include_in_plug_src.h"
#include "IControl.h"
#include "resource.h"

const int kNumPrograms = 1;

enum EParams
{
  kDrive = 0,
  kTone,
  kLevel,
  kNumParams
};

enum ELayout
{
  kWidth = GUI_WIDTH,
  kHeight = GUI_HEIGHT,

  kLevelX = 55,
  kLevelY = 38,
  kToneX = 125,
  kToneY = 95,
  kDriveX = 193,
  kDriveY = 38,
  kKnobFrames = 60
};

ATKSD1::ATKSD1(IPlugInstanceInfo instanceInfo)
  :	IPLUG_CTOR(kNumParams, kNumPrograms, instanceInfo), mDrive(0.), mTone(50), mLevel(100),
    inFilter(NULL, 1, 0, false), outFilter(NULL, 1, 0, false)
{
  TRACE;

  //arguments are: name, defaultVal, minVal, maxVal, step, label
  GetParam(kDrive)->InitDouble("Drive", 0., 0., 100.0, 0.01, "%");
  GetParam(kDrive)->SetShape(2.);
  GetParam(kTone)->InitDouble("Tone", 0, -100., 100.0, 0.01, "%");
  GetParam(kTone)->SetShape(1.);
  GetParam(kLevel)->InitDouble("Level", 100., 0., 100.0, 0.01, "%");
  GetParam(kLevel)->SetShape(2.);

  IGraphics* pGraphics = MakeGraphics(this, kWidth, kHeight);
  pGraphics->AttachBackground(SD1_ID, SD1_FN);

  IBitmap knob = pGraphics->LoadIBitmap(KNOB_ID, KNOB_FN, kKnobFrames);

  pGraphics->AttachControl(new IKnobMultiControl(this, kDriveX, kDriveY, kDrive, &knob));
  pGraphics->AttachControl(new IKnobMultiControl(this, kToneX, kToneY, kTone, &knob));
  pGraphics->AttachControl(new IKnobMultiControl(this, kLevelX, kLevelY, kLevel, &knob));

  AttachGraphics(pGraphics);

  //MakePreset("preset 1", ... );
  MakeDefaultPreset((char *) "-", kNumPrograms);

  //SetLatency(3);

  oversamplingFilter.set_input_port(0, &inFilter, 0);
  overdriveFilter.set_input_port(0, &oversamplingFilter, 0);
  lowpassFilter.set_input_port(0, &overdriveFilter, 0);
  decimationFilter.set_input_port(0, &lowpassFilter, 0);
  toneFilter.set_input_port(0, &decimationFilter, 0);
  highpassFilter.set_input_port(0, &toneFilter, 0);
  volumeFilter.set_input_port(0, &highpassFilter, 0);
  outFilter.set_input_port(0, &volumeFilter, 0);

  lowpassFilter.set_order(8);
  lowpassFilter.set_cut_frequency(20000);
  highpassFilter.select(2);
  highpassFilter.set_cut_frequency(20);
  highpassFilter.set_attenuation(1);

  Reset();
}

ATKSD1::~ATKSD1() {}

void ATKSD1::ProcessDoubleReplacing(double** inputs, double** outputs, int nFrames)
{
  // Mutex is already locked for us.

  inFilter.set_pointer(inputs[0], nFrames);
  outFilter.set_pointer(outputs[0], nFrames);
  outFilter.process(nFrames);
}

void ATKSD1::Reset()
{
  TRACE;
  IMutexLock lock(this);

  int sampling_rate = GetSampleRate();

  inFilter.set_input_sampling_rate(sampling_rate);
  inFilter.set_output_sampling_rate(sampling_rate);
  oversamplingFilter.set_input_sampling_rate(sampling_rate);
  oversamplingFilter.set_output_sampling_rate(sampling_rate * 32);
  overdriveFilter.set_input_sampling_rate(sampling_rate*32);
  overdriveFilter.set_output_sampling_rate(sampling_rate * 32);
  lowpassFilter.set_input_sampling_rate(sampling_rate*32);
  lowpassFilter.set_output_sampling_rate(sampling_rate * 32);
  decimationFilter.set_input_sampling_rate(sampling_rate*32);
  decimationFilter.set_output_sampling_rate(sampling_rate);
  toneFilter.set_input_sampling_rate(sampling_rate);
  toneFilter.set_output_sampling_rate(sampling_rate);
  highpassFilter.set_input_sampling_rate(sampling_rate);
  highpassFilter.set_output_sampling_rate(sampling_rate);
  volumeFilter.set_input_sampling_rate(sampling_rate);
  volumeFilter.set_output_sampling_rate(sampling_rate);
  outFilter.set_input_sampling_rate(sampling_rate);
  outFilter.set_output_sampling_rate(sampling_rate);
  //reset setup
}

void ATKSD1::OnParamChange(int paramIdx)
{
  IMutexLock lock(this);

  switch (paramIdx)
  {
    case kDrive:
      overdriveFilter.set_drive(GetParam(kDrive)->Value() / 100.);
      break;
    case kTone:
      toneFilter.set_tone((GetParam(kTone)->Value() + 100) / 200.);
      break;
    case kLevel:
      volumeFilter.set_volume(GetParam(kLevel)->Value() / 150.);
      break;

    default:
      break;
  }
}
<|endoftext|>


<commit_before>#include <opkele/exception.h>
#include <opkele/curl.h>

#include "config.h"

namespace opkele {

    namespace util {

	curl_slist_t::~curl_slist_t() throw() {
	    if(_s)
		curl_slist_free_all(_s);
	}

	curl_slist_t& curl_slist_t::operator=(curl_slist *s) {
	    if(_s)
		curl_slist_free_all(_s);
	    _s = s;
	    return *this;
	}

	void curl_slist_t::append(const char *str) {
	    curl_slist *s = curl_slist_append(_s,str);
	    if(!s)
		throw opkele::exception(OPKELE_CP_ "failed to curl_slist_append()");
	    _s=s;
	}

	curl_t::~curl_t() throw() {
	    if(_c)
		curl_easy_cleanup(_c);
	}

	curl_t& curl_t::operator=(CURL *c) {
	    if(_c)
		curl_easy_cleanup(_c);
	    _c = c;
	    return *this;
	}

	CURLcode curl_t::misc_sets() {
	    assert(_c);
	    CURLcode r;
	    (r=easy_setopt(CURLOPT_FOLLOWLOCATION,1))
	    || (r=easy_setopt(CURLOPT_MAXREDIRS,5))
	    || (r=easy_setopt(CURLOPT_DNS_CACHE_TIMEOUT,120))
	    || (r=easy_setopt(CURLOPT_DNS_USE_GLOBAL_CACHE,1))
	    || (r=easy_setopt(CURLOPT_USERAGENT,PACKAGE_NAME"/"PACKAGE_SRC_VERSION))
	    || (r=easy_setopt(CURLOPT_TIMEOUT,20))
#ifdef	DISABLE_CURL_SSL_VERIFYHOST
	    || (r=easy_setopt(CURLOPT_SSL_VERIFYHOST,0))
#endif
#ifdef	DISABLE_CURL_SSL_VERIFYPEER
	    || (r=easy_setopt(CURLOPT_SSL_VERIFYPEER,0))
#endif
	    ;
	    return r;
	}

	static size_t _write(void *p,size_t s,size_t nm,void *stream) {
	    return ((curl_t*)stream)->write(p,s,nm);
	}

	CURLcode curl_t::set_write() {
	    assert(_c);
	    CURLcode r;
	    (r = easy_setopt(CURLOPT_WRITEDATA,this))
	    || (r = easy_setopt(CURLOPT_WRITEFUNCTION,_write));
	    return r;
	}

	static int _progress(void *cp,double dlt,double dln,double ult,double uln) {
	    return ((curl_t*)cp)->progress(dlt,dln,ult,uln);
	}

	CURLcode curl_t::set_progress() {
	    assert(_c);
	    CURLcode r;
	    (r = easy_setopt(CURLOPT_PROGRESSDATA,this))
	    || (r = easy_setopt(CURLOPT_PROGRESSFUNCTION,_progress))
	    || (r = easy_setopt(CURLOPT_NOPROGRESS,0));
	    return r;
	}

	static size_t _header(void *p,size_t s,size_t nm,void *stream) {
	    return ((curl_t*)stream)->header(p,s,nm);
	}

	CURLcode curl_t::set_header() {
	    assert(_c);
	    CURLcode r;
	    (r = easy_setopt(CURLOPT_HEADERDATA,this))
	    || (r=easy_setopt(CURLOPT_HEADERFUNCTION,_header));
	    return r;
	}

    }

}
<commit_msg>Fix ambiguity with C++11 user-defined literals<commit_after>#include <opkele/exception.h>
#include <opkele/curl.h>

#include "config.h"

namespace opkele {

    namespace util {

	curl_slist_t::~curl_slist_t() throw() {
	    if(_s)
		curl_slist_free_all(_s);
	}

	curl_slist_t& curl_slist_t::operator=(curl_slist *s) {
	    if(_s)
		curl_slist_free_all(_s);
	    _s = s;
	    return *this;
	}

	void curl_slist_t::append(const char *str) {
	    curl_slist *s = curl_slist_append(_s,str);
	    if(!s)
		throw opkele::exception(OPKELE_CP_ "failed to curl_slist_append()");
	    _s=s;
	}

	curl_t::~curl_t() throw() {
	    if(_c)
		curl_easy_cleanup(_c);
	}

	curl_t& curl_t::operator=(CURL *c) {
	    if(_c)
		curl_easy_cleanup(_c);
	    _c = c;
	    return *this;
	}

	CURLcode curl_t::misc_sets() {
	    assert(_c);
	    CURLcode r;
	    (r=easy_setopt(CURLOPT_FOLLOWLOCATION,1))
	    || (r=easy_setopt(CURLOPT_MAXREDIRS,5))
	    || (r=easy_setopt(CURLOPT_DNS_CACHE_TIMEOUT,120))
	    || (r=easy_setopt(CURLOPT_DNS_USE_GLOBAL_CACHE,1))
	    || (r=easy_setopt(CURLOPT_USERAGENT,PACKAGE_NAME "/" PACKAGE_SRC_VERSION))
	    || (r=easy_setopt(CURLOPT_TIMEOUT,20))
#ifdef	DISABLE_CURL_SSL_VERIFYHOST
	    || (r=easy_setopt(CURLOPT_SSL_VERIFYHOST,0))
#endif
#ifdef	DISABLE_CURL_SSL_VERIFYPEER
	    || (r=easy_setopt(CURLOPT_SSL_VERIFYPEER,0))
#endif
	    ;
	    return r;
	}

	static size_t _write(void *p,size_t s,size_t nm,void *stream) {
	    return ((curl_t*)stream)->write(p,s,nm);
	}

	CURLcode curl_t::set_write() {
	    assert(_c);
	    CURLcode r;
	    (r = easy_setopt(CURLOPT_WRITEDATA,this))
	    || (r = easy_setopt(CURLOPT_WRITEFUNCTION,_write));
	    return r;
	}

	static int _progress(void *cp,double dlt,double dln,double ult,double uln) {
	    return ((curl_t*)cp)->progress(dlt,dln,ult,uln);
	}

	CURLcode curl_t::set_progress() {
	    assert(_c);
	    CURLcode r;
	    (r = easy_setopt(CURLOPT_PROGRESSDATA,this))
	    || (r = easy_setopt(CURLOPT_PROGRESSFUNCTION,_progress))
	    || (r = easy_setopt(CURLOPT_NOPROGRESS,0));
	    return r;
	}

	static size_t _header(void *p,size_t s,size_t nm,void *stream) {
	    return ((curl_t*)stream)->header(p,s,nm);
	}

	CURLcode curl_t::set_header() {
	    assert(_c);
	    CURLcode r;
	    (r = easy_setopt(CURLOPT_HEADERDATA,this))
	    || (r=easy_setopt(CURLOPT_HEADERFUNCTION,_header));
	    return r;
	}

    }

}
<|endoftext|>


<commit_before>/*
 * main.cpp - Main entry point for the executable
 *
 * Contains command processing functions, and uses
 * a Huffman Tree to encode and decode files
 *
 * Built for EECS2510 - Nonlinear Data Structures
 *	at The University of Toledo, Spring 2016
 *
 * Copyright (c) 2016 Nathan Lowe
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#include "stdafx.h"
#include <iostream>
#include <chrono>
#include <iomanip>

#include "CommandLineOptions.h"
#include "HuffmanEncoder.h"
#include "Verbose.h"

using namespace std;

// Since the verbose namespace is used multiple times in different files,
// we need to define an implementation of the enable flag in exactly one
// translation unit so that it is shared between all units
namespace verbose
{
	bool enable = false;
}

// The encoder we'll use for encoding and decoding files
HuffmanEncoder* encoder = nullptr;

// The return code for normal operations
static const int EXIT_OK = 0;
// The return code for bad arguments
static const int EXIT_BAD_ARGUMENTS = -1;
// The return code for a failed encoding job
static const int EXIT_ENCODE_FAILED = -2;
// The return code for a failed decoding job
static const int EXIT_DECODE_FAILED = -3;

// Forward declare these methods so main is at the top as per project spec
CommandLineOptions parseArguments(int argc, char* argv[]);
string PrependExtension(string input, string extension);
void printHelp();
bool doEncode(CommandLineOptions options);
bool doDecode(CommandLineOptions options);

// The main entry point of the application
int main(int argc, char* argv[])
{
	// The project spec requires main to encode and decode a file that is hard-coded for easy testing
	// If we don't have any arguments and we're in debug mode, assume it's being tested
#ifdef DEBUG
	if(argc == 1)
	{
		string INPUT_FILE   = "Shakespeare.txt";
		string ENCODED_FILE = "Shakespeare.enc";
		string DECODED_FILE = "Shakespeare.dec";

		CommandLineOptions interactiveOptions;

		interactiveOptions.input  = INPUT_FILE;
		interactiveOptions.output = ENCODED_FILE;

		cout << "Encoding file " << INPUT_FILE << " to " << ENCODED_FILE << endl;
		if (!doEncode(interactiveOptions)) return EXIT_ENCODE_FAILED;

		interactiveOptions.input  = ENCODED_FILE;
		interactiveOptions.output = DECODED_FILE;

		cout << "Decoding file " << ENCODED_FILE << " to " << DECODED_FILE << endl;
		if (!doDecode(interactiveOptions)) return EXIT_DECODE_FAILED;

		return EXIT_OK;
	}
#endif

	// Parse command line options
	auto options = parseArguments(argc, argv);

	// Enable verbose if requested
	if (options.verbose) verbose::enable = true;

	verbose::write(options.ToString());

	// If the help flag was specified, print the help message and exit
	if (options.printHelp)
	{
		printHelp();
		return EXIT_OK;
	}

	// If there was an error parsing command line options, just exit
	if (options.parseError) return EXIT_BAD_ARGUMENTS;

	// If neither encode nor decode modes were specified, exit
	if (!(options.encode || options.decode))
	{
		cout << "Nothing to do (specify one of -e, -d, or -t)" << endl;
		return EXIT_OK;
	}

	// If the input file or output file are blank, exit
	if (options.input == "" || options.output == "")
	{
		cout << "Both the input and output files must be specified" << endl;
		return EXIT_BAD_ARGUMENTS;
	}

	// Perform an encode operation if specified
	if (options.encode && !doEncode(options)) return EXIT_ENCODE_FAILED;
	// Perform a decode operation if specified
	if (options.decode && !doDecode(options)) return EXIT_DECODE_FAILED;

	// Free the encoder if we created one
	if (encoder != nullptr) delete encoder;

	return EXIT_OK;
}

// Perform an encoding operation using the specified command-line options
bool doEncode(CommandLineOptions options)
{
	// Build the encoder from the input file and record how long that takes
	auto ctor_start = chrono::system_clock::now();
	encoder = HuffmanEncoder::InitializeFromFile(options.input);
	auto ctor_end = chrono::system_clock::now();

	size_t read = 0;
	size_t written = 0;

	try
	{
		// Encode the file and record how long that takes
		auto encode_start = chrono::system_clock::now();
		encoder->EncodeFile(options.input, options.output, read, written);
		auto encode_end = chrono::system_clock::now();

		// Calculate the compression ratio
		auto ratio = static_cast<double>(written) / static_cast<double>(read);

		cout << setiosflags(ios::fixed) << setprecision(3);
		cout << "File encoded. In: " << read << " bytes, Out: " << written << " bytes. Ratio: " << ratio;
		cout << "% Time: " << chrono::duration_cast<chrono::duration<float>>(ctor_end - ctor_start).count();
		cout << "s initialization, " << chrono::duration_cast<chrono::duration<float>>(encode_end - encode_start).count();
		cout << "s encode" << endl;
	}
	catch (exception& e)
	{
		cerr << "An error occurred while encoding: " << e.what() << endl;

		return false;
	}
	return true;
}

// Perform a decode operation using the specified options
bool doDecode(CommandLineOptions options)
{
	auto inFile = options.input;
	auto outFile = options.output;

	// If we haven't already encoded a file, then we need to make an empty encoder/decoder
	if (!options.encode)
	{
		encoder = new HuffmanEncoder();
	}
	else
	{
		// If we have, we need to change the output file, since it gets used twice
		// (once to save encoding output, and once to save decoding output)
		inFile = options.output;
		outFile = PrependExtension(options.input, "hz");
	}

	size_t read = 0;
	size_t written = 0;

	try
	{
		// Decode the file and record how long that takes
		auto start = chrono::system_clock::now();
		encoder->DecodeFile(inFile, outFile, read, written);
		auto end = chrono::system_clock::now();

		cout << setiosflags(ios::fixed) << setprecision(3);
		cout << "File decoded. In: " << read << " bytes, Out: " << written << " bytes, Time: ";
		cout << chrono::duration_cast<chrono::duration<float>>(end - start).count() << "s" << endl;
	}
	catch (exception& e)
	{
		cerr << "An error occurred while decoding: " << e.what() << endl;

		return false;
	}
	return true;
}

// Prepend the specified extension before the actual extension of the input string
// Example: PrependExtension("test.txt", "hz")  returns "test.hz.txt"
string PrependExtension(string input, string extension)
{
	auto period = input.find_last_of('.');
	if(period != string::npos)
	{
		return input.substr(0, period) + '.' + extension + input.substr(period);
	}

	throw invalid_argument("Unable to find extension in " + input);
}

// Prints the help message to standard output
void printHelp()
{
	cout << "Huffman Encoder and Decoder" << endl;
	cout << "Usage: huffman <options> -i <input_file> -o <output_file>" << endl << endl;

	cout << "Options:" << endl;
	cout << "\t-i, --input\tSpecifies the input file to encode or decode" << endl;
	cout << "\t-o, --output\tSpecifies the output file to encode or decode to" << endl;
	cout << "\t-e, --encode\tEncode <input_file> and write to <output_file>" << endl;
	cout << "\t-d, --decode\tDecode <input_file> and write to <output_file>" << endl;
	cout << "\t-t, --test\tEncode <input_file> to <output>.hz, then decode back to <output_file>" << endl;
	cout << "\t-v, --verbose\tPrint verbose messages" << endl;
	cout << "\t-h, --help\tPrint this help message" << endl;
}

// Processes the command-line arguments and returns a CommandLineOptions struct
CommandLineOptions parseArguments(int argc, char* argv[])
{
	CommandLineOptions result;

	for (int i = 1; i < argc; i++)
	{
		auto arg = string(argv[i]);
		if(arg == "-e" || arg == "--encode")
		{
			result.encode = true;
		}
		else if(arg == "-d" || arg == "--decode")
		{
			result.decode = true;
		}
		else if(arg == "-t" || arg == "--test")
		{
			result.encode = result.decode = true;
		}
		else if(arg == "-v" || arg == "--verbose")
		{
			result.verbose = true;
		}
		else if(arg == "-h" || arg == "--help")
		{
			result.printHelp = true;
		}
		else if(arg == "-i" || arg == "--input")
		{
			if(i >= argc-1)
			{
				result.parseError = true;
				cout << "Missing Parameter for " << argv[i] << endl;
			}
			else
			{
				result.input = string(argv[++i]);
			}
		}
		else if(arg == "-o" || arg == "--output")
		{
			if (i >= argc - 1)
			{
				result.parseError = true;
				cout << "Missing Parameter for " << argv[i] << endl;
			}
			else
			{
				result.output = string(argv[++i]);
			}
		}
		else
		{
			result.parseError = true;
			cout << "Unrecognized Argument: " << argv[i] << endl;
		}
	}

	return result;
}
<commit_msg>Catch an exception when a file cannot be found<commit_after>/*
 * main.cpp - Main entry point for the executable
 *
 * Contains command processing functions, and uses
 * a Huffman Tree to encode and decode files
 *
 * Built for EECS2510 - Nonlinear Data Structures
 *	at The University of Toledo, Spring 2016
 *
 * Copyright (c) 2016 Nathan Lowe
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#include "stdafx.h"
#include <iostream>
#include <chrono>
#include <iomanip>

#include "CommandLineOptions.h"
#include "HuffmanEncoder.h"
#include "Verbose.h"

using namespace std;

// Since the verbose namespace is used multiple times in different files,
// we need to define an implementation of the enable flag in exactly one
// translation unit so that it is shared between all units
namespace verbose
{
	bool enable = false;
}

// The encoder we'll use for encoding and decoding files
HuffmanEncoder* encoder = nullptr;

// The return code for normal operations
static const int EXIT_OK = 0;
// The return code for bad arguments
static const int EXIT_BAD_ARGUMENTS = -1;
// The return code for a failed encoding job
static const int EXIT_ENCODE_FAILED = -2;
// The return code for a failed decoding job
static const int EXIT_DECODE_FAILED = -3;

// Forward declare these methods so main is at the top as per project spec
CommandLineOptions parseArguments(int argc, char* argv[]);
string PrependExtension(string input, string extension);
void printHelp();
bool doEncode(CommandLineOptions options);
bool doDecode(CommandLineOptions options);

// The main entry point of the application
int main(int argc, char* argv[])
{
	// The project spec requires main to encode and decode a file that is hard-coded for easy testing
	// If we don't have any arguments and we're in debug mode, assume it's being tested
#ifdef DEBUG
	if(argc == 1)
	{
		string INPUT_FILE   = "Shakespeare.txt";
		string ENCODED_FILE = "Shakespeare.enc";
		string DECODED_FILE = "Shakespeare.dec";

		CommandLineOptions interactiveOptions;

		interactiveOptions.input  = INPUT_FILE;
		interactiveOptions.output = ENCODED_FILE;

		cout << "Encoding file " << INPUT_FILE << " to " << ENCODED_FILE << endl;
		if (!doEncode(interactiveOptions)) return EXIT_ENCODE_FAILED;

		interactiveOptions.input  = ENCODED_FILE;
		interactiveOptions.output = DECODED_FILE;

		cout << "Decoding file " << ENCODED_FILE << " to " << DECODED_FILE << endl;
		if (!doDecode(interactiveOptions)) return EXIT_DECODE_FAILED;

		return EXIT_OK;
	}
#endif

	// Parse command line options
	auto options = parseArguments(argc, argv);

	// Enable verbose if requested
	if (options.verbose) verbose::enable = true;

	verbose::write(options.ToString());

	// If the help flag was specified, print the help message and exit
	if (options.printHelp)
	{
		printHelp();
		return EXIT_OK;
	}

	// If there was an error parsing command line options, just exit
	if (options.parseError) return EXIT_BAD_ARGUMENTS;

	// If neither encode nor decode modes were specified, exit
	if (!(options.encode || options.decode))
	{
		cout << "Nothing to do (specify one of -e, -d, or -t)" << endl;
		return EXIT_OK;
	}

	// If the input file or output file are blank, exit
	if (options.input == "" || options.output == "")
	{
		cout << "Both the input and output files must be specified" << endl;
		return EXIT_BAD_ARGUMENTS;
	}

	// Perform an encode operation if specified
	if (options.encode && !doEncode(options)) return EXIT_ENCODE_FAILED;
	// Perform a decode operation if specified
	if (options.decode && !doDecode(options)) return EXIT_DECODE_FAILED;

	// Free the encoder if we created one
	if (encoder != nullptr) delete encoder;

	return EXIT_OK;
}

// Perform an encoding operation using the specified command-line options
bool doEncode(CommandLineOptions options)
{
	try
	{
		// Build the encoder from the input file and record how long that takes
		auto ctor_start = chrono::system_clock::now();
		encoder = HuffmanEncoder::InitializeFromFile(options.input);
		auto ctor_end = chrono::system_clock::now();

		size_t read = 0;
		size_t written = 0;

		// Encode the file and record how long that takes
		auto encode_start = chrono::system_clock::now();
		encoder->EncodeFile(options.input, options.output, read, written);
		auto encode_end = chrono::system_clock::now();

		// Calculate the compression ratio
		auto ratio = static_cast<double>(written) / static_cast<double>(read);

		cout << setiosflags(ios::fixed) << setprecision(3);
		cout << "File encoded. In: " << read << " bytes, Out: " << written << " bytes. Ratio: " << ratio;
		cout << "% Time: " << chrono::duration_cast<chrono::duration<float>>(ctor_end - ctor_start).count();
		cout << "s initialization, " << chrono::duration_cast<chrono::duration<float>>(encode_end - encode_start).count();
		cout << "s encode" << endl;
	}
	catch (exception& e)
	{
		cerr << "An error occurred while encoding: " << e.what() << endl;

		return false;
	}
	return true;
}

// Perform a decode operation using the specified options
bool doDecode(CommandLineOptions options)
{
	try
	{
		auto inFile = options.input;
		auto outFile = options.output;

		// If we haven't already encoded a file, then we need to make an empty encoder/decoder
		if (!options.encode)
		{
			encoder = new HuffmanEncoder();
		}
		else
		{
			// If we have, we need to change the output file, since it gets used twice
			// (once to save encoding output, and once to save decoding output)
			inFile = options.output;
			outFile = PrependExtension(options.input, "hz");
		}

		size_t read = 0;
		size_t written = 0;

		// Decode the file and record how long that takes
		auto start = chrono::system_clock::now();
		encoder->DecodeFile(inFile, outFile, read, written);
		auto end = chrono::system_clock::now();

		cout << setiosflags(ios::fixed) << setprecision(3);
		cout << "File decoded. In: " << read << " bytes, Out: " << written << " bytes, Time: ";
		cout << chrono::duration_cast<chrono::duration<float>>(end - start).count() << "s" << endl;
	}
	catch (exception& e)
	{
		cerr << "An error occurred while decoding: " << e.what() << endl;

		return false;
	}
	return true;
}

// Prepend the specified extension before the actual extension of the input string
// Example: PrependExtension("test.txt", "hz")  returns "test.hz.txt"
string PrependExtension(string input, string extension)
{
	auto period = input.find_last_of('.');
	if(period != string::npos)
	{
		return input.substr(0, period) + '.' + extension + input.substr(period);
	}

	throw invalid_argument("Unable to find extension in " + input);
}

// Prints the help message to standard output
void printHelp()
{
	cout << "Huffman Encoder and Decoder" << endl;
	cout << "Usage: huffman <options> -i <input_file> -o <output_file>" << endl << endl;

	cout << "Options:" << endl;
	cout << "\t-i, --input\tSpecifies the input file to encode or decode" << endl;
	cout << "\t-o, --output\tSpecifies the output file to encode or decode to" << endl;
	cout << "\t-e, --encode\tEncode <input_file> and write to <output_file>" << endl;
	cout << "\t-d, --decode\tDecode <input_file> and write to <output_file>" << endl;
	cout << "\t-t, --test\tEncode <input_file> to <output>.hz, then decode back to <output_file>" << endl;
	cout << "\t-v, --verbose\tPrint verbose messages" << endl;
	cout << "\t-h, --help\tPrint this help message" << endl;
}

// Processes the command-line arguments and returns a CommandLineOptions struct
CommandLineOptions parseArguments(int argc, char* argv[])
{
	CommandLineOptions result;

	for (int i = 1; i < argc; i++)
	{
		auto arg = string(argv[i]);
		if(arg == "-e" || arg == "--encode")
		{
			result.encode = true;
		}
		else if(arg == "-d" || arg == "--decode")
		{
			result.decode = true;
		}
		else if(arg == "-t" || arg == "--test")
		{
			result.encode = result.decode = true;
		}
		else if(arg == "-v" || arg == "--verbose")
		{
			result.verbose = true;
		}
		else if(arg == "-h" || arg == "--help")
		{
			result.printHelp = true;
		}
		else if(arg == "-i" || arg == "--input")
		{
			if(i >= argc-1)
			{
				result.parseError = true;
				cout << "Missing Parameter for " << argv[i] << endl;
			}
			else
			{
				result.input = string(argv[++i]);
			}
		}
		else if(arg == "-o" || arg == "--output")
		{
			if (i >= argc - 1)
			{
				result.parseError = true;
				cout << "Missing Parameter for " << argv[i] << endl;
			}
			else
			{
				result.output = string(argv[++i]);
			}
		}
		else
		{
			result.parseError = true;
			cout << "Unrecognized Argument: " << argv[i] << endl;
		}
	}

	return result;
}
<|endoftext|>