<commit_before>#include "kulma/io/file.h"

#include "kulma/platform.h"
#if KULMA_PLATFORM_WINDOWS
#   ifndef WIN32_LEAN_AND_MEAN
#       define WIN32_LEAN_AND_MEAN
#   endif
#   include <Windows.h>
#elif KULMA_PLATFORM_LINUX

#endif

namespace kulma
{
    FileReader::FileReader()
#if KULMA_PLATFORM_WINDOWS
        : m_file(INVALID_HANDLE_VALUE)
#elif KULMA_PLATFORM_LINUX
        : m_file(NULL)
#endif
    {

    }

    FileReader::~FileReader()
    {

    }

    int32_t FileReader::read(void * p_data, int32_t p_size, Error * p_err)
    {
        KULMA_ASSERT(p_err != NULL, "Reading interface error handler can't be null");

#if KULMA_PLATFORM_WINDOWS
        DWORD read = 0;
        if (::ReadFile(m_file, p_data, p_size, &read, NULL) == FALSE)
        {
            KULMA_ERROR_SET(p_err,
                KULMA_ERROR_IO_READ,
                "FileReader: read failed");
        }
        else if ((int32_t)read != p_size)
        {
            KULMA_ERROR_SET(p_err,
                KULMA_ERROR_IO_READ,
                "FileReader: read failed");
        }
        return (int32_t)read;
#elif KULMA_PLATFORM_LINUX
        int32_t size = (int32_t)fread(p_data, 1, p_size, m_file);
        if (size != p_size)
        {
            KULMA_ERROR_SET(p_err,
                KULMA_ERROR_IO_READ,
                "FileReader: read failed");
            return size >= 0 ? size : 0;
        }
        return size;
#endif
    }

    int64_t FileReader::seek(int64_t p_offset, Whence::Enum p_whence)
    {
#if KULMA_PLATFORM_WINDOWS
        LARGE_INTEGER li;

        li.QuadPart = p_offset;

        li.LowPart = ::SetFilePointer(m_file,
            li.LowPart,
            &li.HighPart,
            p_whence);

        KULMA_ASSERT(li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR,
            "SetFilePointer failed, GetLastError = %d",
            GetLastError()
            );

        return li.QuadPart;

#elif KULMA_PLATFORM_LINUX
        fseeko64(m_file, p_offset, p_whence);
        return ftello64(m_file);
#endif
    }

    bool FileReader::open(const char * p_filePath, Error * p_err)
    {
        KULMA_ASSERT(p_err != NULL, "Reading interface error handler can't be null");

#if KULMA_PLATFORM_WINDOWS
        m_file = ::CreateFile(
            p_filePath,
            GENERIC_READ,
            0,
            NULL,
            OPEN_ALWAYS,
            FILE_ATTRIBUTE_NORMAL,
            NULL
            );

        if (m_file == INVALID_HANDLE_VALUE)
        {
            KULMA_ERROR_SET(p_err,
                KULMA_ERROR_IO_OPEN,
                "FileReader: failed to open file");
            return false;
        }
#elif KULMA_PLATFORM_LINUX
        m_file = ::fopen(p_filePath, "rb");

        if (m_file == NULL)
        {
            KULMA_ERROR_SET(p_err,
                KULMA_ERROR_IO_OPEN,
                "FileReader: failed to open file");
            return false;
        }
#endif

        return true;
    }

    void FileReader::close()
    {
#if KULMA_PLATFORM_WINDOWS
        if (m_file != INVALID_HANDLE_VALUE)
        {
            ::CloseHandle(m_file);
            m_file = INVALID_HANDLE_VALUE;
        }
#elif KULMA_PLATFORM_LINUX
        if (m_file != NULL)
        {
            ::fclose(m_file);
            m_file = NULL;
        }
#endif
    }

    FileWriter::FileWriter()
#if KULMA_PLATFORM_WINDOWS
        : m_file(INVALID_HANDLE_VALUE)
#elif KULMA_PLATFORM_LINUX
        : m_file(NULL)
#endif
    {

    }

    FileWriter::~FileWriter()
    {

    }

    int32_t FileWriter::write(const void* p_data, int32_t p_size, Error* p_err)
    {
        KULMA_UNUSED(p_data, p_size, p_err);
        return 0;
    }

    int64_t FileWriter::seek(int64_t p_offset, Whence::Enum p_whence)
    {
        KULMA_UNUSED(p_offset, p_whence);
        return 0;
    }

    bool FileWriter::open(const char* p_filePath, bool p_append, Error* p_err)
    {
        KULMA_UNUSED(p_filePath, p_append, p_err);
        return false;
    }

    void FileWriter::close()
    {

    }
}<commit_msg>Open file for writing<commit_after>#include "kulma/io/file.h"

#include "kulma/platform.h"
#if KULMA_PLATFORM_WINDOWS
#   ifndef WIN32_LEAN_AND_MEAN
#       define WIN32_LEAN_AND_MEAN
#   endif
#   include <Windows.h>
#elif KULMA_PLATFORM_LINUX

#endif

namespace kulma
{
    FileReader::FileReader()
#if KULMA_PLATFORM_WINDOWS
        : m_file(INVALID_HANDLE_VALUE)
#elif KULMA_PLATFORM_LINUX
        : m_file(NULL)
#endif
    {

    }

    FileReader::~FileReader()
    {

    }

    int32_t FileReader::read(void * p_data, int32_t p_size, Error * p_err)
    {
        KULMA_ASSERT(p_err != NULL, "Reading interface error handler can't be null");

#if KULMA_PLATFORM_WINDOWS
        DWORD read = 0;
        if (::ReadFile(m_file, p_data, p_size, &read, NULL) == FALSE)
        {
            KULMA_ERROR_SET(p_err,
                KULMA_ERROR_IO_READ,
                "FileReader: read failed");
        }
        else if ((int32_t)read != p_size)
        {
            KULMA_ERROR_SET(p_err,
                KULMA_ERROR_IO_READ,
                "FileReader: read failed");
        }
        return (int32_t)read;
#elif KULMA_PLATFORM_LINUX
        int32_t size = (int32_t)fread(p_data, 1, p_size, m_file);
        if (size != p_size)
        {
            KULMA_ERROR_SET(p_err,
                KULMA_ERROR_IO_READ,
                "FileReader: read failed");
            return size >= 0 ? size : 0;
        }
        return size;
#endif
    }

    int64_t FileReader::seek(int64_t p_offset, Whence::Enum p_whence)
    {
#if KULMA_PLATFORM_WINDOWS
        LARGE_INTEGER li;

        li.QuadPart = p_offset;

        li.LowPart = ::SetFilePointer(m_file,
            li.LowPart,
            &li.HighPart,
            p_whence);

        KULMA_ASSERT(li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR,
            "SetFilePointer failed, GetLastError = %d",
            GetLastError()
            );

        return li.QuadPart;

#elif KULMA_PLATFORM_LINUX
        fseeko64(m_file, p_offset, p_whence);
        return ftello64(m_file);
#endif
    }

    bool FileReader::open(const char * p_filePath, Error * p_err)
    {
        KULMA_ASSERT(p_err != NULL, "Reading interface error handler can't be null");

#if KULMA_PLATFORM_WINDOWS
        m_file = ::CreateFileA(
            p_filePath,
            GENERIC_READ,
            0,
            NULL,
            OPEN_ALWAYS,
            FILE_ATTRIBUTE_NORMAL,
            NULL
            );

        if (m_file == INVALID_HANDLE_VALUE)
        {
            KULMA_ERROR_SET(p_err,
                KULMA_ERROR_IO_OPEN,
                "FileReader: failed to open file");
            return false;
        }
#elif KULMA_PLATFORM_LINUX
        m_file = ::fopen(p_filePath, "rb");

        if (m_file == NULL)
        {
            KULMA_ERROR_SET(p_err,
                KULMA_ERROR_IO_OPEN,
                "FileReader: failed to open file");
            return false;
        }
#endif

        return true;
    }

    void FileReader::close()
    {
#if KULMA_PLATFORM_WINDOWS
        if (m_file != INVALID_HANDLE_VALUE)
        {
            ::CloseHandle(m_file);
            m_file = INVALID_HANDLE_VALUE;
        }
#elif KULMA_PLATFORM_LINUX
        if (m_file != NULL)
        {
            ::fclose(m_file);
            m_file = NULL;
        }
#endif
    }

    FileWriter::FileWriter()
#if KULMA_PLATFORM_WINDOWS
        : m_file(INVALID_HANDLE_VALUE)
#elif KULMA_PLATFORM_LINUX
        : m_file(NULL)
#endif
    {

    }

    FileWriter::~FileWriter()
    {

    }

    int32_t FileWriter::write(const void* p_data, int32_t p_size, Error* p_err)
    {
        KULMA_UNUSED(p_data, p_size, p_err);
        return 0;
    }

    int64_t FileWriter::seek(int64_t p_offset, Whence::Enum p_whence)
    {
        KULMA_UNUSED(p_offset, p_whence);
        return 0;
    }

    bool FileWriter::open(const char* p_filePath, bool p_append, Error* p_err)
    {
#if KULMA_PLATFORM_WINDOWS
        m_file = ::CreateFileA(p_filePath,
            GENERIC_WRITE,
            0,
            NULL,
            p_append ? OPEN_ALWAYS : CREATE_ALWAYS, // truncate if necessary
            FILE_ATTRIBUTE_NORMAL,
            NULL
            );

        if (m_file == INVALID_HANDLE_VALUE)
        {
            KULMA_ERROR_SET(p_err,
                KULMA_ERROR_IO_OPEN,
                "FileWriter: failed to open file");
            return false;
        }

        if (p_append)
        {
            // move the cursor to the eof
            DWORD err = ::SetFilePointer(m_file, 0, NULL, FILE_END);
            if (err == INVALID_SET_FILE_POINTER)
            {
                KULMA_ERROR_SET(p_err,
                    KULMA_ERROR_IO_OPEN,
                    "FileWriter: faled to open file, SetFilePointer failed");
                return false;
            }
        }
#elif KULMA_PLATFORM_LINUX
#endif

        return true;
    }

    void FileWriter::close()
    {
#if KULMA_PLATFORM_WINDOWS
        if (m_file != INVALID_HANDLE_VALUE)
        {
            ::CloseHandle(m_file);
            m_file = INVALID_HANDLE_VALUE;
        }
#elif KULMA_PLATFORM_LINUX
        if (m_file != NULL)
        {
            ::fclose(m_file);
            m_file = NULL;
        }
#endif
    }
}<|endoftext|>


<commit_before>/*
 * MidiCtrl - Host implementation of a MIDI Uart skeletton (with sysex listener)
 *
 * (c) July 2011 - Manuel Odendahl - wesen@ruinwesen.com
 */

#include <unistd.h>

#include "Platform.h"
#include "MidiUartHost.h"

uint8_t sysexBuf[8192];
uint8_t sysexBuf2[8192];

#ifndef TEST_SUITE
MidiClass Midi(NULL, sysexBuf, sizeof(sysexBuf));
MidiClass Midi2(NULL, sysexBuf2, sizeof(sysexBuf2));
MidiUartHostClass MidiUart;
#endif

void MidiUartHostSysexListener::end() {
  // XXX Debug
  //  printf("send sysex of %d bytes\n", sysex->len);

  uint8_t buf[sysex->len +2];
  buf[0] = 0xF0;
  m_memcpy(buf + 1, sysex->data, sysex->len);
  buf[sysex->len + 1] = 0xF7;
  uart->midiSendLong(buf, sysex->len + 2);
}

void handleIncomingMidi() {
  MidiUart.runLoop();
  while (MidiUart.avail()) {
    Midi.handleByte(MidiUart.getc());
  }
  usleep(1000);
}

void MidiUartHostParent::onOutputMessage(uint8_t *msg, uint8_t len) {
  //  printf("output message %d bytes\n", len);
  //  hexdump(msg, len);

  if (len > 3) {
    midiSendLong(msg, len);
  } else {
    switch (len) {
    case 0:
      return;
    case 1:
      midiSendShort(msg[0], 0, 0);
      break;
    case 2:
      midiSendShort(msg[0], msg[1], 0);
      break;
    case 3:
      midiSendShort(msg[0], msg[1], msg[2]);
      break;
    default:
      return;
    }
  }
}

void MidiUartHostParent::init(int _inputDevice, int _outputDevice) {
  inputDevice = _inputDevice;
  outputDevice = _outputDevice;

  outputMidi.init();
  outputMidi.addOnMessageCallback(this, (midi_callback_ptr2_t)&MidiUartHostParent::onOutputMessage);

  outputMidi.midiSysex.addSysexListener(&sysexListener);
}

<commit_msg>Fix method signature for midiuarthost<commit_after>/*
 * MidiCtrl - Host implementation of a MIDI Uart skeletton (with sysex listener)
 *
 * (c) July 2011 - Manuel Odendahl - wesen@ruinwesen.com
 */

#include <unistd.h>

#include "Platform.h"
#include "MidiUartHost.h"

uint8_t sysexBuf[8192];
uint8_t sysexBuf2[8192];

#ifndef TEST_SUITE
MidiClass Midi(NULL, sysexBuf, sizeof(sysexBuf));
MidiClass Midi2(NULL, sysexBuf2, sizeof(sysexBuf2));
MidiUartHostClass MidiUart;
#endif

void MidiUartHostSysexListener::end() {
  // XXX Debug
  //  printf("send sysex of %d bytes\n", sysex->len);

  uint8_t buf[sysex->len +2];
  buf[0] = 0xF0;
  m_memcpy(buf + 1, sysex->data, sysex->len);
  buf[sysex->len + 1] = 0xF7;
  uart->midiSendLong(buf, sysex->len + 2);
}

void handleIncomingMidi() {
  MidiUart.runLoop();
  while (MidiUart.avail()) {
    Midi.handleByte(MidiUart.getc());
  }
  usleep(1000);
}

void MidiUartHostParent::onOutputMessage(uint8_t *msg, uint8_t len) {
  //  printf("output message %d bytes\n", len);
  //  hexdump(msg, len);

  if (len > 3) {
    midiSendLong(msg, len);
  } else {
    switch (len) {
    case 0:
      return;
    case 1:
      midiSendShort(msg[0], 0, 0);
      break;
    case 2:
      midiSendShort(msg[0], msg[1], 0);
      break;
    case 3:
      midiSendShort(msg[0], msg[1], msg[2]);
      break;
    default:
      return;
    }
  }
}

bool MidiUartHostParent::init(int _inputDevice, int _outputDevice) {
  inputDevice = _inputDevice;
  outputDevice = _outputDevice;

  outputMidi.init();
  outputMidi.addOnMessageCallback(this, (midi_callback_ptr2_t)&MidiUartHostParent::onOutputMessage);

  outputMidi.midiSysex.addSysexListener(&sysexListener);

  return true;
}

<|endoftext|>


<commit_before>//
// Created by permal on 7/20/17.
//

#include <smooth/application/network/mqtt/MQTT.h>
#include <smooth/application/network/mqtt/packet/Connect.h>
#include <smooth/application/network/mqtt/state/IdleState.h>
#include "esp_log.h"

using namespace smooth::core::ipc;
using namespace std::chrono;

namespace smooth
{
    namespace application
    {
        namespace network
        {
            namespace mqtt
            {
                MQTT::MQTT(const std::string& mqtt_client_id,
                           std::chrono::seconds keep_alive,
                           uint32_t stack_depth,
                           UBaseType_t priority)
                        : Task(mqtt_client_id, stack_depth, priority, std::chrono::milliseconds(100)),
                          tx_buffer(),
                          rx_buffer(),
                          tx_empty("TX_empty", 5, *this, *this),
                          data_available("data_available", 5, *this, *this),
                          connection_status("connection_status", 5, *this, *this),
                          timer_events("timer_events", 5, *this, *this),
                          guard(),
                          client_id(mqtt_client_id),
                          keep_alive(keep_alive),
                          mqtt_socket(nullptr),
                          receive_timer("receive_timer", MQTT_FSM_RECEIVE_TIMER_ID, timer_events, false,
                                        std::chrono::seconds(10)),
                          reconnect_timer("reconnect_timer", MQTT_FSM_RECONNECT_TIMER_ID, timer_events, false,
                                          std::chrono::seconds(5)),
                          keep_alive_timer("keep_alive_timer", MQTT_FSM_KEEP_ALIVE_TIMER_ID, timer_events, true,
                                           std::chrono::seconds(1)),
                          fsm(*this)
                {
                }

                void MQTT::tick()
                {
                    fsm.tick();
                }

                void MQTT::init()
                {
                    fsm.set_state(new(fsm) state::IdleState(fsm));
                }

                void MQTT::connect_to(std::shared_ptr<smooth::core::network::InetAddress> address, bool auto_reconnect,
                                      bool use_ssl)
                {
                    Mutex::Lock lock(guard);

                    this->auto_reconnect = auto_reconnect;

                    if (!mqtt_socket)
                    {
                        if (use_ssl)
                        {
                            mqtt_socket.reset(
                                    new core::network::SSLSocket<packet::MQTTPacket>(tx_buffer,
                                                                                rx_buffer,
                                                                                tx_empty,
                                                                                data_available,
                                                                                connection_status));
                        }
                        else
                        {
                            mqtt_socket.reset(
                                    new core::network::Socket<packet::MQTTPacket>(tx_buffer,
                                                                                rx_buffer,
                                                                                tx_empty,
                                                                                data_available,
                                                                                connection_status));
                        }

                        mqtt_socket->start(address);
                    }
                }

                void MQTT::disconnect()
                {
                    auto_reconnect = false;
                    mqtt_socket->stop();
                    mqtt_socket.reset();
                    fsm.set_state(new(fsm) state::IdleState(fsm));
                }

                void MQTT::send_packet(packet::MQTTPacket& packet, milliseconds timeout)
                {
                    receive_timer.start(timeout);
                    tx_buffer.put(packet);
                }

                const std::string& MQTT::get_client_id() const
                {
                    return client_id;
                }

                const std::chrono::seconds MQTT::get_keep_alive() const
                {
                    return keep_alive;
                }

                void MQTT::start_reconnect()
                {
                    reconnect_timer.start();
                }

                void MQTT::reconnect()
                {
                    mqtt_socket->restart();
                }

                bool MQTT::get_auto_reconnect() const
                {
                    return auto_reconnect;
                }

                void MQTT::set_keep_alive_timer(std::chrono::seconds interval)
                {
                    if (interval.count() == 0)
                    {
                        keep_alive_timer.stop();
                    }
                    else
                    {
                        std::chrono::milliseconds ms = interval;
                        // Times 0.75 as integer math.
                        ms *= 3;
                        ms /= 4;
                        ESP_LOGV("MQTT", "ms: %d", static_cast<int>(ms.count()));
                        keep_alive_timer.start(ms);
                    }
                }

                void MQTT::message(const core::network::TransmitBufferEmptyEvent& msg)
                {
                    fsm.message(msg);
                }

                void MQTT::message(const core::network::ConnectionStatusEvent& msg)
                {
                    fsm.message(msg);
                }

                void MQTT::message(const core::network::DataAvailableEvent<packet::MQTTPacket>& msg)
                {
                    receive_timer.stop();

                    packet::MQTTPacket p;
                    if (msg.get(p))
                    {
                        fsm.packet_received(p);
                    }
                }

                void MQTT::message(const core::timer::TimerExpiredEvent& msg)
                {
                    fsm.message(msg);
                }
            }
        }
    }
}<commit_msg>Changed interval to 0.5 of keep alive interval.<commit_after>//
// Created by permal on 7/20/17.
//

#include <smooth/application/network/mqtt/MQTT.h>
#include <smooth/application/network/mqtt/packet/Connect.h>
#include <smooth/application/network/mqtt/state/IdleState.h>
#include "esp_log.h"

using namespace smooth::core::ipc;
using namespace std::chrono;

namespace smooth
{
    namespace application
    {
        namespace network
        {
            namespace mqtt
            {
                MQTT::MQTT(const std::string& mqtt_client_id,
                           std::chrono::seconds keep_alive,
                           uint32_t stack_depth,
                           UBaseType_t priority)
                        : Task(mqtt_client_id, stack_depth, priority, std::chrono::milliseconds(100)),
                          tx_buffer(),
                          rx_buffer(),
                          tx_empty("TX_empty", 5, *this, *this),
                          data_available("data_available", 5, *this, *this),
                          connection_status("connection_status", 5, *this, *this),
                          timer_events("timer_events", 5, *this, *this),
                          guard(),
                          client_id(mqtt_client_id),
                          keep_alive(keep_alive),
                          mqtt_socket(nullptr),
                          receive_timer("receive_timer", MQTT_FSM_RECEIVE_TIMER_ID, timer_events, false,
                                        std::chrono::seconds(10)),
                          reconnect_timer("reconnect_timer", MQTT_FSM_RECONNECT_TIMER_ID, timer_events, false,
                                          std::chrono::seconds(5)),
                          keep_alive_timer("keep_alive_timer", MQTT_FSM_KEEP_ALIVE_TIMER_ID, timer_events, true,
                                           std::chrono::seconds(1)),
                          fsm(*this)
                {
                }

                void MQTT::tick()
                {
                    fsm.tick();
                }

                void MQTT::init()
                {
                    fsm.set_state(new(fsm) state::IdleState(fsm));
                }

                void MQTT::connect_to(std::shared_ptr<smooth::core::network::InetAddress> address, bool auto_reconnect,
                                      bool use_ssl)
                {
                    Mutex::Lock lock(guard);

                    this->auto_reconnect = auto_reconnect;

                    if (!mqtt_socket)
                    {
                        if (use_ssl)
                        {
                            mqtt_socket.reset(
                                    new core::network::SSLSocket<packet::MQTTPacket>(tx_buffer,
                                                                                rx_buffer,
                                                                                tx_empty,
                                                                                data_available,
                                                                                connection_status));
                        }
                        else
                        {
                            mqtt_socket.reset(
                                    new core::network::Socket<packet::MQTTPacket>(tx_buffer,
                                                                                rx_buffer,
                                                                                tx_empty,
                                                                                data_available,
                                                                                connection_status));
                        }

                        mqtt_socket->start(address);
                    }
                }

                void MQTT::disconnect()
                {
                    auto_reconnect = false;
                    mqtt_socket->stop();
                    mqtt_socket.reset();
                    fsm.set_state(new(fsm) state::IdleState(fsm));
                }

                void MQTT::send_packet(packet::MQTTPacket& packet, milliseconds timeout)
                {
                    receive_timer.start(timeout);
                    tx_buffer.put(packet);
                }

                const std::string& MQTT::get_client_id() const
                {
                    return client_id;
                }

                const std::chrono::seconds MQTT::get_keep_alive() const
                {
                    return keep_alive;
                }

                void MQTT::start_reconnect()
                {
                    reconnect_timer.start();
                }

                void MQTT::reconnect()
                {
                    mqtt_socket->restart();
                }

                bool MQTT::get_auto_reconnect() const
                {
                    return auto_reconnect;
                }

                void MQTT::set_keep_alive_timer(std::chrono::seconds interval)
                {
                    if (interval.count() == 0)
                    {
                        keep_alive_timer.stop();
                    }
                    else
                    {
                        std::chrono::milliseconds ms = interval;
                        ms /= 2;
                        ESP_LOGV("MQTT", "ms: %d", static_cast<int>(ms.count()));
                        keep_alive_timer.start(ms);
                    }
                }

                void MQTT::message(const core::network::TransmitBufferEmptyEvent& msg)
                {
                    fsm.message(msg);
                }

                void MQTT::message(const core::network::ConnectionStatusEvent& msg)
                {
                    fsm.message(msg);
                }

                void MQTT::message(const core::network::DataAvailableEvent<packet::MQTTPacket>& msg)
                {
                    receive_timer.stop();

                    packet::MQTTPacket p;
                    if (msg.get(p))
                    {
                        fsm.packet_received(p);
                    }
                }

                void MQTT::message(const core::timer::TimerExpiredEvent& msg)
                {
                    fsm.message(msg);
                }
            }
        }
    }
}<|endoftext|>


<commit_before>/** \copyright
 * Copyright (c) 2013, Balazs Racz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are  permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file main.cxx
 *
 * A simple application to demonstrate asynchronous interfaces.
 *
 * @author Balazs Racz
 * @date 7 Dec 2013
 */

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

#include "os/os.h"
#include "utils/gc_pipe.hxx"
#include "executor/Executor.hxx"
#include "nmranet_can.h"
#include "nmranet_config.h"

#include "utils/GcTcpHub.hxx"
#include "nmranet/AsyncIfCan.hxx"
#include "nmranet/NMRAnetIf.hxx"
#include "nmranet/AsyncAliasAllocator.hxx"
#include "nmranet/GlobalEventHandler.hxx"
#include "nmranet/EventHandlerTemplates.hxx"
#include "nmranet/NMRAnetAsyncEventHandler.hxx"
#include "nmranet/NMRAnetAsyncDefaultNode.hxx"
//#include "freertos_drivers/nxp/11cxx_async_can.hxx"

Executor<1> g_executor("g_executor", 0, 1024);
Service g_service(&g_executor);
CanHubFlow can_hub0(&g_service);
#ifdef __linux__
GcPacketPrinter packet_printer(&can_hub0);
#endif

static const NMRAnet::NodeID NODE_ID = 0x050101011441ULL;

extern "C" {
extern int GC_GENERATE_NEWLINES;
int GC_GENERATE_NEWLINES = 1;
}

extern "C" {
const size_t WRITE_FLOW_THREAD_STACK_SIZE = 900;
extern const size_t CAN_TX_BUFFER_SIZE;
extern const size_t CAN_RX_BUFFER_SIZE;
const size_t CAN_RX_BUFFER_SIZE = 1;
const size_t CAN_TX_BUFFER_SIZE = 2;
extern const size_t SERIAL_RX_BUFFER_SIZE;
extern const size_t SERIAL_TX_BUFFER_SIZE;
const size_t SERIAL_RX_BUFFER_SIZE = 16;
const size_t SERIAL_TX_BUFFER_SIZE = 16;
#ifdef BOARD_LAUNCHPAD_EK
const size_t main_stack_size = 2500;
#else
const size_t main_stack_size = 900;
#endif
}

NMRAnet::AsyncIfCan g_if_can(&g_executor, &can_hub0, 3, 3, 2);
static NMRAnet::AddAliasAllocator _alias_allocator(NODE_ID, &g_if_can);
NMRAnet::DefaultAsyncNode g_node(&g_if_can, NODE_ID);
NMRAnet::GlobalEventService g_event_service(&g_if_can);

static const uint64_t EVENT_ID = 0x0501010114FF2200ULL;
const int main_priority = 0;

class BlinkerFlow : public StateFlowBase
{
public:
    BlinkerFlow(NMRAnet::AsyncNode* node)
        : StateFlowBase(node->interface()),
          state_(1),
          bit_(node, EVENT_ID, EVENT_ID + 1, &state_, (uint8_t)1),
          producer_(&bit_),
          sleepData_(this)
    {
        start_flow(STATE(blinker));
    }

private:
    Action blinker()
    {
        state_ = !state_;
#ifdef __linux__
        LOG(INFO, "blink produce %d", state_);
#endif
        producer_.Update(&helper_, n_.reset(this));
        return wait_and_call(STATE(handle_sleep));
    }

    Action handle_sleep()
    {
        return sleep_and_call(&sleepData_, MSEC_TO_NSEC(1000), STATE(blinker));
    }

    uint8_t state_;
    NMRAnet::MemoryBit<uint8_t> bit_;
    NMRAnet::BitEventProducer producer_;
    NMRAnet::WriteHelper helper_;
    StateFlowTimer sleepData_;
    BarrierNotifiable n_;
};

extern "C" { void resetblink(uint32_t pattern); }

class LoggingBit : public NMRAnet::BitEventInterface
{
public:
    LoggingBit(uint64_t event_on, uint64_t event_off, const char* name)
        : BitEventInterface(event_on, event_off), name_(name), state_(false)
    {
    }

    virtual bool GetCurrentState()
    {
        return state_;
    }
    virtual void SetState(bool new_value)
    {
        state_ = new_value;
        //HASSERT(0);
#ifdef __linux__
        LOG(INFO, "bit %s set to %d", name_, state_);
#else
        resetblink(state_ ? 1 : 0);
#endif
    }

    virtual NMRAnet::AsyncNode* node()
    {
        return &g_node;
    }

private:
    const char* name_;
    bool state_;
};

/** Entry point to application.
 * @param argc number of command line arguments
 * @param argv array of command line arguments
 * @return 0, should never return
 */
int appl_main(int argc, char* argv[])
{
#ifdef __linux__
    GcTcpHub hub(&can_hub0, 12021);
#endif
#ifdef NNTARGET_LPC11Cxx
    lpc11cxx::CreateCanDriver(&can_pipe);
#endif
#ifdef BOARD_LAUNCHPAD_EK
    int fd = ::open("/dev/ser0", O_RDWR);
    HASSERT(fd >= 0);
    printf("hello, world!\n");
    create_gc_port_for_can_hub(&can_hub0, fd);
#endif
    // Bootstraps the alias allocation process.
    g_if_can.alias_allocator()->send(g_if_can.alias_allocator()->alloc());

    LoggingBit logger(EVENT_ID, EVENT_ID + 1, "blinker");
    NMRAnet::BitEventConsumer consumer(&logger);
    //BlinkerFlow blinker(&g_node);
    // We don't need to support addressed messages.
    // g_if_can.add_addressed_message_support(1);
    while(1) {
        sleep(1);
    }
    return 0;
}
<commit_msg>Fix main.cxx of async_blink to actually use the physical device.<commit_after>/** \copyright
 * Copyright (c) 2013, Balazs Racz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are  permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file main.cxx
 *
 * A simple application to demonstrate asynchronous interfaces.
 *
 * @author Balazs Racz
 * @date 7 Dec 2013
 */

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

#include "os/os.h"
#include "utils/gc_pipe.hxx"
#include "executor/Executor.hxx"
#include "nmranet_can.h"
#include "nmranet_config.h"

#include "utils/GcTcpHub.hxx"
#include "utils/HubDevice.hxx"
#include "nmranet/AsyncIfCan.hxx"
#include "nmranet/NMRAnetIf.hxx"
#include "nmranet/AsyncAliasAllocator.hxx"
#include "nmranet/GlobalEventHandler.hxx"
#include "nmranet/EventHandlerTemplates.hxx"
#include "nmranet/NMRAnetAsyncEventHandler.hxx"
#include "nmranet/NMRAnetAsyncDefaultNode.hxx"
//#include "freertos_drivers/nxp/11cxx_async_can.hxx"

Executor<1> g_executor("g_executor", 0, 1024);
Service g_service(&g_executor);
CanHubFlow can_hub0(&g_service);
#ifdef __linux__
GcPacketPrinter packet_printer(&can_hub0);
#endif

static const NMRAnet::NodeID NODE_ID = 0x050101011441ULL;

extern "C" {
extern int GC_GENERATE_NEWLINES;
int GC_GENERATE_NEWLINES = 1;
}

extern "C" {
const size_t WRITE_FLOW_THREAD_STACK_SIZE = 900;
extern const size_t CAN_TX_BUFFER_SIZE;
extern const size_t CAN_RX_BUFFER_SIZE;
const size_t CAN_RX_BUFFER_SIZE = 1;
const size_t CAN_TX_BUFFER_SIZE = 2;
extern const size_t SERIAL_RX_BUFFER_SIZE;
extern const size_t SERIAL_TX_BUFFER_SIZE;
const size_t SERIAL_RX_BUFFER_SIZE = 16;
const size_t SERIAL_TX_BUFFER_SIZE = 16;
#ifdef BOARD_LAUNCHPAD_EK
const size_t main_stack_size = 2500;
#else
const size_t main_stack_size = 900;
#endif
}

NMRAnet::AsyncIfCan g_if_can(&g_executor, &can_hub0, 3, 3, 2);
static NMRAnet::AddAliasAllocator _alias_allocator(NODE_ID, &g_if_can);
NMRAnet::DefaultAsyncNode g_node(&g_if_can, NODE_ID);
NMRAnet::GlobalEventService g_event_service(&g_if_can);

static const uint64_t EVENT_ID = 0x0501010114FF2200ULL;
const int main_priority = 0;

class BlinkerFlow : public StateFlowBase
{
public:
    BlinkerFlow(NMRAnet::AsyncNode* node)
        : StateFlowBase(node->interface()),
          state_(1),
          bit_(node, EVENT_ID, EVENT_ID + 1, &state_, (uint8_t)1),
          producer_(&bit_),
          sleepData_(this)
    {
        start_flow(STATE(blinker));
    }

private:
    Action blinker()
    {
        state_ = !state_;
#ifdef __linux__
        LOG(INFO, "blink produce %d", state_);
#endif
        producer_.Update(&helper_, n_.reset(this));
        return wait_and_call(STATE(handle_sleep));
    }

    Action handle_sleep()
    {
        return sleep_and_call(&sleepData_, MSEC_TO_NSEC(1000), STATE(blinker));
    }

    uint8_t state_;
    NMRAnet::MemoryBit<uint8_t> bit_;
    NMRAnet::BitEventProducer producer_;
    NMRAnet::WriteHelper helper_;
    StateFlowTimer sleepData_;
    BarrierNotifiable n_;
};

extern "C" { void resetblink(uint32_t pattern); }

class LoggingBit : public NMRAnet::BitEventInterface
{
public:
    LoggingBit(uint64_t event_on, uint64_t event_off, const char* name)
        : BitEventInterface(event_on, event_off), name_(name), state_(false)
    {
    }

    virtual bool GetCurrentState()
    {
        return state_;
    }
    virtual void SetState(bool new_value)
    {
        state_ = new_value;
        //HASSERT(0);
#ifdef __linux__
        LOG(INFO, "bit %s set to %d", name_, state_);
#else
        resetblink(state_ ? 1 : 0);
#endif
    }

    virtual NMRAnet::AsyncNode* node()
    {
        return &g_node;
    }

private:
    const char* name_;
    bool state_;
};

/** Entry point to application.
 * @param argc number of command line arguments
 * @param argv array of command line arguments
 * @return 0, should never return
 */
int appl_main(int argc, char* argv[])
{
#ifdef __linux__
    GcTcpHub hub(&can_hub0, 12021);
#else
#ifdef NNTARGET_LPC11Cxx
    lpc11cxx::CreateCanDriver(&can_pipe);
#else
    int can_fd = ::open("/dev/can0", O_RDWR);
    HASSERT(can_fd >= 0);

    FdHubPort<CanHubFlow> can_hub_port(&can_hub0, can_fd, EmptyNotifiable::DefaultInstance());
#endif  // default target
#endif  // FreeRTOS

    int fd = ::open("/dev/ser0", O_RDWR);
    HASSERT(fd >= 0);
    create_gc_port_for_can_hub(&can_hub0, fd);

    // Bootstraps the alias allocation process.
    g_if_can.alias_allocator()->send(g_if_can.alias_allocator()->alloc());

    LoggingBit logger(EVENT_ID, EVENT_ID + 1, "blinker");
    NMRAnet::BitEventConsumer consumer(&logger);
    //BlinkerFlow blinker(&g_node);
    // We don't need to support addressed messages.
    // g_if_can.add_addressed_message_support(1);
    while(1) {
        sleep(1);
    }
    return 0;
}
<|endoftext|>


<commit_before>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * 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.
 *
 ***************************************************************/

//////////////////////////////////////////////////////////////////////
// Methods to manipulate and manage daemon names
//////////////////////////////////////////////////////////////////////

#include "condor_common.h"
#include "condor_config.h"
#include "condor_string.h"
#include "get_full_hostname.h"
#include "my_hostname.h"
#include "my_username.h"
#include "condor_uid.h"

extern "C" {

// Return the host portion of a daemon name string.  Either the name
// includes an "@" sign, in which case we return whatever is after it,
// or it doesn't, in which case we just return what we got passed.
const char*
get_host_part( const char* name )
{
	char const *tmp;
	if (name == NULL) return NULL;
	tmp = strrchr( name, '@' );
	if( tmp ) {
		return ++tmp;
	} else {
		return name;
	}
}

// Return a pointer to a newly allocated string that contains the
// valid daemon name that corresponds with the given name.  Basically,
// see if there's an '@'.  If so, resolve everything after it as a
// hostname.  If not, resolve what we were passed as a hostname.
// The string is allocated with strnewp() (or it's equivalent), so you
// should deallocate it with delete [].
char*
get_daemon_name( const char* name )
{
	char *tmp, *fullname, *tmpname, *daemon_name = NULL;
	int size;

	dprintf( D_HOSTNAME, "Finding proper daemon name for \"%s\"\n",
			 name );

		// First, check for a '@' in the name.
	tmpname = strdup( name );
	tmp = strrchr( tmpname, '@' );
	if( tmp ) {
			// There's a '@'.
		*tmp = '\0';
		tmp++;
		if( *tmp ) {
				// There was something after the @, try to resolve it
				// as a full hostname:
			dprintf( D_HOSTNAME, "Daemon name has data after the '@', "
					 "trying to resolve \"%s\"\n", tmp );
			fullname = get_full_hostname( tmp );
		} else {
			dprintf( D_HOSTNAME, "Daemon name has no data after the '@', "
					 "trying to use the local host\n" );
				// There was nothing after the @, use localhost:
			fullname = strnewp( my_full_hostname() );
		}
		if( fullname ) {
			size = strlen(tmpname) + strlen(fullname) + 2;
			daemon_name = new char[size];
			sprintf( daemon_name, "%s@%s", tmpname, fullname );
			delete [] fullname;
		}
	} else {
			// There's no '@', just try to resolve the hostname.
		dprintf( D_HOSTNAME, "Daemon name contains no '@', treating as a "
				 "regular hostname\n" );
		daemon_name = get_full_hostname( tmpname );
	}
	free( tmpname );

		// If there was an error, this will still be NULL.
	if( daemon_name ) {
		dprintf( D_HOSTNAME, "Returning daemon name: \"%s\"\n", daemon_name );
	} else {
		dprintf( D_HOSTNAME, "Failed to construct daemon name, "
				 "returning NULL\n" );
	}
	return daemon_name;
}

// Given some name, create a valid name for ourself with our full
// hostname.  If the name contains an '@', strip off everything after
// it and append my_full_hostname().  If there's no '@', try to
// resolve what we have and see if it's my_full_hostname.  If so, use
// it, otherwise, use name@my_full_hostname().  We return the answer
// in a string which should be deallocated w/ delete [].
char*
build_valid_daemon_name( char* name )
{
	char *tmp, *tmpname = NULL, *daemon_name = NULL;
	int size;

		// This flag determines if we want to just return a copy of
		// my_full_hostname(), or if we want to append
		// "@my_full_hostname" to the name we were given.  The name we
		// were given might include an '@', in which case, we trim off
		// everything after the '@'.
	bool just_host = false;

	if( name && *name ) {
		tmpname = strnewp( name );
		tmp = strrchr( tmpname, '@' );
		if( tmp ) {
				// name we were passed has an '@', ignore everything
				// after (and including) the '@'.
			*tmp = '\0';
		} else {
				// no '@', see if what we have is our hostname
			if( (tmp = get_full_hostname(name)) ) {
				if( !strcmp(tmp, my_full_hostname()) ) {
						// Yup, so just the full hostname.
					just_host = true;
				}
				delete [] tmp;
			}
		}
	} else {
			// Passed NULL for the name.
		just_host = true;
	}

	if( just_host ) {
		daemon_name = strnewp( my_full_hostname() );
	} else {
		size = strlen(tmpname) + strlen(my_full_hostname()) + 2;
		daemon_name = new char[size];
		sprintf( daemon_name, "%s@%s", tmpname, my_full_hostname() );
	}
	delete [] tmpname;
	return daemon_name;
}

/*
   Return a string on the heap (must be deallocated with delete()) that
   contains the default daemon name for the calling process.  If we're
   root (additionally, on UNIX, if we're condor), we default to the
   full hostname.  Otherwise, we default to username@full.hostname.
*/
char*
default_daemon_name( void )
{
	if( is_root() ) {
		return strnewp( my_full_hostname() );
	}
#ifndef WIN32
	if( getuid() == get_real_condor_uid() ) {
		return strnewp( my_full_hostname() );
	}
#endif /* ! LOSE32 */
	char* name = my_username();
	if( ! name ) {
		return NULL;
	}
	char* host = my_full_hostname();
	if( ! host ) {
		free( name );
		return NULL;
	}
	int size = strlen(name) + strlen(host) + 2;
	char* ans = new char[size];
	if( ! ans ) {
		free( name );
		return NULL;
	}
	sprintf( ans, "%s@%s", name, host );
	free(name);
	return ans;
}

} /* extern "C" */
<commit_msg>Change behavior of names ending in an @ sign to allow for multiple Schedds to report the same SCHEDD_NAME. This is critical for transparent Schedd fail-over.<commit_after>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * 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.
 *
 ***************************************************************/

//////////////////////////////////////////////////////////////////////
// Methods to manipulate and manage daemon names
//////////////////////////////////////////////////////////////////////

#include "condor_common.h"
#include "condor_config.h"
#include "condor_string.h"
#include "get_full_hostname.h"
#include "my_hostname.h"
#include "my_username.h"
#include "condor_uid.h"

extern "C" {

// Return the host portion of a daemon name string.  Either the name
// includes an "@" sign, in which case we return whatever is after it,
// or it doesn't, in which case we just return what we got passed.
const char*
get_host_part( const char* name )
{
	char const *tmp;
	if (name == NULL) return NULL;
	tmp = strrchr( name, '@' );
	if( tmp ) {
		return ++tmp;
	} else {
		return name;
	}
}

// Return a pointer to a newly allocated string that contains the
// valid daemon name that corresponds with the given name.  Basically,
// see if there's an '@'.  If so, resolve everything after it as a
// hostname.  If not, resolve what we were passed as a hostname.
// The string is allocated with strnewp() (or it's equivalent), so you
// should deallocate it with delete [].
char*
get_daemon_name( const char* name )
{
	char *tmp, *tmpname, *daemon_name = NULL;
	char *fullname = NULL;
	int size;

	dprintf( D_HOSTNAME, "Finding proper daemon name for \"%s\"\n",
			 name );

		// First, check for a '@' in the name.
	tmpname = strdup( name );
	tmp = strrchr( tmpname, '@' );
	if( tmp ) {
			// There's a '@'.
		*tmp = '\0';
		tmp++;
		if( *tmp ) {
				// There was something after the @, try to resolve it
				// as a full hostname:
			dprintf( D_HOSTNAME, "Daemon name has data after the '@', "
					 "trying to resolve \"%s\"\n", tmp );
			fullname = get_full_hostname( tmp );
		} else {
			dprintf( D_HOSTNAME, "Daemon name has no data after the '@', "
					 "we'll assume that's by design\n" );
			daemon_name = strnewp( name );
		}
		if( fullname ) {
			size = strlen(tmpname) + strlen(fullname) + 2;
			daemon_name = new char[size];
			sprintf( daemon_name, "%s@%s", tmpname, fullname );
			delete [] fullname;
		}
	} else {
			// There's no '@', just try to resolve the hostname.
		dprintf( D_HOSTNAME, "Daemon name contains no '@', treating as a "
				 "regular hostname\n" );
		daemon_name = get_full_hostname( tmpname );
	}
	free( tmpname );

		// If there was an error, this will still be NULL.
	if( daemon_name ) {
		dprintf( D_HOSTNAME, "Returning daemon name: \"%s\"\n", daemon_name );
	} else {
		dprintf( D_HOSTNAME, "Failed to construct daemon name, "
				 "returning NULL\n" );
	}
	return daemon_name;
}

// Given some name, create a valid name for ourself with our full
// hostname.  If the name contains an '@', strip off everything after
// it and append my_full_hostname().  If there's no '@', try to
// resolve what we have and see if it's my_full_hostname.  If so, use
// it, otherwise, use name@my_full_hostname().  We return the answer
// in a string which should be deallocated w/ delete [].
char*
build_valid_daemon_name( char* name )
{
	char *tmp, *tmpname = NULL, *daemon_name = NULL;
	int size;

		// This flag determines if we want to just return a copy of
		// my_full_hostname(), or if we want to append
		// "@my_full_hostname" to the name we were given.  The name we
		// were given might include an '@', in which case, we trim off
		// everything after the '@'.
	bool just_host = false;

	bool just_name = false;

	if( name && *name ) {
		tmpname = strnewp( name );
		tmp = strrchr( tmpname, '@' );
		if( tmp ) {
				// name we were passed has an '@', ignore everything
				// after (and including) the '@'.
			*tmp = '\0';

			just_name = true;
		} else {
				// no '@', see if what we have is our hostname
			if( (tmp = get_full_hostname(name)) ) {
				if( !strcmp(tmp, my_full_hostname()) ) {
						// Yup, so just the full hostname.
					just_host = true;
				}
				delete [] tmp;
			}
		}
	} else {
			// Passed NULL for the name.
		just_host = true;
	}

	if( just_host ) {
		daemon_name = strnewp( my_full_hostname() );
	} else {
		if( just_name ) {
			daemon_name = strnewp( name );
		} else {
			size = strlen(tmpname) + strlen(my_full_hostname()) + 2;
			daemon_name = new char[size];
			sprintf( daemon_name, "%s@%s", tmpname, my_full_hostname() );
		}
	}
	delete [] tmpname;
	return daemon_name;
}

/*
   Return a string on the heap (must be deallocated with delete()) that
   contains the default daemon name for the calling process.  If we're
   root (additionally, on UNIX, if we're condor), we default to the
   full hostname.  Otherwise, we default to username@full.hostname.
*/
char*
default_daemon_name( void )
{
	if( is_root() ) {
		return strnewp( my_full_hostname() );
	}
#ifndef WIN32
	if( getuid() == get_real_condor_uid() ) {
		return strnewp( my_full_hostname() );
	}
#endif /* ! LOSE32 */
	char* name = my_username();
	if( ! name ) {
		return NULL;
	}
	char* host = my_full_hostname();
	if( ! host ) {
		free( name );
		return NULL;
	}
	int size = strlen(name) + strlen(host) + 2;
	char* ans = new char[size];
	if( ! ans ) {
		free( name );
		return NULL;
	}
	sprintf( ans, "%s@%s", name, host );
	free(name);
	return ans;
}

} /* extern "C" */
<|endoftext|>


<commit_before>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * 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 "condor_common.h"
#include "condor_classad.h"
#include "user_proc.h"
#include "starter.h"
#include "condor_attributes.h"
#include "classad_helpers.h"
#include "sig_name.h"
#include "stream_handler.h"
#include "subsystem_info.h"

extern CStarter *Starter;

/* UserProc class implementation */

UserProc::~UserProc()
{
	if( name ) {
		free( name );
	}
}

void
UserProc::initialize( void )
{
	JobPid = -1;
	exit_status = -1;
	requested_exit = false;
	m_proc_exited = false;
	job_universe = 0;  // we'll fill in a real value if we can...
	if( JobAd ) {
		initKillSigs();
		if( JobAd->LookupInteger( ATTR_JOB_UNIVERSE, job_universe ) < 1 ) {
			job_universe = 0;
		}
	}
}

void
UserProc::initKillSigs( void )
{
	int sig;

	sig = findSoftKillSig( JobAd );
	if( sig >= 0 ) {
		soft_kill_sig = sig;
	} else {
		soft_kill_sig = SIGTERM;
	}

	sig = findRmKillSig( JobAd );
	if( sig >= 0 ) {
		rm_kill_sig = sig;
	} else {
		rm_kill_sig = SIGTERM;
	}

	sig = findHoldKillSig( JobAd );
	if( sig >= 0 ) {
		hold_kill_sig = sig;
	} else {
		hold_kill_sig = SIGTERM;
	}

	const char* tmp = signalName( soft_kill_sig );
	dprintf( D_FULLDEBUG, "%s KillSignal: %d (%s)\n",
			 name ? name : "Main job", soft_kill_sig,
			 tmp ? tmp : "Unknown" );

	tmp = signalName( rm_kill_sig );
	dprintf( D_FULLDEBUG, "%s RmKillSignal: %d (%s)\n",
			 name ? name : "Main job", rm_kill_sig,
			 tmp ? tmp : "Unknown" );

	tmp = signalName( hold_kill_sig );
	dprintf( D_FULLDEBUG, "%s HoldKillSignal: %d (%s)\n",
			 name ? name : "Main job", hold_kill_sig,
			 tmp ? tmp : "Unknown" );
}

bool
UserProc::JobReaper(int pid, int status)
{
	if (JobPid == pid) {
		m_proc_exited = true;
		exit_status = status;
		job_exit_time.getTime();
	}
	return m_proc_exited;
}

bool
UserProc::PublishUpdateAd( ClassAd* ad )
{
	char buf[256];

	if( JobPid >= 0 ) {
		sprintf( buf, "%s%s=%d", name ? name : "", ATTR_JOB_PID,
				 JobPid );
		ad->Insert( buf );
	}

	if( job_start_time.seconds() > 0 ) {
		sprintf( buf, "%s%s=%ld", name ? name : "", ATTR_JOB_START_DATE,
				 job_start_time.seconds() );
		ad->Insert( buf );
	}

	if (m_proc_exited) {

		if( job_exit_time.seconds() > 0 ) {
			sprintf( buf, "%s%s=%f", name ? name : "", ATTR_JOB_DURATION,
					 job_exit_time.difference(&job_start_time) );
			ad->Insert( buf );
		}

			/*
			  If we have the exit status, we want to parse it and set
			  some attributes which describe the status in a platform
			  independent way.  This way, we're sure we're analyzing
			  the status integer with the platform-specific macros
			  where it came from, instead of assuming that WIFEXITED()
			  and friends will work correctly on a status integer we
			  got back from a different platform.
			*/
		if( WIFSIGNALED(exit_status) ) {
			sprintf( buf, "%s%s = TRUE", name ? name : "",
					 ATTR_ON_EXIT_BY_SIGNAL );
			ad->Insert( buf );
			sprintf( buf, "%s%s = %d", name ? name : "",
					 ATTR_ON_EXIT_SIGNAL, WTERMSIG(exit_status) );
			ad->Insert( buf );
			sprintf( buf, "%s%s = \"died on %s\"",
					 name ? name : "", ATTR_EXIT_REASON,
					 daemonCore->GetExceptionString(WTERMSIG(exit_status)) );
			ad->Insert( buf );
		} else {
			sprintf( buf, "%s%s = FALSE", name ? name : "",
					 ATTR_ON_EXIT_BY_SIGNAL );
			ad->Insert( buf );
			sprintf( buf, "%s%s = %d", name ? name : "",
					 ATTR_ON_EXIT_CODE, WEXITSTATUS(exit_status) );
			ad->Insert( buf );
		}
	}
	return true;
}

void
UserProc::PublishToEnv( Env* proc_env )
{
	if (m_proc_exited) {
			// TODO: what should these really be called?  use
			// myDistro?  mySubSystem?  hard to say...
		MyString base;
		base = "_";
		base += myDistro->Get();
		base += '_';
		if( name ) {
			base += name;
		} else {
			base += "MAINJOB";
		}
		base += '_';
		base.upper_case();

		MyString env_name;

		if( WIFSIGNALED(exit_status) ) {
			env_name = base.GetCStr();
			env_name += "EXIT_SIGNAL";
			proc_env->SetEnv( env_name.GetCStr(), WTERMSIG(exit_status) );
		} else {
			env_name = base.GetCStr();
			env_name += "EXIT_CODE";
			proc_env->SetEnv( env_name.GetCStr(), WEXITSTATUS(exit_status) );
		}
	}
}

bool
UserProc::getStdFile( std_file_type type,
                      const char* attr,
                      bool allow_dash,
                      const char* log_header,
                      int* out_fd,
                      MyString* out_name)
{
		// we're going to return true on success, false on error.
		// if we succeed, then if we have an open FD that should
		// be passed down to the job, return it in the descriptor
		// argument. otherwise, return -1 in the descriptor
		// argument and return the name of the file that should
		// be opened for the child in the name argument
	ASSERT(out_fd != NULL);
	ASSERT(out_name != NULL);
	*out_fd = -1;

	const char* filename;
	bool wants_stream = false;
	const char* stream_name = NULL;
	const char* phrase = NULL;
	bool is_output = true;
	bool is_null_file = false;

		///////////////////////////////////////////////////////
		// Initialize some settings depending on the type
		///////////////////////////////////////////////////////

	switch( type ) {
	case SFT_IN:
		is_output = false;
		phrase = "standard input";
		stream_name = "stdin";
		break;
	case SFT_OUT:
		is_output = true;
		phrase = "standard output";
		stream_name = "stdout";
		break;
	case SFT_ERR:
		is_output = true;
		phrase = "standard error";
		stream_name = "stderr";
		break;
	}

		///////////////////////////////////////////////////////
		// Figure out what we're trying to open, if anything
		///////////////////////////////////////////////////////

	if( attr ) {
		filename = Starter->jic->getJobStdFile( attr );
		wants_stream = Starter->jic->streamStdFile( attr );
	} else {
		switch( type ) {
		case SFT_IN:
			filename = Starter->jic->jobInputFilename();
			wants_stream = Starter->jic->streamInput();
			break;
		case SFT_OUT:
			filename = Starter->jic->jobOutputFilename();
			wants_stream = Starter->jic->streamOutput();
			break;
		case SFT_ERR:
			filename = Starter->jic->jobErrorFilename();
			wants_stream = Starter->jic->streamError();
			break;
		}
	}

	if( ! filename ) {
			// If there's nothing specified, we always want to open
			// the system-appropriate NULL file (/dev/null or NUL).
			// Otherwise, we can mostly treat this as if the job
			// defined a real local filename.  For the few cases were
			// we have to behave differently, record it in a bool.
		filename = NULL_FILE;
		is_null_file = true;
	}

		///////////////////////////////////////////////////////
		// Deal with special cases
		///////////////////////////////////////////////////////

		//////////////////////
		// Use streaming I/O
		//////////////////////
	if( wants_stream && ! is_null_file ) {
		StreamHandler *handler = new StreamHandler;
		if( !handler->Init(filename, stream_name, is_output) ) {
			MyString err_msg;
			err_msg.sprintf( "unable to establish %s stream", phrase );
			Starter->jic->notifyStarterError( err_msg.Value(), true,
			    is_output ? CONDOR_HOLD_CODE_UnableToOpenOutputStream :
			                CONDOR_HOLD_CODE_UnableToOpenInputStream, 0 );
			return false;
		}
		*out_fd = handler->GetJobPipe();
		dprintf( D_ALWAYS, "%s: streaming from remote file %s\n",
				 log_header, filename );
		return true;
	}

		////////////////////////////////////
		// Use the starter's equivalent fd
		////////////////////////////////////
	if( allow_dash && (filename[0] == '-') && !filename[1] )
	{
			// use the starter's fd
		switch( type ) {
		case SFT_IN:
			*out_fd = Starter->starterStdinFd();
			dprintf( D_ALWAYS, "%s: using STDIN of %s\n", log_header,
					 mySubSystem->getName() );
			break;
		case SFT_OUT:
			*out_fd = Starter->starterStdoutFd();
			dprintf( D_ALWAYS, "%s: using STDOUT of %s\n", log_header,
					 mySubSystem->getName() );
			break;
		case SFT_ERR:
			*out_fd = Starter->starterStderrFd();
			dprintf( D_ALWAYS, "%s: using STDERR of %s\n", log_header,
					 mySubSystem->getName() );
			break;
		}
		return true;
	}

		///////////////////////////////////////////////////////
		// The regular case of a local file
		///////////////////////////////////////////////////////
	*out_name = filename;
	return true;
}

int
UserProc::openStdFile( std_file_type type,
                       const char* attr,
                       bool allow_dash,
                       const char* log_header)
{
		// most of the work gets done by our helper, getStdFile
	int fd;
	MyString filename;
	if (!getStdFile(type,
	                attr,
	                allow_dash,
	                log_header,
	                &fd,
	                &filename))
	{
		return -1;
	}

		// if getStdFile came back with an FD, just return it
	if (fd != -1) {
		return fd;
	}

		// otherwise, we need to perform an open on the name
		// we got back
	bool is_output = (type != SFT_IN);
	if( is_output ) {
		int flags = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND;
		fd = safe_open_wrapper( filename.Value(), flags, 0666 );
		if( fd < 0 ) {
				// if failed, try again without O_TRUNC
			flags &= ~O_TRUNC;
			fd = safe_open_wrapper( filename.Value(), flags, 0666 );
		}
	} else {
		fd = safe_open_wrapper( filename.Value(), O_RDONLY );
	}
	if( fd < 0 ) {
		int open_errno = errno;
		char const *errno_str = strerror( errno );
		MyString err_msg;
		const char* phrase;
		if (type == SFT_IN) {
			phrase = "standard input";
		}
		else if (type == SFT_OUT) {
			phrase = "standard output";
		}
		else {
			phrase = "standard error";
		}
		err_msg.sprintf( "Failed to open '%s' as %s: %s (errno %d)",
		                 filename.Value(),
		                 phrase,
		                 errno_str,
		                 errno );
		dprintf( D_ALWAYS, "%s\n", err_msg.Value() );
		Starter->jic->notifyStarterError( err_msg.Value(), true,
		  is_output ? CONDOR_HOLD_CODE_UnableToOpenOutput :
		              CONDOR_HOLD_CODE_UnableToOpenInput, open_errno );
		return -1;
	}
	dprintf( (filename == NULL_FILE) ? D_FULLDEBUG : D_ALWAYS,
	         "%s: %s\n", log_header,
	         filename.Value() );
	return fd;
}

<commit_msg>Added support for stdout/stderr to be >2G<commit_after>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * 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 "condor_common.h"
#include "condor_classad.h"
#include "user_proc.h"
#include "starter.h"
#include "condor_attributes.h"
#include "classad_helpers.h"
#include "sig_name.h"
#include "stream_handler.h"
#include "subsystem_info.h"

extern CStarter *Starter;

/* UserProc class implementation */

UserProc::~UserProc()
{
	if( name ) {
		free( name );
	}
}

void
UserProc::initialize( void )
{
	JobPid = -1;
	exit_status = -1;
	requested_exit = false;
	m_proc_exited = false;
	job_universe = 0;  // we'll fill in a real value if we can...
	if( JobAd ) {
		initKillSigs();
		if( JobAd->LookupInteger( ATTR_JOB_UNIVERSE, job_universe ) < 1 ) {
			job_universe = 0;
		}
	}
}

void
UserProc::initKillSigs( void )
{
	int sig;

	sig = findSoftKillSig( JobAd );
	if( sig >= 0 ) {
		soft_kill_sig = sig;
	} else {
		soft_kill_sig = SIGTERM;
	}

	sig = findRmKillSig( JobAd );
	if( sig >= 0 ) {
		rm_kill_sig = sig;
	} else {
		rm_kill_sig = SIGTERM;
	}

	sig = findHoldKillSig( JobAd );
	if( sig >= 0 ) {
		hold_kill_sig = sig;
	} else {
		hold_kill_sig = SIGTERM;
	}

	const char* tmp = signalName( soft_kill_sig );
	dprintf( D_FULLDEBUG, "%s KillSignal: %d (%s)\n",
			 name ? name : "Main job", soft_kill_sig,
			 tmp ? tmp : "Unknown" );

	tmp = signalName( rm_kill_sig );
	dprintf( D_FULLDEBUG, "%s RmKillSignal: %d (%s)\n",
			 name ? name : "Main job", rm_kill_sig,
			 tmp ? tmp : "Unknown" );

	tmp = signalName( hold_kill_sig );
	dprintf( D_FULLDEBUG, "%s HoldKillSignal: %d (%s)\n",
			 name ? name : "Main job", hold_kill_sig,
			 tmp ? tmp : "Unknown" );
}

bool
UserProc::JobReaper(int pid, int status)
{
	if (JobPid == pid) {
		m_proc_exited = true;
		exit_status = status;
		job_exit_time.getTime();
	}
	return m_proc_exited;
}

bool
UserProc::PublishUpdateAd( ClassAd* ad )
{
	char buf[256];

	if( JobPid >= 0 ) {
		sprintf( buf, "%s%s=%d", name ? name : "", ATTR_JOB_PID,
				 JobPid );
		ad->Insert( buf );
	}

	if( job_start_time.seconds() > 0 ) {
		sprintf( buf, "%s%s=%ld", name ? name : "", ATTR_JOB_START_DATE,
				 job_start_time.seconds() );
		ad->Insert( buf );
	}

	if (m_proc_exited) {

		if( job_exit_time.seconds() > 0 ) {
			sprintf( buf, "%s%s=%f", name ? name : "", ATTR_JOB_DURATION,
					 job_exit_time.difference(&job_start_time) );
			ad->Insert( buf );
		}

			/*
			  If we have the exit status, we want to parse it and set
			  some attributes which describe the status in a platform
			  independent way.  This way, we're sure we're analyzing
			  the status integer with the platform-specific macros
			  where it came from, instead of assuming that WIFEXITED()
			  and friends will work correctly on a status integer we
			  got back from a different platform.
			*/
		if( WIFSIGNALED(exit_status) ) {
			sprintf( buf, "%s%s = TRUE", name ? name : "",
					 ATTR_ON_EXIT_BY_SIGNAL );
			ad->Insert( buf );
			sprintf( buf, "%s%s = %d", name ? name : "",
					 ATTR_ON_EXIT_SIGNAL, WTERMSIG(exit_status) );
			ad->Insert( buf );
			sprintf( buf, "%s%s = \"died on %s\"",
					 name ? name : "", ATTR_EXIT_REASON,
					 daemonCore->GetExceptionString(WTERMSIG(exit_status)) );
			ad->Insert( buf );
		} else {
			sprintf( buf, "%s%s = FALSE", name ? name : "",
					 ATTR_ON_EXIT_BY_SIGNAL );
			ad->Insert( buf );
			sprintf( buf, "%s%s = %d", name ? name : "",
					 ATTR_ON_EXIT_CODE, WEXITSTATUS(exit_status) );
			ad->Insert( buf );
		}
	}
	return true;
}

void
UserProc::PublishToEnv( Env* proc_env )
{
	if (m_proc_exited) {
			// TODO: what should these really be called?  use
			// myDistro?  mySubSystem?  hard to say...
		MyString base;
		base = "_";
		base += myDistro->Get();
		base += '_';
		if( name ) {
			base += name;
		} else {
			base += "MAINJOB";
		}
		base += '_';
		base.upper_case();

		MyString env_name;

		if( WIFSIGNALED(exit_status) ) {
			env_name = base.GetCStr();
			env_name += "EXIT_SIGNAL";
			proc_env->SetEnv( env_name.GetCStr(), WTERMSIG(exit_status) );
		} else {
			env_name = base.GetCStr();
			env_name += "EXIT_CODE";
			proc_env->SetEnv( env_name.GetCStr(), WEXITSTATUS(exit_status) );
		}
	}
}

bool
UserProc::getStdFile( std_file_type type,
                      const char* attr,
                      bool allow_dash,
                      const char* log_header,
                      int* out_fd,
                      MyString* out_name)
{
		// we're going to return true on success, false on error.
		// if we succeed, then if we have an open FD that should
		// be passed down to the job, return it in the descriptor
		// argument. otherwise, return -1 in the descriptor
		// argument and return the name of the file that should
		// be opened for the child in the name argument
	ASSERT(out_fd != NULL);
	ASSERT(out_name != NULL);
	*out_fd = -1;

	const char* filename;
	bool wants_stream = false;
	const char* stream_name = NULL;
	const char* phrase = NULL;
	bool is_output = true;
	bool is_null_file = false;

		///////////////////////////////////////////////////////
		// Initialize some settings depending on the type
		///////////////////////////////////////////////////////

	switch( type ) {
	case SFT_IN:
		is_output = false;
		phrase = "standard input";
		stream_name = "stdin";
		break;
	case SFT_OUT:
		is_output = true;
		phrase = "standard output";
		stream_name = "stdout";
		break;
	case SFT_ERR:
		is_output = true;
		phrase = "standard error";
		stream_name = "stderr";
		break;
	}

		///////////////////////////////////////////////////////
		// Figure out what we're trying to open, if anything
		///////////////////////////////////////////////////////

	if( attr ) {
		filename = Starter->jic->getJobStdFile( attr );
		wants_stream = Starter->jic->streamStdFile( attr );
	} else {
		switch( type ) {
		case SFT_IN:
			filename = Starter->jic->jobInputFilename();
			wants_stream = Starter->jic->streamInput();
			break;
		case SFT_OUT:
			filename = Starter->jic->jobOutputFilename();
			wants_stream = Starter->jic->streamOutput();
			break;
		case SFT_ERR:
			filename = Starter->jic->jobErrorFilename();
			wants_stream = Starter->jic->streamError();
			break;
		}
	}

	if( ! filename ) {
			// If there's nothing specified, we always want to open
			// the system-appropriate NULL file (/dev/null or NUL).
			// Otherwise, we can mostly treat this as if the job
			// defined a real local filename.  For the few cases were
			// we have to behave differently, record it in a bool.
		filename = NULL_FILE;
		is_null_file = true;
	}

		///////////////////////////////////////////////////////
		// Deal with special cases
		///////////////////////////////////////////////////////

		//////////////////////
		// Use streaming I/O
		//////////////////////
	if( wants_stream && ! is_null_file ) {
		StreamHandler *handler = new StreamHandler;
		if( !handler->Init(filename, stream_name, is_output) ) {
			MyString err_msg;
			err_msg.sprintf( "unable to establish %s stream", phrase );
			Starter->jic->notifyStarterError( err_msg.Value(), true,
			    is_output ? CONDOR_HOLD_CODE_UnableToOpenOutputStream :
			                CONDOR_HOLD_CODE_UnableToOpenInputStream, 0 );
			return false;
		}
		*out_fd = handler->GetJobPipe();
		dprintf( D_ALWAYS, "%s: streaming from remote file %s\n",
				 log_header, filename );
		return true;
	}

		////////////////////////////////////
		// Use the starter's equivalent fd
		////////////////////////////////////
	if( allow_dash && (filename[0] == '-') && !filename[1] )
	{
			// use the starter's fd
		switch( type ) {
		case SFT_IN:
			*out_fd = Starter->starterStdinFd();
			dprintf( D_ALWAYS, "%s: using STDIN of %s\n", log_header,
					 mySubSystem->getName() );
			break;
		case SFT_OUT:
			*out_fd = Starter->starterStdoutFd();
			dprintf( D_ALWAYS, "%s: using STDOUT of %s\n", log_header,
					 mySubSystem->getName() );
			break;
		case SFT_ERR:
			*out_fd = Starter->starterStderrFd();
			dprintf( D_ALWAYS, "%s: using STDERR of %s\n", log_header,
					 mySubSystem->getName() );
			break;
		}
		return true;
	}

		///////////////////////////////////////////////////////
		// The regular case of a local file
		///////////////////////////////////////////////////////
	*out_name = filename;
	return true;
}

int
UserProc::openStdFile( std_file_type type,
                       const char* attr,
                       bool allow_dash,
                       const char* log_header)
{
		// most of the work gets done by our helper, getStdFile
	int fd;
	MyString filename;
	if (!getStdFile(type,
	                attr,
	                allow_dash,
	                log_header,
	                &fd,
	                &filename))
	{
		return -1;
	}

		// if getStdFile came back with an FD, just return it
	if (fd != -1) {
		return fd;
	}

		// otherwise, we need to perform an open on the name
		// we got back
	bool is_output = (type != SFT_IN);
	if( is_output ) {
		int flags = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND | O_LARGEFILE;
		fd = safe_open_wrapper( filename.Value(), flags, 0666 );
		if( fd < 0 ) {
				// if failed, try again without O_TRUNC
			flags &= ~O_TRUNC;
			fd = safe_open_wrapper( filename.Value(), flags, 0666 );
		}
	} else {
		fd = safe_open_wrapper( filename.Value(), O_RDONLY | O_LARGEFILE );
	}
	if( fd < 0 ) {
		int open_errno = errno;
		char const *errno_str = strerror( errno );
		MyString err_msg;
		const char* phrase;
		if (type == SFT_IN) {
			phrase = "standard input";
		}
		else if (type == SFT_OUT) {
			phrase = "standard output";
		}
		else {
			phrase = "standard error";
		}
		err_msg.sprintf( "Failed to open '%s' as %s: %s (errno %d)",
		                 filename.Value(),
		                 phrase,
		                 errno_str,
		                 errno );
		dprintf( D_ALWAYS, "%s\n", err_msg.Value() );
		Starter->jic->notifyStarterError( err_msg.Value(), true,
		  is_output ? CONDOR_HOLD_CODE_UnableToOpenOutput :
		              CONDOR_HOLD_CODE_UnableToOpenInput, open_errno );
		return -1;
	}
	dprintf( (filename == NULL_FILE) ? D_FULLDEBUG : D_ALWAYS,
	         "%s: %s\n", log_header,
	         filename.Value() );
	return fd;
}

<|endoftext|>


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

#include "flutter/lib/ui/compositing/scene_host.h"

#include <lib/fsl/handles/object_info.h>
#include <lib/ui/scenic/cpp/view_token_pair.h>
#include <lib/zx/eventpair.h>
#include <third_party/tonic/dart_args.h>
#include <third_party/tonic/dart_binding_macros.h>
#include <third_party/tonic/logging/dart_invoke.h>

#include "flutter/flow/export_node.h"
#include "flutter/flow/view_holder.h"
#include "flutter/fml/thread_local.h"
#include "flutter/lib/ui/ui_dart_state.h"

namespace {

using SceneHostBindings = std::unordered_map<zx_koid_t, SceneHost*>;

FML_THREAD_LOCAL fml::ThreadLocal tls_scene_host_bindings([](intptr_t value) {
  delete reinterpret_cast<SceneHostBindings*>(value);
});

void SceneHost_constructor(Dart_NativeArguments args) {
  tonic::DartCallConstructor(&SceneHost::Create, args);
}

void SceneHost_constructorViewHolderToken(Dart_NativeArguments args) {
  // This UI thread / Isolate contains at least 1 SceneHost.  Initialize the
  // per-Isolate bindings.
  if (tls_scene_host_bindings.Get() == 0) {
    tls_scene_host_bindings.Set(
        reinterpret_cast<intptr_t>(new SceneHostBindings()));
  }

  tonic::DartCallConstructor(&SceneHost::CreateViewHolder, args);
}

SceneHost* GetSceneHost(scenic::ResourceId id) {
  auto* bindings =
      reinterpret_cast<SceneHostBindings*>(tls_scene_host_bindings.Get());
  FML_DCHECK(bindings);

  auto binding = bindings->find(id);
  if (binding != bindings->end()) {
    return binding->second;
  }

  return nullptr;
}

void InvokeDartClosure(tonic::DartPersistentValue* closure) {
  if (closure) {
    std::shared_ptr<tonic::DartState> dart_state = closure->dart_state().lock();
    if (!dart_state) {
      return;
    }

    tonic::DartState::Scope scope(dart_state);
    tonic::DartInvoke(closure->value(), {});
  }
}

template <typename T>
void InvokeDartFunction(tonic::DartPersistentValue* function, T& arg) {
  if (function) {
    std::shared_ptr<tonic::DartState> dart_state =
        function->dart_state().lock();
    if (!dart_state) {
      return;
    }

    tonic::DartState::Scope scope(dart_state);
    tonic::DartInvoke(function->value(), {tonic::ToDart(arg)});
  }
}

}  // namespace

namespace flutter {

IMPLEMENT_WRAPPERTYPEINFO(ui, SceneHost);

#define FOR_EACH_BINDING(V) \
  V(SceneHost, dispose)     \
  V(SceneHost, setProperties)

FOR_EACH_BINDING(DART_NATIVE_CALLBACK)

void SceneHost::RegisterNatives(tonic::DartLibraryNatives* natives) {
  natives->Register({{"SceneHost_constructor", SceneHost_constructor, 2, true},
                     FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
  natives->Register({{"SceneHost_constructorViewHolderToken",
                      SceneHost_constructorViewHolderToken, 5, true},
                     FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
}

fml::RefPtr<SceneHost> SceneHost::Create(
    fml::RefPtr<zircon::dart::Handle> exportTokenHandle) {
  return fml::MakeRefCounted<SceneHost>(exportTokenHandle);
}

fml::RefPtr<SceneHost> SceneHost::CreateViewHolder(
    fml::RefPtr<zircon::dart::Handle> viewHolderTokenHandle,
    Dart_Handle viewConnectedCallback,
    Dart_Handle viewDisconnectedCallback,
    Dart_Handle viewStateChangedCallback) {
  return fml::MakeRefCounted<SceneHost>(
      viewHolderTokenHandle, viewConnectedCallback, viewDisconnectedCallback,
      viewStateChangedCallback);
}

SceneHost::SceneHost(fml::RefPtr<zircon::dart::Handle> exportTokenHandle)
    : gpu_task_runner_(
          UIDartState::Current()->GetTaskRunners().GetGPUTaskRunner()),
      id_(fsl::GetKoid(exportTokenHandle->handle())),
      use_view_holder_(false) {
  gpu_task_runner_->PostTask(
      [id = id_, handle = std::move(exportTokenHandle)]() {
        auto export_token = zx::eventpair(handle->ReleaseHandle());
        flow::ExportNode::Create(id, std::move(export_token));
      });
}

SceneHost::SceneHost(fml::RefPtr<zircon::dart::Handle> viewHolderTokenHandle,
                     Dart_Handle viewConnectedCallback,
                     Dart_Handle viewDisconnectedCallback,
                     Dart_Handle viewStateChangedCallback)
    : gpu_task_runner_(
          UIDartState::Current()->GetTaskRunners().GetGPUTaskRunner()),
      id_(fsl::GetKoid(viewHolderTokenHandle->handle())),
      use_view_holder_(true) {
  if (Dart_IsClosure(viewConnectedCallback)) {
    view_connected_callback_ = std::make_unique<tonic::DartPersistentValue>(
        UIDartState::Current(), viewConnectedCallback);
  }
  if (Dart_IsClosure(viewDisconnectedCallback)) {
    view_disconnected_callback_ = std::make_unique<tonic::DartPersistentValue>(
        UIDartState::Current(), viewDisconnectedCallback);
  }
  if (Dart_IsClosure(viewConnectedCallback)) {
    view_state_changed_callback_ = std::make_unique<tonic::DartPersistentValue>(
        UIDartState::Current(), viewStateChangedCallback);
  }

  auto bind_callback = [scene_host = this](scenic::ResourceId id) {
    auto* bindings =
        reinterpret_cast<SceneHostBindings*>(tls_scene_host_bindings.Get());
    FML_DCHECK(bindings);
    FML_DCHECK(bindings->find(id) == bindings->end());

    bindings->emplace(std::make_pair(id, scene_host));
  };

  auto ui_task_runner =
      UIDartState::Current()->GetTaskRunners().GetUITaskRunner();
  gpu_task_runner_->PostTask([id = id_,
                              ui_task_runner = std::move(ui_task_runner),
                              handle = std::move(viewHolderTokenHandle),
                              bind_callback = std::move(bind_callback)]() {
    auto view_holder_token =
        scenic::ToViewHolderToken(zx::eventpair(handle->ReleaseHandle()));
    flow::ViewHolder::Create(id, std::move(ui_task_runner),
                             std::move(view_holder_token),
                             std::move(bind_callback));
  });
}

SceneHost::~SceneHost() {
  if (use_view_holder_) {
    auto* bindings =
        reinterpret_cast<SceneHostBindings*>(tls_scene_host_bindings.Get());
    FML_DCHECK(bindings);
    bindings->erase(id_);

    gpu_task_runner_->PostTask([id = id_]() { flow::ViewHolder::Destroy(id); });
  } else {
    gpu_task_runner_->PostTask([id = id_]() { flow::ExportNode::Destroy(id); });
  }
}

void SceneHost::OnViewConnected(scenic::ResourceId id) {
  auto* scene_host = GetSceneHost(id);

  if (scene_host) {
    InvokeDartClosure(scene_host->view_connected_callback_.get());
  }
}

void SceneHost::OnViewDisconnected(scenic::ResourceId id) {
  auto* scene_host = GetSceneHost(id);

  if (scene_host) {
    InvokeDartClosure(scene_host->view_disconnected_callback_.get());
  }
}

void SceneHost::OnViewStateChanged(scenic::ResourceId id, bool state) {
  auto* scene_host = GetSceneHost(id);

  if (scene_host) {
    InvokeDartFunction(scene_host->view_state_changed_callback_.get(), state);
  }
}

void SceneHost::setProperties(double width,
                              double height,
                              double insetTop,
                              double insetRight,
                              double insetBottom,
                              double insetLeft,
                              bool focusable) {
  FML_DCHECK(use_view_holder_);

  gpu_task_runner_->PostTask([id = id_, width, height, insetTop, insetRight,
                              insetBottom, insetLeft, focusable]() {
    auto* view_holder = flow::ViewHolder::FromId(id);
    FML_DCHECK(view_holder);

    view_holder->SetProperties(width, height, insetTop, insetRight, insetBottom,
                               insetLeft, focusable);
  });
}

void SceneHost::dispose() {
  ClearDartWrapper();
}

}  // namespace flutter
<commit_msg>[fuchsia] Add flutter:: to scene_host.cc (#8549)<commit_after>// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/lib/ui/compositing/scene_host.h"

#include <lib/fsl/handles/object_info.h>
#include <lib/ui/scenic/cpp/view_token_pair.h>
#include <lib/zx/eventpair.h>
#include <third_party/tonic/dart_args.h>
#include <third_party/tonic/dart_binding_macros.h>
#include <third_party/tonic/logging/dart_invoke.h>

#include "flutter/flow/export_node.h"
#include "flutter/flow/view_holder.h"
#include "flutter/fml/thread_local.h"
#include "flutter/lib/ui/ui_dart_state.h"

namespace {

using SceneHostBindings = std::unordered_map<zx_koid_t, flutter::SceneHost*>;

FML_THREAD_LOCAL fml::ThreadLocal tls_scene_host_bindings([](intptr_t value) {
  delete reinterpret_cast<SceneHostBindings*>(value);
});

void SceneHost_constructor(Dart_NativeArguments args) {
  tonic::DartCallConstructor(&flutter::SceneHost::Create, args);
}

void SceneHost_constructorViewHolderToken(Dart_NativeArguments args) {
  // This UI thread / Isolate contains at least 1 SceneHost.  Initialize the
  // per-Isolate bindings.
  if (tls_scene_host_bindings.Get() == 0) {
    tls_scene_host_bindings.Set(
        reinterpret_cast<intptr_t>(new SceneHostBindings()));
  }

  tonic::DartCallConstructor(&flutter::SceneHost::CreateViewHolder, args);
}

flutter::SceneHost* GetSceneHost(scenic::ResourceId id) {
  auto* bindings =
      reinterpret_cast<SceneHostBindings*>(tls_scene_host_bindings.Get());
  FML_DCHECK(bindings);

  auto binding = bindings->find(id);
  if (binding != bindings->end()) {
    return binding->second;
  }

  return nullptr;
}

void InvokeDartClosure(tonic::DartPersistentValue* closure) {
  if (closure) {
    std::shared_ptr<tonic::DartState> dart_state = closure->dart_state().lock();
    if (!dart_state) {
      return;
    }

    tonic::DartState::Scope scope(dart_state);
    tonic::DartInvoke(closure->value(), {});
  }
}

template <typename T>
void InvokeDartFunction(tonic::DartPersistentValue* function, T& arg) {
  if (function) {
    std::shared_ptr<tonic::DartState> dart_state =
        function->dart_state().lock();
    if (!dart_state) {
      return;
    }

    tonic::DartState::Scope scope(dart_state);
    tonic::DartInvoke(function->value(), {tonic::ToDart(arg)});
  }
}

}  // namespace

namespace flutter {

IMPLEMENT_WRAPPERTYPEINFO(ui, SceneHost);

#define FOR_EACH_BINDING(V) \
  V(SceneHost, dispose)     \
  V(SceneHost, setProperties)

FOR_EACH_BINDING(DART_NATIVE_CALLBACK)

void SceneHost::RegisterNatives(tonic::DartLibraryNatives* natives) {
  natives->Register({{"SceneHost_constructor", SceneHost_constructor, 2, true},
                     FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
  natives->Register({{"SceneHost_constructorViewHolderToken",
                      SceneHost_constructorViewHolderToken, 5, true},
                     FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
}

fml::RefPtr<SceneHost> SceneHost::Create(
    fml::RefPtr<zircon::dart::Handle> exportTokenHandle) {
  return fml::MakeRefCounted<SceneHost>(exportTokenHandle);
}

fml::RefPtr<SceneHost> SceneHost::CreateViewHolder(
    fml::RefPtr<zircon::dart::Handle> viewHolderTokenHandle,
    Dart_Handle viewConnectedCallback,
    Dart_Handle viewDisconnectedCallback,
    Dart_Handle viewStateChangedCallback) {
  return fml::MakeRefCounted<SceneHost>(
      viewHolderTokenHandle, viewConnectedCallback, viewDisconnectedCallback,
      viewStateChangedCallback);
}

SceneHost::SceneHost(fml::RefPtr<zircon::dart::Handle> exportTokenHandle)
    : gpu_task_runner_(
          UIDartState::Current()->GetTaskRunners().GetGPUTaskRunner()),
      id_(fsl::GetKoid(exportTokenHandle->handle())),
      use_view_holder_(false) {
  gpu_task_runner_->PostTask(
      [id = id_, handle = std::move(exportTokenHandle)]() {
        auto export_token = zx::eventpair(handle->ReleaseHandle());
        flow::ExportNode::Create(id, std::move(export_token));
      });
}

SceneHost::SceneHost(fml::RefPtr<zircon::dart::Handle> viewHolderTokenHandle,
                     Dart_Handle viewConnectedCallback,
                     Dart_Handle viewDisconnectedCallback,
                     Dart_Handle viewStateChangedCallback)
    : gpu_task_runner_(
          UIDartState::Current()->GetTaskRunners().GetGPUTaskRunner()),
      id_(fsl::GetKoid(viewHolderTokenHandle->handle())),
      use_view_holder_(true) {
  if (Dart_IsClosure(viewConnectedCallback)) {
    view_connected_callback_ = std::make_unique<tonic::DartPersistentValue>(
        UIDartState::Current(), viewConnectedCallback);
  }
  if (Dart_IsClosure(viewDisconnectedCallback)) {
    view_disconnected_callback_ = std::make_unique<tonic::DartPersistentValue>(
        UIDartState::Current(), viewDisconnectedCallback);
  }
  if (Dart_IsClosure(viewConnectedCallback)) {
    view_state_changed_callback_ = std::make_unique<tonic::DartPersistentValue>(
        UIDartState::Current(), viewStateChangedCallback);
  }

  auto bind_callback = [scene_host = this](scenic::ResourceId id) {
    auto* bindings =
        reinterpret_cast<SceneHostBindings*>(tls_scene_host_bindings.Get());
    FML_DCHECK(bindings);
    FML_DCHECK(bindings->find(id) == bindings->end());

    bindings->emplace(std::make_pair(id, scene_host));
  };

  auto ui_task_runner =
      UIDartState::Current()->GetTaskRunners().GetUITaskRunner();
  gpu_task_runner_->PostTask([id = id_,
                              ui_task_runner = std::move(ui_task_runner),
                              handle = std::move(viewHolderTokenHandle),
                              bind_callback = std::move(bind_callback)]() {
    auto view_holder_token =
        scenic::ToViewHolderToken(zx::eventpair(handle->ReleaseHandle()));
    flow::ViewHolder::Create(id, std::move(ui_task_runner),
                             std::move(view_holder_token),
                             std::move(bind_callback));
  });
}

SceneHost::~SceneHost() {
  if (use_view_holder_) {
    auto* bindings =
        reinterpret_cast<SceneHostBindings*>(tls_scene_host_bindings.Get());
    FML_DCHECK(bindings);
    bindings->erase(id_);

    gpu_task_runner_->PostTask([id = id_]() { flow::ViewHolder::Destroy(id); });
  } else {
    gpu_task_runner_->PostTask([id = id_]() { flow::ExportNode::Destroy(id); });
  }
}

void SceneHost::OnViewConnected(scenic::ResourceId id) {
  auto* scene_host = GetSceneHost(id);

  if (scene_host) {
    InvokeDartClosure(scene_host->view_connected_callback_.get());
  }
}

void SceneHost::OnViewDisconnected(scenic::ResourceId id) {
  auto* scene_host = GetSceneHost(id);

  if (scene_host) {
    InvokeDartClosure(scene_host->view_disconnected_callback_.get());
  }
}

void SceneHost::OnViewStateChanged(scenic::ResourceId id, bool state) {
  auto* scene_host = GetSceneHost(id);

  if (scene_host) {
    InvokeDartFunction(scene_host->view_state_changed_callback_.get(), state);
  }
}

void SceneHost::setProperties(double width,
                              double height,
                              double insetTop,
                              double insetRight,
                              double insetBottom,
                              double insetLeft,
                              bool focusable) {
  FML_DCHECK(use_view_holder_);

  gpu_task_runner_->PostTask([id = id_, width, height, insetTop, insetRight,
                              insetBottom, insetLeft, focusable]() {
    auto* view_holder = flow::ViewHolder::FromId(id);
    FML_DCHECK(view_holder);

    view_holder->SetProperties(width, height, insetTop, insetRight, insetBottom,
                               insetLeft, focusable);
  });
}

void SceneHost::dispose() {
  ClearDartWrapper();
}

}  // namespace flutter
<|endoftext|>