<commit_before>/*
 * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <stdexcept>
#include "instanceNormalizationPlugin.h"

using namespace nvinfer1;
using nvinfer1::plugin::InstanceNormalizationPlugin;
using nvinfer1::plugin::InstanceNormalizationPluginCreator;

#define CHECK_CUDA(call)                                                                                \
    do                                                                                \
    {                                                                                \
        cudaError_t status = call;                                                                                \
        if (status != cudaSuccess)                                                                                \
        {                                                                                \
            return status;                                                                                \
        }                                                                                \
    } while (0)

#define CHECK_CUDNN(call)                                                                                \
    do                                                                                \
    {                                                                                \
        cudnnStatus_t status = call;                                                                                \
        if (status != CUDNN_STATUS_SUCCESS)                                                                            \
        {                                                                                \
            return status;                                                                                \
        }                                                                                \
    } while (0)

inline bool is_CHW(nvinfer1::Dims const& dims)
{
    return (dims.nbDims == 3 && dims.type[0] == nvinfer1::DimensionType::kCHANNEL
        && dims.type[1] == nvinfer1::DimensionType::kSPATIAL && dims.type[2] == nvinfer1::DimensionType::kSPATIAL);
}

// This is derived from: https://fgiesen.wordpress.com/2012/03/28/half-to-float-done-quic/
inline float half_to_float_fast(unsigned short value)
{
    union F32
    {
        unsigned int u;
        float f;
    };
    static const F32 magic = {(254 - 15) << 23};
    static const F32 was_infnan = {(127 + 16) << 23};
    F32 result;
    result.u = (value & 0x7fff) << 13; // exponent/mantissa bits
    result.f *= magic.f;               // exponent adjust
    if (result.f >= was_infnan.f)
    { // make sure Inf/NaN survive
        result.u |= 255 << 23;
    }
    result.u |= (value & 0x8000) << 16; // sign bit
    return result.f;
}

cudnnStatus_t convert_trt2cudnn_dtype(nvinfer1::DataType trt_dtype, cudnnDataType_t* cudnn_dtype)
{
    switch (trt_dtype)
    {
    case nvinfer1::DataType::kFLOAT: *cudnn_dtype = CUDNN_DATA_FLOAT; break;
    case nvinfer1::DataType::kHALF: *cudnn_dtype = CUDNN_DATA_HALF; break;
    default: return CUDNN_STATUS_BAD_PARAM;
    }
    return CUDNN_STATUS_SUCCESS;
}

namespace {
    constexpr const char* INSTANCE_PLUGIN_VERSION{"001"};
    constexpr const char* INSTANCE_PLUGIN_NAME{"InstanceNormalization_TRT"};
}

PluginFieldCollection InstanceNormalizationPluginCreator::mFC{};
std::vector<PluginField> InstanceNormalizationPluginCreator::mPluginAttributes;

InstanceNormalizationPlugin::InstanceNormalizationPlugin(
    float epsilon, const std::vector<float>& scale, const std::vector<float>& bias)
    : _epsilon(epsilon)
    , _nchan(scale.size())
    , _h_scale(scale)
    , _h_bias(bias)
    , _initialized(false)
{
    ASSERT(scale.size() == bias.size());
}

InstanceNormalizationPlugin::InstanceNormalizationPlugin(
    float epsilon, nvinfer1::Weights const& scale, nvinfer1::Weights const& bias)
    : _epsilon(epsilon)
    , _nchan(scale.count)
    , _initialized(false)
{
    ASSERT(scale.count == bias.count);
    if (scale.type == nvinfer1::DataType::kFLOAT)
    {
        _h_scale.assign((float*) scale.values, (float*) scale.values + scale.count);
    }
    else if (scale.type == nvinfer1::DataType::kHALF)
    {
        _h_scale.reserve(_nchan);
        for (int c = 0; c < _nchan; ++c)
        {
            unsigned short value = ((unsigned short*) scale.values)[c];
            _h_scale.push_back(half_to_float_fast(value));
        }
    }
    else
    {
        throw std::runtime_error("Unsupported scale dtype");
    }
    if (bias.type == nvinfer1::DataType::kFLOAT)
    {
        _h_bias.assign((float*) bias.values, (float*) bias.values + bias.count);
    }
    else if (bias.type == nvinfer1::DataType::kHALF)
    {
        _h_bias.reserve(_nchan);
        for (int c = 0; c < _nchan; ++c)
        {
            unsigned short value = ((unsigned short*) bias.values)[c];
            _h_bias.push_back(half_to_float_fast(value));
        }
    }
    else
    {
        throw std::runtime_error("Unsupported bias dtype");
    }
}

InstanceNormalizationPlugin::InstanceNormalizationPlugin(void const* serialData, size_t serialLength) : _initialized(false)
{
    deserialize_value(&serialData, &serialLength, &_epsilon);
    deserialize_value(&serialData, &serialLength, &_nchan);
    deserialize_value(&serialData, &serialLength, &_h_scale);
    deserialize_value(&serialData, &serialLength, &_h_bias);
}

InstanceNormalizationPlugin::~InstanceNormalizationPlugin()
{
    terminate();
}

// InstanceNormalizationPlugin returns one output.
int InstanceNormalizationPlugin::getNbOutputs() const
{
    return 1;
}

DimsExprs InstanceNormalizationPlugin::getOutputDimensions(
    int outputIndex, const nvinfer1::DimsExprs* inputs, int nbInputs, nvinfer1::IExprBuilder& exprBuilder)
{
    nvinfer1::DimsExprs output(inputs[0]);
    return output;
}

int InstanceNormalizationPlugin::initialize()
{
    _initialized = true;
    CHECK_CUDNN(cudnnCreate(&_cudnn_handle));
    CHECK_CUDNN(cudnnCreateTensorDescriptor(&_b_desc));
    CHECK_CUDNN(cudnnCreateTensorDescriptor(&_x_desc));
    CHECK_CUDNN(cudnnCreateTensorDescriptor(&_y_desc));
    return 0;
}

void InstanceNormalizationPlugin::terminate()
{
    if (!_initialized)
    {
        return;
    }
    cudnnDestroyTensorDescriptor(_y_desc);
    cudnnDestroyTensorDescriptor(_x_desc);
    cudnnDestroyTensorDescriptor(_b_desc);
    cudnnDestroy(_cudnn_handle);
    _initialized = false;
}

size_t InstanceNormalizationPlugin::getWorkspaceSize(const nvinfer1::PluginTensorDesc* inputs, int nbInputs, const nvinfer1::PluginTensorDesc* outputs, int nbOutputs) const
{
    return 0;
}

int InstanceNormalizationPlugin::enqueue(const nvinfer1::PluginTensorDesc* inputDesc,
    const nvinfer1::PluginTensorDesc* outputDesc, const void* const* inputs, void* const* outputs, void* workspace,
    cudaStream_t stream)
{
    nvinfer1::Dims input_dims = inputDesc[0].dims;
    int n = input_dims.d[0];
    int c = input_dims.d[1];
    int h = input_dims.d[2];
    int w = input_dims.d[3];
    size_t nchan_bytes = c * sizeof(float);

    // Note: We repeat the data for each batch entry so that we can do the full
    //       computation in a single CUDNN call in enqueue().
    CHECK_CUDA(cudaMalloc((void**) &_d_scale, n * nchan_bytes));
    CHECK_CUDA(cudaMalloc((void**) &_d_bias, n * nchan_bytes));
    for (int i = 0; i < n; ++i)
    {
        CHECK_CUDA(cudaMemcpy(_d_scale + i * c, _h_scale.data(), nchan_bytes, cudaMemcpyHostToDevice));
        CHECK_CUDA(cudaMemcpy(_d_bias + i * c, _h_bias.data(), nchan_bytes, cudaMemcpyHostToDevice));
    }

    CHECK_CUDNN(cudnnSetTensor4dDescriptor(_b_desc, CUDNN_TENSOR_NCHW, CUDNN_DATA_FLOAT, 1, n * c, 1, 1));
    cudnnDataType_t cudnn_dtype;
    CHECK_CUDNN(convert_trt2cudnn_dtype(inputDesc[0].type, &cudnn_dtype));
    CHECK_CUDNN(cudnnSetTensor4dDescriptor(_x_desc, CUDNN_TENSOR_NCHW, cudnn_dtype, 1, n * c, h, w));
    CHECK_CUDNN(cudnnSetTensor4dDescriptor(_y_desc, CUDNN_TENSOR_NCHW, cudnn_dtype, 1, n * c, h, w));
    float alpha = 1;
    float beta = 0;
    void const* x_ptr = inputs[0];
    void* y_ptr = outputs[0];
    CHECK_CUDNN(cudnnSetStream(_cudnn_handle, stream));
    // Note: Use of CUDNN_BATCHNORM_SPATIAL_PERSISTENT can cause numerical
    //       overflows (NaNs) for fp32 data in some circumstances. The lower-
    //       performance CUDNN_BATCHNORM_SPATIAL should be used if this is not
    //       acceptable.
    CHECK_CUDNN(cudnnBatchNormalizationForwardTraining(_cudnn_handle, CUDNN_BATCHNORM_SPATIAL_PERSISTENT, &alpha, &beta,
        _x_desc, x_ptr, _y_desc, y_ptr, _b_desc, _d_scale, _d_bias, 1., nullptr, nullptr, _epsilon, nullptr, nullptr));
    cudaFree(_d_bias);
    cudaFree(_d_scale);
    return 0;
}

size_t InstanceNormalizationPlugin::getSerializationSize() const
{
    return (serialized_size(_epsilon) +
            serialized_size(_nchan) +
            serialized_size(_h_scale) +
            serialized_size(_h_bias));
}

void InstanceNormalizationPlugin::serialize(void *buffer) const
{
    serialize_value(&buffer, _epsilon);
    serialize_value(&buffer, _nchan);
    serialize_value(&buffer, _h_scale);
    serialize_value(&buffer, _h_bias);
}

bool InstanceNormalizationPlugin::supportsFormatCombination(
    int pos, const nvinfer1::PluginTensorDesc* inOut, int nbInputs, int nbOutputs)
{
    ASSERT(inOut && pos < (nbInputs + nbOutputs));
    return ((inOut[pos].type == nvinfer1::DataType::kFLOAT || inOut[pos].type == nvinfer1::DataType::kHALF)
        && inOut[pos].format == nvinfer1::PluginFormat::kNCHW);
}

const char* InstanceNormalizationPlugin::getPluginType() const
{
    return INSTANCE_PLUGIN_NAME;
}

const char* InstanceNormalizationPlugin::getPluginVersion() const
{
    return INSTANCE_PLUGIN_VERSION;
}

void InstanceNormalizationPlugin::destroy()
{
    delete this;
}

IPluginV2DynamicExt* InstanceNormalizationPlugin::clone() const
{
    return new InstanceNormalizationPlugin{_epsilon, _h_scale, _h_bias};
}

// Set plugin namespace
void InstanceNormalizationPlugin::setPluginNamespace(const char* pluginNamespace)
{
    mPluginNamespace = pluginNamespace;
}

const char* InstanceNormalizationPlugin::getPluginNamespace() const
{
    return mPluginNamespace;
}

nvinfer1::DataType InstanceNormalizationPlugin::getOutputDataType(
    int index, const nvinfer1::DataType* inputTypes, int nbInputs) const
{
    ASSERT(inputTypes && nbInputs > 0 && index == 0);
    return inputTypes[0];
}

// Attach the plugin object to an execution context and grant the plugin the access to some context resource.
void InstanceNormalizationPlugin::attachToContext(cudnnContext* cudnnContext, cublasContext* cublasContext, IGpuAllocator* gpuAllocator)
{
}

// Detach the plugin object from its execution context.
void InstanceNormalizationPlugin::detachFromContext() {}

void InstanceNormalizationPlugin::configurePlugin(const nvinfer1::DynamicPluginTensorDesc* in, int nbInputs,
    const nvinfer1::DynamicPluginTensorDesc* out, int nbOutputs)
{
    for (int i = 0; i < nbInputs; i++)
    {
      for (int j = 0; j < in[0].desc.dims.nbDims; j++)
      {
        // Do not support dynamic dimensions
        ASSERT(in[0].desc.dims.d[j] != -1);
      }
    }
}

// InstanceNormalizationPluginCreator methods
InstanceNormalizationPluginCreator::InstanceNormalizationPluginCreator()
{
    mPluginAttributes.emplace_back(PluginField("epsilon", nullptr, PluginFieldType::kFLOAT32, 1));
    mPluginAttributes.emplace_back(PluginField("scales", nullptr, PluginFieldType::kFLOAT32, 1));
    mPluginAttributes.emplace_back(PluginField("bias", nullptr, PluginFieldType::kFLOAT32, 1));

    mFC.nbFields = mPluginAttributes.size();
    mFC.fields = mPluginAttributes.data();
}

const char* InstanceNormalizationPluginCreator::getPluginName() const
{
    return INSTANCE_PLUGIN_NAME;
}

const char* InstanceNormalizationPluginCreator::getPluginVersion() const
{
    return INSTANCE_PLUGIN_VERSION;
}

const PluginFieldCollection* InstanceNormalizationPluginCreator::getFieldNames()
{
    return &mFC;
}

IPluginV2DynamicExt* InstanceNormalizationPluginCreator::createPlugin(const char* name, const nvinfer1::PluginFieldCollection* fc)
{
    std::vector<float> scaleValues;
    std::vector<float> biasValues;
    float epsilon {};
    const PluginField* fields = fc->fields;
    for (int i = 0; i < fc->nbFields; ++i)
    {
        const char* attrName = fields[i].name;
        if (!strcmp(attrName, "epsilon"))
        {
            ASSERT(fields[i].type == PluginFieldType::kFLOAT32);
            epsilon= *(static_cast<const float*>(fields[i].data));
        }
        else if (!strcmp(attrName, "scales"))
        {
            ASSERT(fields[i].type == PluginFieldType::kFLOAT32);
            int size = fields[i].length;
            scaleValues.reserve(size);
            const auto* w = static_cast<const float*>(fields[i].data);
            for (int j = 0; j < size; j++)
            {
                scaleValues.push_back(*w);
                w++;
            }
        }
        else if (!strcmp(attrName, "bias"))
        {
            ASSERT(fields[i].type == PluginFieldType::kFLOAT32);
            int size = fields[i].length;
            biasValues.reserve(size);
            const auto* w = static_cast<const float*>(fields[i].data);
            for (int j = 0; j < size; j++)
            {
                biasValues.push_back(*w);
                w++;
            }
        }
    }

    Weights scaleWeights{DataType::kFLOAT, scaleValues.data(), (int64_t) scaleValues.size()};
    Weights biasWeights{DataType::kFLOAT, biasValues.data(), (int64_t) biasValues.size()};

    InstanceNormalizationPlugin* obj = new InstanceNormalizationPlugin(epsilon, scaleWeights, biasWeights);
    obj->setPluginNamespace(mNamespace.c_str());
    return obj;
}

IPluginV2DynamicExt* InstanceNormalizationPluginCreator::deserializePlugin(const char* name, const void* serialData, size_t serialLength)
{
    InstanceNormalizationPlugin* obj = new InstanceNormalizationPlugin{serialData, serialLength};
    obj->setPluginNamespace(mNamespace.c_str());
    return obj;
}
<commit_msg>Correctly set namespace when doing clone in instanceNormalizationPlugin (#318)<commit_after>/*
 * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <stdexcept>
#include "instanceNormalizationPlugin.h"

using namespace nvinfer1;
using nvinfer1::plugin::InstanceNormalizationPlugin;
using nvinfer1::plugin::InstanceNormalizationPluginCreator;

#define CHECK_CUDA(call)                                                                                \
    do                                                                                \
    {                                                                                \
        cudaError_t status = call;                                                                                \
        if (status != cudaSuccess)                                                                                \
        {                                                                                \
            return status;                                                                                \
        }                                                                                \
    } while (0)

#define CHECK_CUDNN(call)                                                                                \
    do                                                                                \
    {                                                                                \
        cudnnStatus_t status = call;                                                                                \
        if (status != CUDNN_STATUS_SUCCESS)                                                                            \
        {                                                                                \
            return status;                                                                                \
        }                                                                                \
    } while (0)

inline bool is_CHW(nvinfer1::Dims const& dims)
{
    return (dims.nbDims == 3 && dims.type[0] == nvinfer1::DimensionType::kCHANNEL
        && dims.type[1] == nvinfer1::DimensionType::kSPATIAL && dims.type[2] == nvinfer1::DimensionType::kSPATIAL);
}

// This is derived from: https://fgiesen.wordpress.com/2012/03/28/half-to-float-done-quic/
inline float half_to_float_fast(unsigned short value)
{
    union F32
    {
        unsigned int u;
        float f;
    };
    static const F32 magic = {(254 - 15) << 23};
    static const F32 was_infnan = {(127 + 16) << 23};
    F32 result;
    result.u = (value & 0x7fff) << 13; // exponent/mantissa bits
    result.f *= magic.f;               // exponent adjust
    if (result.f >= was_infnan.f)
    { // make sure Inf/NaN survive
        result.u |= 255 << 23;
    }
    result.u |= (value & 0x8000) << 16; // sign bit
    return result.f;
}

cudnnStatus_t convert_trt2cudnn_dtype(nvinfer1::DataType trt_dtype, cudnnDataType_t* cudnn_dtype)
{
    switch (trt_dtype)
    {
    case nvinfer1::DataType::kFLOAT: *cudnn_dtype = CUDNN_DATA_FLOAT; break;
    case nvinfer1::DataType::kHALF: *cudnn_dtype = CUDNN_DATA_HALF; break;
    default: return CUDNN_STATUS_BAD_PARAM;
    }
    return CUDNN_STATUS_SUCCESS;
}

namespace {
    constexpr const char* INSTANCE_PLUGIN_VERSION{"001"};
    constexpr const char* INSTANCE_PLUGIN_NAME{"InstanceNormalization_TRT"};
}

PluginFieldCollection InstanceNormalizationPluginCreator::mFC{};
std::vector<PluginField> InstanceNormalizationPluginCreator::mPluginAttributes;

InstanceNormalizationPlugin::InstanceNormalizationPlugin(
    float epsilon, const std::vector<float>& scale, const std::vector<float>& bias)
    : _epsilon(epsilon)
    , _nchan(scale.size())
    , _h_scale(scale)
    , _h_bias(bias)
    , _initialized(false)
{
    ASSERT(scale.size() == bias.size());
}

InstanceNormalizationPlugin::InstanceNormalizationPlugin(
    float epsilon, nvinfer1::Weights const& scale, nvinfer1::Weights const& bias)
    : _epsilon(epsilon)
    , _nchan(scale.count)
    , _initialized(false)
{
    ASSERT(scale.count == bias.count);
    if (scale.type == nvinfer1::DataType::kFLOAT)
    {
        _h_scale.assign((float*) scale.values, (float*) scale.values + scale.count);
    }
    else if (scale.type == nvinfer1::DataType::kHALF)
    {
        _h_scale.reserve(_nchan);
        for (int c = 0; c < _nchan; ++c)
        {
            unsigned short value = ((unsigned short*) scale.values)[c];
            _h_scale.push_back(half_to_float_fast(value));
        }
    }
    else
    {
        throw std::runtime_error("Unsupported scale dtype");
    }
    if (bias.type == nvinfer1::DataType::kFLOAT)
    {
        _h_bias.assign((float*) bias.values, (float*) bias.values + bias.count);
    }
    else if (bias.type == nvinfer1::DataType::kHALF)
    {
        _h_bias.reserve(_nchan);
        for (int c = 0; c < _nchan; ++c)
        {
            unsigned short value = ((unsigned short*) bias.values)[c];
            _h_bias.push_back(half_to_float_fast(value));
        }
    }
    else
    {
        throw std::runtime_error("Unsupported bias dtype");
    }
}

InstanceNormalizationPlugin::InstanceNormalizationPlugin(void const* serialData, size_t serialLength) : _initialized(false)
{
    deserialize_value(&serialData, &serialLength, &_epsilon);
    deserialize_value(&serialData, &serialLength, &_nchan);
    deserialize_value(&serialData, &serialLength, &_h_scale);
    deserialize_value(&serialData, &serialLength, &_h_bias);
}

InstanceNormalizationPlugin::~InstanceNormalizationPlugin()
{
    terminate();
}

// InstanceNormalizationPlugin returns one output.
int InstanceNormalizationPlugin::getNbOutputs() const
{
    return 1;
}

DimsExprs InstanceNormalizationPlugin::getOutputDimensions(
    int outputIndex, const nvinfer1::DimsExprs* inputs, int nbInputs, nvinfer1::IExprBuilder& exprBuilder)
{
    nvinfer1::DimsExprs output(inputs[0]);
    return output;
}

int InstanceNormalizationPlugin::initialize()
{
    _initialized = true;
    CHECK_CUDNN(cudnnCreate(&_cudnn_handle));
    CHECK_CUDNN(cudnnCreateTensorDescriptor(&_b_desc));
    CHECK_CUDNN(cudnnCreateTensorDescriptor(&_x_desc));
    CHECK_CUDNN(cudnnCreateTensorDescriptor(&_y_desc));
    return 0;
}

void InstanceNormalizationPlugin::terminate()
{
    if (!_initialized)
    {
        return;
    }
    cudnnDestroyTensorDescriptor(_y_desc);
    cudnnDestroyTensorDescriptor(_x_desc);
    cudnnDestroyTensorDescriptor(_b_desc);
    cudnnDestroy(_cudnn_handle);
    _initialized = false;
}

size_t InstanceNormalizationPlugin::getWorkspaceSize(const nvinfer1::PluginTensorDesc* inputs, int nbInputs, const nvinfer1::PluginTensorDesc* outputs, int nbOutputs) const
{
    return 0;
}

int InstanceNormalizationPlugin::enqueue(const nvinfer1::PluginTensorDesc* inputDesc,
    const nvinfer1::PluginTensorDesc* outputDesc, const void* const* inputs, void* const* outputs, void* workspace,
    cudaStream_t stream)
{
    nvinfer1::Dims input_dims = inputDesc[0].dims;
    int n = input_dims.d[0];
    int c = input_dims.d[1];
    int h = input_dims.d[2];
    int w = input_dims.d[3];
    size_t nchan_bytes = c * sizeof(float);

    // Note: We repeat the data for each batch entry so that we can do the full
    //       computation in a single CUDNN call in enqueue().
    CHECK_CUDA(cudaMalloc((void**) &_d_scale, n * nchan_bytes));
    CHECK_CUDA(cudaMalloc((void**) &_d_bias, n * nchan_bytes));
    for (int i = 0; i < n; ++i)
    {
        CHECK_CUDA(cudaMemcpy(_d_scale + i * c, _h_scale.data(), nchan_bytes, cudaMemcpyHostToDevice));
        CHECK_CUDA(cudaMemcpy(_d_bias + i * c, _h_bias.data(), nchan_bytes, cudaMemcpyHostToDevice));
    }

    CHECK_CUDNN(cudnnSetTensor4dDescriptor(_b_desc, CUDNN_TENSOR_NCHW, CUDNN_DATA_FLOAT, 1, n * c, 1, 1));
    cudnnDataType_t cudnn_dtype;
    CHECK_CUDNN(convert_trt2cudnn_dtype(inputDesc[0].type, &cudnn_dtype));
    CHECK_CUDNN(cudnnSetTensor4dDescriptor(_x_desc, CUDNN_TENSOR_NCHW, cudnn_dtype, 1, n * c, h, w));
    CHECK_CUDNN(cudnnSetTensor4dDescriptor(_y_desc, CUDNN_TENSOR_NCHW, cudnn_dtype, 1, n * c, h, w));
    float alpha = 1;
    float beta = 0;
    void const* x_ptr = inputs[0];
    void* y_ptr = outputs[0];
    CHECK_CUDNN(cudnnSetStream(_cudnn_handle, stream));
    // Note: Use of CUDNN_BATCHNORM_SPATIAL_PERSISTENT can cause numerical
    //       overflows (NaNs) for fp32 data in some circumstances. The lower-
    //       performance CUDNN_BATCHNORM_SPATIAL should be used if this is not
    //       acceptable.
    CHECK_CUDNN(cudnnBatchNormalizationForwardTraining(_cudnn_handle, CUDNN_BATCHNORM_SPATIAL_PERSISTENT, &alpha, &beta,
        _x_desc, x_ptr, _y_desc, y_ptr, _b_desc, _d_scale, _d_bias, 1., nullptr, nullptr, _epsilon, nullptr, nullptr));
    cudaFree(_d_bias);
    cudaFree(_d_scale);
    return 0;
}

size_t InstanceNormalizationPlugin::getSerializationSize() const
{
    return (serialized_size(_epsilon) +
            serialized_size(_nchan) +
            serialized_size(_h_scale) +
            serialized_size(_h_bias));
}

void InstanceNormalizationPlugin::serialize(void *buffer) const
{
    serialize_value(&buffer, _epsilon);
    serialize_value(&buffer, _nchan);
    serialize_value(&buffer, _h_scale);
    serialize_value(&buffer, _h_bias);
}

bool InstanceNormalizationPlugin::supportsFormatCombination(
    int pos, const nvinfer1::PluginTensorDesc* inOut, int nbInputs, int nbOutputs)
{
    ASSERT(inOut && pos < (nbInputs + nbOutputs));
    return ((inOut[pos].type == nvinfer1::DataType::kFLOAT || inOut[pos].type == nvinfer1::DataType::kHALF)
        && inOut[pos].format == nvinfer1::PluginFormat::kNCHW);
}

const char* InstanceNormalizationPlugin::getPluginType() const
{
    return INSTANCE_PLUGIN_NAME;
}

const char* InstanceNormalizationPlugin::getPluginVersion() const
{
    return INSTANCE_PLUGIN_VERSION;
}

void InstanceNormalizationPlugin::destroy()
{
    delete this;
}

IPluginV2DynamicExt* InstanceNormalizationPlugin::clone() const
{
    auto plugin = new InstanceNormalizationPlugin{_epsilon, _h_scale, _h_bias};
    plugin->setPluginNamespace(mPluginNamespace);
    return plugin;
}

// Set plugin namespace
void InstanceNormalizationPlugin::setPluginNamespace(const char* pluginNamespace)
{
    mPluginNamespace = pluginNamespace;
}

const char* InstanceNormalizationPlugin::getPluginNamespace() const
{
    return mPluginNamespace;
}

nvinfer1::DataType InstanceNormalizationPlugin::getOutputDataType(
    int index, const nvinfer1::DataType* inputTypes, int nbInputs) const
{
    ASSERT(inputTypes && nbInputs > 0 && index == 0);
    return inputTypes[0];
}

// Attach the plugin object to an execution context and grant the plugin the access to some context resource.
void InstanceNormalizationPlugin::attachToContext(cudnnContext* cudnnContext, cublasContext* cublasContext, IGpuAllocator* gpuAllocator)
{
}

// Detach the plugin object from its execution context.
void InstanceNormalizationPlugin::detachFromContext() {}

void InstanceNormalizationPlugin::configurePlugin(const nvinfer1::DynamicPluginTensorDesc* in, int nbInputs,
    const nvinfer1::DynamicPluginTensorDesc* out, int nbOutputs)
{
    for (int i = 0; i < nbInputs; i++)
    {
      for (int j = 0; j < in[0].desc.dims.nbDims; j++)
      {
        // Do not support dynamic dimensions
        ASSERT(in[0].desc.dims.d[j] != -1);
      }
    }
}

// InstanceNormalizationPluginCreator methods
InstanceNormalizationPluginCreator::InstanceNormalizationPluginCreator()
{
    mPluginAttributes.emplace_back(PluginField("epsilon", nullptr, PluginFieldType::kFLOAT32, 1));
    mPluginAttributes.emplace_back(PluginField("scales", nullptr, PluginFieldType::kFLOAT32, 1));
    mPluginAttributes.emplace_back(PluginField("bias", nullptr, PluginFieldType::kFLOAT32, 1));

    mFC.nbFields = mPluginAttributes.size();
    mFC.fields = mPluginAttributes.data();
}

const char* InstanceNormalizationPluginCreator::getPluginName() const
{
    return INSTANCE_PLUGIN_NAME;
}

const char* InstanceNormalizationPluginCreator::getPluginVersion() const
{
    return INSTANCE_PLUGIN_VERSION;
}

const PluginFieldCollection* InstanceNormalizationPluginCreator::getFieldNames()
{
    return &mFC;
}

IPluginV2DynamicExt* InstanceNormalizationPluginCreator::createPlugin(const char* name, const nvinfer1::PluginFieldCollection* fc)
{
    std::vector<float> scaleValues;
    std::vector<float> biasValues;
    float epsilon {};
    const PluginField* fields = fc->fields;
    for (int i = 0; i < fc->nbFields; ++i)
    {
        const char* attrName = fields[i].name;
        if (!strcmp(attrName, "epsilon"))
        {
            ASSERT(fields[i].type == PluginFieldType::kFLOAT32);
            epsilon= *(static_cast<const float*>(fields[i].data));
        }
        else if (!strcmp(attrName, "scales"))
        {
            ASSERT(fields[i].type == PluginFieldType::kFLOAT32);
            int size = fields[i].length;
            scaleValues.reserve(size);
            const auto* w = static_cast<const float*>(fields[i].data);
            for (int j = 0; j < size; j++)
            {
                scaleValues.push_back(*w);
                w++;
            }
        }
        else if (!strcmp(attrName, "bias"))
        {
            ASSERT(fields[i].type == PluginFieldType::kFLOAT32);
            int size = fields[i].length;
            biasValues.reserve(size);
            const auto* w = static_cast<const float*>(fields[i].data);
            for (int j = 0; j < size; j++)
            {
                biasValues.push_back(*w);
                w++;
            }
        }
    }

    Weights scaleWeights{DataType::kFLOAT, scaleValues.data(), (int64_t) scaleValues.size()};
    Weights biasWeights{DataType::kFLOAT, biasValues.data(), (int64_t) biasValues.size()};

    InstanceNormalizationPlugin* obj = new InstanceNormalizationPlugin(epsilon, scaleWeights, biasWeights);
    obj->setPluginNamespace(mNamespace.c_str());
    return obj;
}

IPluginV2DynamicExt* InstanceNormalizationPluginCreator::deserializePlugin(const char* name, const void* serialData, size_t serialLength)
{
    InstanceNormalizationPlugin* obj = new InstanceNormalizationPlugin{serialData, serialLength};
    obj->setPluginNamespace(mNamespace.c_str());
    return obj;
}
<|endoftext|>


<commit_before>#include "ContactManager.h"

#include <storage/Directory.h>
#include <storage/Entry.h>
#include <storage/FindDirectory.h>
#include <storage/NodeMonitor.h>
#include <storage/Query.h>
#include <storage/VolumeRoster.h>
#include <support/Autolock.h>
#include <support/Locker.h>

#include <libim/Constants.h>
#include <libim/Contact.h>
#include <libim/Helpers.h>

#include "ContactCachedConnections.h"
#include "ContactListener.h"
#include "common/SpecificationFinder.h"

//#pragma mark Definitions

using namespace IM;

class QueryStore : public GenericListStore<BQuery *> {
};

class ContactStore : public GenericMapStore<entry_ref, ContactCachedConnections *>,  public SpecificationFinder<ContactCachedConnections *> {
	public:
		ContactStore(void)
			: GenericMapStore<entry_ref, ContactCachedConnections *>(),
			fLock(new BLocker()) {
		};

		virtual ~ContactStore(void) {
			delete fLock;
		};

		virtual bool FindFirstNoLock(ContactSpecification *specification, ContactCachedConnections **firstMatch, bool deleteSpec = true) {
			bool result = false;
			GenericMapStore<entry_ref, ContactCachedConnections *>::Iterator it;

			for (it = Start(); it != End(); it++) {
				ContactCachedConnections *current = it->second;

				if (specification->IsSatisfiedBy(current) == true) {
					*firstMatch = current;
					result = true;
					break;
				};
			};

			if (deleteSpec == true) {
				delete specification;
			};

			return result;
		};

		virtual bool FindFirst(ContactSpecification *specification, ContactCachedConnections **firstMatch, bool deleteSpec = true) {
			BAutolock lock(fLock);
			bool result = false;

			if (lock.IsLocked() == true) {
				result = FindFirstNoLock(specification, firstMatch, deleteSpec);
			};

			return result;
		};

		virtual GenericListStore<ContactCachedConnections *> FindAll(ContactSpecification *specification, bool deleteSpec = true) {
			GenericListStore<ContactCachedConnections *> contacts(false);
			BAutolock lock(fLock);

			if (lock.IsLocked() == true) {
				GenericMapStore<entry_ref, ContactCachedConnections *>::Iterator it;
				for (it = Start(); it != End(); it++) {
					ContactCachedConnections *current = it->second;

					if (specification->IsSatisfiedBy(current) == true) {
						contacts.Add(current);
					};
				};
			};

			if (deleteSpec == true) {
				delete specification;
			};

			return contacts;
		};

		BLocker *GetLock(void) const {
			return fLock;
		};
	private:
		BLocker	*fLock;
};

//#pragma mark Constants

const char *kContactMIMEType = "application/x-person";
extern char *kAppName;

//#pragma mark Constructor

ContactManager::ContactManager(ContactListener *listener)
	: BLooper("ContactManager", B_LOW_PRIORITY),
	fContactListener(listener),
	fContact(new ContactStore()),
	fQuery(new QueryStore()) {

	Run();
};

ContactManager::~ContactManager(void) {
	delete fQuery;
};

//#pragma mark BLooper Hooks

void ContactManager::MessageReceived(BMessage *msg) {
	switch (msg->what) {
		// Contact messages. Both query and node monitor.
		case B_QUERY_UPDATE: {
			int32 opcode = B_ERROR;

			if (msg->FindInt32("opcode", &opcode) != B_OK) {
				return;
			};

			ContactHandle handle;
			const char *name = NULL;

			switch (opcode) {
				case B_ENTRY_CREATED: {
					// Add to contact list
					msg->FindString("name", &name );
					handle.entry.set_name(name);
					msg->FindInt64("directory", &handle.entry.directory);
					msg->FindInt32("device", &handle.entry.device);
					msg->FindInt64("node", &handle.node);

					if (fContact->Contains(handle.entry) == false) {
						ContactAdded(handle);
					} else {
						LOG(kAppName, liDebug, "Got a B_ENTRY_CREATED for a Contact we already know about - possibly due to live query notification catching up with a call to CreateContact");
					};
				} break;

				default: {
				} break;
			}
		} break;

		case B_NODE_MONITOR: {
			int32 opcode = 0;

			// Malformed message, skip
			if (msg->FindInt32("opcode", &opcode) != B_OK) {
				return;
			};

			ContactHandle handle;
			ContactHandle from;
			ContactHandle to;
			const char *name = NULL;

			switch (opcode) {
				case B_ENTRY_CREATED: {
					// Add to contact list
					msg->FindString("name", &name );
					handle.entry.set_name(name);
					msg->FindInt64("directory", &handle.entry.directory);
					msg->FindInt32("device", &handle.entry.device);
					msg->FindInt64("node", &handle.node);

					if (fContact->Contains(handle.entry) == false) {
						ContactAdded(handle);
					} else {
						LOG(kAppName, liDebug, "Got a B_ENTRY_CREATED for a Contact we already know about - possibly due to live query notification catching up with a call to CreateContact");
					};
				} break;
				case B_ENTRY_MOVED: {
					// Contact moved
					msg->FindString("name", &name );
					from.entry.set_name(name);
					to.entry.set_name(name);
					msg->FindInt64("from directory", &from.entry.directory);
					msg->FindInt64("to directory", &to.entry.directory);
					msg->FindInt32("device", &from.entry.device);
					msg->FindInt32("device", &to.entry.device);
					msg->FindInt64("node", &from.node);
					msg->FindInt64("node", &to.node);

					ContactMoved(from, to);
				} break;
				case B_ATTR_CHANGED: {
					// Add to contact list
					msg->FindInt32("device", &handle.entry.device);
					msg->FindInt64("node", &handle.node);

					ContactCachedConnections *cached = NULL;
					if (fContact->FindFirst(new ContactHandleSpecification(handle), &cached) == true) {
						ContactModified(cached->Handle());
					} else {
						LOG(kAppName, liDebug, "Got a B_ATTR_CHANGED request for a Contact we cannot match");
					};
				} break;

				case B_ENTRY_REMOVED: {
					// Remove from contact list
					msg->FindInt64("directory", &handle.entry.directory);
					msg->FindInt32("device", &handle.entry.device);
					msg->FindInt64("node", &handle.node);

					ContactCachedConnections *cached = NULL;
					if (fContact->FindFirst(new ContactHandleSpecification(handle), &cached) == true) {
						ContactRemoved(handle);
					} else {
						LOG(kAppName, liDebug, "Got a B_ENTRY_REMOVED request for a Contact we cannot match");
					};
				} break;
			}
		} break;

		default: {
			BLooper::MessageReceived(msg);
		} break;
	};
};

//#pragma mark SpecificationFinder<Contact *> Hooks

bool ContactManager::FindFirst(ContactSpecification *spec, ContactCachedConnections **firstMatch, bool canDelete = true) {
	return fContact->FindFirst(spec, firstMatch, canDelete);
};

GenericListStore<ContactCachedConnections *> ContactManager::FindAll(ContactSpecification *spec, bool canDelete = true) {
	return fContact->FindAll(spec, canDelete);
};

//#pragma mark Public

status_t ContactManager::Init(void) {
	BMessage msg;
	ContactHandle handle;
	BVolumeRoster vroster;
	BVolume vol;
	char volName[B_FILE_NAME_LENGTH];

	vroster.Rewind();

	// Query for all contacts on all drives
	while (vroster.GetNextVolume(&vol) == B_OK) {
		if ((vol.InitCheck() != B_OK) || (vol.KnowsQuery() != true)) {
			continue;
		};

		vol.GetName(volName);
		LOG(kAppName, liLow, "ContactManager::Init(): Getting contacts on %s", volName);

		BQuery *query = new BQuery();
		query->SetTarget(BMessenger(this));
		query->SetPredicate("IM:connections=*");
		query->SetVolume(&vol);
		query->Fetch();

		fQuery->Add(query);

		while (query->GetNextRef(&handle.entry) == B_OK) {
			node_ref nref;

			BNode node(&handle.entry);
			if (node.GetNodeRef(&nref) == B_OK) {
				handle.node = nref.node;
				ContactAdded(handle);
			};
		};
	};

	return B_OK;
};

/**
	Create a new People file with a unique name on the form "Unknown contact X"
	and add the specified connection to it

	@param connection The Connection object of the new contact
	@param namebase The name to save the file as (will be appended with an integer if it already exists)
*/

ContactCachedConnections *ContactManager::CreateContact(Connection connection, const char *namebase) {
	ContactCachedConnections *result = NULL;

	BAutolock lock(fContact->GetLock());
	if (lock.IsLocked() == false) {
		LOG(kAppName, liHigh,
			"ContactManager::CreateContact: Unable to acquire storage lock");
		return result;
	};

	if (fContact->FindFirstNoLock(new ConnectionContactSpecification(connection), &result) == true) {
		LOG(kAppName, liHigh,
			"CreateContact for a connection that already exists - returning existing item");
		LOG(kAppName, liHigh, "    %s", result->EntryRef().name);
		return result;
	};

	BPath path;

	if (find_directory(B_USER_DIRECTORY, &path, true, NULL) != B_OK) {
		LOG(kAppName, liHigh, "Unable to find B_USER_DIRECTORY");
		return result;
	};

	path.Append("people");

	// make sure that the target directory exists before we try to create new files
	create_directory(path.Path(), 0777);

	BDirectory dir(path.Path());
	BFile file;
	BEntry entry;
	char filename[512];

	// Make sure we have a decent namebase
	if ((namebase == NULL) || (strlen(namebase) == 0)) {
		namebase = "Unknown contact";
	};

	strcpy(filename, namebase);

	// Attempt to create the contact
	dir.CreateFile(filename, &file, true);

	for (int i = 1; file.InitCheck() != B_OK; i++) {
		sprintf(filename, "%s %d", namebase, i);

		dir.CreateFile(filename, &file, true);
	};

	if (dir.FindEntry(filename,&entry) != B_OK) {
		LOG(kAppName, liHigh,
			"Error: While creating a new contact, dir.FindEntry() failed. filename was [%s]",
			filename);
		return result;
	};

	// File created - set the type
	if (file.WriteAttr("BEOS:TYPE", B_MIME_STRING_TYPE, 0, kContactMIMEType, strlen(kContactMIMEType)) != strlen(kContactMIMEType)) {
		// Error writing type
		entry.Remove();

		LOG(kAppName, liHigh, "ERROR: Unable to write MIME type for newly created contact");
		return result;
	};

	// File created. set type and add connection
	result = new ContactCachedConnections(entry);
	if (result->AddConnection(connection.String()) != B_OK) {
		delete result;
		result = NULL;

		return result;
	};

	if (result->SetStatus(OFFLINE_TEXT) != B_OK) {
		delete result;

		result = NULL;
		return result;
	};

	// Ensure the cached contacts are up to date
	result->ReloadConnections();

	fContact->Add(result->EntryRef(), result);

	return result;
};

//#pragma mark Private

void ContactManager::ContactAdded(ContactHandle handle) {
	// Check if the Contact already exists
	if (fContact->Contains(handle.entry) == true) {
		return;
	};

	// Set up node monitoring
	node_ref nref;
	nref.device = handle.entry.device;
	nref.node = handle.node;
	watch_node(&nref, B_WATCH_ALL, BMessenger(this));

	// Save the Contact
	ContactCachedConnections *contact = new ContactCachedConnections(handle.entry);
	contact->ReloadConnections();
	fContact->Add(handle.entry, contact);

	// Notify the listener
	fContactListener->ContactAdded(contact);
};

void ContactManager::ContactModified(ContactHandle handle) {
	ContactCachedConnections *contact = NULL;

	if (fContact->FindFirst(new ContactHandleSpecification(handle), &contact) == true) {
		ConnectionStore *temp = contact->CachedConnections();
		// Copy the previous connections
		ConnectionStore prevCons;
		for (ConnectionStore::Iterator it = temp->Start(); it != temp->End(); it++) {
			Connection con = (*it);
			prevCons.Add(con);
		};

		temp = NULL;
		contact->ReloadConnections();
		ConnectionStore *newCons = contact->CachedConnections();

		// Notify the listener
		fContactListener->ContactModified(contact, &prevCons, newCons);
	} else {
		LOG(kAppName, liHigh, "ContactManager::ContactModified: %s is an unknown contact", handle.entry.name);
	};
};

void ContactManager::ContactMoved(ContactHandle from, ContactHandle to) {
//	for ( list< pair<ContactHandle, list<string>* > >::iterator i = fContacts.begin(); i != fContacts.end(); i++ )
//	{
//		if ( (*i).first == from )
//		{
//			(*i).first = to;
//			return;
//		}
//	}
};

void ContactManager::ContactRemoved(ContactHandle handle) {
	// Stop node monitoring
	node_ref nref;
	nref.device = handle.entry.device;
	nref.node = handle.node;
	watch_node(&nref, B_STOP_WATCHING, BMessenger(this));

	ContactCachedConnections *contact = NULL;
	if (fContact->FindFirst(new ContactHandleSpecification(handle), &contact) == true) {
		ConnectionStore *prevCons = contact->CachedConnections();

		// Notify the listener
		fContactListener->ContactRemoved(contact, prevCons);

		// Remove the Contact
		if (fContact->Contains(handle.entry) == true) {
			fContact->Remove(handle.entry);
		};
	} else {
		LOG(kAppName, liHigh, "ContactManager::ContactRemoved: %s is an unknown contact", handle.entry.name);
	};
};
<commit_msg>Moving constants on top of the file.<commit_after>#include "ContactManager.h"

#include <storage/Directory.h>
#include <storage/Entry.h>
#include <storage/FindDirectory.h>
#include <storage/NodeMonitor.h>
#include <storage/Query.h>
#include <storage/VolumeRoster.h>
#include <support/Autolock.h>
#include <support/Locker.h>

#include <libim/Constants.h>
#include <libim/Contact.h>
#include <libim/Helpers.h>

#include "ContactCachedConnections.h"
#include "ContactListener.h"
#include "common/SpecificationFinder.h"

//#pragma mark Definitions

//#pragma mark Constants

const char *kContactMIMEType = "application/x-person";
extern char *kAppName;

using namespace IM;

class QueryStore : public GenericListStore<BQuery *> {
};

class ContactStore : public GenericMapStore<entry_ref, ContactCachedConnections *>,  public SpecificationFinder<ContactCachedConnections *> {
	public:
		ContactStore(void)
			: GenericMapStore<entry_ref, ContactCachedConnections *>(),
			fLock(new BLocker()) {
		};

		virtual ~ContactStore(void) {
			delete fLock;
		};

		virtual bool FindFirstNoLock(ContactSpecification *specification, ContactCachedConnections **firstMatch, bool deleteSpec = true) {
			bool result = false;
			GenericMapStore<entry_ref, ContactCachedConnections *>::Iterator it;

			for (it = Start(); it != End(); it++) {
				ContactCachedConnections *current = it->second;

				if (specification->IsSatisfiedBy(current) == true) {
					*firstMatch = current;
					result = true;
					break;
				};
			};

			if (deleteSpec == true) {
				delete specification;
			};

			return result;
		};

		virtual bool FindFirst(ContactSpecification *specification, ContactCachedConnections **firstMatch, bool deleteSpec = true) {
			BAutolock lock(fLock);
			bool result = false;

			if (lock.IsLocked() == true) {
				result = FindFirstNoLock(specification, firstMatch, deleteSpec);
			};

			return result;
		};

		virtual GenericListStore<ContactCachedConnections *> FindAll(ContactSpecification *specification, bool deleteSpec = true) {
			GenericListStore<ContactCachedConnections *> contacts(false);
			BAutolock lock(fLock);

			if (lock.IsLocked() == true) {
				GenericMapStore<entry_ref, ContactCachedConnections *>::Iterator it;
				for (it = Start(); it != End(); it++) {
					ContactCachedConnections *current = it->second;

					if (specification->IsSatisfiedBy(current) == true) {
						contacts.Add(current);
					};
				};
			};

			if (deleteSpec == true) {
				delete specification;
			};

			return contacts;
		};

		BLocker *GetLock(void) const {
			return fLock;
		};
	private:
		BLocker	*fLock;
};

//#pragma mark Constructor

ContactManager::ContactManager(ContactListener *listener)
	: BLooper("ContactManager", B_LOW_PRIORITY),
	fContactListener(listener),
	fContact(new ContactStore()),
	fQuery(new QueryStore()) {

	Run();
};

ContactManager::~ContactManager(void) {
	delete fQuery;
};

//#pragma mark BLooper Hooks

void ContactManager::MessageReceived(BMessage *msg) {
	switch (msg->what) {
		// Contact messages. Both query and node monitor.
		case B_QUERY_UPDATE: {
			int32 opcode = B_ERROR;

			if (msg->FindInt32("opcode", &opcode) != B_OK) {
				return;
			};

			ContactHandle handle;
			const char *name = NULL;

			switch (opcode) {
				case B_ENTRY_CREATED: {
					// Add to contact list
					msg->FindString("name", &name );
					handle.entry.set_name(name);
					msg->FindInt64("directory", &handle.entry.directory);
					msg->FindInt32("device", &handle.entry.device);
					msg->FindInt64("node", &handle.node);

					if (fContact->Contains(handle.entry) == false) {
						ContactAdded(handle);
					} else {
						LOG(kAppName, liDebug, "Got a B_ENTRY_CREATED for a Contact we already know about - possibly due to live query notification catching up with a call to CreateContact");
					};
				} break;

				default: {
				} break;
			}
		} break;

		case B_NODE_MONITOR: {
			int32 opcode = 0;

			// Malformed message, skip
			if (msg->FindInt32("opcode", &opcode) != B_OK) {
				return;
			};

			ContactHandle handle;
			ContactHandle from;
			ContactHandle to;
			const char *name = NULL;

			switch (opcode) {
				case B_ENTRY_CREATED: {
					// Add to contact list
					msg->FindString("name", &name );
					handle.entry.set_name(name);
					msg->FindInt64("directory", &handle.entry.directory);
					msg->FindInt32("device", &handle.entry.device);
					msg->FindInt64("node", &handle.node);

					if (fContact->Contains(handle.entry) == false) {
						ContactAdded(handle);
					} else {
						LOG(kAppName, liDebug, "Got a B_ENTRY_CREATED for a Contact we already know about - possibly due to live query notification catching up with a call to CreateContact");
					};
				} break;
				case B_ENTRY_MOVED: {
					// Contact moved
					msg->FindString("name", &name );
					from.entry.set_name(name);
					to.entry.set_name(name);
					msg->FindInt64("from directory", &from.entry.directory);
					msg->FindInt64("to directory", &to.entry.directory);
					msg->FindInt32("device", &from.entry.device);
					msg->FindInt32("device", &to.entry.device);
					msg->FindInt64("node", &from.node);
					msg->FindInt64("node", &to.node);

					ContactMoved(from, to);
				} break;
				case B_ATTR_CHANGED: {
					// Add to contact list
					msg->FindInt32("device", &handle.entry.device);
					msg->FindInt64("node", &handle.node);

					ContactCachedConnections *cached = NULL;
					if (fContact->FindFirst(new ContactHandleSpecification(handle), &cached) == true) {
						ContactModified(cached->Handle());
					} else {
						LOG(kAppName, liDebug, "Got a B_ATTR_CHANGED request for a Contact we cannot match");
					};
				} break;

				case B_ENTRY_REMOVED: {
					// Remove from contact list
					msg->FindInt64("directory", &handle.entry.directory);
					msg->FindInt32("device", &handle.entry.device);
					msg->FindInt64("node", &handle.node);

					ContactCachedConnections *cached = NULL;
					if (fContact->FindFirst(new ContactHandleSpecification(handle), &cached) == true) {
						ContactRemoved(handle);
					} else {
						LOG(kAppName, liDebug, "Got a B_ENTRY_REMOVED request for a Contact we cannot match");
					};
				} break;
			}
		} break;

		default: {
			BLooper::MessageReceived(msg);
		} break;
	};
};

//#pragma mark SpecificationFinder<Contact *> Hooks

bool ContactManager::FindFirst(ContactSpecification *spec, ContactCachedConnections **firstMatch, bool canDelete = true) {
	return fContact->FindFirst(spec, firstMatch, canDelete);
};

GenericListStore<ContactCachedConnections *> ContactManager::FindAll(ContactSpecification *spec, bool canDelete = true) {
	return fContact->FindAll(spec, canDelete);
};

//#pragma mark Public

status_t ContactManager::Init(void) {
	BMessage msg;
	ContactHandle handle;
	BVolumeRoster vroster;
	BVolume vol;
	char volName[B_FILE_NAME_LENGTH];

	vroster.Rewind();

	// Query for all contacts on all drives
	while (vroster.GetNextVolume(&vol) == B_OK) {
		if ((vol.InitCheck() != B_OK) || (vol.KnowsQuery() != true)) {
			continue;
		};

		vol.GetName(volName);
		LOG(kAppName, liLow, "ContactManager::Init(): Getting contacts on %s", volName);

		BQuery *query = new BQuery();
		query->SetTarget(BMessenger(this));
		query->SetPredicate("IM:connections=*");
		query->SetVolume(&vol);
		query->Fetch();

		fQuery->Add(query);

		while (query->GetNextRef(&handle.entry) == B_OK) {
			node_ref nref;

			BNode node(&handle.entry);
			if (node.GetNodeRef(&nref) == B_OK) {
				handle.node = nref.node;
				ContactAdded(handle);
			};
		};
	};

	return B_OK;
};

/**
	Create a new People file with a unique name on the form "Unknown contact X"
	and add the specified connection to it

	@param connection The Connection object of the new contact
	@param namebase The name to save the file as (will be appended with an integer if it already exists)
*/

ContactCachedConnections *ContactManager::CreateContact(Connection connection, const char *namebase) {
	ContactCachedConnections *result = NULL;

	BAutolock lock(fContact->GetLock());
	if (lock.IsLocked() == false) {
		LOG(kAppName, liHigh,
			"ContactManager::CreateContact: Unable to acquire storage lock");
		return result;
	};

	if (fContact->FindFirstNoLock(new ConnectionContactSpecification(connection), &result) == true) {
		LOG(kAppName, liHigh,
			"CreateContact for a connection that already exists - returning existing item");
		LOG(kAppName, liHigh, "    %s", result->EntryRef().name);
		return result;
	};

	BPath path;

	if (find_directory(B_USER_DIRECTORY, &path, true, NULL) != B_OK) {
		LOG(kAppName, liHigh, "Unable to find B_USER_DIRECTORY");
		return result;
	};

	path.Append("people");

	// make sure that the target directory exists before we try to create new files
	create_directory(path.Path(), 0777);

	BDirectory dir(path.Path());
	BFile file;
	BEntry entry;
	char filename[512];

	// Make sure we have a decent namebase
	if ((namebase == NULL) || (strlen(namebase) == 0)) {
		namebase = "Unknown contact";
	};

	strcpy(filename, namebase);

	// Attempt to create the contact
	dir.CreateFile(filename, &file, true);

	for (int i = 1; file.InitCheck() != B_OK; i++) {
		sprintf(filename, "%s %d", namebase, i);

		dir.CreateFile(filename, &file, true);
	};

	if (dir.FindEntry(filename,&entry) != B_OK) {
		LOG(kAppName, liHigh,
			"Error: While creating a new contact, dir.FindEntry() failed. filename was [%s]",
			filename);
		return result;
	};

	// File created - set the type
	if (file.WriteAttr("BEOS:TYPE", B_MIME_STRING_TYPE, 0, kContactMIMEType, strlen(kContactMIMEType)) != strlen(kContactMIMEType)) {
		// Error writing type
		entry.Remove();

		LOG(kAppName, liHigh, "ERROR: Unable to write MIME type for newly created contact");
		return result;
	};

	// File created. set type and add connection
	result = new ContactCachedConnections(entry);
	if (result->AddConnection(connection.String()) != B_OK) {
		delete result;
		result = NULL;

		return result;
	};

	if (result->SetStatus(OFFLINE_TEXT) != B_OK) {
		delete result;

		result = NULL;
		return result;
	};

	// Ensure the cached contacts are up to date
	result->ReloadConnections();

	fContact->Add(result->EntryRef(), result);

	return result;
};

//#pragma mark Private

void ContactManager::ContactAdded(ContactHandle handle) {
	// Check if the Contact already exists
	if (fContact->Contains(handle.entry) == true) {
		return;
	};

	// Set up node monitoring
	node_ref nref;
	nref.device = handle.entry.device;
	nref.node = handle.node;
	watch_node(&nref, B_WATCH_ALL, BMessenger(this));

	// Save the Contact
	ContactCachedConnections *contact = new ContactCachedConnections(handle.entry);
	contact->ReloadConnections();
	fContact->Add(handle.entry, contact);

	// Notify the listener
	fContactListener->ContactAdded(contact);
};

void ContactManager::ContactModified(ContactHandle handle) {
	ContactCachedConnections *contact = NULL;

	if (fContact->FindFirst(new ContactHandleSpecification(handle), &contact) == true) {
		ConnectionStore *temp = contact->CachedConnections();
		// Copy the previous connections
		ConnectionStore prevCons;
		for (ConnectionStore::Iterator it = temp->Start(); it != temp->End(); it++) {
			Connection con = (*it);
			prevCons.Add(con);
		};

		temp = NULL;
		contact->ReloadConnections();
		ConnectionStore *newCons = contact->CachedConnections();

		// Notify the listener
		fContactListener->ContactModified(contact, &prevCons, newCons);
	} else {
		LOG(kAppName, liHigh, "ContactManager::ContactModified: %s is an unknown contact", handle.entry.name);
	};
};

void ContactManager::ContactMoved(ContactHandle from, ContactHandle to) {
//	for ( list< pair<ContactHandle, list<string>* > >::iterator i = fContacts.begin(); i != fContacts.end(); i++ )
//	{
//		if ( (*i).first == from )
//		{
//			(*i).first = to;
//			return;
//		}
//	}
};

void ContactManager::ContactRemoved(ContactHandle handle) {
	// Stop node monitoring
	node_ref nref;
	nref.device = handle.entry.device;
	nref.node = handle.node;
	watch_node(&nref, B_STOP_WATCHING, BMessenger(this));

	ContactCachedConnections *contact = NULL;
	if (fContact->FindFirst(new ContactHandleSpecification(handle), &contact) == true) {
		ConnectionStore *prevCons = contact->CachedConnections();

		// Notify the listener
		fContactListener->ContactRemoved(contact, prevCons);

		// Remove the Contact
		if (fContact->Contains(handle.entry) == true) {
			fContact->Remove(handle.entry);
		};
	} else {
		LOG(kAppName, liHigh, "ContactManager::ContactRemoved: %s is an unknown contact", handle.entry.name);
	};
};
<|endoftext|>


<commit_before>/*************************************************************************
*    UrBackup - Client/Server backup system
*    Copyright (C) 2011-2016 Martin Raiber
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU Affero General Public License as published by
*    the Free Software Foundation, either version 3 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 Affero General Public License for more details.
*
*    You should have received a copy of the GNU Affero General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/

#include "../Interface/Database.h"
#include "../Interface/Server.h"
#include "../Interface/File.h"
#include "../Interface/DatabaseCursor.h"
#include "database.h"
#include "../stringtools.h"
#include <iostream>
#include <fstream>
#include "../urbackupcommon/sha2/sha2.h"
#include "../urbackupcommon/os_functions.h"
#include <memory.h>
#include <memory>
#include "dao/ServerFilesDao.h"
#include "FileIndex.h"
#include "create_files_index.h"
#include "server_hash.h"
#include "serverinterface/helper.h"

const _u32 c_read_blocksize=4096;
const size_t draw_segments=30;
const size_t c_speed_size=15;
const size_t c_max_l_length=80;

void draw_progress(std::string curr_fn, _i64 curr_verified, _i64 verify_size)
{
	static _i64 last_progress_bytes=0;
	static int64 last_time=0;
	static size_t max_line_length=0;

	int64 passed_time=Server->getTimeMS()-last_time;
	if(passed_time>1000)
	{
		_i64 new_bytes=curr_verified-last_progress_bytes;

		float pc_done=(float)curr_verified/(float)verify_size;

		size_t segments=(size_t)(pc_done*draw_segments);

		std::string toc="\r[";
		for(size_t i=0;i<draw_segments;++i)
		{
			if(i<segments)
			{
				toc+="=";
			}
			else if(i==segments)
			{
				toc+=">";
			}
			else
			{
				toc+=" ";
			}
		}
		std::string speed_str=PrettyPrintSpeed((size_t)((new_bytes*1000)/passed_time));
		while(speed_str.size()<c_speed_size)
			speed_str+=" ";
		std::string pcdone=convert((int)(pc_done*100.f));
		if(pcdone.size()==1)
			pcdone=" "+pcdone;

		toc+="] "+pcdone+"% "+speed_str+" "+(curr_fn);

		if(toc.size()>=c_max_l_length)
		    toc=toc.substr(0, c_max_l_length);

		if(toc.size()>max_line_length)
		    max_line_length=toc.size();

		while(toc.size()<max_line_length)
		    toc+=" ";

		std::cout << toc;
		std::cout.flush();

		last_progress_bytes=curr_verified;
		last_time=Server->getTimeMS();
	}
}

bool verify_file(db_single_result &res, _i64 &curr_verified, _i64 verify_size, bool& missing)
{
	std::string fp=res["fullpath"];
	IFile *f=Server->openFile(os_file_prefix(fp), MODE_READ);
	if( f==NULL )
	{
		Server->Log("Error opening file \""+fp+"\"", LL_ERROR);
		missing = true;
		return false;
	}

	if(watoi64(res["filesize"])!=f->Size())
	{
		Server->Log("Filesize of \""+fp+"\" is wrong", LL_ERROR);
		return false;
	}

	std::string f_name=ExtractFileName(fp);

	sha_def_ctx shactx;
	sha_def_init(&shactx);

	_u32 r;
	char buf[c_read_blocksize];
	int64 curr_verified_start=curr_verified;
	do
	{
		r=f->Read(buf, c_read_blocksize);
		if(r>0)
		{
			sha_def_update(&shactx, (unsigned char*) buf, r);
		}
		curr_verified+=r;

		draw_progress(f_name, curr_verified, verify_size);
	}
	while(r>0);

	Server->destroy(f);

	if(curr_verified-curr_verified_start!=watoi64(res["filesize"]))
	{
		Server->Log("Could not read all bytes of file \""+fp+"\"", LL_ERROR);
		return false;
	}

	const unsigned char * db_sha=(unsigned char*)res["shahash"].c_str();
	unsigned char calc_dig[SHA_DEF_DIGEST_SIZE];
	sha_def_final(&shactx, calc_dig);

	if(memcmp(db_sha, calc_dig, SHA_DEF_DIGEST_SIZE)!=0)
	{
		Server->Log("Hash of \""+fp+"\" is wrong", LL_ERROR);
		return false;
	}

	return true;
}

bool verify_hashes(std::string arg)
{
	IDatabase *db=Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER);

	std::string working_dir=(Server->getServerWorkingDir());
	std::string v_output_fn=working_dir+os_file_sep()+"urbackup"+os_file_sep()+"verification_result.txt";
	std::fstream v_failure;
	v_failure.open(v_output_fn.c_str(), std::ios::out|std::ios::binary);
	if( !v_failure.is_open() )
		Server->Log("Could not open \""+v_output_fn+"\" for writing", LL_ERROR);
	else
		Server->Log("Writing verification results to \""+v_output_fn+"\"", LL_INFO);

	std::string clientname;
	std::string backupname;

	if(arg!="true")
	{
		if(arg.find("/")==std::string::npos)
		{
			clientname=arg;
		}
		else
		{
			clientname=getuntil("/", arg);
			backupname=getafter("/", arg);

		}
	}

	bool delete_failed = Server->getServerParameter("delete_verify_failed")=="true";

	int cid=0;
	int backupid=0;
	std::string filter;

	if(!clientname.empty())
	{
		if(clientname!="*")
		{
			IQuery *q=db->Prepare("SELECT id FROM clients WHERE name=?");
			q->Bind(clientname);
			db_results res=q->Read();
			if(!res.empty())
			{
				cid=watoi(res[0]["id"]);
			}
			else
			{
				Server->Log("Client \""+clientname+"\" not found", LL_ERROR);
				return false;
			}

			filter=" WHERE clientid="+convert(cid);
		}
		else
		{
			filter+=" WHERE 1=1";
		}

		if(!backupname.empty())
		{
			std::string backupid_filter;
			if(backupname=="last")
			{
				if(clientname!="*")
				{
					IQuery* q=db->Prepare("SELECT id,path FROM backups WHERE clientid=? AND complete=1 ORDER BY backuptime DESC LIMIT 1");
					q->Bind(cid);
					db_results res=q->Read();
					if(!res.empty())
					{
						backupid_filter="= "+res[0]["id"];
						Server->Log("Last backup: "+res[0]["path"], LL_INFO);
					}
					else
					{
						Server->Log("Last backup not found", LL_ERROR);
						return false;
					}
				}
				else
				{
					backupid_filter=" IN (SELECT id FROM backups b WHERE NOT EXISTS (SELECT id FROM backups c WHERE complete=1 AND c.backuptime > b.backuptime AND b.clientid=c.clientid))";
				}

			}
			else if(backupname=="*")
			{
				backupid_filter=" IN (SELECT id FROM backups WHERE clientid="+convert(cid)+")";
			}
			else
			{
				IQuery* q=db->Prepare("SELECT id FROM backups WHERE path=? AND clientid=?");
				q->Bind(backupname);
				q->Bind(cid);
				db_results res=q->Read();
				if(!res.empty())
				{
					backupid_filter="= "+res[0]["id"];
				}
				else
				{
					Server->Log("Backup \""+backupname+"\" not found", LL_ERROR);

					return false;
				}
			}

			if(backupname!="*" || clientname!="*")
			{
				filter+=" AND backupid "+backupid_filter;
			}
		}
	}

	std::cout << "Calculating filesize..." << std::endl;
	IQuery *q_num_files=db->Prepare("SELECT SUM(filesize) AS c FROM files"+filter);
	db_results res=q_num_files->Read();
	if(res.empty())
	{
		Server->Log("Error during filesize calculation.", LL_ERROR);
		return false;
	}

	_i64 verify_size=watoi64(res[0]["c"]);
	_i64 curr_verified=0;

	std::cout << "To be verified: " << PrettyPrintBytes(verify_size) << " of files" << std::endl;

	_i64 crowid=0;

	IQuery *q_get_files=db->Prepare("SELECT id, fullpath, shahash, filesize FROM files"+filter, false);

	bool is_okay=true;

	IDatabaseCursor* cursor = q_get_files->Cursor();

	std::vector<int64> todelete;
	std::vector<int64> missing_files;

	db_single_result res_single;
	while(cursor->next(res_single))
	{
		bool is_missing=false;
		if(! verify_file( res_single, curr_verified, verify_size, is_missing) )
		{
			if(!is_missing)
			{
				v_failure << "Verification of \"" << (res_single["fullpath"]) << "\" failed\r\n";
				is_okay=false;

				if(delete_failed)
				{
					todelete.push_back(watoi64(res_single["id"]));
				}
			}
			else
			{
				missing_files.push_back(watoi64(res_single["id"]));
			}
		}
	}

	if(v_failure.is_open() && is_okay)
	{
		v_failure.close();
		Server->deleteFile(v_output_fn);
	}

	db->destroyQuery(q_get_files);

	IQuery* q_get_file = db->Prepare("SELECT id, fullpath, shahash, filesize FROM files WHERE id=?");

	std::cout << missing_files.size() << " could not be opened during verification. Checking now if they have been deleted from the database..." << std::endl;

	for(size_t i=0;i<missing_files.size();++i)
	{
		q_get_file->Bind(missing_files[i]);
		db_results res = q_get_file->Read();
		q_get_file->Reset();

		if(!res.empty())
		{
			bool is_missing=false;
			db_single_result& res_single = res[0];
			if(!verify_file(res_single, curr_verified, verify_size, is_missing))
			{
				v_failure << "Verification of file \"" << (res_single["fullpath"]) << "\" failed (during rechecking previously missing files)\r\n";
				is_okay=false;

				if(delete_failed)
				{
					todelete.push_back(watoi64(res_single["id"]));
				}
			}
		}
	}

	std::cout << std::endl;

	if(delete_failed)
	{
		std::cout << "Deleting " << todelete.size() << " file entries with failed verification from database..." << std::endl;

		SStartupStatus status;
		if(!create_files_index(status))
		{
			std::cout << "Error opening file index -1" << std::endl;
		}
		else
		{
			ServerFilesDao backupdao(db);
			std::auto_ptr<FileIndex> fileindex(create_lmdb_files_index());

			if(fileindex.get()==NULL)
			{
				std::cout << "Error opening file index -2" << std::endl;
			}
			else
			{

				for(size_t i=0;i<todelete.size();++i)
				{
					BackupServerHash::deleteFileSQL(backupdao, *fileindex, todelete[i]);
				}

				std::cout << "done." << std::endl;
			}
		}
	}

	return is_okay;
}<commit_msg>Fixed verification via command line<commit_after>/*************************************************************************
*    UrBackup - Client/Server backup system
*    Copyright (C) 2011-2016 Martin Raiber
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU Affero General Public License as published by
*    the Free Software Foundation, either version 3 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 Affero General Public License for more details.
*
*    You should have received a copy of the GNU Affero General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/

#include "../Interface/Database.h"
#include "../Interface/Server.h"
#include "../Interface/File.h"
#include "../Interface/DatabaseCursor.h"
#include "database.h"
#include "../stringtools.h"
#include <iostream>
#include <fstream>
#include "../urbackupcommon/sha2/sha2.h"
#include "../urbackupcommon/os_functions.h"
#include <memory.h>
#include <memory>
#include "dao/ServerFilesDao.h"
#include "FileIndex.h"
#include "create_files_index.h"
#include "server_hash.h"
#include "serverinterface/helper.h"

const _u32 c_read_blocksize=4096;
const size_t draw_segments=30;
const size_t c_speed_size=15;
const size_t c_max_l_length=80;

void draw_progress(std::string curr_fn, _i64 curr_verified, _i64 verify_size)
{
	static _i64 last_progress_bytes=0;
	static int64 last_time=0;
	static size_t max_line_length=0;

	int64 passed_time=Server->getTimeMS()-last_time;
	if(passed_time>1000)
	{
		_i64 new_bytes=curr_verified-last_progress_bytes;

		float pc_done=(float)curr_verified/(float)verify_size;

		size_t segments=(size_t)(pc_done*draw_segments);

		std::string toc="\r[";
		for(size_t i=0;i<draw_segments;++i)
		{
			if(i<segments)
			{
				toc+="=";
			}
			else if(i==segments)
			{
				toc+=">";
			}
			else
			{
				toc+=" ";
			}
		}
		std::string speed_str=PrettyPrintSpeed((size_t)((new_bytes*1000)/passed_time));
		while(speed_str.size()<c_speed_size)
			speed_str+=" ";
		std::string pcdone=convert((int)(pc_done*100.f));
		if(pcdone.size()==1)
			pcdone=" "+pcdone;

		toc+="] "+pcdone+"% "+speed_str+" "+(curr_fn);

		if(toc.size()>=c_max_l_length)
		    toc=toc.substr(0, c_max_l_length);

		if(toc.size()>max_line_length)
		    max_line_length=toc.size();

		while(toc.size()<max_line_length)
		    toc+=" ";

		std::cout << toc;
		std::cout.flush();

		last_progress_bytes=curr_verified;
		last_time=Server->getTimeMS();
	}
}

bool verify_file(db_single_result &res, _i64 &curr_verified, _i64 verify_size, bool& missing)
{
	std::string fp=res["fullpath"];
	IFsFile *f=Server->openFile(os_file_prefix(fp), MODE_READ);
	if( f==NULL )
	{
		Server->Log("Error opening file \""+fp+"\"", LL_ERROR);
		missing = true;
		return false;
	}

	if(watoi64(res["filesize"])!=f->Size())
	{
		Server->Log("Filesize of \""+fp+"\" is wrong", LL_ERROR);
		return false;
	}

	std::string f_name=ExtractFileName(fp);

	FsExtentIterator extent_iterator(f, 32768);
	std::string calc_dig = BackupServerPrepareHash::hash_sha(f, &extent_iterator, true);
	curr_verified += f->Size();

	if(calc_dig.empty())
	{
		Server->Log("Could not read all bytes of file \""+fp+"\"", LL_ERROR);
		return false;
	}

	if(res["shahash"]!=calc_dig)
	{
		Server->Log("Hash of \""+fp+"\" is wrong", LL_ERROR);
		return false;
	}

	return true;
}

bool verify_hashes(std::string arg)
{
	IDatabase *db=Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER);

	std::string working_dir=(Server->getServerWorkingDir());
	std::string v_output_fn=working_dir+os_file_sep()+"urbackup"+os_file_sep()+"verification_result.txt";
	std::fstream v_failure;
	v_failure.open(v_output_fn.c_str(), std::ios::out|std::ios::binary);
	if( !v_failure.is_open() )
		Server->Log("Could not open \""+v_output_fn+"\" for writing", LL_ERROR);
	else
		Server->Log("Writing verification results to \""+v_output_fn+"\"", LL_INFO);

	std::string clientname;
	std::string backupname;

	if(arg!="true")
	{
		if(arg.find("/")==std::string::npos)
		{
			clientname=arg;
		}
		else
		{
			clientname=getuntil("/", arg);
			backupname=getafter("/", arg);

		}
	}

	bool delete_failed = Server->getServerParameter("delete_verify_failed")=="true";

	int cid=0;
	int backupid=0;
	std::string filter;

	IDatabase *files_db = Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER);

	if(!clientname.empty())
	{
		if(clientname!="*")
		{
			IQuery *q=db->Prepare("SELECT id FROM clients WHERE name=?");
			q->Bind(clientname);
			db_results res=q->Read();
			if(!res.empty())
			{
				cid=watoi(res[0]["id"]);
			}
			else
			{
				Server->Log("Client \""+clientname+"\" not found", LL_ERROR);
				return false;
			}

			filter=" WHERE clientid="+convert(cid);
		}
		else
		{
			filter+=" WHERE 1=1";
		}

		if(!backupname.empty())
		{
			std::string backupid_filter;
			std::string temp_create_query;
			if(backupname=="last")
			{
				if(clientname!="*")
				{
					IQuery* q=db->Prepare("SELECT id,path FROM backups WHERE clientid=? AND complete=1 ORDER BY backuptime DESC LIMIT 1");
					q->Bind(cid);
					db_results res=q->Read();
					if(!res.empty())
					{
						backupid_filter="= "+res[0]["id"];
						Server->Log("Last backup: "+res[0]["path"], LL_INFO);
					}
					else
					{
						Server->Log("Last backup not found", LL_ERROR);
						return false;
					}
				}
				else
				{
					backupid_filter = " IN (SELECT id FROM backups)";
					temp_create_query = "SELECT id FROM backups b WHERE NOT EXISTS (SELECT id FROM backups c WHERE complete=1 AND c.backuptime > b.backuptime AND b.clientid=c.clientid)";
				}

			}
			else if(backupname=="*")
			{
				backupid_filter=" IN (SELECT id FROM backups)";
				temp_create_query = "SELECT id FROM backups WHERE clientid=" + convert(cid);
			}
			else
			{
				IQuery* q=db->Prepare("SELECT id FROM backups WHERE path=? AND clientid=?");
				q->Bind(backupname);
				q->Bind(cid);
				db_results res=q->Read();
				if(!res.empty())
				{
					backupid_filter="= "+res[0]["id"];
				}
				else
				{
					Server->Log("Backup \""+backupname+"\" not found", LL_ERROR);

					return false;
				}
			}

			if(backupname!="*" || clientname!="*")
			{
				filter+=" AND backupid "+backupid_filter;
			}

			if (!temp_create_query.empty())
			{
				files_db->Write("CREATE TEMPORARY TABLE backups (id INTEGER PRIMARY KEY)");

				IQuery* q_insert = files_db->Prepare("INSERT INTO backups (id) VALUES (?)", false);
				IQuery* q_backup_ids = db->Prepare(temp_create_query, false);
				IDatabaseCursor* cur = q_backup_ids->Cursor();

				db_single_result res;
				while (cur->next(res))
				{
					q_insert->Bind(res["id"]);
					q_insert->Write();
					q_insert->Reset();
				}

				db->destroyQuery(q_backup_ids);
				files_db->destroyQuery(q_insert);
			}
		}
	}

	std::cout << "Calculating filesize..." << std::endl;
	IQuery *q_num_files=db->Prepare("SELECT SUM(filesize) AS c FROM files"+filter);
	db_results res=q_num_files->Read();
	if(res.empty())
	{
		Server->Log("Error during filesize calculation.", LL_ERROR);
		return false;
	}

	_i64 verify_size=watoi64(res[0]["c"]);
	_i64 curr_verified=0;

	std::cout << "To be verified: " << PrettyPrintBytes(verify_size) << " of files" << std::endl;

	_i64 crowid=0;

	IQuery *q_get_files=db->Prepare("SELECT id, fullpath, shahash, filesize FROM files"+filter, false);

	bool is_okay=true;

	IDatabaseCursor* cursor = q_get_files->Cursor();

	std::vector<int64> todelete;
	std::vector<int64> missing_files;

	db_single_result res_single;
	while(cursor->next(res_single))
	{
		bool is_missing=false;
		if(! verify_file( res_single, curr_verified, verify_size, is_missing) )
		{
			if(!is_missing)
			{
				v_failure << "Verification of \"" << (res_single["fullpath"]) << "\" failed\r\n";
				is_okay=false;

				if(delete_failed)
				{
					todelete.push_back(watoi64(res_single["id"]));
				}
			}
			else
			{
				missing_files.push_back(watoi64(res_single["id"]));
			}
		}
	}

	if(v_failure.is_open() && is_okay)
	{
		v_failure.close();
		Server->deleteFile(v_output_fn);
	}

	db->destroyQuery(q_get_files);

	IQuery* q_get_file = db->Prepare("SELECT id, fullpath, shahash, filesize FROM files WHERE id=?");

	std::cout << missing_files.size() << " could not be opened during verification. Checking now if they have been deleted from the database..." << std::endl;

	for(size_t i=0;i<missing_files.size();++i)
	{
		q_get_file->Bind(missing_files[i]);
		db_results res = q_get_file->Read();
		q_get_file->Reset();

		if(!res.empty())
		{
			bool is_missing=false;
			db_single_result& res_single = res[0];
			if(!verify_file(res_single, curr_verified, verify_size, is_missing))
			{
				v_failure << "Verification of file \"" << (res_single["fullpath"]) << "\" failed (during rechecking previously missing files)\r\n";
				is_okay=false;

				if(delete_failed)
				{
					todelete.push_back(watoi64(res_single["id"]));
				}
			}
		}
	}

	std::cout << std::endl;

	if(delete_failed)
	{
		std::cout << "Deleting " << todelete.size() << " file entries with failed verification from database..." << std::endl;

		SStartupStatus status;
		if(!create_files_index(status))
		{
			std::cout << "Error opening file index -1" << std::endl;
		}
		else
		{
			ServerFilesDao backupdao(db);
			std::auto_ptr<FileIndex> fileindex(create_lmdb_files_index());

			if(fileindex.get()==NULL)
			{
				std::cout << "Error opening file index -2" << std::endl;
			}
			else
			{

				for(size_t i=0;i<todelete.size();++i)
				{
					BackupServerHash::deleteFileSQL(backupdao, *fileindex, todelete[i]);
				}

				std::cout << "done." << std::endl;
			}
		}
	}

	return is_okay;
}<|endoftext|>


<commit_before>
//#define LOKI_CLASS_LEVEL_THREADING
//#define LOKI_OBJECT_LEVEL_THREADING

// Uncomment this to test new [] and delete [].
// #define LOKI_SMALL_OBJECT_USE_NEW_ARRAY

#include "SmallObj.h"
#include "timer.h"

#include <string>

using namespace std;

class ThisIsASmallObject
{
	int i;
	double d;
	//std::string s;
};

template<class T>
struct Base : public ThisIsASmallObject, public T {};
template<>
struct Base<void> : public ThisIsASmallObject {};

typedef Base<void>
A;
typedef Base<Loki::SmallObject<> >
B;
typedef Base<Loki::SmallValueObject<> >
C;

/*
class A
{ int i; int* p;};
class B : public Loki::SmallObject<>
{ int i; int* p;};
class C : public Loki::SmallValueObject<>
{ int i; int* p;};
*/

template<class T>
int run_new_delete(int loop, Timer& t, char* s)
{
	t.start();
	/****************************************************************/
	for (int i=0; i<loop; ++i)
	{
		T* p = new T;
		delete p;
	}
	/****************************************************************/
	t.stop();
	t.print(t.t(),s);
	return t.t();
}

template<class T>
int run_new_delete(T** array, int N, int loop, Timer& t, char* s)
{
	t.start();
	/****************************************************************/
	for (int i=0; i<loop; ++i)
		for (int n=0; n<N; n++)
		{
			array[n] = new T;
			delete array[n];
		}
	/****************************************************************/
	t.stop();
	t.print(t.t(),s);
	return t.t();
}

template<class T>
int run_new(T** array, int loop, Timer& t, char* s)
{
	t.start();
	/****************************************************************/
	for (int i=0; i<loop; ++i)
		array[i] = new T;
	/****************************************************************/
	t.stop();
	t.print(t.t(),s);
	return t.t();
}
template<class T>
int run_delete(T** array, int loop, Timer& t, char* s)
{
	t.start();
	/****************************************************************/
	for (int i=0; i<loop; ++i)
		delete array[i];
	/****************************************************************/
	t.stop();
	t.print(t.t(),s);
	return t.t();
}

template<class T>
int run_new_delete_array(int N, int loop, Timer& t, char* s)
{
	t.start();
	/****************************************************************/
	for (int i=0; i<loop; ++i)
	{
		T* p = new T[N];
		delete [] p;
	}
	/****************************************************************/
	t.stop();
	t.print(t.t(),s);
	return t.t();
}

int main()
{
	int loop = 1000000
	;

	Timer t;

	t.t100 = 0;
	t.t100 = run_new_delete<A>(loop,t,"new & delete A : ");
	run_new_delete<B>(loop,t,"new & delete B : ");
	run_new_delete<C>(loop,t,"new & delete C : ");

	cout << endl << endl;
//    Loki::AllocatorSingleton<>::ClearExtraMemory();
////////////////////////////////////////////////////////////////////////////////

	int N = 100000;
	int loop2 = loop/N*10;

	A** a = new A*[N];
	B** b = new B*[N];
	C** c = new C*[N];

	for(int i=0; i<N; i++)
	{
		a[i]=0;
		b[i]=0;
		c[i]=0;
	}

	t.t100 = 0;
	t.t100 = run_new_delete(a,N,loop2,t,"new & delete A on array : ");
	run_new_delete(b,N,loop2,t,"new & delete B on array : ");
	run_new_delete(c,N,loop2,t,"new & delete C on array : ");

	cout << endl << endl;
//    Loki::AllocatorSingleton<>::ClearExtraMemory();
////////////////////////////////////////////////////////////////////////////////

	t.t100 = 0;
	t.t100 = run_new(a,N,t,"new A on array : ");
	run_new(b,N,t,"new B on array : ");
	run_new(c,N,t,"new C on array : ");

	cout << endl;
////////////////////////////////////////////////////////////////////////////////

	t.t100 = 0;
	t.t100 = run_delete(a,N,t,"delete A on array : ");
	run_delete(b,N,t,"delete B on array : ");
	run_delete(c,N,t,"delete C on array : ");

	delete [] a;
	delete [] b;
	delete [] c;

	cout << endl << endl;
//    Loki::AllocatorSingleton<>::ClearExtraMemory();
////////////////////////////////////////////////////////////////////////////////

	N = 5;

	t.t100 = 0;
	t.t100 = run_new_delete_array<A>(N,loop,t,"new & delete [] A : ");
	run_new_delete_array<B>(N,loop,t,"new & delete [] B : ");
	run_new_delete_array<C>(N,loop,t,"new & delete [] C : ");

	cout << endl << endl;
    Loki::AllocatorSingleton<>::ClearExtraMemory();
////////////////////////////////////////////////////////////////////////////////

	cout << endl;
	system("PAUSE");
	return 0;
}

<commit_msg>Added tests for new [] and delete [].<commit_after>
//#define LOKI_CLASS_LEVEL_THREADING
//#define LOKI_OBJECT_LEVEL_THREADING

// Uncomment this to test new [] and delete [].
//#define LOKI_SMALL_OBJECT_USE_NEW_ARRAY

#include "SmallObj.h"
#include "timer.h"

#include <string>

using namespace std;

class ThisIsASmallObject
{
	int i;
	double d;
	//std::string s;
};

template<class T>
struct Base : public ThisIsASmallObject, public T {};
template<>
struct Base<void> : public ThisIsASmallObject {};

typedef Base<void>
A;
typedef Base<Loki::SmallObject<> >
B;
typedef Base<Loki::SmallValueObject<> >
C;

/*
class A
{ int i; int* p;};
class B : public Loki::SmallObject<>
{ int i; int* p;};
class C : public Loki::SmallValueObject<>
{ int i; int* p;};
*/

template<class T>
int run_new_delete(int loop, Timer& t, char* s)
{
	t.start();
	/****************************************************************/
	for (int i=0; i<loop; ++i)
	{
		T* p = new T;
		delete p;
	}
	/****************************************************************/
	t.stop();
	t.print(t.t(),s);
	return t.t();
}

template<class T>
int run_new_delete(T** array, int N, int loop, Timer& t, char* s)
{
	t.start();
	/****************************************************************/
	for (int i=0; i<loop; ++i)
		for (int n=0; n<N; n++)
		{
			array[n] = new T;
			delete array[n];
		}
	/****************************************************************/
	t.stop();
	t.print(t.t(),s);
	return t.t();
}

template<class T>
int run_new(T** array, int loop, Timer& t, char* s)
{
	t.start();
	/****************************************************************/
	for (int i=0; i<loop; ++i)
		array[i] = new T;
	/****************************************************************/
	t.stop();
	t.print(t.t(),s);
	return t.t();
}
template<class T>
int run_delete(T** array, int loop, Timer& t, char* s)
{
	t.start();
	/****************************************************************/
	for (int i=0; i<loop; ++i)
		delete array[i];
	/****************************************************************/
	t.stop();
	t.print(t.t(),s);
	return t.t();
}

template<class T>
int run_new_delete_array(int N, int loop, Timer& t, char* s)
{
	t.start();
	/****************************************************************/
	for (int i=0; i<loop; ++i)
	{
		T* p = new T[N];
		delete [] p;
	}
	/****************************************************************/
	t.stop();
	t.print(t.t(),s);
	return t.t();
}

template<class T>
int run_new_array( int N, T** array, int loop, Timer& t, char* s)
{
	t.start();
	/****************************************************************/
	for (int i=0; i<loop; ++i)
		array[i] = new T[N];
	/****************************************************************/
	t.stop();
	t.print(t.t(),s);
	return t.t();
}
template<class T>
int run_delete_array( T** array, int loop, Timer& t, char* s)
{
	t.start();
	/****************************************************************/
	for (int i=0; i<loop; ++i)
		delete [] array[i];
	/****************************************************************/
	t.stop();
	t.print(t.t(),s);
	return t.t();
}

int main()
{
	int loop = 1000000
	;

	Timer t;

	t.t100 = 0;
	t.t100 = run_new_delete<A>(loop,t,"new & delete A : ");
	run_new_delete<B>(loop,t,"new & delete B : ");
	run_new_delete<C>(loop,t,"new & delete C : ");

	cout << endl << endl;
//    Loki::AllocatorSingleton<>::ClearExtraMemory();
////////////////////////////////////////////////////////////////////////////////

	int N = 100000;
	int loop2 = loop/N*10;

	A** a = new A*[N];
	B** b = new B*[N];
	C** c = new C*[N];

	for(int i=0; i<N; i++)
	{
		a[i]=0;
		b[i]=0;
		c[i]=0;
	}

	t.t100 = 0;
	t.t100 = run_new_delete(a,N,loop2,t,"new & delete A on array : ");
	run_new_delete(b,N,loop2,t,"new & delete B on array : ");
	run_new_delete(c,N,loop2,t,"new & delete C on array : ");

	cout << endl << endl;
//    Loki::AllocatorSingleton<>::ClearExtraMemory();
////////////////////////////////////////////////////////////////////////////////

	t.t100 = 0;
	t.t100 = run_new(a,N,t,"new A on array : ");
	run_new(b,N,t,"new B on array : ");
	run_new(c,N,t,"new C on array : ");

	cout << endl;
////////////////////////////////////////////////////////////////////////////////

	t.t100 = 0;
	t.t100 = run_delete(a,N,t,"delete A on array : ");
	run_delete(b,N,t,"delete B on array : ");
	run_delete(c,N,t,"delete C on array : ");

	cout << endl << endl;
//    Loki::AllocatorSingleton<>::ClearExtraMemory();
////////////////////////////////////////////////////////////////////////////////

	N = 5;

	t.t100 = 0;
	t.t100 = run_new_delete_array<A>(N,loop,t,"new & delete [] A : ");
	run_new_delete_array<B>(N,loop,t,"new & delete [] B : ");
	run_new_delete_array<C>(N,loop,t,"new & delete [] C : ");

	cout << endl << endl;
////////////////////////////////////////////////////////////////////////////////

    int count = 1000;
	t.t100 = 0;
	t.t100 = run_new_array(N,a,count,t,"new [] A on array : ");
	run_new_array(N,b,count,t,"new [] B on array : ");
	run_new_array(N,c,count,t,"new [] C on array : ");

	cout << endl;
////////////////////////////////////////////////////////////////////////////////

	t.t100 = 0;
	t.t100 = run_delete_array(a,count,t,"delete [] A on array : ");
	run_delete_array(b,count,t,"delete [] B on array : ");
	run_delete_array(c,count,t,"delete [] C on array : ");

	delete [] a;
	delete [] b;
	delete [] c;

	cout << endl << endl;
    Loki::AllocatorSingleton<>::ClearExtraMemory();
////////////////////////////////////////////////////////////////////////////////

	cout << endl;
	system("PAUSE");
	return 0;
}

<|endoftext|>


<commit_before>#ifndef NNXX_MESSAGE_SREAMBUF_HPP
#define NNXX_MESSAGE_SREAMBUF_HPP

#include <algorithm>

namespace nnxx {

  template < typename Char, typename Traits >
  basic_message_streambuf<Char, Traits>::
  basic_message_streambuf(size_type base_size) noexcept:
    base_type(),
    m_base_size(base_size),
    m_msg()
  { }

  template < typename Char, typename Traits >
  basic_message_streambuf<Char, Traits>::
  basic_message_streambuf(size_type size, int type):
    base_type(),
    m_base_size(size),
    m_msg(size * sizeof(char_type), type)
  { clear(); }

  template < typename Char, typename Traits >
  basic_message_streambuf<Char, Traits>::
  basic_message_streambuf(message &&msg) noexcept:
    base_type(),
    m_base_size(msg.empty() ? 1000 : msg.size()),
    m_msg(std::move(msg))
  { clear(); }

  template < typename Char, typename Traits >
  basic_message_streambuf<Char, Traits>::
  ~basic_message_streambuf()
  { }

  template < typename Char, typename Traits >
  void basic_message_streambuf<Char, Traits>::clear() noexcept
  {
    const auto b = reinterpret_cast<char_type *>(m_msg.data());
    const auto e = reinterpret_cast<char_type *>(m_msg.data()) + m_msg.size();
    this->setg(b, b, e);
    this->setp(b, e);
  }

  template < typename Char, typename Traits >
  void basic_message_streambuf<Char, Traits>::msg(message &&m) noexcept
  {
    m_msg = std::move(m);
    clear();
  }

  template < typename Char, typename Traits >
  message basic_message_streambuf<Char, Traits>::msg(int type)
  { return copy(m_msg, this->pptr() - this->pbase(), type); }

  template < typename Char, typename Traits >
  message basic_message_streambuf<Char, Traits>::move_msg()
  {
    message m;
    m_msg.resize(this->pptr() - this->pbase());
    m_msg.swap(m);
    clear();
    return m;
  }

  template < typename Char, typename Traits >
  typename
  basic_message_streambuf<Char, Traits>::streamsize
  basic_message_streambuf<Char, Traits>::xsputn(const char_type *s, streamsize n)
  {
    using std::copy;

    if (n > static_cast<streamsize>(this->epptr() - this->pptr())) {
      overflow(traits_type::eof());
    }

    copy(s, s + n, this->pptr());
    this->pbump(n);
    return n;
  }

  template < typename Char, typename Traits >
  typename
  basic_message_streambuf<Char, Traits>::int_type
  basic_message_streambuf<Char, Traits>::overflow(int_type c)
  {
    const auto n = m_msg.size();

    if (!m_msg) {
      m_msg = message{ m_base_size * sizeof(char_type) };
    }
    else {
      m_msg.resize(2 * sizeof(char_type) * m_msg.size());
    }

    const auto b = reinterpret_cast<char_type *>(m_msg.data());
    const auto e = reinterpret_cast<char_type *>(m_msg.data()) + m_msg.size();
    this->setp(b, e);
    this->pbump(n);

    if (!traits_type::eq_int_type(c, traits_type::eof())) {
      *(this->pptr()) = char_type(c);
      this->pbump(1);
    }

    return ~traits_type::eof();
  }

#if NNXX_LIBCPP
  template < typename Char, typename Traits >
  basic_message_streambuf<Char, Traits>::
  basic_message_streambuf(basic_message_streambuf &&m) noexcept:
    base_type(std::move(m)),
    m_base_size(m.m_base_size),
    m_msg(std::move(m.m_msg))
  { m.clear(); }

  template < typename Char, typename Traits >
  basic_message_streambuf<Char, Traits> &
  basic_message_streambuf<Char, Traits>::
  operator=(basic_message_streambuf &&m) noexcept
  {
    m.swap(*this);
    return *this;
  }

  template < typename Char, typename Traits >
  void basic_message_streambuf<Char, Traits>::
  swap(basic_message_streambuf &m) noexcept
  {
    using std::swap;
    base_type::swap(m);
    swap(m_base_size, m.m_base_size);
    swap(m_msg, m.m_msg);
  }
#endif // NNXX_LIBCPP

}

#endif // NNXX_MESSAGE_SREAMBUF_H
<commit_msg>implement nnxx::message::resize through nn_reallocmsg and fix nnxx::message_streambuf::move_msg to return a message of the correct size<commit_after>#ifndef NNXX_MESSAGE_SREAMBUF_HPP
#define NNXX_MESSAGE_SREAMBUF_HPP

#include <algorithm>

namespace nnxx {

  template < typename Char, typename Traits >
  basic_message_streambuf<Char, Traits>::
  basic_message_streambuf(size_type base_size) noexcept:
    base_type(),
    m_base_size(base_size),
    m_msg()
  { }

  template < typename Char, typename Traits >
  basic_message_streambuf<Char, Traits>::
  basic_message_streambuf(size_type size, int type):
    base_type(),
    m_base_size(size),
    m_msg(size * sizeof(char_type), type)
  { clear(); }

  template < typename Char, typename Traits >
  basic_message_streambuf<Char, Traits>::
  basic_message_streambuf(message &&msg) noexcept:
    base_type(),
    m_base_size(msg.empty() ? 1000 : msg.size()),
    m_msg(std::move(msg))
  { clear(); }

  template < typename Char, typename Traits >
  basic_message_streambuf<Char, Traits>::
  ~basic_message_streambuf()
  { }

  template < typename Char, typename Traits >
  void basic_message_streambuf<Char, Traits>::clear() noexcept
  {
    const auto b = reinterpret_cast<char_type *>(m_msg.data());
    const auto e = reinterpret_cast<char_type *>(m_msg.data()) + m_msg.size();
    this->setg(b, b, e);
    this->setp(b, e);
  }

  template < typename Char, typename Traits >
  void basic_message_streambuf<Char, Traits>::msg(message &&m) noexcept
  {
    m_msg = std::move(m);
    clear();
  }

  template < typename Char, typename Traits >
  message basic_message_streambuf<Char, Traits>::msg(int type)
  { return copy(m_msg, this->pptr() - this->pbase(), type); }

  template < typename Char, typename Traits >
  message basic_message_streambuf<Char, Traits>::move_msg()
  {
    message m;
    m_msg.resize(this->pptr() - this->pbase());
    m_msg.swap(m);
    clear();
    return m;
  }

  template < typename Char, typename Traits >
  typename
  basic_message_streambuf<Char, Traits>::streamsize
  basic_message_streambuf<Char, Traits>::xsputn(const char_type *s, streamsize n)
  {
    using std::copy;

    if (n > static_cast<streamsize>(this->epptr() - this->pptr())) {
      overflow(traits_type::eof());
    }

    copy(s, s + n, this->pptr());
    this->pbump(n);
    return n;
  }

  template < typename Char, typename Traits >
  typename
  basic_message_streambuf<Char, Traits>::int_type
  basic_message_streambuf<Char, Traits>::overflow(int_type c)
  {
    const auto n = m_msg.size();

    if (!m_msg) {
      m_msg = message{ m_base_size * sizeof(char_type) };
    }
    else {
      m_msg.resize(2 * m_msg.size());
    }

    const auto b = reinterpret_cast<char_type *>(m_msg.data());
    const auto e = reinterpret_cast<char_type *>(m_msg.data()) + m_msg.size();
    this->setp(b, e);
    this->pbump(n);

    if (!traits_type::eq_int_type(c, traits_type::eof())) {
      *(this->pptr()) = char_type(c);
      this->pbump(1);
    }

    return ~traits_type::eof();
  }

#if NNXX_LIBCPP
  template < typename Char, typename Traits >
  basic_message_streambuf<Char, Traits>::
  basic_message_streambuf(basic_message_streambuf &&m) noexcept:
    base_type(std::move(m)),
    m_base_size(m.m_base_size),
    m_msg(std::move(m.m_msg))
  { m.clear(); }

  template < typename Char, typename Traits >
  basic_message_streambuf<Char, Traits> &
  basic_message_streambuf<Char, Traits>::
  operator=(basic_message_streambuf &&m) noexcept
  {
    m.swap(*this);
    return *this;
  }

  template < typename Char, typename Traits >
  void basic_message_streambuf<Char, Traits>::
  swap(basic_message_streambuf &m) noexcept
  {
    using std::swap;
    base_type::swap(m);
    swap(m_base_size, m.m_base_size);
    swap(m_msg, m.m_msg);
  }
#endif // NNXX_LIBCPP

}

#endif // NNXX_MESSAGE_SREAMBUF_H
<|endoftext|>


<commit_before>#include <array>
#include <cstdio>
#include <unistd.h>
#include "base/os.h"
#include "fs/fs.h"
#include "utils.h"

#ifndef O_BINARY
#define O_BINARY 0x0004
#endif

using namespace services::fs;

extern "C" {
extern void initialise_monitor_handles(void);
extern void __libc_init_array(void);
extern int kill(pid_t, int);
}

class PosixFileSystem : public IFileSystem
{
  public:
    virtual FileOpenResult Open(const char* path, FileOpen openFlag, FileAccess accessMode) override
    {
        auto f = open(path, num(openFlag) | O_BINARY, num(accessMode));

        if (f == -1)
        {
            return FileOpenResult(static_cast<OSResult>(errno), -1);
        }
        else
        {
            return FileOpenResult(OSResult::Success, f);
        }
    }

    virtual OSResult Unlink(const char* /*path*/) override
    {
        return OSResult::NotSupported;
    }

    virtual OSResult Move(const char* /*from*/, const char* /*to*/) override
    {
        return OSResult::NotSupported;
    }

    virtual OSResult TruncateFile(FileHandle /*file*/, FileSize /*length*/) override
    {
        return OSResult::NotSupported;
    }

    virtual IOResult Write(FileHandle file, gsl::span<const std::uint8_t> buffer) override
    {
        auto r = write(file, buffer.data(), buffer.size());

        if (r == -1)
        {
            return IOResult(static_cast<OSResult>(errno), {});
        }
        else
        {
            return IOResult(OSResult::Success, buffer.subspan(0, r));
        }
    }

    virtual IOResult Read(FileHandle file, gsl::span<std::uint8_t> buffer) override
    {
        auto r = read(file, buffer.data(), buffer.size());

        if (r == -1)
        {
            return IOResult(static_cast<OSResult>(errno), {});
        }
        else
        {
            return IOResult(OSResult::Success, buffer.subspan(0, r));
        }
    }

    virtual OSResult Close(FileHandle file) override
    {
        return static_cast<OSResult>(close(file));
    }

    virtual DirectoryOpenResult OpenDirectory(const char* /*dirname*/) override
    {
        return DirectoryOpenResult(OSResult::NotSupported, 0);
    }

    virtual char* ReadDirectory(DirectoryHandle /*directory*/) override
    {
        return nullptr;
    }

    virtual OSResult CloseDirectory(DirectoryHandle /*directory*/) override
    {
        return OSResult::NotSupported;
    }

    virtual OSResult Format(const char* /*mountPoint*/) override
    {
        return OSResult::NotSupported;
    }

    virtual OSResult MakeDirectory(const char* /*path*/) override
    {
        return OSResult::NotSupported;
    }

    virtual bool Exists(const char* /*path*/) override
    {
        return false;
    }

    virtual FileSize GetFileSize(FileHandle /*file*/) override
    {
        return 0;
    }

    virtual FileSize GetFileSize(const char* /*dir*/, const char* /*file*/) override
    {
        return 0;
    }

    virtual OSResult Seek(FileHandle file, SeekOrigin origin, FileSize offset) override
    {
        return static_cast<OSResult>(lseek(file, offset, num(origin)));
    }

    virtual std::uint32_t GetFreeSpace(const char* /*devicePath*/) override
    {
        return 0;
    }
};

void GenerateSunSData(IFileSystem& fs);
void GenerateSailData(IFileSystem& fs);
void GenerateDetumblingData(IFileSystem& fs);
void GenerateCameraCommissioningData(IFileSystem& fs);
void GeneratePayloadCommissioningData(IFileSystem& fs);
void GenerateLeopData(IFileSystem& fs);
void GenerateRadfetData(IFileSystem& fs);

int main()
{
    __libc_init_array();

    initialise_monitor_handles();

    PosixFileSystem fs;

    GenerateSunSData(fs);
    GenerateSailData(fs);
    GenerateDetumblingData(fs);
    GenerateCameraCommissioningData(fs);
    GeneratePayloadCommissioningData(fs);
    GenerateLeopData(fs);
    GenerateRadfetData(fs);

    kill(-1, 0);

    return 0;
}
<commit_msg>[Experiment File Generator Update] Standard O_BINARY flag.<commit_after>#include <array>
#include <cstdio>
#include <fcntl.h>
#include <unistd.h>
#include "base/os.h"
#include "fs/fs.h"
#include "utils.h"

using namespace services::fs;

extern "C" {
extern void initialise_monitor_handles(void);
extern void __libc_init_array(void);
extern int kill(pid_t, int);
}

class PosixFileSystem : public IFileSystem
{
  public:
    virtual FileOpenResult Open(const char* path, FileOpen openFlag, FileAccess accessMode) override
    {
        auto f = open(path, num(openFlag) | O_BINARY, num(accessMode));

        if (f == -1)
        {
            return FileOpenResult(static_cast<OSResult>(errno), -1);
        }
        else
        {
            return FileOpenResult(OSResult::Success, f);
        }
    }

    virtual OSResult Unlink(const char* /*path*/) override
    {
        return OSResult::NotSupported;
    }

    virtual OSResult Move(const char* /*from*/, const char* /*to*/) override
    {
        return OSResult::NotSupported;
    }

    virtual OSResult TruncateFile(FileHandle /*file*/, FileSize /*length*/) override
    {
        return OSResult::NotSupported;
    }

    virtual IOResult Write(FileHandle file, gsl::span<const std::uint8_t> buffer) override
    {
        auto r = write(file, buffer.data(), buffer.size());

        if (r == -1)
        {
            return IOResult(static_cast<OSResult>(errno), {});
        }
        else
        {
            return IOResult(OSResult::Success, buffer.subspan(0, r));
        }
    }

    virtual IOResult Read(FileHandle file, gsl::span<std::uint8_t> buffer) override
    {
        auto r = read(file, buffer.data(), buffer.size());

        if (r == -1)
        {
            return IOResult(static_cast<OSResult>(errno), {});
        }
        else
        {
            return IOResult(OSResult::Success, buffer.subspan(0, r));
        }
    }

    virtual OSResult Close(FileHandle file) override
    {
        return static_cast<OSResult>(close(file));
    }

    virtual DirectoryOpenResult OpenDirectory(const char* /*dirname*/) override
    {
        return DirectoryOpenResult(OSResult::NotSupported, 0);
    }

    virtual char* ReadDirectory(DirectoryHandle /*directory*/) override
    {
        return nullptr;
    }

    virtual OSResult CloseDirectory(DirectoryHandle /*directory*/) override
    {
        return OSResult::NotSupported;
    }

    virtual OSResult Format(const char* /*mountPoint*/) override
    {
        return OSResult::NotSupported;
    }

    virtual OSResult MakeDirectory(const char* /*path*/) override
    {
        return OSResult::NotSupported;
    }

    virtual bool Exists(const char* /*path*/) override
    {
        return false;
    }

    virtual FileSize GetFileSize(FileHandle /*file*/) override
    {
        return 0;
    }

    virtual FileSize GetFileSize(const char* /*dir*/, const char* /*file*/) override
    {
        return 0;
    }

    virtual OSResult Seek(FileHandle file, SeekOrigin origin, FileSize offset) override
    {
        return static_cast<OSResult>(lseek(file, offset, num(origin)));
    }

    virtual std::uint32_t GetFreeSpace(const char* /*devicePath*/) override
    {
        return 0;
    }
};

void GenerateSunSData(IFileSystem& fs);
void GenerateSailData(IFileSystem& fs);
void GenerateDetumblingData(IFileSystem& fs);
void GenerateCameraCommissioningData(IFileSystem& fs);
void GeneratePayloadCommissioningData(IFileSystem& fs);
void GenerateLeopData(IFileSystem& fs);
void GenerateRadfetData(IFileSystem& fs);

int main()
{
    __libc_init_array();

    initialise_monitor_handles();

    PosixFileSystem fs;

    GenerateSunSData(fs);
    GenerateSailData(fs);
    GenerateDetumblingData(fs);
    GenerateCameraCommissioningData(fs);
    GeneratePayloadCommissioningData(fs);
    GenerateLeopData(fs);
    GenerateRadfetData(fs);

    kill(-1, 0);

    return 0;
}
<|endoftext|>