<commit_before>// vim settings:
// vim: et ts=2 sw=2
// Add support for OTA***************************************
#include <ArduinoOTA.h>
// **********************************************************
#include "Config.h"
#include "MicroUtil.h"
#include "types.h"
#include "OMIProcessing.h"
#include <ESP8266WiFi.h>
#include <Hash.h>
#include <stdlib.h>
#include <string.h>
#include "SoftwareSerial.h"

extern "C" {
#include "user_interface.h"
}

SoftwareSerial Son_off(PIN_SONOFF_RX,PIN_SONOFF_TX);

void reconnect();
bool modemConnect();
void sonoff(void);
void send_current_or_power(int value,char* whichdata);
TinyGsm modem(SerialAT);
TinyGsmClient client(modem);
DB database;

WebSocketsClient webSocket;

#define MESSAGE_INTERVAL 35000
#define HEARTBEAT_INTERVAL 28000
#define RESPONSE_BUFFER 5120

#define LidStatusName FString("LidStatus")

#define GetValueOfItem(name, object, value) \
                tmp = 0; tmpb = 0; \
                if (!(findInfoItem((object), (name), item, tmp) \
                            && findValue(item, (value), tmpb))) { \
                    D("[OMIreserve] Error: Cannot parse "); DS(name); \
                    continue; \
                }

class StringBuffer : public String {
public:
  StringBuffer() : String() {}
  inline StringBuffer & copy_cstr(const char *cstr, unsigned int length) {
    this->copy(cstr,length);
    return *this;
  }
};
const char* PoleSubscriptionRequest = "<omiEnvelope xmlns=\"http://www.opengroup.org/xsd/omi/1.0/\" version=\"1.0\" ttl=\"-1\"><read msgformat=\"odf\" interval=\"-1\" callback=\"0\"><msg><Objects xmlns=\"http://www.opengroup.org/xsd/odf/1.0/\"><Object><id>HWTEST</id><InfoItem name=\"LidStatus\"/></Object></Objects></msg></read></omiEnvelope>";

/*const char* PoleSubscriptionRequest =
  "<omiEnvelope xmlns=\"http://www.opengroup.org/xsd/omi/1.0/\" version=\"1.0\" ttl=\"-1\">"
   "<read msgformat=\"odf\" interval=\"-1\" callback=\"0\">"
     "<msg>"
       "<Objects xmlns=\"http://www.opengroup.org/xsd/odf/1.0/\">"
         "<Object>"
           "<id>ParkingService</id>"
           "<Object>"
             "<id>ParkingFacilities</id>"
             "<Object>"
               "<id>DipoliParkingLot</id>"
               "<Object>"
                 "<id>ParkingSpaceTypes</id>"
                 "<Object>"
                   "<id>ElectricVehicleParkingSpace</id>"
                   "<Object>"
                     "<id>Spaces</id>"
                     "<Object>"
                       "<id>EVSpace2</id>"
                       "<InfoItem name=\"Available\"/>"
                       "<Object>"
                         "<id>Charger</id>"
                         "<InfoItem name=\"LidStatus\"/>"
                       "</Object>"
                     "</Object>"
                   "</Object>"
                 "</Object>"
               "</Object>"
             "</Object>"
           "</Object>"
         "</Object>"
       "</Objects>"
     "</msg>"
   "</read>"
  "</omiEnvelope>" ;*/

uint64_t messageTimestamp = 0;
uint64_t heartbeatTimestamp = 0;
bool isConnected = false;
bool isSubscribed = false;
bool isXml = false;

//send power or current to server function.
bool send_flag=false;
void send_current_or_power(int value,char* whichdata){

String  str;
char *p;
String const currentdata2="</value></InfoItem></Object></Objects></msg></write></omiEnvelope>,";//you must add "," end of currentdata2 xml text to seperate xml text.
String  currentdata;
char currentdata1[]="15";
itoa(value, currentdata1, 10);

if(whichdata=="CURRENT"){

currentdata="<omiEnvelope xmlns=\"http://www.opengroup.org/xsd/omi/1.0/\" version=\"1.0\" ttl=\"-1\"><write msgformat=\"odf\"><msg><Objects xmlns=\"http://www.opengroup.org/xsd/odf/1.0/\"><Object><id>HWTEST</id><InfoItem name=\"Current\"> <value>";

}
else if(whichdata=="POWER"){

currentdata="<omiEnvelope xmlns=\"http://www.opengroup.org/xsd/omi/1.0/\" version=\"1.0\" ttl=\"-1\"><write msgformat=\"odf\"><msg><Objects xmlns=\"http://www.opengroup.org/xsd/odf/1.0/\"><Object><id>HWTEST</id><InfoItem name=\"Power\"> <value>";

}

str =currentdata+currentdata1+currentdata2;

	p = strtok(&str[0], ",");
send_flag=true;
if(value<15000){
webSocket.sendTXT(p);
}
send_flag=false;
}

StringBuffer responsePayload;

os_timer_t myTimer;
volatile unsigned int beat_index=0,sonoff_index=0;
bool tickOccured=true;
unsigned int data=0;
// start of timerCallback
void timerCallback(void *pArg) {
	ESP.wdtDisable();

if(isConnected&&isSubscribed){
	beat_index++;
	sonoff_index++;
	if(beat_index==6){
 //   digitalWrite(D0,!digitalRead(D0));
	DLN("Sending heartbeat");
    webSocket.sendTXT("");
    beat_index=0;
	}
else{

		if(tickOccured==true){
	data=(unsigned int)Son_off.get_data(3)*256+(unsigned int)Son_off.get_data(4);
	DLN("Sending current_data");
    send_current_or_power(data,"CURRENT");
	tickOccured=false;

}
else{
    data=(unsigned int)Son_off.get_data(1)*256+(unsigned int)Son_off.get_data(2);
	DLN("Sending power_data");

	send_current_or_power(data,"POWER");
	tickOccured=true;

}
}
}

 ESP.wdtEnable(WDTO_8S);

} // End of timerCallback

bool ota_flag=false;
/*void handleInterrupt() {
  digitalWrite(PIN_LOCK, !digitalRead(PIN_LOCK));     // Initialize the LED_BUILTIN pin as an output

}*/

void user_init(void) {

      os_timer_setfn(&myTimer, timerCallback, NULL);
      os_timer_arm(&myTimer, 5000, true);//set timer for every 5sec
} // End of user_init

void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {

if(ota_flag!=true){

    switch(type) {
        case WStype_DISCONNECTED:
            DFORMAT("[WSc] Disconnected!\n\r");
            isConnected = false;

           reconnect();
          digitalWrite(PIN_RUNNING, LOW);
            break;
        case WStype_CONNECTED:
            {
                DFORMAT("[WSc] Connected to url: %s\n\r",  payload);
                isConnected = true;

                DLN("Sending Subscription");
                isSubscribed = false;
                user_init();//timer config for sending power/current data

            }
            break;
        case WStype_TEXT:
            if (length > 0) {
              DFORMAT("[WSc] get text: %s\n\r", payload);
              isXml = true;
              responsePayload.copy_cstr((const char *) payload, length);

            }
            break;
        case WStype_BIN:
            DFORMAT("[WSc] get binary length: %u\n\r", length);
            hexdump(payload, length);

            // send data to server
            // webSocket.sendBIN(payload, length);
            break;
    }
}
}

void setup() {

 responsePayload.reserve(RESPONSE_BUFFER);
 noInterrupts();

  // Set console baud rate
  DEBUG_PORT.begin(115200);
  //SerialD;
  delay(10);

  // Set GSM module baud rate
  SerialAT.begin(115200);
  SerialAT.swap();
  delay(3000);
//sonooff serial
  Son_off.begin(9600);
  Son_off.enableRx(true);
   delay(10);
  // PINS
 pinMode(PIN_LOCK, OUTPUT);
  digitalWrite(PIN_LOCK, LOW);
  pinMode(PIN_GSM_PWR, OUTPUT);
  digitalWrite(PIN_GSM_PWR, LOW);

//Indicator and debug pins init
pinMode(PIN_RUNNING, OUTPUT);
digitalWrite(PIN_RUNNING, LOW);
pinMode(PIN_UPLOAD, OUTPUT);
digitalWrite(PIN_UPLOAD, LOW);
pinMode(PIN_SONOFF_COM, OUTPUT);
digitalWrite(PIN_SONOFF_COM, LOW);

 //OTA update config
  ArduinoOTA.onError([](ota_error_t error) { ESP.restart(); });
  ArduinoOTA.begin();  /* setup the OTA server */

  ArduinoOTA.onStart([]() {
  digitalWrite(PIN_UPLOAD, HIGH);
  });

  ArduinoOTA.onEnd([]() {
    digitalWrite(PIN_UPLOAD, LOW);
  });

   ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
     digitalWrite(PIN_UPLOAD, HIGH);
  });

  // BOOT GSM
  delay(50);
  D("PWR");
  digitalWrite(PIN_GSM_PWR, HIGH);
  D(".HIGH");
  delay(3200);
  D("DONE");
  digitalWrite(PIN_GSM_PWR, LOW);
  D(".LOW");
  delay(300);
  DLN(".INIT...");

interrupts();
  modem.init();
	yield();
  modemConnect();

  //  pinMode(D2, INPUT_PULLUP);
 // attachInterrupt(digitalPinToInterrupt(D2), handleInterrupt, RISING);
}

bool modemConnect() { // TODO: clean, move to websocket library?

  D("Waiting for network...");
  if (!modem.waitForNetwork()) {
    DLN(" fail, retry after 5 secs");
    delay(5000);
    return false;
  }
  DLN(" OK");

  D("Connecting to ");
  DSLN(apn);
  String ip;
  if (!modem.gprsConnect(apn, user, pass, ip)) {
    DLN(" fail, retry after 5 secs");
    delay(5000);
    return false;
  }
  D(" OK, Own IP address: ");
  DSLN(ip);

  // Commented: Connect instead in websocket library?
  D("Connecting to ");
  D(OMI_HOST);
  if (!client.connect(OMI_HOST, 80)) {
    DLN(" fail, retry after 5 secs");
    delay(5000);
    return false;
  }
  DLN(" CONNECT OK ");

  webSocket.onEvent(webSocketEvent);
  yield();
  webSocket.begin(&client, OMI_HOST, 80, OMI_PATH, "omi");
  yield();
  webSocket.connectedCb();
}

void reconnect(void){
  DLN("Initializing modem...");
  modem.init();
   digitalWrite(PIN_RUNNING, LOW);
  modemConnect();
    yield();
}

void loop() {

  // if not connected try to connect
  if (!client.connected()) {
    //if (!reconnect()) return;
    reconnect();

  }

  for (int wait = 0; wait < 15 && !isConnected; wait++) {
    DLN("Waiting for connection.");
    auto time = millis() + 5000;
    while (millis() < time && !isConnected) {
      webSocket.loop();
    }
    yield();
  }

  while (isConnected) {

 while(ota_flag==true&&send_flag==false){//is there OTA UPDATE?
  DLN("======OTA UPDATE==== ");
 //	noInterrupts();
 //   client.stop();
   // ESP.wdtDisable();
   // webSocket.disconnect();

    ArduinoOTA.handle();// Add support for OTA***************************************

    yield();
    //ESP.wdtEnable(WDTO_8S);
    }

if(ota_flag!=true){

   webSocket.loop();
      yield();

    yield();

   if (isXml) {

      isXml = false;
      String value;
      String item;
      unsigned tmp = 0, tmpb = 0;
      //GetValueOfItem(LidStatusName, responsePayload, value)
      if (findInfoItem(responsePayload, LidStatusName, item, tmp)) {
        if (findValue(item, value, tmpb)) {

          DFORMAT("Result: %s", value.c_str());

          // digitalWrite(PIN_LOCK, !digitalRead(PIN_LOCK));
		   if(value=="update"){//do we get update request from server?
		   		os_timer_disarm(&myTimer);
		   	ota_flag=true;
		   	char ip=WiFi.localIP();
		   	send_current_or_power(WiFi.localIP(),"POWER");
		   	// digitalWrite(PIN_LOCK, !digitalRead(PIN_LOCK));
        //	digitalWrite(PIN_LOCK, HIGH);
        //delay(2000);
        //digitalWrite(PIN_LOCK, LOW);

		}else{
		  digitalWrite(PIN_LOCK, HIGH);
          delay(2000);
          digitalWrite(PIN_LOCK, LOW);
		}
		/*else if(value=="open"){
		digitalWrite(PIN_LOCK, HIGH);
        delay(2000);
        digitalWrite(PIN_LOCK, LOW);

		}*/
        }

      }

    }

    //DFORMAT("RAM Memory left: %d\r\n", ESP.getFreeHeap());

 if (! isSubscribed) {

      webSocket.sendTXT(PoleSubscriptionRequest);
      isSubscribed = true; // TODO: Check response success
       digitalWrite(PIN_RUNNING, HIGH);
    }
}

  }

      yield();
}

<commit_msg>change subscription to point to CSParking EV1<commit_after>// vim settings:
// vim: et ts=2 sw=2
// Add support for OTA***************************************
#include <ArduinoOTA.h>
// **********************************************************
#include "Config.h"
#include "MicroUtil.h"
#include "types.h"
#include "OMIProcessing.h"
#include <ESP8266WiFi.h>
#include <Hash.h>
#include <stdlib.h>
#include <string.h>
#include "SoftwareSerial.h"

extern "C" {
#include "user_interface.h"
}

SoftwareSerial Son_off(PIN_SONOFF_RX,PIN_SONOFF_TX);

void reconnect();
bool modemConnect();
void sonoff(void);
void send_current_or_power(int value,char* whichdata);
TinyGsm modem(SerialAT);
TinyGsmClient client(modem);
DB database;

WebSocketsClient webSocket;

#define MESSAGE_INTERVAL 35000
#define HEARTBEAT_INTERVAL 28000
#define RESPONSE_BUFFER 5120

#define LidStatusName FString("LidStatus")

#define GetValueOfItem(name, object, value) \
                tmp = 0; tmpb = 0; \
                if (!(findInfoItem((object), (name), item, tmp) \
                            && findValue(item, (value), tmpb))) { \
                    D("[OMIreserve] Error: Cannot parse "); DS(name); \
                    continue; \
                }

class StringBuffer : public String {
public:
  StringBuffer() : String() {}
  inline StringBuffer & copy_cstr(const char *cstr, unsigned int length) {
    this->copy(cstr,length);
    return *this;
  }
};
//const char* PoleSubscriptionRequest = "<omiEnvelope xmlns=\"http://www.opengroup.org/xsd/omi/1.0/\" version=\"1.0\" ttl=\"-1\"><read msgformat=\"odf\" interval=\"-1\" callback=\"0\"><msg><Objects xmlns=\"http://www.opengroup.org/xsd/odf/1.0/\"><Object><id>HWTEST</id><InfoItem name=\"LidStatus\"/></Object></Objects></msg></read></omiEnvelope>";

const char* PoleSubscriptionRequest =
"<omiEnvelope xmlns=\"http://www.opengroup.org/xsd/omi/1.0/\" version=\"1.0\" ttl=\"0\">"
  "<read msgformat=\"odf\" interval=\"-1\" callback=\"0\">"
    "<msg>"
      "<Objects xmlns=\"http://www.opengroup.org/xsd/odf/1.0/\">"
        "<Object>"
          "<id>ParkingService</id>"
          "<Object>"
            "<id>ParkingFacilities</id>"
            "<Object>"
              "<id>CSBuildingParkingLot</id>"
              "<Object>"
                "<id>ParkingSpaceTypes</id>"
                "<Object>"
                  "<id>ElectricVehicleParkingSpace</id>"
                  "<Object>"
                    "<id>Spaces</id>"
                    "<Object>"
                      "<id>EVSpace1</id>"
                      "<Object>"
                        "<id>Charger</id>"
                        "<InfoItem name=\"LidStatus\"/>"
                      "</Object>"
                    "</Object>"
                  "</Object>"
                "</Object>"
              "</Object>"
            "</Object>"
          "</Object>"
        "</Object>"
      "</Objects>"
    "</msg>"
  "</read>"
"</omiEnvelope>";

uint64_t messageTimestamp = 0;
uint64_t heartbeatTimestamp = 0;
bool isConnected = false;
bool isSubscribed = false;
bool isXml = false;

//send power or current to server function.
bool send_flag=false;
void send_current_or_power(int value,char* whichdata){

String  str;
char *p;
String const currentdata2="</value></InfoItem></Object></Objects></msg></write></omiEnvelope>,";//you must add "," end of currentdata2 xml text to seperate xml text.
String  currentdata;
char currentdata1[]="15";
itoa(value, currentdata1, 10);

if(whichdata=="CURRENT"){

currentdata="<omiEnvelope xmlns=\"http://www.opengroup.org/xsd/omi/1.0/\" version=\"1.0\" ttl=\"-1\"><write msgformat=\"odf\"><msg><Objects xmlns=\"http://www.opengroup.org/xsd/odf/1.0/\"><Object><id>HWTEST</id><InfoItem name=\"Current\"> <value>";

}
else if(whichdata=="POWER"){

currentdata="<omiEnvelope xmlns=\"http://www.opengroup.org/xsd/omi/1.0/\" version=\"1.0\" ttl=\"-1\"><write msgformat=\"odf\"><msg><Objects xmlns=\"http://www.opengroup.org/xsd/odf/1.0/\"><Object><id>HWTEST</id><InfoItem name=\"Power\"> <value>";

}

str =currentdata+currentdata1+currentdata2;

	p = strtok(&str[0], ",");
send_flag=true;
if(value<15000){
webSocket.sendTXT(p);
}
send_flag=false;
}

StringBuffer responsePayload;

os_timer_t myTimer;
volatile unsigned int beat_index=0,sonoff_index=0;
bool tickOccured=true;
unsigned int data=0;
// start of timerCallback
void timerCallback(void *pArg) {
	ESP.wdtDisable();

if(isConnected&&isSubscribed){
	beat_index++;
	sonoff_index++;
	if(beat_index==6){
 //   digitalWrite(D0,!digitalRead(D0));
	DLN("Sending heartbeat");
    webSocket.sendTXT("");
    beat_index=0;
	}
else{

		if(tickOccured==true){
	data=(unsigned int)Son_off.get_data(3)*256+(unsigned int)Son_off.get_data(4);
	DLN("Sending current_data");
    send_current_or_power(data,"CURRENT");
	tickOccured=false;

}
else{
    data=(unsigned int)Son_off.get_data(1)*256+(unsigned int)Son_off.get_data(2);
	DLN("Sending power_data");

	send_current_or_power(data,"POWER");
	tickOccured=true;

}
}
}

 ESP.wdtEnable(WDTO_8S);

} // End of timerCallback

bool ota_flag=false;
/*void handleInterrupt() {
  digitalWrite(PIN_LOCK, !digitalRead(PIN_LOCK));     // Initialize the LED_BUILTIN pin as an output

}*/

void user_init(void) {

      os_timer_setfn(&myTimer, timerCallback, NULL);
      os_timer_arm(&myTimer, 5000, true);//set timer for every 5sec
} // End of user_init

void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {

if(ota_flag!=true){

    switch(type) {
        case WStype_DISCONNECTED:
            DFORMAT("[WSc] Disconnected!\n\r");
            isConnected = false;

           reconnect();
          digitalWrite(PIN_RUNNING, LOW);
            break;
        case WStype_CONNECTED:
            {
                DFORMAT("[WSc] Connected to url: %s\n\r",  payload);
                isConnected = true;

                DLN("Sending Subscription");
                isSubscribed = false;
                user_init();//timer config for sending power/current data

            }
            break;
        case WStype_TEXT:
            if (length > 0) {
              DFORMAT("[WSc] get text: %s\n\r", payload);
              isXml = true;
              responsePayload.copy_cstr((const char *) payload, length);

            }
            break;
        case WStype_BIN:
            DFORMAT("[WSc] get binary length: %u\n\r", length);
            hexdump(payload, length);

            // send data to server
            // webSocket.sendBIN(payload, length);
            break;
    }
}
}

void setup() {

 responsePayload.reserve(RESPONSE_BUFFER);
 noInterrupts();

  // Set console baud rate
  DEBUG_PORT.begin(115200);
  //SerialD;
  delay(10);

  // Set GSM module baud rate
  SerialAT.begin(115200);
  SerialAT.swap();
  delay(3000);
//sonooff serial
  Son_off.begin(9600);
  Son_off.enableRx(true);
   delay(10);
  // PINS
 pinMode(PIN_LOCK, OUTPUT);
  digitalWrite(PIN_LOCK, LOW);
  pinMode(PIN_GSM_PWR, OUTPUT);
  digitalWrite(PIN_GSM_PWR, LOW);

//Indicator and debug pins init
pinMode(PIN_RUNNING, OUTPUT);
digitalWrite(PIN_RUNNING, LOW);
pinMode(PIN_UPLOAD, OUTPUT);
digitalWrite(PIN_UPLOAD, LOW);
pinMode(PIN_SONOFF_COM, OUTPUT);
digitalWrite(PIN_SONOFF_COM, LOW);

 //OTA update config
  ArduinoOTA.onError([](ota_error_t error) { ESP.restart(); });
  ArduinoOTA.begin();  /* setup the OTA server */

  ArduinoOTA.onStart([]() {
  digitalWrite(PIN_UPLOAD, HIGH);
  });

  ArduinoOTA.onEnd([]() {
    digitalWrite(PIN_UPLOAD, LOW);
  });

   ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
     digitalWrite(PIN_UPLOAD, HIGH);
  });

  // BOOT GSM
  delay(50);
  D("PWR");
  digitalWrite(PIN_GSM_PWR, HIGH);
  D(".HIGH");
  delay(3200);
  D("DONE");
  digitalWrite(PIN_GSM_PWR, LOW);
  D(".LOW");
  delay(300);
  DLN(".INIT...");

interrupts();
  modem.init();
	yield();
  modemConnect();

  //  pinMode(D2, INPUT_PULLUP);
 // attachInterrupt(digitalPinToInterrupt(D2), handleInterrupt, RISING);
}

bool modemConnect() { // TODO: clean, move to websocket library?

  D("Waiting for network...");
  if (!modem.waitForNetwork()) {
    DLN(" fail, retry after 5 secs");
    delay(5000);
    return false;
  }
  DLN(" OK");

  D("Connecting to ");
  DSLN(apn);
  String ip;
  if (!modem.gprsConnect(apn, user, pass, ip)) {
    DLN(" fail, retry after 5 secs");
    delay(5000);
    return false;
  }
  D(" OK, Own IP address: ");
  DSLN(ip);

  // Commented: Connect instead in websocket library?
  D("Connecting to ");
  D(OMI_HOST);
  if (!client.connect(OMI_HOST, 80)) {
    DLN(" fail, retry after 5 secs");
    delay(5000);
    return false;
  }
  DLN(" CONNECT OK ");

  webSocket.onEvent(webSocketEvent);
  yield();
  webSocket.begin(&client, OMI_HOST, 80, OMI_PATH, "omi");
  yield();
  webSocket.connectedCb();
}

void reconnect(void){
  DLN("Initializing modem...");
  modem.init();
   digitalWrite(PIN_RUNNING, LOW);
  modemConnect();
    yield();
}

void loop() {

  // if not connected try to connect
  if (!client.connected()) {
    //if (!reconnect()) return;
    reconnect();

  }

  for (int wait = 0; wait < 15 && !isConnected; wait++) {
    DLN("Waiting for connection.");
    auto time = millis() + 5000;
    while (millis() < time && !isConnected) {
      webSocket.loop();
    }
    yield();
  }

  while (isConnected) {

 while(ota_flag==true&&send_flag==false){//is there OTA UPDATE?
  DLN("======OTA UPDATE==== ");
 //	noInterrupts();
 //   client.stop();
   // ESP.wdtDisable();
   // webSocket.disconnect();

    ArduinoOTA.handle();// Add support for OTA***************************************

    yield();
    //ESP.wdtEnable(WDTO_8S);
    }

if(ota_flag!=true){

   webSocket.loop();
      yield();

    yield();

   if (isXml) {

      isXml = false;
      String value;
      String item;
      unsigned tmp = 0, tmpb = 0;
      //GetValueOfItem(LidStatusName, responsePayload, value)
      if (findInfoItem(responsePayload, LidStatusName, item, tmp)) {
        if (findValue(item, value, tmpb)) {

          DFORMAT("Result: %s", value.c_str());

          // digitalWrite(PIN_LOCK, !digitalRead(PIN_LOCK));
		   if(value=="update"){//do we get update request from server?
		   		os_timer_disarm(&myTimer);
		   	ota_flag=true;
		   	char ip=WiFi.localIP();
		   	send_current_or_power(WiFi.localIP(),"POWER");
		   	// digitalWrite(PIN_LOCK, !digitalRead(PIN_LOCK));
        //	digitalWrite(PIN_LOCK, HIGH);
        //delay(2000);
        //digitalWrite(PIN_LOCK, LOW);

		}else{
		  digitalWrite(PIN_LOCK, HIGH);
          delay(2000);
          digitalWrite(PIN_LOCK, LOW);
		}
		/*else if(value=="open"){
		digitalWrite(PIN_LOCK, HIGH);
        delay(2000);
        digitalWrite(PIN_LOCK, LOW);

		}*/
        }

      }

    }

    //DFORMAT("RAM Memory left: %d\r\n", ESP.getFreeHeap());

 if (! isSubscribed) {

      webSocket.sendTXT(PoleSubscriptionRequest);
      isSubscribed = true; // TODO: Check response success
       digitalWrite(PIN_RUNNING, HIGH);
    }
}

  }

      yield();
}

<|endoftext|>


<commit_before>// Copyright (c) 2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <optional.h>
#include <streams.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>

#include <array>
#include <cstdint>
#include <iostream>
#include <optional>
#include <string>
#include <vector>

void test_one_input(const std::vector<uint8_t>& buffer)
{
    FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
    FuzzedFileProvider fuzzed_file_provider = ConsumeFile(fuzzed_data_provider);
    std::optional<CBufferedFile> opt_buffered_file;
    FILE* fuzzed_file = fuzzed_file_provider.open();
    try {
        opt_buffered_file.emplace(fuzzed_file, fuzzed_data_provider.ConsumeIntegralInRange<uint64_t>(0, 4096), fuzzed_data_provider.ConsumeIntegralInRange<uint64_t>(0, 4096), fuzzed_data_provider.ConsumeIntegral<int>(), fuzzed_data_provider.ConsumeIntegral<int>());
    } catch (const std::ios_base::failure&) {
        if (fuzzed_file != nullptr) {
            fclose(fuzzed_file);
        }
    }
    if (opt_buffered_file && fuzzed_file != nullptr) {
        while (fuzzed_data_provider.ConsumeBool()) {
            switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 4)) {
            case 0: {
                std::array<uint8_t, 4096> arr{};
                try {
                    opt_buffered_file->read((char*)arr.data(), fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096));
                } catch (const std::ios_base::failure&) {
                }
                break;
            }
            case 1: {
                opt_buffered_file->Seek(fuzzed_data_provider.ConsumeIntegralInRange<uint64_t>(0, 4096));
                break;
            }
            case 2: {
                opt_buffered_file->SetLimit(fuzzed_data_provider.ConsumeIntegralInRange<uint64_t>(0, 4096));
                break;
            }
            case 3: {
                try {
                    opt_buffered_file->FindByte(fuzzed_data_provider.ConsumeIntegral<char>());
                } catch (const std::ios_base::failure&) {
                }
                break;
            }
            case 4: {
                ReadFromStream(fuzzed_data_provider, *opt_buffered_file);
                break;
            }
            }
        }
    }
}
<commit_msg>tests: Add fuzzing harness for CBufferedFile::{SetPos,GetPos,GetType,GetVersion} (stream.h)<commit_after>// Copyright (c) 2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <optional.h>
#include <streams.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>

#include <array>
#include <cstdint>
#include <iostream>
#include <optional>
#include <string>
#include <vector>

void test_one_input(const std::vector<uint8_t>& buffer)
{
    FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
    FuzzedFileProvider fuzzed_file_provider = ConsumeFile(fuzzed_data_provider);
    std::optional<CBufferedFile> opt_buffered_file;
    FILE* fuzzed_file = fuzzed_file_provider.open();
    try {
        opt_buffered_file.emplace(fuzzed_file, fuzzed_data_provider.ConsumeIntegralInRange<uint64_t>(0, 4096), fuzzed_data_provider.ConsumeIntegralInRange<uint64_t>(0, 4096), fuzzed_data_provider.ConsumeIntegral<int>(), fuzzed_data_provider.ConsumeIntegral<int>());
    } catch (const std::ios_base::failure&) {
        if (fuzzed_file != nullptr) {
            fclose(fuzzed_file);
        }
    }
    if (opt_buffered_file && fuzzed_file != nullptr) {
        bool setpos_fail = false;
        while (fuzzed_data_provider.ConsumeBool()) {
            switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 5)) {
            case 0: {
                std::array<uint8_t, 4096> arr{};
                try {
                    opt_buffered_file->read((char*)arr.data(), fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096));
                } catch (const std::ios_base::failure&) {
                }
                break;
            }
            case 1: {
                opt_buffered_file->Seek(fuzzed_data_provider.ConsumeIntegralInRange<uint64_t>(0, 4096));
                break;
            }
            case 2: {
                opt_buffered_file->SetLimit(fuzzed_data_provider.ConsumeIntegralInRange<uint64_t>(0, 4096));
                break;
            }
            case 3: {
                if (!opt_buffered_file->SetPos(fuzzed_data_provider.ConsumeIntegralInRange<uint64_t>(0, 4096))) {
                    setpos_fail = true;
                }
                break;
            }
            case 4: {
                if (setpos_fail) {
                    // Calling FindByte(...) after a failed SetPos(...) call may result in an infinite loop.
                    break;
                }
                try {
                    opt_buffered_file->FindByte(fuzzed_data_provider.ConsumeIntegral<char>());
                } catch (const std::ios_base::failure&) {
                }
                break;
            }
            case 5: {
                ReadFromStream(fuzzed_data_provider, *opt_buffered_file);
                break;
            }
            }
        }
        opt_buffered_file->GetPos();
        opt_buffered_file->GetType();
        opt_buffered_file->GetVersion();
    }
}
<|endoftext|>


<commit_before>// @(#)root/eve:$Id$
// Author: Matevz Tadel

// Complex example showing ALICE VSD visualization.

/*
  alice_vsd.C - a simple event-display for ALICE

  ------------------------------------------------------------------------
  ------------------------------------------------------------------------

  Only standard ROOT is used to process the ALICE VSD files.

  No ALICE code is needed -- the VSD file is exported from AliRoot into
  VSD format -- see TEveVSDStructs.h and TEveVSD.h.

  A simple geometry of 10KB, extracted from the full TGeo-geometry, is
  used to outline the central detectors of ALICE.

  All files are access from the web by using the "CACHEREAD" option.

*/

#if defined(__CINT__) && !defined(__MAKECINT__)
{
   Info("alice_vsd.C", "Has to be run in compiled mode ... doing this for you.");
   gSystem->CompileMacro("alice_vsd.C");
   alice_vsd();
}
#else

#include <TEveManager.h>
#include <TEveEventManager.h>
#include <TEveVSD.h>
#include <TEveVSDStructs.h>

#include <TEveTrack.h>
#include <TEveTrackPropagator.h>
#include <TEveGeoShape.h>

#include <TGTab.h>
#include <TGButton.h>

#include <TFile.h>
#include <TKey.h>
#include <TSystem.h>
#include <TPRegexp.h>

// Include componets -- compile time link :)

#include "MultiView.C"
MultiView* gMultiView = 0;

class TVSDReader
{
public:
   // ----------------------------------------------------------
   // File / Event Data
   // ----------------------------------------------------------

   TFile      *fFile;
   TDirectory *fDirectory;

   TObjArray  *fEvDirKeys;

   TEveVSD    *fVSD;

   Int_t       fMaxEv, fCurEv;

   // ----------------------------------------------------------
   // Event visualization structures
   // ----------------------------------------------------------

   TEveTrackList *fTrackList;
   TEvePointSet  *fITSClusters;
   TEvePointSet  *fTPCClusters;
   TEvePointSet  *fTRDClusters;
   TEvePointSet  *fTOFClusters;

public:
   TVSDReader(const char* file_name) :
      fFile(0), fDirectory(0), fEvDirKeys(0),
      fVSD(0),

      fMaxEv(-1), fCurEv(-1),

      fTrackList(0),
      fITSClusters(0), fTPCClusters(0), fTRDClusters(0), fTOFClusters(0)
   {
      fFile = TFile::Open(file_name);
      if (!fFile)
      {
         Error("VSD_Reader", "Can not open file '%s' ... terminating.", file_name);
         gSystem->Exit(1);
      }

      fEvDirKeys = new TObjArray;
      TPMERegexp name_re("Event\\d+");
      TObjLink* lnk = fFile->GetListOfKeys()->FirstLink();
      while (lnk)
      {
         if (name_re.Match(lnk->GetObject()->GetName()))
         {
            fEvDirKeys->Add(lnk->GetObject());
         }
         lnk = lnk->Next();
      }

      fMaxEv = fEvDirKeys->GetEntriesFast();
      if (fMaxEv == 0)
      {
         Error("VSD_Reader", "No events to show ... terminating.");
         gSystem->Exit(1);
      }

      fVSD = new TEveVSD;
   }

   virtual ~TVSDReader()
   {
      // Destructor.

      DropEvent();

      delete fVSD;
      delete fEvDirKeys;

      fFile->Close();
      delete fFile;
   }

   void AttachEvent()
   {
      // Attach event data from current directory.

      fVSD->LoadTrees();
      fVSD->SetBranchAddresses();
   }

   void DropEvent()
   {
      // Drup currently held event data, release current directory.

      // Drop old visualization structures.

      gEve->GetViewers()->DeleteAnnotations();
      gEve->GetCurrentEvent()->DestroyElements();

      // Drop old event-data.

      fVSD->DeleteTrees();
      delete fDirectory;
      fDirectory = 0;
   }

   //---------------------------------------------------------------------------
   // Event navigation
   //---------------------------------------------------------------------------

   void NextEvent()
   {
      GotoEvent(fCurEv + 1);
   }

   void PrevEvent()
   {
      GotoEvent(fCurEv - 1);
   }

   Bool_t GotoEvent(Int_t ev)
   {
      if (ev < 0 || ev >= fMaxEv)
      {
         Warning("GotoEvent", "Invalid event id %d.", ev);
         return kFALSE;
      }

      DropEvent();

      // Connect to new event-data.

      fCurEv = ev;
      fDirectory = (TDirectory*) ((TKey*) fEvDirKeys->At(fCurEv))->ReadObj();
      fVSD->SetDirectory(fDirectory);

      AttachEvent();

      // Load event data into visualization structures.

      LoadClusters(fITSClusters, "ITS", 0);
      LoadClusters(fTPCClusters, "TPC", 1);
      LoadClusters(fTRDClusters, "TRD", 2);
      LoadClusters(fTOFClusters, "TOF", 3);

      LoadEsdTracks();

      // Fill projected views.

      TEveElement* top = gEve->GetCurrentEvent();

      gMultiView->DestroyEventRPhi();
      gMultiView->ImportEventRPhi(top);

      gMultiView->DestroyEventRhoZ();
      gMultiView->ImportEventRhoZ(top);

      gEve->Redraw3D(kFALSE, kTRUE);

      return kTRUE;
   }

   //---------------------------------------------------------------------------
   // Cluster loading
   //---------------------------------------------------------------------------

   void LoadClusters(TEvePointSet*& ps, const TString& det_name, Int_t det_id)
   {
      if (ps == 0)
      {
         ps = new TEvePointSet(det_name);
         ps->SetMainColor((Color_t)(det_id + 2));
         ps->SetMarkerSize(0.5);
         ps->SetMarkerStyle(2);
         ps->IncDenyDestroy();
      }
      else
      {
         ps->Reset();
      }

      TEvePointSelector ss(fVSD->fTreeC, ps, "fV.fX:fV.fY:fV.fZ",
                           TString::Format("fDetId==%d", det_id));
      ss.Select();
      ps->SetTitle(TString::Format("N=%d", ps->Size()));

      gEve->AddElement(ps);
   }

   //---------------------------------------------------------------------------
   // Track loading
   //---------------------------------------------------------------------------

   enum ESDTrackFlags
   {
      kITSin=0x0001,kITSout=0x0002,kITSrefit=0x0004,kITSpid=0x0008,
      kTPCin=0x0010,kTPCout=0x0020,kTPCrefit=0x0040,kTPCpid=0x0080,
      kTRDin=0x0100,kTRDout=0x0200,kTRDrefit=0x0400,kTRDpid=0x0800,
      kTOFin=0x1000,kTOFout=0x2000,kTOFrefit=0x4000,kTOFpid=0x8000,
      kHMPIDpid=0x20000,
      kEMCALmatch=0x40000,
      kTRDbackup=0x80000,
      kTRDStop=0x20000000,
      kESDpid=0x40000000,
      kTIME=0x80000000
   };

   Bool_t trackIsOn(TEveTrack* t, Int_t mask)
   {
      // Check is track-flag specified by mask are set.

      return (t->fStatus & mask) > 0;
   }

   void LoadEsdTracks()
   {
      // Read reconstructed tracks from current event.

      if (fTrackList == 0)
      {
         fTrackList = new TEveTrackList("ESD Tracks");
         fTrackList->SetMainColor(6);
         fTrackList->SetMarkerColor(kYellow);
         fTrackList->SetMarkerStyle(4);
         fTrackList->SetMarkerSize(0.5);

         fTrackList->IncDenyDestroy();
      }
      else
      {
         fTrackList->DestroyElements();
      }

      TEveTrackPropagator* trkProp = fTrackList->GetPropagator();
      // !!!! Need to store field on file !!!!
      // Can store TEveMagField ?
      trkProp->SetMagField(0.5);

      Int_t nTracks = fVSD->fTreeR->GetEntries();
      for (Int_t n = 0; n < nTracks; ++n)
      {
         fVSD->fTreeR->GetEntry(n);

         TEveTrack* track = new TEveTrack(&fVSD->fR, trkProp);
         track->SetName(Form("ESD Track %d", fVSD->fR.fIndex));
         track->SetStdTitle();
         track->SetAttLineAttMarker(fTrackList);
         fTrackList->AddElement(track);
      }

      fTrackList->MakeTracks();

      gEve->AddElement(fTrackList);
   }

   ClassDef(TVSDReader, 0);
};

TVSDReader* gVSDReader = 0;

// Forward declaration.
void make_gui();

//______________________________________________________________________________
void alice_vsd(const char* vsd_file_name = "http://mtadel.home.cern.ch/mtadel/root/AliVSD.root")
{
   // Main function, initializes the application.
   //
   // 1. Load the auto-generated library holding ESD classes and ESD dictionaries.
   // 2. Open ESD data-files.
   // 3. Load cartoon geometry.
   // 4. Spawn simple GUI.
   // 5. Load first event.

   TFile::SetCacheFileDir(".");

   TEveVSD::DisableTObjectStreamersForVSDStruct();

   gVSDReader = new TVSDReader(vsd_file_name);

   TEveManager::Create();

   TEveGeoShape *gentle_geom = 0;

   { // Simple geometry
      TFile* geom = TFile::Open("http://mtadel.home.cern.ch/mtadel/root/alice_mini_geom.root", "CACHEREAD");
      if (!geom)
         return;
      TEveGeoShapeExtract* gse = (TEveGeoShapeExtract*) geom->Get("Gentle");
      gentle_geom = TEveGeoShape::ImportShapeExtract(gse, 0);
      geom->Close();
      delete geom;
      gEve->AddGlobalElement(gentle_geom);
   }

   // Standard multi-view
   //=====================

   gMultiView = new MultiView;
   gMultiView->f3DView->GetGLViewer()->SetStyle(TGLRnrCtx::kOutline);

   gMultiView->SetDepth(-10);
   gMultiView->ImportGeomRPhi(gentle_geom);
   gMultiView->ImportGeomRhoZ(gentle_geom);
   gMultiView->SetDepth(0);

   // Final stuff
   //=============

   gEve->GetViewers()->SwitchColorSet();
   gEve->GetDefaultGLViewer()->SetStyle(TGLRnrCtx::kOutline);

   gEve->GetBrowser()->GetTabRight()->SetTab(1);

   make_gui();

   gEve->AddEvent(new TEveEventManager("Event", "ALICE VSD Event"));

   gVSDReader->GotoEvent(0);

   gEve->Redraw3D(kTRUE); // Reset camera after the first event has been shown.
}

//______________________________________________________________________________
void make_gui()
{
   // Create minimal GUI for event navigation.

   TEveBrowser* browser = gEve->GetBrowser();
   browser->StartEmbedding(TRootBrowser::kLeft);

   TGMainFrame* frmMain = new TGMainFrame(gClient->GetRoot(), 1000, 600);
   frmMain->SetWindowName("XX GUI");
   frmMain->SetCleanup(kDeepCleanup);

   TGHorizontalFrame* hf = new TGHorizontalFrame(frmMain);
   {
      TString icondir(TString::Format("%s/icons/", gSystem->Getenv("ROOTSYS")) );
      TGPictureButton* b = 0;

      b = new TGPictureButton(hf, gClient->GetPicture(icondir + "GoBack.gif"));
      hf->AddFrame(b);
      b->Connect("Clicked()", "TVSDReader", gVSDReader, "PrevEvent()");

      b = new TGPictureButton(hf, gClient->GetPicture(icondir + "GoForward.gif"));
      hf->AddFrame(b);
      b->Connect("Clicked()", "TVSDReader", gVSDReader, "NextEvent()");
   }
   frmMain->AddFrame(hf);

   frmMain->MapSubwindows();
   frmMain->Resize();
   frmMain->MapWindow();

   browser->StopEmbedding();
   browser->SetTabTitle("Event Control", 0);
}

#endif
<commit_msg>From Bertrand: fix to run in compiled mode on windows.<commit_after>// @(#)root/eve:$Id$
// Author: Matevz Tadel

// Complex example showing ALICE VSD visualization.

/*
  alice_vsd.C - a simple event-display for ALICE

  ------------------------------------------------------------------------
  ------------------------------------------------------------------------

  Only standard ROOT is used to process the ALICE VSD files.

  No ALICE code is needed -- the VSD file is exported from AliRoot into
  VSD format -- see TEveVSDStructs.h and TEveVSD.h.

  A simple geometry of 10KB, extracted from the full TGeo-geometry, is
  used to outline the central detectors of ALICE.

  All files are access from the web by using the "CACHEREAD" option.

*/

#if defined(__CINT__) && !defined(__MAKECINT__)
{
   Info("alice_vsd.C", "Has to be run in compiled mode ... doing this for you.");
   gSystem->CompileMacro("alice_vsd.C");
   alice_vsd();
}
#else

#include <TEveManager.h>
#include <TEveEventManager.h>
#include <TEveVSD.h>
#include <TEveVSDStructs.h>

#include <TEveTrack.h>
#include <TEveTrackPropagator.h>
#include <TEveGeoShape.h>

#include <TGTab.h>
#include <TGButton.h>

#include <TFile.h>
#include <TKey.h>
#include <TSystem.h>
#include <TPRegexp.h>

// Include componets -- compile time link :)

#include "MultiView.C"
MultiView* gMultiView = 0;

class TVSDReader
{
public:
   // ----------------------------------------------------------
   // File / Event Data
   // ----------------------------------------------------------

   TFile      *fFile;
   TDirectory *fDirectory;

   TObjArray  *fEvDirKeys;

   TEveVSD    *fVSD;

   Int_t       fMaxEv, fCurEv;

   // ----------------------------------------------------------
   // Event visualization structures
   // ----------------------------------------------------------

   TEveTrackList *fTrackList;
   TEvePointSet  *fITSClusters;
   TEvePointSet  *fTPCClusters;
   TEvePointSet  *fTRDClusters;
   TEvePointSet  *fTOFClusters;

public:
   TVSDReader(const char* file_name) :
      fFile(0), fDirectory(0), fEvDirKeys(0),
      fVSD(0),

      fMaxEv(-1), fCurEv(-1),

      fTrackList(0),
      fITSClusters(0), fTPCClusters(0), fTRDClusters(0), fTOFClusters(0)
   {
      fFile = TFile::Open(file_name);
      if (!fFile)
      {
         Error("VSD_Reader", "Can not open file '%s' ... terminating.", file_name);
         gSystem->Exit(1);
      }

      fEvDirKeys = new TObjArray;
      TPMERegexp name_re("Event\\d+");
      TObjLink* lnk = fFile->GetListOfKeys()->FirstLink();
      while (lnk)
      {
         if (name_re.Match(lnk->GetObject()->GetName()))
         {
            fEvDirKeys->Add(lnk->GetObject());
         }
         lnk = lnk->Next();
      }

      fMaxEv = fEvDirKeys->GetEntriesFast();
      if (fMaxEv == 0)
      {
         Error("VSD_Reader", "No events to show ... terminating.");
         gSystem->Exit(1);
      }

      fVSD = new TEveVSD;
   }

   virtual ~TVSDReader()
   {
      // Destructor.

      DropEvent();

      delete fVSD;
      delete fEvDirKeys;

      fFile->Close();
      delete fFile;
   }

   void AttachEvent()
   {
      // Attach event data from current directory.

      fVSD->LoadTrees();
      fVSD->SetBranchAddresses();
   }

   void DropEvent()
   {
      // Drup currently held event data, release current directory.

      // Drop old visualization structures.

      gEve->GetViewers()->DeleteAnnotations();
      gEve->GetCurrentEvent()->DestroyElements();

      // Drop old event-data.

      fVSD->DeleteTrees();
      delete fDirectory;
      fDirectory = 0;
   }

   //---------------------------------------------------------------------------
   // Event navigation
   //---------------------------------------------------------------------------

   void NextEvent()
   {
      GotoEvent(fCurEv + 1);
   }

   void PrevEvent()
   {
      GotoEvent(fCurEv - 1);
   }

   Bool_t GotoEvent(Int_t ev)
   {
      if (ev < 0 || ev >= fMaxEv)
      {
         Warning("GotoEvent", "Invalid event id %d.", ev);
         return kFALSE;
      }

      DropEvent();

      // Connect to new event-data.

      fCurEv = ev;
      fDirectory = (TDirectory*) ((TKey*) fEvDirKeys->At(fCurEv))->ReadObj();
      fVSD->SetDirectory(fDirectory);

      AttachEvent();

      // Load event data into visualization structures.

      LoadClusters(fITSClusters, "ITS", 0);
      LoadClusters(fTPCClusters, "TPC", 1);
      LoadClusters(fTRDClusters, "TRD", 2);
      LoadClusters(fTOFClusters, "TOF", 3);

      LoadEsdTracks();

      // Fill projected views.

      TEveElement* top = gEve->GetCurrentEvent();

      gMultiView->DestroyEventRPhi();
      gMultiView->ImportEventRPhi(top);

      gMultiView->DestroyEventRhoZ();
      gMultiView->ImportEventRhoZ(top);

      gEve->Redraw3D(kFALSE, kTRUE);

      return kTRUE;
   }

   //---------------------------------------------------------------------------
   // Cluster loading
   //---------------------------------------------------------------------------

   void LoadClusters(TEvePointSet*& ps, const TString& det_name, Int_t det_id)
   {
      if (ps == 0)
      {
         ps = new TEvePointSet(det_name);
         ps->SetMainColor((Color_t)(det_id + 2));
         ps->SetMarkerSize(0.5);
         ps->SetMarkerStyle(2);
         ps->IncDenyDestroy();
      }
      else
      {
         ps->Reset();
      }

      TEvePointSelector ss(fVSD->fTreeC, ps, "fV.fX:fV.fY:fV.fZ",
                           TString::Format("fDetId==%d", det_id));
      ss.Select();
      ps->SetTitle(TString::Format("N=%d", ps->Size()));

      gEve->AddElement(ps);
   }

   //---------------------------------------------------------------------------
   // Track loading
   //---------------------------------------------------------------------------

   enum ESDTrackFlags
   {
      kITSin=0x0001,kITSout=0x0002,kITSrefit=0x0004,kITSpid=0x0008,
      kTPCin=0x0010,kTPCout=0x0020,kTPCrefit=0x0040,kTPCpid=0x0080,
      kTRDin=0x0100,kTRDout=0x0200,kTRDrefit=0x0400,kTRDpid=0x0800,
      kTOFin=0x1000,kTOFout=0x2000,kTOFrefit=0x4000,kTOFpid=0x8000,
      kHMPIDpid=0x20000,
      kEMCALmatch=0x40000,
      kTRDbackup=0x80000,
      kTRDStop=0x20000000,
      kESDpid=0x40000000,
      kTIME=0x80000000
   };

   Bool_t trackIsOn(TEveTrack* t, Int_t mask)
   {
      // Check is track-flag specified by mask are set.

      return (t->GetStatus() & mask) > 0;
   }

   void LoadEsdTracks()
   {
      // Read reconstructed tracks from current event.

      if (fTrackList == 0)
      {
         fTrackList = new TEveTrackList("ESD Tracks");
         fTrackList->SetMainColor(6);
         fTrackList->SetMarkerColor(kYellow);
         fTrackList->SetMarkerStyle(4);
         fTrackList->SetMarkerSize(0.5);

         fTrackList->IncDenyDestroy();
      }
      else
      {
         fTrackList->DestroyElements();
      }

      TEveTrackPropagator* trkProp = fTrackList->GetPropagator();
      // !!!! Need to store field on file !!!!
      // Can store TEveMagField ?
      trkProp->SetMagField(0.5);

      Int_t nTracks = fVSD->fTreeR->GetEntries();
      for (Int_t n = 0; n < nTracks; ++n)
      {
         fVSD->fTreeR->GetEntry(n);

         TEveTrack* track = new TEveTrack(&fVSD->fR, trkProp);
         track->SetName(Form("ESD Track %d", fVSD->fR.fIndex));
         track->SetStdTitle();
         track->SetAttLineAttMarker(fTrackList);
         fTrackList->AddElement(track);
      }

      fTrackList->MakeTracks();

      gEve->AddElement(fTrackList);
   }

   ClassDef(TVSDReader, 0);
};

TVSDReader* gVSDReader = 0;

// Forward declaration.
void make_gui();

//______________________________________________________________________________
void alice_vsd(const char* vsd_file_name = "http://mtadel.home.cern.ch/mtadel/root/AliVSD.root")
{
   // Main function, initializes the application.
   //
   // 1. Load the auto-generated library holding ESD classes and ESD dictionaries.
   // 2. Open ESD data-files.
   // 3. Load cartoon geometry.
   // 4. Spawn simple GUI.
   // 5. Load first event.

   TFile::SetCacheFileDir(".");

   TEveVSD::DisableTObjectStreamersForVSDStruct();

   gVSDReader = new TVSDReader(vsd_file_name);

   TEveManager::Create();

   TEveGeoShape *gentle_geom = 0;

   { // Simple geometry
      TFile* geom = TFile::Open("http://mtadel.home.cern.ch/mtadel/root/alice_mini_geom.root", "CACHEREAD");
      if (!geom)
         return;
      TEveGeoShapeExtract* gse = (TEveGeoShapeExtract*) geom->Get("Gentle");
      gentle_geom = TEveGeoShape::ImportShapeExtract(gse, 0);
      geom->Close();
      delete geom;
      gEve->AddGlobalElement(gentle_geom);
   }

   // Standard multi-view
   //=====================

   gMultiView = new MultiView;
   gMultiView->f3DView->GetGLViewer()->SetStyle(TGLRnrCtx::kOutline);

   gMultiView->SetDepth(-10);
   gMultiView->ImportGeomRPhi(gentle_geom);
   gMultiView->ImportGeomRhoZ(gentle_geom);
   gMultiView->SetDepth(0);

   // Final stuff
   //=============

   gEve->GetViewers()->SwitchColorSet();
   gEve->GetDefaultGLViewer()->SetStyle(TGLRnrCtx::kOutline);

   gEve->GetBrowser()->GetTabRight()->SetTab(1);

   make_gui();

   gEve->AddEvent(new TEveEventManager("Event", "ALICE VSD Event"));

   gVSDReader->GotoEvent(0);

   gEve->Redraw3D(kTRUE); // Reset camera after the first event has been shown.
}

//______________________________________________________________________________
void make_gui()
{
   // Create minimal GUI for event navigation.

   TEveBrowser* browser = gEve->GetBrowser();
   browser->StartEmbedding(TRootBrowser::kLeft);

   TGMainFrame* frmMain = new TGMainFrame(gClient->GetRoot(), 1000, 600);
   frmMain->SetWindowName("XX GUI");
   frmMain->SetCleanup(kDeepCleanup);

   TGHorizontalFrame* hf = new TGHorizontalFrame(frmMain);
   {
      TString icondir(TString::Format("%s/icons/", gSystem->Getenv("ROOTSYS")) );
      TGPictureButton* b = 0;

      b = new TGPictureButton(hf, gClient->GetPicture(icondir + "GoBack.gif"));
      hf->AddFrame(b);
      b->Connect("Clicked()", "TVSDReader", gVSDReader, "PrevEvent()");

      b = new TGPictureButton(hf, gClient->GetPicture(icondir + "GoForward.gif"));
      hf->AddFrame(b);
      b->Connect("Clicked()", "TVSDReader", gVSDReader, "NextEvent()");
   }
   frmMain->AddFrame(hf);

   frmMain->MapSubwindows();
   frmMain->Resize();
   frmMain->MapWindow();

   browser->StopEmbedding();
   browser->SetTabTitle("Event Control", 0);
}

#endif
<|endoftext|>


<commit_before>#include <cstdio>

#include <io/Inet4Address.hpp>
#include <io/Resolv.hpp>
#include <io/ServerSocket.hpp>
#include <io/Socket.hpp>
#include <io/StringWriter.hpp>
#include <io/binary/StreamGetter.hpp>

#include <json/Json.hpp>

#include <log/LogManager.hpp>

#include <mercury/Mercury.hpp>

#include <os/Condition.hpp>

#include <sys/wait.h>

#include <errno.h>
#include <signal.h>
#include <unistd.h>

using namespace logger ;
using namespace std ;
using namespace io ;
using namespace os ;
using namespace json ;

byte mercury_magic_cookie[32] = {
    0xe2, 0x1a, 0x14, 0xc8, 0xa2, 0x35, 0x0a, 0x92,
    0xaf, 0x1a, 0xff, 0xd6, 0x35, 0x2b, 0xa4, 0xf3,
    0x97, 0x79, 0xaf, 0xb5, 0xc1, 0x23, 0x43, 0xf0,
    0xf7, 0x14, 0x17, 0x62, 0x53, 0x4a, 0xa9, 0x7e,
};

class MercuryConfig {
public:
    MercuryConfig(): logEverything(false) {}
    bool logEverything;
};

template<>
struct JsonBasicConvert<MercuryConfig> {
    static MercuryConfig convert(const json::Json& jsn) {
        MercuryConfig ret;
        ret.logEverything = jsn.hasAttribute("logEverything") && jsn["logEverything"] != 0;
        return ret;
    }
};

void sigchld_hdlr(int sig) {
}

int startMercury(LogContext& m_log) {
    StreamServerSocket sock;
    Inet4Address bind_addr("0.0.0.0", 8639);

    m_log.printfln(INFO, "Binding to address: %s", bind_addr.toString().c_str());
    sock.bind(bind_addr);
    sock.listen(1);

    while(true) {
        StreamSocket* client = sock.accept();
        m_log.printfln(INFO, "Connection accepted");

        /* simply get 64 bytes from the client and
         * then close the connection */
        byte recieve[64];
        client->read(recieve, sizeof(recieve));
        delete client;

        /* make sure the cookie is equal to what we expect */
        if(std::equal(recieve, recieve + 32, mercury_magic_cookie)) {
            /* the cookie is equal to what we expect
             * so continue with the fork() */
            m_log.printfln(INFO, "Magic cookie accepted, forking new process");
            pid_t child;
            if(!(child = fork())) {
                /* Child process. Setup the config and boot
                 * the merucry state machine */
                mercury::Config conf;
                std::copy(recieve + 32, recieve + 64, conf.mercury_id);
                mercury::Proxy& process = mercury::ProxyHolder::instance();

                /* start mercury */
                process.start(conf, NULL);
            } else {
                /* parent */
                m_log.printfln(INFO, "Child started pid=%d", child);
                int res = 0;
                pid_t pid;

                /* Wait for the child to exit */
                if((pid = waitpid(child, &res, 0))) {
                    if(pid == -1) {
                        m_log.printfln(ERROR, "Error in waitpid %s", strerror(errno));
                    } else {
                        m_log.printfln(INFO, "Reap child (%d)\n", (int)pid);
                    }
                }

                if( WEXITSTATUS(res) ) {
                    m_log.printfln(WARN, "Child returned abnormal status: %d", WEXITSTATUS(res));
                }
            }
        } else {
            m_log.printfln(ERROR, "Bad magic cookie received. Timeout for 5 seconds");
            sleep(5);
            m_log.printfln(INFO, "Timeout complete");
        }
    }

    return 0;
}

int main( int argc, char** argv ) {
    (void) argc ; (void) argv ;

    MercuryConfig conf;
    signal(SIGCHLD, sigchld_hdlr);

    try {
        Json* jsn = Json::fromFile("config.json");
        conf = jsn->convert<MercuryConfig>();
    } catch(Exception& exp) {
        fprintf(stderr, "Unable to load config file: %s", exp.getMessage());
    };

    if(conf.logEverything) {
        LogManager::instance().logEverything();
    }

    LogContext& m_log = LogManager::instance().getLogContext("Main", "Main");
    m_log.printfln(INFO, "Mercury started");
    try {
        return startMercury(m_log);
    } catch(Exception& exp) {
        m_log.printfln(FATAL, "Uncaught exception: %s", exp.getMessage());
        return 127;
    }
}
<commit_msg>add newline to errormsg<commit_after>#include <cstdio>

#include <io/Inet4Address.hpp>
#include <io/Resolv.hpp>
#include <io/ServerSocket.hpp>
#include <io/Socket.hpp>
#include <io/StringWriter.hpp>
#include <io/binary/StreamGetter.hpp>

#include <json/Json.hpp>

#include <log/LogManager.hpp>

#include <mercury/Mercury.hpp>

#include <os/Condition.hpp>

#include <sys/wait.h>

#include <errno.h>
#include <signal.h>
#include <unistd.h>

using namespace logger ;
using namespace std ;
using namespace io ;
using namespace os ;
using namespace json ;

byte mercury_magic_cookie[32] = {
    0xe2, 0x1a, 0x14, 0xc8, 0xa2, 0x35, 0x0a, 0x92,
    0xaf, 0x1a, 0xff, 0xd6, 0x35, 0x2b, 0xa4, 0xf3,
    0x97, 0x79, 0xaf, 0xb5, 0xc1, 0x23, 0x43, 0xf0,
    0xf7, 0x14, 0x17, 0x62, 0x53, 0x4a, 0xa9, 0x7e,
};

class MercuryConfig {
public:
    MercuryConfig(): logEverything(false) {}
    bool logEverything;
};

template<>
struct JsonBasicConvert<MercuryConfig> {
    static MercuryConfig convert(const json::Json& jsn) {
        MercuryConfig ret;
        ret.logEverything = jsn.hasAttribute("logEverything") && jsn["logEverything"] != 0;
        return ret;
    }
};

void sigchld_hdlr(int sig) {
}

int startMercury(LogContext& m_log) {
    StreamServerSocket sock;
    Inet4Address bind_addr("0.0.0.0", 8639);

    m_log.printfln(INFO, "Binding to address: %s", bind_addr.toString().c_str());
    sock.bind(bind_addr);
    sock.listen(1);

    while(true) {
        StreamSocket* client = sock.accept();
        m_log.printfln(INFO, "Connection accepted");

        /* simply get 64 bytes from the client and
         * then close the connection */
        byte recieve[64];
        client->read(recieve, sizeof(recieve));
        delete client;

        /* make sure the cookie is equal to what we expect */
        if(std::equal(recieve, recieve + 32, mercury_magic_cookie)) {
            /* the cookie is equal to what we expect
             * so continue with the fork() */
            m_log.printfln(INFO, "Magic cookie accepted, forking new process");
            pid_t child;
            if(!(child = fork())) {
                /* Child process. Setup the config and boot
                 * the merucry state machine */
                mercury::Config conf;
                std::copy(recieve + 32, recieve + 64, conf.mercury_id);
                mercury::Proxy& process = mercury::ProxyHolder::instance();

                /* start mercury */
                process.start(conf, NULL);
            } else {
                /* parent */
                m_log.printfln(INFO, "Child started pid=%d", child);
                int res = 0;
                pid_t pid;

                /* Wait for the child to exit */
                if((pid = waitpid(child, &res, 0))) {
                    if(pid == -1) {
                        m_log.printfln(ERROR, "Error in waitpid %s", strerror(errno));
                    } else {
                        m_log.printfln(INFO, "Reap child (%d)\n", (int)pid);
                    }
                }

                if( WEXITSTATUS(res) ) {
                    m_log.printfln(WARN, "Child returned abnormal status: %d", WEXITSTATUS(res));
                }
            }
        } else {
            m_log.printfln(ERROR, "Bad magic cookie received. Timeout for 5 seconds");
            sleep(5);
            m_log.printfln(INFO, "Timeout complete");
        }
    }

    return 0;
}

int main( int argc, char** argv ) {
    (void) argc ; (void) argv ;

    MercuryConfig conf;
    signal(SIGCHLD, sigchld_hdlr);

    try {
        Json* jsn = Json::fromFile("config.json");
        conf = jsn->convert<MercuryConfig>();
    } catch(Exception& exp) {
        fprintf(stderr, "Unable to load config file: %s\n", exp.getMessage());
    };

    if(conf.logEverything) {
        LogManager::instance().logEverything();
    }

    LogContext& m_log = LogManager::instance().getLogContext("Main", "Main");
    m_log.printfln(INFO, "Mercury started");
    try {
        return startMercury(m_log);
    } catch(Exception& exp) {
        m_log.printfln(FATAL, "Uncaught exception: %s", exp.getMessage());
        return 127;
    }
}
<|endoftext|>


<commit_before>/*
    Copyright 2010 Google Inc.

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

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

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

#include "GrBufferAllocPool.h"
#include "GrTypes.h"
#include "GrVertexBuffer.h"
#include "GrIndexBuffer.h"
#include "GrGpu.h"

#if GR_DEBUG
    #define VALIDATE validate
#else
    #define VALIDATE()
#endif

#define GrBufferAllocPool_MIN_BLOCK_SIZE ((size_t)1 << 12)

GrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu,
                                     BufferType bufferType,
                                     bool frequentResetHint,
                                     size_t blockSize,
                                     int preallocBufferCnt) :
        fBlocks(GrMax(8, 2*preallocBufferCnt)) {

    GrAssert(NULL != gpu);
    fGpu = gpu;
    fGpu->ref();
    fGpuIsReffed = true;

    fBufferType = bufferType;
    fFrequentResetHint = frequentResetHint;
    fBufferPtr = NULL;
    fMinBlockSize = GrMax(GrBufferAllocPool_MIN_BLOCK_SIZE, blockSize);

    fPreallocBuffersInUse = 0;
    fFirstPreallocBuffer = 0;
    for (int i = 0; i < preallocBufferCnt; ++i) {
        GrGeometryBuffer* buffer = this->createBuffer(fMinBlockSize);
        if (NULL != buffer) {
            *fPreallocBuffers.append() = buffer;
            buffer->ref();
        }
    }
}

GrBufferAllocPool::~GrBufferAllocPool() {
    VALIDATE();
    if (fBlocks.count()) {
        GrGeometryBuffer* buffer = fBlocks.back().fBuffer;
        if (buffer->isLocked()) {
            buffer->unlock();
        }
    }
    while (!fBlocks.empty()) {
        destroyBlock();
    }
    fPreallocBuffers.unrefAll();
    releaseGpuRef();
}

void GrBufferAllocPool::releaseGpuRef() {
    if (fGpuIsReffed) {
        fGpu->unref();
        fGpuIsReffed = false;
    }
}

void GrBufferAllocPool::reset() {
    VALIDATE();
    if (fBlocks.count()) {
        GrGeometryBuffer* buffer = fBlocks.back().fBuffer;
        if (buffer->isLocked()) {
            buffer->unlock();
        }
    }
    while (!fBlocks.empty()) {
        destroyBlock();
    }
    if (fPreallocBuffers.count()) {
        // must set this after above loop.
        fFirstPreallocBuffer = (fFirstPreallocBuffer + fPreallocBuffersInUse) %
                               fPreallocBuffers.count();
    }
    fCpuData.realloc(fGpu->supportsBufferLocking() ? 0 : fMinBlockSize);
    GrAssert(0 == fPreallocBuffersInUse);
    VALIDATE();
}

void GrBufferAllocPool::unlock() {
    VALIDATE();

    if (NULL != fBufferPtr) {
        BufferBlock& block = fBlocks.back();
        if (block.fBuffer->isLocked()) {
            block.fBuffer->unlock();
        } else {
            size_t flushSize = block.fBuffer->size() - block.fBytesFree;
            flushCpuData(fBlocks.back().fBuffer, flushSize);
        }
        fBufferPtr = NULL;
    }
    VALIDATE();
}

#if GR_DEBUG
void GrBufferAllocPool::validate() const {
    if (NULL != fBufferPtr) {
        GrAssert(!fBlocks.empty());
        if (fBlocks.back().fBuffer->isLocked()) {
            GrGeometryBuffer* buf = fBlocks.back().fBuffer;
            GrAssert(buf->lockPtr() == fBufferPtr);
        } else {
            GrAssert(fCpuData.get() == fBufferPtr);
            GrAssert(fCpuData.size() == fBlocks.back().fBuffer->size());
        }
    } else {
        GrAssert(fBlocks.empty() || !fBlocks.back().fBuffer->isLocked());
    }
    for (int i = 0; i < fBlocks.count() - 1; ++i) {
        GrAssert(!fBlocks[i].fBuffer->isLocked());
    }
}
#endif

void* GrBufferAllocPool::makeSpace(size_t size,
                                   size_t alignment,
                                   const GrGeometryBuffer** buffer,
                                   size_t* offset) {
    VALIDATE();

    GrAssert(NULL != buffer);
    GrAssert(NULL != offset);

    if (NULL != fBufferPtr) {
        BufferBlock& back = fBlocks.back();
        size_t usedBytes = back.fBuffer->size() - back.fBytesFree;
        size_t pad = GrSizeAlignUpPad(usedBytes,
                                      alignment);
        if ((size + pad) <= back.fBytesFree) {
            usedBytes += pad;
            *offset = usedBytes;
            *buffer = back.fBuffer;
            back.fBytesFree -= size + pad;
            return (void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes);
        }
    }

    if (!createBlock(size)) {
        return NULL;
    }
    VALIDATE();
    GrAssert(NULL != fBufferPtr);

    *offset = 0;
    BufferBlock& back = fBlocks.back();
    *buffer = back.fBuffer;
    back.fBytesFree -= size;
    return fBufferPtr;
}

int GrBufferAllocPool::currentBufferItems(size_t itemSize) const {
    VALIDATE();
    if (NULL != fBufferPtr) {
        const BufferBlock& back = fBlocks.back();
        size_t usedBytes = back.fBuffer->size() - back.fBytesFree;
        size_t pad = GrSizeAlignUpPad(usedBytes, itemSize);
        return (back.fBytesFree - pad) / itemSize;
    } else if (fPreallocBuffersInUse < fPreallocBuffers.count()) {
        return fMinBlockSize / itemSize;
    }
    return 0;
}

int GrBufferAllocPool::preallocatedBuffersRemaining() const {
    return fPreallocBuffers.count() - fPreallocBuffersInUse;
}

int GrBufferAllocPool::preallocatedBufferCount() const {
    return fPreallocBuffers.count();
}

void GrBufferAllocPool::putBack(size_t bytes) {
    VALIDATE();
    if (NULL != fBufferPtr) {
        BufferBlock& back = fBlocks.back();
        size_t bytesUsed = back.fBuffer->size() - back.fBytesFree;
        if (bytes >= bytesUsed) {
            destroyBlock();
            bytes -= bytesUsed;
        } else {
            back.fBytesFree += bytes;
            return;
        }
    }
    VALIDATE();
    GrAssert(NULL == fBufferPtr);
    // we don't partially roll-back buffers because our VB semantics say locking
    // a VB discards its previous content.
    // We could honor it by being sure we use updateSubData and not lock
    // we will roll-back fully released buffers, though.
    while (!fBlocks.empty() &&
           bytes >= fBlocks.back().fBuffer->size()) {
        bytes -= fBlocks.back().fBuffer->size();
        destroyBlock();
    }
    VALIDATE();
}

bool GrBufferAllocPool::createBlock(size_t requestSize) {

    size_t size = GrMax(requestSize, fMinBlockSize);
    GrAssert(size >= GrBufferAllocPool_MIN_BLOCK_SIZE);

    VALIDATE();

    BufferBlock& block = fBlocks.push_back();

    if (size == fMinBlockSize &&
        fPreallocBuffersInUse < fPreallocBuffers.count()) {

        uint32_t nextBuffer = (fPreallocBuffersInUse + fFirstPreallocBuffer) %
                               fPreallocBuffers.count();
        block.fBuffer = fPreallocBuffers[nextBuffer];
        block.fBuffer->ref();
        ++fPreallocBuffersInUse;
    } else {
        block.fBuffer = this->createBuffer(size);
        if (NULL == block.fBuffer) {
            fBlocks.pop_back();
            return false;
        }
    }

    block.fBytesFree = size;
    if (NULL != fBufferPtr) {
        GrAssert(fBlocks.count() > 1);
        BufferBlock& prev = fBlocks.fromBack(1);
        if (prev.fBuffer->isLocked()) {
            prev.fBuffer->unlock();
        } else {
            flushCpuData(prev.fBuffer,
                         prev.fBuffer->size() - prev.fBytesFree);
        }
        fBufferPtr = NULL;
    }

    GrAssert(NULL == fBufferPtr);

    if (fGpu->supportsBufferLocking() &&
        size > GR_GEOM_BUFFER_LOCK_THRESHOLD &&
        (!fFrequentResetHint || requestSize > GR_GEOM_BUFFER_LOCK_THRESHOLD)) {
        fBufferPtr = block.fBuffer->lock();
    }

    if (NULL == fBufferPtr) {
        fBufferPtr = fCpuData.realloc(size);
    }

    VALIDATE();

    return true;
}

void GrBufferAllocPool::destroyBlock() {
    GrAssert(!fBlocks.empty());

    BufferBlock& block = fBlocks.back();
    if (fPreallocBuffersInUse > 0) {
        uint32_t prevPreallocBuffer = (fPreallocBuffersInUse +
                                       fFirstPreallocBuffer +
                                       (fPreallocBuffers.count() - 1)) %
                                      fPreallocBuffers.count();
        if (block.fBuffer == fPreallocBuffers[prevPreallocBuffer]) {
            --fPreallocBuffersInUse;
        }
    }
    GrAssert(!block.fBuffer->isLocked());
    block.fBuffer->unref();
    fBlocks.pop_back();
    fBufferPtr = NULL;
}

void GrBufferAllocPool::flushCpuData(GrGeometryBuffer* buffer,
                                     size_t flushSize) {
    GrAssert(NULL != buffer);
    GrAssert(!buffer->isLocked());
    GrAssert(fCpuData.get() == fBufferPtr);
    GrAssert(fCpuData.size() == buffer->size());
    GrAssert(flushSize <= buffer->size());

    bool updated = false;
    if (fGpu->supportsBufferLocking() &&
        flushSize > GR_GEOM_BUFFER_LOCK_THRESHOLD) {
        void* data = buffer->lock();
        if (NULL != data) {
            memcpy(data, fBufferPtr, flushSize);
            buffer->unlock();
            updated = true;
        }
    }
    buffer->updateData(fBufferPtr, flushSize);
}

GrGeometryBuffer* GrBufferAllocPool::createBuffer(size_t size) {
    if (kIndex_BufferType == fBufferType) {
        return fGpu->createIndexBuffer(size, true);
    } else {
        GrAssert(kVertex_BufferType == fBufferType);
        return fGpu->createVertexBuffer(size, true);
    }
}

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

GrVertexBufferAllocPool::GrVertexBufferAllocPool(GrGpu* gpu,
                                                 bool frequentResetHint,
                                                 size_t bufferSize,
                                                 int preallocBufferCnt)
: GrBufferAllocPool(gpu,
                    kVertex_BufferType,
                    frequentResetHint,
                    bufferSize,
                    preallocBufferCnt) {
}

void* GrVertexBufferAllocPool::makeSpace(GrVertexLayout layout,
                                         int vertexCount,
                                         const GrVertexBuffer** buffer,
                                         int* startVertex) {

    GrAssert(vertexCount >= 0);
    GrAssert(NULL != buffer);
    GrAssert(NULL != startVertex);

    size_t vSize = GrDrawTarget::VertexSize(layout);
    size_t offset;
    const GrGeometryBuffer* geomBuffer;
    void* ptr = INHERITED::makeSpace(vSize * vertexCount,
                                     vSize,
                                     &geomBuffer,
                                     &offset);

    *buffer = (const GrVertexBuffer*) geomBuffer;
    GrAssert(0 == offset % vSize);
    *startVertex = offset / vSize;
    return ptr;
}

bool GrVertexBufferAllocPool::appendVertices(GrVertexLayout layout,
                                             int vertexCount,
                                             const void* vertices,
                                             const GrVertexBuffer** buffer,
                                             int* startVertex) {
    void* space = makeSpace(layout, vertexCount, buffer, startVertex);
    if (NULL != space) {
        memcpy(space,
               vertices,
               GrDrawTarget::VertexSize(layout) * vertexCount);
        return true;
    } else {
        return false;
    }
}

int GrVertexBufferAllocPool::preallocatedBufferVertices(GrVertexLayout layout) const {
    return INHERITED::preallocatedBufferSize() /
            GrDrawTarget::VertexSize(layout);
}

int GrVertexBufferAllocPool::currentBufferVertices(GrVertexLayout layout) const {
    return currentBufferItems(GrDrawTarget::VertexSize(layout));
}

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

GrIndexBufferAllocPool::GrIndexBufferAllocPool(GrGpu* gpu,
                                               bool frequentResetHint,
                                               size_t bufferSize,
                                               int preallocBufferCnt)
: GrBufferAllocPool(gpu,
                    kIndex_BufferType,
                    frequentResetHint,
                    bufferSize,
                    preallocBufferCnt) {
}

void* GrIndexBufferAllocPool::makeSpace(int indexCount,
                                        const GrIndexBuffer** buffer,
                                        int* startIndex) {

    GrAssert(indexCount >= 0);
    GrAssert(NULL != buffer);
    GrAssert(NULL != startIndex);

    size_t offset;
    const GrGeometryBuffer* geomBuffer;
    void* ptr = INHERITED::makeSpace(indexCount * sizeof(uint16_t),
                                     sizeof(uint16_t),
                                     &geomBuffer,
                                     &offset);

    *buffer = (const GrIndexBuffer*) geomBuffer;
    GrAssert(0 == offset % sizeof(uint16_t));
    *startIndex = offset / sizeof(uint16_t);
    return ptr;
}

bool GrIndexBufferAllocPool::appendIndices(int indexCount,
                                           const void* indices,
                                           const GrIndexBuffer** buffer,
                                           int* startIndex) {
    void* space = makeSpace(indexCount, buffer, startIndex);
    if (NULL != space) {
        memcpy(space, indices, sizeof(uint16_t) * indexCount);
        return true;
    } else {
        return false;
    }
}

int GrIndexBufferAllocPool::preallocatedBufferIndices() const {
    return INHERITED::preallocatedBufferSize() / sizeof(uint16_t);
}

int GrIndexBufferAllocPool::currentBufferIndices() const {
    return currentBufferItems(sizeof(uint16_t));
}
<commit_msg>Suppress warnings in GrBufferAllocPool<commit_after>/*
    Copyright 2010 Google Inc.

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

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

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

#include "GrBufferAllocPool.h"
#include "GrTypes.h"
#include "GrVertexBuffer.h"
#include "GrIndexBuffer.h"
#include "GrGpu.h"

#if GR_DEBUG
    #define VALIDATE validate
#else
    #define VALIDATE()
#endif

#define GrBufferAllocPool_MIN_BLOCK_SIZE ((size_t)1 << 12)

GrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu,
                                     BufferType bufferType,
                                     bool frequentResetHint,
                                     size_t blockSize,
                                     int preallocBufferCnt) :
        fBlocks(GrMax(8, 2*preallocBufferCnt)) {

    GrAssert(NULL != gpu);
    fGpu = gpu;
    fGpu->ref();
    fGpuIsReffed = true;

    fBufferType = bufferType;
    fFrequentResetHint = frequentResetHint;
    fBufferPtr = NULL;
    fMinBlockSize = GrMax(GrBufferAllocPool_MIN_BLOCK_SIZE, blockSize);

    fPreallocBuffersInUse = 0;
    fFirstPreallocBuffer = 0;
    for (int i = 0; i < preallocBufferCnt; ++i) {
        GrGeometryBuffer* buffer = this->createBuffer(fMinBlockSize);
        if (NULL != buffer) {
            *fPreallocBuffers.append() = buffer;
            buffer->ref();
        }
    }
}

GrBufferAllocPool::~GrBufferAllocPool() {
    VALIDATE();
    if (fBlocks.count()) {
        GrGeometryBuffer* buffer = fBlocks.back().fBuffer;
        if (buffer->isLocked()) {
            buffer->unlock();
        }
    }
    while (!fBlocks.empty()) {
        destroyBlock();
    }
    fPreallocBuffers.unrefAll();
    releaseGpuRef();
}

void GrBufferAllocPool::releaseGpuRef() {
    if (fGpuIsReffed) {
        fGpu->unref();
        fGpuIsReffed = false;
    }
}

void GrBufferAllocPool::reset() {
    VALIDATE();
    if (fBlocks.count()) {
        GrGeometryBuffer* buffer = fBlocks.back().fBuffer;
        if (buffer->isLocked()) {
            buffer->unlock();
        }
    }
    while (!fBlocks.empty()) {
        destroyBlock();
    }
    if (fPreallocBuffers.count()) {
        // must set this after above loop.
        fFirstPreallocBuffer = (fFirstPreallocBuffer + fPreallocBuffersInUse) %
                               fPreallocBuffers.count();
    }
    fCpuData.realloc(fGpu->supportsBufferLocking() ? 0 : fMinBlockSize);
    GrAssert(0 == fPreallocBuffersInUse);
    VALIDATE();
}

void GrBufferAllocPool::unlock() {
    VALIDATE();

    if (NULL != fBufferPtr) {
        BufferBlock& block = fBlocks.back();
        if (block.fBuffer->isLocked()) {
            block.fBuffer->unlock();
        } else {
            size_t flushSize = block.fBuffer->size() - block.fBytesFree;
            flushCpuData(fBlocks.back().fBuffer, flushSize);
        }
        fBufferPtr = NULL;
    }
    VALIDATE();
}

#if GR_DEBUG
void GrBufferAllocPool::validate() const {
    if (NULL != fBufferPtr) {
        GrAssert(!fBlocks.empty());
        if (fBlocks.back().fBuffer->isLocked()) {
            GrGeometryBuffer* buf = fBlocks.back().fBuffer;
            GrAssert(buf->lockPtr() == fBufferPtr);
        } else {
            GrAssert(fCpuData.get() == fBufferPtr);
            GrAssert(fCpuData.size() == fBlocks.back().fBuffer->size());
        }
    } else {
        GrAssert(fBlocks.empty() || !fBlocks.back().fBuffer->isLocked());
    }
    for (int i = 0; i < fBlocks.count() - 1; ++i) {
        GrAssert(!fBlocks[i].fBuffer->isLocked());
    }
}
#endif

void* GrBufferAllocPool::makeSpace(size_t size,
                                   size_t alignment,
                                   const GrGeometryBuffer** buffer,
                                   size_t* offset) {
    VALIDATE();

    GrAssert(NULL != buffer);
    GrAssert(NULL != offset);

    if (NULL != fBufferPtr) {
        BufferBlock& back = fBlocks.back();
        size_t usedBytes = back.fBuffer->size() - back.fBytesFree;
        size_t pad = GrSizeAlignUpPad(usedBytes,
                                      alignment);
        if ((size + pad) <= back.fBytesFree) {
            usedBytes += pad;
            *offset = usedBytes;
            *buffer = back.fBuffer;
            back.fBytesFree -= size + pad;
            return (void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes);
        }
    }

    if (!createBlock(size)) {
        return NULL;
    }
    VALIDATE();
    GrAssert(NULL != fBufferPtr);

    *offset = 0;
    BufferBlock& back = fBlocks.back();
    *buffer = back.fBuffer;
    back.fBytesFree -= size;
    return fBufferPtr;
}

int GrBufferAllocPool::currentBufferItems(size_t itemSize) const {
    VALIDATE();
    if (NULL != fBufferPtr) {
        const BufferBlock& back = fBlocks.back();
        size_t usedBytes = back.fBuffer->size() - back.fBytesFree;
        size_t pad = GrSizeAlignUpPad(usedBytes, itemSize);
        return (back.fBytesFree - pad) / itemSize;
    } else if (fPreallocBuffersInUse < fPreallocBuffers.count()) {
        return fMinBlockSize / itemSize;
    }
    return 0;
}

int GrBufferAllocPool::preallocatedBuffersRemaining() const {
    return fPreallocBuffers.count() - fPreallocBuffersInUse;
}

int GrBufferAllocPool::preallocatedBufferCount() const {
    return fPreallocBuffers.count();
}

void GrBufferAllocPool::putBack(size_t bytes) {
    VALIDATE();
    if (NULL != fBufferPtr) {
        BufferBlock& back = fBlocks.back();
        size_t bytesUsed = back.fBuffer->size() - back.fBytesFree;
        if (bytes >= bytesUsed) {
            destroyBlock();
            bytes -= bytesUsed;
        } else {
            back.fBytesFree += bytes;
            return;
        }
    }
    VALIDATE();
    GrAssert(NULL == fBufferPtr);
    // we don't partially roll-back buffers because our VB semantics say locking
    // a VB discards its previous content.
    // We could honor it by being sure we use updateSubData and not lock
    // we will roll-back fully released buffers, though.
    while (!fBlocks.empty() &&
           bytes >= fBlocks.back().fBuffer->size()) {
        bytes -= fBlocks.back().fBuffer->size();
        destroyBlock();
    }
    VALIDATE();
}

bool GrBufferAllocPool::createBlock(size_t requestSize) {

    size_t size = GrMax(requestSize, fMinBlockSize);
    GrAssert(size >= GrBufferAllocPool_MIN_BLOCK_SIZE);

    VALIDATE();

    BufferBlock& block = fBlocks.push_back();

    if (size == fMinBlockSize &&
        fPreallocBuffersInUse < fPreallocBuffers.count()) {

        uint32_t nextBuffer = (fPreallocBuffersInUse + fFirstPreallocBuffer) %
                               fPreallocBuffers.count();
        block.fBuffer = fPreallocBuffers[nextBuffer];
        block.fBuffer->ref();
        ++fPreallocBuffersInUse;
    } else {
        block.fBuffer = this->createBuffer(size);
        if (NULL == block.fBuffer) {
            fBlocks.pop_back();
            return false;
        }
    }

    block.fBytesFree = size;
    if (NULL != fBufferPtr) {
        GrAssert(fBlocks.count() > 1);
        BufferBlock& prev = fBlocks.fromBack(1);
        if (prev.fBuffer->isLocked()) {
            prev.fBuffer->unlock();
        } else {
            flushCpuData(prev.fBuffer,
                         prev.fBuffer->size() - prev.fBytesFree);
        }
        fBufferPtr = NULL;
    }

    GrAssert(NULL == fBufferPtr);

    if (fGpu->supportsBufferLocking() &&
        size > GR_GEOM_BUFFER_LOCK_THRESHOLD &&
        (!fFrequentResetHint || requestSize > GR_GEOM_BUFFER_LOCK_THRESHOLD)) {
        fBufferPtr = block.fBuffer->lock();
    }

    if (NULL == fBufferPtr) {
        fBufferPtr = fCpuData.realloc(size);
    }

    VALIDATE();

    return true;
}

void GrBufferAllocPool::destroyBlock() {
    GrAssert(!fBlocks.empty());

    BufferBlock& block = fBlocks.back();
    if (fPreallocBuffersInUse > 0) {
        uint32_t prevPreallocBuffer = (fPreallocBuffersInUse +
                                       fFirstPreallocBuffer +
                                       (fPreallocBuffers.count() - 1)) %
                                      fPreallocBuffers.count();
        if (block.fBuffer == fPreallocBuffers[prevPreallocBuffer]) {
            --fPreallocBuffersInUse;
        }
    }
    GrAssert(!block.fBuffer->isLocked());
    block.fBuffer->unref();
    fBlocks.pop_back();
    fBufferPtr = NULL;
}

void GrBufferAllocPool::flushCpuData(GrGeometryBuffer* buffer,
                                     size_t flushSize) {
    GrAssert(NULL != buffer);
    GrAssert(!buffer->isLocked());
    GrAssert(fCpuData.get() == fBufferPtr);
    GrAssert(fCpuData.size() == buffer->size());
    GrAssert(flushSize <= buffer->size());

    bool updated = false;
    if (fGpu->supportsBufferLocking() &&
        flushSize > GR_GEOM_BUFFER_LOCK_THRESHOLD) {
        void* data = buffer->lock();
        if (NULL != data) {
            memcpy(data, fBufferPtr, flushSize);
            buffer->unlock();
            updated = true;
        }
    }
    buffer->updateData(fBufferPtr, flushSize);
}

GrGeometryBuffer* GrBufferAllocPool::createBuffer(size_t size) {
    if (kIndex_BufferType == fBufferType) {
        return fGpu->createIndexBuffer(size, true);
    } else {
        GrAssert(kVertex_BufferType == fBufferType);
        return fGpu->createVertexBuffer(size, true);
    }
}

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

GrVertexBufferAllocPool::GrVertexBufferAllocPool(GrGpu* gpu,
                                                 bool frequentResetHint,
                                                 size_t bufferSize,
                                                 int preallocBufferCnt)
: GrBufferAllocPool(gpu,
                    kVertex_BufferType,
                    frequentResetHint,
                    bufferSize,
                    preallocBufferCnt) {
}

void* GrVertexBufferAllocPool::makeSpace(GrVertexLayout layout,
                                         int vertexCount,
                                         const GrVertexBuffer** buffer,
                                         int* startVertex) {

    GrAssert(vertexCount >= 0);
    GrAssert(NULL != buffer);
    GrAssert(NULL != startVertex);

    size_t vSize = GrDrawTarget::VertexSize(layout);
    size_t offset = 0; // assign to suppress warning
    const GrGeometryBuffer* geomBuffer = NULL; // assign to suppress warning
    void* ptr = INHERITED::makeSpace(vSize * vertexCount,
                                     vSize,
                                     &geomBuffer,
                                     &offset);

    *buffer = (const GrVertexBuffer*) geomBuffer;
    GrAssert(0 == offset % vSize);
    *startVertex = offset / vSize;
    return ptr;
}

bool GrVertexBufferAllocPool::appendVertices(GrVertexLayout layout,
                                             int vertexCount,
                                             const void* vertices,
                                             const GrVertexBuffer** buffer,
                                             int* startVertex) {
    void* space = makeSpace(layout, vertexCount, buffer, startVertex);
    if (NULL != space) {
        memcpy(space,
               vertices,
               GrDrawTarget::VertexSize(layout) * vertexCount);
        return true;
    } else {
        return false;
    }
}

int GrVertexBufferAllocPool::preallocatedBufferVertices(GrVertexLayout layout) const {
    return INHERITED::preallocatedBufferSize() /
            GrDrawTarget::VertexSize(layout);
}

int GrVertexBufferAllocPool::currentBufferVertices(GrVertexLayout layout) const {
    return currentBufferItems(GrDrawTarget::VertexSize(layout));
}

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

GrIndexBufferAllocPool::GrIndexBufferAllocPool(GrGpu* gpu,
                                               bool frequentResetHint,
                                               size_t bufferSize,
                                               int preallocBufferCnt)
: GrBufferAllocPool(gpu,
                    kIndex_BufferType,
                    frequentResetHint,
                    bufferSize,
                    preallocBufferCnt) {
}

void* GrIndexBufferAllocPool::makeSpace(int indexCount,
                                        const GrIndexBuffer** buffer,
                                        int* startIndex) {

    GrAssert(indexCount >= 0);
    GrAssert(NULL != buffer);
    GrAssert(NULL != startIndex);

    size_t offset = 0; // assign to suppress warning
    const GrGeometryBuffer* geomBuffer = NULL; // assign to suppress warning
    void* ptr = INHERITED::makeSpace(indexCount * sizeof(uint16_t),
                                     sizeof(uint16_t),
                                     &geomBuffer,
                                     &offset);

    *buffer = (const GrIndexBuffer*) geomBuffer;
    GrAssert(0 == offset % sizeof(uint16_t));
    *startIndex = offset / sizeof(uint16_t);
    return ptr;
}

bool GrIndexBufferAllocPool::appendIndices(int indexCount,
                                           const void* indices,
                                           const GrIndexBuffer** buffer,
                                           int* startIndex) {
    void* space = makeSpace(indexCount, buffer, startIndex);
    if (NULL != space) {
        memcpy(space, indices, sizeof(uint16_t) * indexCount);
        return true;
    } else {
        return false;
    }
}

int GrIndexBufferAllocPool::preallocatedBufferIndices() const {
    return INHERITED::preallocatedBufferSize() / sizeof(uint16_t);
}

int GrIndexBufferAllocPool::currentBufferIndices() const {
    return currentBufferItems(sizeof(uint16_t));
}
<|endoftext|>


<commit_before>#ifndef K3_RUNTIME_COMMON_H
#define K3_RUNTIME_COMMON_H

#include <cstdint>
#include <list>
#include <vector>
#include <map>
#include <memory>
#include <sstream>
#include <string>
#include <functional>
#include <stdexcept>
#include <tuple>
#include <utility>
#include <boost/algorithm/string.hpp>
#include <boost/any.hpp>
#include <boost/asio.hpp>
#include <boost/log/core.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/sources/severity_channel_logger.hpp>
#include <boost/log/sources/severity_feature.hpp>
#include <boost/log/trivial.hpp>
#include <boost/regex.hpp>

namespace K3 {

  using std::shared_ptr;
  using std::make_shared;
  using std::string;
  using std::tuple;
  using std::make_tuple;

  // String implementation
  class base_string;
  typedef K3::base_string string_impl;
  template <class r> using F = std::function<r>;
  typedef std::string Identifier;
  typedef int TriggerId;
  typedef std::string Value;

  typedef std::string Value;
  typedef std::string EValue;
  typedef std::string IValue;

  typedef uint32_t fixed_int;

  typedef std::tuple<boost::asio::ip::address, unsigned short> Address;

  enum class Builtin { Stdin, Stdout, Stderr };
  enum class IOMode  { Read, Write, Append, ReadWrite };

  //---------------
  // Addresses.

  inline Address make_address(const std::string& host, unsigned short port)   {
    return Address(boost::asio::ip::address::from_string(host), port);
  }

  inline Address make_address(const char* host, unsigned short port) {
    return Address(boost::asio::ip::address::from_string(host), port);
  }

  static inline Address make_address(const std::string&& host, unsigned short port)  {
    return Address(boost::asio::ip::address::from_string(host), port);
  }

  inline std::string addressHost(const Address& addr) { return std::get<0>(addr).to_string(); }
  inline std::string addressHost(Address&& addr) { return std::get<0>(std::forward<Address>(addr)).to_string(); }

  inline int addressPort(const Address& addr) { return std::get<1>(addr); }
  inline int addressPort(Address&& addr) { return std::get<1>(std::forward<Address>(addr)); }

  inline std::string addressAsString(const Address& addr) {
    return addressHost(addr) + ":" + std::to_string(addressPort(addr));
  }

  inline std::string addressAsString(Address&& addr) {
    return addressHost(std::forward<Address>(addr))
            + ":" + std::to_string(addressPort(std::forward<Address>(addr)));
  }

  inline Address internalSendAddress(const Address& addr) {
    return make_address(addressHost(addr), addressPort(addr)+1);
  }

  inline Address internalSendAddress(Address&& addr) {
    return make_address(addressHost(std::forward<Address>(addr)),
                        addressPort(std::forward<Address>(addr))+1);
  }

  inline Address externalSendAddress(const Address& addr) {
    return make_address(addressHost(addr), addressPort(addr)+2);
  }

  inline Address externalSendAddress(Address&& addr) {
    return make_address(addressHost(std::forward<Address>(addr)),
                        addressPort(std::forward<Address>(addr))+2);
  }

  // TODO put the definition somewhere
  static Address defaultAddress = make_address("127.0.0.1", 40000);

  //--------------------
  // System environment.

  // Literals are native values rather than an AST reprensentation as in Haskell.
  typedef boost::any Literal;
  typedef std::map<Identifier, Literal> PeerBootstrap;
  typedef std::map<Address, PeerBootstrap> SystemEnvironment;

  static inline SystemEnvironment defaultEnvironment(Address addr) {
    PeerBootstrap bootstrap = PeerBootstrap();
    SystemEnvironment s_env = SystemEnvironment();
    s_env[addr] = bootstrap;
    return s_env;
  }

  inline SystemEnvironment defaultEnvironment(std::list<Address> addrs) {
    SystemEnvironment s_env;
    for (Address addr : addrs) {
      PeerBootstrap bootstrap = PeerBootstrap();
      s_env[addr] = bootstrap;
    }
    return s_env;
  }

  inline SystemEnvironment defaultEnvironment() {
    return defaultEnvironment(defaultAddress);
  }

  inline std::list<Address> deployedNodes(const SystemEnvironment& sysEnv) {
    std::list<Address> r;
    for (auto x : sysEnv) { r.push_back(x.first); }
    return std::move(r);
  }

  inline bool isDeployedNode(const SystemEnvironment& sysEnv, Address addr) {
    return sysEnv.find(addr) != sysEnv.end();
  }

  //-------------
  // Logging.
  class Log {
  public:
    Log() {}
    Log(boost::log::trivial::severity_level lvl) : defaultLevel(lvl) {}

    virtual void log(const std::string& msg) = 0;
    virtual void log(const char* msg) = 0;
    virtual void logAt(boost::log::trivial::severity_level lvl, const std::string& msg) = 0;
    virtual void logAt(boost::log::trivial::severity_level lvl, const char* msg) = 0;

  protected:
    boost::log::trivial::severity_level defaultLevel;
  };

  class LogST : public boost::log::sources::severity_channel_logger<boost::log::trivial::severity_level,std::string>, public Log
  {
  public:
    typedef severity_channel_logger<boost::log::trivial::severity_level,std::string> logger;

    LogST(std::string chan): logger(boost::log::keywords::channel = chan),
                             Log(boost::log::trivial::severity_level::info) {}
    LogST(std::string chan, boost::log::trivial::severity_level lvl): logger(boost::log::keywords::channel = chan),
                                                                      Log(lvl) {}

    void log(const std::string& msg) { BOOST_LOG_SEV(*this, defaultLevel) << msg; }
    void log(const char* msg) { BOOST_LOG_SEV(*this, defaultLevel) << msg; }

    void logAt(boost::log::trivial::severity_level lvl, const std::string& msg) { BOOST_LOG_SEV(*this, lvl) << msg; }
    void logAt(boost::log::trivial::severity_level lvl, const char* msg) { BOOST_LOG_SEV(*this, lvl) << msg; }
  };

  class LogMT : public boost::log::sources::severity_channel_logger_mt<boost::log::trivial::severity_level,std::string>, public Log
  {
  public:
    typedef severity_channel_logger_mt<boost::log::trivial::severity_level,std::string> logger;

    LogMT(std::string chan) : logger(boost::log::keywords::channel = chan), Log(boost::log::trivial::severity_level::info) {}
    LogMT(std::string chan, boost::log::trivial::severity_level lvl) : logger(boost::log::keywords::channel = chan), Log(lvl) {}

    void log(const std::string& msg) { BOOST_LOG_SEV(*this, defaultLevel) << msg; }
    void log(const char* msg) { BOOST_LOG_SEV(*this, defaultLevel) << msg; }

    void logAt(boost::log::trivial::severity_level lvl, const std::string& msg) { BOOST_LOG_SEV(*this, lvl) << msg; }
    void logAt(boost::log::trivial::severity_level lvl, const char* msg) { BOOST_LOG_SEV(*this, lvl) << msg; }
  }; // Class LogMT

  // Hashing
  template <class T>
  std::size_t hash_value(T const& t) {
    boost::hash<T> hasher;
    return hasher(t);
  }
  template <>
  std::size_t hash_value<K3::base_string>(const K3::base_string&);

} // namespace K3

#endif
<commit_msg>Added flushing to C++ logging<commit_after>#ifndef K3_RUNTIME_COMMON_H
#define K3_RUNTIME_COMMON_H

#include <cstdint>
#include <list>
#include <vector>
#include <map>
#include <memory>
#include <sstream>
#include <string>
#include <functional>
#include <stdexcept>
#include <tuple>
#include <utility>
#include <boost/algorithm/string.hpp>
#include <boost/any.hpp>
#include <boost/asio.hpp>
#include <boost/log/core.hpp>
#include <boost/log/core/core.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/sources/severity_channel_logger.hpp>
#include <boost/log/sources/severity_feature.hpp>
#include <boost/log/trivial.hpp>
#include <boost/regex.hpp>

namespace K3 {

  using std::shared_ptr;
  using std::make_shared;
  using std::string;
  using std::tuple;
  using std::make_tuple;

  // String implementation
  class base_string;
  typedef K3::base_string string_impl;
  template <class r> using F = std::function<r>;
  typedef std::string Identifier;
  typedef int TriggerId;
  typedef std::string Value;

  typedef std::string Value;
  typedef std::string EValue;
  typedef std::string IValue;

  typedef uint32_t fixed_int;

  typedef std::tuple<boost::asio::ip::address, unsigned short> Address;

  enum class Builtin { Stdin, Stdout, Stderr };
  enum class IOMode  { Read, Write, Append, ReadWrite };

  //---------------
  // Addresses.

  inline Address make_address(const std::string& host, unsigned short port)   {
    return Address(boost::asio::ip::address::from_string(host), port);
  }

  inline Address make_address(const char* host, unsigned short port) {
    return Address(boost::asio::ip::address::from_string(host), port);
  }

  static inline Address make_address(const std::string&& host, unsigned short port)  {
    return Address(boost::asio::ip::address::from_string(host), port);
  }

  inline std::string addressHost(const Address& addr) { return std::get<0>(addr).to_string(); }
  inline std::string addressHost(Address&& addr) { return std::get<0>(std::forward<Address>(addr)).to_string(); }

  inline int addressPort(const Address& addr) { return std::get<1>(addr); }
  inline int addressPort(Address&& addr) { return std::get<1>(std::forward<Address>(addr)); }

  inline std::string addressAsString(const Address& addr) {
    return addressHost(addr) + ":" + std::to_string(addressPort(addr));
  }

  inline std::string addressAsString(Address&& addr) {
    return addressHost(std::forward<Address>(addr))
            + ":" + std::to_string(addressPort(std::forward<Address>(addr)));
  }

  inline Address internalSendAddress(const Address& addr) {
    return make_address(addressHost(addr), addressPort(addr)+1);
  }

  inline Address internalSendAddress(Address&& addr) {
    return make_address(addressHost(std::forward<Address>(addr)),
                        addressPort(std::forward<Address>(addr))+1);
  }

  inline Address externalSendAddress(const Address& addr) {
    return make_address(addressHost(addr), addressPort(addr)+2);
  }

  inline Address externalSendAddress(Address&& addr) {
    return make_address(addressHost(std::forward<Address>(addr)),
                        addressPort(std::forward<Address>(addr))+2);
  }

  // TODO put the definition somewhere
  static Address defaultAddress = make_address("127.0.0.1", 40000);

  //--------------------
  // System environment.

  // Literals are native values rather than an AST reprensentation as in Haskell.
  typedef boost::any Literal;
  typedef std::map<Identifier, Literal> PeerBootstrap;
  typedef std::map<Address, PeerBootstrap> SystemEnvironment;

  static inline SystemEnvironment defaultEnvironment(Address addr) {
    PeerBootstrap bootstrap = PeerBootstrap();
    SystemEnvironment s_env = SystemEnvironment();
    s_env[addr] = bootstrap;
    return s_env;
  }

  inline SystemEnvironment defaultEnvironment(std::list<Address> addrs) {
    SystemEnvironment s_env;
    for (Address addr : addrs) {
      PeerBootstrap bootstrap = PeerBootstrap();
      s_env[addr] = bootstrap;
    }
    return s_env;
  }

  inline SystemEnvironment defaultEnvironment() {
    return defaultEnvironment(defaultAddress);
  }

  inline std::list<Address> deployedNodes(const SystemEnvironment& sysEnv) {
    std::list<Address> r;
    for (auto x : sysEnv) { r.push_back(x.first); }
    return std::move(r);
  }

  inline bool isDeployedNode(const SystemEnvironment& sysEnv, Address addr) {
    return sysEnv.find(addr) != sysEnv.end();
  }

  //-------------
  // Logging.
  class Log {
  public:
    Log() {}
    Log(boost::log::trivial::severity_level lvl) : defaultLevel(lvl) {}

    virtual void log(const std::string& msg) = 0;
    virtual void log(const char* msg) = 0;
    virtual void logAt(boost::log::trivial::severity_level lvl, const std::string& msg) = 0;
    virtual void logAt(boost::log::trivial::severity_level lvl, const char* msg) = 0;

  protected:
    boost::log::trivial::severity_level defaultLevel;
  };

  class LogST : public boost::log::sources::severity_channel_logger<boost::log::trivial::severity_level,std::string>, public Log
  {
  public:
    typedef severity_channel_logger<boost::log::trivial::severity_level,std::string> logger;

    LogST(std::string chan): logger(boost::log::keywords::channel = chan),
                             Log(boost::log::trivial::severity_level::info) {}
    LogST(std::string chan, boost::log::trivial::severity_level lvl): logger(boost::log::keywords::channel = chan),
                                                                      Log(lvl) {}

    void log(const std::string& msg) {
      BOOST_LOG_SEV(*this, defaultLevel) << msg;
      boost::log::core::get()->flush();
    }

    void log(const char* msg) {
      BOOST_LOG_SEV(*this, defaultLevel) << msg;
      boost::log::core::get()->flush();
    }

    void logAt(boost::log::trivial::severity_level lvl, const std::string& msg) {
      BOOST_LOG_SEV(*this, lvl) << msg;
      boost::log::core::get()->flush();
    }

    void logAt(boost::log::trivial::severity_level lvl, const char* msg) {
      BOOST_LOG_SEV(*this, lvl) << msg;
      boost::log::core::get()->flush();
    }
  };

  class LogMT : public boost::log::sources::severity_channel_logger_mt<boost::log::trivial::severity_level,std::string>, public Log
  {
  public:
    typedef severity_channel_logger_mt<boost::log::trivial::severity_level,std::string> logger;

    LogMT(std::string chan) : logger(boost::log::keywords::channel = chan), Log(boost::log::trivial::severity_level::info) {}
    LogMT(std::string chan, boost::log::trivial::severity_level lvl) : logger(boost::log::keywords::channel = chan), Log(lvl) {}

    void log(const std::string& msg) {
      BOOST_LOG_SEV(*this, defaultLevel) << msg;
      boost::log::core::get()->flush();
    }

    void log(const char* msg) {
      BOOST_LOG_SEV(*this, defaultLevel) << msg;
      boost::log::core::get()->flush();
    }

    void logAt(boost::log::trivial::severity_level lvl, const std::string& msg) {
      BOOST_LOG_SEV(*this, lvl) << msg;
      boost::log::core::get()->flush();
    }

    void logAt(boost::log::trivial::severity_level lvl, const char* msg) {
      BOOST_LOG_SEV(*this, lvl) << msg;
      boost::log::core::get()->flush();
    }
  }; // Class LogMT

  // Hashing
  template <class T>
  std::size_t hash_value(T const& t) {
    boost::hash<T> hasher;
    return hasher(t);
  }
  template <>
  std::size_t hash_value<K3::base_string>(const K3::base_string&);

} // namespace K3

#endif
<|endoftext|>