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

#include "util.h"

#ifdef _WIN32
#include <windows.h>
#include <io.h>
#endif

#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>

#ifndef _WIN32
#include <sys/time.h>
#endif

#include <vector>

#ifdef _WIN32
#include <direct.h>  // _mkdir
#endif

#include "edit_distance.h"
#include "metrics.h"

void Fatal(const char* msg, ...) {
  va_list ap;
  fprintf(stderr, "ninja: fatal: ");
  va_start(ap, msg);
  vfprintf(stderr, msg, ap);
  va_end(ap);
  fprintf(stderr, "\n");
#ifdef _WIN32
  // On Windows, some tools may inject extra threads.
  // exit() may block on locks held by those threads, so forcibly exit.
  fflush(stderr);
  fflush(stdout);
  ExitProcess(1);
#else
  exit(1);
#endif
}

void Warning(const char* msg, ...) {
  va_list ap;
  fprintf(stderr, "ninja: warning: ");
  va_start(ap, msg);
  vfprintf(stderr, msg, ap);
  va_end(ap);
  fprintf(stderr, "\n");
}

void Error(const char* msg, ...) {
  va_list ap;
  fprintf(stderr, "ninja: error: ");
  va_start(ap, msg);
  vfprintf(stderr, msg, ap);
  va_end(ap);
  fprintf(stderr, "\n");
}

bool CanonicalizePath(string* path, string* err) {
  METRIC_RECORD("canonicalize str");
  int len = path->size();
  char* str = 0;
  if (len > 0)
    str = &(*path)[0];
  if (!CanonicalizePath(str, &len, err))
    return false;
  path->resize(len);
  return true;
}

bool CanonicalizePath(char* path, int* len, string* err) {
  // WARNING: this function is performance-critical; please benchmark
  // any changes you make to it.
  METRIC_RECORD("canonicalize path");
  if (*len == 0) {
    *err = "empty path";
    return false;
  }

  const int kMaxPathComponents = 30;
  char* components[kMaxPathComponents];
  int component_count = 0;

  char* start = path;
  char* dst = start;
  const char* src = start;
  const char* end = start + *len;

  if (*src == '/') {
    ++src;
    ++dst;
  }

  while (src < end) {
    if (*src == '.') {
      if (src + 1 == end || src[1] == '/') {
        // '.' component; eliminate.
        src += 2;
        continue;
      } else if (src[1] == '.' && (src + 2 == end || src[2] == '/')) {
        // '..' component.  Back up if possible.
        if (component_count > 0) {
          dst = components[component_count - 1];
          src += 3;
          --component_count;
        } else {
          *dst++ = *src++;
          *dst++ = *src++;
          *dst++ = *src++;
        }
        continue;
      }
    }

    if (*src == '/') {
      src++;
      continue;
    }

    if (component_count == kMaxPathComponents)
      Fatal("path has too many components");
    components[component_count] = dst;
    ++component_count;

    while (*src != '/' && src != end)
      *dst++ = *src++;
    *dst++ = *src++;  // Copy '/' or final \0 character as well.
  }

  if (dst == start) {
    *err = "path canonicalizes to the empty path";
    return false;
  }

  *len = dst - start - 1;
  return true;
}

int MakeDir(const string& path) {
#ifdef _WIN32
  return _mkdir(path.c_str());
#else
  return mkdir(path.c_str(), 0777);
#endif
}

int ReadFile(const string& path, string* contents, string* err) {
  FILE* f = fopen(path.c_str(), "r");
  if (!f) {
    err->assign(strerror(errno));
    return -errno;
  }

  char buf[64 << 10];
  size_t len;
  while ((len = fread(buf, 1, sizeof(buf), f)) > 0) {
    contents->append(buf, len);
  }
  if (ferror(f)) {
    err->assign(strerror(errno));  // XXX errno?
    contents->clear();
    fclose(f);
    return -errno;
  }
  fclose(f);
  return 0;
}

void SetCloseOnExec(int fd) {
#ifndef _WIN32
  int flags = fcntl(fd, F_GETFD);
  if (flags < 0) {
    perror("fcntl(F_GETFD)");
  } else {
    if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
      perror("fcntl(F_SETFD)");
  }
#else
  HANDLE hd = (HANDLE) _get_osfhandle(fd);
  if (! SetHandleInformation(hd, HANDLE_FLAG_INHERIT, 0)) {
    fprintf(stderr, "SetHandleInformation(): %s", GetLastErrorString().c_str());
  }
#endif  // ! _WIN32
}

const char* SpellcheckStringV(const string& text,
                              const vector<const char*>& words) {
  const bool kAllowReplacements = true;
  const int kMaxValidEditDistance = 3;

  int min_distance = kMaxValidEditDistance + 1;
  const char* result = NULL;
  for (vector<const char*>::const_iterator i = words.begin();
       i != words.end(); ++i) {
    int distance = EditDistance(*i, text, kAllowReplacements,
                                kMaxValidEditDistance);
    if (distance < min_distance) {
      min_distance = distance;
      result = *i;
    }
  }
  return result;
}

const char* SpellcheckString(const string& text, ...) {
  va_list ap;
  va_start(ap, text);
  vector<const char*> words;
  const char* word;
  while ((word = va_arg(ap, const char*)))
    words.push_back(word);
  return SpellcheckStringV(text, words);
}

#ifdef _WIN32
string GetLastErrorString() {
  DWORD err = GetLastError();

  char* msg_buf;
  FormatMessageA(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        err,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (char*)&msg_buf,
        0,
        NULL);
  string msg = msg_buf;
  LocalFree(msg_buf);
  return msg;
}
#endif

static bool islatinalpha(int c) {
  // isalpha() is locale-dependent.
  return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}

string StripAnsiEscapeCodes(const string& in) {
  string stripped;
  stripped.reserve(in.size());

  for (size_t i = 0; i < in.size(); ++i) {
    if (in[i] != '\33') {
      // Not an escape code.
      stripped.push_back(in[i]);
      continue;
    }

    // Only strip CSIs for now.
    if (i + 1 >= in.size()) break;
    if (in[i + 1] != '[') continue;  // Not a CSI.
    i += 2;

    // Skip everything up to and including the next [a-zA-Z].
    while (i < in.size() && !islatinalpha(in[i]))
      ++i;
  }
  return stripped;
}

#ifdef _WIN32
static double GetLoadAverage_win32()
{
  // TODO(nicolas.despres@gmail.com): Find a way to implement it on Windows.
  return -0.0f;
}
#else
static double GetLoadAverage_unix()
{
  double loadavg[3] = { 0.0f, 0.0f, 0.0f };
  if (getloadavg(loadavg, 3) < 0)
  {
    // Maybe we should return an error here or the availability of
    // getloadavg(3) should be checked when ninja is configured.
    return -0.0f;
  }
  return loadavg[0];
}
#endif // _WIN32

double GetLoadAverage()
{
#ifdef _WIN32
  return GetLoadAverage_win32();
#else
  return GetLoadAverage_unix();
#endif // _WIN32
}
<commit_msg>simplify load-average code<commit_after>// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "util.h"

#ifdef _WIN32
#include <windows.h>
#include <io.h>
#endif

#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>

#ifndef _WIN32
#include <sys/time.h>
#endif

#include <vector>

#ifdef _WIN32
#include <direct.h>  // _mkdir
#endif

#include "edit_distance.h"
#include "metrics.h"

void Fatal(const char* msg, ...) {
  va_list ap;
  fprintf(stderr, "ninja: fatal: ");
  va_start(ap, msg);
  vfprintf(stderr, msg, ap);
  va_end(ap);
  fprintf(stderr, "\n");
#ifdef _WIN32
  // On Windows, some tools may inject extra threads.
  // exit() may block on locks held by those threads, so forcibly exit.
  fflush(stderr);
  fflush(stdout);
  ExitProcess(1);
#else
  exit(1);
#endif
}

void Warning(const char* msg, ...) {
  va_list ap;
  fprintf(stderr, "ninja: warning: ");
  va_start(ap, msg);
  vfprintf(stderr, msg, ap);
  va_end(ap);
  fprintf(stderr, "\n");
}

void Error(const char* msg, ...) {
  va_list ap;
  fprintf(stderr, "ninja: error: ");
  va_start(ap, msg);
  vfprintf(stderr, msg, ap);
  va_end(ap);
  fprintf(stderr, "\n");
}

bool CanonicalizePath(string* path, string* err) {
  METRIC_RECORD("canonicalize str");
  int len = path->size();
  char* str = 0;
  if (len > 0)
    str = &(*path)[0];
  if (!CanonicalizePath(str, &len, err))
    return false;
  path->resize(len);
  return true;
}

bool CanonicalizePath(char* path, int* len, string* err) {
  // WARNING: this function is performance-critical; please benchmark
  // any changes you make to it.
  METRIC_RECORD("canonicalize path");
  if (*len == 0) {
    *err = "empty path";
    return false;
  }

  const int kMaxPathComponents = 30;
  char* components[kMaxPathComponents];
  int component_count = 0;

  char* start = path;
  char* dst = start;
  const char* src = start;
  const char* end = start + *len;

  if (*src == '/') {
    ++src;
    ++dst;
  }

  while (src < end) {
    if (*src == '.') {
      if (src + 1 == end || src[1] == '/') {
        // '.' component; eliminate.
        src += 2;
        continue;
      } else if (src[1] == '.' && (src + 2 == end || src[2] == '/')) {
        // '..' component.  Back up if possible.
        if (component_count > 0) {
          dst = components[component_count - 1];
          src += 3;
          --component_count;
        } else {
          *dst++ = *src++;
          *dst++ = *src++;
          *dst++ = *src++;
        }
        continue;
      }
    }

    if (*src == '/') {
      src++;
      continue;
    }

    if (component_count == kMaxPathComponents)
      Fatal("path has too many components");
    components[component_count] = dst;
    ++component_count;

    while (*src != '/' && src != end)
      *dst++ = *src++;
    *dst++ = *src++;  // Copy '/' or final \0 character as well.
  }

  if (dst == start) {
    *err = "path canonicalizes to the empty path";
    return false;
  }

  *len = dst - start - 1;
  return true;
}

int MakeDir(const string& path) {
#ifdef _WIN32
  return _mkdir(path.c_str());
#else
  return mkdir(path.c_str(), 0777);
#endif
}

int ReadFile(const string& path, string* contents, string* err) {
  FILE* f = fopen(path.c_str(), "r");
  if (!f) {
    err->assign(strerror(errno));
    return -errno;
  }

  char buf[64 << 10];
  size_t len;
  while ((len = fread(buf, 1, sizeof(buf), f)) > 0) {
    contents->append(buf, len);
  }
  if (ferror(f)) {
    err->assign(strerror(errno));  // XXX errno?
    contents->clear();
    fclose(f);
    return -errno;
  }
  fclose(f);
  return 0;
}

void SetCloseOnExec(int fd) {
#ifndef _WIN32
  int flags = fcntl(fd, F_GETFD);
  if (flags < 0) {
    perror("fcntl(F_GETFD)");
  } else {
    if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
      perror("fcntl(F_SETFD)");
  }
#else
  HANDLE hd = (HANDLE) _get_osfhandle(fd);
  if (! SetHandleInformation(hd, HANDLE_FLAG_INHERIT, 0)) {
    fprintf(stderr, "SetHandleInformation(): %s", GetLastErrorString().c_str());
  }
#endif  // ! _WIN32
}

const char* SpellcheckStringV(const string& text,
                              const vector<const char*>& words) {
  const bool kAllowReplacements = true;
  const int kMaxValidEditDistance = 3;

  int min_distance = kMaxValidEditDistance + 1;
  const char* result = NULL;
  for (vector<const char*>::const_iterator i = words.begin();
       i != words.end(); ++i) {
    int distance = EditDistance(*i, text, kAllowReplacements,
                                kMaxValidEditDistance);
    if (distance < min_distance) {
      min_distance = distance;
      result = *i;
    }
  }
  return result;
}

const char* SpellcheckString(const string& text, ...) {
  va_list ap;
  va_start(ap, text);
  vector<const char*> words;
  const char* word;
  while ((word = va_arg(ap, const char*)))
    words.push_back(word);
  return SpellcheckStringV(text, words);
}

#ifdef _WIN32
string GetLastErrorString() {
  DWORD err = GetLastError();

  char* msg_buf;
  FormatMessageA(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        err,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (char*)&msg_buf,
        0,
        NULL);
  string msg = msg_buf;
  LocalFree(msg_buf);
  return msg;
}
#endif

static bool islatinalpha(int c) {
  // isalpha() is locale-dependent.
  return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}

string StripAnsiEscapeCodes(const string& in) {
  string stripped;
  stripped.reserve(in.size());

  for (size_t i = 0; i < in.size(); ++i) {
    if (in[i] != '\33') {
      // Not an escape code.
      stripped.push_back(in[i]);
      continue;
    }

    // Only strip CSIs for now.
    if (i + 1 >= in.size()) break;
    if (in[i + 1] != '[') continue;  // Not a CSI.
    i += 2;

    // Skip everything up to and including the next [a-zA-Z].
    while (i < in.size() && !islatinalpha(in[i]))
      ++i;
  }
  return stripped;
}

#ifdef _WIN32
double GetLoadAverage() {
  // TODO(nicolas.despres@gmail.com): Find a way to implement it on Windows.
  return -0.0f;
}
#else
double GetLoadAverage() {
  double loadavg[3] = { 0.0f, 0.0f, 0.0f };
  if (getloadavg(loadavg, 3) < 0) {
    // Maybe we should return an error here or the availability of
    // getloadavg(3) should be checked when ninja is configured.
    return -0.0f;
  }
  return loadavg[0];
}
#endif // _WIN32
<|endoftext|>


<commit_before>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

#include "OSDMap.h"

#include "config.h"

void OSDMap::print(ostream& out)
{
  out << "epoch " << get_epoch() << "\n"
      << "fsid " << get_fsid() << "\n"
      << "created " << get_created() << "\n"
      << "modifed " << get_modified() << "\n"
      << std::endl;
  for (map<int,pg_pool_t>::iterator p = pools.begin(); p != pools.end(); p++) {
    out << "pg_pool " << p->first
	<< " '" << pool_name[p->first]
	<< "' " << p->second << "\n";
    for (map<snapid_t,pool_snap_info_t>::iterator q = p->second.snaps.begin();
	 q != p->second.snaps.end();
	 q++)
      out << "\tsnap " << q->second.snapid << " '" << q->second.name << "' " << q->second.stamp << "\n";
    if (!p->second.removed_snaps.empty())
      out << "\tremoved_snaps " << p->second.removed_snaps << "\n";
  }
  out << std::endl;

  out << "max_osd " << get_max_osd() << "\n";
  for (int i=0; i<get_max_osd(); i++) {
    if (exists(i)) {
      out << "osd" << i;
      out << (is_in(i) ? " in":" out");
      if (is_in(i))
	out << " weight " << get_weightf(i);
      out << (is_up(i) ? " up  ":" down");
      osd_info_t& info = get_info(i);
      out << " (up_from " << info.up_from
	  << " up_thru " << info.up_thru
	  << " down_at " << info.down_at
	  << " last_clean " << info.last_clean_first << "-" << info.last_clean_last << ")";
      if (is_up(i))
	out << " " << get_addr(i) << " " << get_hb_addr(i);
      out << "\n";
    }
  }
  out << std::endl;

  for (map<pg_t,vector<int> >::iterator p = pg_temp.begin();
       p != pg_temp.end();
       p++)
    out << "pg_temp " << p->first << " " << p->second << "\n";

  for (hash_map<entity_addr_t,utime_t>::iterator p = blacklist.begin();
       p != blacklist.end();
       p++)
    out << "blacklist " << p->first << " expires " << p->second << "\n";

  // ignore pg_swap_primary
}

void OSDMap::print_summary(ostream& out)
{
  out << "e" << get_epoch() << ": "
      << get_num_osds() << " osds: "
      << get_num_up_osds() << " up, "
      << get_num_in_osds() << " in";
  if (blacklist.size())
    out << " -- " << blacklist.size() << " blacklisted MDSes";
}

void OSDMap::build_simple(epoch_t e, ceph_fsid_t &fsid,
			  int num_osd, int num_dom, int pg_bits, int lpg_bits,
			  int mds_local_osd)
{
  dout(10) << "build_simple on " << num_osd
	   << " osds with " << pg_bits << " pg bits per osd, "
	   << lpg_bits << " lpg bits" << dendl;
  epoch = e;
  set_fsid(fsid);
  created = modified = g_clock.now();

  set_max_osd(num_osd);

  // crush map
  map<int, const char*> rulesets;
  rulesets[CEPH_DATA_RULE] = "data";
  rulesets[CEPH_METADATA_RULE] = "metadata";
  rulesets[CEPH_CASDATA_RULE] = "casdata";
  rulesets[CEPH_RBD_RULE] = "rbd";

  for (map<int,const char*>::iterator p = rulesets.begin(); p != rulesets.end(); p++) {
    int pool = ++pool_max;
    pools[pool].v.type = CEPH_PG_TYPE_REP;
    pools[pool].v.size = 2;
    pools[pool].v.crush_ruleset = p->first;
    pools[pool].v.object_hash = CEPH_STR_HASH_RJENKINS;
    pools[pool].v.pg_num = num_osd << pg_bits;
    pools[pool].v.pgp_num = num_osd << pg_bits;
    pools[pool].v.lpg_num = lpg_bits ? (1 << (lpg_bits-1)) : 0;
    pools[pool].v.lpgp_num = lpg_bits ? (1 << (lpg_bits-1)) : 0;
    pools[pool].v.last_change = epoch;
    pool_name[pool] = p->second;
  }

  build_simple_crush_map(crush, rulesets, num_osd, num_dom);

  for (int i=0; i<num_osd; i++) {
    set_state(i, 0);
    set_weight(i, CEPH_OSD_OUT);
  }

  if (mds_local_osd) {
    set_max_osd(mds_local_osd+num_osd);

    // add mds local osds, but don't put them in the crush mapping func
    for (int i=0; i<mds_local_osd; i++) {
      set_state(i+num_osd, 0);
      set_weight(i+num_osd, CEPH_OSD_OUT);
    }
  }
}

void OSDMap::build_simple_crush_map(CrushWrapper& crush, map<int, const char*>& rulesets, int num_osd,
				    int num_dom)
{
  // new
  crush.create();

  crush.set_type_name(1, "domain");
  crush.set_type_name(2, "pool");

  int minrep = g_conf.osd_min_rep;
  int ndom = num_dom;
  if (!ndom)
    ndom = MAX(g_conf.osd_max_rep, g_conf.osd_max_raid_width);
  if (ndom > 1 &&
      num_osd >= ndom*3 &&
      num_osd > 8) {
    int ritems[ndom];
    int rweights[ndom];

    int nper = ((num_osd - 1) / ndom) + 1;
    derr(0) << ndom << " failure domains, " << nper << " osds each" << dendl;

    int o = 0;
    for (int i=0; i<ndom; i++) {
      int items[nper], weights[nper];
      int j;
      rweights[i] = 0;
      for (j=0; j<nper; j++, o++) {
	if (o == num_osd) break;
	dout(20) << "added osd" << o << dendl;
	items[j] = o;
	weights[j] = 0x10000;
	//w[j] = weights[o] ? (0x10000 - (int)(weights[o] * 0x10000)):0x10000;
	//rweights[i] += w[j];
	rweights[i] += 0x10000;
      }

      crush_bucket *domain = crush_make_bucket(CRUSH_BUCKET_UNIFORM, CRUSH_HASH_DEFAULT, 1, j, items, weights);
      ritems[i] = crush_add_bucket(crush.crush, 0, domain);
      dout(20) << "added domain bucket i " << ritems[i] << " of size " << j << dendl;

      char bname[10];
      snprintf(bname, sizeof(bname), "dom%d", i);
      crush.set_item_name(ritems[i], bname);
    }

    // root
    crush_bucket *root = crush_make_bucket(CRUSH_BUCKET_STRAW, CRUSH_HASH_DEFAULT, 2, ndom, ritems, rweights);
    int rootid = crush_add_bucket(crush.crush, 0, root);
    crush.set_item_name(rootid, "root");

    // rules
    for (map<int,const char*>::iterator p = rulesets.begin(); p != rulesets.end(); p++) {
      int ruleset = p->first;
      crush_rule *rule = crush_make_rule(3, ruleset, CEPH_PG_TYPE_REP, minrep, g_conf.osd_max_rep);
      crush_rule_set_step(rule, 0, CRUSH_RULE_TAKE, rootid, 0);
      crush_rule_set_step(rule, 1, CRUSH_RULE_CHOOSE_LEAF_FIRSTN, CRUSH_CHOOSE_N, 1); // choose N domains
      crush_rule_set_step(rule, 2, CRUSH_RULE_EMIT, 0, 0);
      int rno = crush_add_rule(crush.crush, rule, -1);
      crush.set_rule_name(rno, p->second);
    }

  } else {
    // one bucket

    int items[num_osd];
    int weights[num_osd];
    for (int i=0; i<num_osd; i++) {
      items[i] = i;
      weights[i] = 0x10000;
    }

    crush_bucket *b = crush_make_bucket(CRUSH_BUCKET_STRAW, CRUSH_HASH_DEFAULT, 1, num_osd, items, weights);
    int rootid = crush_add_bucket(crush.crush, 0, b);
    crush.set_item_name(rootid, "root");

    // replication
    for (map<int,const char*>::iterator p = rulesets.begin(); p != rulesets.end(); p++) {
      int ruleset = p->first;
      crush_rule *rule = crush_make_rule(3, ruleset, CEPH_PG_TYPE_REP, g_conf.osd_min_rep, g_conf.osd_max_rep);
      crush_rule_set_step(rule, 0, CRUSH_RULE_TAKE, rootid, 0);
      crush_rule_set_step(rule, 1, CRUSH_RULE_CHOOSE_FIRSTN, CRUSH_CHOOSE_N, 0);
      crush_rule_set_step(rule, 2, CRUSH_RULE_EMIT, 0, 0);
      int rno = crush_add_rule(crush.crush, rule, -1);
      crush.set_rule_name(rno, p->second);
    }

  }

  crush.finalize();

  dout(20) << "crush max_devices " << crush.crush->max_devices << dendl;
}

<commit_msg>osdmap: assert maxrep >= minrep<commit_after>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

#include "OSDMap.h"

#include "config.h"

void OSDMap::print(ostream& out)
{
  out << "epoch " << get_epoch() << "\n"
      << "fsid " << get_fsid() << "\n"
      << "created " << get_created() << "\n"
      << "modifed " << get_modified() << "\n"
      << std::endl;
  for (map<int,pg_pool_t>::iterator p = pools.begin(); p != pools.end(); p++) {
    out << "pg_pool " << p->first
	<< " '" << pool_name[p->first]
	<< "' " << p->second << "\n";
    for (map<snapid_t,pool_snap_info_t>::iterator q = p->second.snaps.begin();
	 q != p->second.snaps.end();
	 q++)
      out << "\tsnap " << q->second.snapid << " '" << q->second.name << "' " << q->second.stamp << "\n";
    if (!p->second.removed_snaps.empty())
      out << "\tremoved_snaps " << p->second.removed_snaps << "\n";
  }
  out << std::endl;

  out << "max_osd " << get_max_osd() << "\n";
  for (int i=0; i<get_max_osd(); i++) {
    if (exists(i)) {
      out << "osd" << i;
      out << (is_in(i) ? " in":" out");
      if (is_in(i))
	out << " weight " << get_weightf(i);
      out << (is_up(i) ? " up  ":" down");
      osd_info_t& info = get_info(i);
      out << " (up_from " << info.up_from
	  << " up_thru " << info.up_thru
	  << " down_at " << info.down_at
	  << " last_clean " << info.last_clean_first << "-" << info.last_clean_last << ")";
      if (is_up(i))
	out << " " << get_addr(i) << " " << get_hb_addr(i);
      out << "\n";
    }
  }
  out << std::endl;

  for (map<pg_t,vector<int> >::iterator p = pg_temp.begin();
       p != pg_temp.end();
       p++)
    out << "pg_temp " << p->first << " " << p->second << "\n";

  for (hash_map<entity_addr_t,utime_t>::iterator p = blacklist.begin();
       p != blacklist.end();
       p++)
    out << "blacklist " << p->first << " expires " << p->second << "\n";

  // ignore pg_swap_primary
}

void OSDMap::print_summary(ostream& out)
{
  out << "e" << get_epoch() << ": "
      << get_num_osds() << " osds: "
      << get_num_up_osds() << " up, "
      << get_num_in_osds() << " in";
  if (blacklist.size())
    out << " -- " << blacklist.size() << " blacklisted MDSes";
}

void OSDMap::build_simple(epoch_t e, ceph_fsid_t &fsid,
			  int num_osd, int num_dom, int pg_bits, int lpg_bits,
			  int mds_local_osd)
{
  dout(10) << "build_simple on " << num_osd
	   << " osds with " << pg_bits << " pg bits per osd, "
	   << lpg_bits << " lpg bits" << dendl;
  epoch = e;
  set_fsid(fsid);
  created = modified = g_clock.now();

  set_max_osd(num_osd);

  // crush map
  map<int, const char*> rulesets;
  rulesets[CEPH_DATA_RULE] = "data";
  rulesets[CEPH_METADATA_RULE] = "metadata";
  rulesets[CEPH_CASDATA_RULE] = "casdata";
  rulesets[CEPH_RBD_RULE] = "rbd";

  for (map<int,const char*>::iterator p = rulesets.begin(); p != rulesets.end(); p++) {
    int pool = ++pool_max;
    pools[pool].v.type = CEPH_PG_TYPE_REP;
    pools[pool].v.size = 2;
    pools[pool].v.crush_ruleset = p->first;
    pools[pool].v.object_hash = CEPH_STR_HASH_RJENKINS;
    pools[pool].v.pg_num = num_osd << pg_bits;
    pools[pool].v.pgp_num = num_osd << pg_bits;
    pools[pool].v.lpg_num = lpg_bits ? (1 << (lpg_bits-1)) : 0;
    pools[pool].v.lpgp_num = lpg_bits ? (1 << (lpg_bits-1)) : 0;
    pools[pool].v.last_change = epoch;
    pool_name[pool] = p->second;
  }

  build_simple_crush_map(crush, rulesets, num_osd, num_dom);

  for (int i=0; i<num_osd; i++) {
    set_state(i, 0);
    set_weight(i, CEPH_OSD_OUT);
  }

  if (mds_local_osd) {
    set_max_osd(mds_local_osd+num_osd);

    // add mds local osds, but don't put them in the crush mapping func
    for (int i=0; i<mds_local_osd; i++) {
      set_state(i+num_osd, 0);
      set_weight(i+num_osd, CEPH_OSD_OUT);
    }
  }
}

void OSDMap::build_simple_crush_map(CrushWrapper& crush, map<int, const char*>& rulesets, int num_osd,
				    int num_dom)
{
  // new
  crush.create();

  crush.set_type_name(1, "domain");
  crush.set_type_name(2, "pool");

  int minrep = g_conf.osd_min_rep;
  int maxrep = g_conf.osd_max_rep;
  assert(maxrep >= minrep);
  int ndom = num_dom;
  if (!ndom)
    ndom = MAX(maxrep, g_conf.osd_max_raid_width);
  if (ndom > 1 &&
      num_osd >= ndom*3 &&
      num_osd > 8) {
    int ritems[ndom];
    int rweights[ndom];

    int nper = ((num_osd - 1) / ndom) + 1;
    derr(0) << ndom << " failure domains, " << nper << " osds each" << dendl;

    int o = 0;
    for (int i=0; i<ndom; i++) {
      int items[nper], weights[nper];
      int j;
      rweights[i] = 0;
      for (j=0; j<nper; j++, o++) {
	if (o == num_osd) break;
	dout(20) << "added osd" << o << dendl;
	items[j] = o;
	weights[j] = 0x10000;
	//w[j] = weights[o] ? (0x10000 - (int)(weights[o] * 0x10000)):0x10000;
	//rweights[i] += w[j];
	rweights[i] += 0x10000;
      }

      crush_bucket *domain = crush_make_bucket(CRUSH_BUCKET_UNIFORM, CRUSH_HASH_DEFAULT, 1, j, items, weights);
      ritems[i] = crush_add_bucket(crush.crush, 0, domain);
      dout(20) << "added domain bucket i " << ritems[i] << " of size " << j << dendl;

      char bname[10];
      snprintf(bname, sizeof(bname), "dom%d", i);
      crush.set_item_name(ritems[i], bname);
    }

    // root
    crush_bucket *root = crush_make_bucket(CRUSH_BUCKET_STRAW, CRUSH_HASH_DEFAULT, 2, ndom, ritems, rweights);
    int rootid = crush_add_bucket(crush.crush, 0, root);
    crush.set_item_name(rootid, "root");

    // rules
    for (map<int,const char*>::iterator p = rulesets.begin(); p != rulesets.end(); p++) {
      int ruleset = p->first;
      crush_rule *rule = crush_make_rule(3, ruleset, CEPH_PG_TYPE_REP, minrep, maxrep);
      crush_rule_set_step(rule, 0, CRUSH_RULE_TAKE, rootid, 0);
      crush_rule_set_step(rule, 1, CRUSH_RULE_CHOOSE_LEAF_FIRSTN, CRUSH_CHOOSE_N, 1); // choose N domains
      crush_rule_set_step(rule, 2, CRUSH_RULE_EMIT, 0, 0);
      int rno = crush_add_rule(crush.crush, rule, -1);
      crush.set_rule_name(rno, p->second);
    }

  } else {
    // one bucket

    int items[num_osd];
    int weights[num_osd];
    for (int i=0; i<num_osd; i++) {
      items[i] = i;
      weights[i] = 0x10000;
    }

    crush_bucket *b = crush_make_bucket(CRUSH_BUCKET_STRAW, CRUSH_HASH_DEFAULT, 1, num_osd, items, weights);
    int rootid = crush_add_bucket(crush.crush, 0, b);
    crush.set_item_name(rootid, "root");

    // replication
    for (map<int,const char*>::iterator p = rulesets.begin(); p != rulesets.end(); p++) {
      int ruleset = p->first;
      crush_rule *rule = crush_make_rule(3, ruleset, CEPH_PG_TYPE_REP, g_conf.osd_min_rep, maxrep);
      crush_rule_set_step(rule, 0, CRUSH_RULE_TAKE, rootid, 0);
      crush_rule_set_step(rule, 1, CRUSH_RULE_CHOOSE_FIRSTN, CRUSH_CHOOSE_N, 0);
      crush_rule_set_step(rule, 2, CRUSH_RULE_EMIT, 0, 0);
      int rno = crush_add_rule(crush.crush, rule, -1);
      crush.set_rule_name(rno, p->second);
    }

  }

  crush.finalize();

  dout(20) << "crush max_devices " << crush.crush->max_devices << dendl;
}

<|endoftext|>


<commit_before>#ifndef BOP_VECTOR_HPP
#define BOP_VECTOR_HPP

#include <initializer_list>
#include <string>

/*
	bop::maths::Vector forward declaration file
*/

namespace bop::maths {

	template<class T>
	class Vector {
		protected:
			int width;
			int pivot_index;
		public:
			T* data;
			//Constructors
			Vector(int, T);
			Vector(int, int, T);
			Vector(std::initializer_list<T>);
			Vector();
			//Operator Overloads
			T& operator[] (const unsigned int);
			Vector<T>& operator= (const Vector<T>&);
			Vector<T>& operator= (std::initializer_list<T>);
			//Arithmetic Operator Overloads
			Vector<T>& operator*= (const T);
			Vector<T>& operator/= (const T);
			Vector<T>& operator+= (Vector<T>&);
			Vector<T>& operator-= (Vector<T>&);
			//Vector information functions
			int pivot(int);
			unsigned int size();
			std::string string();
			T& x();
			T& y();
			T& z();
	};

}

#endif<commit_msg>More vector maths operators<commit_after>#ifndef BOP_VECTOR_HPP
#define BOP_VECTOR_HPP

#include <initializer_list>
#include <string>

/*
	bop::maths::Vector forward declaration file
*/

namespace bop::maths {

	template<class T>
	class Vector {
		protected:
			int width;
			int pivot_index;
		public:
			T* data;
			//Constructors
			Vector(int, T);
			Vector(int, int, T);
			Vector(std::initializer_list<T>);
			Vector();
			//Operator Overloads
			T& operator[] (const unsigned int);
			Vector<T>& operator= (const Vector<T>&);
			Vector<T>& operator= (std::initializer_list<T>);
			//Arithmetic Operator Overloads
			Vector<T>& operator*= (const T);
			Vector<T>& operator/= (const T);
			Vector<T>& operator+= (Vector<T>&);
			Vector<T>& operator-= (Vector<T>&);
			//Vector information functions
			int pivot(int);
			unsigned int size();
			std::string string();
			T& x();
			T& y();
			T& z();
	};

	template<class T>
	Vector<T> operator* (Vector<T>, const T);
	template<class T>
	Vector<T> operator/ (Vector<T>, const T);
	template<class T>
	Vector<T> operator+ (Vector<T>, Vector<T>&);
	template<class T>
	Vector<T> operator- (Vector<T>, Vector<T>&);

}

#endif<|endoftext|>


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

#include "webkit/glue/plugins/pepper_scrollbar.h"

#include "base/logging.h"
#include "base/message_loop.h"
#include "third_party/ppapi/c/ppp_scrollbar.h"
#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
#include "third_party/WebKit/WebKit/chromium/public/WebRect.h"
#include "third_party/WebKit/WebKit/chromium/public/WebScrollbar.h"
#include "third_party/WebKit/WebKit/chromium/public/WebVector.h"
#include "webkit/glue/plugins/pepper_event_conversion.h"
#include "webkit/glue/plugins/pepper_image_data.h"
#include "webkit/glue/plugins/pepper_plugin_instance.h"
#include "webkit/glue/plugins/pepper_plugin_module.h"
#include "webkit/glue/webkit_glue.h"

using WebKit::WebInputEvent;
using WebKit::WebRect;
using WebKit::WebScrollbar;

namespace pepper {

namespace {

PP_Resource Create(PP_Instance instance_id, bool vertical) {
  PluginInstance* instance = PluginInstance::FromPPInstance(instance_id);
  if (!instance)
    return 0;

  scoped_refptr<Scrollbar> scrollbar(new Scrollbar(instance, vertical));
  return scrollbar->GetReference();
}

bool IsScrollbar(PP_Resource resource) {
  return !!Resource::GetAs<Scrollbar>(resource);
}

uint32_t GetThickness() {
  return WebScrollbar::defaultThickness();
}

uint32_t GetValue(PP_Resource resource) {
  scoped_refptr<Scrollbar> scrollbar(Resource::GetAs<Scrollbar>(resource));
  if (!scrollbar)
    return 0;
  return scrollbar->GetValue();
}

void SetValue(PP_Resource resource, uint32_t value) {
  scoped_refptr<Scrollbar> scrollbar(Resource::GetAs<Scrollbar>(resource));
  if (scrollbar)
    scrollbar->SetValue(value);
}

void SetDocumentSize(PP_Resource resource, uint32_t size) {
  scoped_refptr<Scrollbar> scrollbar(Resource::GetAs<Scrollbar>(resource));
  if (scrollbar)
    scrollbar->SetDocumentSize(size);
}

void SetTickMarks(PP_Resource resource,
                  const PP_Rect* tick_marks,
                  uint32_t count) {
  scoped_refptr<Scrollbar> scrollbar(Resource::GetAs<Scrollbar>(resource));
  if (scrollbar)
    scrollbar->SetTickMarks(tick_marks, count);
}

void ScrollBy(PP_Resource resource,
              PP_ScrollBy unit,
              int32_t multiplier) {
  scoped_refptr<Scrollbar> scrollbar(Resource::GetAs<Scrollbar>(resource));
  if (scrollbar)
    scrollbar->ScrollBy(unit, multiplier);
}

const PPB_Scrollbar ppb_scrollbar = {
  &Create,
  &IsScrollbar,
  &GetThickness,
  &GetValue,
  &SetValue,
  &SetDocumentSize,
  &SetTickMarks,
  &ScrollBy
};

}  // namespace

Scrollbar::Scrollbar(PluginInstance* instance, bool vertical)
    : Widget(instance) {
  scrollbar_.reset(WebScrollbar::create(
      static_cast<WebKit::WebScrollbarClient*>(this),
      vertical ? WebScrollbar::Vertical : WebScrollbar::Horizontal));
}

Scrollbar::~Scrollbar() {
}

// static
const PPB_Scrollbar* Scrollbar::GetInterface() {
  return &ppb_scrollbar;
}

uint32_t Scrollbar::GetValue() {
  return scrollbar_->value();
}

void Scrollbar::SetValue(uint32_t value) {
  scrollbar_->setValue(value);
}

void Scrollbar::SetDocumentSize(uint32_t size) {
  scrollbar_->setDocumentSize(size);
}

void Scrollbar::SetTickMarks(const PP_Rect* tick_marks, uint32_t count) {
  tickmarks_.resize(count);
  for (uint32 i = 0; i < count; ++i) {
    tickmarks_[i] = WebRect(tick_marks[i].point.x,
                            tick_marks[i].point.y,
                            tick_marks[i].size.width,
                            tick_marks[i].size.height);;
  }
  PP_Rect rect = location();
  Invalidate(&rect);
}

void Scrollbar::ScrollBy(PP_ScrollBy unit, int32_t multiplier) {
  WebScrollbar::ScrollDirection direction = multiplier >= 0 ?
      WebScrollbar::ScrollForward : WebScrollbar::ScrollBackward;
  float fmultiplier = 1.0;

  WebScrollbar::ScrollGranularity granularity;
  if (unit == PP_SCROLLBY_LINE) {
    granularity = WebScrollbar::ScrollByLine;
  } else if (unit == PP_SCROLLBY_PAGE) {
    granularity = WebScrollbar::ScrollByPage;
  } else if (unit == PP_SCROLLBY_DOCUMENT) {
    granularity = WebScrollbar::ScrollByDocument;
  } else {
    granularity = WebScrollbar::ScrollByPixel;
    fmultiplier = static_cast<float>(multiplier);
    if (fmultiplier < 0)
      fmultiplier *= -1;
  }
  scrollbar_->scroll(direction, granularity, fmultiplier);
}

bool Scrollbar::Paint(const PP_Rect* rect, ImageData* image) {
  gfx::Rect gfx_rect(rect->point.x,
                     rect->point.y,
                     rect->size.width,
                     rect->size.height);
  skia::PlatformCanvas* canvas = image->mapped_canvas();
  if (!canvas)
    return false;
  scrollbar_->paint(webkit_glue::ToWebCanvas(canvas), gfx_rect);
  return true;
}

bool Scrollbar::HandleEvent(const PP_Event* event) {
  scoped_ptr<WebInputEvent> web_input_event(CreateWebInputEvent(*event));
  if (!web_input_event.get())
    return false;

  return scrollbar_->handleInputEvent(*web_input_event.get());
}

void Scrollbar::SetLocationInternal(const PP_Rect* location) {
  scrollbar_->setLocation(WebRect(location->point.x,
                                  location->point.y,
                                  location->size.width,
                                  location->size.height));
}

void Scrollbar::valueChanged(WebKit::WebScrollbar* scrollbar) {
  const PPP_Scrollbar* ppp_scrollbar = static_cast<const PPP_Scrollbar*>(
      module()->GetPluginInterface(PPP_SCROLLBAR_INTERFACE));
  if (!ppp_scrollbar)
    return;
  ScopedResourceId resource(this);
  ppp_scrollbar->ValueChanged(
      instance()->GetPPInstance(), resource.id, scrollbar_->value());
}

void Scrollbar::invalidateScrollbarRect(WebKit::WebScrollbar* scrollbar,
                                        const WebKit::WebRect& rect) {
  gfx::Rect gfx_rect(rect.x,
                     rect.y,
                     rect.width,
                     rect.height);
  dirty_ = dirty_.Union(gfx_rect);
  // Can't call into the client to tell them about the invalidate right away,
  // since the Scrollbar code is still in the middle of updating its internal
  // state.
  MessageLoop::current()->PostTask(
      FROM_HERE,
      NewRunnableMethod(this, &Scrollbar::NotifyInvalidate));
}

void Scrollbar::getTickmarks(
    WebKit::WebScrollbar* scrollbar,
    WebKit::WebVector<WebKit::WebRect>* tick_marks) const {
  if (tickmarks_.empty()) {
    WebRect* rects = NULL;
    tick_marks->assign(rects, 0);
  } else {
    tick_marks->assign(&tickmarks_[0], tickmarks_.size());
  }
}

void Scrollbar::NotifyInvalidate() {
  if (dirty_.IsEmpty())
    return;
  PP_Rect pp_rect;
  pp_rect.point.x = dirty_.x();
  pp_rect.point.y = dirty_.y();
  pp_rect.size.width = dirty_.width();
  pp_rect.size.height = dirty_.height();
  dirty_ = gfx::Rect();
  Invalidate(&pp_rect);
}

}  // namespace pepper
<commit_msg>Fix strange colors on scrollbars when using classic theme on XP. This is a port of the fix from pepper v1 to pepper v2.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "webkit/glue/plugins/pepper_scrollbar.h"

#include "base/logging.h"
#include "base/message_loop.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/ppapi/c/ppp_scrollbar.h"
#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
#include "third_party/WebKit/WebKit/chromium/public/WebRect.h"
#include "third_party/WebKit/WebKit/chromium/public/WebScrollbar.h"
#include "third_party/WebKit/WebKit/chromium/public/WebVector.h"
#include "webkit/glue/plugins/pepper_event_conversion.h"
#include "webkit/glue/plugins/pepper_image_data.h"
#include "webkit/glue/plugins/pepper_plugin_instance.h"
#include "webkit/glue/plugins/pepper_plugin_module.h"
#include "webkit/glue/webkit_glue.h"

#if defined(OS_WIN)
#include "base/win_util.h"
#endif

using WebKit::WebInputEvent;
using WebKit::WebRect;
using WebKit::WebScrollbar;

namespace pepper {

namespace {

PP_Resource Create(PP_Instance instance_id, bool vertical) {
  PluginInstance* instance = PluginInstance::FromPPInstance(instance_id);
  if (!instance)
    return 0;

  scoped_refptr<Scrollbar> scrollbar(new Scrollbar(instance, vertical));
  return scrollbar->GetReference();
}

bool IsScrollbar(PP_Resource resource) {
  return !!Resource::GetAs<Scrollbar>(resource);
}

uint32_t GetThickness() {
  return WebScrollbar::defaultThickness();
}

uint32_t GetValue(PP_Resource resource) {
  scoped_refptr<Scrollbar> scrollbar(Resource::GetAs<Scrollbar>(resource));
  if (!scrollbar)
    return 0;
  return scrollbar->GetValue();
}

void SetValue(PP_Resource resource, uint32_t value) {
  scoped_refptr<Scrollbar> scrollbar(Resource::GetAs<Scrollbar>(resource));
  if (scrollbar)
    scrollbar->SetValue(value);
}

void SetDocumentSize(PP_Resource resource, uint32_t size) {
  scoped_refptr<Scrollbar> scrollbar(Resource::GetAs<Scrollbar>(resource));
  if (scrollbar)
    scrollbar->SetDocumentSize(size);
}

void SetTickMarks(PP_Resource resource,
                  const PP_Rect* tick_marks,
                  uint32_t count) {
  scoped_refptr<Scrollbar> scrollbar(Resource::GetAs<Scrollbar>(resource));
  if (scrollbar)
    scrollbar->SetTickMarks(tick_marks, count);
}

void ScrollBy(PP_Resource resource,
              PP_ScrollBy unit,
              int32_t multiplier) {
  scoped_refptr<Scrollbar> scrollbar(Resource::GetAs<Scrollbar>(resource));
  if (scrollbar)
    scrollbar->ScrollBy(unit, multiplier);
}

const PPB_Scrollbar ppb_scrollbar = {
  &Create,
  &IsScrollbar,
  &GetThickness,
  &GetValue,
  &SetValue,
  &SetDocumentSize,
  &SetTickMarks,
  &ScrollBy
};

}  // namespace

Scrollbar::Scrollbar(PluginInstance* instance, bool vertical)
    : Widget(instance) {
  scrollbar_.reset(WebScrollbar::create(
      static_cast<WebKit::WebScrollbarClient*>(this),
      vertical ? WebScrollbar::Vertical : WebScrollbar::Horizontal));
}

Scrollbar::~Scrollbar() {
}

// static
const PPB_Scrollbar* Scrollbar::GetInterface() {
  return &ppb_scrollbar;
}

uint32_t Scrollbar::GetValue() {
  return scrollbar_->value();
}

void Scrollbar::SetValue(uint32_t value) {
  scrollbar_->setValue(value);
}

void Scrollbar::SetDocumentSize(uint32_t size) {
  scrollbar_->setDocumentSize(size);
}

void Scrollbar::SetTickMarks(const PP_Rect* tick_marks, uint32_t count) {
  tickmarks_.resize(count);
  for (uint32 i = 0; i < count; ++i) {
    tickmarks_[i] = WebRect(tick_marks[i].point.x,
                            tick_marks[i].point.y,
                            tick_marks[i].size.width,
                            tick_marks[i].size.height);;
  }
  PP_Rect rect = location();
  Invalidate(&rect);
}

void Scrollbar::ScrollBy(PP_ScrollBy unit, int32_t multiplier) {
  WebScrollbar::ScrollDirection direction = multiplier >= 0 ?
      WebScrollbar::ScrollForward : WebScrollbar::ScrollBackward;
  float fmultiplier = 1.0;

  WebScrollbar::ScrollGranularity granularity;
  if (unit == PP_SCROLLBY_LINE) {
    granularity = WebScrollbar::ScrollByLine;
  } else if (unit == PP_SCROLLBY_PAGE) {
    granularity = WebScrollbar::ScrollByPage;
  } else if (unit == PP_SCROLLBY_DOCUMENT) {
    granularity = WebScrollbar::ScrollByDocument;
  } else {
    granularity = WebScrollbar::ScrollByPixel;
    fmultiplier = static_cast<float>(multiplier);
    if (fmultiplier < 0)
      fmultiplier *= -1;
  }
  scrollbar_->scroll(direction, granularity, fmultiplier);
}

bool Scrollbar::Paint(const PP_Rect* rect, ImageData* image) {
  gfx::Rect gfx_rect(rect->point.x,
                     rect->point.y,
                     rect->size.width,
                     rect->size.height);
  skia::PlatformCanvas* canvas = image->mapped_canvas();
  if (!canvas)
    return false;
  scrollbar_->paint(webkit_glue::ToWebCanvas(canvas), gfx_rect);

#if defined(OS_WIN)
  if (win_util::GetWinVersion() == win_util::WINVERSION_XP) {
    canvas->getTopPlatformDevice().makeOpaque(
        gfx_rect.x(), gfx_rect.y(), gfx_rect.width(), gfx_rect.height());
  }
#endif

  return true;
}

bool Scrollbar::HandleEvent(const PP_Event* event) {
  scoped_ptr<WebInputEvent> web_input_event(CreateWebInputEvent(*event));
  if (!web_input_event.get())
    return false;

  return scrollbar_->handleInputEvent(*web_input_event.get());
}

void Scrollbar::SetLocationInternal(const PP_Rect* location) {
  scrollbar_->setLocation(WebRect(location->point.x,
                                  location->point.y,
                                  location->size.width,
                                  location->size.height));
}

void Scrollbar::valueChanged(WebKit::WebScrollbar* scrollbar) {
  const PPP_Scrollbar* ppp_scrollbar = static_cast<const PPP_Scrollbar*>(
      module()->GetPluginInterface(PPP_SCROLLBAR_INTERFACE));
  if (!ppp_scrollbar)
    return;
  ScopedResourceId resource(this);
  ppp_scrollbar->ValueChanged(
      instance()->GetPPInstance(), resource.id, scrollbar_->value());
}

void Scrollbar::invalidateScrollbarRect(WebKit::WebScrollbar* scrollbar,
                                        const WebKit::WebRect& rect) {
  gfx::Rect gfx_rect(rect.x,
                     rect.y,
                     rect.width,
                     rect.height);
  dirty_ = dirty_.Union(gfx_rect);
  // Can't call into the client to tell them about the invalidate right away,
  // since the Scrollbar code is still in the middle of updating its internal
  // state.
  MessageLoop::current()->PostTask(
      FROM_HERE,
      NewRunnableMethod(this, &Scrollbar::NotifyInvalidate));
}

void Scrollbar::getTickmarks(
    WebKit::WebScrollbar* scrollbar,
    WebKit::WebVector<WebKit::WebRect>* tick_marks) const {
  if (tickmarks_.empty()) {
    WebRect* rects = NULL;
    tick_marks->assign(rects, 0);
  } else {
    tick_marks->assign(&tickmarks_[0], tickmarks_.size());
  }
}

void Scrollbar::NotifyInvalidate() {
  if (dirty_.IsEmpty())
    return;
  PP_Rect pp_rect;
  pp_rect.point.x = dirty_.x();
  pp_rect.point.y = dirty_.y();
  pp_rect.size.width = dirty_.width();
  pp_rect.size.height = dirty_.height();
  dirty_ = gfx::Rect();
  Invalidate(&pp_rect);
}

}  // namespace pepper
<|endoftext|>


<commit_before>#pragma once

#include <math.h>
#include <stdlib.h>

// base vector struct
template <int n> struct Vec {
    float v[n];

    float& operator[]( const int i ) {
        return this->v[i];
    }

    const float& operator[]( const int i ) const {
        return this->v[i];
    }
};

typedef Vec<2> Vec2;
typedef Vec<3> Vec3;
typedef Vec<4> Vec4;

// specialized definitions for Vec2, Vec3, and Vec4
template<> struct Vec<2> {
    union {
        float vals[2];
        struct { float x, y; };
        struct { float r, g; };
        struct { float u, v; };
    };

    Vec( float _x, float _y )
        : x( _x ) , y( _y ) {}

    Vec()
        : x( 0 ), y ( 0 ) {}

    float& operator[]( const int i ) {
        return this->vals[i];
    }

    const float& operator[]( const int i ) const {
        return this->vals[i];
    }
};

template<> struct Vec<3> {
    union {
        float v[3];
        struct { float x, y, z; };
        struct { float r, g, b; };
        Vec<2> xy;
    };

    Vec( float _x, float _y, float _z )
        : x( _x ), y( _y ), z( _z ) {}

    Vec()
        : x( 0 ), y( 0 ), z( 0 ) {}

    float& operator[]( const int i ) {
        return this->v[i];
    }

    const float& operator[]( const int i ) const {
        return this->v[i];
    }
};

template<> struct Vec<4> {
    union {
        float v[4];
        struct { float x, y, z, w; };
        struct { float r, g, b, a; };
        Vec<2> xy;
        Vec<3> xyz;
        Vec<3> rgb;
    };

    Vec( float _x, float _y, float _z, float _w )
        : x( _x ), y( _y ), z( _z ), w( _w ) {}

    Vec()
        : x( 0 ), y( 0 ), z( 0 ), w( 1 ) {}

    float& operator[]( const int i ) {
        return this->v[i];
    }

    const float& operator[]( const int i ) const {
        return this->v[i];
    }
};

// generic operators
template <int n> Vec<n>  operator+          ( const Vec<n> lhs , const Vec<n> rhs );
template <int n> Vec<n>& operator+=         ( Vec<n>& lhs      , const Vec<n> rhs );
template <int n> Vec<n>  operator-          ( const Vec<n> lhs , const Vec<n> rhs );
template <int n> Vec<n>& operator-=         ( Vec<n>& lhs      , const Vec<n> rhs );
template <int n> Vec<n>  operator*          ( const Vec<n> lhs , const Vec<n> rhs );
template <int n> Vec<n>& operator*=         ( Vec<n>& lhs      , const Vec<n> rhs );
template <int n> Vec<n>  operator*          ( const Vec<n> lhs , const float rhs  );
template <int n> Vec<n>& operator*=         ( Vec<n>& lhs      , const float rhs  );
template <int n> Vec<n>  operator*          ( const float lhs  , const Vec<n> rhs );
template <int n> Vec<n>  operator/          ( const Vec<n> lhs , const Vec<n> rhs );
template <int n> Vec<n>& operator/=         ( Vec<n>& lhs      , const Vec<n> rhs );
template <int n> Vec<n>  operator/          ( const Vec<n> lhs , const float rhs  );
template <int n> Vec<n>& operator/=         ( Vec<n>& lhs      , const float rhs  );
template <int n> Vec<n>  operator^          ( const Vec<n> lhs , const Vec<n> rhs );
template <int n> Vec<n>& operator^=         ( Vec<n>& lhs      , const Vec<n> rhs );
template <int n> Vec<n>  operator^          ( const Vec<n> lhs , const float rhs  );
template <int n> Vec<n>& operator^=         ( Vec<n>& lhs      , const float rhs  );

// vector-specific operations
template <int n> float   dot                ( const Vec<n> lhs, const Vec<n> rhs );
template <int n> Vec<n>  cross              ( const Vec<n> lhs, const Vec<n> rhs );
template <int n> float   cross2D            ( const Vec<n> lhs, const Vec<n> rhs ); // only for vec2s
template <int n> float   lengthsq           ( const Vec<n> in );
template <int n> float   length             ( const Vec<n> in );
template <int n> Vec<n>  normalize          ( const Vec<n> in );

// free-floating constructors
template <int n> Vec<n>  zero               ( void );
template <int n> void    zero               ( Vec<n>& in_out );

// user should seed with srand() before calling random constructors
template <int n> Vec<n>  randomOnSphere ( float radius = 1.f );
template <int n> void    randomOnSphere ( Vec<n>& in_out, float radius = 1.f );

// generic operator definitions
template <int n>
Vec<n> operator+ ( const Vec<n> lhs, const Vec<n> rhs ) {
    Vec<n> sum;
    for ( int i = 0; i < n; i++ ) {
        sum[i] = lhs[i] + rhs[i];
    }
    return sum;
}

template <int n>
Vec<n>& operator+= ( Vec<n>& lhs, const Vec<n> rhs ) {
    for ( int i = 0; i < n; i++ ) {
        lhs[i] += rhs[i];
    }
    return lhs;
}

template <int n>
Vec<n> operator- ( const Vec<n> lhs, const Vec<n> rhs ) {
    Vec<n> difference;
    for ( int i = 0; i < n; i++ ) {
        difference[i] = lhs[i] - rhs[i];
    }
    return difference;
}

template <int n>
Vec<n>& operator-= ( Vec<n>& lhs, const Vec<n> rhs ) {
    for ( int i = 0; i < n; i++ ) {
        lhs[i] -= rhs[i];
    }
    return lhs;
}

template <int n>
Vec<n> operator* ( const Vec<n> lhs, const Vec<n> rhs ) {
    Vec<n> product;
    for ( int i = 0; i < n; i++ ) {
        product[i] = lhs[i] * rhs[i];
    }
    return product;
}

template <int n>
Vec<n>& operator*= ( Vec<n>& lhs, const Vec<n> rhs ) {
    for ( int i = 0; i < n; i++ ) {
        lhs[i] *= rhs[i];
    }
    return lhs;
}

template <int n>
Vec<n> operator* ( const Vec<n> lhs, const float rhs ) {
    Vec<n> scaled;
    for ( int i = 0; i < n; i++ ) {
        scaled[i] = lhs[i] * rhs;
    }
    return scaled;
}

template <int n>
Vec<n>& operator*= ( Vec<n>& lhs, const float rhs ) {
    for ( int i = 0; i < n; i++ ) {
        lhs[i] *= rhs;
    }
    return lhs;
}

template <int n>
Vec<n> operator* ( const float lhs, const Vec<n> rhs ) {
    return operator*( rhs, lhs );
}

template <int n>
Vec<n> operator/ ( const Vec<n> lhs, const Vec<n> rhs ) {
    Vec<n> quotient;
    for ( int i = 0; i < n; i++ ) {
        quotient[i] = lhs[i] / rhs[i];
    }
    return quotient;
}

template <int n>
Vec<n>& operator/= ( Vec<n>& lhs, const Vec<n> rhs ) {
    for ( int i = 0; i < n; i++ ) {
        lhs[i] /= rhs[i];
    }
    return lhs;
}

template <int n>
Vec<n> operator/ ( const Vec<n> lhs, const float rhs ) {
    Vec<n> scaled;
    for ( int i = 0; i < n; i++ ) {
        scaled[i] = lhs[i] / rhs;
    }
    return scaled;
}

template <int n>
Vec<n>& operator/= ( Vec<n>& lhs, const float rhs ) {
    for ( int i = 0; i < n; i++ ) {
        lhs[i] /= rhs;
    }
    return lhs;
}

template <int n>
Vec<n>& operator^= ( Vec<n>& lhs, const Vec<n> rhs ) {
    for ( int i = 0; i < n; i++ ) {
        lhs[i] = pow( lhs[i], rhs[i] );
    }
    return lhs;
}

template <int n>
Vec<n> operator^ ( const Vec<n> lhs, const Vec<n> rhs ) {
    Vec<n> raised;
    for ( int i = 0; i < n; i++ ) {
        raised[i] = pow( lhs[i], rhs[i] );
    }
    return raised;
}

template <int n>
Vec<n>& operator^= ( Vec<n>& lhs, const float rhs ) {
    for ( int i = 0; i < n; i++ ) {
        lhs[i] = pow( lhs[i], rhs );
    }
    return lhs;
}

template <int n>
Vec<n> operator^ ( const Vec<n> lhs, const float rhs ) {
    Vec<n> raised;
    for ( int i = 0; i < n; i++ ) {
        raised[i] = pow( lhs[i], rhs );
    }
    return raised;
}

template <int n>
float dot( const Vec<n> lhs, const Vec<n> rhs ) {
    float dp = 0.f;
    for ( int i = 0; i < n; i++ ) {
        dp += lhs[i] * rhs[i];
    }
    return dp;
}

template <int n>
float lengthsq( const Vec<n> in ) {
    float sum = 0.f;
    for ( int i = 0; i < n; i++ ) {
        sum += in[i] * in[i];
    }
    return sum;
}

template <int n>
float length( const Vec<n> in ) {
    return sqrt( lengthsq( in ) );
}

template <int n>
Vec<n> normalize( const Vec<n> in ) {
    return in / length( in );
}

template <int n>
Vec<n> cross( const Vec<n> lhs, const Vec<n> rhs ) {
    static_assert( n == 3, "cross only defined for Vec<3>!" );
    return { lhs[1] * rhs[2] - lhs[2] * rhs[1]
           , lhs[2] * rhs[0] - lhs[0] * rhs[2]
           , lhs[0] * rhs[1] - lhs[1] * rhs[0] };
}

template <int n>
float cross2D( const Vec<n> lhs, const Vec<n> rhs ) {
    static_assert( n == 2, "cross2D only defined for Vec<2>!" );
    return lhs[0] * rhs[1] - lhs[1] * rhs[0];
}

template <int n>
Vec<n> zero() {
    Vec<n> out;
    for ( int i = 0; i < n; i++ ) {
        out[i] = 0;
    }
    return out;
}

template <int n>
void zero( Vec<n>& in_out ) {
    for ( int i = 0; i < n; i++ ) {
        in_out[i] = 0;
    }
}

template <int n>
Vec<n> randomOnSphere( float radius ) {
    Vec<n> out;
    for ( int i = 0; i < n; i++ ) {
        out[i] = static_cast<float>( rand() ) / RAND_MAX;
    }
    out *= ( radius / length( out ) );
    return out;
}

template <int n>
void randomOnSphere( Vec<n>& in_out, float radius ) {
    for ( int i = 0; i < n; i++ ) {
        in_out[i] = static_cast<float>( rand() ) / RAND_MAX;
    }
    in_out *= ( radius / length( in_out ) );
}
<commit_msg>use drand48()<commit_after>#pragma once

#include <math.h>
#include <stdlib.h>

// base vector struct
template <int n> struct Vec {
    float v[n];

    float& operator[]( const int i ) {
        return this->v[i];
    }

    const float& operator[]( const int i ) const {
        return this->v[i];
    }
};

typedef Vec<2> Vec2;
typedef Vec<3> Vec3;
typedef Vec<4> Vec4;

// specialized definitions for Vec2, Vec3, and Vec4
template<> struct Vec<2> {
    union {
        float vals[2];
        struct { float x, y; };
        struct { float r, g; };
        struct { float u, v; };
    };

    Vec( float _x, float _y )
        : x( _x ) , y( _y ) {}

    Vec()
        : x( 0 ), y ( 0 ) {}

    float& operator[]( const int i ) {
        return this->vals[i];
    }

    const float& operator[]( const int i ) const {
        return this->vals[i];
    }
};

template<> struct Vec<3> {
    union {
        float v[3];
        struct { float x, y, z; };
        struct { float r, g, b; };
        Vec<2> xy;
    };

    Vec( float _x, float _y, float _z )
        : x( _x ), y( _y ), z( _z ) {}

    Vec()
        : x( 0 ), y( 0 ), z( 0 ) {}

    float& operator[]( const int i ) {
        return this->v[i];
    }

    const float& operator[]( const int i ) const {
        return this->v[i];
    }
};

template<> struct Vec<4> {
    union {
        float v[4];
        struct { float x, y, z, w; };
        struct { float r, g, b, a; };
        Vec<2> xy;
        Vec<3> xyz;
        Vec<3> rgb;
    };

    Vec( float _x, float _y, float _z, float _w )
        : x( _x ), y( _y ), z( _z ), w( _w ) {}

    Vec()
        : x( 0 ), y( 0 ), z( 0 ), w( 1 ) {}

    float& operator[]( const int i ) {
        return this->v[i];
    }

    const float& operator[]( const int i ) const {
        return this->v[i];
    }
};

// generic operators
template <int n> Vec<n>  operator+          ( const Vec<n> lhs , const Vec<n> rhs );
template <int n> Vec<n>& operator+=         ( Vec<n>& lhs      , const Vec<n> rhs );
template <int n> Vec<n>  operator-          ( const Vec<n> lhs , const Vec<n> rhs );
template <int n> Vec<n>& operator-=         ( Vec<n>& lhs      , const Vec<n> rhs );
template <int n> Vec<n>  operator*          ( const Vec<n> lhs , const Vec<n> rhs );
template <int n> Vec<n>& operator*=         ( Vec<n>& lhs      , const Vec<n> rhs );
template <int n> Vec<n>  operator*          ( const Vec<n> lhs , const float rhs  );
template <int n> Vec<n>& operator*=         ( Vec<n>& lhs      , const float rhs  );
template <int n> Vec<n>  operator*          ( const float lhs  , const Vec<n> rhs );
template <int n> Vec<n>  operator/          ( const Vec<n> lhs , const Vec<n> rhs );
template <int n> Vec<n>& operator/=         ( Vec<n>& lhs      , const Vec<n> rhs );
template <int n> Vec<n>  operator/          ( const Vec<n> lhs , const float rhs  );
template <int n> Vec<n>& operator/=         ( Vec<n>& lhs      , const float rhs  );
template <int n> Vec<n>  operator^          ( const Vec<n> lhs , const Vec<n> rhs );
template <int n> Vec<n>& operator^=         ( Vec<n>& lhs      , const Vec<n> rhs );
template <int n> Vec<n>  operator^          ( const Vec<n> lhs , const float rhs  );
template <int n> Vec<n>& operator^=         ( Vec<n>& lhs      , const float rhs  );

// vector-specific operations
template <int n> float   dot                ( const Vec<n> lhs, const Vec<n> rhs );
template <int n> Vec<n>  cross              ( const Vec<n> lhs, const Vec<n> rhs );
template <int n> float   cross2D            ( const Vec<n> lhs, const Vec<n> rhs ); // only for vec2s
template <int n> float   lengthsq           ( const Vec<n> in );
template <int n> float   length             ( const Vec<n> in );
template <int n> Vec<n>  normalize          ( const Vec<n> in );

// free-floating constructors
template <int n> Vec<n>  zero               ( void );
template <int n> void    zero               ( Vec<n>& in_out );

// user should seed with srand() before calling random constructors
template <int n> Vec<n>  randomOnSphere ( float radius = 1.f );
template <int n> void    randomOnSphere ( Vec<n>& in_out, float radius = 1.f );

// generic operator definitions
template <int n>
Vec<n> operator+ ( const Vec<n> lhs, const Vec<n> rhs ) {
    Vec<n> sum;
    for ( int i = 0; i < n; i++ ) {
        sum[i] = lhs[i] + rhs[i];
    }
    return sum;
}

template <int n>
Vec<n>& operator+= ( Vec<n>& lhs, const Vec<n> rhs ) {
    for ( int i = 0; i < n; i++ ) {
        lhs[i] += rhs[i];
    }
    return lhs;
}

template <int n>
Vec<n> operator- ( const Vec<n> lhs, const Vec<n> rhs ) {
    Vec<n> difference;
    for ( int i = 0; i < n; i++ ) {
        difference[i] = lhs[i] - rhs[i];
    }
    return difference;
}

template <int n>
Vec<n>& operator-= ( Vec<n>& lhs, const Vec<n> rhs ) {
    for ( int i = 0; i < n; i++ ) {
        lhs[i] -= rhs[i];
    }
    return lhs;
}

template <int n>
Vec<n> operator* ( const Vec<n> lhs, const Vec<n> rhs ) {
    Vec<n> product;
    for ( int i = 0; i < n; i++ ) {
        product[i] = lhs[i] * rhs[i];
    }
    return product;
}

template <int n>
Vec<n>& operator*= ( Vec<n>& lhs, const Vec<n> rhs ) {
    for ( int i = 0; i < n; i++ ) {
        lhs[i] *= rhs[i];
    }
    return lhs;
}

template <int n>
Vec<n> operator* ( const Vec<n> lhs, const float rhs ) {
    Vec<n> scaled;
    for ( int i = 0; i < n; i++ ) {
        scaled[i] = lhs[i] * rhs;
    }
    return scaled;
}

template <int n>
Vec<n>& operator*= ( Vec<n>& lhs, const float rhs ) {
    for ( int i = 0; i < n; i++ ) {
        lhs[i] *= rhs;
    }
    return lhs;
}

template <int n>
Vec<n> operator* ( const float lhs, const Vec<n> rhs ) {
    return operator*( rhs, lhs );
}

template <int n>
Vec<n> operator/ ( const Vec<n> lhs, const Vec<n> rhs ) {
    Vec<n> quotient;
    for ( int i = 0; i < n; i++ ) {
        quotient[i] = lhs[i] / rhs[i];
    }
    return quotient;
}

template <int n>
Vec<n>& operator/= ( Vec<n>& lhs, const Vec<n> rhs ) {
    for ( int i = 0; i < n; i++ ) {
        lhs[i] /= rhs[i];
    }
    return lhs;
}

template <int n>
Vec<n> operator/ ( const Vec<n> lhs, const float rhs ) {
    Vec<n> scaled;
    for ( int i = 0; i < n; i++ ) {
        scaled[i] = lhs[i] / rhs;
    }
    return scaled;
}

template <int n>
Vec<n>& operator/= ( Vec<n>& lhs, const float rhs ) {
    for ( int i = 0; i < n; i++ ) {
        lhs[i] /= rhs;
    }
    return lhs;
}

template <int n>
Vec<n>& operator^= ( Vec<n>& lhs, const Vec<n> rhs ) {
    for ( int i = 0; i < n; i++ ) {
        lhs[i] = pow( lhs[i], rhs[i] );
    }
    return lhs;
}

template <int n>
Vec<n> operator^ ( const Vec<n> lhs, const Vec<n> rhs ) {
    Vec<n> raised;
    for ( int i = 0; i < n; i++ ) {
        raised[i] = pow( lhs[i], rhs[i] );
    }
    return raised;
}

template <int n>
Vec<n>& operator^= ( Vec<n>& lhs, const float rhs ) {
    for ( int i = 0; i < n; i++ ) {
        lhs[i] = pow( lhs[i], rhs );
    }
    return lhs;
}

template <int n>
Vec<n> operator^ ( const Vec<n> lhs, const float rhs ) {
    Vec<n> raised;
    for ( int i = 0; i < n; i++ ) {
        raised[i] = pow( lhs[i], rhs );
    }
    return raised;
}

template <int n>
float dot( const Vec<n> lhs, const Vec<n> rhs ) {
    float dp = 0.f;
    for ( int i = 0; i < n; i++ ) {
        dp += lhs[i] * rhs[i];
    }
    return dp;
}

template <int n>
float lengthsq( const Vec<n> in ) {
    float sum = 0.f;
    for ( int i = 0; i < n; i++ ) {
        sum += in[i] * in[i];
    }
    return sum;
}

template <int n>
float length( const Vec<n> in ) {
    return sqrt( lengthsq( in ) );
}

template <int n>
Vec<n> normalize( const Vec<n> in ) {
    return in / length( in );
}

template <int n>
Vec<n> cross( const Vec<n> lhs, const Vec<n> rhs ) {
    static_assert( n == 3, "cross only defined for Vec<3>!" );
    return { lhs[1] * rhs[2] - lhs[2] * rhs[1]
           , lhs[2] * rhs[0] - lhs[0] * rhs[2]
           , lhs[0] * rhs[1] - lhs[1] * rhs[0] };
}

template <int n>
float cross2D( const Vec<n> lhs, const Vec<n> rhs ) {
    static_assert( n == 2, "cross2D only defined for Vec<2>!" );
    return lhs[0] * rhs[1] - lhs[1] * rhs[0];
}

template <int n>
Vec<n> zero() {
    Vec<n> out;
    for ( int i = 0; i < n; i++ ) {
        out[i] = 0;
    }
    return out;
}

template <int n>
void zero( Vec<n>& in_out ) {
    for ( int i = 0; i < n; i++ ) {
        in_out[i] = 0;
    }
}

template <int n>
Vec<n> randomOnSphere( float radius ) {
    Vec<n> out;
    for ( int i = 0; i < n; i++ ) {
        out[i] = drand48();
    }
    out *= ( radius / length( out ) );
    return out;
}

template <int n>
void randomOnSphere( Vec<n>& in_out, float radius ) {
    for ( int i = 0; i < n; i++ ) {
        in_out[i] = drand48();
    }
    in_out *= ( radius / length( in_out ) );
}
<|endoftext|>


<commit_before>
#include <cmath>
#include <chrono>
#include <random>
#include <vector>
#include <cassert>
#include <fstream>
#include <iomanip>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>

#include "caf/all.hpp"

#include "vast/coder.hpp"
#include "vast/operator.hpp"
#include "vast/wah_bitmap.hpp"
#include "vast/bitmap_index.hpp"

#include "vast/concept/printable/stream.hpp"
#include "vast/concept/printable/to_string.hpp"
#include "vast/concept/printable/vast/bitmap.hpp"

using namespace std;
using namespace std::chrono;
using namespace caf;
using namespace vast;

class config : public actor_system_config {
public:
  string filename = "";
  uint32_t bound = 0;
  bool print_results;
  config() {
    opt_group{custom_options_, "global"}
    .add(filename, "data-file,f", "File with test data (one value per line)")
    .add(bound, "bound,b", "maximum value (0 will scan values)")
    .add(print_results, "print,p", "print resulting bitmap index");
  }
};

void caf_main(actor_system&, const config& cfg) {
  vector<uint32_t> values;
  if (cfg.filename.empty()) {
    values = {10,  7, 22,  6,  7,  1,  9, 42,  2,  5,
              13,  3,  2,  1,  0,  1, 18, 18,  3, 13,
               5,  9,  0,  3,  2, 19,  5, 23, 22, 10,
               6, 22};
  } else {
    cout << "Reading data from '" << cfg.filename << "' ... " << flush;
    ifstream source{cfg.filename, std::ios::in};
    uint32_t next;
    while (source >> next) {
      values.push_back(next);
    }
  }
  auto amount = values.size();
  cout << "Read " << amount << " values." << endl;
  auto bound = cfg.bound;
  if (bound == 0 && amount > 0) {
    auto itr = max_element(values.begin(), values.end());
    bound = *itr;
  }
  cout << "Maximum value is '" << bound << "'." << endl;

  // Extract key set
  vector<uint32_t> keys = values;
  std::sort(keys.begin(), keys.end());
  auto last = std::unique(keys.begin(), keys.end());
  keys.erase(last, end(keys));

  auto start = high_resolution_clock::now();
  bitmap_index<uint32_t, equality_coder<wah_bitmap>> bmi{bound + 1};
  for (auto& val : values)
    bmi.push_back(val);
  auto stop = high_resolution_clock::now();

  if (cfg.print_results) {
    // print index by key
    auto& coder = bmi.coder();
    auto& storage = coder.storage();
    for (auto& key : keys)
      cout << "Index for value " << key << ":" << endl
           << storage[key] << endl;
  }
  cout << "Time: '"
       << duration_cast<milliseconds>(stop - start).count()
       << "' ms" << endl;
}

CAF_MAIN()
<commit_msg>Print coder directly<commit_after>
#include <cmath>
#include <chrono>
#include <random>
#include <vector>
#include <cassert>
#include <fstream>
#include <iomanip>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>

#include "caf/all.hpp"

#include "vast/coder.hpp"
#include "vast/operator.hpp"
#include "vast/wah_bitmap.hpp"
#include "vast/bitmap_index.hpp"

#include "vast/concept/printable/stream.hpp"
#include "vast/concept/printable/to_string.hpp"
#include "vast/concept/printable/vast/coder.hpp"
#include "vast/concept/printable/vast/bitmap.hpp"

using namespace std;
using namespace std::chrono;
using namespace caf;
using namespace vast;

class config : public actor_system_config {
public:
  string filename = "";
  uint32_t bound = 0;
  bool print_results;
  config() {
    opt_group{custom_options_, "global"}
    .add(filename, "data-file,f", "File with test data (one value per line)")
    .add(bound, "bound,b", "maximum value (0 will scan values)")
    .add(print_results, "print,p", "print resulting bitmap index");
  }
};

void caf_main(actor_system&, const config& cfg) {
  vector<uint32_t> values;
  if (cfg.filename.empty()) {
    values = {10,  7, 22,  6,  7,  1,  9, 42,  2,  5,
              13,  3,  2,  1,  0,  1, 18, 18,  3, 13,
               5,  9,  0,  3,  2, 19,  5, 23, 22, 10,
               6, 22};
  } else {
    cout << "Reading data from '" << cfg.filename << "' ... " << flush;
    ifstream source{cfg.filename, std::ios::in};
    uint32_t next;
    while (source >> next) {
      values.push_back(next);
    }
  }
  auto amount = values.size();
  cout << "Read " << amount << " values." << endl;
  auto bound = cfg.bound;
  if (bound == 0 && amount > 0) {
    auto itr = max_element(values.begin(), values.end());
    bound = *itr;
  }
  cout << "Maximum value is '" << bound << "'." << endl;

  /*
  // Extract key set
  vector<uint32_t> keys = values;
  std::sort(keys.begin(), keys.end());
  auto last = std::unique(keys.begin(), keys.end());
  keys.erase(last, end(keys));
  */

  auto start = high_resolution_clock::now();
  bitmap_index<uint32_t, equality_coder<wah_bitmap>> bmi{bound + 1};
  for (auto& val : values)
    bmi.push_back(val);
  auto stop = high_resolution_clock::now();

  if (cfg.print_results) {
    // print index by key
    auto& coder = bmi.coder();
    cout << coder << endl;
    /*
    auto& storage = coder.storage();
    for (auto& key : keys)
      cout << "Index for value " << key << ":" << endl
           << storage[key] << endl;
    */
  }
  cout << "Time: '"
       << duration_cast<milliseconds>(stop - start).count()
       << "' ms" << endl;
}

CAF_MAIN()
<|endoftext|>


<commit_before><commit_msg>landing the issue 482008 for dmuir<commit_after><|endoftext|>


<commit_before><commit_msg>Use the SecInvalidateHandle and SecIsValidHandle macros to reset and test a CredHandle.<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 * Copyright 2020 Realm Inc.
 *
 * 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.
 *
 **************************************************************************/

#ifndef REALM_SET_HPP
#define REALM_SET_HPP

#include <realm/collection.hpp>

#include <numeric> // std::iota

namespace realm {

class SetBase : public CollectionBase {
public:
    using CollectionBase::CollectionBase;

    virtual ~SetBase() {}
    SetBasePtr clone() const
    {
        return m_obj.get_setbase_ptr(m_col_key);
    }

    virtual void insert_null() = 0;
    virtual void erase_null() = 0;
    virtual void clear() = 0;

protected:
    void clear_repl(Replication* repl) const;
};

template <class T>
class Set : public Collection<T, SetBase> {
public:
    using Collection<T, SetBase>::m_tree;
    using Collection<T, SetBase>::size;
    using Collection<T, SetBase>::begin;
    using Collection<T, SetBase>::end;
    using Collection<T, SetBase>::get;

    Set() = default;
    Set(const Obj& owner, ColKey col_key);

    /// Insert a value into the set if it does not already exist, returning the index of the inserted value,
    /// or the index of the already-existing value.
    size_t insert(T value);

    /// Find the index of a value in the set, or `size_t(-1)` if it is not in the set.
    size_t find(T value) const;

    /// Erase an element from the set, returning the index at which it was removed, or `size_t(-1)` if it did
    /// not exist.
    size_t erase(T value);

    // Overriding members of CollectionBase:
    Mixed min(size_t* return_ndx = nullptr) const final;
    Mixed max(size_t* return_ndx = nullptr) const final;
    Mixed sum(size_t* return_cnt = nullptr) const final;
    Mixed avg(size_t* return_cnt = nullptr) const final;
    void sort(std::vector<size_t>& indices, bool ascending = true) const final;
    void distinct(std::vector<size_t>& indices, util::Optional<bool> sort_order = util::none) const final;

    // Overriding members of SetBase:
    void insert_null() override;
    void erase_null() override;
    void clear() override;

private:
    using Collection<T, SetBase>::m_valid;
    using Collection<T, SetBase>::m_obj;

    void create()
    {
        m_tree->create();
        m_valid = true;
    }

    bool update_if_needed()
    {
        if (m_obj.update_if_needed()) {
            return this->init_from_parent();
        }
        return false;
    }
    void ensure_created()
    {
        if (!m_valid && m_obj.is_valid()) {
            create();
        }
    }
};

/// Compare set elements.
///
/// We cannot use `std::less<>` directly, because the ordering of set elements
/// impacts the file format. For primitive types this is trivial (and can indeed
/// be just `std::less<>`), but for example `Mixed` has specialized comparison
/// that defines equality of numeric types.
template <class T>
struct SetElementLessThan {
    bool operator()(const T& a, const T& b) const noexcept
    {
        // CAUTION: This routine is technically part of the file format, because
        // it determines the storage order of Set elements.
        return a < b;
    }
};

template <class T>
struct SetElementEquals {
    bool operator()(const T& a, const T& b) const noexcept
    {
        // CAUTION: This routine is technically part of the file format, because
        // it determines the storage order of Set elements.
        return a == b;
    }
};

template <>
struct SetElementLessThan<Mixed> {
    bool operator()(const Mixed& a, const Mixed& b) const noexcept
    {
        // CAUTION: This routine is technically part of the file format, because
        // it determines the storage order of Set elements.

        if (a.is_null() != b.is_null()) {
            // If a is NULL but not b, a < b.
            return a.is_null();
        }
        else if (a.is_null()) {
            // NULLs are equal.
            return false;
        }

        if (a.get_type() != b.get_type()) {
            return a.get_type() < b.get_type();
        }

        switch (a.get_type()) {
            case type_Int:
                return a.get<int64_t>() < b.get<int64_t>();
            case type_Bool:
                return a.get<bool>() < b.get<bool>();
            case type_String:
                return a.get<StringData>() < b.get<StringData>();
            case type_Binary:
                return a.get<BinaryData>() < b.get<BinaryData>();
            case type_Timestamp:
                return a.get<Timestamp>() < b.get<Timestamp>();
            case type_Float:
                return a.get<float>() < b.get<float>();
            case type_Double:
                return a.get<double>() < b.get<double>();
            case type_Decimal:
                return a.get<Decimal128>() < b.get<Decimal128>();
            case type_ObjectId:
                return a.get<ObjectId>() < b.get<ObjectId>();
            case type_TypedLink:
                return a.get<ObjLink>() < b.get<ObjLink>();
            case type_OldTable:
                [[fallthrough]];
            case type_Mixed:
                [[fallthrough]];
            case type_OldDateTime:
                [[fallthrough]];
            case type_Link:
                [[fallthrough]];
            case type_LinkList:
                REALM_TERMINATE("Invalid Mixed payload in Set.");
                return false;
        }
    }
};

template <>
struct SetElementEquals<Mixed> {
    bool operator()(const Mixed& a, const Mixed& b) const noexcept
    {
        // CAUTION: This routine is technically part of the file format, because
        // it determines the storage order of Set elements.

        if (a.is_null() != b.is_null()) {
            return false;
        }
        else if (a.is_null()) {
            return true;
        }

        if (a.get_type() != b.get_type()) {
            return false;
        }

        switch (a.get_type()) {
            case type_Int:
                return a.get<int64_t>() == b.get<int64_t>();
            case type_Bool:
                return a.get<bool>() == b.get<bool>();
            case type_String:
                return a.get<StringData>() == b.get<StringData>();
            case type_Binary:
                return a.get<BinaryData>() == b.get<BinaryData>();
            case type_Timestamp:
                return a.get<Timestamp>() == b.get<Timestamp>();
            case type_Float:
                return a.get<float>() == b.get<float>();
            case type_Double:
                return a.get<double>() == b.get<double>();
            case type_Decimal:
                return a.get<Decimal128>() == b.get<Decimal128>();
            case type_ObjectId:
                return a.get<ObjectId>() == b.get<ObjectId>();
            case type_TypedLink:
                return a.get<ObjLink>() == b.get<ObjLink>();
            case type_OldTable:
                [[fallthrough]];
            case type_Mixed:
                [[fallthrough]];
            case type_OldDateTime:
                [[fallthrough]];
            case type_Link:
                [[fallthrough]];
            case type_LinkList:
                REALM_TERMINATE("Invalid Mixed payload in Set.");
                return false;
        }
    }
};

template <class T>
inline Set<T>::Set(const Obj& obj, ColKey col_key)
    : Collection<T, SetBase>(obj, col_key)
{
    if (m_obj) {
        this->init_from_parent();
    }
}

template <typename U>
Set<U> Obj::get_set(ColKey col_key) const
{
    return Set<U>(*this, col_key);
}

template <class T>
size_t Set<T>::find(T value) const
{
    return m_tree->find_first(value);
}

template <class T>
size_t Set<T>::insert(T value)
{
    REALM_ASSERT_DEBUG(!update_if_needed());

    ensure_created();
    this->ensure_writeable();
    auto b = this->begin();
    auto e = this->end();
    auto it = std::lower_bound(b, e, value, SetElementLessThan<T>{});

    if (it != e && SetElementEquals<T>{}(*it, value)) {
        return it.index();
    }

    if (Replication* repl = m_obj.get_replication()) {
        // FIXME: We should emit an instruction regardless of element presence for the purposes of conflict
        // resolution in synchronized databases. The reason is that the new insertion may come at a later time
        // than an interleaving erase instruction, so emitting the instruction ensures that last "write" wins.
        repl->set_insert(*this, it.index(), value);
    }

    m_tree->insert(it.index(), value);
    CollectionBase::m_obj.bump_content_version();
    return it.index();
}

template <class T>
size_t Set<T>::erase(T value)
{
    REALM_ASSERT_DEBUG(!update_if_needed());
    this->ensure_writeable();

    auto b = this->begin();
    auto e = this->end();
    auto it = std::lower_bound(b, e, value, SetElementLessThan<T>{});

    if (it == e || !SetElementEquals<T>{}(*it, value)) {
        return not_found;
    }

    if (Replication* repl = m_obj.get_replication()) {
        repl->set_erase(*this, it.index(), value);
    }
    m_tree->erase(it.index());
    CollectionBase::adj_remove(it.index());
    CollectionBase::m_obj.bump_content_version();
    return it.index();
}

template <class T>
inline void Set<T>::insert_null()
{
    insert(BPlusTree<T>::default_value(this->m_nullable));
}

template <class T>
inline void Set<T>::erase_null()
{
    erase(BPlusTree<T>::default_value(this->m_nullable));
}

template <class T>
inline void Set<T>::clear()
{
    ensure_created();
    update_if_needed();
    this->ensure_writeable();
    if (size() > 0) {
        if (Replication* repl = this->m_obj.get_replication()) {
            repl->set_clear(*this);
        }
        m_tree->clear();
        m_obj.bump_content_version();
    }
}

template <class T>
inline Mixed Set<T>::min(size_t* return_ndx) const
{
    if (size() != 0) {
        if (return_ndx) {
            *return_ndx = 0;
        }
        return *begin();
    }
    else {
        if (return_ndx) {
            *return_ndx = not_found;
        }
        return Mixed{};
    }
}

template <class T>
inline Mixed Set<T>::max(size_t* return_ndx) const
{
    auto sz = size();
    if (sz != 0) {
        if (return_ndx) {
            *return_ndx = sz - 1;
        }
        auto e = end();
        --e;
        return *e;
    }
    else {
        if (return_ndx) {
            *return_ndx = not_found;
        }
        return Mixed{};
    }
}

template <class T>
inline Mixed Set<T>::sum(size_t* return_cnt) const
{
    return SumHelper<T>::eval(*m_tree, return_cnt);
}

template <class T>
inline Mixed Set<T>::avg(size_t* return_cnt) const
{
    return AverageHelper<T>::eval(*m_tree, return_cnt);
}

template <class T>
inline void Set<T>::sort(std::vector<size_t>& indices, bool ascending) const
{
    auto sz = size();
    indices.resize(sz);
    if (ascending) {
        std::iota(indices.begin(), indices.end(), 0);
    }
    else {
        std::iota(indices.rbegin(), indices.rend(), 0);
    }
}

template <class T>
inline void Set<T>::distinct(std::vector<size_t>& indices, util::Optional<bool> sort_order) const
{
    auto ascending = !sort_order || *sort_order;
    sort(indices, ascending);
}

} // namespace realm

#endif // REALM_SET_HPP
<commit_msg>Fix compiler warning<commit_after>/*************************************************************************
 *
 * Copyright 2020 Realm Inc.
 *
 * 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.
 *
 **************************************************************************/

#ifndef REALM_SET_HPP
#define REALM_SET_HPP

#include <realm/collection.hpp>

#include <numeric> // std::iota

namespace realm {

class SetBase : public CollectionBase {
public:
    using CollectionBase::CollectionBase;

    virtual ~SetBase() {}
    SetBasePtr clone() const
    {
        return m_obj.get_setbase_ptr(m_col_key);
    }

    virtual void insert_null() = 0;
    virtual void erase_null() = 0;
    virtual void clear() = 0;

protected:
    void clear_repl(Replication* repl) const;
};

template <class T>
class Set : public Collection<T, SetBase> {
public:
    using Collection<T, SetBase>::m_tree;
    using Collection<T, SetBase>::size;
    using Collection<T, SetBase>::begin;
    using Collection<T, SetBase>::end;
    using Collection<T, SetBase>::get;

    Set() = default;
    Set(const Obj& owner, ColKey col_key);

    /// Insert a value into the set if it does not already exist, returning the index of the inserted value,
    /// or the index of the already-existing value.
    size_t insert(T value);

    /// Find the index of a value in the set, or `size_t(-1)` if it is not in the set.
    size_t find(T value) const;

    /// Erase an element from the set, returning the index at which it was removed, or `size_t(-1)` if it did
    /// not exist.
    size_t erase(T value);

    // Overriding members of CollectionBase:
    Mixed min(size_t* return_ndx = nullptr) const final;
    Mixed max(size_t* return_ndx = nullptr) const final;
    Mixed sum(size_t* return_cnt = nullptr) const final;
    Mixed avg(size_t* return_cnt = nullptr) const final;
    void sort(std::vector<size_t>& indices, bool ascending = true) const final;
    void distinct(std::vector<size_t>& indices, util::Optional<bool> sort_order = util::none) const final;

    // Overriding members of SetBase:
    void insert_null() override;
    void erase_null() override;
    void clear() override;

private:
    using Collection<T, SetBase>::m_valid;
    using Collection<T, SetBase>::m_obj;

    void create()
    {
        m_tree->create();
        m_valid = true;
    }

    bool update_if_needed()
    {
        if (m_obj.update_if_needed()) {
            return this->init_from_parent();
        }
        return false;
    }
    void ensure_created()
    {
        if (!m_valid && m_obj.is_valid()) {
            create();
        }
    }
};

/// Compare set elements.
///
/// We cannot use `std::less<>` directly, because the ordering of set elements
/// impacts the file format. For primitive types this is trivial (and can indeed
/// be just `std::less<>`), but for example `Mixed` has specialized comparison
/// that defines equality of numeric types.
template <class T>
struct SetElementLessThan {
    bool operator()(const T& a, const T& b) const noexcept
    {
        // CAUTION: This routine is technically part of the file format, because
        // it determines the storage order of Set elements.
        return a < b;
    }
};

template <class T>
struct SetElementEquals {
    bool operator()(const T& a, const T& b) const noexcept
    {
        // CAUTION: This routine is technically part of the file format, because
        // it determines the storage order of Set elements.
        return a == b;
    }
};

template <>
struct SetElementLessThan<Mixed> {
    bool operator()(const Mixed& a, const Mixed& b) const noexcept
    {
        // CAUTION: This routine is technically part of the file format, because
        // it determines the storage order of Set elements.

        if (a.is_null() != b.is_null()) {
            // If a is NULL but not b, a < b.
            return a.is_null();
        }
        else if (a.is_null()) {
            // NULLs are equal.
            return false;
        }

        if (a.get_type() != b.get_type()) {
            return a.get_type() < b.get_type();
        }

        switch (a.get_type()) {
            case type_Int:
                return a.get<int64_t>() < b.get<int64_t>();
            case type_Bool:
                return a.get<bool>() < b.get<bool>();
            case type_String:
                return a.get<StringData>() < b.get<StringData>();
            case type_Binary:
                return a.get<BinaryData>() < b.get<BinaryData>();
            case type_Timestamp:
                return a.get<Timestamp>() < b.get<Timestamp>();
            case type_Float:
                return a.get<float>() < b.get<float>();
            case type_Double:
                return a.get<double>() < b.get<double>();
            case type_Decimal:
                return a.get<Decimal128>() < b.get<Decimal128>();
            case type_ObjectId:
                return a.get<ObjectId>() < b.get<ObjectId>();
            case type_TypedLink:
                return a.get<ObjLink>() < b.get<ObjLink>();
            case type_OldTable:
                [[fallthrough]];
            case type_Mixed:
                [[fallthrough]];
            case type_OldDateTime:
                [[fallthrough]];
            case type_Link:
                [[fallthrough]];
            case type_LinkList:
                REALM_TERMINATE("Invalid Mixed payload in Set.");
        }
        return false;
    }
};

template <>
struct SetElementEquals<Mixed> {
    bool operator()(const Mixed& a, const Mixed& b) const noexcept
    {
        // CAUTION: This routine is technically part of the file format, because
        // it determines the storage order of Set elements.

        if (a.is_null() != b.is_null()) {
            return false;
        }
        else if (a.is_null()) {
            return true;
        }

        if (a.get_type() != b.get_type()) {
            return false;
        }

        switch (a.get_type()) {
            case type_Int:
                return a.get<int64_t>() == b.get<int64_t>();
            case type_Bool:
                return a.get<bool>() == b.get<bool>();
            case type_String:
                return a.get<StringData>() == b.get<StringData>();
            case type_Binary:
                return a.get<BinaryData>() == b.get<BinaryData>();
            case type_Timestamp:
                return a.get<Timestamp>() == b.get<Timestamp>();
            case type_Float:
                return a.get<float>() == b.get<float>();
            case type_Double:
                return a.get<double>() == b.get<double>();
            case type_Decimal:
                return a.get<Decimal128>() == b.get<Decimal128>();
            case type_ObjectId:
                return a.get<ObjectId>() == b.get<ObjectId>();
            case type_TypedLink:
                return a.get<ObjLink>() == b.get<ObjLink>();
            case type_OldTable:
                [[fallthrough]];
            case type_Mixed:
                [[fallthrough]];
            case type_OldDateTime:
                [[fallthrough]];
            case type_Link:
                [[fallthrough]];
            case type_LinkList:
                REALM_TERMINATE("Invalid Mixed payload in Set.");
        }
        return false;
    }
};

template <class T>
inline Set<T>::Set(const Obj& obj, ColKey col_key)
    : Collection<T, SetBase>(obj, col_key)
{
    if (m_obj) {
        this->init_from_parent();
    }
}

template <typename U>
Set<U> Obj::get_set(ColKey col_key) const
{
    return Set<U>(*this, col_key);
}

template <class T>
size_t Set<T>::find(T value) const
{
    return m_tree->find_first(value);
}

template <class T>
size_t Set<T>::insert(T value)
{
    REALM_ASSERT_DEBUG(!update_if_needed());

    ensure_created();
    this->ensure_writeable();
    auto b = this->begin();
    auto e = this->end();
    auto it = std::lower_bound(b, e, value, SetElementLessThan<T>{});

    if (it != e && SetElementEquals<T>{}(*it, value)) {
        return it.index();
    }

    if (Replication* repl = m_obj.get_replication()) {
        // FIXME: We should emit an instruction regardless of element presence for the purposes of conflict
        // resolution in synchronized databases. The reason is that the new insertion may come at a later time
        // than an interleaving erase instruction, so emitting the instruction ensures that last "write" wins.
        repl->set_insert(*this, it.index(), value);
    }

    m_tree->insert(it.index(), value);
    CollectionBase::m_obj.bump_content_version();
    return it.index();
}

template <class T>
size_t Set<T>::erase(T value)
{
    REALM_ASSERT_DEBUG(!update_if_needed());
    this->ensure_writeable();

    auto b = this->begin();
    auto e = this->end();
    auto it = std::lower_bound(b, e, value, SetElementLessThan<T>{});

    if (it == e || !SetElementEquals<T>{}(*it, value)) {
        return not_found;
    }

    if (Replication* repl = m_obj.get_replication()) {
        repl->set_erase(*this, it.index(), value);
    }
    m_tree->erase(it.index());
    CollectionBase::adj_remove(it.index());
    CollectionBase::m_obj.bump_content_version();
    return it.index();
}

template <class T>
inline void Set<T>::insert_null()
{
    insert(BPlusTree<T>::default_value(this->m_nullable));
}

template <class T>
inline void Set<T>::erase_null()
{
    erase(BPlusTree<T>::default_value(this->m_nullable));
}

template <class T>
inline void Set<T>::clear()
{
    ensure_created();
    update_if_needed();
    this->ensure_writeable();
    if (size() > 0) {
        if (Replication* repl = this->m_obj.get_replication()) {
            repl->set_clear(*this);
        }
        m_tree->clear();
        m_obj.bump_content_version();
    }
}

template <class T>
inline Mixed Set<T>::min(size_t* return_ndx) const
{
    if (size() != 0) {
        if (return_ndx) {
            *return_ndx = 0;
        }
        return *begin();
    }
    else {
        if (return_ndx) {
            *return_ndx = not_found;
        }
        return Mixed{};
    }
}

template <class T>
inline Mixed Set<T>::max(size_t* return_ndx) const
{
    auto sz = size();
    if (sz != 0) {
        if (return_ndx) {
            *return_ndx = sz - 1;
        }
        auto e = end();
        --e;
        return *e;
    }
    else {
        if (return_ndx) {
            *return_ndx = not_found;
        }
        return Mixed{};
    }
}

template <class T>
inline Mixed Set<T>::sum(size_t* return_cnt) const
{
    return SumHelper<T>::eval(*m_tree, return_cnt);
}

template <class T>
inline Mixed Set<T>::avg(size_t* return_cnt) const
{
    return AverageHelper<T>::eval(*m_tree, return_cnt);
}

template <class T>
inline void Set<T>::sort(std::vector<size_t>& indices, bool ascending) const
{
    auto sz = size();
    indices.resize(sz);
    if (ascending) {
        std::iota(indices.begin(), indices.end(), 0);
    }
    else {
        std::iota(indices.rbegin(), indices.rend(), 0);
    }
}

template <class T>
inline void Set<T>::distinct(std::vector<size_t>& indices, util::Optional<bool> sort_order) const
{
    auto ascending = !sort_order || *sort_order;
    sort(indices, ascending);
}

} // namespace realm

#endif // REALM_SET_HPP
<|endoftext|>


<commit_before><commit_msg>test tools: reset moved attribute in MoveOnly<commit_after><|endoftext|>


<commit_before>/** @file

  ProxyClientTransaction - Base class for protocol client transactions.

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you 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 "http/HttpSM.h"
#include "http/HttpServerSession.h"
#include "Plugin.h"

#define DebugHttpTxn(fmt, ...) DebugSsn(this, "http_txn", fmt, __VA_ARGS__)

ProxyClientTransaction::ProxyClientTransaction()
  : VConnection(NULL),
    m_active(false),
    parent(NULL),
    current_reader(NULL),
    sm_reader(NULL),
    host_res_style(HOST_RES_NONE),
    restart_immediate(false)
{
}

void
ProxyClientTransaction::new_transaction()
{
  ink_assert(current_reader == NULL);

  // Defensive programming, make sure nothing persists across
  // connection re-use

  ink_release_assert(parent != NULL);
  current_reader = HttpSM::allocate();
  current_reader->init();
  DebugHttpTxn("[%" PRId64 "] Starting transaction %d using sm [%" PRId64 "]", parent->connection_id(),
               parent->get_transact_count(), current_reader->sm_id);

  current_reader->attach_client_session(this, sm_reader);
}

void
ProxyClientTransaction::release(IOBufferReader *r)
{
  ink_assert(current_reader != NULL);

  DebugHttpTxn("[%" PRId64 "] session released by sm [%" PRId64 "]", parent ? parent->connection_id() : 0,
               current_reader ? current_reader->sm_id : 0);

  // current_reader = NULL; // Clear reference to SM

  // Pass along the release to the session
  if (parent) {
    parent->release(this);
  }
}

void
ProxyClientTransaction::attach_server_session(HttpServerSession *ssession, bool transaction_done)
{
  parent->attach_server_session(ssession, transaction_done);
}

void
ProxyClientTransaction::destroy()
{
  if (current_reader) {
    current_reader->ua_session = NULL;
    current_reader             = NULL;
  }
  this->mutex.clear();
}

Action *
ProxyClientTransaction::adjust_thread(Continuation *cont, int event, void *data)
{
  NetVConnection *vc   = this->get_netvc();
  EThread *this_thread = this_ethread();
  if (vc && vc->thread != this_thread) {
    if (vc->thread->is_event_type(ET_NET) || vc->thread->is_event_type(SSLNetProcessor::ET_SSL)) {
      return vc->thread->schedule_imm(cont, event, data);
    } else { // Not a net thread, take over this thread
      vc->thread = this_thread;
    }
  }
  return NULL;
}
<commit_msg>TS-4726: Remove unnecessary assert in ProxyClientTransaction::release<commit_after>/** @file

  ProxyClientTransaction - Base class for protocol client transactions.

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you 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 "http/HttpSM.h"
#include "http/HttpServerSession.h"
#include "Plugin.h"

#define DebugHttpTxn(fmt, ...) DebugSsn(this, "http_txn", fmt, __VA_ARGS__)

ProxyClientTransaction::ProxyClientTransaction()
  : VConnection(NULL),
    m_active(false),
    parent(NULL),
    current_reader(NULL),
    sm_reader(NULL),
    host_res_style(HOST_RES_NONE),
    restart_immediate(false)
{
}

void
ProxyClientTransaction::new_transaction()
{
  ink_assert(current_reader == NULL);

  // Defensive programming, make sure nothing persists across
  // connection re-use

  ink_release_assert(parent != NULL);
  current_reader = HttpSM::allocate();
  current_reader->init();
  DebugHttpTxn("[%" PRId64 "] Starting transaction %d using sm [%" PRId64 "]", parent->connection_id(),
               parent->get_transact_count(), current_reader->sm_id);

  current_reader->attach_client_session(this, sm_reader);
}

void
ProxyClientTransaction::release(IOBufferReader *r)
{
  DebugHttpTxn("[%" PRId64 "] session released by sm [%" PRId64 "]", parent ? parent->connection_id() : 0,
               current_reader ? current_reader->sm_id : 0);

  // Pass along the release to the session
  if (parent) {
    parent->release(this);
  }
}

void
ProxyClientTransaction::attach_server_session(HttpServerSession *ssession, bool transaction_done)
{
  parent->attach_server_session(ssession, transaction_done);
}

void
ProxyClientTransaction::destroy()
{
  if (current_reader) {
    current_reader->ua_session = NULL;
    current_reader             = NULL;
  }
  this->mutex.clear();
}

Action *
ProxyClientTransaction::adjust_thread(Continuation *cont, int event, void *data)
{
  NetVConnection *vc   = this->get_netvc();
  EThread *this_thread = this_ethread();
  if (vc && vc->thread != this_thread) {
    if (vc->thread->is_event_type(ET_NET) || vc->thread->is_event_type(SSLNetProcessor::ET_SSL)) {
      return vc->thread->schedule_imm(cont, event, data);
    } else { // Not a net thread, take over this thread
      vc->thread = this_thread;
    }
  }
  return NULL;
}
<|endoftext|>