<commit_before>
#include "Globals.h"  // NOTE: MSVC stupidness requires this to be the same across all modules

#include "Authenticator.h"
#include "../OSSupport/BlockingTCPLink.h"
#include "../Root.h"
#include "../Server.h"
#include "../ClientHandle.h"

#include "inifile/iniFile.h"
#include "json/json.h"

#include "polarssl/config.h"
#include "polarssl/net.h"
#include "polarssl/ssl.h"
#include "polarssl/entropy.h"
#include "polarssl/ctr_drbg.h"
#include "polarssl/error.h"
#include "polarssl/certs.h"

#include <sstream>
#include <iomanip>

#define DEFAULT_AUTH_SERVER "sessionserver.mojang.com"
#define DEFAULT_AUTH_ADDRESS "/session/minecraft/hasJoined?username=%USERNAME%&serverId=%SERVERID%"

cAuthenticator::cAuthenticator(void) :
	super("cAuthenticator"),
	m_Server(DEFAULT_AUTH_SERVER),
	m_Address(DEFAULT_AUTH_ADDRESS),
	m_ShouldAuthenticate(true)
{
}

cAuthenticator::~cAuthenticator()
{
	Stop();
}

void cAuthenticator::ReadINI(cIniFile & IniFile)
{
	m_Server = IniFile.GetValueSet("Authentication", "Server", DEFAULT_AUTH_SERVER);
	m_Address = IniFile.GetValueSet("Authentication", "Address", DEFAULT_AUTH_ADDRESS);
	m_ShouldAuthenticate = IniFile.GetValueSetB("Authentication", "Authenticate", true);
}

void cAuthenticator::Authenticate(int a_ClientID, const AString & a_UserName, const AString & a_ServerHash)
{
	if (!m_ShouldAuthenticate)
	{
		cRoot::Get()->AuthenticateUser(a_ClientID, a_UserName, cClientHandle::GenerateOfflineUUID(a_UserName));
		return;
	}

	cCSLock LOCK(m_CS);
	m_Queue.push_back(cUser(a_ClientID, a_UserName, a_ServerHash));
	m_QueueNonempty.Set();
}

void cAuthenticator::Start(cIniFile & IniFile)
{
	ReadINI(IniFile);
	m_ShouldTerminate = false;
	super::Start();
}

void cAuthenticator::Stop(void)
{
	m_ShouldTerminate = true;
	m_QueueNonempty.Set();
	Wait();
}

void cAuthenticator::Execute(void)
{
	for (;;)
	{
		cCSLock Lock(m_CS);
		while (!m_ShouldTerminate && (m_Queue.size() == 0))
		{
			cCSUnlock Unlock(Lock);
			m_QueueNonempty.Wait();
		}
		if (m_ShouldTerminate)
		{
			return;
		}
		ASSERT(!m_Queue.empty());

		cAuthenticator::cUser & User = m_Queue.front();
		int ClientID = User.m_ClientID;
		AString UserName = User.m_Name;
		AString ServerID = User.m_ServerID;
		m_Queue.pop_front();
		Lock.Unlock();

		AString NewUserName = UserName;
		AString UUID;
		if (AuthWithYggdrasil(NewUserName, ServerID, UUID))
		{
			LOGINFO("User %s authenticated with UUID '%s'", NewUserName.c_str(), UUID.c_str());
			cRoot::Get()->AuthenticateUser(ClientID, NewUserName, UUID);
		}
		else
		{
			cRoot::Get()->KickUser(ClientID, "Failed to authenticate account!");
		}
	}  // for (-ever)
}

bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_ServerId, AString & a_UUID)
{
	LOGD("Trying to auth user %s", a_UserName.c_str());

	int ret, server_fd = -1;
	unsigned char buf[1024];
	const char *pers = "cAuthenticator";

	entropy_context entropy;
	ctr_drbg_context ctr_drbg;
	ssl_context ssl;
	x509_crt cacert;

	/* Initialize the RNG and the session data */
	memset(&ssl, 0, sizeof(ssl_context));
	x509_crt_init(&cacert);

	entropy_init(&entropy);
	if ((ret = ctr_drbg_init(&ctr_drbg, entropy_func, &entropy, (const unsigned char *)pers, strlen(pers))) != 0)
	{
		LOGWARNING("cAuthenticator: ctr_drbg_init returned %d", ret);
		return false;
	}

	/* Initialize certificates */
	// TODO: Grab the sessionserver's root CA and any intermediates and hard-code them here, instead of test_ca_list
	ret = x509_crt_parse(&cacert, (const unsigned char *)test_ca_list, strlen(test_ca_list));

	if (ret < 0)
	{
		LOGWARNING("cAuthenticator: x509_crt_parse returned -0x%x", -ret);
		return false;
	}

	/* Connect */
	if ((ret = net_connect(&server_fd, m_Server.c_str(), 443)) != 0)
	{
		LOGWARNING("cAuthenticator: Can't connect to %s: %d", m_Server.c_str(), ret);
		return false;
	}

	/* Setup */
	if ((ret = ssl_init(&ssl)) != 0)
	{
		LOGWARNING("cAuthenticator: ssl_init returned %d", ret);
		return false;
	}
	ssl_set_endpoint(&ssl, SSL_IS_CLIENT);
	ssl_set_authmode(&ssl, SSL_VERIFY_OPTIONAL);
	ssl_set_ca_chain(&ssl, &cacert, NULL, "PolarSSL Server 1");
	ssl_set_rng(&ssl, ctr_drbg_random, &ctr_drbg);
	ssl_set_bio(&ssl, net_recv, &server_fd, net_send, &server_fd);

	/* Handshake */
	while ((ret = ssl_handshake(&ssl)) != 0)
	{
		if ((ret != POLARSSL_ERR_NET_WANT_READ) && (ret != POLARSSL_ERR_NET_WANT_WRITE))
		{
			LOGWARNING("cAuthenticator: ssl_handshake returned -0x%x", -ret);
			return false;
		}
	}

	/* Write the GET request */
	AString ActualAddress = m_Address;
	ReplaceString(ActualAddress, "%USERNAME%", a_UserName);
	ReplaceString(ActualAddress, "%SERVERID%", a_ServerId);

	AString Request;
	Request += "GET " + ActualAddress + " HTTP/1.1\r\n";
	Request += "Host: " + m_Server + "\r\n";
	Request += "User-Agent: MCServer\r\n";
	Request += "Connection: close\r\n";
	Request += "\r\n";

	ret = ssl_write(&ssl, (const unsigned char *)Request.c_str(), Request.size());
	if (ret <= 0)
	{
		LOGWARNING("cAuthenticator: ssl_write returned %d", ret);
		return false;
	}

	/* Read the HTTP response */
	std::string Response;
	for (;;)
	{
		memset(buf, 0, sizeof(buf));
		ret = ssl_read(&ssl, buf, sizeof(buf));

		if ((ret == POLARSSL_ERR_NET_WANT_READ) || (ret == POLARSSL_ERR_NET_WANT_WRITE))
		{
			continue;
		}
		if (ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY)
		{
			break;
		}
		if (ret < 0)
		{
			LOGWARNING("cAuthenticator: ssl_read returned %d", ret);
			break;
		}
		if (ret == 0)
		{
			LOGWARNING("cAuthenticator: EOF");
			break;
		}

		Response.append((const char *)buf, ret);
	}

	ssl_close_notify(&ssl);
	x509_crt_free(&cacert);
	net_close(server_fd);
	ssl_free(&ssl);
	entropy_free(&entropy);
	memset(&ssl, 0, sizeof(ssl));

	// Check the HTTP status line:
	AString prefix("HTTP/1.1 200 OK");
	AString HexDump;
	if (Response.compare(0, prefix.size(), prefix))
	{
		LOGINFO("User \"%s\" failed to auth, bad http status line received", a_UserName.c_str());
		LOG("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
		return false;
	}

	// Erase the HTTP headers from the response:
	size_t idxHeadersEnd = Response.find("\r\n\r\n");
	if (idxHeadersEnd == AString::npos)
	{
		LOGINFO("User \"%s\" failed to authenticate, bad http response header received", a_UserName.c_str());
		LOG("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
		return false;
	}
	Response.erase(0, idxHeadersEnd + 4);

	// Parse the Json response:
	if (Response.empty())
	{
		return false;
	}
	Json::Value root;
	Json::Reader reader;
	if (!reader.parse(Response, root, false))
	{
		LOGWARNING("cAuthenticator: Cannot parse Received Data to json!");
		return false;
	}
	a_UserName = root.get("name", "Unknown").asString();
	a_UUID = root.get("id", "").asString();

	// If the UUID doesn't contain the hashes, insert them at the proper places:
	if (a_UUID.size() == 32)
	{
		a_UUID.insert(8, "-");
		a_UUID.insert(13, "-");
		a_UUID.insert(18, "-");
		a_UUID.insert(23, "-");
	}
	return true;
}

<commit_msg>Fixes resource leaks in the yggdrasil authenticator. (CID 43617)<commit_after>
#include "Globals.h"  // NOTE: MSVC stupidness requires this to be the same across all modules

#include "Authenticator.h"
#include "../OSSupport/BlockingTCPLink.h"
#include "../Root.h"
#include "../Server.h"
#include "../ClientHandle.h"

#include "inifile/iniFile.h"
#include "json/json.h"

#include "polarssl/config.h"
#include "polarssl/net.h"
#include "polarssl/ssl.h"
#include "polarssl/entropy.h"
#include "polarssl/ctr_drbg.h"
#include "polarssl/error.h"
#include "polarssl/certs.h"

#include <sstream>
#include <iomanip>

#define DEFAULT_AUTH_SERVER "sessionserver.mojang.com"
#define DEFAULT_AUTH_ADDRESS "/session/minecraft/hasJoined?username=%USERNAME%&serverId=%SERVERID%"

cAuthenticator::cAuthenticator(void) :
	super("cAuthenticator"),
	m_Server(DEFAULT_AUTH_SERVER),
	m_Address(DEFAULT_AUTH_ADDRESS),
	m_ShouldAuthenticate(true)
{
}

cAuthenticator::~cAuthenticator()
{
	Stop();
}

void cAuthenticator::ReadINI(cIniFile & IniFile)
{
	m_Server = IniFile.GetValueSet("Authentication", "Server", DEFAULT_AUTH_SERVER);
	m_Address = IniFile.GetValueSet("Authentication", "Address", DEFAULT_AUTH_ADDRESS);
	m_ShouldAuthenticate = IniFile.GetValueSetB("Authentication", "Authenticate", true);
}

void cAuthenticator::Authenticate(int a_ClientID, const AString & a_UserName, const AString & a_ServerHash)
{
	if (!m_ShouldAuthenticate)
	{
		cRoot::Get()->AuthenticateUser(a_ClientID, a_UserName, cClientHandle::GenerateOfflineUUID(a_UserName));
		return;
	}

	cCSLock LOCK(m_CS);
	m_Queue.push_back(cUser(a_ClientID, a_UserName, a_ServerHash));
	m_QueueNonempty.Set();
}

void cAuthenticator::Start(cIniFile & IniFile)
{
	ReadINI(IniFile);
	m_ShouldTerminate = false;
	super::Start();
}

void cAuthenticator::Stop(void)
{
	m_ShouldTerminate = true;
	m_QueueNonempty.Set();
	Wait();
}

void cAuthenticator::Execute(void)
{
	for (;;)
	{
		cCSLock Lock(m_CS);
		while (!m_ShouldTerminate && (m_Queue.size() == 0))
		{
			cCSUnlock Unlock(Lock);
			m_QueueNonempty.Wait();
		}
		if (m_ShouldTerminate)
		{
			return;
		}
		ASSERT(!m_Queue.empty());

		cAuthenticator::cUser & User = m_Queue.front();
		int ClientID = User.m_ClientID;
		AString UserName = User.m_Name;
		AString ServerID = User.m_ServerID;
		m_Queue.pop_front();
		Lock.Unlock();

		AString NewUserName = UserName;
		AString UUID;
		if (AuthWithYggdrasil(NewUserName, ServerID, UUID))
		{
			LOGINFO("User %s authenticated with UUID '%s'", NewUserName.c_str(), UUID.c_str());
			cRoot::Get()->AuthenticateUser(ClientID, NewUserName, UUID);
		}
		else
		{
			cRoot::Get()->KickUser(ClientID, "Failed to authenticate account!");
		}
	}  // for (-ever)
}

bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_ServerId, AString & a_UUID)
{
	LOGD("Trying to auth user %s", a_UserName.c_str());

	int ret, server_fd = -1;
	unsigned char buf[1024];
	const char *pers = "cAuthenticator";

	entropy_context entropy;
	ctr_drbg_context ctr_drbg;
	ssl_context ssl;
	x509_crt cacert;

	/* Initialize the RNG and the session data */
	memset(&ssl, 0, sizeof(ssl_context));
	x509_crt_init(&cacert);

	entropy_init(&entropy);
	if ((ret = ctr_drbg_init(&ctr_drbg, entropy_func, &entropy, (const unsigned char *)pers, strlen(pers))) != 0)
	{
		LOGWARNING("cAuthenticator: ctr_drbg_init returned %d", ret);

		// Free all resources which have been initialized up to this line
		x509_crt_free(&cacert);
		entropy_free(&entropy);
		return false;
	}

	/* Initialize certificates */
	// TODO: Grab the sessionserver's root CA and any intermediates and hard-code them here, instead of test_ca_list
	ret = x509_crt_parse(&cacert, (const unsigned char *)test_ca_list, strlen(test_ca_list));

	if (ret < 0)
	{
		LOGWARNING("cAuthenticator: x509_crt_parse returned -0x%x", -ret);

		// Free all resources which have been initialized up to this line
		x509_crt_free(&cacert);
		entropy_free(&entropy);
		return false;
	}

	/* Connect */
	if ((ret = net_connect(&server_fd, m_Server.c_str(), 443)) != 0)
	{
		LOGWARNING("cAuthenticator: Can't connect to %s: %d", m_Server.c_str(), ret);

		// Free all resources which have been initialized up to this line
		x509_crt_free(&cacert);
		entropy_free(&entropy);
		return false;
	}

	/* Setup */
	if ((ret = ssl_init(&ssl)) != 0)
	{
		LOGWARNING("cAuthenticator: ssl_init returned %d", ret);

		// Free all resources which have been initialized up to this line
		x509_crt_free(&cacert);
		net_close(server_fd);
		ssl_free(&ssl);
		entropy_free(&entropy);
		memset(&ssl, 0, sizeof(ssl));
		return false;
	}
	ssl_set_endpoint(&ssl, SSL_IS_CLIENT);
	ssl_set_authmode(&ssl, SSL_VERIFY_OPTIONAL);
	ssl_set_ca_chain(&ssl, &cacert, NULL, "PolarSSL Server 1");
	ssl_set_rng(&ssl, ctr_drbg_random, &ctr_drbg);
	ssl_set_bio(&ssl, net_recv, &server_fd, net_send, &server_fd);

	/* Handshake */
	while ((ret = ssl_handshake(&ssl)) != 0)
	{
		if ((ret != POLARSSL_ERR_NET_WANT_READ) && (ret != POLARSSL_ERR_NET_WANT_WRITE))
		{
			LOGWARNING("cAuthenticator: ssl_handshake returned -0x%x", -ret);

			// Free all resources which have been initialized up to this line
			x509_crt_free(&cacert);
			net_close(server_fd);
			ssl_free(&ssl);
			entropy_free(&entropy);
			memset(&ssl, 0, sizeof(ssl));
			return false;
		}
	}

	/* Write the GET request */
	AString ActualAddress = m_Address;
	ReplaceString(ActualAddress, "%USERNAME%", a_UserName);
	ReplaceString(ActualAddress, "%SERVERID%", a_ServerId);

	AString Request;
	Request += "GET " + ActualAddress + " HTTP/1.1\r\n";
	Request += "Host: " + m_Server + "\r\n";
	Request += "User-Agent: MCServer\r\n";
	Request += "Connection: close\r\n";
	Request += "\r\n";

	ret = ssl_write(&ssl, (const unsigned char *)Request.c_str(), Request.size());
	if (ret <= 0)
	{
		LOGWARNING("cAuthenticator: ssl_write returned %d", ret);

		// Free all resources which have been initialized up to this line
		x509_crt_free(&cacert);
		net_close(server_fd);
		ssl_free(&ssl);
		entropy_free(&entropy);
		memset(&ssl, 0, sizeof(ssl));
		return false;
	}

	/* Read the HTTP response */
	std::string Response;
	for (;;)
	{
		memset(buf, 0, sizeof(buf));
		ret = ssl_read(&ssl, buf, sizeof(buf));

		if ((ret == POLARSSL_ERR_NET_WANT_READ) || (ret == POLARSSL_ERR_NET_WANT_WRITE))
		{
			continue;
		}
		if (ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY)
		{
			break;
		}
		if (ret < 0)
		{
			LOGWARNING("cAuthenticator: ssl_read returned %d", ret);
			break;
		}
		if (ret == 0)
		{
			LOGWARNING("cAuthenticator: EOF");
			break;
		}

		Response.append((const char *)buf, ret);
	}

	ssl_close_notify(&ssl);
	x509_crt_free(&cacert);
	net_close(server_fd);
	ssl_free(&ssl);
	entropy_free(&entropy);
	memset(&ssl, 0, sizeof(ssl));

	// Check the HTTP status line:
	AString prefix("HTTP/1.1 200 OK");
	AString HexDump;
	if (Response.compare(0, prefix.size(), prefix))
	{
		LOGINFO("User \"%s\" failed to auth, bad http status line received", a_UserName.c_str());
		LOG("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
		return false;
	}

	// Erase the HTTP headers from the response:
	size_t idxHeadersEnd = Response.find("\r\n\r\n");
	if (idxHeadersEnd == AString::npos)
	{
		LOGINFO("User \"%s\" failed to authenticate, bad http response header received", a_UserName.c_str());
		LOG("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
		return false;
	}
	Response.erase(0, idxHeadersEnd + 4);

	// Parse the Json response:
	if (Response.empty())
	{
		return false;
	}
	Json::Value root;
	Json::Reader reader;
	if (!reader.parse(Response, root, false))
	{
		LOGWARNING("cAuthenticator: Cannot parse Received Data to json!");
		return false;
	}
	a_UserName = root.get("name", "Unknown").asString();
	a_UUID = root.get("id", "").asString();

	// If the UUID doesn't contain the hashes, insert them at the proper places:
	if (a_UUID.size() == 32)
	{
		a_UUID.insert(8, "-");
		a_UUID.insert(13, "-");
		a_UUID.insert(18, "-");
		a_UUID.insert(23, "-");
	}
	return true;
}

<|endoftext|>


<commit_before>#include "fdsb/test.hpp"
#include "fdsb/nid.hpp"
#include "fdsb/harc.hpp"
#include "fdsb/fabric.hpp"

using namespace fdsb;

void test_fabric_addget()
{
	Harc h1(1_n,2_n);
	add(h1);
	get(1_n,2_n) = 47_n;
	add(3_n,4_n);
	get(3_n,4_n) = 56_n;
	CHECK(get(1_n,2_n) == 47_n);
	CHECK(get(3_n,4_n) == 56_n);
	DONE;
}

void test_fabric_symetric()
{
	add(10_n,11_n);
	get(10_n,11_n) = 55_n;
	CHECK(get(10_n,11_n) == 55_n);
	CHECK(get(11_n,10_n) == 55_n);
	get(11_n,10_n) = 66_n;
	CHECK(get(10_n,11_n) == 66_n);
	CHECK(get(11_n,10_n) == 66_n);
	DONE;
}

void test_fabric_autocreate()
{
	get(15_n,16_n) = 67_n;
	CHECK(get(15_n,16_n) == 67_n);
	DONE;
}

void test_fabric_subscript()
{
	19_n[20_n] = 21_n;
	CHECK(19_n[20_n] == 21_n);
	CHECK(20_n[19_nid] == 21_n);
	DONE;
}

int main(int argc, char *argv[])
{
	test(test_fabric_addget);
	test(test_fabric_symetric);
	test(test_fabric_autocreate);
	test(test_fabric_subscript);
	return 0;
}
<commit_msg>Missing _nid changes<commit_after>#include "fdsb/test.hpp"
#include "fdsb/nid.hpp"
#include "fdsb/harc.hpp"
#include "fdsb/fabric.hpp"

using namespace fdsb;

void test_fabric_addget()
{
	Harc h1(1_n,2_n);
	add(h1);
	get(1_n,2_n) = 47_n;
	add(3_n,4_n);
	get(3_n,4_n) = 56_n;
	CHECK(get(1_n,2_n) == 47_n);
	CHECK(get(3_n,4_n) == 56_n);
	DONE;
}

void test_fabric_symetric()
{
	add(10_n,11_n);
	get(10_n,11_n) = 55_n;
	CHECK(get(10_n,11_n) == 55_n);
	CHECK(get(11_n,10_n) == 55_n);
	get(11_n,10_n) = 66_n;
	CHECK(get(10_n,11_n) == 66_n);
	CHECK(get(11_n,10_n) == 66_n);
	DONE;
}

void test_fabric_autocreate()
{
	get(15_n,16_n) = 67_n;
	CHECK(get(15_n,16_n) == 67_n);
	DONE;
}

void test_fabric_subscript()
{
	19_n[20_n] = 21_n;
	CHECK(19_n[20_n] == 21_n);
	CHECK(20_n[19_n] == 21_n);
	DONE;
}

int main(int argc, char *argv[])
{
	test(test_fabric_addget);
	test(test_fabric_symetric);
	test(test_fabric_autocreate);
	test(test_fabric_subscript);
	return 0;
}
<|endoftext|>


<commit_before><commit_msg>Ensures that writes are at least one byte, matching the libevent version. As discussed in http://codereview.chromium.org/55014 .<commit_after><|endoftext|>


<commit_before>/* -*-  mode: c++; c-default-style: "google"; indent-tabs-mode: nil -*- */

/*
  Bioturbation via diffusion

  Authors: Ethan Coon (ecoon@lanl.gov)
*/

#include "Epetra_SerialDenseVector.h"

#include "bioturbation_evaluator.hh"

namespace Amanzi {
namespace BGC {
namespace BGCRelations {

BioturbationEvaluator::BioturbationEvaluator(Teuchos::ParameterList& plist) :
    SecondaryVariableFieldEvaluator(plist) {

  carbon_key_ = plist_.get<std::string>("SOM key", "soil_organic_matter");
  dependencies_.insert(carbon_key_);
  diffusivity_key_ = plist_.get<std::string>("cryoturbation diffusivity key", "cryoturbation_diffusivity");
  dependencies_.insert(diffusivity_key_);

  if (my_key_ == std::string("")) {
    my_key_ = plist_.get<std::string>("divergence of bioturbation fluxes",
            "div_bioturbation");
  }
}

BioturbationEvaluator::BioturbationEvaluator(const BioturbationEvaluator& other) :
    SecondaryVariableFieldEvaluator(other),
    carbon_key_(other.carbon_key_),
    diffusivity_key_(other.diffusivity_key_) {}

Teuchos::RCP<FieldEvaluator>
BioturbationEvaluator::Clone() const {
  return Teuchos::rcp(new BioturbationEvaluator(*this));
}

// Required methods from SecondaryVariableFieldEvaluator
void BioturbationEvaluator::EvaluateField_(const Teuchos::Ptr<State>& S,
        const Teuchos::Ptr<CompositeVector>& result) {

  Teuchos::RCP<const CompositeVector> carbon_cv = S->GetFieldData(carbon_key_);
  const AmanziMesh::Mesh& mesh = *carbon_cv->Mesh();

  const Epetra_MultiVector& carbon = *carbon_cv->ViewComponent("cell",false);
  const Epetra_MultiVector& diff = *S->GetFieldData(diffusivity_key_)
      ->ViewComponent("cell",false);
  Epetra_MultiVector& res_c = *result->ViewComponent("cell",false);

  // iterate over columns of the mesh
  const AmanziMesh::Entity_ID_List& columns = mesh.cell_column_indices();
  for (AmanziMesh::Entity_ID_List::const_iterator i=columns.begin(); i!=columns.end(); ++i) {
    // grab the column
    const AmanziMesh::Entity_ID_List& col = mesh.cell_column(*i);

    Epetra_SerialDenseVector dC_up(carbon.NumVectors());
    Epetra_SerialDenseVector dC_dn(carbon.NumVectors());

    // loop over column, getting cell index ci and cell c
    int ci=0;
    for (AmanziMesh::Entity_ID_List::const_iterator c=col.begin(); c!=col.end(); ++c, ++ci) {
      double my_z = mesh.cell_centroid(*c)[2];
      double dz_up = 0.;
      double dz_dn = 0.;

      if (ci != 0) {
        double my_z = mesh.cell_centroid(*c)[2];
        int c_up = col[ci-1];
        dz_up = mesh.cell_centroid(c_up)[2] - my_z;

        for (int p=0; p!=carbon.NumVectors(); ++p) {
          dC_up[p] = (diff[p][*c]+diff[p][c_up]) / 2. * (carbon[p][*c] - carbon[p][c_up]) / dz_up;
        }
      }

      if (ci != col.size()-1) {
        int c_dn = col[ci+1];
        dz_dn = mesh.cell_centroid(c_dn)[2] - my_z;

        for (int p=0; p!=carbon.NumVectors(); ++p) {
          dC_dn[p] = (diff[p][*c]+diff[p][c_dn]) / 2. * (carbon[p][c_dn] - carbon[p][*c]) / dz_up;
        }
      }

      double dz = dz_dn == 0. ? dz_up :
          dz_up == 0. ? dz_dn : (dz_up + dz_dn) / 2.;
      for (int p=0; p!=carbon.NumVectors(); ++p) {
        res_c[p][*c] = (dC_dn[p] - dC_up[p]) / dz;
      }
    }

  }
}

void BioturbationEvaluator::EvaluateFieldPartialDerivative_(
    const Teuchos::Ptr<State>& S,
    Key wrt_key, const Teuchos::Ptr<CompositeVector>& result) {
  ASSERT(0);
}

} //namespace
} //namespace
} //namespace
<commit_msg>changed calls to get column info in accordance with changes in Amanzi<commit_after>/* -*-  mode: c++; c-default-style: "google"; indent-tabs-mode: nil -*- */

/*
  Bioturbation via diffusion

  Authors: Ethan Coon (ecoon@lanl.gov)
*/

#include "Epetra_SerialDenseVector.h"

#include "bioturbation_evaluator.hh"

namespace Amanzi {
namespace BGC {
namespace BGCRelations {

BioturbationEvaluator::BioturbationEvaluator(Teuchos::ParameterList& plist) :
    SecondaryVariableFieldEvaluator(plist) {

  carbon_key_ = plist_.get<std::string>("SOM key", "soil_organic_matter");
  dependencies_.insert(carbon_key_);
  diffusivity_key_ = plist_.get<std::string>("cryoturbation diffusivity key", "cryoturbation_diffusivity");
  dependencies_.insert(diffusivity_key_);

  if (my_key_ == std::string("")) {
    my_key_ = plist_.get<std::string>("divergence of bioturbation fluxes",
            "div_bioturbation");
  }
}

BioturbationEvaluator::BioturbationEvaluator(const BioturbationEvaluator& other) :
    SecondaryVariableFieldEvaluator(other),
    carbon_key_(other.carbon_key_),
    diffusivity_key_(other.diffusivity_key_) {}

Teuchos::RCP<FieldEvaluator>
BioturbationEvaluator::Clone() const {
  return Teuchos::rcp(new BioturbationEvaluator(*this));
}

// Required methods from SecondaryVariableFieldEvaluator
void BioturbationEvaluator::EvaluateField_(const Teuchos::Ptr<State>& S,
        const Teuchos::Ptr<CompositeVector>& result) {

  Teuchos::RCP<const CompositeVector> carbon_cv = S->GetFieldData(carbon_key_);
  const AmanziMesh::Mesh& mesh = *carbon_cv->Mesh();

  const Epetra_MultiVector& carbon = *carbon_cv->ViewComponent("cell",false);
  const Epetra_MultiVector& diff = *S->GetFieldData(diffusivity_key_)
      ->ViewComponent("cell",false);
  Epetra_MultiVector& res_c = *result->ViewComponent("cell",false);

  // iterate over columns of the mesh
  int ncolumns = mesh.num_columns();
  for (int i=0; i<ncolumns; ++i) {
    // grab the column
    const AmanziMesh::Entity_ID_List& col = mesh.cells_of_column(i);

    Epetra_SerialDenseVector dC_up(carbon.NumVectors());
    Epetra_SerialDenseVector dC_dn(carbon.NumVectors());

    // loop over column, getting cell index ci and cell c
    int ci=0;
    for (AmanziMesh::Entity_ID_List::const_iterator c=col.begin(); c!=col.end(); ++c, ++ci) {
      double my_z = mesh.cell_centroid(*c)[2];
      double dz_up = 0.;
      double dz_dn = 0.;

      if (ci != 0) {
        double my_z = mesh.cell_centroid(*c)[2];
        int c_up = col[ci-1];
        dz_up = mesh.cell_centroid(c_up)[2] - my_z;

        for (int p=0; p!=carbon.NumVectors(); ++p) {
          dC_up[p] = (diff[p][*c]+diff[p][c_up]) / 2. * (carbon[p][*c] - carbon[p][c_up]) / dz_up;
        }
      }

      if (ci != col.size()-1) {
        int c_dn = col[ci+1];
        dz_dn = mesh.cell_centroid(c_dn)[2] - my_z;

        for (int p=0; p!=carbon.NumVectors(); ++p) {
          dC_dn[p] = (diff[p][*c]+diff[p][c_dn]) / 2. * (carbon[p][c_dn] - carbon[p][*c]) / dz_up;
        }
      }

      double dz = dz_dn == 0. ? dz_up :
          dz_up == 0. ? dz_dn : (dz_up + dz_dn) / 2.;
      for (int p=0; p!=carbon.NumVectors(); ++p) {
        res_c[p][*c] = (dC_dn[p] - dC_up[p]) / dz;
      }
    }

  }
}

void BioturbationEvaluator::EvaluateFieldPartialDerivative_(
    const Teuchos::Ptr<State>& S,
    Key wrt_key, const Teuchos::Ptr<CompositeVector>& result) {
  ASSERT(0);
}

} //namespace
} //namespace
} //namespace
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (ivan.frade@nokia.com)
**
** This file is part of the QtSparql module (not yet part of the Qt Toolkit).
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you have questions regarding the use of this file, please contact
** Nokia at ivan.frade@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include <tracker-sparql.h>

#include "qsparql_tracker_direct_update_result_p.h"
#include "qsparql_tracker_direct_driver_p.h"
#include "qsparql_tracker_direct_result_p.h"

#include <qsparqlerror.h>
#include <qsparqlbinding.h>
#include <qsparqlquery.h>
#include <qsparqlresultrow.h>

#include <QtCore/qcoreapplication.h>
#include <QtCore/qeventloop.h>

#include <QtCore/qdebug.h>

QT_BEGIN_NAMESPACE

////////////////////////////////////////////////////////////////////////////

class QTrackerDirectUpdateResultPrivate : public QObject {
    Q_OBJECT
public:
    QTrackerDirectUpdateResultPrivate(QTrackerDirectUpdateResult* result, QTrackerDirectDriverPrivate *dpp);

    ~QTrackerDirectUpdateResultPrivate();
    void terminate();
    void setLastError(const QSparqlError& e);

    QAtomicInt isFinished;
    bool resultAlive; // whether the corresponding Result object is still alive
    QEventLoop *loop;

    QTrackerDirectUpdateResult* q;
    QTrackerDirectDriverPrivate *driverPrivate;
};

static void
async_update_callback( GObject *source_object,
                       GAsyncResult *result,
                       gpointer user_data)
{
    Q_UNUSED(source_object);
    QTrackerDirectUpdateResultPrivate *data = static_cast<QTrackerDirectUpdateResultPrivate*>(user_data);
    if (!data->resultAlive) {
        // The user has deleted the Result object before this callback was
        // called. Just delete the ResultPrivate here and do nothing.
        delete data;
        return;
    }

    GError *error = 0;
    tracker_sparql_connection_update_finish(data->driverPrivate->connection, result, &error);

    if (error) {
        QSparqlError e(QString::fromUtf8(error->message));
        e.setType(errorCodeToType(error->code));
        e.setNumber(error->code);
        data->setLastError(e);
        g_error_free(error);
    }

    // A workaround for http://bugreports.qt.nokia.com/browse/QTBUG-18434

    // We cannot emit the QSparqlResult::finished() signal directly here; so
    // delay it and emit it the next time the main loop spins.
    QMetaObject::invokeMethod(data->q, "terminate", Qt::QueuedConnection);
}

QTrackerDirectUpdateResultPrivate::QTrackerDirectUpdateResultPrivate(QTrackerDirectUpdateResult* result,
                                                                     QTrackerDirectDriverPrivate *dpp)
  : resultAlive(true), loop(0),
  q(result), driverPrivate(dpp)
{
}

QTrackerDirectUpdateResultPrivate::~QTrackerDirectUpdateResultPrivate()
{
}

void QTrackerDirectUpdateResultPrivate::terminate()
{
    isFinished = 1;
    q->Q_EMIT finished();

    if (loop)
        loop->exit();
}

void QTrackerDirectUpdateResultPrivate::setLastError(const QSparqlError& e)
{
    q->setLastError(e);
}

////////////////////////////////////////////////////////////////////////////

QTrackerDirectUpdateResult::QTrackerDirectUpdateResult(QTrackerDirectDriverPrivate* p,
                                           const QString& query,
                                           QSparqlQuery::StatementType type)
{
    setQuery(query);
    setStatementType(type);
    d = new QTrackerDirectUpdateResultPrivate(this, p);
}

QTrackerDirectUpdateResult::~QTrackerDirectUpdateResult()
{
    if (d->isFinished == 0) {
        // We're deleting the Result before the async update has
        // finished. There is a pending async callback that will be called at
        // some point, and that will have our ResultPrivate as user_data. Don't
        // delete the ResultPrivate here, but just mark that we're no longer
        // alive. The callback will then delete the ResultPrivate.
        d->resultAlive = false;
        return;
    }

    delete d;
}

void QTrackerDirectUpdateResult::exec()
{
    if (!d->driverPrivate->driver->isOpen()) {
        setLastError(QSparqlError(d->driverPrivate->error,
                                  QSparqlError::ConnectionError));
        d->terminate();
        return;
    }

    tracker_sparql_connection_update_async( d->driverPrivate->connection,
                                            query().toUtf8().constData(),
                                            0,
                                            0,
                                            async_update_callback,
                                            d);
}

QSparqlBinding QTrackerDirectUpdateResult::binding(int /*field*/) const
{
    return QSparqlBinding();
}

QVariant QTrackerDirectUpdateResult::value(int /*field*/) const
{
    return QVariant();
}

void QTrackerDirectUpdateResult::waitForFinished()
{
    if (d->isFinished == 1)
        return;

    // We first need the connection to be ready before doing anything
    if (!d->driverPrivate->asyncOpenCalled) {
        QEventLoop loop;
        connect(d->driverPrivate->driver, SIGNAL(opened()), &loop, SLOT(quit()));
        loop.exec();
    }

    if (!d->driverPrivate->driver->isOpen()) {
        setLastError(QSparqlError(d->driverPrivate->error,
                                  QSparqlError::ConnectionError));
        d->terminate();
        return;
    }

    QEventLoop loop;
    d->loop = &loop;
    loop.exec();
    d->loop = 0;
}

bool QTrackerDirectUpdateResult::isFinished() const
{
    return d->isFinished == 1;
}

void QTrackerDirectUpdateResult::terminate()
{
    d->terminate();
}

int QTrackerDirectUpdateResult::size() const
{
    return 0;
}

QSparqlResultRow QTrackerDirectUpdateResult::current() const
{
    return QSparqlResultRow();
}

QT_END_NAMESPACE

#include "qsparql_tracker_direct_update_result_p.moc"
<commit_msg>Remove redundant resultAlive member of QTrackerDirectUpdateResultPrivate<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (ivan.frade@nokia.com)
**
** This file is part of the QtSparql module (not yet part of the Qt Toolkit).
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you have questions regarding the use of this file, please contact
** Nokia at ivan.frade@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include <tracker-sparql.h>

#include "qsparql_tracker_direct_update_result_p.h"
#include "qsparql_tracker_direct_driver_p.h"
#include "qsparql_tracker_direct_result_p.h"

#include <qsparqlerror.h>
#include <qsparqlbinding.h>
#include <qsparqlquery.h>
#include <qsparqlresultrow.h>

#include <QtCore/qcoreapplication.h>
#include <QtCore/qeventloop.h>

#include <QtCore/qdebug.h>

QT_BEGIN_NAMESPACE

////////////////////////////////////////////////////////////////////////////

class QTrackerDirectUpdateResultPrivate : public QObject {
    Q_OBJECT
public:
    QTrackerDirectUpdateResultPrivate(QTrackerDirectUpdateResult* result, QTrackerDirectDriverPrivate *dpp);

    ~QTrackerDirectUpdateResultPrivate();
    void terminate();
    void setLastError(const QSparqlError& e);

    QAtomicInt isFinished;
    QEventLoop *loop;

    QTrackerDirectUpdateResult* q;
    QTrackerDirectDriverPrivate *driverPrivate;
};

static void
async_update_callback( GObject *source_object,
                       GAsyncResult *result,
                       gpointer user_data)
{
    Q_UNUSED(source_object);
    QTrackerDirectUpdateResultPrivate *data = static_cast<QTrackerDirectUpdateResultPrivate*>(user_data);
    if (!data->q) {
        // The user has deleted the Result object before this callback was
        // called. Just delete the ResultPrivate here and do nothing.
        delete data;
        return;
    }

    GError *error = 0;
    tracker_sparql_connection_update_finish(data->driverPrivate->connection, result, &error);

    if (error) {
        QSparqlError e(QString::fromUtf8(error->message));
        e.setType(errorCodeToType(error->code));
        e.setNumber(error->code);
        data->setLastError(e);
        g_error_free(error);
    }

    // A workaround for http://bugreports.qt.nokia.com/browse/QTBUG-18434

    // We cannot emit the QSparqlResult::finished() signal directly here; so
    // delay it and emit it the next time the main loop spins.
    QMetaObject::invokeMethod(data->q, "terminate", Qt::QueuedConnection);
}

QTrackerDirectUpdateResultPrivate::QTrackerDirectUpdateResultPrivate(QTrackerDirectUpdateResult* result,
                                                                     QTrackerDirectDriverPrivate *dpp)
  : loop(0),
  q(result), driverPrivate(dpp)
{
}

QTrackerDirectUpdateResultPrivate::~QTrackerDirectUpdateResultPrivate()
{
}

void QTrackerDirectUpdateResultPrivate::terminate()
{
    isFinished = 1;
    q->Q_EMIT finished();

    if (loop)
        loop->exit();
}

void QTrackerDirectUpdateResultPrivate::setLastError(const QSparqlError& e)
{
    q->setLastError(e);
}

////////////////////////////////////////////////////////////////////////////

QTrackerDirectUpdateResult::QTrackerDirectUpdateResult(QTrackerDirectDriverPrivate* p,
                                           const QString& query,
                                           QSparqlQuery::StatementType type)
{
    setQuery(query);
    setStatementType(type);
    d = new QTrackerDirectUpdateResultPrivate(this, p);
}

QTrackerDirectUpdateResult::~QTrackerDirectUpdateResult()
{
    if (d->isFinished == 0) {
        // We're deleting the Result before the async update has
        // finished. There is a pending async callback that will be called at
        // some point, and that will have our ResultPrivate as user_data. Don't
        // delete the ResultPrivate here, but just mark that we're no longer
        // alive. The callback will then delete the ResultPrivate.
        d->q = 0;
        return;
    }

    delete d;
}

void QTrackerDirectUpdateResult::exec()
{
    if (!d->driverPrivate->driver->isOpen()) {
        setLastError(QSparqlError(d->driverPrivate->error,
                                  QSparqlError::ConnectionError));
        d->terminate();
        return;
    }

    tracker_sparql_connection_update_async( d->driverPrivate->connection,
                                            query().toUtf8().constData(),
                                            0,
                                            0,
                                            async_update_callback,
                                            d);
}

QSparqlBinding QTrackerDirectUpdateResult::binding(int /*field*/) const
{
    return QSparqlBinding();
}

QVariant QTrackerDirectUpdateResult::value(int /*field*/) const
{
    return QVariant();
}

void QTrackerDirectUpdateResult::waitForFinished()
{
    if (d->isFinished == 1)
        return;

    // We first need the connection to be ready before doing anything
    if (!d->driverPrivate->asyncOpenCalled) {
        QEventLoop loop;
        connect(d->driverPrivate->driver, SIGNAL(opened()), &loop, SLOT(quit()));
        loop.exec();
    }

    if (!d->driverPrivate->driver->isOpen()) {
        setLastError(QSparqlError(d->driverPrivate->error,
                                  QSparqlError::ConnectionError));
        d->terminate();
        return;
    }

    QEventLoop loop;
    d->loop = &loop;
    loop.exec();
    d->loop = 0;
}

bool QTrackerDirectUpdateResult::isFinished() const
{
    return d->isFinished == 1;
}

void QTrackerDirectUpdateResult::terminate()
{
    d->terminate();
}

int QTrackerDirectUpdateResult::size() const
{
    return 0;
}

QSparqlResultRow QTrackerDirectUpdateResult::current() const
{
    return QSparqlResultRow();
}

QT_END_NAMESPACE

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


<commit_before>// =============================================================================
//
// Copyright (c) 2013 Christopher Baker <http://christopherbaker.net>
//               2014 Brannon Dorsey <http://brannondorsey.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// =============================================================================

#include "ProjectManager.h"

using namespace ofx;

namespace of {
namespace Sketch {

ProjectManager::ProjectManager(const std::string& path):
    _path(path),
    _templateProject(ofToDataPath("Resources/Templates/NewProject", true))
{
    _projectWatcher.addPath(_path);

    std::vector<std::string> files;

    ofx::IO::DirectoryFilter filter;

    ofx::IO::DirectoryUtils::list(ofToDataPath(_path, true),
                                  files,
                                  true,
                                  &filter);

    std::vector<std::string>::iterator iter = files.begin();

    while(iter != files.end())
    {
        ofLogVerbose("ProjectManager::ProjectManager") << *iter;
        _projects.push_back(Project(*iter));
        ++iter;
    }

}

ProjectManager::~ProjectManager()
{
}

// can this function be: return getProjectRef(projectName); only?
const Project& ProjectManager::getProject(const std::string& projectName) const
{
    for (int i = 0; i < _projects.size(); i++) {
        if (_projects[i].getName() == projectName) {
            return _projects[i];
        }
    }

    return _projects[0]; //fallback
}

Project& ProjectManager::getProjectRef(const std::string& projectName)
{
    for (int i = 0; i < _projects.size(); i++) {
        if (_projects[i].getName() == projectName) {
            return _projects[i];
        }
    }

    return _projects[0]; //fallback
}

const std::vector<Project>& ProjectManager::getProjects() const
{
    return _projects;
}

//    std::string sketchPath = ofToDataPath("HelloWorldSketch/src/main.cpp",true);
//
//    ofBuffer buffer = ofBufferFromFile(sketchPath);
//
//    Json::Value setEditorSource;
//    setEditorSource["method"] = "setEditorSource";
//    Json::Value editorSource;
//    editorSource["source"] = buffer.getText();
//    setEditorSource["data"] = editorSource;
//
//    cout << setEditorSource.toStyledString() << endl;
//
//    evt.getConnectionRef().sendFrame(WebSocketFrame(setEditorSource.toStyledString()));
//
//    cout << "Connection opened from: " << evt.getConnectionRef().getClientAddress().toString() << endl;

void ProjectManager::getProjectList(const void* pSender, JSONRPC::MethodArgs& args)
{
    Json::Value projectList;
    for (int i = 0; i < _projects.size(); i++) {
        projectList[i]["projectName"] = _projects[i].getName();
    }
    args.result = projectList;
}

void ProjectManager::loadProject(const void* pSender, JSONRPC::MethodArgs& args)
{
    if (args.params.isMember("projectName")){
        std::string projectName = args.params["projectName"].asString();
        if (projectExists(projectName)) {
            for (int i = 0; i < _projects.size(); i++) {
                if (_projects[i].getName() == projectName) {
                    Project& project = _projects[i];
                    if (!project.isLoaded()) {
                        project.load(project.getPath(), projectName);
                    }
                    args.result = project.getData();
                    return;
                }
            }
            ofLogError("Project::loadProject") << "Project: "<< projectName << " was not found.";
        }
        else
        {
            ofLogError("Project::loadProject") << "Error loading project";
        }
    }
    else
    {
        ofLogError("Project::loadProject") << "ProjectName is not a member.";
    }
}

void ProjectManager::loadTemplateProject(const void *pSender, JSONRPC::MethodArgs &args)
{

    if (!_templateProject.isLoaded()) {
        _templateProject.load(_templateProject.getPath(), _templateProject.getName());
    }
    args.result = _templateProject.getData();
}

void ProjectManager::saveProject(const void* pSender, ofx::JSONRPC::MethodArgs& args)
{
    if (args.params.isMember("projectData")) {
        ofLogNotice("ProjectManager::saveProject") << "Saving project...";
        Json::Value projectData = args.params["projectData"];
        std::string projectName = projectData["projectFile"]["name"].asString();
        if (projectExists(projectName)) {
            Project& project = getProjectRef(projectName);
            project.save(projectData);
        }

    } else args.error = "A projectData object was not sent.";
}

void ProjectManager::createProject(const void* pSender, ofx::JSONRPC::MethodArgs& args)
{
    Json::Value projectData = args.params["projectData"];
    std::string projectName = args.params["projectData"]["projectFile"]["name"].asString();
    ofDirectory projectDir(_templateProject.getPath());
    projectDir.copyTo(ofToDataPath("Projects/" + projectName));
    ofFile templateProjectFile(ofToDataPath("Projects/" + projectName) + "/sketch/NewProject.sketch");
    templateProjectFile.remove();

    Project project(ofToDataPath("Projects/" + projectName));
    project.save(projectData);
    _projects.push_back(project);
    args.result = project.getData();
}

void ProjectManager::deleteProject(const void *pSender, ofx::JSONRPC::MethodArgs &args)
{
    std::string projectName = args.params["projectName"].asString();
    Project& project = getProjectRef(projectName);
    project.remove();

    for (int i = 0; i < _projects.size(); i++) {
        if (_projects[i].getName() == projectName) {
            _projects.erase(_projects.begin() + i);

            args.result["message"] = "Deleted " + projectName + " project.";
            return;
        }
    }
    args.error["message"] = "Error deleting " + projectName + " project.";
}

void ProjectManager::renameProject(const void *pSender, ofx::JSONRPC::MethodArgs &args)
{
    std::string projectName = args.params["projectName"].asString();
    std::string newProjectName = args.params["newProjectName"].asString();
    Project& project = getProjectRef(projectName);
    if (project.rename(newProjectName)) {
        args.result["message"] = "Renamed " + projectName + " project to " + newProjectName + ".";
    } else {
        args.error["message"] = "Error renaming " + projectName + " project.";
    }
}

bool ProjectManager::projectExists(const std::string& projectName) const
{
    for (int i = 0; i < _projects.size(); i++) {
        if (projectName == _projects[i].getName())
            return true;
    }

    return false;
}

void ProjectManager::reloadProjects()
{

}

void ProjectManager::updateProject(const std::string& projectName)
{

}

void ProjectManager::onDirectoryWatcherItemAdded(const Poco::DirectoryWatcher::DirectoryEvent& evt)
{
    ofSendMessage("Added:    " + evt.item.path());
}

void ProjectManager::onDirectoryWatcherItemRemoved(const Poco::DirectoryWatcher::DirectoryEvent& evt)
{
    ofSendMessage("Removed:  " + evt.item.path());
}

void ProjectManager::onDirectoryWatcherItemModified(const Poco::DirectoryWatcher::DirectoryEvent& evt)
{
    ofSendMessage("Modified: " + evt.item.path());
}

void ProjectManager::onDirectoryWatcherItemMovedFrom(const Poco::DirectoryWatcher::DirectoryEvent& evt)
{
    ofLogNotice("ofApp::onDirectoryWatcherItemMovedFrom") << "Moved From: " << evt.item.path();
}

void ProjectManager::onDirectoryWatcherItemMovedTo(const Poco::DirectoryWatcher::DirectoryEvent& evt)
{
    ofLogNotice("ofApp::onDirectoryWatcherItemMovedTo") << "Moved To: " << evt.item.path();
}

void ProjectManager::onDirectoryWatcherError(const Poco::Exception& exc)
{
    ofLogError("ofApp::onDirectoryWatcherError") << "Error: " << exc.displayText();
}

} } // namespace of::Sketch
<commit_msg>ProjectManager now reuses _path variable.<commit_after>// =============================================================================
//
// Copyright (c) 2013 Christopher Baker <http://christopherbaker.net>
//               2014 Brannon Dorsey <http://brannondorsey.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// =============================================================================

#include "ProjectManager.h"

using namespace ofx;

namespace of {
namespace Sketch {

ProjectManager::ProjectManager(const std::string& path):
    _path(path),
    _templateProject(ofToDataPath("Resources/Templates/NewProject", true))
{
    _projectWatcher.addPath(_path);
    ofLogNotice("ProjectManager::ProjectManager") << _path;

    std::vector<std::string> files;

    ofx::IO::DirectoryFilter filter;

    ofx::IO::DirectoryUtils::list(ofToDataPath(_path, true),
                                  files,
                                  true,
                                  &filter);

    std::vector<std::string>::iterator iter = files.begin();

    while(iter != files.end())
    {
        ofLogVerbose("ProjectManager::ProjectManager") << *iter;
        _projects.push_back(Project(*iter));
        ++iter;
    }

}

ProjectManager::~ProjectManager()
{
}

// can this function be: return getProjectRef(projectName); only?
const Project& ProjectManager::getProject(const std::string& projectName) const
{
    for (int i = 0; i < _projects.size(); i++) {
        if (_projects[i].getName() == projectName) {
            return _projects[i];
        }
    }

    return _projects[0]; //fallback
}

Project& ProjectManager::getProjectRef(const std::string& projectName)
{
    for (int i = 0; i < _projects.size(); i++) {
        if (_projects[i].getName() == projectName) {
            return _projects[i];
        }
    }

    return _projects[0]; //fallback
}

const std::vector<Project>& ProjectManager::getProjects() const
{
    return _projects;
}

//    std::string sketchPath = ofToDataPath("HelloWorldSketch/src/main.cpp",true);
//
//    ofBuffer buffer = ofBufferFromFile(sketchPath);
//
//    Json::Value setEditorSource;
//    setEditorSource["method"] = "setEditorSource";
//    Json::Value editorSource;
//    editorSource["source"] = buffer.getText();
//    setEditorSource["data"] = editorSource;
//
//    cout << setEditorSource.toStyledString() << endl;
//
//    evt.getConnectionRef().sendFrame(WebSocketFrame(setEditorSource.toStyledString()));
//
//    cout << "Connection opened from: " << evt.getConnectionRef().getClientAddress().toString() << endl;

void ProjectManager::getProjectList(const void* pSender, JSONRPC::MethodArgs& args)
{
    Json::Value projectList;
    for (int i = 0; i < _projects.size(); i++) {
        projectList[i]["projectName"] = _projects[i].getName();
    }
    args.result = projectList;
}

void ProjectManager::loadProject(const void* pSender, JSONRPC::MethodArgs& args)
{
    if (args.params.isMember("projectName")){
        std::string projectName = args.params["projectName"].asString();
        if (projectExists(projectName)) {
            for (int i = 0; i < _projects.size(); i++) {
                if (_projects[i].getName() == projectName) {
                    Project& project = _projects[i];
                    if (!project.isLoaded()) {
                        project.load(project.getPath(), projectName);
                    }
                    args.result = project.getData();
                    return;
                }
            }
            ofLogError("Project::loadProject") << "Project: "<< projectName << " was not found.";
        }
        else
        {
            ofLogError("Project::loadProject") << "Error loading project";
        }
    }
    else
    {
        ofLogError("Project::loadProject") << "ProjectName is not a member.";
    }
}

void ProjectManager::loadTemplateProject(const void *pSender, JSONRPC::MethodArgs &args)
{

    if (!_templateProject.isLoaded()) {
        _templateProject.load(_templateProject.getPath(), _templateProject.getName());
    }
    args.result = _templateProject.getData();
}

void ProjectManager::saveProject(const void* pSender, ofx::JSONRPC::MethodArgs& args)
{
    if (args.params.isMember("projectData")) {
        ofLogNotice("ProjectManager::saveProject") << "Saving project...";
        Json::Value projectData = args.params["projectData"];
        std::string projectName = projectData["projectFile"]["name"].asString();
        if (projectExists(projectName)) {
            Project& project = getProjectRef(projectName);
            project.save(projectData);
        }

    } else args.error = "A projectData object was not sent.";
}

void ProjectManager::createProject(const void* pSender, ofx::JSONRPC::MethodArgs& args)
{
    Json::Value projectData = args.params["projectData"];
    std::string projectName = args.params["projectData"]["projectFile"]["name"].asString();
    ofDirectory projectDir(_templateProject.getPath());
    projectDir.copyTo(_path + "/" + projectName);
    ofFile templateProjectFile(_path + "/" + projectName + "/sketch/NewProject.sketch");
    templateProjectFile.remove();

    Project project(_path + "/" + projectName);
    project.save(projectData);
    _projects.push_back(project);
    args.result = project.getData();
}

void ProjectManager::deleteProject(const void *pSender, ofx::JSONRPC::MethodArgs &args)
{
    std::string projectName = args.params["projectName"].asString();
    Project& project = getProjectRef(projectName);
    project.remove();

    for (int i = 0; i < _projects.size(); i++) {
        if (_projects[i].getName() == projectName) {
            _projects.erase(_projects.begin() + i);

            args.result["message"] = "Deleted " + projectName + " project.";
            return;
        }
    }
    args.error["message"] = "Error deleting " + projectName + " project.";
}

void ProjectManager::renameProject(const void *pSender, ofx::JSONRPC::MethodArgs &args)
{
    std::string projectName = args.params["projectName"].asString();
    std::string newProjectName = args.params["newProjectName"].asString();
    Project& project = getProjectRef(projectName);
    if (project.rename(newProjectName)) {
        args.result["message"] = "Renamed " + projectName + " project to " + newProjectName + ".";
    } else {
        args.error["message"] = "Error renaming " + projectName + " project.";
    }
}

bool ProjectManager::projectExists(const std::string& projectName) const
{
    for (int i = 0; i < _projects.size(); i++) {
        if (projectName == _projects[i].getName())
            return true;
    }

    return false;
}

void ProjectManager::reloadProjects()
{

}

void ProjectManager::updateProject(const std::string& projectName)
{

}

void ProjectManager::onDirectoryWatcherItemAdded(const Poco::DirectoryWatcher::DirectoryEvent& evt)
{
    ofSendMessage("Added:    " + evt.item.path());
}

void ProjectManager::onDirectoryWatcherItemRemoved(const Poco::DirectoryWatcher::DirectoryEvent& evt)
{
    ofSendMessage("Removed:  " + evt.item.path());
}

void ProjectManager::onDirectoryWatcherItemModified(const Poco::DirectoryWatcher::DirectoryEvent& evt)
{
    ofSendMessage("Modified: " + evt.item.path());
}

void ProjectManager::onDirectoryWatcherItemMovedFrom(const Poco::DirectoryWatcher::DirectoryEvent& evt)
{
    ofLogNotice("ofApp::onDirectoryWatcherItemMovedFrom") << "Moved From: " << evt.item.path();
}

void ProjectManager::onDirectoryWatcherItemMovedTo(const Poco::DirectoryWatcher::DirectoryEvent& evt)
{
    ofLogNotice("ofApp::onDirectoryWatcherItemMovedTo") << "Moved To: " << evt.item.path();
}

void ProjectManager::onDirectoryWatcherError(const Poco::Exception& exc)
{
    ofLogError("ofApp::onDirectoryWatcherError") << "Error: " << exc.displayText();
}

} } // namespace of::Sketch
<|endoftext|>


<commit_before>/*
 * VariableList.cc
 *
 * Copyright (C) 2009, 2014, 2015 Linas Vepstas
 *
 * Author: Linas Vepstas <linasvepstas@gmail.com>  January 2009
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the
 * exceptions at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/atoms/base/ClassServer.h>
#include <opencog/atoms/TypeNode.h>

#include "VariableList.h"

using namespace opencog;

void VariableList::validate_vardecl(const HandleSeq& oset)
{
	for (const Handle& h: oset)
	{
		Type t = h->getType();
		if (VARIABLE_NODE == t or GLOB_NODE == t)
		{
			_varlist.varset.insert(h);    // tree (unordered)
			_varlist.varseq.emplace_back(h); // vector (ordered)
		}
		else if (TYPED_VARIABLE_LINK == t)
		{
			get_vartype(h);
		}
		else
			throw InvalidParamException(TRACE_INFO,
				"Expected a VariableNode or a TypedVariableLink, got: %s",
					classserver().getTypeName(t).c_str());
	}
	build_index();
}

VariableList::VariableList(const HandleSeq& oset,
                       TruthValuePtr tv, AttentionValuePtr av)
	: Link(VARIABLE_LIST, oset, tv, av)
{
	validate_vardecl(oset);
}

VariableList::VariableList(Type t, const HandleSeq& oset,
                       TruthValuePtr tv, AttentionValuePtr av)
	: Link(t, oset, tv, av)
{
	// derived classes have a different initialization order
	if (VARIABLE_LIST != t) return;
	validate_vardecl(oset);
}

VariableList::VariableList(Link &l)
	: Link(l)
{
	// Type must be as expected
	Type tscope = l.getType();
	if (not classserver().isA(tscope, VARIABLE_LIST))
	{
		const std::string& tname = classserver().getTypeName(tscope);
		throw InvalidParamException(TRACE_INFO,
			"Expecting a VariableList, got %s", tname.c_str());
	}

	// Dervided types have a different initialization sequence
	if (VARIABLE_LIST != tscope) return;
	validate_vardecl(_outgoing);
}

/* ================================================================= */
/**
 * Extract the variable type(s) from a TypedVariableLink
 *
 * The call is expecting htypelink to point to one of the two
 * following structures:
 *
 *    TypedVariableLink
 *       VariableNode "$some_var_name"
 *       TypeNode  "ConceptNode"
 *
 * or
 *
 *    TypedVariableLink
 *       VariableNode "$some_var_name"
 *       TypeChoice
 *          TypeNode  "ConceptNode"
 *          TypeNode  "NumberNode"
 *          TypeNode  "WordNode"
 *
 * or possibly types that are SignatureLink's or FuyzzyLink's or
 * polymorphic combinations thereof: e.g. the following is valid:
 *
 *    TypedVariableLink
 *       VariableNode "$some_var_name"
 *       TypeChoice
 *          TypeNode  "ConceptNode"
 *          SignatureLink
 *              InheritanceLink
 *                 PredicateNode "foobar"
 *                 TypeNode  "ListLink"
 *          FuzzyLink
 *              InheritanceLink
 *                 ConceptNode "animal"
 *                 ConceptNode "tiger"
 *
 * In either case, the variable itself is appended to "vset",
 * and the list of allowed types are associated with the variable
 * via the map "typemap".
 */
void VariableList::get_vartype(const Handle& htypelink)
{
	const std::vector<Handle>& oset = LinkCast(htypelink)->getOutgoingSet();
	if (2 != oset.size())
	{
		throw InvalidParamException(TRACE_INFO,
			"TypedVariableLink has wrong size, got %lu", oset.size());
	}

	Handle varname = oset[0];
	Handle vartype = oset[1];

	// The vartype is either a single type name, or a list of typenames.
	Type t = vartype->getType();
	if (TYPE_NODE == t)
	{
		Type vt = TypeNodeCast(vartype)->get_value();
		if (vt != ATOM)  // Atom type is same as untyped.
		{
			std::set<Type> ts = {vt};
			_varlist._simple_typemap.insert({varname, ts});
		}
	}
	else if (TYPE_CHOICE == t)
	{
		std::set<Type> typeset;
		std::set<Handle> deepset;
		std::set<Handle> fuzzset;

		const HandleSeq& tset = LinkCast(vartype)->getOutgoingSet();
		size_t tss = tset.size();
		for (size_t i=0; i<tss; i++)
		{
			Handle ht(tset[i]);
			Type var_type = ht->getType();
			if (TYPE_NODE == var_type)
			{
				Type vt = TypeNodeCast(ht)->get_value();
				if (ATOM != vt) typeset.insert(vt);
			}
			else if (SIGNATURE_LINK == var_type)
			{
				const HandleSeq& sig = LinkCast(ht)->getOutgoingSet();
				if (1 != sig.size())
					throw SyntaxException(TRACE_INFO,
						"Unexpected contents in SignatureLink\n"
						"Expected arity==1, got %s", vartype->toString().c_str());

				deepset.insert(ht);
			}
			else if (FUZZY_LINK == var_type)
			{
				const HandleSeq& fuz = LinkCast(ht)->getOutgoingSet();
				if (1 != fuz.size())
					throw SyntaxException(TRACE_INFO,
						"Unexpected contents in FuzzyLink\n"
						"Expected arity==1, got %s", vartype->toString().c_str());

				fuzzset.insert(ht);
			}
			else
			{
				throw InvalidParamException(TRACE_INFO,
					"VariableChoice has unexpected content:\n"
					"Expected TypeNode, got %s",
					    classserver().getTypeName(ht->getType()).c_str());
			}
		}

		if (0 < typeset.size())
			_varlist._simple_typemap.insert({varname, typeset});
		if (0 < deepset.size())
			_varlist._deep_typemap.insert({varname, deepset});
		if (0 < fuzzset.size())
			_varlist._fuzzy_typemap.insert({varname, fuzzset});
	}
	else if (SIGNATURE_LINK == t)
	{
		const HandleSeq& tset = LinkCast(vartype)->getOutgoingSet();
		if (1 != tset.size())
			throw SyntaxException(TRACE_INFO,
				"Unexpected contents in SignatureLink\n"
				"Expected arity==1, got %s", vartype->toString().c_str());

		std::set<Handle> ts;
		ts.insert(vartype);
		_varlist._deep_typemap.insert({varname, ts});
	}
	else if (FUZZY_LINK == t)
	{
		const HandleSeq& tset = LinkCast(vartype)->getOutgoingSet();
		if (1 != tset.size())
			throw SyntaxException(TRACE_INFO,
				"Unexpected contents in FuzzyLink\n"
				"Expected arity==1, got %s", vartype->toString().c_str());

		std::set<Handle> ts;
		ts.insert(vartype);
		_varlist._fuzzy_typemap.insert({varname, ts});
	}
	else
	{
		throw SyntaxException(TRACE_INFO,
			"Unexpected contents in TypedVariableLink\n"
			"Expected type specifier (e.g. TypeNode, TypeChoice, etc.), got %s",
			classserver().getTypeName(t).c_str());
	}

	_varlist.varset.insert(varname);
	_varlist.varseq.emplace_back(varname);
}

/* ================================================================= */
/**
 * Validate variable declarations for syntax correctness.
 *
 * This will check to make sure that a set of variable declarations are
 * of a reasonable form. Thus, for example, a structure similar to the
 * below is expected.
 *
 *       VariableList
 *          VariableNode "$var0"
 *          VariableNode "$var1"
 *          TypedVariableLink
 *             VariableNode "$var2"
 *             TypeNode  "ConceptNode"
 *          TypedVariableLink
 *             VariableNode "$var3"
 *             TypeChoice
 *                 TypeNode  "PredicateNode"
 *                 TypeNode  "GroundedPredicateNode"
 *
 * As a side-effect, the variables and type restrictions are unpacked.
 */
void VariableList::validate_vardecl(const Handle& hdecls)
{
	// Expecting the declaration list to be either a single
	// variable, or a list of variable declarations
	Type tdecls = hdecls->getType();
	if (VARIABLE_NODE == tdecls or GLOB_NODE == tdecls)
	{
		_varlist.varset.insert(hdecls);
		_varlist.varseq.emplace_back(hdecls);
	}
	else if (TYPED_VARIABLE_LINK == tdecls)
	{
		get_vartype(hdecls);
	}
	else if (VARIABLE_LIST == tdecls)
	{
		// The list of variable declarations should be .. a list of
		// variables! Make sure its as expected.
		const std::vector<Handle>& dset = LinkCast(hdecls)->getOutgoingSet();
		validate_vardecl(dset);
	}
	else
	{
		throw InvalidParamException(TRACE_INFO,
			"Expected a VariableList holding variable declarations");
	}
	build_index();
}

/* ================================================================= */
/**
 * Build the index from variable name, to its ordinal number.
 * The index is needed for variable substitution, i.e. for the
 * substitute method below.  The specific sequence order of the
 * variables is essential for making substitution work.
 */
void VariableList::build_index(void)
{
	if (0 < _varlist.index.size()) return;
	size_t sz = _varlist.varseq.size();
	for (size_t i=0; i<sz; i++)
	{
		_varlist.index.insert(std::pair<Handle, unsigned int>(_varlist.varseq[i], i));
	}
}

/* ===================== END OF FILE ===================== */
<commit_msg>Remove some un-needed casts<commit_after>/*
 * VariableList.cc
 *
 * Copyright (C) 2009, 2014, 2015 Linas Vepstas
 *
 * Author: Linas Vepstas <linasvepstas@gmail.com>  January 2009
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the
 * exceptions at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/atoms/base/ClassServer.h>
#include <opencog/atoms/TypeNode.h>

#include "VariableList.h"

using namespace opencog;

void VariableList::validate_vardecl(const HandleSeq& oset)
{
	for (const Handle& h: oset)
	{
		Type t = h->getType();
		if (VARIABLE_NODE == t or GLOB_NODE == t)
		{
			_varlist.varset.insert(h);    // tree (unordered)
			_varlist.varseq.emplace_back(h); // vector (ordered)
		}
		else if (TYPED_VARIABLE_LINK == t)
		{
			get_vartype(h);
		}
		else
			throw InvalidParamException(TRACE_INFO,
				"Expected a VariableNode or a TypedVariableLink, got: %s",
					classserver().getTypeName(t).c_str());
	}
	build_index();
}

VariableList::VariableList(const HandleSeq& oset,
                       TruthValuePtr tv, AttentionValuePtr av)
	: Link(VARIABLE_LIST, oset, tv, av)
{
	validate_vardecl(oset);
}

VariableList::VariableList(Type t, const HandleSeq& oset,
                       TruthValuePtr tv, AttentionValuePtr av)
	: Link(t, oset, tv, av)
{
	// derived classes have a different initialization order
	if (VARIABLE_LIST != t) return;
	validate_vardecl(oset);
}

VariableList::VariableList(Link &l)
	: Link(l)
{
	// Type must be as expected
	Type tscope = l.getType();
	if (not classserver().isA(tscope, VARIABLE_LIST))
	{
		const std::string& tname = classserver().getTypeName(tscope);
		throw InvalidParamException(TRACE_INFO,
			"Expecting a VariableList, got %s", tname.c_str());
	}

	// Dervided types have a different initialization sequence
	if (VARIABLE_LIST != tscope) return;
	validate_vardecl(_outgoing);
}

/* ================================================================= */
/**
 * Extract the variable type(s) from a TypedVariableLink
 *
 * The call is expecting htypelink to point to one of the two
 * following structures:
 *
 *    TypedVariableLink
 *       VariableNode "$some_var_name"
 *       TypeNode  "ConceptNode"
 *
 * or
 *
 *    TypedVariableLink
 *       VariableNode "$some_var_name"
 *       TypeChoice
 *          TypeNode  "ConceptNode"
 *          TypeNode  "NumberNode"
 *          TypeNode  "WordNode"
 *
 * or possibly types that are SignatureLink's or FuyzzyLink's or
 * polymorphic combinations thereof: e.g. the following is valid:
 *
 *    TypedVariableLink
 *       VariableNode "$some_var_name"
 *       TypeChoice
 *          TypeNode  "ConceptNode"
 *          SignatureLink
 *              InheritanceLink
 *                 PredicateNode "foobar"
 *                 TypeNode  "ListLink"
 *          FuzzyLink
 *              InheritanceLink
 *                 ConceptNode "animal"
 *                 ConceptNode "tiger"
 *
 * In either case, the variable itself is appended to "vset",
 * and the list of allowed types are associated with the variable
 * via the map "typemap".
 */
void VariableList::get_vartype(const Handle& htypelink)
{
	const std::vector<Handle>& oset = htypelink->getOutgoingSet();
	if (2 != oset.size())
	{
		throw InvalidParamException(TRACE_INFO,
			"TypedVariableLink has wrong size, got %lu", oset.size());
	}

	Handle varname = oset[0];
	Handle vartype = oset[1];

	// The vartype is either a single type name, or a list of typenames.
	Type t = vartype->getType();
	if (TYPE_NODE == t)
	{
		Type vt = TypeNodeCast(vartype)->get_value();
		if (vt != ATOM)  // Atom type is same as untyped.
		{
			std::set<Type> ts = {vt};
			_varlist._simple_typemap.insert({varname, ts});
		}
	}
	else if (TYPE_CHOICE == t)
	{
		std::set<Type> typeset;
		std::set<Handle> deepset;
		std::set<Handle> fuzzset;

		const HandleSeq& tset = vartype->getOutgoingSet();
		size_t tss = tset.size();
		for (size_t i=0; i<tss; i++)
		{
			Handle ht(tset[i]);
			Type var_type = ht->getType();
			if (TYPE_NODE == var_type)
			{
				Type vt = TypeNodeCast(ht)->get_value();
				if (ATOM != vt) typeset.insert(vt);
			}
			else if (SIGNATURE_LINK == var_type)
			{
				const HandleSeq& sig = ht->getOutgoingSet();
				if (1 != sig.size())
					throw SyntaxException(TRACE_INFO,
						"Unexpected contents in SignatureLink\n"
						"Expected arity==1, got %s", vartype->toString().c_str());

				deepset.insert(ht);
			}
			else if (FUZZY_LINK == var_type)
			{
				const HandleSeq& fuz = ht->getOutgoingSet();
				if (1 != fuz.size())
					throw SyntaxException(TRACE_INFO,
						"Unexpected contents in FuzzyLink\n"
						"Expected arity==1, got %s", vartype->toString().c_str());

				fuzzset.insert(ht);
			}
			else
			{
				throw InvalidParamException(TRACE_INFO,
					"VariableChoice has unexpected content:\n"
					"Expected TypeNode, got %s",
					    classserver().getTypeName(ht->getType()).c_str());
			}
		}

		if (0 < typeset.size())
			_varlist._simple_typemap.insert({varname, typeset});
		if (0 < deepset.size())
			_varlist._deep_typemap.insert({varname, deepset});
		if (0 < fuzzset.size())
			_varlist._fuzzy_typemap.insert({varname, fuzzset});
	}
	else if (SIGNATURE_LINK == t)
	{
		const HandleSeq& tset = vartype->getOutgoingSet();
		if (1 != tset.size())
			throw SyntaxException(TRACE_INFO,
				"Unexpected contents in SignatureLink\n"
				"Expected arity==1, got %s", vartype->toString().c_str());

		std::set<Handle> ts;
		ts.insert(vartype);
		_varlist._deep_typemap.insert({varname, ts});
	}
	else if (FUZZY_LINK == t)
	{
		const HandleSeq& tset = vartype->getOutgoingSet();
		if (1 != tset.size())
			throw SyntaxException(TRACE_INFO,
				"Unexpected contents in FuzzyLink\n"
				"Expected arity==1, got %s", vartype->toString().c_str());

		std::set<Handle> ts;
		ts.insert(vartype);
		_varlist._fuzzy_typemap.insert({varname, ts});
	}
	else
	{
		throw SyntaxException(TRACE_INFO,
			"Unexpected contents in TypedVariableLink\n"
			"Expected type specifier (e.g. TypeNode, TypeChoice, etc.), got %s",
			classserver().getTypeName(t).c_str());
	}

	_varlist.varset.insert(varname);
	_varlist.varseq.emplace_back(varname);
}

/* ================================================================= */
/**
 * Validate variable declarations for syntax correctness.
 *
 * This will check to make sure that a set of variable declarations are
 * of a reasonable form. Thus, for example, a structure similar to the
 * below is expected.
 *
 *       VariableList
 *          VariableNode "$var0"
 *          VariableNode "$var1"
 *          TypedVariableLink
 *             VariableNode "$var2"
 *             TypeNode  "ConceptNode"
 *          TypedVariableLink
 *             VariableNode "$var3"
 *             TypeChoice
 *                 TypeNode  "PredicateNode"
 *                 TypeNode  "GroundedPredicateNode"
 *
 * As a side-effect, the variables and type restrictions are unpacked.
 */
void VariableList::validate_vardecl(const Handle& hdecls)
{
	// Expecting the declaration list to be either a single
	// variable, or a list of variable declarations
	Type tdecls = hdecls->getType();
	if (VARIABLE_NODE == tdecls or GLOB_NODE == tdecls)
	{
		_varlist.varset.insert(hdecls);
		_varlist.varseq.emplace_back(hdecls);
	}
	else if (TYPED_VARIABLE_LINK == tdecls)
	{
		get_vartype(hdecls);
	}
	else if (VARIABLE_LIST == tdecls)
	{
		// The list of variable declarations should be .. a list of
		// variables! Make sure its as expected.
		const std::vector<Handle>& dset = hdecls->getOutgoingSet();
		validate_vardecl(dset);
	}
	else
	{
		throw InvalidParamException(TRACE_INFO,
			"Expected a VariableList holding variable declarations");
	}
	build_index();
}

/* ================================================================= */
/**
 * Build the index from variable name, to its ordinal number.
 * The index is needed for variable substitution, i.e. for the
 * substitute method below.  The specific sequence order of the
 * variables is essential for making substitution work.
 */
void VariableList::build_index(void)
{
	if (0 < _varlist.index.size()) return;
	size_t sz = _varlist.varseq.size();
	for (size_t i=0; i<sz; i++)
	{
		_varlist.index.insert(std::pair<Handle, unsigned int>(_varlist.varseq[i], i));
	}
}

/* ===================== END OF FILE ===================== */
<|endoftext|>


<commit_before>#include "ncd_gateway.h"
#include "S3B.h"
#include "spark_wiring_eeprom.h"

String firmware_version = "000029";
S3B sModule;
String eventReturns[5];
unsigned long tOut = 3000;

void init_gateway(){
    Particle.function("deviceComm", gatewayCommand);
    Particle.subscribe("ncd_deviceCom", commandHandler, MY_DEVICES);
    Particle.variable("ncd_version", firmware_version);
    Serial1.begin(115200);
    Wire.begin();
}
int hexToInt(String arg, byte bytes[], int length){
    arg.getBytes(bytes, length+1);
    for(int i=0;i<length;i++){
        if(bytes[i]>70) bytes[i] -= 32;
        if(bytes[i]>58) bytes[i] -= 7;
        bytes[i] -= 48;
    }
    return 1;
}
int base64ToInt(String arg, byte buff[], int length){
    byte bytes[length];
    arg.getBytes(bytes, length+1);
    int buffInd=0;
    int cbits=0;
    int cByte;
    int adj;
    for(int i=0;i<length;i++){
        cByte = bytes[i];
        if(cByte==43) cByte = 58;
        if(cByte==47) cByte = 59;
        if(cByte<65) cByte += 75;
        if(cByte<97) cByte += 6;
        cByte -= 71;
        switch(cbits){
            case 0:
                buff[buffInd] = cByte << 2;
                cbits = 6;
                break;
            case 2:
                buff[buffInd] = buff[buffInd]+cByte;
                buffInd++;
                cbits = 0;
                break;
            case 4:
                buff[buffInd] = buff[buffInd] + (cByte >> 2);
                buffInd++;
                buff[buffInd] = (cByte & 3) << 6;
                cbits = 2;
                break;
            case 6:
                buff[buffInd] = buff[buffInd] + (cByte >> 4);
                buffInd++;
                buff[buffInd] = (cByte & 15) << 4;
                cbits = 4;
                break;
        }
    }
    return 1;
}
int gatewayCommand(String arg){
    int length = arg.length();
    byte buff[length];
    base64ToInt(arg, buff, length);
    return ncdApi(buff);
}

void commandHandler(const char *event, const char *data){
    String newCommand = String(data);
    gatewayCommand(newCommand);
}
int ncdApi(byte packetBytes[]){
    int buffLen = 1;
    Serial.println(String(packetBytes[0]));
    switch(packetBytes[0]){
        case 185:
            {
                return firmware_version.toInt();
            }
        case 186:
            {
                //I2C bus scan
                int start = packetBytes[1]*32+1;
                int end = start+32;
                int addrStatus;
                int status = 0;
                for(start;start<end;start++){
                    Wire.beginTransmission(start);
                    addrStatus = Wire.endTransmission();
                    if(start+32 > end){
                        status = status << 1;
                    }
                    if(addrStatus > 0){
                        addrStatus = 1;
                    }
                    status+=addrStatus;
                }
                return status;
            }
        case 187:
            {
                //packet of packets
                int i=2;
                int max;
                byte status[packetBytes[1]];
                for(int pn = 0; pn<packetBytes[1]; pn++){

                    max=i+packetBytes[i];
                    Serial.println(max);
                    byte intPacket[packetBytes[i]];
                    i++;
                    int ni=0;
                    for(i;i<=max;i++){
                        intPacket[ni]=packetBytes[i];
                        ni++;
                    }
                    status[pn]=ncdApi(intPacket);
                }
                return bytesToInt(status, packetBytes[1]);
            }
        case 188:
            {
                //plain i2c w/r command
                if(packetBytes[3] > 0){
                    buffLen = packetBytes[3];
                }
                byte buff[buffLen];
                i2c_command(packetBytes, buff);
                return bytesToInt(buff, buffLen);
            }
        case 189:
            {
                //masking command
                int addr = packetBytes[1];
                int maskOp = packetBytes[2];
                int maskedOffsets = packetBytes[3];
                int readCommandLen = packetBytes[4];
                int readLen = packetBytes[5];
                int readCommand[readCommandLen];

                array_slice(packetBytes, 6, readCommandLen, readCommand);

                int writeCommandLen = packetBytes[6+readCommandLen];
                int writeCommand[writeCommandLen];

                array_slice(packetBytes, 7+readCommandLen, writeCommandLen, writeCommand);

                int writeVals[writeCommandLen];
                int wi=0;
                for(wi; wi<maskedOffsets; wi++){
                    writeVals[wi]=writeCommand[wi];
                    Serial.println(writeVals[wi]);
                }

                writeCommandsI2C(addr, readCommand, readCommandLen);
                Wire.requestFrom(addr, readLen);
                for(int i=0;i<readLen;i++){
                    int current = Wire.read();
                    writeVals[wi] = mask(current, writeCommand[wi], maskOp);
                    Serial.println(current);
                    Serial.println(writeVals[wi]);
                    wi++;
                }

                return writeCommandsI2C(addr, writeVals, writeCommandLen);
            }
        case 190:
            {
                int delayTime = (packetBytes[1] << 8) + packetBytes[2];
                delay(delayTime);
                return 1;
            }
    }
    return 1;
}
int mask(int val, int mask, int type){
    switch(type){
        case 0:
            val |= mask;
            break;
        case 1:
            val ^= mask;
            break;
        case 2:
            val &= ~mask;
            break;
        case 3:
            val &= mask;
            break;
        case 4:
            val = val << mask;
            break;
        case 5:
            val = val >> mask;
    }
    return val;
}
void i2c_command(byte bytes[], byte *buff){
    if(bytes[0] == 188){
        int commands[bytes[2]];
        array_slice(bytes, 4, bytes[2], commands);
        int addr = bytes[1];
        if(bytes[3] == 0){
            //write command
            buff[0]=writeCommandsI2C(addr, commands, bytes[2]);
        }else{
            //read command
            writeCommandsI2C(addr, commands, bytes[2]);
            Wire.requestFrom(addr, bytes[3]);
            for(int i=0;i<bytes[3];i++){
                buff[i] = Wire.read();
            }
        }
    }
}
void array_slice(byte bytes[], int start, int len, byte *buff){
    int ni = 0;
    int end = start+len;
    for(int i=start; i<=end; i++){
        buff[ni] = bytes[i];
        ni++;
    }
}
void array_slice(byte bytes[], int start, int len, int *buff){
    int ni=0;
    int end = start+len;
    for(int i=start; i<=end; i++){
        buff[ni] = bytes[i];
        ni++;
    }
}
int sendEvent(String key){
    int i = key.toInt();
    String eventName = "";
    eventName = "eventReturn_"+key;
    Particle.publish(eventName, eventReturns[i], 60, PRIVATE);
    eventReturns[i] = "";
    return 1;
};
int setEventReturn(String value){
    int index = 0;
    while(eventReturns[index].length() > 1){
        index++;
    }
    eventReturns[index] = value;
    return index;
};
int writeCommandsI2C(int addr, int* commands, int commandsLen){
    Serial.printf("Running I2C Command, address: %i data: ",addr);
    Wire.beginTransmission(addr);
    for(int i = 0; i < commandsLen; i++){
        Wire.write(commands[i]);
        Serial.printf("%i, ",commands[i]);
    }
    int status = Wire.endTransmission();
    Serial.printf(" Status: %i \n", status);
    return status;
};
int bytesToInt(byte bytes[], int length){
    int ret = bytes[0];
    for(int i=1; i<length; i++){
        ret = ret << 8;
        ret += bytes[i];
    }
    return ret;
}
<commit_msg>Update ncd_gateway.cpp<commit_after>#include "ncd_gateway.h"
#include "spark_wiring_eeprom.h"

String firmware_version = "000029";
String eventReturns[5];
unsigned long tOut = 3000;

void init_gateway(){
    Particle.function("deviceComm", gatewayCommand);
    Particle.subscribe("ncd_deviceCom", commandHandler, MY_DEVICES);
    Particle.variable("ncd_version", firmware_version);
    Wire.begin();
}
int hexToInt(String arg, byte bytes[], int length){
    arg.getBytes(bytes, length+1);
    for(int i=0;i<length;i++){
        if(bytes[i]>70) bytes[i] -= 32;
        if(bytes[i]>58) bytes[i] -= 7;
        bytes[i] -= 48;
    }
    return 1;
}
int base64ToInt(String arg, byte buff[], int length){
    byte bytes[length];
    arg.getBytes(bytes, length+1);
    int buffInd=0;
    int cbits=0;
    int cByte;
    int adj;
    for(int i=0;i<length;i++){
        cByte = bytes[i];
        if(cByte==43) cByte = 58;
        if(cByte==47) cByte = 59;
        if(cByte<65) cByte += 75;
        if(cByte<97) cByte += 6;
        cByte -= 71;
        switch(cbits){
            case 0:
                buff[buffInd] = cByte << 2;
                cbits = 6;
                break;
            case 2:
                buff[buffInd] = buff[buffInd]+cByte;
                buffInd++;
                cbits = 0;
                break;
            case 4:
                buff[buffInd] = buff[buffInd] + (cByte >> 2);
                buffInd++;
                buff[buffInd] = (cByte & 3) << 6;
                cbits = 2;
                break;
            case 6:
                buff[buffInd] = buff[buffInd] + (cByte >> 4);
                buffInd++;
                buff[buffInd] = (cByte & 15) << 4;
                cbits = 4;
                break;
        }
    }
    return 1;
}
int gatewayCommand(String arg){
    int length = arg.length();
    byte buff[length];
    base64ToInt(arg, buff, length);
    Serial.println(arg);
    return ncdApi(buff);
}

void commandHandler(const char *event, const char *data){
    String newCommand = String(data);
    gatewayCommand(newCommand);
}
int ncdApi(byte packetBytes[]){
    int buffLen = 1;
    Serial.println(String(packetBytes[0]));
    switch(packetBytes[0]){
        case 185:
            {
                return firmware_version.toInt();
            }
        case 186:
            {
                //I2C bus scan
                Serial.println(String(packetBytes[1]));
                Serial.println(String(packetBytes[2]));
                int start = packetBytes[1]*32+1;
                int end = start+32;
                int addrStatus;
                int status = 0;
                for(start;start<end;start++){
                    Wire.beginTransmission(start);
                    addrStatus = Wire.endTransmission();
                    if(start+32 > end){
                        status = status << 1;
                    }
                    if(addrStatus > 0){
                        addrStatus = 1;
                    }else{
                        Serial.print("Device found on: ");
                        Serial.println(start);
                    }
                    status+=addrStatus;
                }
                return status;
            }
        case 187:
            {
                //packet of packets
                int i=2;
                int max;
                byte status[packetBytes[1]];
                for(int pn = 0; pn<packetBytes[1]; pn++){

                    max=i+packetBytes[i];
                    Serial.println(max);
                    byte intPacket[packetBytes[i]];
                    i++;
                    int ni=0;
                    for(i;i<=max;i++){
                        intPacket[ni]=packetBytes[i];
                        ni++;
                    }
                    status[pn]=ncdApi(intPacket);
                }
                return bytesToInt(status, packetBytes[1]);
            }
        case 188:
            {
                //plain i2c w/r command
                if(packetBytes[3] > 0){
                    buffLen = packetBytes[3];
                }
                byte buff[buffLen];
                i2c_command(packetBytes, buff);
                return bytesToInt(buff, buffLen);
            }
        case 189:
            {
                //masking command
                int addr = packetBytes[1];
                int maskOp = packetBytes[2];
                int maskedOffsets = packetBytes[3];
                int readCommandLen = packetBytes[4];
                int readLen = packetBytes[5];
                int readCommand[readCommandLen];

                array_slice(packetBytes, 6, readCommandLen, readCommand);

                int writeCommandLen = packetBytes[6+readCommandLen];
                int writeCommand[writeCommandLen];

                array_slice(packetBytes, 7+readCommandLen, writeCommandLen, writeCommand);

                int writeVals[writeCommandLen];
                int wi=0;
                for(wi; wi<maskedOffsets; wi++){
                    writeVals[wi]=writeCommand[wi];
                    Serial.println(writeVals[wi]);
                }

                writeCommandsI2C(addr, readCommand, readCommandLen);
                Wire.requestFrom(addr, readLen);
                for(int i=0;i<readLen;i++){
                    int current = Wire.read();
                    writeVals[wi] = mask(current, writeCommand[wi], maskOp);
                    Serial.println(current);
                    Serial.println(writeVals[wi]);
                    wi++;
                }

                return writeCommandsI2C(addr, writeVals, writeCommandLen);
            }
        case 190:
            {
                int delayTime = (packetBytes[1] << 8) + packetBytes[2];
                delay(delayTime);
                return 1;
            }
    }
    return 1;
}
int mask(int val, int mask, int type){
    switch(type){
        case 0:
            val |= mask;
            break;
        case 1:
            val ^= mask;
            break;
        case 2:
            val &= ~mask;
            break;
        case 3:
            val &= mask;
            break;
        case 4:
            val = val << mask;
            break;
        case 5:
            val = val >> mask;
    }
    return val;
}
void i2c_command(byte bytes[], byte *buff){
    if(bytes[0] == 188){
        int commands[bytes[2]];
        array_slice(bytes, 4, bytes[2], commands);
        int addr = bytes[1];
        if(bytes[3] == 0){
            //write command
            buff[0]=writeCommandsI2C(addr, commands, bytes[2]);
        }else{
            //read command
            writeCommandsI2C(addr, commands, bytes[2]);
            Wire.requestFrom(addr, bytes[3]);
            for(int i=0;i<bytes[3];i++){
                buff[i] = Wire.read();
            }
        }
    }
}
void array_slice(byte bytes[], int start, int len, byte *buff){
    int ni = 0;
    int end = start+len;
    for(int i=start; i<=end; i++){
        buff[ni] = bytes[i];
        ni++;
    }
}
void array_slice(byte bytes[], int start, int len, int *buff){
    int ni=0;
    int end = start+len;
    for(int i=start; i<=end; i++){
        buff[ni] = bytes[i];
        ni++;
    }
}
int sendEvent(String key){
    int i = key.toInt();
    String eventName = "";
    eventName = "eventReturn_"+key;
    Particle.publish(eventName, eventReturns[i], 60, PRIVATE);
    eventReturns[i] = "";
    return 1;
};
int setEventReturn(String value){
    int index = 0;
    while(eventReturns[index].length() > 1){
        index++;
    }
    eventReturns[index] = value;
    return index;
};
int writeCommandsI2C(int addr, int* commands, int commandsLen){
    Serial.printf("Running I2C Command, address: %i data: ",addr);
    Wire.beginTransmission(addr);
    for(int i = 0; i < commandsLen; i++){
        Wire.write(commands[i]);
        Serial.printf("%i, ",commands[i]);
    }
    int status = Wire.endTransmission();
    Serial.printf(" Status: %i \n", status);
    return status;
};
int bytesToInt(byte bytes[], int length){
    int ret = bytes[0];
    for(int i=1; i<length; i++){
        ret = ret << 8;
        ret += bytes[i];
    }
    return ret;
}
<|endoftext|>


<commit_before>/*

   nsjail - logging
   -----------------------------------------

   Copyright 2014 Google Inc. All Rights Reserved.

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

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

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

*/

#include "logs.h"

#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>

#include "macros.h"
#include "util.h"

#include <string.h>

namespace logs {

static int _log_fd = STDERR_FILENO;
static bool _log_fd_isatty = true;
static enum llevel_t _log_level = INFO;
static bool _log_set = false;

__attribute__((constructor)) static void log_init(void) {
	_log_fd_isatty = isatty(_log_fd);
}

bool logSet() {
  return _log_set;
}

/*
 * Log to stderr by default. Use a dup()d fd, because in the future we'll associate the
 * connection socket with fd (0, 1, 2).
 */

void logLevel(enum llevel_t ll) {
	_log_level = ll;
}

void logFile(const std::string& logfile) {
        _log_set = true;
	/* Close previous log_fd */
	if (_log_fd > STDERR_FILENO) {
		close(_log_fd);
		_log_fd = STDERR_FILENO;
	}
	if (logfile.empty()) {
		_log_fd = fcntl(_log_fd, F_DUPFD_CLOEXEC, 0);
	} else {
		if (TEMP_FAILURE_RETRY(_log_fd = open(logfile.c_str(),
					   O_CREAT | O_RDWR | O_APPEND | O_CLOEXEC, 0640)) == -1) {
			_log_fd = STDERR_FILENO;
			_log_fd_isatty = (isatty(_log_fd) == 1 ? true : false);
			PLOG_E("Couldn't open logfile open('%s')", logfile.c_str());
		}
	}
	_log_fd_isatty = (isatty(_log_fd) == 1 ? true : false);
}

void logMsg(enum llevel_t ll, const char* fn, int ln, bool perr, const char* fmt, ...) {
	if (ll < _log_level) {
		return;
	}

	char strerr[512];
	if (perr) {
		snprintf(strerr, sizeof(strerr), "%s", strerror(errno));
	}
	struct ll_t {
		const char* const descr;
		const char* const prefix;
		const bool print_funcline;
		const bool print_time;
	};
	static struct ll_t const logLevels[] = {
	    {"D", "\033[0;4m", true, true},
	    {"I", "\033[1m", false, true},
	    {"W", "\033[0;33m", true, true},
	    {"E", "\033[1;31m", true, true},
	    {"F", "\033[7;35m", true, true},
	    {"HR", "\033[0m", false, false},
	    {"HB", "\033[1m", false, false},
	};

	/* Start printing logs */
	if (_log_fd_isatty) {
		dprintf(_log_fd, "%s", logLevels[ll].prefix);
	}
	if (logLevels[ll].print_time) {
		const auto timestr = util::timeToStr(time(NULL));
		dprintf(_log_fd, "[%s] ", timestr.c_str());
	}
	if (logLevels[ll].print_funcline) {
		dprintf(_log_fd, "[%s][%d] %s():%d ", logLevels[ll].descr, (int)getpid(), fn, ln);
	}

	va_list args;
	va_start(args, fmt);
	vdprintf(_log_fd, fmt, args);
	va_end(args);
	if (perr) {
		dprintf(_log_fd, ": %s", strerr);
	}
	if (_log_fd_isatty) {
		dprintf(_log_fd, "\033[0m");
	}
	dprintf(_log_fd, "\n");
	/* End printing logs */

	if (ll == FATAL) {
		exit(0xff);
	}
}

void logStop(int sig) {
	LOG_I("Server stops due to fatal signal (%d) caught. Exiting", sig);
}

}  // namespace logs
<commit_msg>logs: lower logfile error to warning<commit_after>/*

   nsjail - logging
   -----------------------------------------

   Copyright 2014 Google Inc. All Rights Reserved.

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

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

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

*/

#include "logs.h"

#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>

#include "macros.h"
#include "util.h"

#include <string.h>

namespace logs {

static int _log_fd = STDERR_FILENO;
static bool _log_fd_isatty = true;
static enum llevel_t _log_level = INFO;
static bool _log_set = false;

__attribute__((constructor)) static void log_init(void) {
	_log_fd_isatty = isatty(_log_fd);
}

bool logSet() {
  return _log_set;
}

/*
 * Log to stderr by default. Use a dup()d fd, because in the future we'll associate the
 * connection socket with fd (0, 1, 2).
 */

void logLevel(enum llevel_t ll) {
	_log_level = ll;
}

void logFile(const std::string& logfile) {
        _log_set = true;
	/* Close previous log_fd */
	if (_log_fd > STDERR_FILENO) {
		close(_log_fd);
		_log_fd = STDERR_FILENO;
	}
	if (logfile.empty()) {
		_log_fd = fcntl(_log_fd, F_DUPFD_CLOEXEC, 0);
	} else {
		if (TEMP_FAILURE_RETRY(_log_fd = open(logfile.c_str(),
					   O_CREAT | O_RDWR | O_APPEND | O_CLOEXEC, 0640)) == -1) {
			_log_fd = STDERR_FILENO;
			_log_fd_isatty = (isatty(_log_fd) == 1 ? true : false);
			PLOG_W("Couldn't open logfile open('%s')", logfile.c_str());
		}
	}
	_log_fd_isatty = (isatty(_log_fd) == 1);
}

void logMsg(enum llevel_t ll, const char* fn, int ln, bool perr, const char* fmt, ...) {
	if (ll < _log_level) {
		return;
	}

	char strerr[512];
	if (perr) {
		snprintf(strerr, sizeof(strerr), "%s", strerror(errno));
	}
	struct ll_t {
		const char* const descr;
		const char* const prefix;
		const bool print_funcline;
		const bool print_time;
	};
	static struct ll_t const logLevels[] = {
	    {"D", "\033[0;4m", true, true},
	    {"I", "\033[1m", false, true},
	    {"W", "\033[0;33m", true, true},
	    {"E", "\033[1;31m", true, true},
	    {"F", "\033[7;35m", true, true},
	    {"HR", "\033[0m", false, false},
	    {"HB", "\033[1m", false, false},
	};

	/* Start printing logs */
	if (_log_fd_isatty) {
		dprintf(_log_fd, "%s", logLevels[ll].prefix);
	}
	if (logLevels[ll].print_time) {
		const auto timestr = util::timeToStr(time(NULL));
		dprintf(_log_fd, "[%s] ", timestr.c_str());
	}
	if (logLevels[ll].print_funcline) {
		dprintf(_log_fd, "[%s][%d] %s():%d ", logLevels[ll].descr, (int)getpid(), fn, ln);
	}

	va_list args;
	va_start(args, fmt);
	vdprintf(_log_fd, fmt, args);
	va_end(args);
	if (perr) {
		dprintf(_log_fd, ": %s", strerr);
	}
	if (_log_fd_isatty) {
		dprintf(_log_fd, "\033[0m");
	}
	dprintf(_log_fd, "\n");
	/* End printing logs */

	if (ll == FATAL) {
		exit(0xff);
	}
}

void logStop(int sig) {
	LOG_I("Server stops due to fatal signal (%d) caught. Exiting", sig);
}

}  // namespace logs
<|endoftext|>