<commit_before>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SkBitmapProcShader.h"
#include "SkColorPriv.h"
#include "SkFlattenableBuffers.h"
#include "SkPixelRef.h"

bool SkBitmapProcShader::CanDo(const SkBitmap& bm, TileMode tx, TileMode ty) {
    switch (bm.config()) {
        case SkBitmap::kA8_Config:
        case SkBitmap::kRGB_565_Config:
        case SkBitmap::kIndex8_Config:
        case SkBitmap::kARGB_8888_Config:
    //        if (tx == ty && (kClamp_TileMode == tx || kRepeat_TileMode == tx))
                return true;
        default:
            break;
    }
    return false;
}

SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src,
                                       TileMode tmx, TileMode tmy) {
    fRawBitmap = src;
    fState.fTileModeX = (uint8_t)tmx;
    fState.fTileModeY = (uint8_t)tmy;
    fFlags = 0; // computed in setContext
}

SkBitmapProcShader::SkBitmapProcShader(SkFlattenableReadBuffer& buffer)
        : INHERITED(buffer) {
    buffer.readBitmap(&fRawBitmap);
    fRawBitmap.setImmutable();
    fState.fTileModeX = buffer.readUInt();
    fState.fTileModeY = buffer.readUInt();
    fFlags = 0; // computed in setContext
}

SkShader::BitmapType SkBitmapProcShader::asABitmap(SkBitmap* texture,
                                                   SkMatrix* texM,
                                                   TileMode xy[]) const {
    if (texture) {
        *texture = fRawBitmap;
    }
    if (texM) {
        texM->reset();
    }
    if (xy) {
        xy[0] = (TileMode)fState.fTileModeX;
        xy[1] = (TileMode)fState.fTileModeY;
    }
    return kDefault_BitmapType;
}

void SkBitmapProcShader::flatten(SkFlattenableWriteBuffer& buffer) const {
    this->INHERITED::flatten(buffer);

    buffer.writeBitmap(fRawBitmap);
    buffer.writeUInt(fState.fTileModeX);
    buffer.writeUInt(fState.fTileModeY);
}

static bool only_scale_and_translate(const SkMatrix& matrix) {
    unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
    return (matrix.getType() & ~mask) == 0;
}

bool SkBitmapProcShader::isOpaque() const {
    return fRawBitmap.isOpaque();
}

bool SkBitmapProcShader::setContext(const SkBitmap& device,
                                    const SkPaint& paint,
                                    const SkMatrix& matrix) {
    // do this first, so we have a correct inverse matrix
    if (!this->INHERITED::setContext(device, paint, matrix)) {
        return false;
    }

    fState.fOrigBitmap = fRawBitmap;
    fState.fOrigBitmap.lockPixels();
    if (!fState.fOrigBitmap.getTexture() && !fState.fOrigBitmap.readyToDraw()) {
        fState.fOrigBitmap.unlockPixels();
        return false;
    }

    if (!fState.chooseProcs(this->getTotalInverse(), paint)) {
        fState.fOrigBitmap.unlockPixels();
        return false;
    }

    const SkBitmap& bitmap = *fState.fBitmap;
    bool bitmapIsOpaque = bitmap.isOpaque();

    // update fFlags
    uint32_t flags = 0;
    if (bitmapIsOpaque && (255 == this->getPaintAlpha())) {
        flags |= kOpaqueAlpha_Flag;
    }

    switch (bitmap.config()) {
        case SkBitmap::kRGB_565_Config:
            flags |= (kHasSpan16_Flag | kIntrinsicly16_Flag);
            break;
        case SkBitmap::kIndex8_Config:
        case SkBitmap::kARGB_8888_Config:
            if (bitmapIsOpaque) {
                flags |= kHasSpan16_Flag;
            }
            break;
        case SkBitmap::kA8_Config:
            break;  // never set kHasSpan16_Flag
        default:
            break;
    }

    if (paint.isDither() && bitmap.config() != SkBitmap::kRGB_565_Config) {
        // gradients can auto-dither in their 16bit sampler, but we don't so
        // we clear the flag here.
        flags &= ~kHasSpan16_Flag;
    }

    // if we're only 1-pixel heigh, and we don't rotate, then we can claim this
    if (1 == bitmap.height() &&
            only_scale_and_translate(this->getTotalInverse())) {
        flags |= kConstInY32_Flag;
        if (flags & kHasSpan16_Flag) {
            flags |= kConstInY16_Flag;
        }
    }

    fFlags = flags;
    return true;
}

void SkBitmapProcShader::endContext() {
    fState.fOrigBitmap.unlockPixels();
    this->INHERITED::endContext();
}

#define BUF_MAX     128

#define TEST_BUFFER_OVERRITEx

#ifdef TEST_BUFFER_OVERRITE
    #define TEST_BUFFER_EXTRA   32
    #define TEST_PATTERN    0x88888888
#else
    #define TEST_BUFFER_EXTRA   0
#endif

void SkBitmapProcShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
    const SkBitmapProcState& state = fState;
    if (state.getShaderProc32()) {
        state.getShaderProc32()(state, x, y, dstC, count);
        return;
    }

    uint32_t buffer[BUF_MAX + TEST_BUFFER_EXTRA];
    SkBitmapProcState::MatrixProc   mproc = state.getMatrixProc();
    SkBitmapProcState::SampleProc32 sproc = state.getSampleProc32();
    int max = fState.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX);

    SkASSERT(state.fBitmap->getPixels());
    SkASSERT(state.fBitmap->pixelRef() == NULL ||
             state.fBitmap->pixelRef()->isLocked());

    for (;;) {
        int n = count;
        if (n > max) {
            n = max;
        }
        SkASSERT(n > 0 && n < BUF_MAX*2);
#ifdef TEST_BUFFER_OVERRITE
        for (int i = 0; i < TEST_BUFFER_EXTRA; i++) {
            buffer[BUF_MAX + i] = TEST_PATTERN;
        }
#endif
        mproc(state, buffer, n, x, y);
#ifdef TEST_BUFFER_OVERRITE
        for (int j = 0; j < TEST_BUFFER_EXTRA; j++) {
            SkASSERT(buffer[BUF_MAX + j] == TEST_PATTERN);
        }
#endif
        sproc(state, buffer, n, dstC);

        if ((count -= n) == 0) {
            break;
        }
        SkASSERT(count > 0);
        x += n;
        dstC += n;
    }
}

SkShader::ShadeProc SkBitmapProcShader::asAShadeProc(void** ctx) {
    if (fState.getShaderProc32()) {
        *ctx = &fState;
        return (ShadeProc)fState.getShaderProc32();
    }
    return NULL;
}

void SkBitmapProcShader::shadeSpan16(int x, int y, uint16_t dstC[], int count) {
    const SkBitmapProcState& state = fState;
    if (state.getShaderProc16()) {
        state.getShaderProc16()(state, x, y, dstC, count);
        return;
    }

    uint32_t buffer[BUF_MAX];
    SkBitmapProcState::MatrixProc   mproc = state.getMatrixProc();
    SkBitmapProcState::SampleProc16 sproc = state.getSampleProc16();
    int max = fState.maxCountForBufferSize(sizeof(buffer));

    SkASSERT(state.fBitmap->getPixels());
    SkASSERT(state.fBitmap->pixelRef() == NULL ||
             state.fBitmap->pixelRef()->isLocked());

    for (;;) {
        int n = count;
        if (n > max) {
            n = max;
        }
        mproc(state, buffer, n, x, y);
        sproc(state, buffer, n, dstC);

        if ((count -= n) == 0) {
            break;
        }
        x += n;
        dstC += n;
    }
}

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

#include "SkUnPreMultiply.h"
#include "SkColorShader.h"
#include "SkEmptyShader.h"

// returns true and set color if the bitmap can be drawn as a single color
// (for efficiency)
static bool canUseColorShader(const SkBitmap& bm, SkColor* color) {
    if (1 != bm.width() || 1 != bm.height()) {
        return false;
    }

    SkAutoLockPixels alp(bm);
    if (!bm.readyToDraw()) {
        return false;
    }

    switch (bm.config()) {
        case SkBitmap::kARGB_8888_Config:
            *color = SkUnPreMultiply::PMColorToColor(*bm.getAddr32(0, 0));
            return true;
        case SkBitmap::kRGB_565_Config:
            *color = SkPixel16ToColor(*bm.getAddr16(0, 0));
            return true;
        case SkBitmap::kIndex8_Config:
            *color = SkUnPreMultiply::PMColorToColor(bm.getIndex8Color(0, 0));
            return true;
        default: // just skip the other configs for now
            break;
    }
    return false;
}

#include "SkTemplatesPriv.h"

static bool bitmapIsTooBig(const SkBitmap& bm) {
    // SkBitmapProcShader stores bitmap coordinates in a 16bit buffer, as it
    // communicates between its matrix-proc and its sampler-proc. Until we can
    // widen that, we have to reject bitmaps that are larger.
    //
    const int maxSize = 65535;

    return bm.width() > maxSize || bm.height() > maxSize;
}

SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
                                       TileMode tmx, TileMode tmy,
                                       void* storage, size_t storageSize) {
    SkShader* shader;
    SkColor color;
    if (src.isNull() || bitmapIsTooBig(src)) {
        SK_PLACEMENT_NEW(shader, SkEmptyShader, storage, storageSize);
    }
    else if (canUseColorShader(src, &color)) {
        SK_PLACEMENT_NEW_ARGS(shader, SkColorShader, storage, storageSize,
                              (color));
    } else {
        SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage,
                              storageSize, (src, tmx, tmy));
    }
    return shader;
}

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

static const char* gTileModeName[] = {
    "clamp", "repeat", "mirror"
};

bool SkBitmapProcShader::toDumpString(SkString* str) const {
    str->printf("BitmapShader: [%d %d %d",
                fRawBitmap.width(), fRawBitmap.height(),
                fRawBitmap.bytesPerPixel());

    // add the pixelref
    SkPixelRef* pr = fRawBitmap.pixelRef();
    if (pr) {
        const char* uri = pr->getURI();
        if (uri) {
            str->appendf(" \"%s\"", uri);
        }
    }

    // add the (optional) matrix
    {
        if (this->hasLocalMatrix()) {
            SkString info;
            this->getLocalMatrix().toDumpString(&info);
            str->appendf(" %s", info.c_str());
        }
    }

    str->appendf(" [%s %s]]",
                 gTileModeName[fState.fTileModeX],
                 gTileModeName[fState.fTileModeY]);
    return true;
}
///////////////////////////////////////////////////////////////////////////////

#if SK_SUPPORT_GPU

#include "GrTextureAccess.h"
#include "effects/GrSingleTextureEffect.h"
#include "SkGr.h"

GrEffect* SkBitmapProcShader::asNewEffect(GrContext* context, const SkPaint& paint) const {
    SkMatrix matrix;
    matrix.setIDiv(fRawBitmap.width(), fRawBitmap.height());

    if (this->hasLocalMatrix()) {
        SkMatrix inverse;
        if (!this->getLocalMatrix().invert(&inverse)) {
            return false;
        }
        matrix.preConcat(inverse);
    }
    SkShader::TileMode tm[] = {
        (TileMode)fState.fTileModeX,
        (TileMode)fState.fTileModeY,
    };

    // Must set wrap and filter on the sampler before requesting a texture.
    GrTextureParams params(tm, paint.isFilterBitmap());
    GrTexture* texture = GrLockCachedBitmapTexture(context, fRawBitmap, &params);

    if (NULL == texture) {
        SkDebugf("Couldn't convert bitmap to texture.\n");
        return NULL;
    }

    GrEffect* effect = SkNEW_ARGS(GrSingleTextureEffect, (texture, matrix, params));
    GrUnlockCachedBitmapTexture(texture);
    return effect;
}
#endif
<commit_msg>false --> NULL for failure return<commit_after>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SkBitmapProcShader.h"
#include "SkColorPriv.h"
#include "SkFlattenableBuffers.h"
#include "SkPixelRef.h"

bool SkBitmapProcShader::CanDo(const SkBitmap& bm, TileMode tx, TileMode ty) {
    switch (bm.config()) {
        case SkBitmap::kA8_Config:
        case SkBitmap::kRGB_565_Config:
        case SkBitmap::kIndex8_Config:
        case SkBitmap::kARGB_8888_Config:
    //        if (tx == ty && (kClamp_TileMode == tx || kRepeat_TileMode == tx))
                return true;
        default:
            break;
    }
    return false;
}

SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src,
                                       TileMode tmx, TileMode tmy) {
    fRawBitmap = src;
    fState.fTileModeX = (uint8_t)tmx;
    fState.fTileModeY = (uint8_t)tmy;
    fFlags = 0; // computed in setContext
}

SkBitmapProcShader::SkBitmapProcShader(SkFlattenableReadBuffer& buffer)
        : INHERITED(buffer) {
    buffer.readBitmap(&fRawBitmap);
    fRawBitmap.setImmutable();
    fState.fTileModeX = buffer.readUInt();
    fState.fTileModeY = buffer.readUInt();
    fFlags = 0; // computed in setContext
}

SkShader::BitmapType SkBitmapProcShader::asABitmap(SkBitmap* texture,
                                                   SkMatrix* texM,
                                                   TileMode xy[]) const {
    if (texture) {
        *texture = fRawBitmap;
    }
    if (texM) {
        texM->reset();
    }
    if (xy) {
        xy[0] = (TileMode)fState.fTileModeX;
        xy[1] = (TileMode)fState.fTileModeY;
    }
    return kDefault_BitmapType;
}

void SkBitmapProcShader::flatten(SkFlattenableWriteBuffer& buffer) const {
    this->INHERITED::flatten(buffer);

    buffer.writeBitmap(fRawBitmap);
    buffer.writeUInt(fState.fTileModeX);
    buffer.writeUInt(fState.fTileModeY);
}

static bool only_scale_and_translate(const SkMatrix& matrix) {
    unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
    return (matrix.getType() & ~mask) == 0;
}

bool SkBitmapProcShader::isOpaque() const {
    return fRawBitmap.isOpaque();
}

bool SkBitmapProcShader::setContext(const SkBitmap& device,
                                    const SkPaint& paint,
                                    const SkMatrix& matrix) {
    // do this first, so we have a correct inverse matrix
    if (!this->INHERITED::setContext(device, paint, matrix)) {
        return false;
    }

    fState.fOrigBitmap = fRawBitmap;
    fState.fOrigBitmap.lockPixels();
    if (!fState.fOrigBitmap.getTexture() && !fState.fOrigBitmap.readyToDraw()) {
        fState.fOrigBitmap.unlockPixels();
        return false;
    }

    if (!fState.chooseProcs(this->getTotalInverse(), paint)) {
        fState.fOrigBitmap.unlockPixels();
        return false;
    }

    const SkBitmap& bitmap = *fState.fBitmap;
    bool bitmapIsOpaque = bitmap.isOpaque();

    // update fFlags
    uint32_t flags = 0;
    if (bitmapIsOpaque && (255 == this->getPaintAlpha())) {
        flags |= kOpaqueAlpha_Flag;
    }

    switch (bitmap.config()) {
        case SkBitmap::kRGB_565_Config:
            flags |= (kHasSpan16_Flag | kIntrinsicly16_Flag);
            break;
        case SkBitmap::kIndex8_Config:
        case SkBitmap::kARGB_8888_Config:
            if (bitmapIsOpaque) {
                flags |= kHasSpan16_Flag;
            }
            break;
        case SkBitmap::kA8_Config:
            break;  // never set kHasSpan16_Flag
        default:
            break;
    }

    if (paint.isDither() && bitmap.config() != SkBitmap::kRGB_565_Config) {
        // gradients can auto-dither in their 16bit sampler, but we don't so
        // we clear the flag here.
        flags &= ~kHasSpan16_Flag;
    }

    // if we're only 1-pixel heigh, and we don't rotate, then we can claim this
    if (1 == bitmap.height() &&
            only_scale_and_translate(this->getTotalInverse())) {
        flags |= kConstInY32_Flag;
        if (flags & kHasSpan16_Flag) {
            flags |= kConstInY16_Flag;
        }
    }

    fFlags = flags;
    return true;
}

void SkBitmapProcShader::endContext() {
    fState.fOrigBitmap.unlockPixels();
    this->INHERITED::endContext();
}

#define BUF_MAX     128

#define TEST_BUFFER_OVERRITEx

#ifdef TEST_BUFFER_OVERRITE
    #define TEST_BUFFER_EXTRA   32
    #define TEST_PATTERN    0x88888888
#else
    #define TEST_BUFFER_EXTRA   0
#endif

void SkBitmapProcShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
    const SkBitmapProcState& state = fState;
    if (state.getShaderProc32()) {
        state.getShaderProc32()(state, x, y, dstC, count);
        return;
    }

    uint32_t buffer[BUF_MAX + TEST_BUFFER_EXTRA];
    SkBitmapProcState::MatrixProc   mproc = state.getMatrixProc();
    SkBitmapProcState::SampleProc32 sproc = state.getSampleProc32();
    int max = fState.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX);

    SkASSERT(state.fBitmap->getPixels());
    SkASSERT(state.fBitmap->pixelRef() == NULL ||
             state.fBitmap->pixelRef()->isLocked());

    for (;;) {
        int n = count;
        if (n > max) {
            n = max;
        }
        SkASSERT(n > 0 && n < BUF_MAX*2);
#ifdef TEST_BUFFER_OVERRITE
        for (int i = 0; i < TEST_BUFFER_EXTRA; i++) {
            buffer[BUF_MAX + i] = TEST_PATTERN;
        }
#endif
        mproc(state, buffer, n, x, y);
#ifdef TEST_BUFFER_OVERRITE
        for (int j = 0; j < TEST_BUFFER_EXTRA; j++) {
            SkASSERT(buffer[BUF_MAX + j] == TEST_PATTERN);
        }
#endif
        sproc(state, buffer, n, dstC);

        if ((count -= n) == 0) {
            break;
        }
        SkASSERT(count > 0);
        x += n;
        dstC += n;
    }
}

SkShader::ShadeProc SkBitmapProcShader::asAShadeProc(void** ctx) {
    if (fState.getShaderProc32()) {
        *ctx = &fState;
        return (ShadeProc)fState.getShaderProc32();
    }
    return NULL;
}

void SkBitmapProcShader::shadeSpan16(int x, int y, uint16_t dstC[], int count) {
    const SkBitmapProcState& state = fState;
    if (state.getShaderProc16()) {
        state.getShaderProc16()(state, x, y, dstC, count);
        return;
    }

    uint32_t buffer[BUF_MAX];
    SkBitmapProcState::MatrixProc   mproc = state.getMatrixProc();
    SkBitmapProcState::SampleProc16 sproc = state.getSampleProc16();
    int max = fState.maxCountForBufferSize(sizeof(buffer));

    SkASSERT(state.fBitmap->getPixels());
    SkASSERT(state.fBitmap->pixelRef() == NULL ||
             state.fBitmap->pixelRef()->isLocked());

    for (;;) {
        int n = count;
        if (n > max) {
            n = max;
        }
        mproc(state, buffer, n, x, y);
        sproc(state, buffer, n, dstC);

        if ((count -= n) == 0) {
            break;
        }
        x += n;
        dstC += n;
    }
}

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

#include "SkUnPreMultiply.h"
#include "SkColorShader.h"
#include "SkEmptyShader.h"

// returns true and set color if the bitmap can be drawn as a single color
// (for efficiency)
static bool canUseColorShader(const SkBitmap& bm, SkColor* color) {
    if (1 != bm.width() || 1 != bm.height()) {
        return false;
    }

    SkAutoLockPixels alp(bm);
    if (!bm.readyToDraw()) {
        return false;
    }

    switch (bm.config()) {
        case SkBitmap::kARGB_8888_Config:
            *color = SkUnPreMultiply::PMColorToColor(*bm.getAddr32(0, 0));
            return true;
        case SkBitmap::kRGB_565_Config:
            *color = SkPixel16ToColor(*bm.getAddr16(0, 0));
            return true;
        case SkBitmap::kIndex8_Config:
            *color = SkUnPreMultiply::PMColorToColor(bm.getIndex8Color(0, 0));
            return true;
        default: // just skip the other configs for now
            break;
    }
    return false;
}

#include "SkTemplatesPriv.h"

static bool bitmapIsTooBig(const SkBitmap& bm) {
    // SkBitmapProcShader stores bitmap coordinates in a 16bit buffer, as it
    // communicates between its matrix-proc and its sampler-proc. Until we can
    // widen that, we have to reject bitmaps that are larger.
    //
    const int maxSize = 65535;

    return bm.width() > maxSize || bm.height() > maxSize;
}

SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
                                       TileMode tmx, TileMode tmy,
                                       void* storage, size_t storageSize) {
    SkShader* shader;
    SkColor color;
    if (src.isNull() || bitmapIsTooBig(src)) {
        SK_PLACEMENT_NEW(shader, SkEmptyShader, storage, storageSize);
    }
    else if (canUseColorShader(src, &color)) {
        SK_PLACEMENT_NEW_ARGS(shader, SkColorShader, storage, storageSize,
                              (color));
    } else {
        SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage,
                              storageSize, (src, tmx, tmy));
    }
    return shader;
}

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

static const char* gTileModeName[] = {
    "clamp", "repeat", "mirror"
};

bool SkBitmapProcShader::toDumpString(SkString* str) const {
    str->printf("BitmapShader: [%d %d %d",
                fRawBitmap.width(), fRawBitmap.height(),
                fRawBitmap.bytesPerPixel());

    // add the pixelref
    SkPixelRef* pr = fRawBitmap.pixelRef();
    if (pr) {
        const char* uri = pr->getURI();
        if (uri) {
            str->appendf(" \"%s\"", uri);
        }
    }

    // add the (optional) matrix
    {
        if (this->hasLocalMatrix()) {
            SkString info;
            this->getLocalMatrix().toDumpString(&info);
            str->appendf(" %s", info.c_str());
        }
    }

    str->appendf(" [%s %s]]",
                 gTileModeName[fState.fTileModeX],
                 gTileModeName[fState.fTileModeY]);
    return true;
}
///////////////////////////////////////////////////////////////////////////////

#if SK_SUPPORT_GPU

#include "GrTextureAccess.h"
#include "effects/GrSingleTextureEffect.h"
#include "SkGr.h"

GrEffect* SkBitmapProcShader::asNewEffect(GrContext* context, const SkPaint& paint) const {
    SkMatrix matrix;
    matrix.setIDiv(fRawBitmap.width(), fRawBitmap.height());

    if (this->hasLocalMatrix()) {
        SkMatrix inverse;
        if (!this->getLocalMatrix().invert(&inverse)) {
            return NULL;
        }
        matrix.preConcat(inverse);
    }
    SkShader::TileMode tm[] = {
        (TileMode)fState.fTileModeX,
        (TileMode)fState.fTileModeY,
    };

    // Must set wrap and filter on the sampler before requesting a texture.
    GrTextureParams params(tm, paint.isFilterBitmap());
    GrTexture* texture = GrLockCachedBitmapTexture(context, fRawBitmap, &params);

    if (NULL == texture) {
        SkDebugf("Couldn't convert bitmap to texture.\n");
        return NULL;
    }

    GrEffect* effect = SkNEW_ARGS(GrSingleTextureEffect, (texture, matrix, params));
    GrUnlockCachedBitmapTexture(texture);
    return effect;
}
#endif
<|endoftext|>


<commit_before>#include "angular_quadrature.hpp"

#include <vector>
#include <string>
#include <iostream>
#include <iomanip>

#include "core/error.hpp"
#include "core/string_utils.hpp"
#include "core/level_symmetric.hpp"

namespace mocc {

    const int AngularQuadrature::reflection_[3][8] = { {1,0,3,2,5,4,7,6},
                                                       {3,2,1,0,7,6,5,4},
                                                       {4,5,6,7,0,1,2,3} };

    AngularQuadrature::AngularQuadrature( const pugi::xml_node &input ) {
        // Make sure we got input
        if( input.empty() ) {
            throw EXCEPT("No input provided for angular quadrature.");
        }
        if( input.name() != std::string("ang_quad") ) {
            std::cerr << input.name() << std::endl;
            throw EXCEPT("Input is not an <ang_quad/> tag");
        }

        // Extract the quadrature type
        std::string type_str = input.attribute("type").value();
        sanitize(type_str);
        if ( (type_str == "ls") || (type_str == "level-symmetric") ) {
            type_ = QuadratureType::LS;

            // extract the quadrature order
            int order = input.attribute("order").as_int(-1);

            // Generate angles for octant 1
            angles_ = GenSn( order );
        } else if ((type_str == "cg") || (type_str == "chebyshev-gaussian" )) {
            type_ = QuadratureType::CHEB_GAUSS;

            //extract the quadrature order
            int azi_order = input.attribute("azimuthal-order").as_int(-1);
            int pol_order = input.attribute("polar-order").as_int(-1);

            //Generate angles for octant 1
            angles_ = GenProduct(GenChebyshev(azi_order),GenGauss(pol_order));
        } else if ((type_str == "cy") || (type_str == "chebyshev-yamamoto" )) {
            type_ = QuadratureType::CHEB_YAMAMOTO;

            //extract the quadrature order
            int azi_order = input.attribute("azimuthal-order").as_int(-1);
            int pol_order = input.attribute("polar-order").as_int(-1);

            //Generate angles from octant 1
            angles_ = GenProduct(GenChebyshev(azi_order),GenYamamoto(pol_order));
        } else {
            std::cerr << "'" << type_str << "'" << std::endl;
            throw EXCEPT("Unrecognized angular quadrature type specified.");
        }

        // Store the number of angles per octant
        ndir_oct_ = angles_.size();

        // Expand angles to other octants
        for ( int ioct=2; ioct<=8; ioct++ ) {
            for ( int iang=0; iang < ndir_oct_; iang++ ) {
                Angle a = angles_[iang];
                angles_.push_back( a.to_octant(ioct) );
            }
        }

        return;
    }

    AngularQuadrature::AngularQuadrature( const H5Node &input ) {
        VecF ox;
        VecF oy;
        VecF oz;
        VecF weights;

        input.read("ang_quad/omega_x", ox);
        input.read("ang_quad/omega_y", oy);
        input.read("ang_quad/omega_z", oz);
        input.read("ang_quad/weight", weights);

        if( (ox.size() != oy.size()) || (ox.size() != oz.size()) ||
                (ox.size() != weights.size()) ) {
            throw EXCEPT("Incompatible data sizes");
        }

        int size = ox.size();
        if( size%8 != 0 ) {
            throw EXCEPT("Size is not evenly-divisible by 8");
        }

        ndir_oct_ = size/8;

        angles_.reserve(size);
        for( int iang=0; iang<size; iang++ ) {
            angles_.emplace_back(ox[iang], oy[iang], oz[iang], weights[iang]);
        }

        type_ = QuadratureType::MANUAL;

        return;
    }

    void AngularQuadrature::modify_angle(int iang, Angle ang ) {
        for ( int ioct=0; ioct<8; ioct++ ){
            angles_[iang + ioct*ndir_oct_] = ang.to_octant(ioct+1);
        }
    }

    std::ostream& operator<<(std::ostream& os,
            const AngularQuadrature &angquad) {
        const int w = 12;
        os << std::setw(w) << "Alpha"
           << std::setw(w) << "Theta"
           << std::setw(w) << "omega x"
           << std::setw(w) << "omega y"
           << std::setw(w) << "omega z" << std::endl;
        for( auto &ang: angquad.angles_ ) {
            os << ang << std::endl;
        }
        return os;
    }

    void AngularQuadrature::output( H5Node &node ) const {
        VecF alpha; alpha.reserve(this->ndir());
        VecF theta; theta.reserve(this->ndir());
        VecF ox;    ox.reserve(this->ndir());
        VecF oy;    oy.reserve(this->ndir());
        VecF oz;    oz.reserve(this->ndir());
        VecF w;     w.reserve(this->ndir());

        for( auto a: angles_ ) {
            alpha.push_back(a.alpha);
            theta.push_back(a.theta);
            ox.push_back(a.ox);
            oy.push_back(a.oy);
            oz.push_back(a.oz);
            w.push_back(a.weight);
        }

        auto g = node.create_group("ang_quad");

        g.write("alpha", alpha);
        g.write("theta", theta);
        g.write("omega_x", ox);
        g.write("omega_y", oy);
        g.write("omega_z", oz);
        g.write("weight", w);

        return;
    }
}
<commit_msg>inclue product_quadrature.hpp file in angular_quadrature.cpp<commit_after>#include "angular_quadrature.hpp"

#include <vector>
#include <string>
#include <iostream>
#include <iomanip>

#include "core/error.hpp"
#include "core/string_utils.hpp"
#include "core/level_symmetric.hpp"
#include "core/product_quadrature.hpp"

namespace mocc {

    const int AngularQuadrature::reflection_[3][8] = { {1,0,3,2,5,4,7,6},
                                                       {3,2,1,0,7,6,5,4},
                                                       {4,5,6,7,0,1,2,3} };

    AngularQuadrature::AngularQuadrature( const pugi::xml_node &input ) {
        // Make sure we got input
        if( input.empty() ) {
            throw EXCEPT("No input provided for angular quadrature.");
        }
        if( input.name() != std::string("ang_quad") ) {
            std::cerr << input.name() << std::endl;
            throw EXCEPT("Input is not an <ang_quad/> tag");
        }

        // Extract the quadrature type
        std::string type_str = input.attribute("type").value();
        sanitize(type_str);
        if ( (type_str == "ls") || (type_str == "level-symmetric") ) {
            type_ = QuadratureType::LS;

            // extract the quadrature order
            int order = input.attribute("order").as_int(-1);

            // Generate angles for octant 1
            angles_ = GenSn( order );
        } else if ((type_str == "cg") || (type_str == "chebyshev-gaussian" )) {
            type_ = QuadratureType::CHEB_GAUSS;

            //extract the quadrature order
            int azi_order = input.attribute("azimuthal-order").as_int(-1);
            int pol_order = input.attribute("polar-order").as_int(-1);

            //Generate angles for octant 1
            angles_ = GenProduct(GenChebyshev(azi_order),GenGauss(pol_order));
        } else if ((type_str == "cy") || (type_str == "chebyshev-yamamoto" )) {
            type_ = QuadratureType::CHEB_YAMAMOTO;

            //extract the quadrature order
            int azi_order = input.attribute("azimuthal-order").as_int(-1);
            int pol_order = input.attribute("polar-order").as_int(-1);

            //Generate angles from octant 1
            angles_ = GenProduct(GenChebyshev(azi_order),GenYamamoto(pol_order));
        } else {
            std::cerr << "'" << type_str << "'" << std::endl;
            throw EXCEPT("Unrecognized angular quadrature type specified.");
        }

        // Store the number of angles per octant
        ndir_oct_ = angles_.size();

        // Expand angles to other octants
        for ( int ioct=2; ioct<=8; ioct++ ) {
            for ( int iang=0; iang < ndir_oct_; iang++ ) {
                Angle a = angles_[iang];
                angles_.push_back( a.to_octant(ioct) );
            }
        }

        return;
    }

    AngularQuadrature::AngularQuadrature( const H5Node &input ) {
        VecF ox;
        VecF oy;
        VecF oz;
        VecF weights;

        input.read("ang_quad/omega_x", ox);
        input.read("ang_quad/omega_y", oy);
        input.read("ang_quad/omega_z", oz);
        input.read("ang_quad/weight", weights);

        if( (ox.size() != oy.size()) || (ox.size() != oz.size()) ||
                (ox.size() != weights.size()) ) {
            throw EXCEPT("Incompatible data sizes");
        }

        int size = ox.size();
        if( size%8 != 0 ) {
            throw EXCEPT("Size is not evenly-divisible by 8");
        }

        ndir_oct_ = size/8;

        angles_.reserve(size);
        for( int iang=0; iang<size; iang++ ) {
            angles_.emplace_back(ox[iang], oy[iang], oz[iang], weights[iang]);
        }

        type_ = QuadratureType::MANUAL;

        return;
    }

    void AngularQuadrature::modify_angle(int iang, Angle ang ) {
        for ( int ioct=0; ioct<8; ioct++ ){
            angles_[iang + ioct*ndir_oct_] = ang.to_octant(ioct+1);
        }
    }

    std::ostream& operator<<(std::ostream& os,
            const AngularQuadrature &angquad) {
        const int w = 12;
        os << std::setw(w) << "Alpha"
           << std::setw(w) << "Theta"
           << std::setw(w) << "omega x"
           << std::setw(w) << "omega y"
           << std::setw(w) << "omega z" << std::endl;
        for( auto &ang: angquad.angles_ ) {
            os << ang << std::endl;
        }
        return os;
    }

    void AngularQuadrature::output( H5Node &node ) const {
        VecF alpha; alpha.reserve(this->ndir());
        VecF theta; theta.reserve(this->ndir());
        VecF ox;    ox.reserve(this->ndir());
        VecF oy;    oy.reserve(this->ndir());
        VecF oz;    oz.reserve(this->ndir());
        VecF w;     w.reserve(this->ndir());

        for( auto a: angles_ ) {
            alpha.push_back(a.alpha);
            theta.push_back(a.theta);
            ox.push_back(a.ox);
            oy.push_back(a.oy);
            oz.push_back(a.oz);
            w.push_back(a.weight);
        }

        auto g = node.create_group("ang_quad");

        g.write("alpha", alpha);
        g.write("theta", theta);
        g.write("omega_x", ox);
        g.write("omega_y", oy);
        g.write("omega_z", oz);
        g.write("weight", w);

        return;
    }
}
<|endoftext|>


<commit_before>#include <derecho/core/detail/connection_manager.hpp>

#include <cassert>
#include <iostream>
#include <set>

namespace tcp {
bool tcp_connections::add_connection(const node_id_t other_id,
                                     const std::pair<ip_addr_t, uint16_t>& other_ip_and_port) {
    if(other_id < my_id) {
        try {
            sockets[other_id] = socket(other_ip_and_port.first, other_ip_and_port.second);
        } catch(connection_failure) {
            std::cerr << "WARNING: failed to connect to node " << other_id << " at "
                      << other_ip_and_port.first << ":" << other_ip_and_port.second << std::endl;
            return false;
        }

        node_id_t remote_id = 0;

        try {
            sockets[other_id].exchange(my_id, remote_id);
        } catch(socket_error&) {
            std::cerr << "WARNING: failed to exchange rank with node "
                      << other_id << " at " << other_ip_and_port.first << ":" << other_ip_and_port.second
                      << std::endl;
            sockets.erase(other_id);
            return false;
        }
        if(remote_id != other_id) {
            std::cerr << "WARNING: node at " << other_ip_and_port.first << ":" << other_ip_and_port.second
                      << " replied with wrong id (expected " << other_id
                      << " but got " << remote_id << ")" << std::endl;

            sockets.erase(other_id);
            return false;
        }
        return true;
    } else if(other_id > my_id) {
        while(true) {
            try {
                socket s = conn_listener->accept();

                node_id_t remote_id = 0;
                s.exchange(my_id, remote_id);

                sockets[remote_id] = std::move(s);
                //If the connection we got wasn't the intended node, keep
                //looping and try again; there must be multiple nodes connecting
                //simultaneously
                if(remote_id == other_id)
                    return true;

            } catch(connection_failure&) {
                std::cerr << "Got error while attempting to listen on port"
                          << std::endl;
                return false;
            } catch(socket_error&) {
                std::cerr << "WARNING: failed to exchange id with node" << other_id
                          << std::endl;
                return false;
            }
        }
    }

    return false;
}

void tcp_connections::establish_node_connections(const std::map<node_id_t, std::pair<ip_addr_t, uint16_t>>& ip_addrs_and_ports) {
    for(auto it = ip_addrs_and_ports.begin(); it != ip_addrs_and_ports.end(); it++) {
        //Check that there isn't already a connection to this ID,
        //since an earlier add_connection could have connected to it by "mistake"
        if(it->first != my_id && sockets.count(it->first) == 0) {
            if(!add_connection(it->first, it->second)) {
                std::cerr << "WARNING: failed to connect to node " << it->first
                          << " at " << it->second.first
                          << ":" << it->second.second << std::endl;
            }
        }
    }
}

tcp_connections::tcp_connections(node_id_t my_id,
                                 const std::map<node_id_t, std::pair<ip_addr_t, uint16_t>> ip_addrs_and_ports)
        : my_id(my_id) {
    assert(ip_addrs_and_ports.count(my_id) > 0);
    conn_listener = std::make_unique<connection_listener>(ip_addrs_and_ports.at(my_id).second);
    establish_node_connections(ip_addrs_and_ports);
}

void tcp_connections::destroy() {
    std::lock_guard<std::mutex> lock(sockets_mutex);
    sockets.clear();
    conn_listener.reset();
}

void tcp_connections::write(node_id_t node_id, char const* buffer,
                            size_t size) {
    std::lock_guard<std::mutex> lock(sockets_mutex);
    const auto it = sockets.find(node_id);
    assert(it != sockets.end());
    it->second.write(buffer, size);
}

void tcp_connections::write_all(char const* buffer, size_t size) {
    std::lock_guard<std::mutex> lock(sockets_mutex);
    for(auto& p : sockets) {
        if(p.first == my_id) {
            continue;
        }
        p.second.write(buffer, size);
    }
}

void tcp_connections::read(node_id_t node_id, char* buffer,
                           size_t size) {
    std::lock_guard<std::mutex> lock(sockets_mutex);
    const auto it = sockets.find(node_id);
    assert(it != sockets.end());
    it->second.read(buffer, size);
}

bool tcp_connections::add_node(node_id_t new_id, const std::pair<ip_addr_t, uint16_t>& new_ip_addr_and_port) {
    std::lock_guard<std::mutex> lock(sockets_mutex);
    assert(new_id != my_id);
    //If there's already a connection to this ID, just return "success"
    if(sockets.count(new_id) > 0)
        return true;
    return add_connection(new_id, new_ip_addr_and_port);
}

bool tcp_connections::delete_node(node_id_t remove_id) {
    std::lock_guard<std::mutex> lock(sockets_mutex);
    return (sockets.erase(remove_id) > 0);
}

bool tcp_connections::contains_node(node_id_t node_id) {
    std::lock_guard<std::mutex> lock(sockets_mutex);
    return (sockets.find(node_id) != sockets.end());
}

int32_t tcp_connections::probe_all() {
    std::lock_guard<std::mutex> lock(sockets_mutex);
    for(auto& p : sockets) {
        bool new_data_available = p.second.probe();
        if(new_data_available == true) {
            return p.first;
        }
    }
    return -1;
}

void tcp_connections::filter_to(const std::vector<node_id_t>& live_nodes_list) {
    std::vector<node_id_t> sorted_nodes_list(live_nodes_list.size());
    //There's nothing "partial" about this. Make a sorted copy of live_nodes_list.
    std::partial_sort_copy(live_nodes_list.begin(), live_nodes_list.end(),
                           sorted_nodes_list.begin(), sorted_nodes_list.end());
    std::lock_guard<std::mutex> lock(sockets_mutex);
    for(auto socket_map_iter = sockets.begin(); socket_map_iter != sockets.end();) {
        if(!std::binary_search(sorted_nodes_list.begin(),
                               sorted_nodes_list.end(),
                               socket_map_iter->first)) {
            //If the node ID is not in the list, delete the socket
            socket_map_iter = sockets.erase(socket_map_iter);
        } else {
            socket_map_iter++;
        }
    }
}

derecho::LockedReference<std::unique_lock<std::mutex>, socket> tcp_connections::get_socket(node_id_t node_id) {
    return derecho::LockedReference<std::unique_lock<std::mutex>, socket>(sockets.at(node_id), sockets_mutex);
}
}  // namespace tcp
<commit_msg>bugfix: ip_addrs_and_ports is empty for external clients. We should allow that on initializing TCP connections.<commit_after>#include <derecho/core/detail/connection_manager.hpp>

#include <cassert>
#include <iostream>
#include <set>

namespace tcp {
bool tcp_connections::add_connection(const node_id_t other_id,
                                     const std::pair<ip_addr_t, uint16_t>& other_ip_and_port) {
    if(other_id < my_id) {
        try {
            sockets[other_id] = socket(other_ip_and_port.first, other_ip_and_port.second);
        } catch(connection_failure) {
            std::cerr << "WARNING: failed to connect to node " << other_id << " at "
                      << other_ip_and_port.first << ":" << other_ip_and_port.second << std::endl;
            return false;
        }

        node_id_t remote_id = 0;

        try {
            sockets[other_id].exchange(my_id, remote_id);
        } catch(socket_error&) {
            std::cerr << "WARNING: failed to exchange rank with node "
                      << other_id << " at " << other_ip_and_port.first << ":" << other_ip_and_port.second
                      << std::endl;
            sockets.erase(other_id);
            return false;
        }
        if(remote_id != other_id) {
            std::cerr << "WARNING: node at " << other_ip_and_port.first << ":" << other_ip_and_port.second
                      << " replied with wrong id (expected " << other_id
                      << " but got " << remote_id << ")" << std::endl;

            sockets.erase(other_id);
            return false;
        }
        return true;
    } else if(other_id > my_id) {
        while(true) {
            try {
                socket s = conn_listener->accept();

                node_id_t remote_id = 0;
                s.exchange(my_id, remote_id);

                sockets[remote_id] = std::move(s);
                //If the connection we got wasn't the intended node, keep
                //looping and try again; there must be multiple nodes connecting
                //simultaneously
                if(remote_id == other_id)
                    return true;

            } catch(connection_failure&) {
                std::cerr << "Got error while attempting to listen on port"
                          << std::endl;
                return false;
            } catch(socket_error&) {
                std::cerr << "WARNING: failed to exchange id with node" << other_id
                          << std::endl;
                return false;
            }
        }
    }

    return false;
}

void tcp_connections::establish_node_connections(const std::map<node_id_t, std::pair<ip_addr_t, uint16_t>>& ip_addrs_and_ports) {
    for(auto it = ip_addrs_and_ports.begin(); it != ip_addrs_and_ports.end(); it++) {
        //Check that there isn't already a connection to this ID,
        //since an earlier add_connection could have connected to it by "mistake"
        if(it->first != my_id && sockets.count(it->first) == 0) {
            if(!add_connection(it->first, it->second)) {
                std::cerr << "WARNING: failed to connect to node " << it->first
                          << " at " << it->second.first
                          << ":" << it->second.second << std::endl;
            }
        }
    }
}

tcp_connections::tcp_connections(node_id_t my_id,
                                 const std::map<node_id_t, std::pair<ip_addr_t, uint16_t>> ip_addrs_and_ports)
        : my_id(my_id) {
    if(!ip_addrs_and_ports.empty()) {
        assert(ip_addrs_and_ports.count(my_id) > 0);
        conn_listener = std::make_unique<connection_listener>(ip_addrs_and_ports.at(my_id).second);
        establish_node_connections(ip_addrs_and_ports);
    }
}

void tcp_connections::destroy() {
    std::lock_guard<std::mutex> lock(sockets_mutex);
    sockets.clear();
    conn_listener.reset();
}

void tcp_connections::write(node_id_t node_id, char const* buffer,
                            size_t size) {
    std::lock_guard<std::mutex> lock(sockets_mutex);
    const auto it = sockets.find(node_id);
    assert(it != sockets.end());
    it->second.write(buffer, size);
}

void tcp_connections::write_all(char const* buffer, size_t size) {
    std::lock_guard<std::mutex> lock(sockets_mutex);
    for(auto& p : sockets) {
        if(p.first == my_id) {
            continue;
        }
        p.second.write(buffer, size);
    }
}

void tcp_connections::read(node_id_t node_id, char* buffer,
                           size_t size) {
    std::lock_guard<std::mutex> lock(sockets_mutex);
    const auto it = sockets.find(node_id);
    assert(it != sockets.end());
    it->second.read(buffer, size);
}

bool tcp_connections::add_node(node_id_t new_id, const std::pair<ip_addr_t, uint16_t>& new_ip_addr_and_port) {
    std::lock_guard<std::mutex> lock(sockets_mutex);
    assert(new_id != my_id);
    //If there's already a connection to this ID, just return "success"
    if(sockets.count(new_id) > 0)
        return true;
    return add_connection(new_id, new_ip_addr_and_port);
}

bool tcp_connections::delete_node(node_id_t remove_id) {
    std::lock_guard<std::mutex> lock(sockets_mutex);
    return (sockets.erase(remove_id) > 0);
}

bool tcp_connections::contains_node(node_id_t node_id) {
    std::lock_guard<std::mutex> lock(sockets_mutex);
    return (sockets.find(node_id) != sockets.end());
}

int32_t tcp_connections::probe_all() {
    std::lock_guard<std::mutex> lock(sockets_mutex);
    for(auto& p : sockets) {
        bool new_data_available = p.second.probe();
        if(new_data_available == true) {
            return p.first;
        }
    }
    return -1;
}

void tcp_connections::filter_to(const std::vector<node_id_t>& live_nodes_list) {
    std::vector<node_id_t> sorted_nodes_list(live_nodes_list.size());
    //There's nothing "partial" about this. Make a sorted copy of live_nodes_list.
    std::partial_sort_copy(live_nodes_list.begin(), live_nodes_list.end(),
                           sorted_nodes_list.begin(), sorted_nodes_list.end());
    std::lock_guard<std::mutex> lock(sockets_mutex);
    for(auto socket_map_iter = sockets.begin(); socket_map_iter != sockets.end();) {
        if(!std::binary_search(sorted_nodes_list.begin(),
                               sorted_nodes_list.end(),
                               socket_map_iter->first)) {
            //If the node ID is not in the list, delete the socket
            socket_map_iter = sockets.erase(socket_map_iter);
        } else {
            socket_map_iter++;
        }
    }
}

derecho::LockedReference<std::unique_lock<std::mutex>, socket> tcp_connections::get_socket(node_id_t node_id) {
    return derecho::LockedReference<std::unique_lock<std::mutex>, socket>(sockets.at(node_id), sockets_mutex);
}
}  // namespace tcp
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2016, The OpenThread Authors.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of the copyright holder nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @file
 *   This file implements Thread security material generation.
 */

#include <openthread/config.h>

#include "key_manager.hpp"

#include "openthread-instance.h"
#include "common/code_utils.hpp"
#include "common/timer.hpp"
#include "crypto/hmac_sha256.hpp"
#include "thread/mle_router.hpp"
#include "thread/thread_netif.hpp"

namespace ot {

static const uint8_t kThreadString[] =
{
    'T', 'h', 'r', 'e', 'a', 'd',
};

KeyManager::KeyManager(ThreadNetif &aThreadNetif):
    ThreadNetifLocator(aThreadNetif),
    mKeySequence(0),
    mMacFrameCounter(0),
    mMleFrameCounter(0),
    mStoredMacFrameCounter(0),
    mStoredMleFrameCounter(0),
    mHoursSinceKeyRotation(0),
    mKeyRotationTime(kDefaultKeyRotationTime),
    mKeySwitchGuardTime(kDefaultKeySwitchGuardTime),
    mKeySwitchGuardEnabled(false),
    mKeyRotationTimer(aThreadNetif.GetInstance(), &KeyManager::HandleKeyRotationTimer, this),
    mKekFrameCounter(0),
    mSecurityPolicyFlags(0xff)
{
}

void KeyManager::Start(void)
{
    mKeySwitchGuardEnabled = false;
    StartKeyRotationTimer();
}

void KeyManager::Stop(void)
{
    mKeyRotationTimer.Stop();
}

#if OPENTHREAD_FTD
const uint8_t *KeyManager::GetPSKc(void) const
{
    return mPSKc;
}

void KeyManager::SetPSKc(const uint8_t *aPSKc)
{
    memcpy(mPSKc, aPSKc, sizeof(mPSKc));
}
#endif

const otMasterKey &KeyManager::GetMasterKey(void) const
{
    return mMasterKey;
}

otError KeyManager::SetMasterKey(const otMasterKey &aKey)
{
    otError error = OT_ERROR_NONE;
    Router *routers;
    Child *children;
    uint8_t num;

    VerifyOrExit(memcmp(&mMasterKey, &aKey, sizeof(mMasterKey)) != 0);

    mMasterKey = aKey;
    mKeySequence = 0;
    ComputeKey(mKeySequence, mKey);

    // reset parent frame counters
    routers = GetNetif().GetMle().GetParent();
    routers->SetKeySequence(0);
    routers->SetLinkFrameCounter(0);
    routers->SetMleFrameCounter(0);

    // reset router frame counters
    routers = GetNetif().GetMle().GetRouters(&num);

    for (uint8_t i = 0; i < num; i++)
    {
        routers[i].SetKeySequence(0);
        routers[i].SetLinkFrameCounter(0);
        routers[i].SetMleFrameCounter(0);
    }

    // reset child frame counters
    children = GetNetif().GetMle().GetChildren(&num);

    for (uint8_t i = 0; i < num; i++)
    {
        children[i].SetKeySequence(0);
        children[i].SetLinkFrameCounter(0);
        children[i].SetMleFrameCounter(0);
    }

    GetNetif().SetStateChangedFlags(OT_CHANGED_THREAD_KEY_SEQUENCE_COUNTER);

exit:
    return error;
}

otError KeyManager::ComputeKey(uint32_t aKeySequence, uint8_t *aKey)
{
    Crypto::HmacSha256 hmac;
    uint8_t keySequenceBytes[4];

    hmac.Start(mMasterKey.m8, sizeof(mMasterKey.m8));

    keySequenceBytes[0] = (aKeySequence >> 24) & 0xff;
    keySequenceBytes[1] = (aKeySequence >> 16) & 0xff;
    keySequenceBytes[2] = (aKeySequence >> 8) & 0xff;
    keySequenceBytes[3] = aKeySequence & 0xff;
    hmac.Update(keySequenceBytes, sizeof(keySequenceBytes));
    hmac.Update(kThreadString, sizeof(kThreadString));

    hmac.Finish(aKey);

    return OT_ERROR_NONE;
}

void KeyManager::SetCurrentKeySequence(uint32_t aKeySequence)
{
    if (aKeySequence == mKeySequence)
    {
        ExitNow();
    }

    // Check if the guard timer has expired if key rotation is requested.
    if ((aKeySequence == (mKeySequence + 1)) &&
        (mKeySwitchGuardTime != 0) &&
        mKeyRotationTimer.IsRunning() &&
        mKeySwitchGuardEnabled)
    {
        VerifyOrExit(mHoursSinceKeyRotation < mKeySwitchGuardTime);
    }

    mKeySequence = aKeySequence;
    ComputeKey(mKeySequence, mKey);

    mMacFrameCounter = 0;
    mMleFrameCounter = 0;

    if (mKeyRotationTimer.IsRunning())
    {
        mKeySwitchGuardEnabled = true;
        StartKeyRotationTimer();
    }

    GetNetif().SetStateChangedFlags(OT_CHANGED_THREAD_KEY_SEQUENCE_COUNTER);

exit:
    return;
}

const uint8_t *KeyManager::GetTemporaryMacKey(uint32_t aKeySequence)
{
    ComputeKey(aKeySequence, mTemporaryKey);
    return mTemporaryKey + kMacKeyOffset;
}

const uint8_t *KeyManager::GetTemporaryMleKey(uint32_t aKeySequence)
{
    ComputeKey(aKeySequence, mTemporaryKey);
    return mTemporaryKey;
}

void KeyManager::IncrementMacFrameCounter(void)
{
    mMacFrameCounter++;

    if (mMacFrameCounter >= mStoredMacFrameCounter)
    {
        GetNetif().GetMle().Store();
    }
}

void KeyManager::IncrementMleFrameCounter(void)
{
    mMleFrameCounter++;

    if (mMleFrameCounter >= mStoredMleFrameCounter)
    {
        GetNetif().GetMle().Store();
    }
}

void KeyManager::SetKek(const uint8_t *aKek)
{
    memcpy(mKek, aKek, sizeof(mKek));
    mKekFrameCounter = 0;
}

otError KeyManager::SetKeyRotation(uint32_t aKeyRotation)
{
    otError result = OT_ERROR_NONE;

    VerifyOrExit(aKeyRotation >= static_cast<uint32_t>(kMinKeyRotationTime), result = OT_ERROR_INVALID_ARGS);

    mKeyRotationTime = aKeyRotation;

exit:
    return result;
}

void KeyManager::StartKeyRotationTimer(void)
{
    mHoursSinceKeyRotation = 0;
    mKeyRotationTimer.Start(kOneHourIntervalInMsec);
}

void KeyManager::HandleKeyRotationTimer(Timer &aTimer)
{
    GetOwner(aTimer).HandleKeyRotationTimer();
}

void KeyManager::HandleKeyRotationTimer(void)
{
    mHoursSinceKeyRotation++;

    // Order of operations below is important. We should restart the timer (from
    // last fire time for one hour interval) before potentially calling
    // `SetCurrentKeySequence()`. `SetCurrentKeySequence()` uses the fact that
    // timer is running to decide to check for the guard time and to reset the
    // rotation timer (and the `mHoursSinceKeyRotation`) if it updates the key
    // sequence.

    mKeyRotationTimer.StartAt(mKeyRotationTimer.GetFireTime(), kOneHourIntervalInMsec);

    if (mHoursSinceKeyRotation >= mKeyRotationTime)
    {
        SetCurrentKeySequence(mKeySequence + 1);
    }
}

KeyManager &KeyManager::GetOwner(const Context &aContext)
{
#if OPENTHREAD_ENABLE_MULTIPLE_INSTANCES
    KeyManager &keyManager = *static_cast<KeyManager *>(aContext.GetContext());
#else
    KeyManager &keyManager = otGetThreadNetif().GetKeyManager();
    OT_UNUSED_VARIABLE(aContext);
#endif
    return keyManager;
}

}  // namespace ot
<commit_msg>[key-manager] fix bug that prevents local key rotation (#2235)<commit_after>/*
 *  Copyright (c) 2016, The OpenThread Authors.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of the copyright holder nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @file
 *   This file implements Thread security material generation.
 */

#include <openthread/config.h>

#include "key_manager.hpp"

#include "openthread-instance.h"
#include "common/code_utils.hpp"
#include "common/timer.hpp"
#include "crypto/hmac_sha256.hpp"
#include "thread/mle_router.hpp"
#include "thread/thread_netif.hpp"

namespace ot {

static const uint8_t kThreadString[] =
{
    'T', 'h', 'r', 'e', 'a', 'd',
};

KeyManager::KeyManager(ThreadNetif &aThreadNetif):
    ThreadNetifLocator(aThreadNetif),
    mKeySequence(0),
    mMacFrameCounter(0),
    mMleFrameCounter(0),
    mStoredMacFrameCounter(0),
    mStoredMleFrameCounter(0),
    mHoursSinceKeyRotation(0),
    mKeyRotationTime(kDefaultKeyRotationTime),
    mKeySwitchGuardTime(kDefaultKeySwitchGuardTime),
    mKeySwitchGuardEnabled(false),
    mKeyRotationTimer(aThreadNetif.GetInstance(), &KeyManager::HandleKeyRotationTimer, this),
    mKekFrameCounter(0),
    mSecurityPolicyFlags(0xff)
{
}

void KeyManager::Start(void)
{
    mKeySwitchGuardEnabled = false;
    StartKeyRotationTimer();
}

void KeyManager::Stop(void)
{
    mKeyRotationTimer.Stop();
}

#if OPENTHREAD_FTD
const uint8_t *KeyManager::GetPSKc(void) const
{
    return mPSKc;
}

void KeyManager::SetPSKc(const uint8_t *aPSKc)
{
    memcpy(mPSKc, aPSKc, sizeof(mPSKc));
}
#endif

const otMasterKey &KeyManager::GetMasterKey(void) const
{
    return mMasterKey;
}

otError KeyManager::SetMasterKey(const otMasterKey &aKey)
{
    otError error = OT_ERROR_NONE;
    Router *routers;
    Child *children;
    uint8_t num;

    VerifyOrExit(memcmp(&mMasterKey, &aKey, sizeof(mMasterKey)) != 0);

    mMasterKey = aKey;
    mKeySequence = 0;
    ComputeKey(mKeySequence, mKey);

    // reset parent frame counters
    routers = GetNetif().GetMle().GetParent();
    routers->SetKeySequence(0);
    routers->SetLinkFrameCounter(0);
    routers->SetMleFrameCounter(0);

    // reset router frame counters
    routers = GetNetif().GetMle().GetRouters(&num);

    for (uint8_t i = 0; i < num; i++)
    {
        routers[i].SetKeySequence(0);
        routers[i].SetLinkFrameCounter(0);
        routers[i].SetMleFrameCounter(0);
    }

    // reset child frame counters
    children = GetNetif().GetMle().GetChildren(&num);

    for (uint8_t i = 0; i < num; i++)
    {
        children[i].SetKeySequence(0);
        children[i].SetLinkFrameCounter(0);
        children[i].SetMleFrameCounter(0);
    }

    GetNetif().SetStateChangedFlags(OT_CHANGED_THREAD_KEY_SEQUENCE_COUNTER);

exit:
    return error;
}

otError KeyManager::ComputeKey(uint32_t aKeySequence, uint8_t *aKey)
{
    Crypto::HmacSha256 hmac;
    uint8_t keySequenceBytes[4];

    hmac.Start(mMasterKey.m8, sizeof(mMasterKey.m8));

    keySequenceBytes[0] = (aKeySequence >> 24) & 0xff;
    keySequenceBytes[1] = (aKeySequence >> 16) & 0xff;
    keySequenceBytes[2] = (aKeySequence >> 8) & 0xff;
    keySequenceBytes[3] = aKeySequence & 0xff;
    hmac.Update(keySequenceBytes, sizeof(keySequenceBytes));
    hmac.Update(kThreadString, sizeof(kThreadString));

    hmac.Finish(aKey);

    return OT_ERROR_NONE;
}

void KeyManager::SetCurrentKeySequence(uint32_t aKeySequence)
{
    if (aKeySequence == mKeySequence)
    {
        ExitNow();
    }

    // Check if the guard timer has expired if key rotation is requested.
    if ((aKeySequence == (mKeySequence + 1)) &&
        (mKeySwitchGuardTime != 0) &&
        mKeyRotationTimer.IsRunning() &&
        mKeySwitchGuardEnabled)
    {
        VerifyOrExit(mHoursSinceKeyRotation >= mKeySwitchGuardTime);
    }

    mKeySequence = aKeySequence;
    ComputeKey(mKeySequence, mKey);

    mMacFrameCounter = 0;
    mMleFrameCounter = 0;

    if (mKeyRotationTimer.IsRunning())
    {
        mKeySwitchGuardEnabled = true;
        StartKeyRotationTimer();
    }

    GetNetif().SetStateChangedFlags(OT_CHANGED_THREAD_KEY_SEQUENCE_COUNTER);

exit:
    return;
}

const uint8_t *KeyManager::GetTemporaryMacKey(uint32_t aKeySequence)
{
    ComputeKey(aKeySequence, mTemporaryKey);
    return mTemporaryKey + kMacKeyOffset;
}

const uint8_t *KeyManager::GetTemporaryMleKey(uint32_t aKeySequence)
{
    ComputeKey(aKeySequence, mTemporaryKey);
    return mTemporaryKey;
}

void KeyManager::IncrementMacFrameCounter(void)
{
    mMacFrameCounter++;

    if (mMacFrameCounter >= mStoredMacFrameCounter)
    {
        GetNetif().GetMle().Store();
    }
}

void KeyManager::IncrementMleFrameCounter(void)
{
    mMleFrameCounter++;

    if (mMleFrameCounter >= mStoredMleFrameCounter)
    {
        GetNetif().GetMle().Store();
    }
}

void KeyManager::SetKek(const uint8_t *aKek)
{
    memcpy(mKek, aKek, sizeof(mKek));
    mKekFrameCounter = 0;
}

otError KeyManager::SetKeyRotation(uint32_t aKeyRotation)
{
    otError result = OT_ERROR_NONE;

    VerifyOrExit(aKeyRotation >= static_cast<uint32_t>(kMinKeyRotationTime), result = OT_ERROR_INVALID_ARGS);

    mKeyRotationTime = aKeyRotation;

exit:
    return result;
}

void KeyManager::StartKeyRotationTimer(void)
{
    mHoursSinceKeyRotation = 0;
    mKeyRotationTimer.Start(kOneHourIntervalInMsec);
}

void KeyManager::HandleKeyRotationTimer(Timer &aTimer)
{
    GetOwner(aTimer).HandleKeyRotationTimer();
}

void KeyManager::HandleKeyRotationTimer(void)
{
    mHoursSinceKeyRotation++;

    // Order of operations below is important. We should restart the timer (from
    // last fire time for one hour interval) before potentially calling
    // `SetCurrentKeySequence()`. `SetCurrentKeySequence()` uses the fact that
    // timer is running to decide to check for the guard time and to reset the
    // rotation timer (and the `mHoursSinceKeyRotation`) if it updates the key
    // sequence.

    mKeyRotationTimer.StartAt(mKeyRotationTimer.GetFireTime(), kOneHourIntervalInMsec);

    if (mHoursSinceKeyRotation >= mKeyRotationTime)
    {
        SetCurrentKeySequence(mKeySequence + 1);
    }
}

KeyManager &KeyManager::GetOwner(const Context &aContext)
{
#if OPENTHREAD_ENABLE_MULTIPLE_INSTANCES
    KeyManager &keyManager = *static_cast<KeyManager *>(aContext.GetContext());
#else
    KeyManager &keyManager = otGetThreadNetif().GetKeyManager();
    OT_UNUSED_VARIABLE(aContext);
#endif
    return keyManager;
}

}  // namespace ot
<|endoftext|>


<commit_before>/*
 * Client.cpp
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include <monitor/http/Client.hpp>

#include <boost/asio/io_service.hpp>

#include <monitor/metrics/Metric.hpp>

using namespace core;

namespace monitor {
namespace http {

namespace {

class MonitorLogWriter : public core::LogWriter
{
public:
   MonitorLogWriter(const std::string& metricsSocket,
                    const std::string& sharedSecret,
                    const std::string& programIdentity)
      : metricsSocket_(metricsSocket),
        sharedSecret_(sharedSecret),
        programIdentity_(programIdentity)
   {
   }

   virtual void log(core::system::LogLevel level, const std::string& message)
   {
      monitor::http::log(metricsSocket_,
                         sharedSecret_,
                         programIdentity_,
                         level,
                         message);
   }

protected:
   std::string metricsSocket_;
   std::string sharedSecret_;
   std::string programIdentity_;
};

class MonitorAsyncLogWriter : public MonitorLogWriter
{
public:
   MonitorAsyncLogWriter(boost::asio::io_service& ioService,
                         const std::string& metricsSocket,
                         const std::string& sharedSecret,
                         const std::string& programIdentity)
      : MonitorLogWriter(metricsSocket, sharedSecret, programIdentity),
        ioService_(ioService)
   {
   }

   virtual void log(core::system::LogLevel level, const std::string& message)
   {
      monitor::http::logAsync(ioService_,
                              metricsSocket_,
                              sharedSecret_,
                              programIdentity_,
                              level,
                              message);
   }

private:
   boost::asio::io_service& ioService_;
};

} // anonymous namespace

boost::shared_ptr<core::LogWriter> monitorLogWriter(
                                       const std::string& metricsSocket,
                                       const std::string& sharedSecret,
                                       const std::string& programIdentity)
{
   return boost::shared_ptr<core::LogWriter>(new MonitorLogWriter(
                                                   metricsSocket,
                                                   sharedSecret,
                                                   programIdentity));
}

boost::shared_ptr<core::LogWriter> monitorAsyncLogWriter(
                                       boost::asio::io_service& ioService,
                                       const std::string& metricsSocket,
                                       const std::string& sharedSecret,
                                       const std::string& programIdentity)
{
   return boost::shared_ptr<core::LogWriter>(new MonitorAsyncLogWriter(
                                                   ioService,
                                                   metricsSocket,
                                                   sharedSecret,
                                                   programIdentity));
}

void log(const std::string& metricsSocket,
         const std::string& sharedSecret,
         const std::string& programIdentity,
         core::system::LogLevel level,
         const std::string& message)
{
}

void logAsync(boost::asio::io_service& ioService,
              const std::string& metricsSocket,
              const std::string& sharedSecret,
              const std::string& programIdentity,
              core::system::LogLevel level,
              const std::string& message)
{
}

void sendMetrics(const std::string& metricsSocket,
                 const std::string& sharedSecret,
                 const std::vector<metrics::Metric>& metrics)
{
}

void sendMultiMetrics(const std::string& metricsSocket,
                      const std::string& sharedSecret,
                      const std::vector<metrics::MultiMetric>& metrics)
{
}

void sendMetricsAsync(boost::asio::io_service& ioService,
                      const std::string& metricsSocket,
                      const std::string& sharedSecret,
                      const std::vector<metrics::Metric>& metrics)
{
}

void sendMultiMetricsAsync(boost::asio::io_service& ioService,
                           const std::string& metricsSocket,
                           const std::string& sharedSecret,
                           const std::vector<metrics::MultiMetric>& metrics)
{
}

} // namespace http
} // namespace monitor

<commit_msg>implement program identity override for monitor log writers<commit_after>/*
 * Client.cpp
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include <monitor/http/Client.hpp>

#include <boost/asio/io_service.hpp>

#include <monitor/metrics/Metric.hpp>

using namespace core;

namespace monitor {
namespace http {

namespace {

class MonitorLogWriter : public core::LogWriter
{
public:
   MonitorLogWriter(const std::string& metricsSocket,
                    const std::string& sharedSecret,
                    const std::string& programIdentity)
      : metricsSocket_(metricsSocket),
        sharedSecret_(sharedSecret),
        programIdentity_(programIdentity)
   {
   }

   virtual void log(core::system::LogLevel level, const std::string& message)
   {
      log(programIdentity_, level, message);
   }

   virtual void log(const std::string& programIdentity,
                    core::system::LogLevel level,
                    const std::string& message)
   {
      monitor::http::log(metricsSocket_,
                         sharedSecret_,
                         programIdentity,
                         level,
                         message);
   }

protected:
   std::string metricsSocket_;
   std::string sharedSecret_;
   std::string programIdentity_;
};

class MonitorAsyncLogWriter : public MonitorLogWriter
{
public:
   MonitorAsyncLogWriter(boost::asio::io_service& ioService,
                         const std::string& metricsSocket,
                         const std::string& sharedSecret,
                         const std::string& programIdentity)
      : MonitorLogWriter(metricsSocket, sharedSecret, programIdentity),
        ioService_(ioService)
   {
   }

   virtual void log(core::system::LogLevel level, const std::string& message)
   {
      log(programIdentity_, level, message);
   }

   virtual void log(const std::string& programIdentity,
                    core::system::LogLevel level,
                    const std::string& message)
   {
      monitor::http::logAsync(ioService_,
                              metricsSocket_,
                              sharedSecret_,
                              programIdentity,
                              level,
                              message);
   }

private:
   boost::asio::io_service& ioService_;
};

} // anonymous namespace

boost::shared_ptr<core::LogWriter> monitorLogWriter(
                                       const std::string& metricsSocket,
                                       const std::string& sharedSecret,
                                       const std::string& programIdentity)
{
   return boost::shared_ptr<core::LogWriter>(new MonitorLogWriter(
                                                   metricsSocket,
                                                   sharedSecret,
                                                   programIdentity));
}

boost::shared_ptr<core::LogWriter> monitorAsyncLogWriter(
                                       boost::asio::io_service& ioService,
                                       const std::string& metricsSocket,
                                       const std::string& sharedSecret,
                                       const std::string& programIdentity)
{
   return boost::shared_ptr<core::LogWriter>(new MonitorAsyncLogWriter(
                                                   ioService,
                                                   metricsSocket,
                                                   sharedSecret,
                                                   programIdentity));
}

void log(const std::string& metricsSocket,
         const std::string& sharedSecret,
         const std::string& programIdentity,
         core::system::LogLevel level,
         const std::string& message)
{
}

void logAsync(boost::asio::io_service& ioService,
              const std::string& metricsSocket,
              const std::string& sharedSecret,
              const std::string& programIdentity,
              core::system::LogLevel level,
              const std::string& message)
{
}

void sendMetrics(const std::string& metricsSocket,
                 const std::string& sharedSecret,
                 const std::vector<metrics::Metric>& metrics)
{
}

void sendMultiMetrics(const std::string& metricsSocket,
                      const std::string& sharedSecret,
                      const std::vector<metrics::MultiMetric>& metrics)
{
}

void sendMetricsAsync(boost::asio::io_service& ioService,
                      const std::string& metricsSocket,
                      const std::string& sharedSecret,
                      const std::vector<metrics::Metric>& metrics)
{
}

void sendMultiMetricsAsync(boost::asio::io_service& ioService,
                           const std::string& metricsSocket,
                           const std::string& sharedSecret,
                           const std::vector<metrics::MultiMetric>& metrics)
{
}

} // namespace http
} // namespace monitor

<|endoftext|>


<commit_before>#include "Resizer.h"
using namespace std;
namespace cvImagePipeline {
	namespace Filter {
		///////////////////////////////////////////////////////////////////////////
		// class Resizer

		IMPLEMENT_CVFILTER(Resizer);
		Resizer::Resizer()
			: width("width", 640), height("height", 480)
		{
			defParam(this->width);
			defParam(this->height);
		}
		Resizer::Resizer(int width, int height)
			: width("width", width), height("height", height)
		{
			defParam(this->width);
			defParam(this->height);
		}
		void Resizer::execute() {
			const cv::Mat& inputMat = getInputMat();
			cv::resize(inputMat, refOutputMat(), cv::Size(width, height));
		}
	}
}
<commit_msg>check input Mat empty.<commit_after>#include "Resizer.h"
using namespace std;
namespace cvImagePipeline {
	namespace Filter {
		///////////////////////////////////////////////////////////////////////////
		// class Resizer

		IMPLEMENT_CVFILTER(Resizer);
		Resizer::Resizer()
			: width("width", 640), height("height", 480)
		{
			defParam(this->width);
			defParam(this->height);
		}
		Resizer::Resizer(int width, int height)
			: width("width", width), height("height", height)
		{
			defParam(this->width);
			defParam(this->height);
		}
		void Resizer::execute() {
			const cv::Mat& inputMat = getInputMat();
			if(!inputMat.empty()) {
				cv::resize(inputMat, refOutputMat(), cv::Size(width, height));
			}
		}
	}
}
<|endoftext|>


<commit_before>/**
  \file
  Microscope task.  Acquire stacks for each marked tile in a plane.

  \author Nathan Clack <clackn@janelia.hhmi.org>

  \copyright
  Copyright 2010 Howard Hughes Medical Institute.
  All rights reserved.
  Use is subject to Janelia Farm Research Campus Software Copyright 1.1
  license terms (http://license.janelia.org/license/jfrc_copyright_1_1.html).
 */

#include "common.h"
#include "AdaptiveTiledAcquisition.h"
#include "StackAcquisition.h"
#include "Video.h"
#include "frame.h"
#include "devices\digitizer.h"
#include "devices\Microscope.h"
#include "devices\tiling.h"
#include "tasks\SurfaceFind.h"

#if 1 // PROFILING
#define TS_OPEN(name)   timestream_t ts__=timestream_open(name)
#define TS_TIC          timestream_tic(ts__)
#define TS_TOC          timestream_toc(ts__)
#define TS_CLOSE        timestream_close(ts__)
#else
#define TS_OPEN(name)
#define TS_TIC
#define TS_TOC
#define TS_CLOSE
#endif

#define CHKJMP(expr) if(!(expr)) {warning("%s(%d)"ENDL"\tExpression indicated failure:"ENDL"\t%s"ENDL,__FILE__,__LINE__,#expr); goto Error;}

namespace fetch
{

  namespace task
  {

    //
    // AdaptiveTiledAcquisition -  microscope task
    //

    namespace microscope {

      //Upcasting
      unsigned int AdaptiveTiledAcquisition::config(IDevice *d) {return config(dynamic_cast<device::Microscope*>(d));}
      unsigned int AdaptiveTiledAcquisition::run   (IDevice *d) {return run   (dynamic_cast<device::Microscope*>(d));}

      unsigned int AdaptiveTiledAcquisition::config(device::Microscope *d)
      {
        static task::scanner::ScanStack<u16> grabstack;
        std::string filename;

        Guarded_Assert(d);

        //Assemble pipeline here
        IDevice *cur;
        cur = d->configPipeline();

        CHKJMP(d->file_series.ensurePathExists());
        d->file_series.inc();
        filename = d->stack_filename();
        IDevice::connect(&d->disk,0,cur,0);
        Guarded_Assert( d->disk.close()==0 );
        //Guarded_Assert( d->disk.open(filename,"w")==0);

        d->__scan_agent.disarm(10000/*timeout_ms*/);
        int isok=d->__scan_agent.arm(&grabstack,&d->scanner)==0;
        d->stage()->tiling()->resetCursor();          // this is here so that run/stop cycles will pick up where they left off

        return isok; //success
Error:
        return 0;
      }

      static int _handle_wait_for_result(DWORD result, const char *msg)
      {
          return_val_if( result == WAIT_OBJECT_0  , 0 );
          return_val_if( result == WAIT_OBJECT_0+1, 1 );
          Guarded_Assert_WinErr( result != WAIT_FAILED );
          if(result == WAIT_ABANDONED_0)   warning("%s(%d)"ENDL "\tAdaptiveTiledAcquisition: Wait 0 abandoned"ENDL "\t%s"ENDL, __FILE__, __LINE__, msg);
          if(result == WAIT_ABANDONED_0+1) warning("%s(%d)"ENDL "\tAdaptiveTiledAcquisition: Wait 1 abandoned"ENDL "\t%s"ENDL, __FILE__, __LINE__, msg);
          if(result == WAIT_TIMEOUT)       warning("%s(%d)"ENDL "\tAdaptiveTiledAcquisition: Wait timeout"ENDL     "\t%s"ENDL, __FILE__, __LINE__, msg);

          Guarded_Assert_WinErr( result !=WAIT_FAILED );

          return -1;
      }

      unsigned int AdaptiveTiledAcquisition::run(device::Microscope *dc)
      {
        SurfaceFind surface_find;
        std::string filename;
        unsigned int eflag = 0; // success
        Vector3f tilepos;
        float tiling_offset_acc_mm=0.0f;
        float nsamp=0;
		int numberImaged;
        int adapt_count=0;
        int adapt_thresh=dc->get_config().adaptive_tiling().every();
        int adapt_mindist=dc->get_config().adaptive_tiling().mindist();
        TS_OPEN("timer-tiles.f32");
        CHKJMP(dc->__scan_agent.is_runnable());

        device::StageTiling* tiling = dc->stage()->tiling();
		uint32_t attributes = device::StageTiling::Addressable | device::StageTiling::Safe | device::StageTiling::Active | device::StageTiling::Done; //DGA: Will be used to count the number of tiles already imaged
		numberImaged = tiling->numberOfTilesWithGivenAttributes(attributes);
		// 1. iterate over tiles to measure the average tile offset
        tiling->resetCursor();
		float startingZForImagingTilesForTwoDimensionalTiling_um = dc->stage()->getTarget().z()*1000.0f; //DGA: Gets the current stage target position in z and stores that as the startingZForImagingTilesForTwoDimensionalTiling_um since using tilepos determined from lattice position would be nonsensical when only using a 2D lattice
		//DGA:Next, reset tiling z offset to 0, otherwise when surface_find is performed, tiling_offset_acc_mm accumulates ALL of the z offsets.
		//This is because originally, in 3D tiling mode, an offset in one slice would be used as the amount to translate when starting the next slice.
		//Then that slice's offset would be measured from there etc and so the total offset would accumulate.
		if (tiling->useTwoDimensionalTiling_) dc->stage()->set_tiling_z_offset_mm(0.0f);

		bool skipSurfaceFindOnImageResume = dc->getSkipSurfaceFindOnImageResume();//DGA: Is skipSurfaceFindOnImageResume true
		if ( numberImaged==0 ? true : !skipSurfaceFindOnImageResume){ //DGA: If no tiles have been imaged, then will iterate over tiles as usual. If at least one has been imaged, then will skip this iteration if skipSurfaceFindOnImageResume is true; else will do the iteration (which will update z)
			while (eflag == 0 && !dc->_agent->is_stopping() && tiling->nextInPlanePosition(tilepos))
			{
				if (adapt_mindist <= tiling->minDistTo(0, 0,  // domain query   -- do not restrict to a particular tile type
					device::StageTiling::Active, 0)) // boundary query -- this is defines what is "outside"
				{
					if (++adapt_count > adapt_thresh) // is it time to try?
					{	adapt_count = 0;
						// M O V E
						Vector3f curpos = dc->stage()->getTarget(); // use current target z for tilepos z
						debug("%s(%d)"ENDL "\t[Adaptive Tiling Task] curpos: %5.1f %5.1f %5.1f"ENDL, __FILE__, __LINE__, curpos[0] * 1000.0f, curpos[1] * 1000.0f, curpos[2] * 1000.0f);
						if (tiling->useTwoDimensionalTiling_) tilepos[2] = curpos[2]*1000.0f; // DGA: Use current target z for tilepos z if using two dimensional tiling (rather than the lattice position)
						dc->stage()->setPos(0.001f*tilepos);        // convert um to mm
						curpos = dc->stage()->getTarget(); // use current target z for tilepos z
						debug("%s(%d)"ENDL "\t[Adaptive Tiling Task] curpos: %5.1f %5.1f %5.1f"ENDL, __FILE__, __LINE__, curpos[0] * 1000.0f, curpos[1] * 1000.0f, curpos[2] * 1000.0f);

						// A D A P T I V E
#if 0
						if (adapt_count>2*adapt_thresh) // have too many detections been missed
						{ warning("Could not track surface.  Giving up.\n");
						goto Error;
						}
#endif
						//surface_find.config();  -- arms stack task as scan agent...redundant
						eflag |= surface_find.run(dc);
						if (surface_find.hit())
						{	tiling_offset_acc_mm += dc->stage()->tiling_z_offset_mm();
							++nsamp;
						}

					}
				}
			}
			if (nsamp == 0)
			{
				warning("Could not track surface because no candidate sampling points were found.\n");
				//goto Error;
			}
			else {
				debug("%s(%d)"ENDL "\t[Adaptive Tiling Task] Average tile offset (samples: %5d) %f"ENDL, __FILE__, __LINE__, (int)nsamp, tiling_offset_acc_mm / nsamp);
				dc->stage()->set_tiling_z_offset_mm(tiling_offset_acc_mm / nsamp);
				startingZForImagingTilesForTwoDimensionalTiling_um += dc->stage()->tiling_z_offset_mm()*1000.0f; //DGA: If offset measurement has been performed, add the average tiling offset to the starting z position for two dimensional tiling imaging
			}
		}
		// retore connection between end of pipeline and disk
        IDevice::connect(&dc->disk,0,dc->_end_of_pipeline,0);

        // 2. iterate over tiles to image
        tiling->resetCursor();
        while(eflag==0 && !dc->_agent->is_stopping() && tiling->nextInPlanePosition(tilepos))
        { TS_TIC;
          debug("%s(%d)"ENDL "\t[Adaptive Tiling Task] tilepos: %5.1f %5.1f %5.1f"ENDL,__FILE__,__LINE__,tilepos[0],tilepos[1],tilepos[2]);
          filename = dc->stack_filename();
          dc->file_series.ensurePathExists();
          dc->disk.set_nchan(dc->scanner.get2d()->digitizer()->nchan());
          eflag |= dc->disk.open(filename,"w");
          if(eflag)
          {
            warning("Couldn't open file: %s"ENDL, filename.c_str());
            return eflag;
          }

          // Move stage
          Vector3f curpos = dc->stage()->getTarget(); // use current target z for tilepos z

         // if (skipSurfaceFindOnImageResume) tilepos(2) = dc->stage()->getPos().z()*1000; //DGA: When surface find is skipped, imaging resumes at the stage's current z value (in um);
          debug("%s(%d)"ENDL "\t[Adaptive Tiling Task] curpos: %5.1f %5.1f %5.1f"ENDL,__FILE__,__LINE__,curpos[0]*1000.0f,curpos[1]*1000.0f,curpos[2]*1000.0f);
		  if (tiling->useTwoDimensionalTiling_) tilepos[2] = startingZForImagingTilesForTwoDimensionalTiling_um; // DGA: Use startingZForImagingTilesForTwoDimensionalTiling_um if using two dimensional tiling
          dc->stage()->setPos(0.001f*tilepos);        // convert um to mm
          curpos = dc->stage()->getTarget(); // use current target z for tilepos z
          debug("%s(%d)"ENDL "\t[Adaptive Tiling Task] curpos: %5.1f %5.1f %5.1f"ENDL,__FILE__,__LINE__,curpos[0]*1000.0f,curpos[1]*1000.0f,curpos[2]*1000.0f);

          eflag |= dc->runPipeline();
          eflag |= dc->__scan_agent.run() != 1;

          { // Wait for stack to finish
            HANDLE hs[] = {
              dc->__scan_agent._thread,
              dc->__self_agent._notify_stop};
            DWORD res;
            int   t;

            // wait for scan to complete (or cancel)
            res = WaitForMultipleObjects(2,hs,FALSE,INFINITE);
            t = _handle_wait_for_result(res,"AdaptiveTiledAcquisition::run - Wait for scanner to finish.");
            switch(t)
            {
            case 0:                            // in this case, the scanner thread stopped.  Nothing left to do.
              eflag |= dc->__scan_agent.last_run_result(); // check the run result
              eflag |= dc->__io_agent.last_run_result();
              if(eflag==0) // remove this if statement to mark tiles as "error" tiles.  In practice, it seems it's ok to go back and reimage, so the if statement stays
                tiling->markDone(eflag==0);      // only mark the tile done if the scanner task completed normally
            case 1:                            // in this case, the stop event triggered and must be propagated.
              eflag |= dc->__scan_agent.stop(SCANNER2D_DEFAULT_TIMEOUT) != 1;
              break;
            default:                           // in this case, there was a timeout or abandoned wait
              eflag |= 1;                      // failure
            }
          } // end waiting block

          // Output and Increment files
          dc->write_stack_metadata();          // write the metadata
          eflag |= dc->disk.close();
          dc->file_series.inc();               // increment regardless of completion status
          eflag |= dc->stopPipeline();         // wait till everything stops

          TS_TOC;
        } // end loop over tiles
        eflag |= dc->stopPipeline();           // wait till the  pipeline stops
        TS_CLOSE;
        return eflag;
Error:
        TS_CLOSE;
        return 1;
      }

    } // namespace microscope

  }   // namespace task
}     // namespace fetch
<commit_msg>fix/SettableZForSkipSurfaceFind: Now when surface find is skipped in 3D mode, imaging will resume at the stage's z position<commit_after>/**
  \file
  Microscope task.  Acquire stacks for each marked tile in a plane.

  \author Nathan Clack <clackn@janelia.hhmi.org>

  \copyright
  Copyright 2010 Howard Hughes Medical Institute.
  All rights reserved.
  Use is subject to Janelia Farm Research Campus Software Copyright 1.1
  license terms (http://license.janelia.org/license/jfrc_copyright_1_1.html).
 */

#include "common.h"
#include "AdaptiveTiledAcquisition.h"
#include "StackAcquisition.h"
#include "Video.h"
#include "frame.h"
#include "devices\digitizer.h"
#include "devices\Microscope.h"
#include "devices\tiling.h"
#include "tasks\SurfaceFind.h"

#if 1 // PROFILING
#define TS_OPEN(name)   timestream_t ts__=timestream_open(name)
#define TS_TIC          timestream_tic(ts__)
#define TS_TOC          timestream_toc(ts__)
#define TS_CLOSE        timestream_close(ts__)
#else
#define TS_OPEN(name)
#define TS_TIC
#define TS_TOC
#define TS_CLOSE
#endif

#define CHKJMP(expr) if(!(expr)) {warning("%s(%d)"ENDL"\tExpression indicated failure:"ENDL"\t%s"ENDL,__FILE__,__LINE__,#expr); goto Error;}

namespace fetch
{

  namespace task
  {

    //
    // AdaptiveTiledAcquisition -  microscope task
    //

    namespace microscope {

      //Upcasting
      unsigned int AdaptiveTiledAcquisition::config(IDevice *d) {return config(dynamic_cast<device::Microscope*>(d));}
      unsigned int AdaptiveTiledAcquisition::run   (IDevice *d) {return run   (dynamic_cast<device::Microscope*>(d));}

      unsigned int AdaptiveTiledAcquisition::config(device::Microscope *d)
      {
        static task::scanner::ScanStack<u16> grabstack;
        std::string filename;

        Guarded_Assert(d);

        //Assemble pipeline here
        IDevice *cur;
        cur = d->configPipeline();

        CHKJMP(d->file_series.ensurePathExists());
        d->file_series.inc();
        filename = d->stack_filename();
        IDevice::connect(&d->disk,0,cur,0);
        Guarded_Assert( d->disk.close()==0 );
        //Guarded_Assert( d->disk.open(filename,"w")==0);

        d->__scan_agent.disarm(10000/*timeout_ms*/);
        int isok=d->__scan_agent.arm(&grabstack,&d->scanner)==0;
        d->stage()->tiling()->resetCursor();          // this is here so that run/stop cycles will pick up where they left off

        return isok; //success
Error:
        return 0;
      }

      static int _handle_wait_for_result(DWORD result, const char *msg)
      {
          return_val_if( result == WAIT_OBJECT_0  , 0 );
          return_val_if( result == WAIT_OBJECT_0+1, 1 );
          Guarded_Assert_WinErr( result != WAIT_FAILED );
          if(result == WAIT_ABANDONED_0)   warning("%s(%d)"ENDL "\tAdaptiveTiledAcquisition: Wait 0 abandoned"ENDL "\t%s"ENDL, __FILE__, __LINE__, msg);
          if(result == WAIT_ABANDONED_0+1) warning("%s(%d)"ENDL "\tAdaptiveTiledAcquisition: Wait 1 abandoned"ENDL "\t%s"ENDL, __FILE__, __LINE__, msg);
          if(result == WAIT_TIMEOUT)       warning("%s(%d)"ENDL "\tAdaptiveTiledAcquisition: Wait timeout"ENDL     "\t%s"ENDL, __FILE__, __LINE__, msg);

          Guarded_Assert_WinErr( result !=WAIT_FAILED );

          return -1;
      }

      unsigned int AdaptiveTiledAcquisition::run(device::Microscope *dc)
      {
        SurfaceFind surface_find;
        std::string filename;
        unsigned int eflag = 0; // success
        Vector3f tilepos;
        float tiling_offset_acc_mm=0.0f;
        float nsamp=0;
		int numberImaged;
        int adapt_count=0;
        int adapt_thresh=dc->get_config().adaptive_tiling().every();
        int adapt_mindist=dc->get_config().adaptive_tiling().mindist();
        TS_OPEN("timer-tiles.f32");
        CHKJMP(dc->__scan_agent.is_runnable());

        device::StageTiling* tiling = dc->stage()->tiling();
		uint32_t attributes = device::StageTiling::Addressable | device::StageTiling::Safe | device::StageTiling::Active | device::StageTiling::Done; //DGA: Will be used to count the number of tiles already imaged
		numberImaged = tiling->numberOfTilesWithGivenAttributes(attributes);
		// 1. iterate over tiles to measure the average tile offset
        tiling->resetCursor();
		float startingZForImagingTilesForTwoDimensionalTiling_um = dc->stage()->getTarget().z()*1000.0f; //DGA: Gets the current stage target position in z and stores that as the startingZForImagingTilesForTwoDimensionalTiling_um since using tilepos determined from lattice position would be nonsensical when only using a 2D lattice
		//DGA:Next, reset tiling z offset to 0, otherwise when surface_find is performed, tiling_offset_acc_mm accumulates ALL of the z offsets.
		//This is because originally, in 3D tiling mode, an offset in one slice would be used as the amount to translate when starting the next slice.
		//Then that slice's offset would be measured from there etc and so the total offset would accumulate.
		if (tiling->useTwoDimensionalTiling_) dc->stage()->set_tiling_z_offset_mm(0.0f);

		bool skipSurfaceFindOnImageResume = dc->getSkipSurfaceFindOnImageResume();//DGA: Is skipSurfaceFindOnImageResume true
		bool didSkipSurfaceFind = true;
		if ( numberImaged==0 ? true : !skipSurfaceFindOnImageResume){ //DGA: If no tiles have been imaged, then will iterate over tiles as usual. If at least one has been imaged, then will skip this iteration if skipSurfaceFindOnImageResume is true; else will do the iteration (which will update z)
			while (eflag == 0 && !dc->_agent->is_stopping() && tiling->nextInPlanePosition(tilepos))
			{
				if (adapt_mindist <= tiling->minDistTo(0, 0,  // domain query   -- do not restrict to a particular tile type
					device::StageTiling::Active, 0)) // boundary query -- this is defines what is "outside"
				{
					if (++adapt_count > adapt_thresh) // is it time to try?
					{	adapt_count = 0;
						// M O V E
						Vector3f curpos = dc->stage()->getTarget(); // use current target z for tilepos z
						debug("%s(%d)"ENDL "\t[Adaptive Tiling Task] curpos: %5.1f %5.1f %5.1f"ENDL, __FILE__, __LINE__, curpos[0] * 1000.0f, curpos[1] * 1000.0f, curpos[2] * 1000.0f);
						if (tiling->useTwoDimensionalTiling_) tilepos[2] = curpos[2]*1000.0f; // DGA: Use current target z for tilepos z if using two dimensional tiling (rather than the lattice position)
						dc->stage()->setPos(0.001f*tilepos);        // convert um to mm
						curpos = dc->stage()->getTarget(); // use current target z for tilepos z
						debug("%s(%d)"ENDL "\t[Adaptive Tiling Task] curpos: %5.1f %5.1f %5.1f"ENDL, __FILE__, __LINE__, curpos[0] * 1000.0f, curpos[1] * 1000.0f, curpos[2] * 1000.0f);

						// A D A P T I V E
#if 0
						if (adapt_count>2*adapt_thresh) // have too many detections been missed
						{ warning("Could not track surface.  Giving up.\n");
						goto Error;
						}
#endif
						//surface_find.config();  -- arms stack task as scan agent...redundant
						eflag |= surface_find.run(dc);
						if (surface_find.hit())
						{	tiling_offset_acc_mm += dc->stage()->tiling_z_offset_mm();
							++nsamp;
						}

					}
				}
			}
			if (nsamp == 0)
			{
				warning("Could not track surface because no candidate sampling points were found.\n");
				//goto Error;
			}
			else {
				debug("%s(%d)"ENDL "\t[Adaptive Tiling Task] Average tile offset (samples: %5d) %f"ENDL, __FILE__, __LINE__, (int)nsamp, tiling_offset_acc_mm / nsamp);
				dc->stage()->set_tiling_z_offset_mm(tiling_offset_acc_mm / nsamp);
				startingZForImagingTilesForTwoDimensionalTiling_um += dc->stage()->tiling_z_offset_mm()*1000.0f; //DGA: If offset measurement has been performed, add the average tiling offset to the starting z position for two dimensional tiling imaging
			}
			didSkipSurfaceFind = false;
		}
		// retore connection between end of pipeline and disk
        IDevice::connect(&dc->disk,0,dc->_end_of_pipeline,0);

        // 2. iterate over tiles to image
        tiling->resetCursor();
        while(eflag==0 && !dc->_agent->is_stopping() && tiling->nextInPlanePosition(tilepos))
        { TS_TIC;
          debug("%s(%d)"ENDL "\t[Adaptive Tiling Task] tilepos: %5.1f %5.1f %5.1f"ENDL,__FILE__,__LINE__,tilepos[0],tilepos[1],tilepos[2]);
          filename = dc->stack_filename();
          dc->file_series.ensurePathExists();
          dc->disk.set_nchan(dc->scanner.get2d()->digitizer()->nchan());
          eflag |= dc->disk.open(filename,"w");
          if(eflag)
          {
            warning("Couldn't open file: %s"ENDL, filename.c_str());
            return eflag;
          }

          // Move stage
          Vector3f curpos = dc->stage()->getTarget(); // use current target z for tilepos z

          debug("%s(%d)"ENDL "\t[Adaptive Tiling Task] curpos: %5.1f %5.1f %5.1f"ENDL,__FILE__,__LINE__,curpos[0]*1000.0f,curpos[1]*1000.0f,curpos[2]*1000.0f);
		  if (didSkipSurfaceFind || tiling->useTwoDimensionalTiling_) tilepos[2] = startingZForImagingTilesForTwoDimensionalTiling_um; // DGA: Use startingZForImagingTilesForTwoDimensionalTiling_um if using two dimensional tiling or if surface find was skipped (useful when 3D tiling used)
          dc->stage()->setPos(0.001f*tilepos);        // convert um to mm
          curpos = dc->stage()->getTarget(); // use current target z for tilepos z
          debug("%s(%d)"ENDL "\t[Adaptive Tiling Task] curpos: %5.1f %5.1f %5.1f"ENDL,__FILE__,__LINE__,curpos[0]*1000.0f,curpos[1]*1000.0f,curpos[2]*1000.0f);

          eflag |= dc->runPipeline();
          eflag |= dc->__scan_agent.run() != 1;

          { // Wait for stack to finish
            HANDLE hs[] = {
              dc->__scan_agent._thread,
              dc->__self_agent._notify_stop};
            DWORD res;
            int   t;

            // wait for scan to complete (or cancel)
            res = WaitForMultipleObjects(2,hs,FALSE,INFINITE);
            t = _handle_wait_for_result(res,"AdaptiveTiledAcquisition::run - Wait for scanner to finish.");
            switch(t)
            {
            case 0:                            // in this case, the scanner thread stopped.  Nothing left to do.
              eflag |= dc->__scan_agent.last_run_result(); // check the run result
              eflag |= dc->__io_agent.last_run_result();
              if(eflag==0) // remove this if statement to mark tiles as "error" tiles.  In practice, it seems it's ok to go back and reimage, so the if statement stays
                tiling->markDone(eflag==0);      // only mark the tile done if the scanner task completed normally
            case 1:                            // in this case, the stop event triggered and must be propagated.
              eflag |= dc->__scan_agent.stop(SCANNER2D_DEFAULT_TIMEOUT) != 1;
              break;
            default:                           // in this case, there was a timeout or abandoned wait
              eflag |= 1;                      // failure
            }
          } // end waiting block

          // Output and Increment files
          dc->write_stack_metadata();          // write the metadata
          eflag |= dc->disk.close();
          dc->file_series.inc();               // increment regardless of completion status
          eflag |= dc->stopPipeline();         // wait till everything stops

          TS_TOC;
        } // end loop over tiles
        eflag |= dc->stopPipeline();           // wait till the  pipeline stops
        TS_CLOSE;
        return eflag;
Error:
        TS_CLOSE;
        return 1;
      }

    } // namespace microscope

  }   // namespace task
}     // namespace fetch
<|endoftext|>


<commit_before>#include "niven/Mime.h"

namespace niven
{
	const std::map<std::string, std::string> Mime::ByExtension = {
		{ "json",	"application/json" },
		{ "js",		"application/javascript" },

		{ "gif",	"image/gif" },
		{ "jpg",	"image/jpeg" },
		{ "jpeg",	"image/jpeg" },
		{ "png",	"image/png" },

		{ "css", 	"text/css" },
		{ "html", 	"text/html" },
		{ "txt",	"text/plain" },
		{ "xml", 	"text/xml" },
	};
}
<commit_msg>Added gz mimetype<commit_after>#include "niven/Mime.h"

namespace niven
{
	const std::map<std::string, std::string> Mime::ByExtension = {
		{ "json",	"application/json" },
		{ "js",		"application/javascript" },

		{ "gif",	"image/gif" },
		{ "jpg",	"image/jpeg" },
		{ "jpeg",	"image/jpeg" },
		{ "png",	"image/png" },

		{ "css", 	"text/css" },
		{ "html", 	"text/html" },
		{ "txt",	"text/plain" },
		{ "xml", 	"text/xml" },

		{ "gz",		"application/gzip" }
	};
}
<|endoftext|>