<commit_before>/*
 *  Copyright 2010-2011 Fabric Technologies Inc. All rights reserved.
 */

#include <Fabric/EDK/EDK.h>

using namespace Fabric::EDK;
IMPLEMENT_FABRIC_EDK_ENTRIES

#include <stdint.h>

#ifdef _WIN32
  #ifndef INT64_C
    #define INT64_C(c) (c ## LL)
    #define UINT64_C(c) (c ## ULL)
  #endif
#endif

extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}

class videoStream;

const float cFrameSkipTolerance = 0.005f;

struct videoHandle
{
  videoStream * pointer;
  KL::Size width;
  KL::Size height;
  KL::Scalar duration;
  KL::Scalar fps;
  KL::Scalar time;
};

class videoStream
{
private:
  static bool sRegistered;
  AVFormatContext * mFormatCtx;
  AVCodecContext * mCodecCtx;
  int mVideoStreamID;
  AVCodec * mCodec;
  AVFrame * mFrameYUV;
  AVFrame * mFrameRGB;
  uint8_t * mBuffer;
  SwsContext * mConvertCtx;
  videoHandle * mHandle;

public:

  videoStream(videoHandle * in_Handle)
  {
    mHandle = in_Handle;

    if(!sRegistered)
    {
      av_register_all();
      sRegistered = true;
    }

    mFormatCtx = NULL;
    mCodecCtx = NULL;
    mVideoStreamID = -1;
    mCodec = NULL;
    mFrameYUV = NULL;
    mFrameRGB = NULL;
    mBuffer = NULL;
    mConvertCtx = NULL;
  }

  ~videoStream()
  {
    av_free(mBuffer);
    av_free(mFrameRGB);
    av_free(mFrameYUV);
    avcodec_close(mCodecCtx);
    av_close_input_file(mFormatCtx);
  }

  KL::Size getWidth()
  {
    return mCodecCtx ? mCodecCtx->width : 0;
  }

  KL::Size getHeight()
  {
    return mCodecCtx ? mCodecCtx->height : 0;
  }

  KL::Scalar getDuration()
  {
    if(!mFormatCtx)
      return 0;
    return KL::Scalar(mFormatCtx->duration) / KL::Scalar(AV_TIME_BASE);
  }

  KL::Scalar getFPS()
  {
    return KL::Scalar(mFormatCtx->streams[mVideoStreamID]->r_frame_rate.num) / KL::Scalar(mFormatCtx->streams[mVideoStreamID]->r_frame_rate.den);
  }

  KL::Scalar getTime()
  {
    return mHandle->time;
  }

  bool init(KL::String & filename)
  {
    if(filename.data()== NULL){
      printf("=======> VIDEO-ERROR: No filename specified.......\n");
      return false;
    }

    // open video file
    if(av_open_input_file(&mFormatCtx, filename.data(), NULL, 0, NULL)!=0)
    {
      printf("=======> VIDEO-ERROR: Cannot open video file '%s'.\n",filename.data());
      return false;
    }

    // retrieve stream information
    if(av_find_stream_info(mFormatCtx)<0)
    {
      printf("=======> VIDEO-ERROR: Cannot read stream information in '%s'.\n",filename.data());
      return false;
    }

    // find the first video stream
    for(int i=0; i<int(mFormatCtx->nb_streams); i++)
    {
      if(mFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)
      {
        mVideoStreamID=i;
        break;
      }
    }
    if(mVideoStreamID==-1)
    {
      printf("=======> VIDEO-ERROR: Didn't find a video stream in '%s'.\n",filename.data());
      return false;
    }

    // get a pointer to the codec context for the video stream
    mCodecCtx = mFormatCtx->streams[mVideoStreamID]->codec;

    // find the decoder for the video stream
    mCodec = avcodec_find_decoder(mCodecCtx->codec_id);
    if(mCodec==NULL)
    {
      printf("=======> VIDEO-ERROR: Unsupported codec in '%s'.\n",filename.data());
      return false;
    }

    // open codec
    if(avcodec_open(mCodecCtx, mCodec)<0)
    {
      printf("=======> VIDEO-ERROR: Could not open (supported) codec for '%s'.\n",filename.data());
      return false;
    }

    // allocate video frame (for YUV and RGB)
    mFrameYUV = avcodec_alloc_frame();
    mFrameRGB = avcodec_alloc_frame();

    // determine required buffer size and allocate buffer
    int numBytes = avpicture_get_size( PIX_FMT_RGB24, getWidth(),getHeight());
    mBuffer = (uint8_t *)av_malloc(numBytes*sizeof(uint8_t));

    // check if we received the memory
    if(!mFrameRGB || !mFrameYUV || !mBuffer)
    {
      printf("=======> VIDEO-ERROR: Couldn't allocate buffer in '%s'.\n",filename.data());
      return false;
    }

    // connect the picture frame with the buffer
    avpicture_fill((AVPicture *)mFrameRGB, mBuffer, PIX_FMT_RGB24, getWidth(), getHeight());

    // init the handle's values
    mHandle->time = -10000.0;
    mHandle->width = getWidth();
    mHandle->height = getHeight();
    mHandle->duration = getDuration();
    mHandle->fps = getFPS();

    return true;
  }

  bool readNextFrame(KL::Boolean &loop)
  {
    AVPacket packet;
    int frameFinished = 0;
    bool result = false;
    while(av_read_frame(mFormatCtx, &packet)>=0)
    {
      // is this a packet from the video stream?
      if(packet.stream_index == mVideoStreamID)
      {
        // decode video frame
        avcodec_decode_video2(mCodecCtx, mFrameYUV, &frameFinished, &packet);

        // did we get a complete video frame?
        if(frameFinished != 0)
        {
          // let's see if we need to create a conversion context
          if(!mConvertCtx)
          {
            mConvertCtx = sws_getContext(getWidth(), getHeight(), mCodecCtx->pix_fmt, getWidth(), getHeight(), PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
            if(!mConvertCtx)
            {
              printf("=======> VIDEO-ERROR: Could not create sws_conversion object.\n");
              return false;
            }
          }

          // convert the image from its native format to RGB
          sws_scale(mConvertCtx, mFrameYUV->data, mFrameYUV->linesize, 0, getHeight(), mFrameRGB->data, mFrameRGB->linesize);
          result = true;
          break;
        }
      }

      // Free the packet that was allocated by av_read_frame
      av_free_packet(&packet);
    }

    // if we didn't find a frame (we are at the end)
    if(!result && loop)
      av_seek_frame(mFormatCtx,mVideoStreamID,0,0);
    else
      mHandle->time += 1.0 / getFPS();

    return result;
  }

  bool seekTime(KL::Scalar &time)
  {
    KL::Boolean loop = false;

    if(fabs(time - mHandle->time) < cFrameSkipTolerance)
      return true;

    if(fabs(time - mHandle->time) > 1.0 / getFPS() + cFrameSkipTolerance)
    {
      if(fabs(time - mHandle->time) < 2.0 / getFPS() + cFrameSkipTolerance)
      {
        readNextFrame(loop);
      }
      else
      {
        int64_t frame = (int64_t)(0.5 * (time - 1.0 / getFPS()) * KL::Scalar(mCodecCtx->time_base.den) / KL::Scalar(mCodecCtx->time_base.num));
        av_seek_frame(mFormatCtx,mVideoStreamID,frame,0);
        mHandle->time = time - 1.0 / getFPS();
      }
    }

    return readNextFrame(loop);
  }

  bool getAllPixels(KL::VariableArray<KL::RGB> &pixels)
  {
    pixels.resize(getHeight() * getWidth());
    memcpy(&pixels[0],mFrameRGB->data[0],sizeof(pixels[0]) * getHeight() * getWidth());
    return true;
  }

};
bool videoStream::sRegistered = false;

FABRIC_EXT_EXPORT void FabricVIDEOOpenFileName(
  KL::String filename,
  videoHandle &handle
)
{
  if(handle.pointer == NULL)
  {
    // init the stream
    handle.pointer = new videoStream(&handle);
    if(!handle.pointer){
      printf("=======> VIDEO-ERROR: Could not create videoStream object.\n");
      handle.pointer = NULL;
      return;
    }
    if(!handle.pointer->init(filename))
    {
      delete(handle.pointer);
      handle.pointer = NULL;
      return;
    }
  }
}

FABRIC_EXT_EXPORT void FabricVIDEOOpenResource(
  KL::Data resourceData,
  KL::Size resourceDataSize,
  videoHandle &handle
)
{
  if(handle.pointer == NULL && resourceData != NULL && resourceDataSize > 0)
  {
#if defined(FABRIC_OS_WINDOWS)
    char const *dir = getenv("APPDATA");
    if(dir == NULL)
      dir = getenv("TEMP");
    if(dir == NULL)
      dir = getenv("TMP");
    if(dir == NULL)
      Fabric::EDK::throwException("Alembic extension: environment variable APP_DATA or TMP or TEMP is undefined");
    KL::String fileName( _tempnam( dir, "tmpfab_" ) );
#else
    KL::String fileName(tmpnam(NULL));
#endif

    // save the file to disk
    FILE * file = fopen(fileName.data(),"wb");
    fwrite(resourceData,resourceDataSize,1,file);
    fclose(file);
    file = NULL;

    return FabricVIDEOOpenFileName(fileName,handle);
  }
}

FABRIC_EXT_EXPORT void FabricVIDEOSeekTime(
  videoHandle & handle,
  KL::Scalar &time
)
{
  if(handle.pointer == NULL)
    return;
  handle.pointer->seekTime(time);
}

FABRIC_EXT_EXPORT void FabricVIDEOGetAllPixels(
  videoHandle & handle,
  KL::VariableArray<KL::RGB> &pixels
)
{
  if(handle.pointer == NULL)
    return;
  handle.pointer->getAllPixels(pixels);
}

FABRIC_EXT_EXPORT void FabricVIDEOFreeHandle(
  videoHandle &handle
)
{
  if(handle.pointer != NULL) {
    delete(handle.pointer);
    handle.pointer = NULL;
  }
}
<commit_msg>Windows: Video: Final fixes<commit_after>/*
 *  Copyright 2010-2011 Fabric Technologies Inc. All rights reserved.
 */

#include <Fabric/EDK/EDK.h>

using namespace Fabric::EDK;
IMPLEMENT_FABRIC_EDK_ENTRIES

#include <stdint.h>

#ifdef _WIN32
  #ifndef INT64_C
    #define INT64_C(c) (c ## LL)
    #define UINT64_C(c) (c ## ULL)
  #endif
#endif

extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}

class videoStream;

const float cFrameSkipTolerance = 0.005f;

struct videoHandle
{
  videoStream * pointer;
  KL::Size width;
  KL::Size height;
  KL::Scalar duration;
  KL::Scalar fps;
  KL::Scalar time;
};

class videoStream
{
private:
  static bool sRegistered;
  AVFormatContext * mFormatCtx;
  AVCodecContext * mCodecCtx;
  int mVideoStreamID;
  AVCodec * mCodec;
  AVFrame * mFrameYUV;
  AVFrame * mFrameRGB;
  uint8_t * mBuffer;
  SwsContext * mConvertCtx;
  videoHandle * mHandle;

public:

  videoStream(videoHandle * in_Handle)
  {
    mHandle = in_Handle;

    if(!sRegistered)
    {
      av_register_all();
      sRegistered = true;
    }

    mFormatCtx = NULL;
    mCodecCtx = NULL;
    mVideoStreamID = -1;
    mCodec = NULL;
    mFrameYUV = NULL;
    mFrameRGB = NULL;
    mBuffer = NULL;
    mConvertCtx = NULL;
  }

  ~videoStream()
  {
    av_free(mBuffer);
    av_free(mFrameRGB);
    av_free(mFrameYUV);
    avcodec_close(mCodecCtx);
    av_close_input_file(mFormatCtx);
  }

  KL::Size getWidth()
  {
    return mCodecCtx ? mCodecCtx->width : 0;
  }

  KL::Size getHeight()
  {
    return mCodecCtx ? mCodecCtx->height : 0;
  }

  KL::Scalar getDuration()
  {
    if(!mFormatCtx)
      return 0;
    return KL::Scalar(mFormatCtx->duration) / KL::Scalar(AV_TIME_BASE);
  }

  KL::Scalar getFPS()
  {
    return KL::Scalar(mFormatCtx->streams[mVideoStreamID]->r_frame_rate.num) / KL::Scalar(mFormatCtx->streams[mVideoStreamID]->r_frame_rate.den);
  }

  KL::Scalar getTime()
  {
    return mHandle->time;
  }

  bool init(KL::String & filename)
  {
    if(filename.data()== NULL){
      printf("=======> VIDEO-ERROR: No filename specified.......\n");
      return false;
    }

    // open video file
    if(av_open_input_file(&mFormatCtx, filename.data(), NULL, 0, NULL)!=0)
    {
      printf("=======> VIDEO-ERROR: Cannot open video file '%s'.\n",filename.data());
      return false;
    }

    // retrieve stream information
    if(av_find_stream_info(mFormatCtx)<0)
    {
      printf("=======> VIDEO-ERROR: Cannot read stream information in '%s'.\n",filename.data());
      return false;
    }

    // find the first video stream
    for(int i=0; i<int(mFormatCtx->nb_streams); i++)
    {
      if(mFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)
      {
        mVideoStreamID=i;
        break;
      }
    }
    if(mVideoStreamID==-1)
    {
      printf("=======> VIDEO-ERROR: Didn't find a video stream in '%s'.\n",filename.data());
      return false;
    }

    // get a pointer to the codec context for the video stream
    mCodecCtx = mFormatCtx->streams[mVideoStreamID]->codec;

    // find the decoder for the video stream
    mCodec = avcodec_find_decoder(mCodecCtx->codec_id);
    if(mCodec==NULL)
    {
      printf("=======> VIDEO-ERROR: Unsupported codec in '%s'.\n",filename.data());
      return false;
    }

    // open codec
    if(avcodec_open(mCodecCtx, mCodec)<0)
    {
      printf("=======> VIDEO-ERROR: Could not open (supported) codec for '%s'.\n",filename.data());
      return false;
    }

    // allocate video frame (for YUV and RGB)
    mFrameYUV = avcodec_alloc_frame();
    mFrameRGB = avcodec_alloc_frame();

    // determine required buffer size and allocate buffer
    int numBytes = avpicture_get_size( PIX_FMT_RGB24, getWidth(),getHeight());
    mBuffer = (uint8_t *)av_malloc(numBytes*sizeof(uint8_t));

    // check if we received the memory
    if(!mFrameRGB || !mFrameYUV || !mBuffer)
    {
      printf("=======> VIDEO-ERROR: Couldn't allocate buffer in '%s'.\n",filename.data());
      return false;
    }

    // connect the picture frame with the buffer
    avpicture_fill((AVPicture *)mFrameRGB, mBuffer, PIX_FMT_RGB24, getWidth(), getHeight());

    // init the handle's values
    mHandle->time = -10000.0;
    mHandle->width = getWidth();
    mHandle->height = getHeight();
    mHandle->duration = getDuration();
    mHandle->fps = getFPS();

    return true;
  }

  bool readNextFrame(KL::Boolean &loop)
  {
    AVPacket packet;
    av_init_packet(&packet);
    int frameFinished = 0;
    bool result = false;
    while(av_read_frame(mFormatCtx, &packet)>=0)
    {
      // is this a packet from the video stream?
      if(packet.stream_index == mVideoStreamID)
      {
        // decode video frame
        avcodec_decode_video2(mCodecCtx, mFrameYUV, &frameFinished, &packet);

        // did we get a complete video frame?
        if(frameFinished != 0)
        {
          // let's see if we need to create a conversion context
          if(!mConvertCtx)
          {
            mConvertCtx = sws_getContext(getWidth(), getHeight(), mCodecCtx->pix_fmt, getWidth(), getHeight(), PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
            if(!mConvertCtx)
            {
              printf("=======> VIDEO-ERROR: Could not create sws_conversion object.\n");
              return false;
            }
          }

          // convert the image from its native format to RGB
          sws_scale(mConvertCtx, mFrameYUV->data, mFrameYUV->linesize, 0, getHeight(), mFrameRGB->data, mFrameRGB->linesize);
          result = true;
          break;
        }
      }

      // Free the packet that was allocated by av_read_frame
      av_free_packet(&packet);
    }

    // if we didn't find a frame (we are at the end)
    if(!result && loop)
      av_seek_frame(mFormatCtx,mVideoStreamID,0,0);
    else
      mHandle->time += 1.0 / getFPS();

    return result;
  }

  bool seekTime(KL::Scalar &time)
  {
    KL::Boolean loop = false;

    if(fabs(time - mHandle->time) < cFrameSkipTolerance)
      return true;

    if(fabs(time - mHandle->time) > 1.0 / getFPS() + cFrameSkipTolerance)
    {
      if(fabs(time - mHandle->time) < 2.0 / getFPS() + cFrameSkipTolerance)
      {
        readNextFrame(loop);
      }
      else
      {
        int64_t frame = (int64_t)(0.5 * (time - 1.0 / getFPS()) * KL::Scalar(mCodecCtx->time_base.den) / KL::Scalar(mCodecCtx->time_base.num));
        av_seek_frame(mFormatCtx,mVideoStreamID,frame,0);
        mHandle->time = time - 1.0 / getFPS();
      }
    }

    return readNextFrame(loop);
  }

  bool getAllPixels(KL::VariableArray<KL::RGB> &pixels)
  {
    mHandle->width = getWidth();
    mHandle->height = getHeight();
    pixels.resize(getHeight() * getWidth());
    memcpy(&pixels[0],mFrameRGB->data[0],sizeof(KL::RGB) * getHeight() * getWidth());
    return true;
  }

};
bool videoStream::sRegistered = false;

FABRIC_EXT_EXPORT void FabricVIDEOOpenFileName(
  KL::String filename,
  videoHandle &handle
)
{
  if(handle.pointer == NULL)
  {
    // init the stream
    handle.pointer = new videoStream(&handle);
    if(!handle.pointer){
      printf("=======> VIDEO-ERROR: Could not create videoStream object.\n");
      handle.pointer = NULL;
      return;
    }
    if(!handle.pointer->init(filename))
    {
      delete(handle.pointer);
      handle.pointer = NULL;
      return;
    }
  }
}

FABRIC_EXT_EXPORT void FabricVIDEOOpenResource(
  KL::Data resourceData,
  KL::Size resourceDataSize,
  videoHandle &handle
)
{
  if(handle.pointer == NULL && resourceData != NULL && resourceDataSize > 0)
  {
#if defined(FABRIC_OS_WINDOWS)
    char const *dir = getenv("APPDATA");
    if(dir == NULL)
      dir = getenv("TEMP");
    if(dir == NULL)
      dir = getenv("TMP");
    if(dir == NULL)
      Fabric::EDK::throwException("Alembic extension: environment variable APP_DATA or TMP or TEMP is undefined");
    KL::String fileName( _tempnam( dir, "tmpfab_" ) );
#else
    KL::String fileName(tmpnam(NULL));
#endif

    // save the file to disk
    FILE * file = fopen(fileName.data(),"wb");
    fwrite(resourceData,resourceDataSize,1,file);
    fclose(file);
    file = NULL;

    return FabricVIDEOOpenFileName(fileName,handle);
  }
}

FABRIC_EXT_EXPORT void FabricVIDEOSeekTime(
  videoHandle & handle,
  KL::Scalar &time
)
{
  if(handle.pointer == NULL)
    return;
  handle.pointer->seekTime(time);
}

FABRIC_EXT_EXPORT void FabricVIDEOGetAllPixels(
  videoHandle & handle,
  KL::VariableArray<KL::RGB> &pixels
)
{
  if(handle.pointer == NULL)
    return;
  handle.pointer->getAllPixels(pixels);
}

FABRIC_EXT_EXPORT void FabricVIDEOFreeHandle(
  videoHandle &handle
)
{
  if(handle.pointer != NULL) {
    delete(handle.pointer);
    handle.pointer = NULL;
  }
}
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Modified by Cloudius Systems.
 * Copyright 2015 Cloudius Systems.
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "gms/failure_detector.hh"
#include "gms/gossiper.hh"
#include "gms/i_failure_detector.hh"
#include "gms/i_failure_detection_event_listener.hh"
#include "gms/endpoint_state.hh"
#include "gms/application_state.hh"
#include "gms/inet_address.hh"
#include <iostream>
#include <chrono>

namespace gms {

extern logging::logger logger;

using clk = arrival_window::clk;

static clk::duration get_initial_value() {
#if 0
    String newvalue = System.getProperty("cassandra.fd_initial_value_ms");
    if (newvalue == null)
    {
        return Gossiper.intervalInMillis * 2;
    }
    else
    {
        logger.info("Overriding FD INITIAL_VALUE to {}ms", newvalue);
        return Integer.parseInt(newvalue);
    }
#endif
    warn(unimplemented::cause::GOSSIP);
    return std::chrono::seconds(2);
}

clk::duration arrival_window::get_max_interval() {
#if 0
    sstring newvalue = System.getProperty("cassandra.fd_max_interval_ms");
    if (newvalue == null)
    {
        return failure_detector.INITIAL_VALUE_NANOS;
    }
    else
    {
        logger.info("Overriding FD MAX_INTERVAL to {}ms", newvalue);
        return TimeUnit.NANOSECONDS.convert(Integer.parseInt(newvalue), TimeUnit.MILLISECONDS);
    }
#endif
    warn(unimplemented::cause::GOSSIP);
    return get_initial_value();
}

void arrival_window::add(clk::time_point value) {
    if (_tlast > clk::time_point::min()) {
        auto inter_arrival_time = value - _tlast;
        if (inter_arrival_time <= get_max_interval()) {
            _arrival_intervals.add(inter_arrival_time.count());
        } else  {
            logger.debug("failure_detector: Ignoring interval time of {}", inter_arrival_time.count());
        }
    } else {
        // We use a very large initial interval since the "right" average depends on the cluster size
        // and it's better to err high (false negatives, which will be corrected by waiting a bit longer)
        // than low (false positives, which cause "flapping").
        _arrival_intervals.add(get_initial_value().count());
    }
    _tlast = value;
}

double arrival_window::mean() {
    return _arrival_intervals.mean();
}

double arrival_window::phi(clk::time_point tnow) {
    assert(_arrival_intervals.size() > 0 && _tlast > clk::time_point::min()); // should not be called before any samples arrive
    auto t = (tnow - _tlast).count();
    auto m = mean();
    double phi = t / m;
    logger.debug("failure_detector: now={}, tlast={}, t={}, mean={}, phi={}",
        tnow.time_since_epoch().count(), _tlast.time_since_epoch().count(), t, m, phi);
    return phi;
}

std::ostream& operator<<(std::ostream& os, const arrival_window& w) {
    for (auto& x : w._arrival_intervals.deque()) {
        os << x << " ";
    }
    return os;
}

sstring failure_detector::get_all_endpoint_states() {
    std::stringstream ss;
    for (auto& entry : get_local_gossiper().endpoint_state_map) {
        auto& ep = entry.first;
        auto& state = entry.second;
        ss << ep << "\n";
        append_endpoint_state(ss, state);
    }
    return sstring(ss.str());
}

std::map<sstring, sstring> failure_detector::get_simple_states() {
    std::map<sstring, sstring> nodes_status;
    for (auto& entry : get_local_gossiper().endpoint_state_map) {
        auto& ep = entry.first;
        auto& state = entry.second;
        std::stringstream ss;
        ss << ep;
        if (state.is_alive())
            nodes_status.emplace(sstring(ss.str()), "UP");
        else
            nodes_status.emplace(sstring(ss.str()), "DOWN");
    }
    return nodes_status;
}

int failure_detector::get_down_endpoint_count() {
    int count = 0;
    for (auto& entry : get_local_gossiper().endpoint_state_map) {
        auto& state = entry.second;
        if (!state.is_alive()) {
            count++;
        }
    }
    return count;
}

int failure_detector::get_up_endpoint_count() {
    int count = 0;
    for (auto& entry : get_local_gossiper().endpoint_state_map) {
        auto& state = entry.second;
        if (state.is_alive()) {
            count++;
        }
    }
    return count;
}

sstring failure_detector::get_endpoint_state(sstring address) {
    std::stringstream ss;
    auto eps = get_local_gossiper().get_endpoint_state_for_endpoint(inet_address(address));
    if (eps) {
        append_endpoint_state(ss, *eps);
        return sstring(ss.str());
    } else {
        return sstring("unknown endpoint ") + address;
    }
}

void failure_detector::append_endpoint_state(std::stringstream& ss, endpoint_state& state) {
    ss << "  generation:" << state.get_heart_beat_state().get_generation() << "\n";
    ss << "  heartbeat:" << state.get_heart_beat_state().get_heart_beat_version() << "\n";
    for (auto& entry : state.get_application_state_map()) {
        auto& app_state = entry.first;
        auto& value = entry.second;
        if (app_state == application_state::TOKENS) {
            continue;
        }
        // FIXME: Add operator<< for application_state
        ss << "  " << int32_t(app_state) << ":" << value.value << "\n";
    }
}

void failure_detector::set_phi_convict_threshold(double phi) {
    // FIXME
    // DatabaseDescriptor.setPhiConvictThreshold(phi);
}

double failure_detector::get_phi_convict_threshold() {
    // FIXME: phi_convict_threshold must be between 5 and 16"
    // return DatabaseDescriptor.getPhiConvictThreshold();
    warn(unimplemented::cause::GOSSIP);
    return 8;
}

bool failure_detector::is_alive(inet_address ep) {
    return get_local_gossiper().is_alive(ep);
}

void failure_detector::report(inet_address ep) {
    logger.trace("failure_detector: reporting {}", ep);
    auto now = clk::now();
    auto it = _arrival_samples.find(ep);
    if (it == _arrival_samples.end()) {
        // avoid adding an empty ArrivalWindow to the Map
        auto heartbeat_window = arrival_window(SAMPLE_SIZE);
        heartbeat_window.add(now);
        _arrival_samples.emplace(ep, heartbeat_window);
    } else {
        it->second.add(now);
    }
}

// Runs inside seastar::async context
void failure_detector::interpret(inet_address ep) {
    auto it = _arrival_samples.find(ep);
    if (it == _arrival_samples.end()) {
        return;
    }
    arrival_window& hb_wnd = it->second;
    auto now = clk::now();
    double phi = hb_wnd.phi(now);
    logger.trace("failure_detector: PHI for {} : {}", ep, phi);

    if (PHI_FACTOR * phi > get_phi_convict_threshold()) {
        logger.trace("failure_detector: notifying listeners that {} is down", ep);
        logger.trace("failure_detector: intervals: {} mean: {}", hb_wnd, hb_wnd.mean());
        for (auto& listener : _fd_evnt_listeners) {
            logger.debug("failure_detector: convict ep={} phi={}", ep, phi);
            listener->convict(ep, phi);
        }
    }
}

// Runs inside seastar::async context
void failure_detector::force_conviction(inet_address ep) {
    logger.debug("failure_detector: Forcing conviction of {}", ep);
    for (auto& listener : _fd_evnt_listeners) {
        listener->convict(ep, get_phi_convict_threshold());
    }
}

void failure_detector::remove(inet_address ep) {
    _arrival_samples.erase(ep);
}

void failure_detector::register_failure_detection_event_listener(i_failure_detection_event_listener* listener) {
    _fd_evnt_listeners.push_back(std::move(listener));
}

void failure_detector::unregister_failure_detection_event_listener(i_failure_detection_event_listener* listener) {
    _fd_evnt_listeners.remove(listener);
}

std::ostream& operator<<(std::ostream& os, const failure_detector& x) {
    os << "----------- failure_detector:    -----------\n";
    for (auto& entry : x._arrival_samples) {
        const inet_address& ep = entry.first;
        const arrival_window& win = entry.second;
        os << ep << " : "  << win << "\n";
    }
    return os;
}

distributed<failure_detector> _the_failure_detector;

} // namespace gms
<commit_msg>failure_detector: Remove debug print in operator<<<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Modified by Cloudius Systems.
 * Copyright 2015 Cloudius Systems.
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "gms/failure_detector.hh"
#include "gms/gossiper.hh"
#include "gms/i_failure_detector.hh"
#include "gms/i_failure_detection_event_listener.hh"
#include "gms/endpoint_state.hh"
#include "gms/application_state.hh"
#include "gms/inet_address.hh"
#include <iostream>
#include <chrono>

namespace gms {

extern logging::logger logger;

using clk = arrival_window::clk;

static clk::duration get_initial_value() {
#if 0
    String newvalue = System.getProperty("cassandra.fd_initial_value_ms");
    if (newvalue == null)
    {
        return Gossiper.intervalInMillis * 2;
    }
    else
    {
        logger.info("Overriding FD INITIAL_VALUE to {}ms", newvalue);
        return Integer.parseInt(newvalue);
    }
#endif
    warn(unimplemented::cause::GOSSIP);
    return std::chrono::seconds(2);
}

clk::duration arrival_window::get_max_interval() {
#if 0
    sstring newvalue = System.getProperty("cassandra.fd_max_interval_ms");
    if (newvalue == null)
    {
        return failure_detector.INITIAL_VALUE_NANOS;
    }
    else
    {
        logger.info("Overriding FD MAX_INTERVAL to {}ms", newvalue);
        return TimeUnit.NANOSECONDS.convert(Integer.parseInt(newvalue), TimeUnit.MILLISECONDS);
    }
#endif
    warn(unimplemented::cause::GOSSIP);
    return get_initial_value();
}

void arrival_window::add(clk::time_point value) {
    if (_tlast > clk::time_point::min()) {
        auto inter_arrival_time = value - _tlast;
        if (inter_arrival_time <= get_max_interval()) {
            _arrival_intervals.add(inter_arrival_time.count());
        } else  {
            logger.debug("failure_detector: Ignoring interval time of {}", inter_arrival_time.count());
        }
    } else {
        // We use a very large initial interval since the "right" average depends on the cluster size
        // and it's better to err high (false negatives, which will be corrected by waiting a bit longer)
        // than low (false positives, which cause "flapping").
        _arrival_intervals.add(get_initial_value().count());
    }
    _tlast = value;
}

double arrival_window::mean() {
    return _arrival_intervals.mean();
}

double arrival_window::phi(clk::time_point tnow) {
    assert(_arrival_intervals.size() > 0 && _tlast > clk::time_point::min()); // should not be called before any samples arrive
    auto t = (tnow - _tlast).count();
    auto m = mean();
    double phi = t / m;
    logger.debug("failure_detector: now={}, tlast={}, t={}, mean={}, phi={}",
        tnow.time_since_epoch().count(), _tlast.time_since_epoch().count(), t, m, phi);
    return phi;
}

std::ostream& operator<<(std::ostream& os, const arrival_window& w) {
    for (auto& x : w._arrival_intervals.deque()) {
        os << x << " ";
    }
    return os;
}

sstring failure_detector::get_all_endpoint_states() {
    std::stringstream ss;
    for (auto& entry : get_local_gossiper().endpoint_state_map) {
        auto& ep = entry.first;
        auto& state = entry.second;
        ss << ep << "\n";
        append_endpoint_state(ss, state);
    }
    return sstring(ss.str());
}

std::map<sstring, sstring> failure_detector::get_simple_states() {
    std::map<sstring, sstring> nodes_status;
    for (auto& entry : get_local_gossiper().endpoint_state_map) {
        auto& ep = entry.first;
        auto& state = entry.second;
        std::stringstream ss;
        ss << ep;
        if (state.is_alive())
            nodes_status.emplace(sstring(ss.str()), "UP");
        else
            nodes_status.emplace(sstring(ss.str()), "DOWN");
    }
    return nodes_status;
}

int failure_detector::get_down_endpoint_count() {
    int count = 0;
    for (auto& entry : get_local_gossiper().endpoint_state_map) {
        auto& state = entry.second;
        if (!state.is_alive()) {
            count++;
        }
    }
    return count;
}

int failure_detector::get_up_endpoint_count() {
    int count = 0;
    for (auto& entry : get_local_gossiper().endpoint_state_map) {
        auto& state = entry.second;
        if (state.is_alive()) {
            count++;
        }
    }
    return count;
}

sstring failure_detector::get_endpoint_state(sstring address) {
    std::stringstream ss;
    auto eps = get_local_gossiper().get_endpoint_state_for_endpoint(inet_address(address));
    if (eps) {
        append_endpoint_state(ss, *eps);
        return sstring(ss.str());
    } else {
        return sstring("unknown endpoint ") + address;
    }
}

void failure_detector::append_endpoint_state(std::stringstream& ss, endpoint_state& state) {
    ss << "  generation:" << state.get_heart_beat_state().get_generation() << "\n";
    ss << "  heartbeat:" << state.get_heart_beat_state().get_heart_beat_version() << "\n";
    for (auto& entry : state.get_application_state_map()) {
        auto& app_state = entry.first;
        auto& value = entry.second;
        if (app_state == application_state::TOKENS) {
            continue;
        }
        // FIXME: Add operator<< for application_state
        ss << "  " << int32_t(app_state) << ":" << value.value << "\n";
    }
}

void failure_detector::set_phi_convict_threshold(double phi) {
    // FIXME
    // DatabaseDescriptor.setPhiConvictThreshold(phi);
}

double failure_detector::get_phi_convict_threshold() {
    // FIXME: phi_convict_threshold must be between 5 and 16"
    // return DatabaseDescriptor.getPhiConvictThreshold();
    warn(unimplemented::cause::GOSSIP);
    return 8;
}

bool failure_detector::is_alive(inet_address ep) {
    return get_local_gossiper().is_alive(ep);
}

void failure_detector::report(inet_address ep) {
    logger.trace("failure_detector: reporting {}", ep);
    auto now = clk::now();
    auto it = _arrival_samples.find(ep);
    if (it == _arrival_samples.end()) {
        // avoid adding an empty ArrivalWindow to the Map
        auto heartbeat_window = arrival_window(SAMPLE_SIZE);
        heartbeat_window.add(now);
        _arrival_samples.emplace(ep, heartbeat_window);
    } else {
        it->second.add(now);
    }
}

// Runs inside seastar::async context
void failure_detector::interpret(inet_address ep) {
    auto it = _arrival_samples.find(ep);
    if (it == _arrival_samples.end()) {
        return;
    }
    arrival_window& hb_wnd = it->second;
    auto now = clk::now();
    double phi = hb_wnd.phi(now);
    logger.trace("failure_detector: PHI for {} : {}", ep, phi);

    if (PHI_FACTOR * phi > get_phi_convict_threshold()) {
        logger.trace("failure_detector: notifying listeners that {} is down", ep);
        logger.trace("failure_detector: intervals: {} mean: {}", hb_wnd, hb_wnd.mean());
        for (auto& listener : _fd_evnt_listeners) {
            logger.debug("failure_detector: convict ep={} phi={}", ep, phi);
            listener->convict(ep, phi);
        }
    }
}

// Runs inside seastar::async context
void failure_detector::force_conviction(inet_address ep) {
    logger.debug("failure_detector: Forcing conviction of {}", ep);
    for (auto& listener : _fd_evnt_listeners) {
        listener->convict(ep, get_phi_convict_threshold());
    }
}

void failure_detector::remove(inet_address ep) {
    _arrival_samples.erase(ep);
}

void failure_detector::register_failure_detection_event_listener(i_failure_detection_event_listener* listener) {
    _fd_evnt_listeners.push_back(std::move(listener));
}

void failure_detector::unregister_failure_detection_event_listener(i_failure_detection_event_listener* listener) {
    _fd_evnt_listeners.remove(listener);
}

std::ostream& operator<<(std::ostream& os, const failure_detector& x) {
    for (auto& entry : x._arrival_samples) {
        const inet_address& ep = entry.first;
        const arrival_window& win = entry.second;
        os << ep << " : "  << win << "\n";
    }
    return os;
}

distributed<failure_detector> _the_failure_detector;

} // namespace gms
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#ifndef INCLUDED_SW_INC_NDGRF_HXX
#define INCLUDED_SW_INC_NDGRF_HXX
#include <sfx2/lnkbase.hxx>
#include <svtools/grfmgr.hxx>
#include <ndnotxt.hxx>
#include <com/sun/star/embed/XStorage.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
class SwAsyncRetrieveInputStreamThreadConsumer;

class SwGrfFmtColl;
class SwDoc;
class GraphicAttr;
class SvStorage;

// SwGrfNode
class SW_DLLPUBLIC SwGrfNode: public SwNoTxtNode
{
    friend class SwNodes;

    GraphicObject maGrfObj;
    GraphicObject *mpReplacementGraphic;
    ::sfx2::SvBaseLinkRef refLink;       ///< If graphics only as link then pointer is set.
    Size nGrfSize;
    OUString aLowResGrf;                   ///< HTML: LowRes graphics (substitute until regular HighRes graphics is loaded).
    sal_Bool bTransparentFlagValid  :1;
    sal_Bool bInSwapIn              :1;

    sal_Bool bGraphicArrived        :1;
    sal_Bool bChgTwipSize           :1;
    sal_Bool bChgTwipSizeFromPixel  :1;
    sal_Bool bLoadLowResGrf         :1;
    sal_Bool bFrameInPaint          :1; ///< To avoid Start-/EndActions in Paint via SwapIn.
    sal_Bool bScaleImageMap         :1; ///< Scale image map in SetTwipSize.

    boost::shared_ptr< SwAsyncRetrieveInputStreamThreadConsumer > mpThreadConsumer;
    bool mbLinkedInputStreamReady;
    com::sun::star::uno::Reference<com::sun::star::io::XInputStream> mxInputStream;
    sal_Bool mbIsStreamReadOnly;

    SwGrfNode( const SwNodeIndex& rWhere,
               const OUString& rGrfName, const OUString& rFltName,
               const Graphic* pGraphic,
               SwGrfFmtColl* pGrfColl,
               SwAttrSet* pAutoAttr = 0 );
    ///< Ctor for reading (SW/G) without graphics.
    SwGrfNode( const SwNodeIndex& rWhere,
               const OUString& rGrfName, const OUString& rFltName,
               SwGrfFmtColl* pGrfColl,
               SwAttrSet* pAutoAttr = 0 );
    SwGrfNode( const SwNodeIndex& rWhere,
               const GraphicObject& rGrfObj,
               SwGrfFmtColl* pGrfColl,
               SwAttrSet* pAutoAttr = 0 );

    void InsertLink( const OUString& rGrfName, const OUString& rFltName );
    sal_Bool ImportGraphic( SvStream& rStrm );
    sal_Bool HasStreamName() const { return maGrfObj.HasUserData(); }
    /** adjust return type and rename method to
       indicate that its an private one. */

    void DelStreamName();
    DECL_LINK( SwapGraphic, GraphicObject* );

    /** helper method to determine stream for the embedded graphic.

        Important note: caller of this method has to handle the thrown exceptions
        Storage, which should contain the stream of the embedded graphic, is
        provided via parameter. Otherwise the returned stream will be closed
        after the method returns, because its parent stream is closed and deleted.
        Proposed name of embedded graphic stream is also provided by parameter.

        @author OD

        @param _refPics
        input parameter - reference to storage, which should contain the
        embedded graphic stream.

        @param rStrmName
        input parameter - proposed name of the embedded graphic stream.

        @return SvStream*
        new created stream of the embedded graphic, which has to be destroyed
        after its usage. Could be NULL, if the stream isn't found.
    */
    SvStream* _GetStreamForEmbedGrf(
            const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& _refPics,
            const OUString& rStreamName ) const;

    /** helper method to get a substorage of the document storage for readonly access.

        A substorage with the specified name will be opened readonly. If the provided
        name is empty the root storage will be returned.

        @param _aStgName
        input parameter - name of substorage. Can be empty.

        @return XStorage
        reference to substorage or the root storage
    */
    ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > _GetDocSubstorageOrRoot(
                                                const OUString& aStgName ) const;

public:
    virtual ~SwGrfNode();
    const Graphic&          GetGrf() const      { return maGrfObj.GetGraphic(); }
    const GraphicObject&    GetGrfObj() const   { return maGrfObj; }
    const GraphicObject* GetReplacementGrfObj() const;
    virtual SwCntntNode *SplitCntntNode( const SwPosition & );

    /// isolated only way to set GraphicObject to allow more actions when doing so
    void SetGraphic(const Graphic& rGraphic, const OUString& rLink);

    /// wrappers for non-const calls at GraphicObject
    void ReleaseGraphicFromCache() { maGrfObj.ReleaseFromCache(); }
    void StartGraphicAnimation(OutputDevice* pOut, const Point& rPt, const Size& rSz, long nExtraData = 0, const GraphicAttr* pAttr = NULL, sal_uLong nFlags = GRFMGR_DRAW_STANDARD, OutputDevice* pFirstFrameOutDev = NULL) { maGrfObj.StartAnimation(pOut, rPt, rSz, nExtraData, pAttr, nFlags, pFirstFrameOutDev); }
    void StopGraphicAnimation(OutputDevice* pOut = NULL, long nExtraData = 0) { maGrfObj.StopAnimation(pOut, nExtraData); }

    /// allow reaction on change of content of GraphicObject, so always call
    /// when GraphicObject content changes
    void onGraphicChanged();

    virtual Size GetTwipSize() const;
    void SetTwipSize( const Size& rSz );

    sal_Bool IsTransparent() const;

    inline sal_Bool IsAnimated() const              { return maGrfObj.IsAnimated(); }

    inline sal_Bool IsChgTwipSize() const           { return bChgTwipSize; }
    inline sal_Bool IsChgTwipSizeFromPixel() const  { return bChgTwipSizeFromPixel; }
    inline void SetChgTwipSize( sal_Bool b, sal_Bool bFromPx=sal_False )        { bChgTwipSize = b; bChgTwipSizeFromPixel = bFromPx; }

    inline sal_Bool IsGraphicArrived() const         { return bGraphicArrived; }
    inline void SetGraphicArrived( sal_Bool b )      { bGraphicArrived = b; }

    inline sal_Bool IsFrameInPaint() const          { return bFrameInPaint; }
    inline void SetFrameInPaint( sal_Bool b )       { bFrameInPaint = b; }

    inline sal_Bool IsScaleImageMap() const         { return bScaleImageMap; }
    inline void SetScaleImageMap( sal_Bool b )      { bScaleImageMap = b; }

    /// in ndcopy.cxx
    virtual SwCntntNode* MakeCopy( SwDoc*, const SwNodeIndex& ) const;

    /** Re-read in case graphic was not OK. The current one
       gets replaced by the new one. */
    sal_Bool ReRead( const OUString& rGrfName, const OUString& rFltName,
                 const Graphic* pGraphic = 0,
                 const GraphicObject* pGrfObj = 0,
                 sal_Bool bModify = sal_True );
    /// Loading of graphic immediately before displaying.
    short SwapIn( sal_Bool bWaitForData = sal_False );
    /// Remove graphic in order to free memory.
    short SwapOut();
    /// Access to storage stream-name.
    void SetStreamName( const OUString& r ) { maGrfObj.SetUserData( r ); }
    /// Is this node selected by any shell?
    sal_Bool IsSelected() const;

    /// Communicate to graphic that node is in Undo-range.
    virtual sal_Bool SavePersistentData();
    virtual sal_Bool RestorePersistentData();

    /// Query link-data.
    bool IsGrfLink() const                  { return refLink.Is(); }
    inline bool IsLinkedFile() const;
    inline bool IsLinkedDDE() const;
    ::sfx2::SvBaseLinkRef GetLink() const    { return refLink; }
    bool GetFileFilterNms( OUString* pFileNm, OUString* pFilterNm ) const;
    void ReleaseLink();

    /** Scale an image-map: the image-map becomes zoomed in / out by
       factor between graphic-size and border-size. */
    void ScaleImageMap();

    /// Returns the with our graphic attributes filled Graphic-Attr-Structure.
    GraphicAttr& GetGraphicAttr( GraphicAttr&, const SwFrm* pFrm ) const;

    boost::weak_ptr< SwAsyncRetrieveInputStreamThreadConsumer > GetThreadConsumer();
    bool IsLinkedInputStreamReady() const;
    void TriggerAsyncRetrieveInputStream();
    void ApplyInputStream(
        com::sun::star::uno::Reference<com::sun::star::io::XInputStream> xInputStream,
        const sal_Bool bIsStreamReadOnly );
    void UpdateLinkWithInputStream();
    bool IsAsyncRetrieveInputStreamPossible() const;
};

// Inline methods from Node.hxx - it is only now that we know TxtNode!!
inline       SwGrfNode   *SwNode::GetGrfNode()
{
     return ND_GRFNODE == nNodeType ? (SwGrfNode*)this : 0;
}

inline const SwGrfNode   *SwNode::GetGrfNode() const
{
     return ND_GRFNODE == nNodeType ? (const SwGrfNode*)this : 0;
}

inline bool SwGrfNode::IsLinkedFile() const
{
    return refLink.Is() && OBJECT_CLIENT_GRF == refLink->GetObjType();
}

inline bool SwGrfNode::IsLinkedDDE() const
{
    return refLink.Is() && OBJECT_CLIENT_DDE == refLink->GetObjType();
}

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>coverity#738885 unused member variable<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#ifndef INCLUDED_SW_INC_NDGRF_HXX
#define INCLUDED_SW_INC_NDGRF_HXX
#include <sfx2/lnkbase.hxx>
#include <svtools/grfmgr.hxx>
#include <ndnotxt.hxx>
#include <com/sun/star/embed/XStorage.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
class SwAsyncRetrieveInputStreamThreadConsumer;

class SwGrfFmtColl;
class SwDoc;
class GraphicAttr;
class SvStorage;

// SwGrfNode
class SW_DLLPUBLIC SwGrfNode: public SwNoTxtNode
{
    friend class SwNodes;

    GraphicObject maGrfObj;
    GraphicObject *mpReplacementGraphic;
    ::sfx2::SvBaseLinkRef refLink;       ///< If graphics only as link then pointer is set.
    Size nGrfSize;
    OUString aLowResGrf;                   ///< HTML: LowRes graphics (substitute until regular HighRes graphics is loaded).
    sal_Bool bInSwapIn              :1;

    sal_Bool bGraphicArrived        :1;
    sal_Bool bChgTwipSize           :1;
    sal_Bool bChgTwipSizeFromPixel  :1;
    sal_Bool bLoadLowResGrf         :1;
    sal_Bool bFrameInPaint          :1; ///< To avoid Start-/EndActions in Paint via SwapIn.
    sal_Bool bScaleImageMap         :1; ///< Scale image map in SetTwipSize.

    boost::shared_ptr< SwAsyncRetrieveInputStreamThreadConsumer > mpThreadConsumer;
    bool mbLinkedInputStreamReady;
    com::sun::star::uno::Reference<com::sun::star::io::XInputStream> mxInputStream;
    sal_Bool mbIsStreamReadOnly;

    SwGrfNode( const SwNodeIndex& rWhere,
               const OUString& rGrfName, const OUString& rFltName,
               const Graphic* pGraphic,
               SwGrfFmtColl* pGrfColl,
               SwAttrSet* pAutoAttr = 0 );
    ///< Ctor for reading (SW/G) without graphics.
    SwGrfNode( const SwNodeIndex& rWhere,
               const OUString& rGrfName, const OUString& rFltName,
               SwGrfFmtColl* pGrfColl,
               SwAttrSet* pAutoAttr = 0 );
    SwGrfNode( const SwNodeIndex& rWhere,
               const GraphicObject& rGrfObj,
               SwGrfFmtColl* pGrfColl,
               SwAttrSet* pAutoAttr = 0 );

    void InsertLink( const OUString& rGrfName, const OUString& rFltName );
    sal_Bool ImportGraphic( SvStream& rStrm );
    sal_Bool HasStreamName() const { return maGrfObj.HasUserData(); }
    /** adjust return type and rename method to
       indicate that its an private one. */

    void DelStreamName();
    DECL_LINK( SwapGraphic, GraphicObject* );

    /** helper method to determine stream for the embedded graphic.

        Important note: caller of this method has to handle the thrown exceptions
        Storage, which should contain the stream of the embedded graphic, is
        provided via parameter. Otherwise the returned stream will be closed
        after the method returns, because its parent stream is closed and deleted.
        Proposed name of embedded graphic stream is also provided by parameter.

        @author OD

        @param _refPics
        input parameter - reference to storage, which should contain the
        embedded graphic stream.

        @param rStrmName
        input parameter - proposed name of the embedded graphic stream.

        @return SvStream*
        new created stream of the embedded graphic, which has to be destroyed
        after its usage. Could be NULL, if the stream isn't found.
    */
    SvStream* _GetStreamForEmbedGrf(
            const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& _refPics,
            const OUString& rStreamName ) const;

    /** helper method to get a substorage of the document storage for readonly access.

        A substorage with the specified name will be opened readonly. If the provided
        name is empty the root storage will be returned.

        @param _aStgName
        input parameter - name of substorage. Can be empty.

        @return XStorage
        reference to substorage or the root storage
    */
    ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > _GetDocSubstorageOrRoot(
                                                const OUString& aStgName ) const;

public:
    virtual ~SwGrfNode();
    const Graphic&          GetGrf() const      { return maGrfObj.GetGraphic(); }
    const GraphicObject&    GetGrfObj() const   { return maGrfObj; }
    const GraphicObject* GetReplacementGrfObj() const;
    virtual SwCntntNode *SplitCntntNode( const SwPosition & );

    /// isolated only way to set GraphicObject to allow more actions when doing so
    void SetGraphic(const Graphic& rGraphic, const OUString& rLink);

    /// wrappers for non-const calls at GraphicObject
    void ReleaseGraphicFromCache() { maGrfObj.ReleaseFromCache(); }
    void StartGraphicAnimation(OutputDevice* pOut, const Point& rPt, const Size& rSz, long nExtraData = 0, const GraphicAttr* pAttr = NULL, sal_uLong nFlags = GRFMGR_DRAW_STANDARD, OutputDevice* pFirstFrameOutDev = NULL) { maGrfObj.StartAnimation(pOut, rPt, rSz, nExtraData, pAttr, nFlags, pFirstFrameOutDev); }
    void StopGraphicAnimation(OutputDevice* pOut = NULL, long nExtraData = 0) { maGrfObj.StopAnimation(pOut, nExtraData); }

    /// allow reaction on change of content of GraphicObject, so always call
    /// when GraphicObject content changes
    void onGraphicChanged();

    virtual Size GetTwipSize() const;
    void SetTwipSize( const Size& rSz );

    sal_Bool IsTransparent() const;

    inline sal_Bool IsAnimated() const              { return maGrfObj.IsAnimated(); }

    inline sal_Bool IsChgTwipSize() const           { return bChgTwipSize; }
    inline sal_Bool IsChgTwipSizeFromPixel() const  { return bChgTwipSizeFromPixel; }
    inline void SetChgTwipSize( sal_Bool b, sal_Bool bFromPx=sal_False )        { bChgTwipSize = b; bChgTwipSizeFromPixel = bFromPx; }

    inline sal_Bool IsGraphicArrived() const         { return bGraphicArrived; }
    inline void SetGraphicArrived( sal_Bool b )      { bGraphicArrived = b; }

    inline sal_Bool IsFrameInPaint() const          { return bFrameInPaint; }
    inline void SetFrameInPaint( sal_Bool b )       { bFrameInPaint = b; }

    inline sal_Bool IsScaleImageMap() const         { return bScaleImageMap; }
    inline void SetScaleImageMap( sal_Bool b )      { bScaleImageMap = b; }

    /// in ndcopy.cxx
    virtual SwCntntNode* MakeCopy( SwDoc*, const SwNodeIndex& ) const;

    /** Re-read in case graphic was not OK. The current one
       gets replaced by the new one. */
    sal_Bool ReRead( const OUString& rGrfName, const OUString& rFltName,
                 const Graphic* pGraphic = 0,
                 const GraphicObject* pGrfObj = 0,
                 sal_Bool bModify = sal_True );
    /// Loading of graphic immediately before displaying.
    short SwapIn( sal_Bool bWaitForData = sal_False );
    /// Remove graphic in order to free memory.
    short SwapOut();
    /// Access to storage stream-name.
    void SetStreamName( const OUString& r ) { maGrfObj.SetUserData( r ); }
    /// Is this node selected by any shell?
    sal_Bool IsSelected() const;

    /// Communicate to graphic that node is in Undo-range.
    virtual sal_Bool SavePersistentData();
    virtual sal_Bool RestorePersistentData();

    /// Query link-data.
    bool IsGrfLink() const                  { return refLink.Is(); }
    inline bool IsLinkedFile() const;
    inline bool IsLinkedDDE() const;
    ::sfx2::SvBaseLinkRef GetLink() const    { return refLink; }
    bool GetFileFilterNms( OUString* pFileNm, OUString* pFilterNm ) const;
    void ReleaseLink();

    /** Scale an image-map: the image-map becomes zoomed in / out by
       factor between graphic-size and border-size. */
    void ScaleImageMap();

    /// Returns the with our graphic attributes filled Graphic-Attr-Structure.
    GraphicAttr& GetGraphicAttr( GraphicAttr&, const SwFrm* pFrm ) const;

    boost::weak_ptr< SwAsyncRetrieveInputStreamThreadConsumer > GetThreadConsumer();
    bool IsLinkedInputStreamReady() const;
    void TriggerAsyncRetrieveInputStream();
    void ApplyInputStream(
        com::sun::star::uno::Reference<com::sun::star::io::XInputStream> xInputStream,
        const sal_Bool bIsStreamReadOnly );
    void UpdateLinkWithInputStream();
    bool IsAsyncRetrieveInputStreamPossible() const;
};

// Inline methods from Node.hxx - it is only now that we know TxtNode!!
inline       SwGrfNode   *SwNode::GetGrfNode()
{
     return ND_GRFNODE == nNodeType ? (SwGrfNode*)this : 0;
}

inline const SwGrfNode   *SwNode::GetGrfNode() const
{
     return ND_GRFNODE == nNodeType ? (const SwGrfNode*)this : 0;
}

inline bool SwGrfNode::IsLinkedFile() const
{
    return refLink.Is() && OBJECT_CLIENT_GRF == refLink->GetObjType();
}

inline bool SwGrfNode::IsLinkedDDE() const
{
    return refLink.Is() && OBJECT_CLIENT_DDE == refLink->GetObjType();
}

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


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

/**
 * @file
 **/

#include "modules/planning/scenarios/side_pass/side_pass_stage.h"

#include <algorithm>
#include <vector>

#include "modules/common/configs/vehicle_config_helper.h"
#include "modules/common/proto/pnc_point.pb.h"
#include "modules/planning/common/frame.h"
#include "modules/planning/common/speed_profile_generator.h"

namespace apollo {
namespace planning {
namespace scenario {
namespace side_pass {

using apollo::common::TrajectoryPoint;
using apollo::common::math::Vec2d;

constexpr double kExtraMarginforStopOnWaitPointStage = 3.0;

/*
 * @brief:
 * STAGE: SidePassApproachObstacle
 */
Stage::StageStatus SidePassApproachObstacle::Process(
    const TrajectoryPoint& planning_start_point, Frame* frame) {
  bool plan_ok = PlanningOnReferenceLine(planning_start_point, frame);
  if (!plan_ok) {
    AERROR << "Stage " << Name() << " error: "
           << "planning on reference line failed.";
    return Stage::ERROR;
  }
  const ReferenceLineInfo& reference_line_info =
      frame->reference_line_info().front();
  double adc_velocity = frame->vehicle_state().linear_velocity();
  double adc_front_edge_s = reference_line_info.AdcSlBoundary().end_s();
  const PathDecision& path_decision = reference_line_info.path_decision();

  double front_obstacle_distance = 1000;
  for (const auto* obstacle : path_decision.obstacles().Items()) {
    if (obstacle->IsVirtual()) {
      continue;
    }

    bool is_on_road = reference_line_info.reference_line().HasOverlap(
        obstacle->PerceptionBoundingBox());
    if (!is_on_road) {
      continue;
    }

    const auto& obstacle_sl = obstacle->PerceptionSLBoundary();
    if (obstacle_sl.end_s() <= reference_line_info.AdcSlBoundary().start_s()) {
      continue;
    }

    double distance = obstacle_sl.start_s() - adc_front_edge_s;
    if (distance < front_obstacle_distance) {
      front_obstacle_distance = distance;
    }
  }

  if ((front_obstacle_distance) < 0) {
    AERROR << "Stage " << Name() << " error: "
           << "front obstacle has wrong position.";
    return Stage::ERROR;
  }

  double max_stop_velocity =
      GetContext()->scenario_config_.approach_obstacle_max_stop_speed();
  double min_stop_obstacle_distance =
      GetContext()->scenario_config_.approach_obstacle_min_stop_distance();

  if (adc_velocity < max_stop_velocity &&
      front_obstacle_distance > min_stop_obstacle_distance) {
    next_stage_ = ScenarioConfig::SIDE_PASS_GENERATE_PATH;
    return Stage::FINISHED;
  }
  return Stage::RUNNING;
}

/*
 * @brief:
 * STAGE: SidePassGeneratePath
 */
Stage::StageStatus SidePassGeneratePath::Process(
    const TrajectoryPoint& planning_start_point, Frame* frame) {
  if (!PlanningOnReferenceLine(planning_start_point, frame)) {
    AERROR << "Fail to plan on reference_line.";
    return Stage::ERROR;
  }
  GetContext()->path_data_ = frame->reference_line_info().front().path_data();
  if (frame->reference_line_info().front().trajectory().NumOfPoints() > 0) {
    next_stage_ = ScenarioConfig::SIDE_PASS_STOP_ON_WAITPOINT;
    return Stage::FINISHED;
  }
  return Stage::RUNNING;
}

/*
 * @brief:
 * STAGE: SidePassDetectSafety
 */

Stage::StageStatus SidePassDetectSafety::Process(
    const TrajectoryPoint& planning_start_point, Frame* frame) {
  const auto& reference_line_info = frame->reference_line_info().front();
  bool update_success = GetContext()->path_data_.UpdateFrenetFramePath(
      &reference_line_info.reference_line());
  if (!update_success) {
    AERROR << "Fail to update path_data.";
    return Stage::ERROR;
  }

  const auto adc_frenet_frame_point_ =
      reference_line_info.reference_line().GetFrenetPoint(
          frame->PlanningStartPoint());

  bool trim_success = GetContext()->path_data_.LeftTrimWithRefS(
      adc_frenet_frame_point_.s(), adc_frenet_frame_point_.l());
  if (!trim_success) {
    AERROR << "Fail to trim path_data. adc_frenet_frame_point: "
           << adc_frenet_frame_point_.ShortDebugString();
    return Stage::ERROR;
  }

  auto& rfl_info = frame->mutable_reference_line_info()->front();
  *(rfl_info.mutable_path_data()) = GetContext()->path_data_;

  const auto& path_points =
      rfl_info.path_data().discretized_path().path_points();
  auto* debug_path =
      rfl_info.mutable_debug()->mutable_planning_data()->add_path();

  debug_path->set_name("DpPolyPathOptimizer");
  debug_path->mutable_path_point()->CopyFrom(
      {path_points.begin(), path_points.end()});

  if (!PlanningOnReferenceLine(planning_start_point, frame)) {
    return Stage::ERROR;
  }
  bool is_safe = true;
  double adc_front_edge_s = reference_line_info.AdcSlBoundary().end_s();

  const PathDecision& path_decision =
      frame->reference_line_info().front().path_decision();
  for (const auto* obstacle : path_decision.obstacles().Items()) {
    // TODO(All): check according to neighbor lane.
    if (obstacle->IsVirtual() && obstacle->Id().substr(0, 3) == "SP_" &&
        obstacle->PerceptionSLBoundary().start_s() >= adc_front_edge_s) {
      is_safe = false;
      break;
    }
  }
  if (is_safe) {
    next_stage_ = ScenarioConfig::SIDE_PASS_PASS_OBSTACLE;
    return Stage::FINISHED;
  }
  return Stage::RUNNING;
}

/*
 * @brief:
 * STAGE: SidePassPassObstacle
 */
Stage::StageStatus SidePassPassObstacle::Process(
    const TrajectoryPoint& planning_start_point, Frame* frame) {
  const auto& reference_line_info = frame->reference_line_info().front();
  bool update_success = GetContext()->path_data_.UpdateFrenetFramePath(
      &reference_line_info.reference_line());
  if (!update_success) {
    AERROR << "Fail to update path_data.";
    return Stage::ERROR;
  }

  const auto adc_frenet_frame_point_ =
      reference_line_info.reference_line().GetFrenetPoint(
          frame->PlanningStartPoint());

  bool trim_success = GetContext()->path_data_.LeftTrimWithRefS(
      adc_frenet_frame_point_.s(), adc_frenet_frame_point_.l());
  if (!trim_success) {
    AERROR << "Fail to trim path_data. adc_frenet_frame_point: "
           << adc_frenet_frame_point_.ShortDebugString();
    return Stage::ERROR;
  }

  auto& rfl_info = frame->mutable_reference_line_info()->front();
  *(rfl_info.mutable_path_data()) = GetContext()->path_data_;

  const auto& path_points =
      rfl_info.path_data().discretized_path().path_points();
  auto* debug_path =
      rfl_info.mutable_debug()->mutable_planning_data()->add_path();

  // TODO(All):
  // Have to use DpPolyPathOptimizer to show in dreamview. Need change to
  // correct name.
  debug_path->set_name("DpPolyPathOptimizer");
  debug_path->mutable_path_point()->CopyFrom(
      {path_points.begin(), path_points.end()});

  bool plan_ok = PlanningOnReferenceLine(planning_start_point, frame);
  if (!plan_ok) {
    AERROR << "Fail to plan on reference line.";
    return Stage::ERROR;
  }

  const SLBoundary& adc_sl_boundary = reference_line_info.AdcSlBoundary();
  const auto& end_point =
      reference_line_info.path_data().discretized_path().EndPoint();
  Vec2d last_xy_point(end_point.x(), end_point.y());
  // get s of last point on path
  common::SLPoint sl_point;
  if (!reference_line_info.reference_line().XYToSL(last_xy_point, &sl_point)) {
    AERROR << "Fail to transfer cartesian point to frenet point.";
    return Stage::ERROR;
  }

  double distance_to_path_end =
      sl_point.s() - GetContext()->scenario_config_.side_pass_exit_distance();
  if (adc_sl_boundary.end_s() > distance_to_path_end) {
    next_stage_ = ScenarioConfig::NO_STAGE;
    return Stage::FINISHED;
  }
  return Stage::RUNNING;
}

}  // namespace side_pass
}  // namespace scenario
}  // namespace planning
}  // namespace apollo
<commit_msg>planning: side pass check blocking osb status in stage 1.<commit_after>/******************************************************************************
 * Copyright 2018 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

/**
 * @file
 **/

#include "modules/planning/scenarios/side_pass/side_pass_stage.h"

#include <algorithm>
#include <vector>

#include "modules/common/configs/vehicle_config_helper.h"
#include "modules/common/proto/pnc_point.pb.h"
#include "modules/planning/common/frame.h"
#include "modules/planning/common/speed_profile_generator.h"

namespace apollo {
namespace planning {
namespace scenario {
namespace side_pass {

using apollo::common::TrajectoryPoint;
using apollo::common::math::Vec2d;

constexpr double kExtraMarginforStopOnWaitPointStage = 3.0;

/*
 * @brief:
 * STAGE: SidePassApproachObstacle
 */
Stage::StageStatus SidePassApproachObstacle::Process(
    const TrajectoryPoint& planning_start_point, Frame* frame) {
  // check the status of side pass scenario
  const SLBoundary& adc_sl_boundary =
      frame->reference_line_info().front().AdcSlBoundary();
  const PathDecision& path_decision =
      frame->reference_line_info().front().path_decision();
  for (const auto* obstacle : path_decision.obstacles().Items()) {
    if (obstacle->IsVirtual() || !obstacle->IsStatic()) {
      continue;
    }
    CHECK(obstacle->IsStatic());

    if (obstacle->PerceptionSLBoundary().start_s() <=
        adc_sl_boundary.end_s()) {  // such vehicles are behind the ego car.
      continue;
    }
    constexpr double kAdcDistanceThreshold = 15.0;  // unit: m
    if (obstacle->PerceptionSLBoundary().start_s() >
        adc_sl_boundary.end_s() +
            kAdcDistanceThreshold) {  // vehicles are far away
      continue;
    }
    if (obstacle->PerceptionSLBoundary().start_l() > 1.0 ||
        obstacle->PerceptionSLBoundary().end_l() < -1.0) {
      continue;
    }
    next_stage_ = ScenarioConfig::NO_STAGE;
    return Stage::FINISHED;
  }
  // do path planning
  bool plan_ok = PlanningOnReferenceLine(planning_start_point, frame);
  if (!plan_ok) {
    AERROR << "Stage " << Name() << " error: "
           << "planning on reference line failed.";
    return Stage::ERROR;
  }
  const ReferenceLineInfo& reference_line_info =
      frame->reference_line_info().front();
  double adc_velocity = frame->vehicle_state().linear_velocity();
  double adc_front_edge_s = reference_line_info.AdcSlBoundary().end_s();

  double front_obstacle_distance = 1000;
  for (const auto* obstacle : path_decision.obstacles().Items()) {
    if (obstacle->IsVirtual()) {
      continue;
    }

    bool is_on_road = reference_line_info.reference_line().HasOverlap(
        obstacle->PerceptionBoundingBox());
    if (!is_on_road) {
      continue;
    }

    const auto& obstacle_sl = obstacle->PerceptionSLBoundary();
    if (obstacle_sl.end_s() <= reference_line_info.AdcSlBoundary().start_s()) {
      continue;
    }

    double distance = obstacle_sl.start_s() - adc_front_edge_s;
    if (distance < front_obstacle_distance) {
      front_obstacle_distance = distance;
    }
  }

  if ((front_obstacle_distance) < 0) {
    AERROR << "Stage " << Name() << " error: "
           << "front obstacle has wrong position.";
    return Stage::ERROR;
  }

  double max_stop_velocity =
      GetContext()->scenario_config_.approach_obstacle_max_stop_speed();
  double min_stop_obstacle_distance =
      GetContext()->scenario_config_.approach_obstacle_min_stop_distance();

  if (adc_velocity < max_stop_velocity &&
      front_obstacle_distance > min_stop_obstacle_distance) {
    next_stage_ = ScenarioConfig::SIDE_PASS_GENERATE_PATH;
    return Stage::FINISHED;
  }
  return Stage::RUNNING;
}

/*
 * @brief:
 * STAGE: SidePassGeneratePath
 */
Stage::StageStatus SidePassGeneratePath::Process(
    const TrajectoryPoint& planning_start_point, Frame* frame) {
  if (!PlanningOnReferenceLine(planning_start_point, frame)) {
    AERROR << "Fail to plan on reference_line.";
    return Stage::ERROR;
  }
  GetContext()->path_data_ = frame->reference_line_info().front().path_data();
  if (frame->reference_line_info().front().trajectory().NumOfPoints() > 0) {
    next_stage_ = ScenarioConfig::SIDE_PASS_STOP_ON_WAITPOINT;
    return Stage::FINISHED;
  }
  return Stage::RUNNING;
}

/*
 * @brief:
 * STAGE: SidePassDetectSafety
 */

Stage::StageStatus SidePassDetectSafety::Process(
    const TrajectoryPoint& planning_start_point, Frame* frame) {
  const auto& reference_line_info = frame->reference_line_info().front();
  bool update_success = GetContext()->path_data_.UpdateFrenetFramePath(
      &reference_line_info.reference_line());
  if (!update_success) {
    AERROR << "Fail to update path_data.";
    return Stage::ERROR;
  }

  const auto adc_frenet_frame_point_ =
      reference_line_info.reference_line().GetFrenetPoint(
          frame->PlanningStartPoint());

  bool trim_success = GetContext()->path_data_.LeftTrimWithRefS(
      adc_frenet_frame_point_.s(), adc_frenet_frame_point_.l());
  if (!trim_success) {
    AERROR << "Fail to trim path_data. adc_frenet_frame_point: "
           << adc_frenet_frame_point_.ShortDebugString();
    return Stage::ERROR;
  }

  auto& rfl_info = frame->mutable_reference_line_info()->front();
  *(rfl_info.mutable_path_data()) = GetContext()->path_data_;

  const auto& path_points =
      rfl_info.path_data().discretized_path().path_points();
  auto* debug_path =
      rfl_info.mutable_debug()->mutable_planning_data()->add_path();

  debug_path->set_name("DpPolyPathOptimizer");
  debug_path->mutable_path_point()->CopyFrom(
      {path_points.begin(), path_points.end()});

  if (!PlanningOnReferenceLine(planning_start_point, frame)) {
    return Stage::ERROR;
  }
  bool is_safe = true;
  double adc_front_edge_s = reference_line_info.AdcSlBoundary().end_s();

  const PathDecision& path_decision =
      frame->reference_line_info().front().path_decision();
  for (const auto* obstacle : path_decision.obstacles().Items()) {
    // TODO(All): check according to neighbor lane.
    if (obstacle->IsVirtual() && obstacle->Id().substr(0, 3) == "SP_" &&
        obstacle->PerceptionSLBoundary().start_s() >= adc_front_edge_s) {
      is_safe = false;
      break;
    }
  }
  if (is_safe) {
    next_stage_ = ScenarioConfig::SIDE_PASS_PASS_OBSTACLE;
    return Stage::FINISHED;
  }
  return Stage::RUNNING;
}

/*
 * @brief:
 * STAGE: SidePassPassObstacle
 */
Stage::StageStatus SidePassPassObstacle::Process(
    const TrajectoryPoint& planning_start_point, Frame* frame) {
  const auto& reference_line_info = frame->reference_line_info().front();
  bool update_success = GetContext()->path_data_.UpdateFrenetFramePath(
      &reference_line_info.reference_line());
  if (!update_success) {
    AERROR << "Fail to update path_data.";
    return Stage::ERROR;
  }

  const auto adc_frenet_frame_point_ =
      reference_line_info.reference_line().GetFrenetPoint(
          frame->PlanningStartPoint());

  bool trim_success = GetContext()->path_data_.LeftTrimWithRefS(
      adc_frenet_frame_point_.s(), adc_frenet_frame_point_.l());
  if (!trim_success) {
    AERROR << "Fail to trim path_data. adc_frenet_frame_point: "
           << adc_frenet_frame_point_.ShortDebugString();
    return Stage::ERROR;
  }

  auto& rfl_info = frame->mutable_reference_line_info()->front();
  *(rfl_info.mutable_path_data()) = GetContext()->path_data_;

  const auto& path_points =
      rfl_info.path_data().discretized_path().path_points();
  auto* debug_path =
      rfl_info.mutable_debug()->mutable_planning_data()->add_path();

  // TODO(All):
  // Have to use DpPolyPathOptimizer to show in dreamview. Need change to
  // correct name.
  debug_path->set_name("DpPolyPathOptimizer");
  debug_path->mutable_path_point()->CopyFrom(
      {path_points.begin(), path_points.end()});

  bool plan_ok = PlanningOnReferenceLine(planning_start_point, frame);
  if (!plan_ok) {
    AERROR << "Fail to plan on reference line.";
    return Stage::ERROR;
  }

  const SLBoundary& adc_sl_boundary = reference_line_info.AdcSlBoundary();
  const auto& end_point =
      reference_line_info.path_data().discretized_path().EndPoint();
  Vec2d last_xy_point(end_point.x(), end_point.y());
  // get s of last point on path
  common::SLPoint sl_point;
  if (!reference_line_info.reference_line().XYToSL(last_xy_point, &sl_point)) {
    AERROR << "Fail to transfer cartesian point to frenet point.";
    return Stage::ERROR;
  }

  double distance_to_path_end =
      sl_point.s() - GetContext()->scenario_config_.side_pass_exit_distance();
  if (adc_sl_boundary.end_s() > distance_to_path_end) {
    next_stage_ = ScenarioConfig::NO_STAGE;
    return Stage::FINISHED;
  }
  return Stage::RUNNING;
}

}  // namespace side_pass
}  // namespace scenario
}  // namespace planning
}  // namespace apollo
<|endoftext|>


<commit_before>//===------------------------ CalcSpillWeights.cpp ------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "calcspillweights"

#include "llvm/CodeGen/CalcSpillWeights.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
using namespace llvm;

void llvm::calculateSpillWeightsAndHints(LiveIntervals &LIS,
                           MachineFunction &MF,
                           const MachineLoopInfo &MLI,
                           const MachineBlockFrequencyInfo &MBFI,
                           VirtRegAuxInfo::NormalizingFn norm) {
  DEBUG(dbgs() << "********** Compute Spill Weights **********\n"
               << "********** Function: " << MF.getName() << '\n');

  MachineRegisterInfo &MRI = MF.getRegInfo();
  VirtRegAuxInfo VRAI(MF, LIS, MLI, MBFI, norm);
  for (unsigned i = 0, e = MRI.getNumVirtRegs(); i != e; ++i) {
    unsigned Reg = TargetRegisterInfo::index2VirtReg(i);
    if (MRI.reg_nodbg_empty(Reg))
      continue;
    VRAI.calculateSpillWeightAndHint(LIS.getInterval(Reg));
  }
}

// Return the preferred allocation register for reg, given a COPY instruction.
static unsigned copyHint(const MachineInstr *mi, unsigned reg,
                         const TargetRegisterInfo &tri,
                         const MachineRegisterInfo &mri) {
  unsigned sub, hreg, hsub;
  if (mi->getOperand(0).getReg() == reg) {
    sub = mi->getOperand(0).getSubReg();
    hreg = mi->getOperand(1).getReg();
    hsub = mi->getOperand(1).getSubReg();
  } else {
    sub = mi->getOperand(1).getSubReg();
    hreg = mi->getOperand(0).getReg();
    hsub = mi->getOperand(0).getSubReg();
  }

  if (!hreg)
    return 0;

  if (TargetRegisterInfo::isVirtualRegister(hreg))
    return sub == hsub ? hreg : 0;

  const TargetRegisterClass *rc = mri.getRegClass(reg);

  // Only allow physreg hints in rc.
  if (sub == 0)
    return rc->contains(hreg) ? hreg : 0;

  // reg:sub should match the physreg hreg.
  return tri.getMatchingSuperReg(hreg, sub, rc);
}

// Check if all values in LI are rematerializable
static bool isRematerializable(const LiveInterval &LI,
                               const LiveIntervals &LIS,
                               const TargetInstrInfo &TII) {
  for (LiveInterval::const_vni_iterator I = LI.vni_begin(), E = LI.vni_end();
       I != E; ++I) {
    const VNInfo *VNI = *I;
    if (VNI->isUnused())
      continue;
    if (VNI->isPHIDef())
      return false;

    MachineInstr *MI = LIS.getInstructionFromIndex(VNI->def);
    assert(MI && "Dead valno in interval");

    if (!TII.isTriviallyReMaterializable(MI, LIS.getAliasAnalysis()))
      return false;
  }
  return true;
}

void
VirtRegAuxInfo::calculateSpillWeightAndHint(LiveInterval &li) {
  MachineRegisterInfo &mri = MF.getRegInfo();
  const TargetRegisterInfo &tri = *MF.getTarget().getRegisterInfo();
  MachineBasicBlock *mbb = nullptr;
  MachineLoop *loop = nullptr;
  bool isExiting = false;
  float totalWeight = 0;
  SmallPtrSet<MachineInstr*, 8> visited;

  // Find the best physreg hint and the best virtreg hint.
  float bestPhys = 0, bestVirt = 0;
  unsigned hintPhys = 0, hintVirt = 0;

  // Don't recompute a target specific hint.
  bool noHint = mri.getRegAllocationHint(li.reg).first != 0;

  // Don't recompute spill weight for an unspillable register.
  bool Spillable = li.isSpillable();

  for (MachineRegisterInfo::reg_instr_iterator
       I = mri.reg_instr_begin(li.reg), E = mri.reg_instr_end();
       I != E; ) {
    MachineInstr *mi = &*(I++);
    if (mi->isIdentityCopy() || mi->isImplicitDef() || mi->isDebugValue())
      continue;
    if (!visited.insert(mi))
      continue;

    float weight = 1.0f;
    if (Spillable) {
      // Get loop info for mi.
      if (mi->getParent() != mbb) {
        mbb = mi->getParent();
        loop = Loops.getLoopFor(mbb);
        isExiting = loop ? loop->isLoopExiting(mbb) : false;
      }

      // Calculate instr weight.
      bool reads, writes;
      std::tie(reads, writes) = mi->readsWritesVirtualRegister(li.reg);
      weight = LiveIntervals::getSpillWeight(
        writes, reads, &MBFI, mi);

      // Give extra weight to what looks like a loop induction variable update.
      if (writes && isExiting && LIS.isLiveOutOfMBB(li, mbb))
        weight *= 3;

      totalWeight += weight;
    }

    // Get allocation hints from copies.
    if (noHint || !mi->isCopy())
      continue;
    unsigned hint = copyHint(mi, li.reg, tri, mri);
    if (!hint)
      continue;
    float hweight = Hint[hint] += weight;
    if (TargetRegisterInfo::isPhysicalRegister(hint)) {
      if (hweight > bestPhys && mri.isAllocatable(hint))
        bestPhys = hweight, hintPhys = hint;
    } else {
      if (hweight > bestVirt)
        bestVirt = hweight, hintVirt = hint;
    }
  }

  Hint.clear();

  // Always prefer the physreg hint.
  if (unsigned hint = hintPhys ? hintPhys : hintVirt) {
    mri.setRegAllocationHint(li.reg, 0, hint);
    // Weakly boost the spill weight of hinted registers.
    totalWeight *= 1.01F;
  }

  // If the live interval was already unspillable, leave it that way.
  if (!Spillable)
    return;

  // Mark li as unspillable if all live ranges are tiny.
  if (li.isZeroLength(LIS.getSlotIndexes())) {
    li.markNotSpillable();
    return;
  }

  // If all of the definitions of the interval are re-materializable,
  // it is a preferred candidate for spilling.
  // FIXME: this gets much more complicated once we support non-trivial
  // re-materialization.
  if (isRematerializable(li, LIS, *MF.getTarget().getInstrInfo()))
    totalWeight *= 0.5F;

  li.weight = normalize(totalWeight, li.getSize());
}
<commit_msg>CalcSpillWeights: Hack to prevent x87 nonsense<commit_after>//===------------------------ CalcSpillWeights.cpp ------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "calcspillweights"

#include "llvm/CodeGen/CalcSpillWeights.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
using namespace llvm;

void llvm::calculateSpillWeightsAndHints(LiveIntervals &LIS,
                           MachineFunction &MF,
                           const MachineLoopInfo &MLI,
                           const MachineBlockFrequencyInfo &MBFI,
                           VirtRegAuxInfo::NormalizingFn norm) {
  DEBUG(dbgs() << "********** Compute Spill Weights **********\n"
               << "********** Function: " << MF.getName() << '\n');

  MachineRegisterInfo &MRI = MF.getRegInfo();
  VirtRegAuxInfo VRAI(MF, LIS, MLI, MBFI, norm);
  for (unsigned i = 0, e = MRI.getNumVirtRegs(); i != e; ++i) {
    unsigned Reg = TargetRegisterInfo::index2VirtReg(i);
    if (MRI.reg_nodbg_empty(Reg))
      continue;
    VRAI.calculateSpillWeightAndHint(LIS.getInterval(Reg));
  }
}

// Return the preferred allocation register for reg, given a COPY instruction.
static unsigned copyHint(const MachineInstr *mi, unsigned reg,
                         const TargetRegisterInfo &tri,
                         const MachineRegisterInfo &mri) {
  unsigned sub, hreg, hsub;
  if (mi->getOperand(0).getReg() == reg) {
    sub = mi->getOperand(0).getSubReg();
    hreg = mi->getOperand(1).getReg();
    hsub = mi->getOperand(1).getSubReg();
  } else {
    sub = mi->getOperand(1).getSubReg();
    hreg = mi->getOperand(0).getReg();
    hsub = mi->getOperand(0).getSubReg();
  }

  if (!hreg)
    return 0;

  if (TargetRegisterInfo::isVirtualRegister(hreg))
    return sub == hsub ? hreg : 0;

  const TargetRegisterClass *rc = mri.getRegClass(reg);

  // Only allow physreg hints in rc.
  if (sub == 0)
    return rc->contains(hreg) ? hreg : 0;

  // reg:sub should match the physreg hreg.
  return tri.getMatchingSuperReg(hreg, sub, rc);
}

// Check if all values in LI are rematerializable
static bool isRematerializable(const LiveInterval &LI,
                               const LiveIntervals &LIS,
                               const TargetInstrInfo &TII) {
  for (LiveInterval::const_vni_iterator I = LI.vni_begin(), E = LI.vni_end();
       I != E; ++I) {
    const VNInfo *VNI = *I;
    if (VNI->isUnused())
      continue;
    if (VNI->isPHIDef())
      return false;

    MachineInstr *MI = LIS.getInstructionFromIndex(VNI->def);
    assert(MI && "Dead valno in interval");

    if (!TII.isTriviallyReMaterializable(MI, LIS.getAliasAnalysis()))
      return false;
  }
  return true;
}

void
VirtRegAuxInfo::calculateSpillWeightAndHint(LiveInterval &li) {
  MachineRegisterInfo &mri = MF.getRegInfo();
  const TargetRegisterInfo &tri = *MF.getTarget().getRegisterInfo();
  MachineBasicBlock *mbb = nullptr;
  MachineLoop *loop = nullptr;
  bool isExiting = false;
  float totalWeight = 0;
  SmallPtrSet<MachineInstr*, 8> visited;

  // Find the best physreg hint and the best virtreg hint.
  float bestPhys = 0, bestVirt = 0;
  unsigned hintPhys = 0, hintVirt = 0;

  // Don't recompute a target specific hint.
  bool noHint = mri.getRegAllocationHint(li.reg).first != 0;

  // Don't recompute spill weight for an unspillable register.
  bool Spillable = li.isSpillable();

  for (MachineRegisterInfo::reg_instr_iterator
       I = mri.reg_instr_begin(li.reg), E = mri.reg_instr_end();
       I != E; ) {
    MachineInstr *mi = &*(I++);
    if (mi->isIdentityCopy() || mi->isImplicitDef() || mi->isDebugValue())
      continue;
    if (!visited.insert(mi))
      continue;

    float weight = 1.0f;
    if (Spillable) {
      // Get loop info for mi.
      if (mi->getParent() != mbb) {
        mbb = mi->getParent();
        loop = Loops.getLoopFor(mbb);
        isExiting = loop ? loop->isLoopExiting(mbb) : false;
      }

      // Calculate instr weight.
      bool reads, writes;
      std::tie(reads, writes) = mi->readsWritesVirtualRegister(li.reg);
      weight = LiveIntervals::getSpillWeight(
        writes, reads, &MBFI, mi);

      // Give extra weight to what looks like a loop induction variable update.
      if (writes && isExiting && LIS.isLiveOutOfMBB(li, mbb))
        weight *= 3;

      totalWeight += weight;
    }

    // Get allocation hints from copies.
    if (noHint || !mi->isCopy())
      continue;
    unsigned hint = copyHint(mi, li.reg, tri, mri);
    if (!hint)
      continue;
    // Force hweight onto the stack so that x86 doesn't add hidden precision,
    // making the comparison incorrectly pass (i.e., 1 > 1 == true??).
    //
    // FIXME: we probably shouldn't use floats at all.
    volatile float hweight = Hint[hint] += weight;
    if (TargetRegisterInfo::isPhysicalRegister(hint)) {
      if (hweight > bestPhys && mri.isAllocatable(hint))
        bestPhys = hweight, hintPhys = hint;
    } else {
      if (hweight > bestVirt)
        bestVirt = hweight, hintVirt = hint;
    }
  }

  Hint.clear();

  // Always prefer the physreg hint.
  if (unsigned hint = hintPhys ? hintPhys : hintVirt) {
    mri.setRegAllocationHint(li.reg, 0, hint);
    // Weakly boost the spill weight of hinted registers.
    totalWeight *= 1.01F;
  }

  // If the live interval was already unspillable, leave it that way.
  if (!Spillable)
    return;

  // Mark li as unspillable if all live ranges are tiny.
  if (li.isZeroLength(LIS.getSlotIndexes())) {
    li.markNotSpillable();
    return;
  }

  // If all of the definitions of the interval are re-materializable,
  // it is a preferred candidate for spilling.
  // FIXME: this gets much more complicated once we support non-trivial
  // re-materialization.
  if (isRematerializable(li, LIS, *MF.getTarget().getInstrInfo()))
    totalWeight *= 0.5F;

  li.weight = normalize(totalWeight, li.getSize());
}
<|endoftext|>