text:
using namespace arangodb;
using namespace arangodb::basics;

////////////////////////////////////////////////////////////////////////////////
/// @brief creates a v8 exception object
////////////////////////////////////////////////////////////////////////////////

#define THROW_AGENCY_EXCEPTION(data) \
  CreateAgencyException(args, data); \
  return;

#define ONLY_IN_CLUSTER                                 \
  if (!ServerState::instance()->isRunningInCluster()) { \
    TRI_V8_THROW_EXCEPTION_INTERNAL(                    \
        "ArangoDB is not running in cluster mode");     \
  }

static void CreateAgencyException(
    v8::FunctionCallbackInfo<v8::Value> const& args,
    AgencyCommResult const& result) {
  v8::Isolate* isolate = args.GetIsolate();
  TRI_V8_CURRENT_GLOBALS_AND_SCOPE;

  std::string const errorDetails = result.errorDetails();
  v8::Handle<v8::String> errorMessage = TRI_V8_STD_STRING(errorDetails);
  if (errorMessage.IsEmpty()) {
    isolate->ThrowException(v8::Object::New(isolate));
    return;
  }
  v8::Handle<v8::Object> errorObject =
      v8::Exception::Error(errorMessage)->ToObject();
  if (errorObject.IsEmpty()) {
    isolate->ThrowException(v8::Object::New(isolate));
    return;
  }

  errorObject->Set(TRI_V8_ASCII_STRING("code"),
                   v8::Number::New(isolate, result.httpCode()));
  errorObject->Set(TRI_V8_ASCII_STRING("errorNum"),
                   v8::Number::New(isolate, result.errorCode()));
  errorObject->Set(TRI_V8_ASCII_STRING("errorMessage"), errorMessage);
  errorObject->Set(TRI_V8_ASCII_STRING("error"), v8::True(isolate));

  TRI_GET_GLOBAL(ArangoErrorTempl, v8::ObjectTemplate);
  v8::Handle<v8::Value> proto = ArangoErrorTempl->NewInstance();
  if (!proto.IsEmpty()) {
    errorObject->SetPrototype(proto);
  }

  args.GetIsolate()->ThrowException(errorObject);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief compares and swaps a value in the agency
////////////////////////////////////////////////////////////////////////////////

static void JS_CasAgency(v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  if (args.Length() < 3) {
    TRI_V8_THROW_EXCEPTION_USAGE(
        "cas(<key>, <oldValue>, <newValue>, <ttl>, <timeout>, <throw>)");
  }

  std::string const key = TRI_ObjectToString(args[0]);

  VPackBuilder oldBuilder;
  int res = TRI_V8ToVPack(isolate, oldBuilder, args[1], false);

  if (res != TRI_ERROR_NO_ERROR) {
    TRI_V8_THROW_EXCEPTION_PARAMETER("cannot convert <oldValue> to VPack");
  }

  VPackBuilder newBuilder;
  res = TRI_V8ToVPack(isolate, newBuilder, args[2], false);

  if (res != TRI_ERROR_NO_ERROR) {
    TRI_V8_THROW_EXCEPTION_PARAMETER("cannot convert <newValue> to VPack");
  }

  double ttl = 0.0;
  if (args.Length() > 3) {
    ttl = TRI_ObjectToDouble(args[3]);
  }

  double timeout = 1.0;
  if (args.Length() > 4) {
    timeout = TRI_ObjectToDouble(args[4]);
  }

  bool shouldThrow = false;
  if (args.Length() > 5) {
    shouldThrow = TRI_ObjectToBoolean(args[5]);
  }

  AgencyComm comm;
  AgencyCommResult result =
      comm.casValue(key, oldBuilder.slice(), newBuilder.slice(), ttl, timeout);

  if (!result.successful()) {
    if (!shouldThrow) {
      TRI_V8_RETURN_FALSE();
    }

    THROW_AGENCY_EXCEPTION(result);
  }

  TRI_V8_RETURN_TRUE();
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief creates a directory in the agency
////////////////////////////////////////////////////////////////////////////////

static void JS_CreateDirectoryAgency(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  if (args.Length() != 1) {
    TRI_V8_THROW_EXCEPTION_USAGE("createDirectory(<key>)");
  }

  std::string const key = TRI_ObjectToString(args[0]);

  AgencyComm comm;
  AgencyCommResult result = comm.createDirectory(key);

  if (!result.successful()) {
    THROW_AGENCY_EXCEPTION(result);
  }

  TRI_V8_RETURN_TRUE();
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the agency is enabled
////////////////////////////////////////////////////////////////////////////////

static void JS_IsEnabledAgency(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate)
  v8::HandleScope scope(isolate);

  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("isEnabled()");
  }

  if (AgencyCommManager::isEnabled()) {
    TRI_V8_RETURN_TRUE();
  }

  TRI_V8_RETURN_FALSE();
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief increase the version number
////////////////////////////////////////////////////////////////////////////////

static void JS_IncreaseVersionAgency(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate)
  v8::HandleScope scope(isolate);

  if (args.Length() != 1) {
    TRI_V8_THROW_EXCEPTION_USAGE("increaseVersion(<key>)");
  }

  std::string const key = TRI_ObjectToString(args[0]);

  AgencyComm comm;
  if (!comm.increaseVersion(key)) {
    TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
                                   "unable to increase version");
  }

  TRI_V8_RETURN_TRUE();
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief gets a value from the agency
////////////////////////////////////////////////////////////////////////////////

static void JS_GetAgency(v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate)
  v8::HandleScope scope(isolate);

  if (args.Length() < 1) {
    TRI_V8_THROW_EXCEPTION_USAGE("get(<key>)");
  }

  std::string const key = TRI_ObjectToString(args[0]);
  AgencyComm comm;
  AgencyCommResult result = comm.getValues(key);

  if (!result.successful()) {
    THROW_AGENCY_EXCEPTION(result);
  }

  v8::Handle<v8::Object> l = v8::Object::New(isolate);

  // return just the value for each key

  for (auto const& a : VPackArrayIterator(result.slice())) {
    for (auto const& o : VPackObjectIterator(a)) {
      std::string const key = o.key.copyString();
      VPackSlice const slice = o.value;

      if (!slice.isNone()) {
        l->ForceSet(TRI_V8_STD_STRING(key), TRI_VPackToV8(isolate, slice));
      }
    }
  }

  TRI_V8_RETURN(l);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief read transaction to the agency
////////////////////////////////////////////////////////////////////////////////

static void JS_APIAgency(std::string const& envelope,
                         v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate)
  v8::HandleScope scope(isolate);

  if (args.Length() < 1) {
    TRI_V8_THROW_EXCEPTION_USAGE("read([[...]])");
  }

  VPackBuilder builder;
  int res = TRI_V8ToVPack(isolate, builder, args[0], false);

  if (res != TRI_ERROR_NO_ERROR) {
    TRI_V8_THROW_EXCEPTION_PARAMETER("cannot convert query to JSON");
  }

  AgencyComm comm;
  AgencyCommResult result =
    comm.sendWithFailover(
      arangodb::rest::RequestType::POST,
      AgencyCommManager::CONNECTION_OPTIONS._requestTimeout,
      std::string("/_api/agency/") + envelope, builder.slice());

  if (!result.successful()) {
    THROW_AGENCY_EXCEPTION(result);
  }

  try {
    result.setVPack(VPackParser::fromJson(result.bodyRef()));
    result._body.clear();
  } catch (std::exception const& e) {
    LOG_TOPIC(ERR, Logger::AGENCYCOMM)
      << "Error transforming result. " << e.what();
    result.clear();
  } catch (...) {
    LOG_TOPIC(ERR, Logger::AGENCYCOMM)
      << "Error transforming result. Out of memory";
    result.clear();
  }

  auto l = TRI_VPackToV8(isolate, result.slice());

  TRI_V8_RETURN(l);
  TRI_V8_TRY_CATCH_END

}
static void JS_ReadAgency(v8::FunctionCallbackInfo<v8::Value> const& args) {
  JS_APIAgency("read", args);
}
static void JS_WriteAgency(v8::FunctionCallbackInfo<v8::Value> const& args) {
  JS_APIAgency("write", args);
}
static void JS_TransactAgency(v8::FunctionCallbackInfo<v8::Value> const& args) {
  JS_APIAgency("transact", args);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief acquires a write-lock in the agency
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief removes a value from the agency
////////////////////////////////////////////////////////////////////////////////

static void JS_RemoveAgency(v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  if (args.Length() < 1) {
    TRI_V8_THROW_EXCEPTION_USAGE("remove(<key>, <recursive>)");
  }

  std::string const key = TRI_ObjectToString(args[0]);
  bool recursive = false;

  if (args.Length() > 1) {
    recursive = TRI_ObjectToBoolean(args[1]);
  }

  AgencyComm comm;
  AgencyCommResult result = comm.removeValues(key, recursive);

  if (!result.successful()) {
    THROW_AGENCY_EXCEPTION(result);
  }

  TRI_V8_RETURN_TRUE();
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief sets a value in the agency
////////////////////////////////////////////////////////////////////////////////

static void JS_SetAgency(v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  if (args.Length() < 2) {
    TRI_V8_THROW_EXCEPTION_USAGE("set(<key>, <value>, <ttl>)");
  }

  std::string const key = TRI_ObjectToString(args[0]);

  VPackBuilder builder;
  int res = TRI_V8ToVPack(isolate, builder, args[1], false);

  if (res != TRI_ERROR_NO_ERROR) {
    TRI_V8_THROW_EXCEPTION_PARAMETER("cannot convert <value> to JSON");
  }

  double ttl = 0.0;
  if (args.Length() > 2) {
    ttl = TRI_ObjectToDouble(args[2]);
  }

  AgencyComm comm;
  AgencyCommResult result = comm.setValue(key, builder.slice(), ttl);

  if (!result.successful()) {
    THROW_AGENCY_EXCEPTION(result);
  }

  TRI_V8_RETURN_TRUE();
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief returns the agency endpoints
////////////////////////////////////////////////////////////////////////////////

static void JS_EndpointsAgency(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("endpoints()");
  }

  std::vector<std::string> endpoints = AgencyCommManager::MANAGER->endpoints();
  // make the list of endpoints unique
  std::sort(endpoints.begin(), endpoints.end());
  endpoints.assign(endpoints.begin(),
                   std::unique(endpoints.begin(), endpoints.end()));

  v8::Handle<v8::Array> l = v8::Array::New(isolate);

  for (size_t i = 0; i < endpoints.size(); ++i) {
    std::string const endpoint = endpoints[i];

    l->Set((uint32_t)i, TRI_V8_STD_STRING(endpoint));
  }

  TRI_V8_RETURN(l);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief returns the agency prefix
////////////////////////////////////////////////////////////////////////////////

static void JS_PrefixAgency(v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  std::string const prefix = AgencyCommManager::path();

  TRI_V8_RETURN_STD_STRING(prefix);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief creates a uniqid
////////////////////////////////////////////////////////////////////////////////

static void JS_UniqidAgency(v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  if (args.Length() > 2) {
    TRI_V8_THROW_EXCEPTION_USAGE("uniqid(<count>, <timeout>)");
  }

  uint64_t count = 1;
  if (args.Length() > 0) {
    count = TRI_ObjectToUInt64(args[0], true);
  }

  if (count < 1 || count > 10000000) {
    TRI_V8_THROW_EXCEPTION_PARAMETER("<count> is invalid");
  }

  double timeout = 0.0;
  if (args.Length() > 1) {
    timeout = TRI_ObjectToDouble(args[1]);
  }

  AgencyComm comm;
  uint64_t result = comm.uniqid(count, timeout);

  std::string const value = StringUtils::itoa(result);

  TRI_V8_RETURN_STD_STRING(value);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief returns the agency version
////////////////////////////////////////////////////////////////////////////////

static void JS_VersionAgency(v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("version()");
  }

  AgencyComm comm;
  std::string const version = comm.version();

  TRI_V8_RETURN_STD_STRING(version);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not a specific database exists
////////////////////////////////////////////////////////////////////////////////

static void JS_DoesDatabaseExistClusterInfo(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  ONLY_IN_CLUSTER
  if (args.Length() != 1) {
    TRI_V8_THROW_EXCEPTION_USAGE("doesDatabaseExist(<database-id>)");
  }

  bool const result = ClusterInfo::instance()->doesDatabaseExist(
      TRI_ObjectToString(args[0]), true);

  if (result) {
    TRI_V8_RETURN_TRUE();
  }
  TRI_V8_RETURN_FALSE();
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get the list of databases in the cluster
////////////////////////////////////////////////////////////////////////////////

static void JS_Databases(v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("databases()");
  }

  ONLY_IN_CLUSTER
  std::vector<DatabaseID> res = ClusterInfo::instance()->databases(true);
  v8::Handle<v8::Array> a = v8::Array::New(isolate, (int)res.size());
  std::vector<DatabaseID>::iterator it;
  int count = 0;
  for (it = res.begin(); it != res.end(); ++it) {
    a->Set((uint32_t)count++, TRI_V8_STD_STRING((*it)));
  }
  TRI_V8_RETURN(a);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief flush the caches (used for testing only)
////////////////////////////////////////////////////////////////////////////////

static void JS_FlushClusterInfo(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  ONLY_IN_CLUSTER
  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("flush()");
  }

  ClusterInfo::instance()->flush();

  TRI_V8_RETURN_TRUE();
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get the info about a collection in Plan
////////////////////////////////////////////////////////////////////////////////

static void JS_GetCollectionInfoClusterInfo(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  ONLY_IN_CLUSTER
  if (args.Length() != 2) {
    TRI_V8_THROW_EXCEPTION_USAGE(
        "getCollectionInfo(<database-id>, <collection-id>)");
  }

  std::shared_ptr<LogicalCollection> ci = ClusterInfo::instance()->getCollection(
      TRI_ObjectToString(args[0]), TRI_ObjectToString(args[1]));
  TRI_ASSERT(ci != nullptr);

  std::unordered_set<std::string> ignoreKeys{"allowUserKeys",
                                             "avoidServers",
                                             "cid",
                                             "count",
                                             "distributeShardsLike",
                                             "indexBuckets",
                                             "keyOptions",
                                             "numberOfShards",
                                             "path",
                                             "planId",
                                             "version"};
  VPackBuilder infoBuilder = ci->toVelocyPackIgnore(ignoreKeys, false, false);
  VPackSlice info = infoBuilder.slice();

  TRI_ASSERT(info.isObject());
  v8::Handle<v8::Object> result = TRI_VPackToV8(isolate, info)->ToObject();

  // Compute ShardShorts
  auto serverAliases = ClusterInfo::instance()->getServerAliases();
  VPackSlice shards = info.get("shards");
  TRI_ASSERT(shards.isObject());
  v8::Handle<v8::Object> shardShorts = v8::Object::New(isolate);
  for (auto const& p : VPackObjectIterator(shards)) {
    TRI_ASSERT(p.value.isArray());
    v8::Handle<v8::Array> shorts =
        v8::Array::New(isolate, static_cast<int>(p.value.length()));
    uint32_t pos = 0;
    for (auto const& s : VPackArrayIterator(p.value)) {
      try {
        std::string t = s.copyString();
        if (t.at(0) == '_') {
          t = t.substr(1);
        }
        shorts->Set(pos++, TRI_V8_STD_STRING(serverAliases.at(t)));
      } catch (...) {}
    }
    shardShorts->Set(TRI_V8_STD_STRING(p.key.copyString()), shorts);
  }
  result->Set(TRI_V8_ASCII_STRING("shardShorts"), shardShorts);
  TRI_V8_RETURN(result);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get the info about a collection in Current
////////////////////////////////////////////////////////////////////////////////

static void JS_GetCollectionInfoCurrentClusterInfo(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  ONLY_IN_CLUSTER
  if (args.Length() != 3) {
    TRI_V8_THROW_EXCEPTION_USAGE(
        "getCollectionInfoCurrent(<database-id>, <collection-id>, <shardID>)");
  }

  ShardID shardID = TRI_ObjectToString(args[2]);

  std::shared_ptr<LogicalCollection> ci = ClusterInfo::instance()->getCollection(
      TRI_ObjectToString(args[0]), TRI_ObjectToString(args[1]));
  TRI_ASSERT(ci != nullptr);

  v8::Handle<v8::Object> result = v8::Object::New(isolate);
  // First some stuff from Plan for which Current does not make sense:
  std::string const cid = ci->cid_as_string();
  std::string const& name = ci->name();
  result->Set(TRI_V8_ASCII_STRING("id"), TRI_V8_STD_STRING(cid));
  result->Set(TRI_V8_ASCII_STRING("name"), TRI_V8_STD_STRING(name));

  std::shared_ptr<CollectionInfoCurrent> cic =
      ClusterInfo::instance()->getCollectionCurrent(TRI_ObjectToString(args[0]),
                                                    cid);

  result->Set(TRI_V8_ASCII_STRING("type"),
              v8::Number::New(isolate, (int)ci->type()));

  VPackSlice slice = cic->getIndexes(shardID);
  v8::Handle<v8::Value> indexes = TRI_VPackToV8(isolate, slice);
  result->Set(TRI_V8_ASCII_STRING("indexes"), indexes);

  // Finally, report any possible error:
  bool error = cic->error(shardID);
  result->Set(TRI_V8_ASCII_STRING("error"), v8::Boolean::New(isolate, error));
  if (error) {
    result->Set(TRI_V8_ASCII_STRING("errorNum"),
                v8::Number::New(isolate, cic->errorNum(shardID)));
    std::string const errorMessage = cic->errorMessage(shardID);
    result->Set(TRI_V8_ASCII_STRING("errorMessage"),
                TRI_V8_STD_STRING(errorMessage));
  }
  auto servers = cic->servers(shardID);
  v8::Handle<v8::Array> list =
      v8::Array::New(isolate, static_cast<int>(servers.size()));
  v8::Handle<v8::Array> shorts =
      v8::Array::New(isolate, static_cast<int>(servers.size()));
  auto serverAliases = ClusterInfo::instance()->getServerAliases();
  uint32_t pos = 0;
  for (auto const& s : servers) {
    try {
      shorts->Set(pos, TRI_V8_STD_STRING(serverAliases.at(s)));
    } catch (...) {}
    list->Set(pos++, TRI_V8_STD_STRING(s));
  }
  result->Set(TRI_V8_ASCII_STRING("servers"), list);
  result->Set(TRI_V8_ASCII_STRING("shorts"), shorts);

  TRI_V8_RETURN(result);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get the responsible server
////////////////////////////////////////////////////////////////////////////////

static void JS_GetResponsibleServerClusterInfo(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  ONLY_IN_CLUSTER
  if (args.Length() != 1) {
    TRI_V8_THROW_EXCEPTION_USAGE("getResponsibleServer(<shard-id>)");
  }

  auto result = ClusterInfo::instance()->getResponsibleServer(
      TRI_ObjectToString(args[0]));
  v8::Handle<v8::Array> list = v8::Array::New(isolate, (int)result->size());
  uint32_t count = 0;
  for (auto const& s : *result) {
    list->Set(count++, TRI_V8_STD_STRING(s));
  }

  TRI_V8_RETURN(list);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get the responsible shard
////////////////////////////////////////////////////////////////////////////////

static void JS_GetResponsibleShardClusterInfo(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  ONLY_IN_CLUSTER
  if (args.Length() < 2 || args.Length() > 3) {
    TRI_V8_THROW_EXCEPTION_USAGE(
        "getResponsibleShard(<collection-id>, <document>, "
        "<documentIsComplete>)");
  }

  if (!args[0]->IsString() && !args[0]->IsStringObject()) {
    TRI_V8_THROW_TYPE_ERROR("expecting a string for <collection-id>)");
  }

  if (!args[1]->IsObject()) {
    TRI_V8_THROW_TYPE_ERROR("expecting an object for <document>)");
  }

  bool documentIsComplete = true;
  if (args.Length() > 2) {
    documentIsComplete = TRI_ObjectToBoolean(args[2]);
  }

  VPackBuilder builder;
  int res = TRI_V8ToVPack(isolate, builder, args[1], false);

  if (res != TRI_ERROR_NO_ERROR) {
    TRI_V8_THROW_EXCEPTION(res);
  }

  ShardID shardId;
  CollectionID collectionId = TRI_ObjectToString(args[0]);
  auto vocbase = GetContextVocBase(isolate);
  auto ci = ClusterInfo::instance();
  auto collInfo = ci->getCollection(vocbase->name(), collectionId);
  bool usesDefaultShardingAttributes;
  res = ClusterInfo::instance()->getResponsibleShard(
      collInfo.get(), builder.slice(), documentIsComplete, shardId,
      usesDefaultShardingAttributes);

  if (res != TRI_ERROR_NO_ERROR) {
    TRI_V8_THROW_EXCEPTION(res);
  }

  v8::Handle<v8::Object> result = v8::Object::New(isolate);
  result->Set(TRI_V8_ASCII_STRING("shardId"), TRI_V8_STD_STRING(shardId));
  result->Set(TRI_V8_ASCII_STRING("usesDefaultShardingAttributes"),
              v8::Boolean::New(isolate, usesDefaultShardingAttributes));

  TRI_V8_RETURN(result);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get the server endpoint for a server
////////////////////////////////////////////////////////////////////////////////

static void JS_GetServerEndpointClusterInfo(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  ONLY_IN_CLUSTER
  if (args.Length() != 1) {
    TRI_V8_THROW_EXCEPTION_USAGE("getServerEndpoint(<server-id>)");
  }

  std::string const result =
      ClusterInfo::instance()->getServerEndpoint(TRI_ObjectToString(args[0]));

  TRI_V8_RETURN_STD_STRING(result);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get the server name for an endpoint
////////////////////////////////////////////////////////////////////////////////

static void JS_GetServerNameClusterInfo(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  ONLY_IN_CLUSTER
  if (args.Length() != 1) {
    TRI_V8_THROW_EXCEPTION_USAGE("getServerName(<endpoint>)");
  }

  std::string const result =
      ClusterInfo::instance()->getServerName(TRI_ObjectToString(args[0]));

  TRI_V8_RETURN_STD_STRING(result);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief returns the DBServers currently registered
////////////////////////////////////////////////////////////////////////////////

static void JS_GetDBServers(v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  ONLY_IN_CLUSTER
  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("getDBServers()");
  }

  auto DBServers = ClusterInfo::instance()->getCurrentDBServers();
  auto serverAliases = ClusterInfo::instance()->getServerAliases();

  v8::Handle<v8::Array> l = v8::Array::New(isolate);

  for (size_t i = 0; i < DBServers.size(); ++i) {
    v8::Handle<v8::Object> result = v8::Object::New(isolate);
    auto id = DBServers[i];

    result->Set(TRI_V8_ASCII_STRING("serverId"), TRI_V8_STD_STRING(id));

    auto itr = serverAliases.find(id);

    if (itr != serverAliases.end()) {
      result->Set(TRI_V8_ASCII_STRING("serverName"),
		  TRI_V8_STD_STRING(itr->second));
    } else {
      result->Set(TRI_V8_ASCII_STRING("serverName"),
		  TRI_V8_STD_STRING(id));
    }

    l->Set((uint32_t)i, result);
  }

  TRI_V8_RETURN(l);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief reloads the cache of DBServers currently registered
////////////////////////////////////////////////////////////////////////////////

static void JS_ReloadDBServers(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  ONLY_IN_CLUSTER
  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("reloadDBServers()");
  }

  ClusterInfo::instance()->loadCurrentDBServers();
  TRI_V8_RETURN_UNDEFINED();
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief returns the coordinators currently registered
////////////////////////////////////////////////////////////////////////////////

static void JS_GetCoordinators(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  ONLY_IN_CLUSTER

  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("getCoordinators()");
  }

  std::vector<std::string> coordinators =
      ClusterInfo::instance()->getCurrentCoordinators();

  v8::Handle<v8::Array> l = v8::Array::New(isolate);

  for (size_t i = 0; i < coordinators.size(); ++i) {
    ServerID const sid = coordinators[i];

    l->Set((uint32_t)i, TRI_V8_STD_STRING(sid));
  }

  TRI_V8_RETURN(l);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief returns a unique id
////////////////////////////////////////////////////////////////////////////////

static void JS_UniqidClusterInfo(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  if (args.Length() > 1) {
    TRI_V8_THROW_EXCEPTION_USAGE("uniqid(<count>)");
  }

  uint64_t count = 1;
  if (args.Length() > 0) {
    count = TRI_ObjectToUInt64(args[0], true);
  }

  if (count == 0) {
    TRI_V8_THROW_EXCEPTION_PARAMETER("<count> is invalid");
  }

  uint64_t value = ClusterInfo::instance()->uniqid(count);

  if (value == 0) {
    TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
                                   "unable to generate unique id");
  }

  std::string const id = StringUtils::itoa(value);

  TRI_V8_RETURN_STD_STRING(id);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief return the servers address
////////////////////////////////////////////////////////////////////////////////

static void JS_AddressServerState(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("address()");
  }

  std::string const address = ServerState::instance()->getAddress();
  TRI_V8_RETURN_STD_STRING(address);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief flush the server state (used for testing only)
////////////////////////////////////////////////////////////////////////////////

static void JS_FlushServerState(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("flush()");
  }

  ServerState::instance()->flush();

  TRI_V8_RETURN_TRUE();
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief return the servers local info
////////////////////////////////////////////////////////////////////////////////

static void JS_LocalInfoServerState(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  ONLY_IN_CLUSTER
  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("localInfo()");
  }

  std::string const li = ServerState::instance()->getLocalInfo();
  TRI_V8_RETURN_STD_STRING(li);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief return the servers id
////////////////////////////////////////////////////////////////////////////////

static void JS_IdServerState(v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  ONLY_IN_CLUSTER
  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("id()");
  }

  std::string const id = ServerState::instance()->getId();
  TRI_V8_RETURN_STD_STRING(id);
  TRI_V8_TRY_CATCH_END
}

static void JS_isFoxxmaster(v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("isFoxxmaster()");
  }

  if (ServerState::instance()->isFoxxmaster()) {
    TRI_V8_RETURN_TRUE();
  } else {
    TRI_V8_RETURN_FALSE();
  }
  TRI_V8_TRY_CATCH_END
}

static void JS_getFoxxmaster(v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("getFoxxmaster()");
  }

  std::string const id = ServerState::instance()->getFoxxmaster();
  TRI_V8_RETURN_STD_STRING(id);
  TRI_V8_TRY_CATCH_END
}

static void JS_getFoxxmasterQueueupdate(
  v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("getFoxxmasterQueueupdate()");
  }

  if (ServerState::instance()->getFoxxmasterQueueupdate()) {
    TRI_V8_RETURN_TRUE();
  } else {
    TRI_V8_RETURN_FALSE();
  }
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief return the primary servers id (only for secondaries)
////////////////////////////////////////////////////////////////////////////////

static void JS_IdOfPrimaryServerState(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  ONLY_IN_CLUSTER
  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("idOfPrimary()");
  }

  std::string const id = ServerState::instance()->getPrimaryId();
  TRI_V8_RETURN_STD_STRING(id);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief return the servers description
////////////////////////////////////////////////////////////////////////////////

static void JS_DescriptionServerState(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("description()");
  }

  std::string const description = ServerState::instance()->getDescription();
  TRI_V8_RETURN_STD_STRING(description);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief returns the javascript startup path
////////////////////////////////////////////////////////////////////////////////

static void JS_JavaScriptPathServerState(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("javaScriptPath()");
  }

  std::string const path = ServerState::instance()->getJavaScriptPath();
  TRI_V8_RETURN_STD_STRING(path);
  TRI_V8_TRY_CATCH_END
}

#ifdef DEBUG_SYNC_REPLICATION
////////////////////////////////////////////////////////////////////////////////
/// @brief set arangoserver state to initialized
////////////////////////////////////////////////////////////////////////////////

static void JS_EnableSyncReplicationDebug(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("enableSyncReplicationDebug()");
  }

  ServerState::instance()->setInitialized();
  ServerState::instance()->setId("repltest");
  AgencyComm::syncReplDebug = true;
  TRI_V8_TRY_CATCH_END
}
#endif

////////////////////////////////////////////////////////////////////////////////
/// @brief return whether the cluster is initialized
////////////////////////////////////////////////////////////////////////////////

static void JS_InitializedServerState(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("initialized()");
  }

  if (ServerState::instance()->initialized()) {
    TRI_V8_RETURN_TRUE();
  }
  TRI_V8_RETURN_FALSE();
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the server is a coordinator
////////////////////////////////////////////////////////////////////////////////

static void JS_IsCoordinatorServerState(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("isCoordinator()");
  }

  if (ServerState::instance()->getRole() == ServerState::ROLE_COORDINATOR) {
    TRI_V8_RETURN_TRUE();
  }
  TRI_V8_RETURN_FALSE();
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief returns the server role
////////////////////////////////////////////////////////////////////////////////

static void JS_RoleServerState(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("role()");
  }

  std::string const role =
      ServerState::roleToString(ServerState::instance()->getRole());

  TRI_V8_RETURN_STD_STRING(role);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief sets the server local info (used for testing)
////////////////////////////////////////////////////////////////////////////////

static void JS_SetLocalInfoServerState(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  ONLY_IN_CLUSTER
  if (args.Length() != 1) {
    TRI_V8_THROW_EXCEPTION_USAGE("setLocalInfo(<info>)");
  }

  std::string const li = TRI_ObjectToString(args[0]);
  ServerState::instance()->setLocalInfo(li);

  TRI_V8_RETURN_TRUE();
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief sets the server id (used for testing)
////////////////////////////////////////////////////////////////////////////////

static void JS_SetIdServerState(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  if (args.Length() != 1) {
    TRI_V8_THROW_EXCEPTION_USAGE("setId(<id>)");
  }

  std::string const id = TRI_ObjectToString(args[0]);
  ServerState::instance()->setId(id);

  TRI_V8_RETURN_TRUE();
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief sets the server role (used for testing)
////////////////////////////////////////////////////////////////////////////////

static void JS_SetRoleServerState(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  if (args.Length() != 1) {
    TRI_V8_THROW_EXCEPTION_USAGE("setRole(<role>)");
  }

  std::string const role = TRI_ObjectToString(args[0]);
  ServerState::RoleEnum r = ServerState::stringToRole(role);

  if (r == ServerState::ROLE_UNDEFINED) {
    TRI_V8_THROW_EXCEPTION_PARAMETER("<role> is invalid");
  }

  ServerState::instance()->setRole(r);

  TRI_V8_RETURN_TRUE();
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief redetermines the role from the agency
////////////////////////////////////////////////////////////////////////////////

static void JS_RedetermineRoleServerState(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  ONLY_IN_CLUSTER
  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("redetermineRole()");
  }

  bool changed = ServerState::instance()->redetermineRole();
  if (changed) {
    TRI_V8_RETURN_TRUE();
  } else {
    TRI_V8_RETURN_FALSE();
  }
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief returns the server state
////////////////////////////////////////////////////////////////////////////////

static void JS_StatusServerState(
    v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);

  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("status()");
  }

  std::string const state =
      ServerState::stateToString(ServerState::instance()->getState());

  TRI_V8_RETURN_STD_STRING(state);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief prepare to send a request
///
/// this is used for asynchronous as well as synchronous requests.
////////////////////////////////////////////////////////////////////////////////

static void PrepareClusterCommRequest(
    v8::FunctionCallbackInfo<v8::Value> const& args,
    arangodb::rest::RequestType& reqType, std::string& destination,
    std::string& path, std::string& body,
    std::unordered_map<std::string, std::string>& headerFields,
    ClientTransactionID& clientTransactionID,
    CoordTransactionID& coordTransactionID, double& timeout,
    bool& singleRequest, double& initTimeout) {
  v8::Isolate* isolate = args.GetIsolate();
  TRI_V8_CURRENT_GLOBALS_AND_SCOPE;

  ONLY_IN_CLUSTER
  TRI_ASSERT(args.Length() >= 4);

  reqType = arangodb::rest::RequestType::GET;
  if (args[0]->IsString()) {
    TRI_Utf8ValueNFC UTF8(TRI_UNKNOWN_MEM_ZONE, args[0]);
    std::string methstring = *UTF8;
    reqType = arangodb::HttpRequest::translateMethod(methstring);
    if (reqType == arangodb::rest::RequestType::ILLEGAL) {
      reqType = arangodb::rest::RequestType::GET;
    }
  }

  destination = TRI_ObjectToString(args[1]);

  std::string dbname = TRI_ObjectToString(args[2]);

  path = TRI_ObjectToString(args[3]);
  path = "/_db/" + dbname + path;

  body.clear();
  if (!args[4]->IsUndefined()) {
    if (args[4]->IsObject() && V8Buffer::hasInstance(isolate, args[4])) {
      // supplied body is a Buffer object
      char const* data = V8Buffer::data(args[4].As<v8::Object>());
      size_t size = V8Buffer::length(args[4].As<v8::Object>());

      if (data == nullptr) {
        TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER,
                                       "invalid <body> buffer value");
      }

      body.assign(data, size);
    } else {
      body = TRI_ObjectToString(args[4]);
    }
  }

  if (args.Length() > 5 && args[5]->IsObject()) {
    v8::Handle<v8::Object> obj = args[5].As<v8::Object>();
    v8::Handle<v8::Array> props = obj->GetOwnPropertyNames();
    uint32_t i;
    for (i = 0; i < props->Length(); ++i) {
      v8::Handle<v8::Value> prop = props->Get(i);
      v8::Handle<v8::Value> val = obj->Get(prop);
      std::string propstring = TRI_ObjectToString(prop);
      std::string valstring = TRI_ObjectToString(val);
      if (propstring != "") {
        headerFields.insert(std::make_pair(propstring, valstring));
      }
    }
  }

  clientTransactionID = "";
  coordTransactionID = 0;
  timeout = 24 * 3600.0;
  singleRequest = false;

  if (args.Length() > 6 && args[6]->IsObject()) {
    v8::Handle<v8::Object> opt = args[6].As<v8::Object>();
    TRI_GET_GLOBAL_STRING(ClientTransactionIDKey);
    if (opt->Has(ClientTransactionIDKey)) {
      clientTransactionID =
          TRI_ObjectToString(opt->Get(ClientTransactionIDKey));
    }
    TRI_GET_GLOBAL_STRING(CoordTransactionIDKey);
    if (opt->Has(CoordTransactionIDKey)) {
      coordTransactionID =
          TRI_ObjectToUInt64(opt->Get(CoordTransactionIDKey), true);
    }
    TRI_GET_GLOBAL_STRING(TimeoutKey);
    if (opt->Has(TimeoutKey)) {
      timeout = TRI_ObjectToDouble(opt->Get(TimeoutKey));
    }
    TRI_GET_GLOBAL_STRING(SingleRequestKey);
    if (opt->Has(SingleRequestKey)) {
      singleRequest = TRI_ObjectToBoolean(opt->Get(SingleRequestKey));
    }
    TRI_GET_GLOBAL_STRING(InitTimeoutKey);
    if (opt->Has(InitTimeoutKey)) {
      initTimeout = TRI_ObjectToDouble(opt->Get(InitTimeoutKey));
    }
  }
  if (clientTransactionID == "") {
    clientTransactionID = StringUtils::itoa(TRI_NewTickServer());
  }
  if (coordTransactionID == 0) {
    coordTransactionID = TRI_NewTickServer();
  }
  if (timeout == 0) {
    timeout = 24 * 3600.0;
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief prepare a ClusterCommResult for JavaScript
////////////////////////////////////////////////////////////////////////////////

static void Return_PrepareClusterCommResultForJS(
    v8::FunctionCallbackInfo<v8::Value> const& args,
    ClusterCommResult const& res) {
  v8::Isolate* isolate = args.GetIsolate();
  TRI_V8_CURRENT_GLOBALS_AND_SCOPE;

  v8::Handle<v8::Object> r = v8::Object::New(isolate);
  if (res.dropped) {
    TRI_GET_GLOBAL_STRING(ErrorMessageKey);
    r->Set(ErrorMessageKey, TRI_V8_ASCII_STRING("operation was dropped"));
  } else {
    TRI_GET_GLOBAL_STRING(ClientTransactionIDKey);
    r->Set(ClientTransactionIDKey, TRI_V8_STD_STRING(res.clientTransactionID));

    // convert the ids to strings as uint64_t might be too big for JavaScript
    // numbers
    TRI_GET_GLOBAL_STRING(CoordTransactionIDKey);
    std::string id = StringUtils::itoa(res.coordTransactionID);
    r->Set(CoordTransactionIDKey, TRI_V8_STD_STRING(id));

    id = StringUtils::itoa(res.operationID);
    TRI_GET_GLOBAL_STRING(OperationIDKey);
    r->Set(OperationIDKey, TRI_V8_STD_STRING(id));
    TRI_GET_GLOBAL_STRING(EndpointKey);
    r->Set(EndpointKey, TRI_V8_STD_STRING(res.endpoint));
    TRI_GET_GLOBAL_STRING(SingleRequestKey);
    r->Set(SingleRequestKey, v8::Boolean::New(isolate, res.single));
    TRI_GET_GLOBAL_STRING(ShardIDKey);
    r->Set(ShardIDKey, TRI_V8_STD_STRING(res.shardID));

    if (res.status == CL_COMM_SUBMITTED) {
      TRI_GET_GLOBAL_STRING(StatusKey);
      r->Set(StatusKey, TRI_V8_ASCII_STRING("SUBMITTED"));
    } else if (res.status == CL_COMM_SENDING) {
      TRI_GET_GLOBAL_STRING(StatusKey);
      r->Set(StatusKey, TRI_V8_ASCII_STRING("SENDING"));
    } else if (res.status == CL_COMM_SENT) {
      TRI_GET_GLOBAL_STRING(StatusKey);
      r->Set(StatusKey, TRI_V8_ASCII_STRING("SENT"));
      // This might be the result of a synchronous request or an asynchronous
      // request with the `singleRequest` flag true and thus contain the
      // actual response. If it is an asynchronous request which has not
      // yet been answered, the following information is probably rather
      // boring:

      // The headers:
      TRI_ASSERT(res.result != nullptr);
      v8::Handle<v8::Object> h = v8::Object::New(isolate);
      for (auto const& i : res.result->getHeaderFields()) {
        h->Set(TRI_V8_STD_STRING(i.first), TRI_V8_STD_STRING(i.second));
      }
      r->Set(TRI_V8_ASCII_STRING("headers"), h);

      // The body:
      arangodb::basics::StringBuffer& body = res.result->getBody();
      if (body.length() != 0) {
        r->Set(TRI_V8_ASCII_STRING("body"), TRI_V8_STD_STRING(body));
        V8Buffer* buffer =
            V8Buffer::New(isolate, body.c_str(), body.length());
        v8::Local<v8::Object> bufferObject =
            v8::Local<v8::Object>::New(isolate, buffer->_handle);
        r->Set(TRI_V8_ASCII_STRING("rawBody"), bufferObject);
      }
    } else if (res.status == CL_COMM_TIMEOUT) {
      TRI_GET_GLOBAL_STRING(StatusKey);
      r->Set(StatusKey, TRI_V8_ASCII_STRING("TIMEOUT"));
      TRI_GET_GLOBAL_STRING(TimeoutKey);
      r->Set(TimeoutKey, v8::BooleanObject::New(true));
    } else if (res.status == CL_COMM_ERROR) {
      TRI_GET_GLOBAL_STRING(StatusKey);
      r->Set(StatusKey, TRI_V8_ASCII_STRING("ERROR"));

      if (res.result && res.result->isComplete()) {
        v8::Handle<v8::Object> details = v8::Object::New(isolate);
        details->Set(TRI_V8_ASCII_STRING("code"),
                     v8::Number::New(isolate, res.result->getHttpReturnCode()));
        details->Set(TRI_V8_ASCII_STRING("message"),
                     TRI_V8_STD_STRING(res.result->getHttpReturnMessage()));
        arangodb::basics::StringBuffer& body = res.result->getBody();
        details->Set(TRI_V8_ASCII_STRING("body"), TRI_V8_STD_STRING(body));
        V8Buffer* buffer =
            V8Buffer::New(isolate, body.c_str(), body.length());
        v8::Local<v8::Object> bufferObject =
            v8::Local<v8::Object>::New(isolate, buffer->_handle);
        details->Set(TRI_V8_ASCII_STRING("rawBody"), bufferObject);

        r->Set(TRI_V8_ASCII_STRING("details"), details);
        TRI_GET_GLOBAL_STRING(ErrorMessageKey);
        r->Set(ErrorMessageKey, TRI_V8_STD_STRING(res.errorMessage));
      } else {
        TRI_GET_GLOBAL_STRING(ErrorMessageKey);
        r->Set(ErrorMessageKey, TRI_V8_STD_STRING(res.errorMessage));
      }
    } else if (res.status == CL_COMM_DROPPED) {
      TRI_GET_GLOBAL_STRING(StatusKey);
      r->Set(StatusKey, TRI_V8_ASCII_STRING("DROPPED"));
      TRI_GET_GLOBAL_STRING(ErrorMessageKey);
      r->Set(ErrorMessageKey,
             TRI_V8_ASCII_STRING("request dropped whilst waiting for answer"));
    } else if (res.status == CL_COMM_BACKEND_UNAVAILABLE) {
      TRI_GET_GLOBAL_STRING(StatusKey);
      r->Set(StatusKey, TRI_V8_ASCII_STRING("BACKEND_UNAVAILABLE"));
      TRI_GET_GLOBAL_STRING(ErrorMessageKey);
      r->Set(ErrorMessageKey,
             TRI_V8_ASCII_STRING("required backend was not available"));
    } else if (res.status == CL_COMM_RECEIVED) {  // Everything is OK
      // FIXME HANDLE VST
      auto httpRequest = std::dynamic_pointer_cast<HttpRequest>(res.answer);
      if (httpRequest == nullptr) {
        THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid request type");
      }

      // The headers:
      v8::Handle<v8::Object> h = v8::Object::New(isolate);
      TRI_GET_GLOBAL_STRING(StatusKey);
      r->Set(StatusKey, TRI_V8_ASCII_STRING("RECEIVED"));
      TRI_ASSERT(res.answer != nullptr);
      std::unordered_map<std::string, std::string> headers =
          res.answer->headers();
      headers["content-length"] =
          StringUtils::itoa(httpRequest->contentLength());
      for (auto& it : headers) {
        h->Set(TRI_V8_STD_STRING(it.first), TRI_V8_STD_STRING(it.second));
      }
      r->Set(TRI_V8_ASCII_STRING("headers"), h);

      // The body:
      std::string const& body = httpRequest->body();
      if (!body.empty()) {
        r->Set(TRI_V8_ASCII_STRING("body"), TRI_V8_STD_STRING(body));
        V8Buffer* buffer =
            V8Buffer::New(isolate, body.c_str(), body.length());
        v8::Local<v8::Object> bufferObject =
            v8::Local<v8::Object>::New(isolate, buffer->_handle);
        r->Set(TRI_V8_ASCII_STRING("rawBody"), bufferObject);
      }

    } else {
      TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
                                     "unknown ClusterComm result status");
    }
  }

  TRI_V8_RETURN(r);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief send an asynchronous request
////////////////////////////////////////////////////////////////////////////////

static void JS_AsyncRequest(v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);
  ONLY_IN_CLUSTER

  if (args.Length() < 4 || args.Length() > 7) {
    TRI_V8_THROW_EXCEPTION_USAGE(
        "asyncRequest("
        "reqType, destination, dbname, path, body, headers, options)");
  }
  // Possible options:
  //   - clientTransactionID  (string)
  //   - coordTransactionID   (number)
  //   - timeout              (number)
  //   - singleRequest        (boolean) default is false
  //   - initTimeout          (number)

  auto cc = ClusterComm::instance();

  if (cc == nullptr) {
    TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_SHUTTING_DOWN,
      "clustercomm object not found (JS_AsyncRequest)");
  }

  arangodb::rest::RequestType reqType;
  std::string destination;
  std::string path;
  auto body = std::make_shared<std::string>();
  auto headerFields =
      std::make_unique<std::unordered_map<std::string, std::string>>();
  ClientTransactionID clientTransactionID;
  CoordTransactionID coordTransactionID;
  double timeout;
  double initTimeout = -1.0;
  bool singleRequest = false;

  PrepareClusterCommRequest(args, reqType, destination, path, *body,
                            *headerFields, clientTransactionID,
                            coordTransactionID, timeout, singleRequest,
                            initTimeout);

  OperationID opId = cc->asyncRequest(
      clientTransactionID, coordTransactionID, destination, reqType, path, body,
      headerFields, 0, timeout, singleRequest, initTimeout);
  ClusterCommResult res = cc->enquire(opId);
  if (res.status == CL_COMM_BACKEND_UNAVAILABLE) {
    TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
                                   "couldn't queue async request");
  }

  LOG_TOPIC(DEBUG, Logger::CLUSTER)
    << "JS_AsyncRequest: request has been submitted";

  Return_PrepareClusterCommResultForJS(args, res);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief send a synchronous request
////////////////////////////////////////////////////////////////////////////////

static void JS_SyncRequest(v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);
  ONLY_IN_CLUSTER

  if (args.Length() < 4 || args.Length() > 7) {
    TRI_V8_THROW_EXCEPTION_USAGE(
        "syncRequest("
        "reqType, destination, dbname, path, body, headers, options)");
  }
  // Possible options:
  //   - clientTransactionID  (string)
  //   - coordTransactionID   (number)
  //   - timeout              (number)

  // Disabled to allow communication originating in a DBserver:
  // 31.7.2014 Max

  // if (ServerState::instance()->getRole() != ServerState::ROLE_COORDINATOR) {
  //  TRI_V8_THROW_EXCEPTION_INTERNAL(scope,"request works only in coordinator
  //  role");
  //}

  auto cc = ClusterComm::instance();

  if (cc == nullptr) {
    TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_SHUTTING_DOWN,
                                   "clustercomm object not found");
  }

  arangodb::rest::RequestType reqType;
  std::string destination;
  std::string path;
  std::string body;
  auto headerFields =
      std::make_unique<std::unordered_map<std::string, std::string>>();
  ClientTransactionID clientTransactionID;
  CoordTransactionID coordTransactionID;
  double timeout;
  double initTimeout = -1.0;
  bool singleRequest = false;  // of no relevance here

  PrepareClusterCommRequest(args, reqType, destination, path, body,
                            *headerFields, clientTransactionID,
                            coordTransactionID, timeout, singleRequest,
                            initTimeout);

  std::unique_ptr<ClusterCommResult> res =
      cc->syncRequest(clientTransactionID, coordTransactionID, destination,
                      reqType, path, body, *headerFields, timeout);

  if (res.get() == nullptr) {
    TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
                                   "couldn't do sync request");
  }

  LOG_TOPIC(DEBUG, Logger::CLUSTER) << "JS_SyncRequest: request has been done";

  Return_PrepareClusterCommResultForJS(args, *res);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief enquire information about an asynchronous request
////////////////////////////////////////////////////////////////////////////////

static void JS_Enquire(v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);
  ONLY_IN_CLUSTER

  if (args.Length() != 1) {
    TRI_V8_THROW_EXCEPTION_USAGE("enquire(operationID)");
  }

  auto cc = ClusterComm::instance();

  if (cc == nullptr) {
    TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
      "clustercomm object not found (JS_SyncRequest)");
  }

  OperationID operationID = TRI_ObjectToUInt64(args[0], true);

  LOG_TOPIC(DEBUG, Logger::CLUSTER)
    << "JS_Enquire: calling ClusterComm::enquire()";

  ClusterCommResult const res = cc->enquire(operationID);

  Return_PrepareClusterCommResultForJS(args, res);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief wait for the result of an asynchronous request
////////////////////////////////////////////////////////////////////////////////

static void JS_Wait(v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  TRI_V8_CURRENT_GLOBALS_AND_SCOPE;
  ONLY_IN_CLUSTER

  if (args.Length() != 1) {
    TRI_V8_THROW_EXCEPTION_USAGE("wait(obj)");
  }
  // Possible options:
  //   - clientTransactionID  (string)
  //   - coordTransactionID   (number)
  //   - operationID          (number)
  //   - shardID              (string)
  //   - timeout              (number)

  auto cc = ClusterComm::instance();

  if (cc == nullptr) {
    TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_SHUTTING_DOWN,
                                   "clustercomm object not found (JS_Wait)");
  }

  ClientTransactionID myclientTransactionID = "";
  CoordTransactionID mycoordTransactionID = 0;
  OperationID myoperationID = 0;
  ShardID myshardID = "";
  double mytimeout = 24 * 3600.0;

  if (args[0]->IsObject()) {
    v8::Handle<v8::Object> obj = args[0].As<v8::Object>();
    TRI_GET_GLOBAL_STRING(ClientTransactionIDKey);
    if (obj->Has(ClientTransactionIDKey)) {
      myclientTransactionID =
          TRI_ObjectToString(obj->Get(ClientTransactionIDKey));
    }
    TRI_GET_GLOBAL_STRING(CoordTransactionIDKey);
    if (obj->Has(CoordTransactionIDKey)) {
      mycoordTransactionID =
          TRI_ObjectToUInt64(obj->Get(CoordTransactionIDKey), true);
    }
    TRI_GET_GLOBAL_STRING(OperationIDKey);
    if (obj->Has(OperationIDKey)) {
      myoperationID = TRI_ObjectToUInt64(obj->Get(OperationIDKey), true);
    }
    TRI_GET_GLOBAL_STRING(ShardIDKey);
    if (obj->Has(ShardIDKey)) {
      myshardID = TRI_ObjectToString(obj->Get(ShardIDKey));
    }
    TRI_GET_GLOBAL_STRING(TimeoutKey);
    if (obj->Has(TimeoutKey)) {
      mytimeout = TRI_ObjectToDouble(obj->Get(TimeoutKey));
      if (mytimeout == 0.0) {
        mytimeout = 24 * 3600.0;
      }
    }
  }

  LOG_TOPIC(DEBUG, Logger::CLUSTER) << "JS_Wait: calling ClusterComm::wait()";

  ClusterCommResult const res =
      cc->wait(myclientTransactionID, mycoordTransactionID, myoperationID,
               myshardID, mytimeout);

  Return_PrepareClusterCommResultForJS(args, res);
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief drop the result of an asynchronous request
////////////////////////////////////////////////////////////////////////////////

static void JS_Drop(v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  TRI_V8_CURRENT_GLOBALS_AND_SCOPE;
  ONLY_IN_CLUSTER

  if (args.Length() != 1) {
    TRI_V8_THROW_EXCEPTION_USAGE("drop(obj)");
  }
  // Possible options:
  //   - clientTransactionID  (string)
  //   - coordTransactionID   (number)
  //   - operationID          (number)
  //   - shardID              (string)

  auto cc = ClusterComm::instance();

  if (cc == nullptr) {
    TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
                                   "clustercomm object not found (JS_Drop)");
  }

  ClientTransactionID myclientTransactionID = "";
  CoordTransactionID mycoordTransactionID = 0;
  OperationID myoperationID = 0;
  ShardID myshardID = "";

  if (args[0]->IsObject()) {
    v8::Handle<v8::Object> obj = args[0].As<v8::Object>();
    TRI_GET_GLOBAL_STRING(ClientTransactionIDKey);
    if (obj->Has(ClientTransactionIDKey)) {
      myclientTransactionID =
          TRI_ObjectToString(obj->Get(ClientTransactionIDKey));
    }
    TRI_GET_GLOBAL_STRING(CoordTransactionIDKey);
    if (obj->Has(CoordTransactionIDKey)) {
      mycoordTransactionID =
          TRI_ObjectToUInt64(obj->Get(CoordTransactionIDKey), true);
    }
    TRI_GET_GLOBAL_STRING(OperationIDKey);
    if (obj->Has(OperationIDKey)) {
      myoperationID = TRI_ObjectToUInt64(obj->Get(OperationIDKey), true);
    }
    TRI_GET_GLOBAL_STRING(ShardIDKey);
    if (obj->Has(ShardIDKey)) {
      myshardID = TRI_ObjectToString(obj->Get(ShardIDKey));
    }
  }

  LOG_TOPIC(DEBUG, Logger::CLUSTER) << "JS_Drop: calling ClusterComm::drop()";

  cc->drop(myclientTransactionID, mycoordTransactionID, myoperationID,
           myshardID);

  TRI_V8_RETURN_UNDEFINED();
  TRI_V8_TRY_CATCH_END
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get an ID for use with coordTransactionId
////////////////////////////////////////////////////////////////////////////////

static void JS_GetId(v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  ONLY_IN_CLUSTER

  if (args.Length() != 0) {
    TRI_V8_THROW_EXCEPTION_USAGE("getId()");
  }

  auto id = TRI_NewTickServer();
  std::string st = StringUtils::itoa(id);
  v8::Handle<v8::String> s = TRI_V8_ASCII_STRING(st.c_str());

  TRI_V8_RETURN(s);
  TRI_V8_TRY_CATCH_END
}

static void JS_ClusterDownload(v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);

  auto authentication = FeatureCacheFeature::instance()->authenticationFeature();
  if (authentication->isActive()) {
    // mop: really quick and dirty
    v8::Handle<v8::Object> options = v8::Object::New(isolate);
    v8::Handle<v8::Object> headers = v8::Object::New(isolate);
    if (args.Length() > 2) {
      if (args[2]->IsObject()) {
        options = v8::Handle<v8::Object>::Cast(args[2]);
        if (options->Has(TRI_V8_ASCII_STRING("headers"))) {
          headers = v8::Handle<v8::Object>::Cast(options->Get(TRI_V8_ASCII_STRING("headers")));
        }
      }
    }
    options->Set(TRI_V8_ASCII_STRING("headers"), headers);

    auto cc = ClusterComm::instance();
    if (cc != nullptr) {
      // nullptr happens only during controlled shutdown
      std::string authorization = "bearer " + ClusterComm::instance()->jwt();
      v8::Handle<v8::String> v8Authorization = TRI_V8_STD_STRING(authorization);
      headers->Set(TRI_V8_ASCII_STRING("Authorization"), v8Authorization);
    }
    args[2] = options;
  }
  TRI_V8_TRY_CATCH_END
  return JS_Download(args);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief creates a global cluster context
////////////////////////////////////////////////////////////////////////////////

void TRI_InitV8Cluster(v8::Isolate* isolate, v8::Handle<v8::Context> context) {
  TRI_V8_CURRENT_GLOBALS_AND_SCOPE;
  TRI_ASSERT(v8g != nullptr);

  v8::Handle<v8::ObjectTemplate> rt;
  v8::Handle<v8::FunctionTemplate> ft;

  // ...........................................................................
  // generate the agency template
  // ...........................................................................

  ft = v8::FunctionTemplate::New(isolate);
  ft->SetClassName(TRI_V8_ASCII_STRING("ArangoAgency"));

  rt = ft->InstanceTemplate();
  rt->SetInternalFieldCount(2);

  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("read"), JS_ReadAgency);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("write"), JS_WriteAgency);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("transact"), JS_TransactAgency);

  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("cas"), JS_CasAgency);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("createDirectory"),
                       JS_CreateDirectoryAgency);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("get"), JS_GetAgency);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("isEnabled"),
                       JS_IsEnabledAgency);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("increaseVersion"),
                       JS_IncreaseVersionAgency);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("remove"),
                       JS_RemoveAgency);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("set"), JS_SetAgency);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("endpoints"),
                       JS_EndpointsAgency);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("prefix"),
                       JS_PrefixAgency);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("uniqid"),
                       JS_UniqidAgency);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("version"),
                       JS_VersionAgency);

  v8g->AgencyTempl.Reset(isolate, rt);
  ft->SetClassName(TRI_V8_ASCII_STRING("ArangoAgencyCtor"));

  TRI_AddGlobalFunctionVocbase(isolate,
                               TRI_V8_ASCII_STRING("ArangoAgencyCtor"),
                               ft->GetFunction(), true);

  // register the global object
  v8::Handle<v8::Object> aa = rt->NewInstance();
  if (!aa.IsEmpty()) {
    TRI_AddGlobalVariableVocbase(isolate,
                                 TRI_V8_ASCII_STRING("ArangoAgency"), aa);
  }

  // ...........................................................................
  // generate the cluster info template
  // ...........................................................................

  ft = v8::FunctionTemplate::New(isolate);
  ft->SetClassName(TRI_V8_ASCII_STRING("ArangoClusterInfo"));

  rt = ft->InstanceTemplate();
  rt->SetInternalFieldCount(2);

  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("doesDatabaseExist"),
                       JS_DoesDatabaseExistClusterInfo);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("databases"),
                       JS_Databases);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("flush"),
                       JS_FlushClusterInfo, true);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("getCollectionInfo"),
                       JS_GetCollectionInfoClusterInfo);
  TRI_AddMethodVocbase(isolate, rt,
                       TRI_V8_ASCII_STRING("getCollectionInfoCurrent"),
                       JS_GetCollectionInfoCurrentClusterInfo);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("getResponsibleServer"),
                       JS_GetResponsibleServerClusterInfo);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("getResponsibleShard"),
                       JS_GetResponsibleShardClusterInfo);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("getServerEndpoint"),
                       JS_GetServerEndpointClusterInfo);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("getServerName"),
                       JS_GetServerNameClusterInfo);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("getDBServers"),
                       JS_GetDBServers);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("reloadDBServers"),
                       JS_ReloadDBServers);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("getCoordinators"),
                       JS_GetCoordinators);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("uniqid"),
                       JS_UniqidClusterInfo);

  v8g->ClusterInfoTempl.Reset(isolate, rt);
  TRI_AddGlobalFunctionVocbase(isolate,
                               TRI_V8_ASCII_STRING("ArangoClusterInfoCtor"),
                               ft->GetFunction(), true);

  // register the global object
  v8::Handle<v8::Object> ci = rt->NewInstance();
  if (!ci.IsEmpty()) {
    TRI_AddGlobalVariableVocbase(isolate,
                                 TRI_V8_ASCII_STRING("ArangoClusterInfo"), ci);
  }

  // .............................................................................
  // generate the server state template
  // ...........................................................................

  ft = v8::FunctionTemplate::New(isolate);
  ft->SetClassName(TRI_V8_ASCII_STRING("ArangoServerState"));

  rt = ft->InstanceTemplate();
  rt->SetInternalFieldCount(2);

  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("address"),
                       JS_AddressServerState);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("flush"),
                       JS_FlushServerState, true);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("localInfo"),
                       JS_LocalInfoServerState);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("id"),
                       JS_IdServerState);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("isFoxxmaster"),
                       JS_isFoxxmaster);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("getFoxxmaster"),
                       JS_getFoxxmaster);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("getFoxxmasterQueueupdate"),
                       JS_getFoxxmasterQueueupdate);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("idOfPrimary"),
                       JS_IdOfPrimaryServerState);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("description"),
                       JS_DescriptionServerState);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("javaScriptPath"),
                       JS_JavaScriptPathServerState);
#ifdef DEBUG_SYNC_REPLICATION
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("enableSyncReplicationDebug"),
                       JS_EnableSyncReplicationDebug);
#endif
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("initialized"),
                       JS_InitializedServerState);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("isCoordinator"),
                       JS_IsCoordinatorServerState);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("role"),
                       JS_RoleServerState);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("setLocalInfo"),
                       JS_SetLocalInfoServerState, true);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("setId"),
                       JS_SetIdServerState, true);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("setRole"),
                       JS_SetRoleServerState, true);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("redetermineRole"),
                       JS_RedetermineRoleServerState, true);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("status"),
                       JS_StatusServerState);

  v8g->ServerStateTempl.Reset(isolate, rt);
  TRI_AddGlobalFunctionVocbase(isolate,
                               TRI_V8_ASCII_STRING("ArangoServerStateCtor"),
                               ft->GetFunction(), true);

  // register the global object
  v8::Handle<v8::Object> ss = rt->NewInstance();
  if (!ss.IsEmpty()) {
    TRI_AddGlobalVariableVocbase(isolate,
                                 TRI_V8_ASCII_STRING("ArangoServerState"), ss);
  }

  // ...........................................................................
  // generate the cluster comm template
  // ...........................................................................

  ft = v8::FunctionTemplate::New(isolate);
  ft->SetClassName(TRI_V8_ASCII_STRING("ArangoClusterComm"));

  rt = ft->InstanceTemplate();
  rt->SetInternalFieldCount(2);

  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("asyncRequest"),
                       JS_AsyncRequest);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("syncRequest"),
                       JS_SyncRequest);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("enquire"), JS_Enquire);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("wait"), JS_Wait);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("drop"), JS_Drop);
  TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("getId"), JS_GetId);

  v8g->ClusterCommTempl.Reset(isolate, rt);
  TRI_AddGlobalFunctionVocbase(isolate,
                               TRI_V8_ASCII_STRING("ArangoClusterCommCtor"),
                               ft->GetFunction(), true);

  // register the global object
  ss = rt->NewInstance();
  if (!ss.IsEmpty()) {
    TRI_AddGlobalVariableVocbase(isolate,
                                 TRI_V8_ASCII_STRING("ArangoClusterComm"), ss);
  }
  TRI_AddGlobalFunctionVocbase(
      isolate, TRI_V8_ASCII_STRING("SYS_CLUSTER_DOWNLOAD"),
      JS_ClusterDownload);
}


It was the fall of 1955 and I was anticipating my first bicycle. Most of my friends had either Schwinn (sold by Cartwright's and Sebastian's Firestone) or J.C. Higgens (Sold by Sears) single-speed bikes with heavy frames, coaster brakes and 26" balloon tires. I prowled all over downtown Santa Fe, looking for the perfect bike, and I found it at Gerkin's Bicycle Shop on Water Street. It was made by British manufacturer Raleigh and, unlike the behemoth machines of my friends, it had a lightweight frame, skinny 27" tires, a 3-speed Sturmey Archer rear hub with the shifter on the handlebars and front and rear caliper hand brakes. It also had front and rear fenders, front and rear lights powered by a generator, a down tube mounted pump and a leather saddle with a little bag full of tools underneath. That bike was made for me and I begged my parents for it as my Christmas present. Since it was considerably more expensive than the bikes everyone else rode, I was told to lower my sights and find one that was reasonably priced. I did, but the anticipation became lukewarm.
Christmas morning arrived and I trudged down to the tree. And there – with a red bow on the handlebars – was the Raleigh English Racer! I don't think I ever got a Christmas present before or since that took my breath away like that bike did. I received a serious lecture from my dad about understanding that it required a lot of care and upkeep, that I was responsible for getting it licensed (Santa Fe had a bike license ordinance in those days and for 50 cents you got this cool little plate to attach to the rear fork) and, above all things, I was NOT to ride it in the dirt. I assured him that I understood and spent the rest of the day taking it apart and putting it back together with the nifty little tool set.
Spring came and I rode that bike all over town. I would put it in high gear and rocket down East Palace from my home on La Vereda, cruise around the Plaza, ride up College Street to Manhattan Street, down Delgado Street to Alameda and then put it into low gear for the stretch back up Palace.
The only downside was that my friends with the big bikes immediately branded mine a peefee bicycle. The word peefee is unique to Santa Fe and its origins are from the nickname given to a slight, effeminate and very flamboyant waiter named Epifano who worked at the Mayflower Café in the 1930s. The word came to mean weak, unmanly or timid. To make matters worse, I was labeled as a peefee because I wouldn't go with my friends to the local off-road bicycle course, the Death Trails. Located between Don Gaspar and Galisteo near the powder house, the Trails were a series of hills, valleys and arroyos where kids had built jumps, banked curves and the like. This was before Cordova Road was built and there were no houses out there – just open country.
As one might guess, it wasn't very long before I made my first trip out to the Death Trails. There were a lot of kids out there, both Hispano and Gringo, and what was most important was how well you could ride. I figured that my 3-speed gears would give me an advantage, especially on the uphill parts. I was wrong – that bike was a real dog off-road. While I could ride fast on the flats and downhill parts, the skinny tires were worthless in the sandy arroyos and the bike would come to a halt almost immediately. I would have to get off the bike, push it up the other side, and remount. This led to hoots and catcalls, further cementing my reputation. I was no longer a peefee – I was their king. Thoroughly humiliated, I left and pedaled the long 3 miles home.
Now, for most people, that would have been the end of it. But it was at this point that all reason and promises to my father went right out the window. I had noticed that the really good riders had stripped their bikes of all unnecessary hardware, and I figured that if I did the same my bike would be much lighter and more nimble. So a couple of days later, after my dad left for work, I got out my little set of tools and went to work. Off came the fenders, the chain guard, the generator, the lights, the pump and the toolbag. When I finished, I was certain that I could reclaim my manhood and off I went.
The bike certainly was faster and by pedaling insanely, I could ride down a hill into the arroyo sand where momentum would carry me across to the uphill side without dismounting. After spending some time getting the feel of things, I headed over to the more technical part and decided to try the jumps. The good riders could get 2 or 3 feet in the air and I figured that I could do at least that. I waited in line for my turn and when it came I rode for the jump as fast as I could. I catapulted into the air, came down on the front wheel and the bike simply quit working. After I picked myself up from a major faceplant I got the bike and tried to figure out what was wrong with it. There was plenty wrong with it – I had broken the frame where the top tube connects to the handlebar headset. Realizing that I was still king of the peefees, I pushed the bike home, arriving an hour after I was supposed to be there. My parents had no idea where I was and I was in big trouble on so many levels. Coming home late – check. Riding way out Galisteo Street – check. Dismantling my bike – check. Riding in the dirt – check. Breaking my bike – check and check. I spent the next two weeks under house arrest.
After my dad cooled down, we took the bike back to Gerkin's to see if it could be repaired. Mr. Gerkin was able to braze the broken frame back together, but the bike was never the same. It would pull to the left instead of going straight and the front brake would shudder whenever it was used. The last time I rode it was in the fall before school began. It wasn't until 30 years later that I discovered today's mountain bikes and learned to ride in the dirt.
This is a picture of my parent's wedding party taken in August, 1947. This was taken in the backyard of my grandparents house on Agua Fria. The property was demolished to make way for St. Francis Drive.
My wifes parents Geraldine and Thomas Martinez.


text:
How to blur your house on Google Street View (and why you should)
A little privacy goes a long way.
By Jack Morse on May 27, 2022
A home blurred on Google Street view Credit: Google street view
> Tech
Privacy Please is an ongoing series exploring the ways privacy is violated in the modern world, and what can be done about it.
Google Street View offers up a window to the world in all its bizarre, intimate, and often raw glory. That window just so happens to peek into your home, as well. What that peek reveals may be more than you've bargained for — think views into bedroom windows, potential fodder for stalkers(Opens in a new window), and more.
Thankfully, there is something you can do about it. Specifically, you can ask Google to permanently blur your house out — leaving only a smeared suggestion of a building in its place. The entire process is surprisingly easy.
As the name would suggest, Street View, launched in 2007(Opens in a new window), provides a street-level view of many cities and towns around the world. Captured by roving vehicles and individual photographers equipped with camera-laden backpacks, the service has been controversial from the start — both in the ways you might imagine, and ways you might not.
In 2008, the Minnesota suburb of North Oaks decided it didn't want pictures of it up on Google's service, and threatened to cite Google for trespassing. Google pulled the images down.
SEE ALSO: How to remove your personal info from Google search results
In 2009, the lobbying organization Privacy International filed a formal complaint to the UK's Information Commissioner's Office (ICO)(Opens in a new window) alleging that Google failed to properly de-identify the people it captured. As a BBC report(Opens in a new window) at the time noted, that type of failure could have serious repercussions.
"Among them were a woman who had moved house to escape a violent partner but who was recognisable outside her new home on Street View," read the article, describing complaints made to Privacy International. "Also complaining were two colleagues pictured in an apparently compromising position who suffered embarrassment when the image was circulated at their workplace."
Staying cool in Brooklyn. Credit: Screenshot / street view
And that's just the obvious stuff.
Google has never exactly been a steward of anyones' privacy. In 2010, the company admitted(Opens in a new window) that its Street View vehicles — the ones endlessly circling neighborhoods around the world — had secretly been collecting information from unencrypted WiFi networks they drove past for years(Opens in a new window).
So maybe you're worried about an online stalker, maybe you don't want strangers peering in your windows, or maybe you value privacy for its own sake and simply don't think Google should have indexed and digitized photos of your home available for all to see. Whatever the reason, it's relatively easy to request Google blur out the image of your home or apartment on Google Street View.
1. Go to Google Maps(Opens in a new window) and enter your home address
2. Enter into Street View mode by dragging the small yellow human-shaped icon, found in the bottom-right corner of the screen, onto the map in front of your house
3. With your house in view, click "Report a problem" in the bottom-right corner of the screen
4. Center the red box on your home, and select "My home" in the "Request blurring" field
Google's San Francisco office. Credit: screenshot / google
5. Write in the provided field why you want the image blurred (for example, you may be concerned about safety issues)
6. Enter in your email address, and click "Submit"
Importantly, be sure it's what you want. Google warns you that once it has blurred your house on Street View "it is permanent."
Don't forget, though, you live in the place. If you ever need to be reminded of what it looks like, presumably you can go outside and see for yourself.
After you hit "submit," you should receive an email from Google noting that it's "reviewing the image you reported and will email you when your request is resolved." The company may follow up, via email, and ask you to be more specific about the area you want blurred. If so, you will need to do the entire process again — clearly detailing the specific area of the picture you want blurred.
SEE ALSO: 7 Google privacy settings you should enable now
It's not clear exactly how long Google takes to process the requests, so you might as well get started now. And, when you're done with that, do the same thing on Bing Maps (the process is surprisingly similar) — it's not like Microsoft should get any special treatment, after all.
More in Cybersecurity, Google, Privacy
Jack Morse
Professionally paranoid. Covering privacy, security, and all things cryptocurrency and blockchain from San Francisco.
More from Privacy Please
Why you need a secret phone number (and how to get one)
No, they're not just for spies, philanderers, or drug dealers.
By Jack Morse
How to stop Spotify from sharing your data, and why you should
Spotify knows every song you've ever listened to, and what it does with your info may surprise you.
How to make your Gmail account self destruct, and why you really should
At least one part of your digital permanent record doesn't need to outlive you.
Your cute pet camera may hide a troubling secret
Putting a pet camera in your home might not be the best idea.
Your car knows too much about you. That could be a privacy nightmare.
Modern cars collect a lot of data on their drivers.
Stephen Colbert blasts Meta's plans to reinstate Trump on Facebook and Instagram
This is fine.
By Amanda Yeo
Icky 'Swallowed' trailer teases a botched drug run with a gross twist
By Sam Haysom
Can you power a village with a tiny stream?
The turbines are designed to be easily maintained in regions of the world where generating energy is difficult.
By Jules Suzdaltsev
Shutterstock launches an AI image generator. Just what we needed.
Be careful: Using AI to find art is controversial.
Emoji reacts are finally coming to Google Meet
It's been 84 years...OK, it's been a year. Still a long wait.

redpajama_set_name: RedPajamaCommonCrawl


text:
Home / MLS / Columbus Crew / MLS in Focus: Columbus' Wil Trapp
MLS in Focus: Columbus' Wil Trapp
By Ryan Brister on 09/04/2015@Throughballs
by RYAN BRISTER
This upcoming weekend is a FIFA international date, which means Major League Soccer teams will generally lack their best players. Half the league mercifully has the weekend off, but the teams that play will be shorthanded.
The Columbus Crew know this all too well; eight players will miss this weekend's game against Dallas due to international duty.
One of those missing players is Wil Trapp who is with the United States U-23 team as they prepare for Olympic qualification. In his third season in MLS, Trapp has established himself as a regular for the Crew. He came up through the club's academy, and has been one of the brightest spots in Columbus even as they've emerged as one of the Eastern Conference's best teams.
In Gregg Berhalter's setup, Trapp plays as one of the pair sitting in front of the back four. Tony Tchani provides the muscle in that pairing, and serves as Columbus' main ball-winner in midfield. Trapp plays as a deep-lying distributor, but does so in a different way than most.
When the Crew win the ball in their own half, Trapp doesn't push up to start the charge down the field, but instead does the opposite. He scampers back, to insert himself between the two center backs.
This has a couple of practical effects. Firstly, by dropping deep, Trapp makes himself available to distribute the ball from an area where he is both better than the center backs and under less pressure than further up the field. Think of a quarterback operating from the shotgun. It gives Trapp the space and time to play touchdown passes such as this one:
Of course, when opponents do put him under pressure, he has the ability to calmly wriggle free anyway:
Secondly, with Trapp operating as a third center back, the back line operates the way a three/five-man back line would in possession: the fullbacks are pushed forward. Columbus relies a lot on wide play in their attacks, and its fullbacks Hector Jimenez and Waylon Francis have combined for 10 assists this year.
Trapp's role means he doesn't pick up too many assists on his own, but when he forays forward, he is capable of unlocking defenses with his passing.
The following is a map of Trapp's performance on Saturday against NYCFC. I haven't removed anything, just narrowed it down to what he did in the middle of the field. Those two red arrows were his only incomplete passes of the day in that area. Both were attempts at long passes, so he effectively never gave the ball away in midfield.
That sort of calm play in the center of the field is invaluable for a team, and impressive coming from a 22-year-old.
While Trapp isn't the flashiest player, the results speak for themselves. When Trapp starts, the Crew are 6-2-3 this season. They are 5-6-5 without him. He missed two and a half months due to a concussion earlier in the year, which was cause for concern not just in Columbus.
Trapp's return has helped stabilize the Crew after a shaky period without him, and they now find themselves in third place in the East. That's where they finished last year, but an early playoff exit left a sour taste in their mouths. Trapp and the Crew want the future to be even brighter.
Related ItemsColumbus CrewfeaturedMLSMLS in FocusWil Trapp
← Previous Story Senna on his Cosmos absence – and how he nearly left the club
Next Story → Cellerino getting acclimated to life with the Cosmos
MLS Cup Rematch: It's Toronto vs. Seattle


text:
Zoguové či dynastie Zogu ( Dinastia Zogolli) byli vládnoucí královskou dynastií v Albánii v letech 1928 až 1939. Za zakladatele dynastie je uváděn Zogu Paša, ovšem jako vládnoucí dynastii jí ustanovil až v roce 1928 Ahmet Zogu (pod jménem Zog I.) Ten však musel v roce 1939 Albánii opustit, protože jí okupovala Itálie. Pouze dva dny před italskou okupací se mu narodil jediný syn Leka Zogu, který byl od smrti Zoga I. v roce 1961 hlavou dynastie. Byl jí až do své smrti v roce 2011. V současnosti je hlavou rodu princ Leka, který je synem korunního prince Leky a jediný vnuk Zoga I.

Původ
Tradičním sídlem vládců z dynastie Zogu byl zámek Burgajet v okresu Mat, odkud rod pocházel resp. dědičně spravoval tento okres. Skutečný zakladatel dynastie král Zog I. odvozoval svůj původ od albánského národního hrdiny a panovníka Skanderbega, resp. od jeho sestry (Zogova matka pocházela z rodu Toptani, který měl pocházel od sestry Skanderbega, i když proto musel být upraven rodokmen). Některými historiky je podobně jako Napoleon Bonaparte (a Napoleon III.) považován za samozvance a uzurpátora trůnu, který předtím patřil dědičně zvolenému rodu Wiedů.

K "legitimitě" Zoga I. resp. dynastie Zogu, ale přispívá, že kníže Vilém z Wiedu byl zvolen z vůle velmocí a vládl pouze krátkou dobu (ve srovnání s Ottou Řeckým a Jiřím I.), navíc jeho synem Karlem Viktorem vymřeli v roce 1973 Vilémovi potomci a tak se dá jejich nárok na trůn považovat za ukončený.

Vládci z dynastie Zogu

Dědičný guvernér okresu Mat
 předchozí vládci neznámí
 Xhelal Pasha Zogolli
 Xhemal Paša Zogolli
 Ahmet Zogu

Král Albánců (1928-1939)
 Zog I.

Pretendenti trůnu a hlavy rodu po roce 1939
 Zog I. – (1939–1961)
 Leka I. Zogu – (1961–2011)
 Leka II. Zogu – (od 2011)

Odkazy

Reference

Související články
 Seznam albánských panovníků
 Dějiny Albánie
 Linie následnictví albánského trůnu

Externí odkazy

 Oficiální stránky dynastie Zogu

Albánské šlechtické rody
Bývalé panovnické rody

redpajama_set_name: RedPajamaWikipedia


On May 2nd, the Department of Energy (DOE) announced that some nuclear waste shipments from Los Alamos National Laboratory (LANL) to Waste Control Specialists (WCS) were suspended for an undetermined amount of time. The reason for the stoppage was that one or more LANL waste containers may have exploded underground and caused the February 14th radiation release from the Waste Isolation Pilot Plant (WIPP). However, DOE continues to state that the cause of the radiation release is unknown, but that it is investigating all possible scenarios.
Neither DOE nor LANL publicly identified the specific group of containers, called a waste stream, that are included in the shipment suspension. Nor have they publicly stated how many of the suspect containers are at WIPP and WCS and how many remain at LANL.
The suspended waste stream is LA-MIN02-V.001, which is the source of 54 of the 268 contact-handled waste containers in room 7, panel 7, at WIPP, where the radiation release may have originated. Another 116 containers from that waste stream are now at WCS. The waste stream was created by plutonium operations at LANL that are continuing at Technical Area 55.
When WIPP was closed in early February, about 100 shipments remained at LANL to meet the June 30th date. Since those shipments could not go to WIPP, DOE agreed to pay WCS $8.8 million to receive and store those wastes for up to one year.
The Environment Department has insisted that LANL meet the June 30th date, but not the deadlines for other cleanup activities included in the Consent Order that require wide-scale cleanup by 2015. Since October 2011,the Environment Department has issued more than 95 extensions of time for LANL to submit groundwater protection and cleanup investigation reports required by the Consent Order. http://www.nmenv.state.nm.us/HWB/documents/LANL_Extensions_as_of_4-7-2014.pdf The Framework Agreement does not give the Environment Department any power to impose fines and penalties to LANL for missing the June 30th deadline, while NMED does have that power under the Consent Order.
Joni Arends, of CCNS, said, "Both LANL and the Environment Department put all of their eggs in one basket by focusing on getting the waste off the Hill to WIPP instead of doing all of the work required under the Consent Order. Now, we still have waste at LANL – with more being created – but many of the important Consent Order activities have not been done."


First of all, I love the packaging and mustard yellow is literally one of my favourite colours so no problems there! As for the scent, I was slightly worried I wasn't going to like it as Honey isn't my fave smell ever, but I was actually pleasantly surprised by how nice it was! The scent can appear quite strong, however the product definitely smells slightly more mellow when it's on the skin.
The first 2 things I tried were the Cleansing Milk and the Gel Wash.
I loved how gentle the cleansing milk was and how easily it removed my makeup with a small amount on a cotton pad. I was slightly worried this would leave a greasy feeling to my skin (with me having such a sporadic skin type). However, I'm pleased to say I didn't find that at all and it left my skin feeling super soft and comfortable. You don't even need to rinse it off!
The gel wash is great as a general rinse off cleanser. It's not stripping and foams up really nicely! I tend to use this more as a morning cleanser personally, as it definitely has more of a refreshing feel to it!
You can tell the toner is aimed at the drier skin types as it's definitely one that takes a bit longer than usual to sink in - that's something I've never really been used to before. Don't let this put you off though! You only need the smallest amount on a cotton pad, as you'll find a little goes a long way. It's really hydrating and leaves such a smooth feeling to the skin after using it.
The day cream is one of my favourites and one I have been using the most religiously. Although I don't have very dry skin on my face, I find during the summer months it gets really dehydrated due to my slightly crazier lifestyle (aka one too many summer ciders!). This is incredibly nourishing and gives dry skin the drink it needs without causing it to over-compensate with oily patches.
What if I don't have dry skin?
There are 4 different ranges tailored to different skin types in the new Skin Active Botanical Range including the Honey Flower, Rose Water, Green Tea and Aloe Extract. All of the botanical range have 96% natural origin ingredients, are dermatologically tested with no parabens, sillicones or artificial colourants.
So, what suits what skin type?
Honey Flower - Dry to Very Dry.
Rose Water - Dry and Sensitive.
Overall, I absolutely love the new Honey Flower range and I'll definitely be purchasing it again the future. I'd really love to give the other ranges a try too. Thank you so much Garnier - you lovely bunch!
This sounds so luxurious! I think I'd love to try the Aloe range if its for combinations skin. I could imagine it being super refreshing in the summer!
Yes definitely. I'd love to give that a go too! :) I bet it smells gorgeous!


text:
Dad accused of throwing crying 7-year-old off cruise boat
A man has been arrested after Southern California authorities say he threw his son off a sightseeing cruise boat during an argument.
By Amy Taxin Associated Press
Tue., Aug. 30, 2011timer2 min. read
SANTA ANA, CALIF.—It was a pleasant afternoon aboard a sightseeing cruise around California's scenic Newport Harbor until the unthinkable happened: a man threw his crying 7-year-old son overboard during an argument in front of shocked passengers, authorities said.
Sloane Briles, 35, was taken into custody for child endangerment and resisting arrest, Orange County sheriff's spokesman Jim Amormino said.
"The father hit him several times and then threatened to throw him overboard if he didn't stop crying," Amormino said. "The crowd on the boat became very angry at the father for hitting the kid and extremely angry when he threw him overboard."
Authorities said Briles appeared to have been drinking. He was released Monday and couldn't immediately be reached at a number listed for him in Irvine.
Briles, his girlfriend and two sons from a previous marriage went on the Sunday afternoon cruise around Newport Harbor on a boat carrying 85 people. Briles began arguing with his girlfriend and his 7-year-old son, Amormino said, adding the child was not an expert swimmer.
The New York Daily News reported that the father's girlfriend told the newspaper that he was only "roughhousing" with his son as he often does and regretted his "stupid" judgment.
"His sons are his whole life," Jennifer Burrelli told the newspaper. "He would never ever do anything to hurt them on purpose. He knows now it could have gone badly. He doesn't even care about the arrest or his own name. He knows it was stupid."
She also said she and Briles were not arguing before the incident.
Staff members on the tour boat said Briles told the boy he needed to toughen up then threw him into the water five feet below, said Charlie Maas, who oversees the tour company.
"Right in the middle of a sunny weekend afternoon in August there is a lot of boat traffic out there," Maas said. "That could have been fatally dangerous."
The incident happened so quickly that Maas said there was little time to react. Someone on the boat threw the boy a life ring, and he was safely rescued, uninjured, by another boater. The father also jumped in to save him.
Both the boy and his brother were returned to the care of their mother, who also could not be reached for comment. The couple was married in 2002 and separated in 2006 after having two children. They divorced in 2007.
Family court filings showed Briles lost his job in the mortgage industry in 2007 and got another job but was injured and drew workers compensation. He successfully petitioned to get his child-support obligation reduced and tried for a second reduction, which his ex-wife, Christin, opposed.
"If he truly wanted to support his boys, he would find a job," she wrote in the filing. She also wrote that Briles sees the boys only on his weekends and rarely calls them during his off weeks.
Briles pleaded guilty in February 2009 to being in contempt for not paying child support. He was sentenced to three years of probation, according to court records. Briles also pleaded guilty in 2011 to public intoxication.
The 90-minute tour on a 42-foot boat called Queen, operated by the Fun Zone Boat Co., goes past Shirley Temple's childhood home and the homes of John Wayne and other celebrities.
Associated Press writer Noaki Schwartz in Los Angeles also contributed to this report.


text:
Q: Listview display tick icon when open I assume that I have activity A, activity B, and activity C. in activity A there is a listview that displays the name of activity B and C. how do I display the tick icon on the listview in activity A when I finish opening activity B or activity C like the example image below.
example

A: Add an ImageView to the right side of your ListView item layout and set it to be visible just after calling startActivity(). Or, if this is making the checkmarks visible too soon, you can use startActivityForResult(), which will allow you to set the ImageView's visibility only upon returning to Activity A. If your ListView isn't using custom item layouts, you'll need to learn how to do that.

redpajama_set_name: RedPajamaStackExchange