<commit_before>/**
   \file undistort.cc

   Apply Lensfun corrections to a PNM file in place.  This means, the original
   file is overwritten.  The command line parameters are:
   - path to the PNM file
   - x coordinate of top left corner
   - y coordinate of top left corner
   - x coordinate of top right corner
   - y coordinate of top right corner
   - x coordinate of bottom left corner
   - y coordinate of bottom left corner
   - x coordinate of bottom right corner
   - y coordinate of bottom right corner

   All coordinates are pixel coordinates, with the top left of the image the
   origin.  The corners must be the corners of a perfect rectangle which was
   taken a picture of, e.g. a sheet of paper.  These are used for the
   perspective correction as well as the rotation, so that the edges of the
   rectangle are parellel to the image borders.

   The program returns the position and the dimensions of the rectangle in
   the output image to stdout in JSON format:

   \code{.json}
   [x₀, y₀, width, height]
   \endcode

   Here, x₀ and y₀ are the coordinates of the top left corner, and width and
   height are the dimensions of the rectangle.

   This program does not apply colour corrections such as vignetting
   correction, as those are handled by kamscan.py using flat field images.
*/
#include <fstream>
#include <vector>
#include <iterator>
#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#include "lensfun.h"

/** Class for bitmap data.

  In case of 2 bytes per channel, network byte order is assumed. */
class Image {
public:
    Image(int width, int height, int channel_size, int channels);
    Image() {};
    Image(const Image &image);
    /** Get the channel intensity at a certian coordinate.
      \param x x coordinate
      \param y y coordinate
      \param channel index of the channel (for greyscale, it is always zero;
        for RGB, it is 0, 1, or 2)
      \return raw integer value of the intensity of this channel at this
        position
    */
    int get(int x, int y, int channel);
    /** Get the channel intensity at a certian coordinate.  The coordinates are
      floats and may contain fractions.  In this case, the intensity is
      calculated using bilinear interpolation between the four pixels around
      this coordinate.
      \param x x coordinate
      \param y y coordinate
      \param channel index of the channel (for greyscale, it is always zero;
        for RGB, it is 0, 1, or 2)
      \return raw integer value of the intensity of this channel at this
        position
    */
    int get(float x, float y, int channel);
    /** Set the channel intensity at a certian coordinate.
      \param x x coordinate
      \param y y coordinate
      \param channel index of the channel (for greyscale, it is always zero;
        for RGB, it is 0, 1, or 2)
      \param value raw integer value of the intensity of this channel at this
        position
    */
    void set(int x, int y, int channel, int value);
    /** Determine the channel descriptions.  This is used by Lensfun internally
      and necessary if you want to apply colour corrections, e.g. vignetting
      correction.
      \return the components of each pixel
    */
    int components();
    /** Determine the pixel format à la Lensfun.  It is derived from
      channel_size.
      \return the pixel format as it is needed by Lensfun
     */
    lfPixelFormat pixel_format();
    int width, height; ///< width and height of the image in pixels
    int channels; ///< number of channels; may be 1 (greyscale) or 3 (RGB)
    /** the raw data (1:1 dump of the PNM content, without header)
     */
    std::vector<unsigned char> data;

private:
    friend std::istream& operator >>(std::istream &inputStream, Image &other);
    friend std::ostream& operator <<(std::ostream &outputStream, const Image &other);
    int channel_size; ///< width of one channel in bytes; may be 1 or 2
};

Image::Image(int width, int height, int channel_size, int channels) :
    width(width), height(height), channel_size(channel_size), channels(channels)
{
    data.resize(width * height * channel_size * channels);
}

Image::Image(const Image &image) :
    width(image.width), height(image.height), channel_size(image.channel_size), channels(image.channels) {
}

int Image::get(int x, int y, int channel) {
    if (x < 0 || x >= width || y < 0 || y >= height)
        return 0;
    int position = channel_size * (channels * (y * width + x) + channel);
    int result = static_cast<int>(data[position]);
    if (channel_size == 2)
        result = (result << 8) + static_cast<int>(data[position + 1]);
    return result;
}

int Image::get(float x, float y, int channel) {
    float dummy;
    int x0 = static_cast<int>(x);
    int y0 = static_cast<int>(y);
    float i0 = static_cast<float>(get(x0, y0, channel));
    float i1 = static_cast<float>(get(x0 + 1, y0, channel));
    float i2 = static_cast<float>(get(x0, y0 + 1, channel));
    float i3 = static_cast<float>(get(x0 + 1, y0 + 1, channel));
    float fraction_x = std::modf(x, &dummy);
    float i01 = (1 - fraction_x) * i0 + fraction_x * i1;
    float i23 = (1 - fraction_x) * i2 + fraction_x * i3;
    float fraction_y = std::modf(y, &dummy);
    return static_cast<int>(std::round((1 - fraction_y) * i01 + fraction_y * i23));
}

void Image::set(int x, int y, int channel, int value) {
    if (x >= 0 && x < width && y >= 0 && y < height) {
        int position = channel_size * (channels * (y * width + x) + channel);
        if (channel_size == 1)
            data[position] = static_cast<unsigned char>(value);
        else if (channel_size == 2) {
            data[position] = static_cast<unsigned char>(value >> 8);
            data[position + 1] = static_cast<unsigned char>(value & 256);
        }
    }
}

int Image::components() {
    switch (channels) {
    case 1:
        return LF_CR_1(INTENSITY);
    case 3:
        return LF_CR_3(RED, GREEN, BLUE);
    default:
        throw std::runtime_error("Invalid value of 'channels'.");
    }
}

lfPixelFormat Image::pixel_format() {
    switch (channel_size) {
    case 1:
        return LF_PF_U8;
    case 2:
        return LF_PF_U16;
    default:
        throw std::runtime_error("Invalid value of 'channel_size'.");
    }
}

std::istream& operator >>(std::istream &inputStream, Image &other)
{
    std::string magic_number;
    int maximum_color_value;
    inputStream >> magic_number;
    if (magic_number == "P5")
        other.channels = 1;
    else if (magic_number == "P6")
        other.channels = 3;
    else
        throw std::runtime_error("Invalid input file.  Must start with 'P5' or 'P6'.");
    inputStream >> other.width >> other.height >> maximum_color_value;
    inputStream.get(); // skip the trailing white space
    switch (maximum_color_value) {
    case 255:
        other.channel_size = 1;
        break;
    case 65535:
        other.channel_size = 2;
        break;
    default:
        throw std::runtime_error("Invalid PPM file: Maximum color value must be 255 or 65535.");
    }
    size_t size = other.width * other.height * other.channel_size * other.channels;
    other.data.resize(size);
    inputStream.read(reinterpret_cast<char*>(other.data.data()), size);
    return inputStream;
}

std::ostream& operator <<(std::ostream &outputStream, const Image &other)
{
    outputStream << (other.channels == 3 ? "P6" : "P5") << "\n"
                 << other.width << " "
                 << other.height << "\n"
                 << (other.channel_size == 1 ? "255" : "65535") << "\n";
    outputStream.write(reinterpret_cast<const char*>(other.data.data()), other.data.size());
    return outputStream;
}

int main(int argc, char* argv[]) {
    if (argc != 10) {
        std::cerr << "You must give path to input file as well as all four corner coordinates.\n";
        return -1;
    }

    lfDatabase ldb;

    if (ldb.Load() != LF_NO_ERROR) {
        std::cerr << "Database could not be loaded\n";
        return -1;
    }

    const lfCamera *camera;
    const lfCamera **cameras = ldb.FindCamerasExt(NULL, "NEX-7");
    if (cameras && !cameras[1])
        camera = cameras[0];
    else {
        std::cerr << "Cannot find unique camera in database.  " << sizeof(cameras) << " cameras found.\n";
        lf_free(cameras);
        return -1;
    }
    lf_free(cameras);

    const lfLens *lens;
    const lfLens **lenses = ldb.FindLenses(camera, NULL, "E 50mm f/1.8 OSS (kamscan)");
    if (lenses && !lenses[1]) {
        lens = lenses[0];
    } else if (!lenses) {
        std::cerr << "Cannot find lens in database\n";
        lf_free(lenses);
        return -1;
    } else {
        std::cerr << "Lens name ambiguous\n";
    }
    lf_free(lenses);

    Image image;
    {
        std::ifstream file(argv[1], std::ios::binary);
        file >> image;
    }

    lfModifier modifier(camera->CropFactor, image.width, image.height, image.pixel_format());
    lfModifier pc_coord_modifier(camera->CropFactor, image.width, image.height, image.pixel_format(), true);
    lfModifier back_modifier(camera->CropFactor, image.width, image.height, image.pixel_format(), true);
    if (!modifier.EnableDistortionCorrection(lens, 50) || !back_modifier.EnableDistortionCorrection(lens, 50) ||
        !pc_coord_modifier.EnableDistortionCorrection(lens, 50)) {
        std::cerr << "Failed to activate undistortion\n";
        return -1;
    }
    if (image.channels == 3)
        if (!modifier.EnableTCACorrection(lens, 50)) {
            std::cerr << "Failed to activate un-TCA\n";
            return -1;
        }
    std::vector<float> x, y;
    x.push_back(std::stof(argv[2]));
    y.push_back(std::stof(argv[3]));

    x.push_back(std::stof(argv[6]));
    y.push_back(std::stof(argv[7]));

    x.push_back(std::stof(argv[4]));
    y.push_back(std::stof(argv[5]));

    x.push_back(std::stof(argv[8]));
    y.push_back(std::stof(argv[9]));

    x.push_back(std::stof(argv[2]));
    y.push_back(std::stof(argv[3]));

    x.push_back(std::stof(argv[4]));
    y.push_back(std::stof(argv[5]));
    std::vector<float> x_undist, y_undist;
    for (int i = 0; i < x.size(); i++) {
        float result[2];
        pc_coord_modifier.ApplyGeometryDistortion(x[i], y[i], 1, 1, result);
        x_undist.push_back(result[0]);
        y_undist.push_back(result[1]);
    }
    if (!modifier.EnablePerspectiveCorrection(lens, 50, x_undist.data(), y_undist.data(), 6, 0) ||
        !back_modifier.EnablePerspectiveCorrection(lens, 50, x_undist.data(), y_undist.data(), 6, 0)) {
        std::cerr << "Failed to activate perspective correction\n";
        return -1;
    }

    std::vector<float> res(image.width * image.height * 2 * image.channels);
    if (image.channels == 3)
        modifier.ApplySubpixelGeometryDistortion(0, 0, image.width, image.height, res.data());
    else
        modifier.ApplyGeometryDistortion(0, 0, image.width, image.height, res.data());
    Image new_image = image;
    for (int x = 0; x < image.width; x++)
        for (int y = 0; y < image.height; y++) {
            int position = 2 * image.channels * (y * image.width + x);
            float source_x_R = res[position];
            float source_y_R = res[position + 1];
            new_image.set(x, y, 0, image.get(source_x_R, source_y_R, 0));
            if (image.channels == 3) {
                float source_x_G = res[position + 2];
                float source_y_G = res[position + 3];
                float source_x_B = res[position + 4];
                float source_y_B = res[position + 5];
                new_image.set(x, y, 1, image.get(source_x_G, source_y_G, 1));
                new_image.set(x, y, 2, image.get(source_x_B, source_y_B, 2));
            }
        }
    std::ofstream file(argv[1], std::ios::binary);
    file << new_image;

    for (int i = 0; i < 4; i++) {
        float result[2];
        back_modifier.ApplyGeometryDistortion(x[i], y[i], 1, 1, result);
        x[i] = result[0];
        y[i] = result[1];
    }
    std::cout << "[" << std::min(x[0], x[2]) << ", " << std::min(y[0], y[1]) <<
        ", " << std::max(x[1], x[3]) - std::min(x[0], x[2]) << ", " << std::max(y[2], y[3]) - std::min(y[0], y[1]) << "]\n";

    return 0;
}
<commit_msg>Improved source code layout.<commit_after>/**
   \file undistort.cc

   Apply Lensfun corrections to a PNM file in place.  This means, the original
   file is overwritten.  The command line parameters are:
   - path to the PNM file
   - x coordinate of top left corner
   - y coordinate of top left corner
   - x coordinate of top right corner
   - y coordinate of top right corner
   - x coordinate of bottom left corner
   - y coordinate of bottom left corner
   - x coordinate of bottom right corner
   - y coordinate of bottom right corner

   All coordinates are pixel coordinates, with the top left of the image the
   origin.  The corners must be the corners of a perfect rectangle which was
   taken a picture of, e.g. a sheet of paper.  These are used for the
   perspective correction as well as the rotation, so that the edges of the
   rectangle are parellel to the image borders.

   The program returns the position and the dimensions of the rectangle in
   the output image to stdout in JSON format:

   \code{.json}
   [x₀, y₀, width, height]
   \endcode

   Here, x₀ and y₀ are the coordinates of the top left corner, and width and
   height are the dimensions of the rectangle.

   This program does not apply colour corrections such as vignetting
   correction, as those are handled by kamscan.py using flat field images.
*/
#include <fstream>
#include <vector>
#include <iterator>
#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#include "lensfun.h"

/** Class for bitmap data.

  In case of 2 bytes per channel, network byte order is assumed. */
class Image {
public:
    Image(int width, int height, int channel_size, int channels);
    Image() {};
    Image(const Image &image);
    /** Get the channel intensity at a certian coordinate.
      \param x x coordinate
      \param y y coordinate
      \param channel index of the channel (for greyscale, it is always zero;
        for RGB, it is 0, 1, or 2)
      \return raw integer value of the intensity of this channel at this
        position
    */
    int get(int x, int y, int channel);
    /** Get the channel intensity at a certian coordinate.  The coordinates are
      floats and may contain fractions.  In this case, the intensity is
      calculated using bilinear interpolation between the four pixels around
      this coordinate.
      \param x x coordinate
      \param y y coordinate
      \param channel index of the channel (for greyscale, it is always zero;
        for RGB, it is 0, 1, or 2)
      \return raw integer value of the intensity of this channel at this
        position
    */
    int get(float x, float y, int channel);
    /** Set the channel intensity at a certian coordinate.
      \param x x coordinate
      \param y y coordinate
      \param channel index of the channel (for greyscale, it is always zero;
        for RGB, it is 0, 1, or 2)
      \param value raw integer value of the intensity of this channel at this
        position
    */
    void set(int x, int y, int channel, int value);
    /** Determine the channel descriptions.  This is used by Lensfun internally
      and necessary if you want to apply colour corrections, e.g. vignetting
      correction.
      \return the components of each pixel
    */
    int components();
    /** Determine the pixel format à la Lensfun.  It is derived from
      channel_size.
      \return the pixel format as it is needed by Lensfun
     */
    lfPixelFormat pixel_format();
    int width, height; ///< width and height of the image in pixels
    int channels; ///< number of channels; may be 1 (greyscale) or 3 (RGB)
    /** the raw data (1:1 dump of the PNM content, without header)
     */
    std::vector<unsigned char> data;

private:
    friend std::istream& operator>>(std::istream &inputStream, Image &other);
    friend std::ostream& operator<<(std::ostream &outputStream, const Image &other);
    int channel_size; ///< width of one channel in bytes; may be 1 or 2
};

Image::Image(int width, int height, int channel_size, int channels) :
    width(width), height(height), channel_size(channel_size), channels(channels)
{
    data.resize(width * height * channel_size * channels);
}

Image::Image(const Image &image) :
    width(image.width), height(image.height), channel_size(image.channel_size), channels(image.channels) {
}

int Image::get(int x, int y, int channel) {
    if (x < 0 || x >= width || y < 0 || y >= height)
        return 0;
    int position = channel_size * (channels * (y * width + x) + channel);
    int result = static_cast<int>(data[position]);
    if (channel_size == 2)
        result = (result << 8) + static_cast<int>(data[position + 1]);
    return result;
}

int Image::get(float x, float y, int channel) {
    float dummy;
    int x0 = static_cast<int>(x);
    int y0 = static_cast<int>(y);
    float i0 = static_cast<float>(get(x0, y0, channel));
    float i1 = static_cast<float>(get(x0 + 1, y0, channel));
    float i2 = static_cast<float>(get(x0, y0 + 1, channel));
    float i3 = static_cast<float>(get(x0 + 1, y0 + 1, channel));
    float fraction_x = std::modf(x, &dummy);
    float i01 = (1 - fraction_x) * i0 + fraction_x * i1;
    float i23 = (1 - fraction_x) * i2 + fraction_x * i3;
    float fraction_y = std::modf(y, &dummy);
    return static_cast<int>(std::round((1 - fraction_y) * i01 + fraction_y * i23));
}

void Image::set(int x, int y, int channel, int value) {
    if (x >= 0 && x < width && y >= 0 && y < height) {
        int position = channel_size * (channels * (y * width + x) + channel);
        if (channel_size == 1)
            data[position] = static_cast<unsigned char>(value);
        else if (channel_size == 2) {
            data[position] = static_cast<unsigned char>(value >> 8);
            data[position + 1] = static_cast<unsigned char>(value & 256);
        }
    }
}

int Image::components() {
    switch (channels) {
    case 1:
        return LF_CR_1(INTENSITY);
    case 3:
        return LF_CR_3(RED, GREEN, BLUE);
    default:
        throw std::runtime_error("Invalid value of 'channels'.");
    }
}

lfPixelFormat Image::pixel_format() {
    switch (channel_size) {
    case 1:
        return LF_PF_U8;
    case 2:
        return LF_PF_U16;
    default:
        throw std::runtime_error("Invalid value of 'channel_size'.");
    }
}

std::istream& operator>>(std::istream &inputStream, Image &other)
{
    std::string magic_number;
    int maximum_color_value;
    inputStream >> magic_number;
    if (magic_number == "P5")
        other.channels = 1;
    else if (magic_number == "P6")
        other.channels = 3;
    else
        throw std::runtime_error("Invalid input file.  Must start with 'P5' or 'P6'.");
    inputStream >> other.width >> other.height >> maximum_color_value;
    inputStream.get(); // skip the trailing white space
    switch (maximum_color_value) {
    case 255:
        other.channel_size = 1;
        break;
    case 65535:
        other.channel_size = 2;
        break;
    default:
        throw std::runtime_error("Invalid PPM file: Maximum color value must be 255 or 65535.");
    }
    size_t size = other.width * other.height * other.channel_size * other.channels;
    other.data.resize(size);
    inputStream.read(reinterpret_cast<char*>(other.data.data()), size);
    return inputStream;
}

std::ostream& operator<<(std::ostream &outputStream, const Image &other)
{
    outputStream << (other.channels == 3 ? "P6" : "P5") << "\n"
                 << other.width << " "
                 << other.height << "\n"
                 << (other.channel_size == 1 ? "255" : "65535") << "\n";
    outputStream.write(reinterpret_cast<const char*>(other.data.data()), other.data.size());
    return outputStream;
}

int main(int argc, char* argv[]) {
    if (argc != 10) {
        std::cerr << "You must give path to input file as well as all four corner coordinates.\n";
        return -1;
    }

    lfDatabase ldb;

    if (ldb.Load() != LF_NO_ERROR) {
        std::cerr << "Database could not be loaded\n";
        return -1;
    }

    const lfCamera *camera;
    const lfCamera **cameras = ldb.FindCamerasExt(NULL, "NEX-7");
    if (cameras && !cameras[1])
        camera = cameras[0];
    else {
        std::cerr << "Cannot find unique camera in database.  " << sizeof(cameras) << " cameras found.\n";
        lf_free(cameras);
        return -1;
    }
    lf_free(cameras);

    const lfLens *lens;
    const lfLens **lenses = ldb.FindLenses(camera, NULL, "E 50mm f/1.8 OSS (kamscan)");
    if (lenses && !lenses[1]) {
        lens = lenses[0];
    } else if (!lenses) {
        std::cerr << "Cannot find lens in database\n";
        lf_free(lenses);
        return -1;
    } else {
        std::cerr << "Lens name ambiguous\n";
    }
    lf_free(lenses);

    Image image;
    {
        std::ifstream file(argv[1], std::ios::binary);
        file >> image;
    }

    lfModifier modifier(camera->CropFactor, image.width, image.height, image.pixel_format());
    lfModifier pc_coord_modifier(camera->CropFactor, image.width, image.height, image.pixel_format(), true);
    lfModifier back_modifier(camera->CropFactor, image.width, image.height, image.pixel_format(), true);
    if (!modifier.EnableDistortionCorrection(lens, 50) || !back_modifier.EnableDistortionCorrection(lens, 50) ||
        !pc_coord_modifier.EnableDistortionCorrection(lens, 50)) {
        std::cerr << "Failed to activate undistortion\n";
        return -1;
    }
    if (image.channels == 3)
        if (!modifier.EnableTCACorrection(lens, 50)) {
            std::cerr << "Failed to activate un-TCA\n";
            return -1;
        }
    std::vector<float> x, y;
    x.push_back(std::stof(argv[2]));
    y.push_back(std::stof(argv[3]));

    x.push_back(std::stof(argv[6]));
    y.push_back(std::stof(argv[7]));

    x.push_back(std::stof(argv[4]));
    y.push_back(std::stof(argv[5]));

    x.push_back(std::stof(argv[8]));
    y.push_back(std::stof(argv[9]));

    x.push_back(std::stof(argv[2]));
    y.push_back(std::stof(argv[3]));

    x.push_back(std::stof(argv[4]));
    y.push_back(std::stof(argv[5]));
    std::vector<float> x_undist, y_undist;
    for (int i = 0; i < x.size(); i++) {
        float result[2];
        pc_coord_modifier.ApplyGeometryDistortion(x[i], y[i], 1, 1, result);
        x_undist.push_back(result[0]);
        y_undist.push_back(result[1]);
    }
    if (!modifier.EnablePerspectiveCorrection(lens, 50, x_undist.data(), y_undist.data(), 6, 0) ||
        !back_modifier.EnablePerspectiveCorrection(lens, 50, x_undist.data(), y_undist.data(), 6, 0)) {
        std::cerr << "Failed to activate perspective correction\n";
        return -1;
    }

    std::vector<float> res(image.width * image.height * 2 * image.channels);
    if (image.channels == 3)
        modifier.ApplySubpixelGeometryDistortion(0, 0, image.width, image.height, res.data());
    else
        modifier.ApplyGeometryDistortion(0, 0, image.width, image.height, res.data());
    Image new_image = image;
    for (int x = 0; x < image.width; x++)
        for (int y = 0; y < image.height; y++) {
            int position = 2 * image.channels * (y * image.width + x);
            float source_x_R = res[position];
            float source_y_R = res[position + 1];
            new_image.set(x, y, 0, image.get(source_x_R, source_y_R, 0));
            if (image.channels == 3) {
                float source_x_G = res[position + 2];
                float source_y_G = res[position + 3];
                float source_x_B = res[position + 4];
                float source_y_B = res[position + 5];
                new_image.set(x, y, 1, image.get(source_x_G, source_y_G, 1));
                new_image.set(x, y, 2, image.get(source_x_B, source_y_B, 2));
            }
        }
    std::ofstream file(argv[1], std::ios::binary);
    file << new_image;

    for (int i = 0; i < 4; i++) {
        float result[2];
        back_modifier.ApplyGeometryDistortion(x[i], y[i], 1, 1, result);
        x[i] = result[0];
        y[i] = result[1];
    }
    std::cout << "[" << std::min(x[0], x[2]) << ", " << std::min(y[0], y[1]) <<
        ", " << std::max(x[1], x[3]) - std::min(x[0], x[2]) << ", " << std::max(y[2], y[3]) - std::min(y[0], y[1]) << "]\n";

    return 0;
}
<|endoftext|>


<commit_before>#include <silicium/http/receive_request.hpp>
#include <silicium/http/generate_response.hpp>
#include <silicium/asio/writing_observable.hpp>
#include <silicium/asio/tcp_acceptor.hpp>
#include <silicium/observable/transform.hpp>
#include <silicium/observable/spawn_coroutine.hpp>
#include <silicium/observable/spawn_observable.hpp>
#include <silicium/sink/iterator_sink.hpp>
#include <silicium/terminate_on_exception.hpp>
#include <iostream>
#include <boost/algorithm/string/predicate.hpp>

#if SILICIUM_HAS_SPAWN_COROUTINE
namespace
{
	template <class YieldContext>
	void serve_client(boost::asio::ip::tcp::socket &client, YieldContext &&yield)
	{
		auto maybe_request = Si::http::receive_request(client, yield);
		if (maybe_request.is_error())
		{
			//The header was incomplete, maybe the connecting was closed.
			//If we want to know the reason, the error_extracting_source remembered it:
			boost::system::error_code error = maybe_request.error();
			boost::ignore_unused_variable_warning(error);
			return;
		}

		if (!maybe_request.get())
		{
			//syntax error in the request
			return;
		}

		Si::http::request const &request = *maybe_request.get();
		if (boost::algorithm::iequals(request.method, "CONNECT"))
		{
			boost::asio::ip::tcp::socket proxy_socket(client.get_io_service());
		}
		else
		{
			std::vector<char> response;
			{
				auto response_writer = Si::make_container_sink(response);
				Si::http::generate_status_line(response_writer, "HTTP/1.0", "200", "OK");
				boost::string_ref const content = "Hello, visitor!";
				Si::http::generate_header(response_writer, "Content-Length", boost::lexical_cast<Si::noexcept_string>(content.size()));
				Si::http::finish_headers(response_writer);
				Si::append(response_writer, content);
			}

			//you can handle the error if you want
			boost::system::error_code error = Si::asio::write(client, Si::make_memory_range(response), yield);
		}

		//ignore shutdown failures, they do not matter here
		boost::system::error_code error;
		client.shutdown(boost::asio::ip::tcp::socket::shutdown_both, error);
	}

	boost::system::error_code spawn_server(boost::asio::io_service &io)
	{
		boost::system::error_code ec;

		//use a unique_ptr to support older versions of Boost where acceptor was not movable
		auto acceptor = Si::make_unique<boost::asio::ip::tcp::acceptor>(io);

		acceptor->open(boost::asio::ip::tcp::v4(), ec);
		if (ec)
		{
			return ec;
		}

		acceptor->bind(boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4(), 8080), ec);
		if (ec)
		{
			return ec;
		}

		acceptor->listen(boost::asio::ip::tcp::acceptor::max_connections, ec);
		if (ec)
		{
			return ec;
		}

		Si::spawn_observable(
			Si::transform(
				Si::asio::make_tcp_acceptor(std::move(acceptor)),
				[](Si::asio::tcp_acceptor_result maybe_client)
				{
					auto client = maybe_client.get();
					Si::spawn_coroutine([client](Si::spawn_context yield)
					{
						serve_client(*client, yield);
					});
				}
			)
		);

		return {};
	}
}
#endif

int main()
{
	boost::asio::io_service io;
#if SILICIUM_HAS_SPAWN_COROUTINE
	boost::system::error_code ec = spawn_server(io);
	if (ec)
	{
		std::cerr << ec << ": " << ec.message() << '\n';
		return 1;
	}
#else
	std::cerr << "This example requires coroutine support\n";
#endif
	io.run();
}
<commit_msg>silence unused variable warning<commit_after>#include <silicium/http/receive_request.hpp>
#include <silicium/http/generate_response.hpp>
#include <silicium/asio/writing_observable.hpp>
#include <silicium/asio/tcp_acceptor.hpp>
#include <silicium/observable/transform.hpp>
#include <silicium/observable/spawn_coroutine.hpp>
#include <silicium/observable/spawn_observable.hpp>
#include <silicium/sink/iterator_sink.hpp>
#include <silicium/terminate_on_exception.hpp>
#include <iostream>
#include <boost/algorithm/string/predicate.hpp>

#if SILICIUM_HAS_SPAWN_COROUTINE
namespace
{
	template <class YieldContext>
	void serve_client(boost::asio::ip::tcp::socket &client, YieldContext &&yield)
	{
		auto maybe_request = Si::http::receive_request(client, yield);
		if (maybe_request.is_error())
		{
			//The header was incomplete, maybe the connecting was closed.
			//If we want to know the reason, the error_extracting_source remembered it:
			boost::system::error_code error = maybe_request.error();
			boost::ignore_unused_variable_warning(error);
			return;
		}

		if (!maybe_request.get())
		{
			//syntax error in the request
			return;
		}

		Si::http::request const &request = *maybe_request.get();
		if (boost::algorithm::iequals(request.method, "CONNECT"))
		{
			boost::asio::ip::tcp::socket proxy_socket(client.get_io_service());
		}
		else
		{
			std::vector<char> response;
			{
				auto response_writer = Si::make_container_sink(response);
				Si::http::generate_status_line(response_writer, "HTTP/1.0", "200", "OK");
				boost::string_ref const content = "Hello, visitor!";
				Si::http::generate_header(response_writer, "Content-Length", boost::lexical_cast<Si::noexcept_string>(content.size()));
				Si::http::finish_headers(response_writer);
				Si::append(response_writer, content);
			}

			//you can handle the error if you want
			boost::system::error_code error = Si::asio::write(client, Si::make_memory_range(response), yield);
			boost::ignore_unused_variable_warning(error);
		}

		//ignore shutdown failures, they do not matter here
		boost::system::error_code error;
		client.shutdown(boost::asio::ip::tcp::socket::shutdown_both, error);
	}

	boost::system::error_code spawn_server(boost::asio::io_service &io)
	{
		boost::system::error_code ec;

		//use a unique_ptr to support older versions of Boost where acceptor was not movable
		auto acceptor = Si::make_unique<boost::asio::ip::tcp::acceptor>(io);

		acceptor->open(boost::asio::ip::tcp::v4(), ec);
		if (ec)
		{
			return ec;
		}

		acceptor->bind(boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4(), 8080), ec);
		if (ec)
		{
			return ec;
		}

		acceptor->listen(boost::asio::ip::tcp::acceptor::max_connections, ec);
		if (ec)
		{
			return ec;
		}

		Si::spawn_observable(
			Si::transform(
				Si::asio::make_tcp_acceptor(std::move(acceptor)),
				[](Si::asio::tcp_acceptor_result maybe_client)
				{
					auto client = maybe_client.get();
					Si::spawn_coroutine([client](Si::spawn_context yield)
					{
						serve_client(*client, yield);
					});
				}
			)
		);

		return {};
	}
}
#endif

int main()
{
	boost::asio::io_service io;
#if SILICIUM_HAS_SPAWN_COROUTINE
	boost::system::error_code ec = spawn_server(io);
	if (ec)
	{
		std::cerr << ec << ": " << ec.message() << '\n';
		return 1;
	}
#else
	std::cerr << "This example requires coroutine support\n";
#endif
	io.run();
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
#ifndef FLUSHER_H
#define FLUSHER_H 1

#include "common.hh"
#include "ep.hh"
#include "dispatcher.hh"

enum flusher_state {
    initializing,
    running,
    pausing,
    paused,
    stopping,
    stopped
};

class Flusher;

class FlusherStepper : public DispatcherCallback {
public:
    FlusherStepper(Flusher* f) : flusher(f) { }
    bool callback(Dispatcher &d, TaskId t);
private:
    Flusher *flusher;
};

class Flusher {
public:
    Flusher(EventuallyPersistentStore *st, Dispatcher *d) :
        store(st), _state(initializing), dispatcher(d),
        flushQueue(NULL) {
    }
    ~Flusher() {
        stop();
        wait();
    }

    bool stop();
    void wait();
    bool pause();
    bool resume();

    void initialize(TaskId);

    void start(void);
    void wake(void);
    bool step(Dispatcher&, TaskId);

    bool transition_state(enum flusher_state to);

    enum flusher_state state() const;
    const char * stateName() const;
private:
    int doFlush();
    void completeFlush();
    void schedule_UNLOCKED();

    EventuallyPersistentStore *store;
    volatile enum flusher_state _state;
    Mutex taskMutex;
    TaskId task;
    Dispatcher *dispatcher;
    const char * stateName(enum flusher_state st) const;

    // Current flush cycle state.
    int                     flushRv;
    std::queue<QueuedItem> *flushQueue;
    std::queue<QueuedItem> *rejectQueue;
    rel_time_t              flushStart;

    DISALLOW_COPY_AND_ASSIGN(Flusher);
};

#endif /* FLUSHER_H */
<commit_msg>bug 2208 - Log if the flusher isn't in stopped state at destruct time.<commit_after>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
#ifndef FLUSHER_H
#define FLUSHER_H 1

#include "common.hh"
#include "ep.hh"
#include "dispatcher.hh"

enum flusher_state {
    initializing,
    running,
    pausing,
    paused,
    stopping,
    stopped
};

class Flusher;

class FlusherStepper : public DispatcherCallback {
public:
    FlusherStepper(Flusher* f) : flusher(f) { }
    bool callback(Dispatcher &d, TaskId t);
private:
    Flusher *flusher;
};

class Flusher {
public:
    Flusher(EventuallyPersistentStore *st, Dispatcher *d) :
        store(st), _state(initializing), dispatcher(d),
        flushQueue(NULL) {
    }
    ~Flusher() {
        if (_state != stopped) {
            getLogger()->log(EXTENSION_LOG_WARN, NULL,
                             "Flusher being destroyed in state %s\n",
                             stateName(_state));

        }
    }

    bool stop();
    void wait();
    bool pause();
    bool resume();

    void initialize(TaskId);

    void start(void);
    void wake(void);
    bool step(Dispatcher&, TaskId);

    bool transition_state(enum flusher_state to);

    enum flusher_state state() const;
    const char * stateName() const;
private:
    int doFlush();
    void completeFlush();
    void schedule_UNLOCKED();

    EventuallyPersistentStore *store;
    volatile enum flusher_state _state;
    Mutex taskMutex;
    TaskId task;
    Dispatcher *dispatcher;
    const char * stateName(enum flusher_state st) const;

    // Current flush cycle state.
    int                     flushRv;
    std::queue<QueuedItem> *flushQueue;
    std::queue<QueuedItem> *rejectQueue;
    rel_time_t              flushStart;

    DISALLOW_COPY_AND_ASSIGN(Flusher);
};

#endif /* FLUSHER_H */
<|endoftext|>


<commit_before>/*
  EEPROMEx.cpp - Extended EEPROM library
  Copyright (c) 2012 Thijs Elenbaas.  All right reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

/******************************************************************************
 * Includes
 ******************************************************************************/
#include "EEPROMex.h"

/******************************************************************************
 * Definitions
 ******************************************************************************/

 #define _EEPROMEX_VERSION 1 // software version of this library
 #define _EEPROMEX_DEBUG     // Enables logging of maximum of writes and out-of-memory
/******************************************************************************
 * Constructors
 ******************************************************************************/

// Boards with ATmega328, Duemilanove, Uno, Uno SMD, Lilypad - 1024 bytes (1 kilobyte)
// Boards with ATmega1280 or 2560, Arduino Mega series – 4096 bytes (4 kilobytes)
// Boards with ATmega168, Lilypad, old Nano, Diecimila  – 512 bytes
// By default we choose conservative settings
EEPROMClassEx::EEPROMClassEx()
  :  _allowedWrites(100)
{
}

/******************************************************************************
 * User API
 ******************************************************************************/

void EEPROMClassEx::setMemPool(int base, int memSize) {
	//Base can only be adjusted if no addresses have already been issued
	if (_nextAvailableaddress == _base)
		_base = base;
		_nextAvailableaddress=_base;

	//Ceiling can only be adjusted if not below issued addresses
	if (memSize >= _nextAvailableaddress )
		_memSize = memSize;

	#ifdef _EEPROMEX_DEBUG
	if (_nextAvailableaddress != _base)
		Serial.println("Cannot change base, addresses have been issued");

	if (memSize < _nextAvailableaddress )
		Serial.println("Cannot change ceiling, below issued addresses");
	#endif

}

void EEPROMClassEx::setMaxAllowedWrites(int allowedWrites) {
#ifdef _EEPROMEX_DEBUG
	_allowedWrites = allowedWrites;
#endif
}

int EEPROMClassEx::getAddress(int noOfBytes){
	int availableaddress   = _nextAvailableaddress;
	_nextAvailableaddress += noOfBytes;

#ifdef _EEPROMEX_DEBUG
	if (_nextAvailableaddress > _memSize) {
		Serial.println("Attempt to write outside of EEPROM memory");
		return -availableaddress;
	} else {
		return availableaddress;
	}
#endif
	return availableaddress;
}

bool EEPROMClassEx::isReady() {
	return eeprom_is_ready();
}

uint8_t EEPROMClassEx::read(int address)
{
	return readByte(address);
}

bool EEPROMClassEx::readBit(int address, byte bit) {
	  if (bit> 7) return false;
	  if (!isReadOk(address+sizeof(uint8_t))) return false;
	  byte byteVal =  eeprom_read_byte((unsigned char *) address);
	  byte bytePos = (1 << bit);
      return (byteVal & bytePos);
}

uint8_t EEPROMClassEx::readByte(int address)
{
	if (!isReadOk(address+sizeof(uint8_t))) return 0;
	return eeprom_read_byte((unsigned char *) address);
}

uint16_t EEPROMClassEx::readInt(int address)
{
	if (!isReadOk(address+sizeof(uint16_t))) return 0;
	return eeprom_read_word((uint16_t *) address);
}

uint32_t EEPROMClassEx::readLong(int address)
{
	if (!isReadOk(address+sizeof(uint32_t))) return 0;
	return eeprom_read_dword((unsigned long *) address);
}

float EEPROMClassEx::readFloat(int address)
{
	if (!isReadOk(address+sizeof(float))) return 0;
	float _value;
	readBlock<float>(address, _value);
	return _value;
}

double EEPROMClassEx::readDouble(int address)
{
	if (!isReadOk(address+sizeof(double))) return 0;
	double _value;
	readBlock<double>(address, _value);
	return _value;
}

bool EEPROMClassEx::write(int address, uint8_t value)
{
	return writeByte(address, value);
}

bool EEPROMClassEx::writeBit(int address, uint8_t bit, bool value) {
	updateBit(address, bit, value);
	return true;
}

bool EEPROMClassEx::writeByte(int address, uint8_t value)
{
	if (!isWriteOk(address+sizeof(uint8_t))) return false;
	eeprom_write_byte((unsigned char *) address, value);
	return true;
}

bool EEPROMClassEx::writeInt(int address, uint16_t value)
{
	if (!isWriteOk(address+sizeof(uint16_t))) return false;
	eeprom_write_word((uint16_t *) address, value);
	return true;
}

bool EEPROMClassEx::writeLong(int address, uint32_t value)
{
	if (!isWriteOk(address+sizeof(uint32_t))) return false;
	eeprom_write_dword((unsigned long *) address, value);
	return true;
}

bool EEPROMClassEx::writeFloat(int address, float value)
{
	return (writeBlock<float>(address, value)!=0);
}

bool EEPROMClassEx::writeDouble(int address, double value)
{
	return (writeBlock<float>(address, value)!=0);
}

bool EEPROMClassEx::update(int address, uint8_t value)
{
	return (updateByte(address, value));
}

bool EEPROMClassEx::updateBit(int address, uint8_t bit, bool value)
{
	  if (bit> 7) return false;

	  byte byteValInput  = readByte(address);
	  byte byteValOutput = byteValInput;
	  // Set bit
	  if (value) {
		byteValOutput |= (1 << bit);  //Set bit to 1
	  } else {
	    byteValOutput &= ~(1 << bit); //Set bit to 0
	  }
	  // Store if different from input
	  if (byteValOutput!=byteValInput) {
		writeByte(address, byteValOutput);
	  }
	  return true;
}

bool EEPROMClassEx::updateByte(int address, uint8_t value)
{
	return (updateBlock<uint8_t>(address, value)!=0);
}

bool EEPROMClassEx::updateInt(int address, uint16_t value)
{
	return (updateBlock<uint16_t>(address, value)!=0);
}

bool EEPROMClassEx::updateLong(int address, uint32_t value)
{
	return (updateBlock<uint32_t>(address, value)!=0);
}

bool EEPROMClassEx::updateFloat(int address, float value)
{
	return (updateBlock<float>(address, value)!=0);
}

bool EEPROMClassEx::updateDouble(int address, double value)
{
	return (writeBlock<double>(address, value)!=0);
}

bool EEPROMClassEx::isWriteOk(int address)
{
#ifdef _EEPROMEX_DEBUG
	_writeCounts++;
	if (_allowedWrites == 0 || _writeCounts > _allowedWrites ) {
		Serial.println("Exceeded maximum number of writes");
		return false;
	}

	if (address > _memSize) {
		Serial.println("Attempt to write outside of EEPROM memory");
		return false;
	} else {
		return true;
	}
#endif
	return true;
}

bool EEPROMClassEx::isReadOk(int address)
{
#ifdef _EEPROMEX_DEBUG
	if (address > _memSize) {
		Serial.println("Attempt to write outside of EEPROM memory");
		return false;
	} else {
		return true;
	}
#endif
	return true;
}

int EEPROMClassEx::_base= 0;
int EEPROMClassEx::_memSize= 512;
int EEPROMClassEx::_nextAvailableaddress= 0;
int EEPROMClassEx::_writeCounts =0;

EEPROMClassEx EEPROM;
<commit_msg>Disable EEPROMex debug mode<commit_after>/*
  EEPROMEx.cpp - Extended EEPROM library
  Copyright (c) 2012 Thijs Elenbaas.  All right reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

/******************************************************************************
 * Includes
 ******************************************************************************/
#include "EEPROMex.h"

/******************************************************************************
 * Definitions
 ******************************************************************************/

 #define _EEPROMEX_VERSION 1 // software version of this library
 //#define _EEPROMEX_DEBUG     // Enables logging of maximum of writes and out-of-memory
/******************************************************************************
 * Constructors
 ******************************************************************************/

// Boards with ATmega328, Duemilanove, Uno, Uno SMD, Lilypad - 1024 bytes (1 kilobyte)
// Boards with ATmega1280 or 2560, Arduino Mega series – 4096 bytes (4 kilobytes)
// Boards with ATmega168, Lilypad, old Nano, Diecimila  – 512 bytes
// By default we choose conservative settings
EEPROMClassEx::EEPROMClassEx()
  :  _allowedWrites(100)
{
}

/******************************************************************************
 * User API
 ******************************************************************************/

void EEPROMClassEx::setMemPool(int base, int memSize) {
	//Base can only be adjusted if no addresses have already been issued
	if (_nextAvailableaddress == _base)
		_base = base;
		_nextAvailableaddress=_base;

	//Ceiling can only be adjusted if not below issued addresses
	if (memSize >= _nextAvailableaddress )
		_memSize = memSize;

	#ifdef _EEPROMEX_DEBUG
	if (_nextAvailableaddress != _base)
		Serial.println("Cannot change base, addresses have been issued");

	if (memSize < _nextAvailableaddress )
		Serial.println("Cannot change ceiling, below issued addresses");
	#endif

}

void EEPROMClassEx::setMaxAllowedWrites(int allowedWrites) {
#ifdef _EEPROMEX_DEBUG
	_allowedWrites = allowedWrites;
#endif
}

int EEPROMClassEx::getAddress(int noOfBytes){
	int availableaddress   = _nextAvailableaddress;
	_nextAvailableaddress += noOfBytes;

#ifdef _EEPROMEX_DEBUG
	if (_nextAvailableaddress > _memSize) {
		Serial.println("Attempt to write outside of EEPROM memory");
		return -availableaddress;
	} else {
		return availableaddress;
	}
#endif
	return availableaddress;
}

bool EEPROMClassEx::isReady() {
	return eeprom_is_ready();
}

uint8_t EEPROMClassEx::read(int address)
{
	return readByte(address);
}

bool EEPROMClassEx::readBit(int address, byte bit) {
	  if (bit> 7) return false;
	  if (!isReadOk(address+sizeof(uint8_t))) return false;
	  byte byteVal =  eeprom_read_byte((unsigned char *) address);
	  byte bytePos = (1 << bit);
      return (byteVal & bytePos);
}

uint8_t EEPROMClassEx::readByte(int address)
{
	if (!isReadOk(address+sizeof(uint8_t))) return 0;
	return eeprom_read_byte((unsigned char *) address);
}

uint16_t EEPROMClassEx::readInt(int address)
{
	if (!isReadOk(address+sizeof(uint16_t))) return 0;
	return eeprom_read_word((uint16_t *) address);
}

uint32_t EEPROMClassEx::readLong(int address)
{
	if (!isReadOk(address+sizeof(uint32_t))) return 0;
	return eeprom_read_dword((unsigned long *) address);
}

float EEPROMClassEx::readFloat(int address)
{
	if (!isReadOk(address+sizeof(float))) return 0;
	float _value;
	readBlock<float>(address, _value);
	return _value;
}

double EEPROMClassEx::readDouble(int address)
{
	if (!isReadOk(address+sizeof(double))) return 0;
	double _value;
	readBlock<double>(address, _value);
	return _value;
}

bool EEPROMClassEx::write(int address, uint8_t value)
{
	return writeByte(address, value);
}

bool EEPROMClassEx::writeBit(int address, uint8_t bit, bool value) {
	updateBit(address, bit, value);
	return true;
}

bool EEPROMClassEx::writeByte(int address, uint8_t value)
{
	if (!isWriteOk(address+sizeof(uint8_t))) return false;
	eeprom_write_byte((unsigned char *) address, value);
	return true;
}

bool EEPROMClassEx::writeInt(int address, uint16_t value)
{
	if (!isWriteOk(address+sizeof(uint16_t))) return false;
	eeprom_write_word((uint16_t *) address, value);
	return true;
}

bool EEPROMClassEx::writeLong(int address, uint32_t value)
{
	if (!isWriteOk(address+sizeof(uint32_t))) return false;
	eeprom_write_dword((unsigned long *) address, value);
	return true;
}

bool EEPROMClassEx::writeFloat(int address, float value)
{
	return (writeBlock<float>(address, value)!=0);
}

bool EEPROMClassEx::writeDouble(int address, double value)
{
	return (writeBlock<float>(address, value)!=0);
}

bool EEPROMClassEx::update(int address, uint8_t value)
{
	return (updateByte(address, value));
}

bool EEPROMClassEx::updateBit(int address, uint8_t bit, bool value)
{
	  if (bit> 7) return false;

	  byte byteValInput  = readByte(address);
	  byte byteValOutput = byteValInput;
	  // Set bit
	  if (value) {
		byteValOutput |= (1 << bit);  //Set bit to 1
	  } else {
	    byteValOutput &= ~(1 << bit); //Set bit to 0
	  }
	  // Store if different from input
	  if (byteValOutput!=byteValInput) {
		writeByte(address, byteValOutput);
	  }
	  return true;
}

bool EEPROMClassEx::updateByte(int address, uint8_t value)
{
	return (updateBlock<uint8_t>(address, value)!=0);
}

bool EEPROMClassEx::updateInt(int address, uint16_t value)
{
	return (updateBlock<uint16_t>(address, value)!=0);
}

bool EEPROMClassEx::updateLong(int address, uint32_t value)
{
	return (updateBlock<uint32_t>(address, value)!=0);
}

bool EEPROMClassEx::updateFloat(int address, float value)
{
	return (updateBlock<float>(address, value)!=0);
}

bool EEPROMClassEx::updateDouble(int address, double value)
{
	return (writeBlock<double>(address, value)!=0);
}

bool EEPROMClassEx::isWriteOk(int address)
{
#ifdef _EEPROMEX_DEBUG
	_writeCounts++;
	if (_allowedWrites == 0 || _writeCounts > _allowedWrites ) {
		Serial.println("Exceeded maximum number of writes");
		return false;
	}

	if (address > _memSize) {
		Serial.println("Attempt to write outside of EEPROM memory");
		return false;
	} else {
		return true;
	}
#endif
	return true;
}

bool EEPROMClassEx::isReadOk(int address)
{
#ifdef _EEPROMEX_DEBUG
	if (address > _memSize) {
		Serial.println("Attempt to write outside of EEPROM memory");
		return false;
	} else {
		return true;
	}
#endif
	return true;
}

int EEPROMClassEx::_base= 0;
int EEPROMClassEx::_memSize= 512;
int EEPROMClassEx::_nextAvailableaddress= 0;
int EEPROMClassEx::_writeCounts =0;

EEPROMClassEx EEPROM;
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 *  ola-artnet.cpp
 *  Configure an ArtNet device
 *  Copyright (C) 2005-2009 Simon Newton
 */

#include <errno.h>
#include <getopt.h>
#include <ola/network/IPV4Address.h>
#include <ola/plugin_id.h>
#include <plugins/artnet/messages/ArtnetConfigMessages.pb.h>
#include <iostream>
#include <string>
#include "examples/OlaConfigurator.h"

using std::cout;
using std::endl;
using std::string;

typedef struct {
  string command;   // argv[0]
  int device_id;    // device id
  bool help;        // help
  bool has_name;
  string name;      // short name
  bool has_long_name;
  string long_name;  // long name
  bool has_subnet;
  int subnet;       // the subnet
  bool has_net;
  int net;  // the net address
  unsigned int universe;
  bool fetch_node_list;
} options;

/*
 * A class that configures Artnet devices
 */
class ArtnetConfigurator: public OlaConfigurator {
  public:
    explicit ArtnetConfigurator(const options &opts):
      OlaConfigurator(opts.device_id, ola::OLA_PLUGIN_ARTNET),
      m_options(opts) {}
    void HandleConfigResponse(const string &reply, const string &error);
    void SendConfigRequest();
  private:
    void SendOptionRequest();
    void SendNodeListRequest();
    void DisplayOptions(const ola::plugin::artnet::OptionsReply &reply);
    void DisplayNodeList(const ola::plugin::artnet::NodeListReply &reply);
    options m_options;
};

/*
 * Handle the device config reply
 */
void ArtnetConfigurator::HandleConfigResponse(const string &reply,
                                              const string &error) {
  Terminate();
  if (!error.empty()) {
    cout << error << endl;
    return;
  }
  ola::plugin::artnet::Reply reply_pb;
  if (!reply_pb.ParseFromString(reply)) {
    cout << "Protobuf parsing failed" << endl;
    return;
  }
  if (reply_pb.type() == ola::plugin::artnet::Reply::ARTNET_OPTIONS_REPLY &&
      reply_pb.has_options()) {
    DisplayOptions(reply_pb.options());
    return;
  } else if (reply_pb.type() ==
               ola::plugin::artnet::Reply::ARTNET_NODE_LIST_REPLY &&
             reply_pb.has_node_list()) {
    DisplayNodeList(reply_pb.node_list());
  } else {
    cout << "Invalid response type or missing options field" << endl;
  }
}

/*
 * Send a request
 */
void ArtnetConfigurator::SendConfigRequest() {
  if (m_options.fetch_node_list)
    SendNodeListRequest();
  else
    SendOptionRequest();
}

/**
 * Send an options request, which may involve setting options
 */
void ArtnetConfigurator::SendOptionRequest() {
  ola::plugin::artnet::Request request;
  request.set_type(ola::plugin::artnet::Request::ARTNET_OPTIONS_REQUEST);
  ola::plugin::artnet::OptionsRequest *options = request.mutable_options();

  if (m_options.has_name)
    options->set_short_name(m_options.name);
  if (m_options.has_long_name)
    options->set_long_name(m_options.long_name);
  if (m_options.has_subnet)
    options->set_subnet(m_options.subnet);
  if (m_options.has_net)
    options->set_net(m_options.net);
  SendMessage(request);
}

/**
 * Send a request for the node list
 */
void ArtnetConfigurator::SendNodeListRequest() {
  ola::plugin::artnet::Request request;
  request.set_type(ola::plugin::artnet::Request::ARTNET_NODE_LIST_REQUEST);
  ola::plugin::artnet::NodeListRequest *node_list_request =
    request.mutable_node_list();
  node_list_request->set_universe(m_options.universe);
  SendMessage(request);
}

/*
 * Display the widget parameters
 */
void ArtnetConfigurator::DisplayOptions(
    const ola::plugin::artnet::OptionsReply &reply) {
  cout << "Name: " << reply.short_name() << endl;
  cout << "Long Name: " << reply.long_name() << endl;
  cout << "Subnet: " << reply.subnet() << endl;
  cout << "Net: " << reply.net() << endl;
}

/**
 * Display the list of discovered nodes
 */
void ArtnetConfigurator::DisplayNodeList(
    const ola::plugin::artnet::NodeListReply &reply) {
  unsigned int nodes = reply.node_size();
  for (unsigned int i = 0; i < nodes; i++) {
    const ola::plugin::artnet::OutputNode &node = reply.node(i);
    ola::network::IPV4Address address(node.ip_address());
    cout << address << endl;
  }
}

/*
 * Parse our cmd line options
 */
int ParseOptions(int argc, char *argv[], options *opts) {
  static struct option long_options[] = {
      {"dev",       required_argument,  0, 'd'},
      {"help",      no_argument,        0, 'h'},
      {"long_name", required_argument,  0, 'l'},
      {"name",      required_argument,  0, 'n'},
      {"subnet",    required_argument,  0, 's'},
      {"net",       required_argument,  0, 'e'},
      {"universes", required_argument, 0, 'u'},
      {0, 0, 0, 0}
    };

  int c;
  int option_index = 0;

  while (1) {
    c = getopt_long(argc, argv, "d:e:hl:n:s:u:", long_options, &option_index);
    if (c == -1)
      break;

    switch (c) {
      case 0:
        break;
      case 'd':
        opts->device_id = atoi(optarg);
        break;
      case 'e':
        opts->net = atoi(optarg);
        opts->has_net = true;
        break;
      case 'h':
        opts->help = true;
        break;
      case 'l':
        opts->long_name = optarg;
        opts->has_long_name = true;
        break;
      case 'n':
        opts->name = optarg;
        opts->has_name = true;
        break;
      case 's':
        opts->subnet = atoi(optarg);
        opts->has_subnet = true;
        break;
      case 'u':
        opts->universe = atoi(optarg);
        opts->fetch_node_list = true;
        break;
      case '?':
        break;
    }
  }
  return 0;
}

/*
 * Display the help message
 */
void DisplayHelpAndExit(const options &opts) {
  cout << "Usage: " << opts.command <<
    " -d <dev_id> -n <name> -l <long_name> -s <subnet>\n\n"
    "Configure ArtNet Devices managed by OLA.\n\n"
    "  -e, --net       Set the net parameter of the ArtNet device\n"
    "  -h, --help      Display this help message and exit.\n"
    "  -l, --long_name Set the long name of the ArtNet device\n"
    "  -n, --name      Set the name of the ArtNet device\n"
    "  -s, --subnet    Set the subnet of the ArtNet device\n"
    "  -u, --universe  List the IPs of devices for this universe\n" <<
    endl;
  exit(0);
}

/*
 * The main function
 */
int main(int argc, char*argv[]) {
  options opts;
  opts.command = argv[0];
  opts.device_id = -1;
  opts.help = false;
  opts.has_name = false;
  opts.has_long_name = false;
  opts.has_subnet = false;
  opts.has_net = false;
  opts.fetch_node_list = false;
  opts.universe = 0;

  ParseOptions(argc, argv, &opts);

  if (opts.help || opts.device_id < 0)
    DisplayHelpAndExit(opts);

  ArtnetConfigurator configurator(opts);
  if (!configurator.Setup()) {
    cout << "error: " << strerror(errno) << endl;
    exit(1);
  }

  configurator.Run();
  return 0;
}
<commit_msg>Show the dev option in the help for ola_artnet<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 *  ola-artnet.cpp
 *  Configure an ArtNet device
 *  Copyright (C) 2005-2009 Simon Newton
 */

#include <errno.h>
#include <getopt.h>
#include <ola/network/IPV4Address.h>
#include <ola/plugin_id.h>
#include <plugins/artnet/messages/ArtnetConfigMessages.pb.h>
#include <iostream>
#include <string>
#include "examples/OlaConfigurator.h"

using std::cout;
using std::endl;
using std::string;

typedef struct {
  string command;   // argv[0]
  int device_id;    // device id
  bool help;        // help
  bool has_name;
  string name;      // short name
  bool has_long_name;
  string long_name;  // long name
  bool has_subnet;
  int subnet;       // the subnet
  bool has_net;
  int net;  // the net address
  unsigned int universe;
  bool fetch_node_list;
} options;

/*
 * A class that configures Artnet devices
 */
class ArtnetConfigurator: public OlaConfigurator {
  public:
    explicit ArtnetConfigurator(const options &opts):
      OlaConfigurator(opts.device_id, ola::OLA_PLUGIN_ARTNET),
      m_options(opts) {}
    void HandleConfigResponse(const string &reply, const string &error);
    void SendConfigRequest();
  private:
    void SendOptionRequest();
    void SendNodeListRequest();
    void DisplayOptions(const ola::plugin::artnet::OptionsReply &reply);
    void DisplayNodeList(const ola::plugin::artnet::NodeListReply &reply);
    options m_options;
};

/*
 * Handle the device config reply
 */
void ArtnetConfigurator::HandleConfigResponse(const string &reply,
                                              const string &error) {
  Terminate();
  if (!error.empty()) {
    cout << error << endl;
    return;
  }
  ola::plugin::artnet::Reply reply_pb;
  if (!reply_pb.ParseFromString(reply)) {
    cout << "Protobuf parsing failed" << endl;
    return;
  }
  if (reply_pb.type() == ola::plugin::artnet::Reply::ARTNET_OPTIONS_REPLY &&
      reply_pb.has_options()) {
    DisplayOptions(reply_pb.options());
    return;
  } else if (reply_pb.type() ==
               ola::plugin::artnet::Reply::ARTNET_NODE_LIST_REPLY &&
             reply_pb.has_node_list()) {
    DisplayNodeList(reply_pb.node_list());
  } else {
    cout << "Invalid response type or missing options field" << endl;
  }
}

/*
 * Send a request
 */
void ArtnetConfigurator::SendConfigRequest() {
  if (m_options.fetch_node_list)
    SendNodeListRequest();
  else
    SendOptionRequest();
}

/**
 * Send an options request, which may involve setting options
 */
void ArtnetConfigurator::SendOptionRequest() {
  ola::plugin::artnet::Request request;
  request.set_type(ola::plugin::artnet::Request::ARTNET_OPTIONS_REQUEST);
  ola::plugin::artnet::OptionsRequest *options = request.mutable_options();

  if (m_options.has_name)
    options->set_short_name(m_options.name);
  if (m_options.has_long_name)
    options->set_long_name(m_options.long_name);
  if (m_options.has_subnet)
    options->set_subnet(m_options.subnet);
  if (m_options.has_net)
    options->set_net(m_options.net);
  SendMessage(request);
}

/**
 * Send a request for the node list
 */
void ArtnetConfigurator::SendNodeListRequest() {
  ola::plugin::artnet::Request request;
  request.set_type(ola::plugin::artnet::Request::ARTNET_NODE_LIST_REQUEST);
  ola::plugin::artnet::NodeListRequest *node_list_request =
    request.mutable_node_list();
  node_list_request->set_universe(m_options.universe);
  SendMessage(request);
}

/*
 * Display the widget parameters
 */
void ArtnetConfigurator::DisplayOptions(
    const ola::plugin::artnet::OptionsReply &reply) {
  cout << "Name: " << reply.short_name() << endl;
  cout << "Long Name: " << reply.long_name() << endl;
  cout << "Subnet: " << reply.subnet() << endl;
  cout << "Net: " << reply.net() << endl;
}

/**
 * Display the list of discovered nodes
 */
void ArtnetConfigurator::DisplayNodeList(
    const ola::plugin::artnet::NodeListReply &reply) {
  unsigned int nodes = reply.node_size();
  for (unsigned int i = 0; i < nodes; i++) {
    const ola::plugin::artnet::OutputNode &node = reply.node(i);
    ola::network::IPV4Address address(node.ip_address());
    cout << address << endl;
  }
}

/*
 * Parse our cmd line options
 */
int ParseOptions(int argc, char *argv[], options *opts) {
  static struct option long_options[] = {
      {"dev",       required_argument,  0, 'd'},
      {"help",      no_argument,        0, 'h'},
      {"long_name", required_argument,  0, 'l'},
      {"name",      required_argument,  0, 'n'},
      {"subnet",    required_argument,  0, 's'},
      {"net",       required_argument,  0, 'e'},
      {"universes", required_argument, 0, 'u'},
      {0, 0, 0, 0}
    };

  int c;
  int option_index = 0;

  while (1) {
    c = getopt_long(argc, argv, "d:e:hl:n:s:u:", long_options, &option_index);
    if (c == -1)
      break;

    switch (c) {
      case 0:
        break;
      case 'd':
        opts->device_id = atoi(optarg);
        break;
      case 'e':
        opts->net = atoi(optarg);
        opts->has_net = true;
        break;
      case 'h':
        opts->help = true;
        break;
      case 'l':
        opts->long_name = optarg;
        opts->has_long_name = true;
        break;
      case 'n':
        opts->name = optarg;
        opts->has_name = true;
        break;
      case 's':
        opts->subnet = atoi(optarg);
        opts->has_subnet = true;
        break;
      case 'u':
        opts->universe = atoi(optarg);
        opts->fetch_node_list = true;
        break;
      case '?':
        break;
    }
  }
  return 0;
}

/*
 * Display the help message
 */
void DisplayHelpAndExit(const options &opts) {
  cout << "Usage: " << opts.command <<
    " -d <dev_id> -n <name> -l <long_name> -s <subnet>\n\n"
    "Configure ArtNet Devices managed by OLA.\n\n"
    "  -d, --dev       The ArtNet device to configure\n"
    "  -e, --net       Set the net parameter of the ArtNet device\n"
    "  -h, --help      Display this help message and exit.\n"
    "  -l, --long_name Set the long name of the ArtNet device\n"
    "  -n, --name      Set the name of the ArtNet device\n"
    "  -s, --subnet    Set the subnet of the ArtNet device\n"
    "  -u, --universe  List the IPs of devices for this universe\n" <<
    endl;
  exit(0);
}

/*
 * The main function
 */
int main(int argc, char*argv[]) {
  options opts;
  opts.command = argv[0];
  opts.device_id = -1;
  opts.help = false;
  opts.has_name = false;
  opts.has_long_name = false;
  opts.has_subnet = false;
  opts.has_net = false;
  opts.fetch_node_list = false;
  opts.universe = 0;

  ParseOptions(argc, argv, &opts);

  if (opts.help || opts.device_id < 0)
    DisplayHelpAndExit(opts);

  ArtnetConfigurator configurator(opts);
  if (!configurator.Setup()) {
    cout << "error: " << strerror(errno) << endl;
    exit(1);
  }

  configurator.Run();
  return 0;
}
<|endoftext|>


<commit_before>/**************************************************************************
* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
*                                                                        *
* Author: The ALICE Off-line Project.                                    *
* Contributors are mentioned in the code where appropriate.              *
*                                                                        *
* Permission to use, copy, modify and distribute this software and its   *
* documentation strictly for non-commercial purposes is hereby granted   *
* without fee, provided that the above copyright notice appears in all   *
* copies and that both the copyright notice and this permission notice   *
* appear in the supporting documentation. The authors make no claims     *
* about the suitability of this software for any purpose. It is          *
* provided "as is" without express or implied warranty.                  *
**************************************************************************/

// $Id$

#include "AliMUONCalibrationData.h"

#include "AliCDBEntry.h"
#include "AliCDBManager.h"
#include "AliCodeTimer.h"
#include "AliLog.h"
#include "AliMUONTriggerEfficiencyCells.h"
#include "AliMUONTriggerLut.h"
#include "AliMUONVStore.h"
#include "AliMUONVStore.h"
#include "AliMUONVCalibParam.h"
#include <Riostream.h>
#include <TClass.h>
#include <TMap.h>

//-----------------------------------------------------------------------------
/// \class AliMUONCalibrationData
///
/// For the moment, this class stores pedestals, gains, hv (for tracker)
/// and lut, masks and efficiencies (for trigger) that are fetched from the CDB.
///
/// This class is to be considered as a convenience class.
/// Its aim is to ease retrieval of calibration data from the
/// condition database.
///
/// It acts as a "facade" to a bunch of underlying
/// containers/calibration classes.
///
/// \author Laurent Aphecetche
//-----------------------------------------------------------------------------

/// \cond CLASSIMP
ClassImp(AliMUONCalibrationData)
/// \endcond

//_____________________________________________________________________________
AliMUONCalibrationData::AliMUONCalibrationData(Int_t runNumber,
                                               Bool_t deferredInitialization)
: TObject(),
fIsValid(kTRUE),
fRunNumber(runNumber),
fGains(0x0),
fPedestals(0x0),
fHV(0x0),
fLocalTriggerBoardMasks(0x0),
fRegionalTriggerBoardMasks(0x0),
fGlobalTriggerBoardMasks(0x0),
fTriggerLut(0x0),
fTriggerEfficiency(0x0),
fCapacitances(0x0),
fNeighbours(0x0)
{
/// Default ctor.

  // If deferredInitialization is false, we read *all* calibrations
  // at once.
  // So when using this class to access only one kind of calibrations (e.g.
  // only pedestals), you should put deferredInitialization to kTRUE, which
  // will instruct this object to fetch the data only when neeeded.

  if ( deferredInitialization == kFALSE )
  {
    Gains();
    Pedestals();
    HV();
    LocalTriggerBoardMasks(0);
    RegionalTriggerBoardMasks(0);
    GlobalTriggerBoardMasks();
    TriggerLut();
    TriggerEfficiency();
    Capacitances();
    Neighbours();
  }
}

//_____________________________________________________________________________
AliMUONCalibrationData::~AliMUONCalibrationData()
{
  /// Destructor. Note that we're the owner of our pointers.
  Reset();
}

//_____________________________________________________________________________
AliMUONVStore*
AliMUONCalibrationData::Capacitances() const
{
  /// Create (if needed) and return the internal store for capacitances.

  if (!fCapacitances)
  {
    fCapacitances = CreateCapacitances(fRunNumber);
  }
  return fCapacitances;
}

//_____________________________________________________________________________
AliMUONVStore*
AliMUONCalibrationData::CreateCapacitances(Int_t runNumber)
{
  /// Create capa store from OCDB for a given run

  return dynamic_cast<AliMUONVStore*>(CreateObject(runNumber,"MUON/Calib/Capacitances"));
}

//_____________________________________________________________________________
AliMUONVStore*
AliMUONCalibrationData::CreateGains(Int_t runNumber)
{
  /// Create a new gain store from the OCDB for a given run
  return dynamic_cast<AliMUONVStore*>(CreateObject(runNumber,"MUON/Calib/Gains"));
}

//_____________________________________________________________________________
AliMUONVCalibParam*
AliMUONCalibrationData::CreateGlobalTriggerBoardMasks(Int_t runNumber)
{
  /// Create the internal store for GlobalTriggerBoardMasks from OCDB

  return dynamic_cast<AliMUONVCalibParam*>(CreateObject(runNumber,"MUON/Calib/GlobalTriggerBoardMasks"));
}

//_____________________________________________________________________________
TMap*
AliMUONCalibrationData::CreateHV(Int_t runNumber)
{
  /// Create a new HV map from the OCDB for a given run
  return dynamic_cast<TMap*>(CreateObject(runNumber,"MUON/Calib/HV"));
}

//_____________________________________________________________________________
AliMUONVStore*
AliMUONCalibrationData::CreateLocalTriggerBoardMasks(Int_t runNumber)
{
  /// Get the internal store for LocalTriggerBoardMasks from OCDB

  return dynamic_cast<AliMUONVStore*>(CreateObject(runNumber,"MUON/Calib/LocalTriggerBoardMasks"));
}

//_____________________________________________________________________________
AliMUONVStore*
AliMUONCalibrationData::CreateNeighbours(Int_t runNumber)
{
  /// Create a neighbour store from the OCDB for a given run
  return dynamic_cast<AliMUONVStore*>(CreateObject(runNumber,"MUON/Calib/Neighbours"));
}

//_____________________________________________________________________________
TObject*
AliMUONCalibrationData::CreateObject(Int_t runNumber, const char* path)
{
  /// Access the CDB for a given path (e.g. MUON/Calib/Pedestals),
  /// and return the corresponding TObject.

  AliCodeTimerAutoClass(Form("%d : %s",runNumber,path));

  AliCDBManager* man = AliCDBManager::Instance();

  Bool_t undefStorage(kFALSE);

  if ( !man->IsDefaultStorageSet() )
  {
    TString storage("local://$ALICE_ROOT");
    AliInfoClass(Form("CDB Storage not set. Will use %s for MUON stuff",storage.Data()));
    man->SetDefaultStorage(storage.Data());
    undefStorage = kTRUE;
  }

  Bool_t cacheStatus = man->GetCacheFlag();

  man->SetCacheFlag(kFALSE);

  AliCDBEntry* entry =  AliCDBManager::Instance()->Get(path,runNumber);

  man->SetCacheFlag(cacheStatus);

  if (entry)
  {
    TObject* object = entry->GetObject();
    entry->SetOwner(kFALSE);
    delete entry;
    return object;
  }

  if ( undefStorage )
  {
    man->UnsetDefaultStorage();
  }

  return 0x0;
}

//_____________________________________________________________________________
AliMUONVStore*
AliMUONCalibrationData::CreatePedestals(Int_t runNumber)
{
  /// Create a new pedestal store from the OCDB for a given run
  return dynamic_cast<AliMUONVStore*>(CreateObject(runNumber,"MUON/Calib/Pedestals"));
}

//_____________________________________________________________________________
AliMUONVStore*
AliMUONCalibrationData::CreateRegionalTriggerBoardMasks(Int_t runNumber)
{
  /// Create the internal store for RegionalTriggerBoardMasks from OCDB

  return dynamic_cast<AliMUONVStore*>(CreateObject(runNumber,"MUON/Calib/RegionalTriggerBoardMasks"));
}

//_____________________________________________________________________________
AliMUONTriggerEfficiencyCells*
AliMUONCalibrationData::CreateTriggerEfficiency(Int_t runNumber)
{
  /// Create trigger efficiency object from OCBD

  return dynamic_cast<AliMUONTriggerEfficiencyCells*>(CreateObject(runNumber,"MUON/Calib/TriggerEfficiency"));
}

//_____________________________________________________________________________
AliMUONTriggerLut*
AliMUONCalibrationData::CreateTriggerLut(Int_t runNumber)
{
  /// Create trigger LUT from OCDB

  return dynamic_cast<AliMUONTriggerLut*>(CreateObject(runNumber,"MUON/Calib/TriggerLut"));
}

//_____________________________________________________________________________
AliMUONVStore*
AliMUONCalibrationData::Gains() const
{
  /// Create (if needed) and return the internal store for gains.
  if (!fGains)
  {
    fGains = CreateGains(fRunNumber);
  }
  return fGains;
}

//_____________________________________________________________________________
AliMUONVCalibParam*
AliMUONCalibrationData::Gains(Int_t detElemId, Int_t manuId) const
{
/// Return the gains for a given (detElemId, manuId) pair
/// Note that, unlike the DeadChannel case, if the result is 0x0, that's an
/// error (meaning that we should get gains for all channels).

  AliMUONVStore* gains = Gains();
  if (!gains)
  {
    return 0x0;
  }

  return static_cast<AliMUONVCalibParam*>(gains->FindObject(detElemId,manuId));
}

//_____________________________________________________________________________
AliMUONVCalibParam*
AliMUONCalibrationData::GlobalTriggerBoardMasks() const
{
  /// Return the masks for the global trigger board.

  if (!fGlobalTriggerBoardMasks)
  {
    fGlobalTriggerBoardMasks = CreateGlobalTriggerBoardMasks(fRunNumber);
  }
  return fGlobalTriggerBoardMasks;
}

//_____________________________________________________________________________
TMap*
AliMUONCalibrationData::HV() const
{
  /// Return the calibration for a given (detElemId, manuId) pair

  if (!fHV)
  {
    fHV = CreateHV(fRunNumber);
  }
  return fHV;
}

//_____________________________________________________________________________
AliMUONVStore*
AliMUONCalibrationData::Neighbours() const
{
  /// Create (if needed) and return the internal store for neighbours.
  if (!fNeighbours)
  {
    fNeighbours = CreateNeighbours(fRunNumber);
  }
  return fNeighbours;
}

//_____________________________________________________________________________
AliMUONVCalibParam*
AliMUONCalibrationData::LocalTriggerBoardMasks(Int_t localBoardNumber) const
{
/// Return the masks for a given trigger local board.

  if (!fLocalTriggerBoardMasks)
  {
    fLocalTriggerBoardMasks = CreateLocalTriggerBoardMasks(fRunNumber);
  }

  if ( fLocalTriggerBoardMasks )
  {
    AliMUONVCalibParam* ltbm =
      static_cast<AliMUONVCalibParam*>(fLocalTriggerBoardMasks->FindObject(localBoardNumber));
    if (!ltbm)
    {
      AliError(Form("Could not get mask for localBoardNumber=%d",localBoardNumber));
    }
    return ltbm;
  }
  return 0x0;
}

//_____________________________________________________________________________
AliMUONVStore*
AliMUONCalibrationData::Pedestals() const
{
  /// Return pedestals
  if (!fPedestals)
  {
    fPedestals = CreatePedestals(fRunNumber);
  }
  return fPedestals;
}

//_____________________________________________________________________________
AliMUONVCalibParam*
AliMUONCalibrationData::Pedestals(Int_t detElemId, Int_t manuId) const
{
  /// Return the pedestals for a given (detElemId, manuId) pair.
  /// A return value of 0x0 is considered an error, meaning we should get
  /// pedestals for all channels.

  AliMUONVStore* pedestals = Pedestals();
  if (!pedestals)
  {
    return 0x0;
  }

  return static_cast<AliMUONVCalibParam*>(pedestals->FindObject(detElemId,manuId));
}

//_____________________________________________________________________________
void
AliMUONCalibrationData::Print(Option_t*) const
{
  /// A very basic dump of our guts.

  cout << "RunNumber " << RunNumber()
  << " fGains=" << fGains
  << " fPedestals=" << fPedestals
  << " fHV=" << fHV
  << " fLocalTriggerBoardMasks=" << fLocalTriggerBoardMasks
  << " fRegionalTriggerBoardMasks=" << fRegionalTriggerBoardMasks
  << " fGlobalTriggerBoardMasks=" << fGlobalTriggerBoardMasks
  << " fTriggerLut=" << fTriggerLut
  << endl;
}

//_____________________________________________________________________________
AliMUONVCalibParam*
AliMUONCalibrationData::RegionalTriggerBoardMasks(Int_t regionalBoardNumber) const
{
/// Return the masks for a given trigger regional board.

  if ( !fRegionalTriggerBoardMasks )
  {
    fRegionalTriggerBoardMasks = CreateRegionalTriggerBoardMasks(fRunNumber);
  }

  if ( fRegionalTriggerBoardMasks )
  {
    AliMUONVCalibParam* rtbm =
      static_cast<AliMUONVCalibParam*>(fRegionalTriggerBoardMasks->FindObject(regionalBoardNumber));

    if (!rtbm)
    {
      AliError(Form("Could not get mask for regionalBoard index=%d",regionalBoardNumber));
    }
    return rtbm;
  }
  return 0x0;
}

//_____________________________________________________________________________
AliMUONTriggerEfficiencyCells*
AliMUONCalibrationData::TriggerEfficiency() const
{
/// Return the trigger efficiency.

  if (!fTriggerEfficiency)
  {
    fTriggerEfficiency = CreateTriggerEfficiency(fRunNumber);
  }
  return fTriggerEfficiency;
}

//_____________________________________________________________________________
AliMUONTriggerLut*
AliMUONCalibrationData::TriggerLut() const
{
/// Return the trigger look up table.

  if (!fTriggerLut)
  {
    fTriggerLut = CreateTriggerLut(fRunNumber);
  }
  return fTriggerLut;
}

//_____________________________________________________________________________
void
AliMUONCalibrationData::Reset()
{
/// Reset all data

  delete fPedestals;
  fPedestals = 0x0;
  delete fGains;
  fGains = 0x0;
  delete fHV;
  fHV = 0x0;
  delete fLocalTriggerBoardMasks;
  fLocalTriggerBoardMasks = 0x0;
  delete fRegionalTriggerBoardMasks;
  fRegionalTriggerBoardMasks = 0x0;
  delete fGlobalTriggerBoardMasks;
  fGlobalTriggerBoardMasks = 0x0;
  delete fTriggerLut;
  fTriggerLut = 0x0;
  delete fTriggerEfficiency;
  fTriggerEfficiency = 0x0;
  delete fCapacitances;
  fCapacitances = 0x0;
  delete fNeighbours;
  fNeighbours = 0x0;
}

<commit_msg>Do not set default CDB storage in this class, return error if it is not set. (Laurent)<commit_after>/**************************************************************************
* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
*                                                                        *
* Author: The ALICE Off-line Project.                                    *
* Contributors are mentioned in the code where appropriate.              *
*                                                                        *
* Permission to use, copy, modify and distribute this software and its   *
* documentation strictly for non-commercial purposes is hereby granted   *
* without fee, provided that the above copyright notice appears in all   *
* copies and that both the copyright notice and this permission notice   *
* appear in the supporting documentation. The authors make no claims     *
* about the suitability of this software for any purpose. It is          *
* provided "as is" without express or implied warranty.                  *
**************************************************************************/

// $Id$

#include "AliMUONCalibrationData.h"

#include "AliCDBEntry.h"
#include "AliCDBManager.h"
#include "AliCodeTimer.h"
#include "AliLog.h"
#include "AliMUONTriggerEfficiencyCells.h"
#include "AliMUONTriggerLut.h"
#include "AliMUONVStore.h"
#include "AliMUONVStore.h"
#include "AliMUONVCalibParam.h"
#include <Riostream.h>
#include <TClass.h>
#include <TMap.h>

//-----------------------------------------------------------------------------
/// \class AliMUONCalibrationData
///
/// For the moment, this class stores pedestals, gains, hv (for tracker)
/// and lut, masks and efficiencies (for trigger) that are fetched from the CDB.
///
/// This class is to be considered as a convenience class.
/// Its aim is to ease retrieval of calibration data from the
/// condition database.
///
/// It acts as a "facade" to a bunch of underlying
/// containers/calibration classes.
///
/// \author Laurent Aphecetche
//-----------------------------------------------------------------------------

/// \cond CLASSIMP
ClassImp(AliMUONCalibrationData)
/// \endcond

//_____________________________________________________________________________
AliMUONCalibrationData::AliMUONCalibrationData(Int_t runNumber,
                                               Bool_t deferredInitialization)
: TObject(),
fIsValid(kTRUE),
fRunNumber(runNumber),
fGains(0x0),
fPedestals(0x0),
fHV(0x0),
fLocalTriggerBoardMasks(0x0),
fRegionalTriggerBoardMasks(0x0),
fGlobalTriggerBoardMasks(0x0),
fTriggerLut(0x0),
fTriggerEfficiency(0x0),
fCapacitances(0x0),
fNeighbours(0x0)
{
/// Default ctor.

  // If deferredInitialization is false, we read *all* calibrations
  // at once.
  // So when using this class to access only one kind of calibrations (e.g.
  // only pedestals), you should put deferredInitialization to kTRUE, which
  // will instruct this object to fetch the data only when neeeded.

  if ( deferredInitialization == kFALSE )
  {
    Gains();
    Pedestals();
    HV();
    LocalTriggerBoardMasks(0);
    RegionalTriggerBoardMasks(0);
    GlobalTriggerBoardMasks();
    TriggerLut();
    TriggerEfficiency();
    Capacitances();
    Neighbours();
  }
}

//_____________________________________________________________________________
AliMUONCalibrationData::~AliMUONCalibrationData()
{
  /// Destructor. Note that we're the owner of our pointers.
  Reset();
}

//_____________________________________________________________________________
AliMUONVStore*
AliMUONCalibrationData::Capacitances() const
{
  /// Create (if needed) and return the internal store for capacitances.

  if (!fCapacitances)
  {
    fCapacitances = CreateCapacitances(fRunNumber);
  }
  return fCapacitances;
}

//_____________________________________________________________________________
AliMUONVStore*
AliMUONCalibrationData::CreateCapacitances(Int_t runNumber)
{
  /// Create capa store from OCDB for a given run

  return dynamic_cast<AliMUONVStore*>(CreateObject(runNumber,"MUON/Calib/Capacitances"));
}

//_____________________________________________________________________________
AliMUONVStore*
AliMUONCalibrationData::CreateGains(Int_t runNumber)
{
  /// Create a new gain store from the OCDB for a given run
  return dynamic_cast<AliMUONVStore*>(CreateObject(runNumber,"MUON/Calib/Gains"));
}

//_____________________________________________________________________________
AliMUONVCalibParam*
AliMUONCalibrationData::CreateGlobalTriggerBoardMasks(Int_t runNumber)
{
  /// Create the internal store for GlobalTriggerBoardMasks from OCDB

  return dynamic_cast<AliMUONVCalibParam*>(CreateObject(runNumber,"MUON/Calib/GlobalTriggerBoardMasks"));
}

//_____________________________________________________________________________
TMap*
AliMUONCalibrationData::CreateHV(Int_t runNumber)
{
  /// Create a new HV map from the OCDB for a given run
  return dynamic_cast<TMap*>(CreateObject(runNumber,"MUON/Calib/HV"));
}

//_____________________________________________________________________________
AliMUONVStore*
AliMUONCalibrationData::CreateLocalTriggerBoardMasks(Int_t runNumber)
{
  /// Get the internal store for LocalTriggerBoardMasks from OCDB

  return dynamic_cast<AliMUONVStore*>(CreateObject(runNumber,"MUON/Calib/LocalTriggerBoardMasks"));
}

//_____________________________________________________________________________
AliMUONVStore*
AliMUONCalibrationData::CreateNeighbours(Int_t runNumber)
{
  /// Create a neighbour store from the OCDB for a given run
  return dynamic_cast<AliMUONVStore*>(CreateObject(runNumber,"MUON/Calib/Neighbours"));
}

//_____________________________________________________________________________
TObject*
AliMUONCalibrationData::CreateObject(Int_t runNumber, const char* path)
{
  /// Access the CDB for a given path (e.g. MUON/Calib/Pedestals),
  /// and return the corresponding TObject.

  AliCodeTimerAutoClass(Form("%d : %s",runNumber,path));

  AliCDBManager* man = AliCDBManager::Instance();

  if ( !man->IsDefaultStorageSet() )
  {
    AliErrorClass("CDB Storage not set. Must use AliCDBManager::Instance()->SetDefaultStorage() first.");
    return 0x0;
  }

  Bool_t cacheStatus = man->GetCacheFlag();

  man->SetCacheFlag(kFALSE);

  AliCDBEntry* entry =  AliCDBManager::Instance()->Get(path,runNumber);

  man->SetCacheFlag(cacheStatus);

  if (entry)
  {
    TObject* object = entry->GetObject();
    entry->SetOwner(kFALSE);
    delete entry;
    return object;
  }

  return 0x0;
}

//_____________________________________________________________________________
AliMUONVStore*
AliMUONCalibrationData::CreatePedestals(Int_t runNumber)
{
  /// Create a new pedestal store from the OCDB for a given run
  return dynamic_cast<AliMUONVStore*>(CreateObject(runNumber,"MUON/Calib/Pedestals"));
}

//_____________________________________________________________________________
AliMUONVStore*
AliMUONCalibrationData::CreateRegionalTriggerBoardMasks(Int_t runNumber)
{
  /// Create the internal store for RegionalTriggerBoardMasks from OCDB

  return dynamic_cast<AliMUONVStore*>(CreateObject(runNumber,"MUON/Calib/RegionalTriggerBoardMasks"));
}

//_____________________________________________________________________________
AliMUONTriggerEfficiencyCells*
AliMUONCalibrationData::CreateTriggerEfficiency(Int_t runNumber)
{
  /// Create trigger efficiency object from OCBD

  return dynamic_cast<AliMUONTriggerEfficiencyCells*>(CreateObject(runNumber,"MUON/Calib/TriggerEfficiency"));
}

//_____________________________________________________________________________
AliMUONTriggerLut*
AliMUONCalibrationData::CreateTriggerLut(Int_t runNumber)
{
  /// Create trigger LUT from OCDB

  return dynamic_cast<AliMUONTriggerLut*>(CreateObject(runNumber,"MUON/Calib/TriggerLut"));
}

//_____________________________________________________________________________
AliMUONVStore*
AliMUONCalibrationData::Gains() const
{
  /// Create (if needed) and return the internal store for gains.
  if (!fGains)
  {
    fGains = CreateGains(fRunNumber);
  }
  return fGains;
}

//_____________________________________________________________________________
AliMUONVCalibParam*
AliMUONCalibrationData::Gains(Int_t detElemId, Int_t manuId) const
{
/// Return the gains for a given (detElemId, manuId) pair
/// Note that, unlike the DeadChannel case, if the result is 0x0, that's an
/// error (meaning that we should get gains for all channels).

  AliMUONVStore* gains = Gains();
  if (!gains)
  {
    return 0x0;
  }

  return static_cast<AliMUONVCalibParam*>(gains->FindObject(detElemId,manuId));
}

//_____________________________________________________________________________
AliMUONVCalibParam*
AliMUONCalibrationData::GlobalTriggerBoardMasks() const
{
  /// Return the masks for the global trigger board.

  if (!fGlobalTriggerBoardMasks)
  {
    fGlobalTriggerBoardMasks = CreateGlobalTriggerBoardMasks(fRunNumber);
  }
  return fGlobalTriggerBoardMasks;
}

//_____________________________________________________________________________
TMap*
AliMUONCalibrationData::HV() const
{
  /// Return the calibration for a given (detElemId, manuId) pair

  if (!fHV)
  {
    fHV = CreateHV(fRunNumber);
  }
  return fHV;
}

//_____________________________________________________________________________
AliMUONVStore*
AliMUONCalibrationData::Neighbours() const
{
  /// Create (if needed) and return the internal store for neighbours.
  if (!fNeighbours)
  {
    fNeighbours = CreateNeighbours(fRunNumber);
  }
  return fNeighbours;
}

//_____________________________________________________________________________
AliMUONVCalibParam*
AliMUONCalibrationData::LocalTriggerBoardMasks(Int_t localBoardNumber) const
{
/// Return the masks for a given trigger local board.

  if (!fLocalTriggerBoardMasks)
  {
    fLocalTriggerBoardMasks = CreateLocalTriggerBoardMasks(fRunNumber);
  }

  if ( fLocalTriggerBoardMasks )
  {
    AliMUONVCalibParam* ltbm =
      static_cast<AliMUONVCalibParam*>(fLocalTriggerBoardMasks->FindObject(localBoardNumber));
    if (!ltbm)
    {
      AliError(Form("Could not get mask for localBoardNumber=%d",localBoardNumber));
    }
    return ltbm;
  }
  return 0x0;
}

//_____________________________________________________________________________
AliMUONVStore*
AliMUONCalibrationData::Pedestals() const
{
  /// Return pedestals
  if (!fPedestals)
  {
    fPedestals = CreatePedestals(fRunNumber);
  }
  return fPedestals;
}

//_____________________________________________________________________________
AliMUONVCalibParam*
AliMUONCalibrationData::Pedestals(Int_t detElemId, Int_t manuId) const
{
  /// Return the pedestals for a given (detElemId, manuId) pair.
  /// A return value of 0x0 is considered an error, meaning we should get
  /// pedestals for all channels.

  AliMUONVStore* pedestals = Pedestals();
  if (!pedestals)
  {
    return 0x0;
  }

  return static_cast<AliMUONVCalibParam*>(pedestals->FindObject(detElemId,manuId));
}

//_____________________________________________________________________________
void
AliMUONCalibrationData::Print(Option_t*) const
{
  /// A very basic dump of our guts.

  cout << "RunNumber " << RunNumber()
  << " fGains=" << fGains
  << " fPedestals=" << fPedestals
  << " fHV=" << fHV
  << " fLocalTriggerBoardMasks=" << fLocalTriggerBoardMasks
  << " fRegionalTriggerBoardMasks=" << fRegionalTriggerBoardMasks
  << " fGlobalTriggerBoardMasks=" << fGlobalTriggerBoardMasks
  << " fTriggerLut=" << fTriggerLut
  << endl;
}

//_____________________________________________________________________________
AliMUONVCalibParam*
AliMUONCalibrationData::RegionalTriggerBoardMasks(Int_t regionalBoardNumber) const
{
/// Return the masks for a given trigger regional board.

  if ( !fRegionalTriggerBoardMasks )
  {
    fRegionalTriggerBoardMasks = CreateRegionalTriggerBoardMasks(fRunNumber);
  }

  if ( fRegionalTriggerBoardMasks )
  {
    AliMUONVCalibParam* rtbm =
      static_cast<AliMUONVCalibParam*>(fRegionalTriggerBoardMasks->FindObject(regionalBoardNumber));

    if (!rtbm)
    {
      AliError(Form("Could not get mask for regionalBoard index=%d",regionalBoardNumber));
    }
    return rtbm;
  }
  return 0x0;
}

//_____________________________________________________________________________
AliMUONTriggerEfficiencyCells*
AliMUONCalibrationData::TriggerEfficiency() const
{
/// Return the trigger efficiency.

  if (!fTriggerEfficiency)
  {
    fTriggerEfficiency = CreateTriggerEfficiency(fRunNumber);
  }
  return fTriggerEfficiency;
}

//_____________________________________________________________________________
AliMUONTriggerLut*
AliMUONCalibrationData::TriggerLut() const
{
/// Return the trigger look up table.

  if (!fTriggerLut)
  {
    fTriggerLut = CreateTriggerLut(fRunNumber);
  }
  return fTriggerLut;
}

//_____________________________________________________________________________
void
AliMUONCalibrationData::Reset()
{
/// Reset all data

  delete fPedestals;
  fPedestals = 0x0;
  delete fGains;
  fGains = 0x0;
  delete fHV;
  fHV = 0x0;
  delete fLocalTriggerBoardMasks;
  fLocalTriggerBoardMasks = 0x0;
  delete fRegionalTriggerBoardMasks;
  fRegionalTriggerBoardMasks = 0x0;
  delete fGlobalTriggerBoardMasks;
  fGlobalTriggerBoardMasks = 0x0;
  delete fTriggerLut;
  fTriggerLut = 0x0;
  delete fTriggerEfficiency;
  fTriggerEfficiency = 0x0;
  delete fCapacitances;
  fCapacitances = 0x0;
  delete fNeighbours;
  fNeighbours = 0x0;
}

<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

// $Id$
//
/// \ingroup macros
/// \file MUONGenerateGeometryData.C
/// \brief Macro for generating the geometry data files:
///  transform.dat, svmap.dat.
///
/// To be run from aliroot:
///
/// .x MUONGenerateGeometryData.C
///
/// The generated files do not replace the existing ones
/// but have different names (with extension ".out").
///
/// \author: I. Hrivnacova, IPN Orsay

#if !defined(__CINT__) || defined(__MAKECINT__)

#include "AliMUON.h"
#include "AliMUONGeometryBuilder.h"
#include "AliMUONGeometryTransformer.h"

#include "AliRun.h"

#include <Riostream.h>

#endif

void MUONGenerateGeometryData(Bool_t transforms = true,
                              Bool_t svmaps = true,
                              Bool_t writeEnvelopes = true)
{
/// \param transforms      option to generete transform.dat
/// \param svmaps          option to generete svmap.dat
/// \param writeEnvelope   option to include virtual envelopes
///                        in the volume paths

  // Initialize
  gAlice->Init("$ALICE_ROOT/MUON/Config.C");
  cout << "Init done " << endl;

  // Get MUON detector
  AliMUON* muon = (AliMUON*)gAlice->GetModule("MUON");
  if (!muon) {
    cerr << "MUON detector not defined." << endl;
    return;
  }

  // Get geometry builder
  AliMUONGeometryBuilder* builder = muon ->GetGeometryBuilder();

  if (transforms) {
    cout << "Generating transformation file ..." << endl;
    builder->GetTransformer()->WriteTransformations("transform.dat.out");
  }

  if (svmaps) {
    cout << "Generating svmaps file ..." << endl;
    builder->WriteSVMaps("svmap.dat.out", true, writeEnvelopes);
  }
}
<commit_msg>Adding setting default CDB storage and run number, now required by the framework. (Javier)<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

// $Id$
//
/// \ingroup macros
/// \file MUONGenerateGeometryData.C
/// \brief Macro for generating the geometry data files:
///  transform.dat, svmap.dat.
///
/// To be run from aliroot:
///
/// .x MUONGenerateGeometryData.C
///
/// The generated files do not replace the existing ones
/// but have different names (with extension ".out").
///
/// \author: I. Hrivnacova, IPN Orsay

#if !defined(__CINT__) || defined(__MAKECINT__)

#include "AliMUON.h"
#include "AliMUONGeometryBuilder.h"
#include "AliMUONGeometryTransformer.h"

#include "AliRun.h"
#include "AliCDBManager.h"

#include <Riostream.h>

#endif

void MUONGenerateGeometryData(Bool_t transforms = true,
                              Bool_t svmaps = true,
                              Bool_t writeEnvelopes = true)
{
/// \param transforms      option to generete transform.dat
/// \param svmaps          option to generete svmap.dat
/// \param writeEnvelope   option to include virtual envelopes
///                        in the volume paths

  // Default CDB and run number
  AliCDBManager* man = AliCDBManager::Instance();
  man->SetDefaultStorage("local://$ALICE_ROOT");
  man->SetRun(0);

  // Initialize
  gAlice->Init("$ALICE_ROOT/MUON/Config.C");
  cout << "Init done " << endl;

  // Get MUON detector
  AliMUON* muon = (AliMUON*)gAlice->GetModule("MUON");
  if (!muon) {
    cerr << "MUON detector not defined." << endl;
    return;
  }

  // Get geometry builder
  AliMUONGeometryBuilder* builder = muon ->GetGeometryBuilder();

  if (transforms) {
    cout << "Generating transformation file ..." << endl;
    builder->GetTransformer()->WriteTransformations("transform.dat.out");
  }

  if (svmaps) {
    cout << "Generating svmaps file ..." << endl;
    builder->WriteSVMaps("svmap.dat.out", true, writeEnvelopes);
  }
}
<|endoftext|>