<commit_before>//---------------------------------------------------------- -*- Mode: C++ -*-
// $Id$
//
// Created 2007/09/05
// Author: Sriram Rao (Kosmix Corp.)
//
// Copyright 2007 Kosmix Corp.
//
// This file is part of Kosmos File System (KFS).
//
// 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.
//
// \brief A sample C++ program that demonstrates KFS APIs.  To run
// this program, you need:
//   - link with libkfsClient.a
//   - a KFS deployment
//
//----------------------------------------------------------------------------

#include <iostream>
#include <fstream>
#include <cerrno>

extern "C" {
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
}

#include "libkfsClient/KfsClient.h"

using std::cout;
using std::endl;
using std::ifstream;

KfsClient *gKfsClient;

// Make the directory hierarchy in KFS defined by path.
bool doMkdirs(const char *path);

// generate sample data for testing
void generateData(char *buf, int numBytes);

int
main(int argc, char **argv)
{
    string serverHost = "";
    int port = -1;
    bool help = false;
    char optchar;
    struct stat statInfo;

    while ((optchar = getopt(argc, argv, "hp:s:")) != -1) {
        switch (optchar) {
            case 'p':
                port = atoi(optarg);
                break;
            case 's':
                serverHost = optarg;
                break;
            case 'h':
                help = true;
                break;
            default:
                cout << "Unrecognized flag " << optchar << endl;
                help = true;
                break;
        }
    }

    if (help || (serverHost == "") || (port < 0)) {
        cout << "Usage: " << argv[0] << " -s <meta server name> -p <port> "
             << endl;
        exit(0);
    }

    //
    // Get a handle to the KFS client object.  This is our entry into
    // the KFS namespace.
    //
    gKfsClient = KfsClient::Instance();
    gKfsClient->Init(serverHost, port);
    if (!gKfsClient->IsInitialized()) {
	cout << "kfs client failed to initialize...exiting" << endl;
        exit(0);
    }

    // Now that the client is init'ed, do some file-I/O

    // Make /ctest
    string basedir = "ctest";
    if (!doMkdirs(basedir.c_str())) {
        exit(0);
    }

    // What we just created better be a directory
    if (!gKfsClient->isDirectory(basedir)) {
        cout << "KFS doesn't think: " << basedir << " is a dir!" << endl;
        exit(-1);
    }

    // Create a simple file with default replication (at most 3)
    string tempFn = new String(basedir + "/foo.1");
    int fd;

    // fd is our file-handle to the file we are creating; this
    // file handle should be used in subsequent I/O calls on
    // the file.
    if ((fd = gKfsClient->Create(path)) < 0) {
        cout << "Create failed: " << ErrorCodeToStr(fd) << endl;
        exit(-1);
    }

    // Get the directory listings
    vector<string> entries;
    int res;

    if ((res = gKfsClient->Readdir(basedir.c_str(), entries)) < 0) {
        cout << "Readdir failed! " << ErrorCodeToStr(res) << endl;
        exit(-1);
    }

    cout << "Read dir returned: ";
    for (int i = 0; i < entries.size(); i++) {
        cout << entries[i] << endl;
    }

    // write something to the file
    int numBytes = 2048;
    char *dataBuf = new char[numBytes];

    generateData(dataBuf, numBytes);

    // make a copy and write out using the copy; we keep the original
    // so we can validate what we get back is what we wrote.
    char *d1 = new char[numBytes];
    memcpy(d1, dataBuf, numBytes);

    int res = gKfsClient->Write(fd, buf, numBytes);
    if (res != numBytes) {
        cout << "Was able to write only: " << res << " instead of " << numBytes << endl;
    }

    // flush out the changes
    gKfsClient->Sync(fd);

    // Close the file-handle
    gKfsClient->Close(fd);

    // Determine the file-size
    gKfsClient->Stat(path.c_str(), statInfo);
    long sz = statInfo.st_size;

    if (sz != numBytes) {
        cout << "KFS thinks the file's size is: " << sz << " instead of " << numBytes << endl;
    }

    // rename the file
    string npath = basedir + "/foo.2";
    gKfsClient->Rename(tempFn.c_str(), npath.c_str());

    if (gKfsClient->Exists(tempFn)) {
        cout << tempFn << " still exists after rename!" << endl;
        exit(-1);
    }

    // Re-create the file and try a rename that should fail...
    int fd1 = gKfsClient->Create(tempFn.c_str());

    if (!gKfsClient->Exists(tempFn.c_str())) {
        cout << " After rec-create..., " << tempFn << " doesn't exist!" << endl;
        exit(-1);
    }

    gKfsClient->Close(fd1);

    // try to rename and don't allow overwrite
    if (gKfsClient->Rename(npath.c_str(), tempFn.c_str(), false) == 0) {
        cout << "Rename  with overwrite disabled succeeded...error!" << endl;
        exit(-1);
    }

    // Remove the file
    gKfsClient->Remove(tempFn.c_str());

    // Re-open the file
    if ((fd = gKfsClient->Open(npath.c_str(), O_RDWR)) < 0) {
        cout << "Open on : " << npath << " failed!" << ErrorCodeToStr(fd) << endl;
        exit(-1);
    }

    // read some bytes
    res = gKfsClient->Read(fd, d1, 128);

    // Verify what we read matches what we wrote
    for (int i = 0; i < 128; i++) {
        if (dataBuf[i] != d1[i]) {
            cout << "Data mismatch at : " << i << endl;
        }
    }

    // seek to offset 40
    gKfsClient->Seek(fd, 40);

    // Seek and verify that we are we think we are
    sz = gKfsClient->Tell(fd);
    if (sz != 40) {
        cout << "After seek, we are at: " << sz << " should be at 40 " << endl;
    }

    gKfsClient->Close(fd);

    // remove the file
    gKfsClient->Remove(npath.c_str());

    // remove the dir
    if ((res = gKfsClient->Rmdir(basedir.c_str()) < 0) {
        cout << "Unable to remove: " << basedir << " : " << ErrorCodeToStr(res) << endl;
    } else {
        cout << "Testts passed!" << endl;
    }
}

bool
doMkdirs(const char *path)
{
    int res;

    res = gKfsClient->Mkdirs((char *) path);
    if ((res < 0) && (res != -EEXIST)) {
        cout << "Mkdir failed: " << ErrorCodeToStr(res) << endl;
        return false;
    }
    return true;
}

void generateData(char *buf, int numBytes)
{
    int i;

    srand(100);
    for (i = 0; i < numBytes; i++) {
        buf[i] = (char) ('a' + (rand() % 26));
    }
}
<commit_msg> -- Fixed sample code so that it compiles with the client library.<commit_after>//---------------------------------------------------------- -*- Mode: C++ -*-
// $Id$
//
// Created 2007/09/05
// Author: Sriram Rao (Kosmix Corp.)
//
// Copyright 2007 Kosmix Corp.
//
// This file is part of Kosmos File System (KFS).
//
// 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.
//
// \brief A sample C++ program that demonstrates KFS APIs.  To run
// this program, you need:
//   - link with libkfsClient.a
//   - a KFS deployment
//
//----------------------------------------------------------------------------

#include <iostream>
#include <fstream>
#include <cerrno>

extern "C" {
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
}

#include "libkfsClient/KfsClient.h"

using std::cout;
using std::endl;
using std::ifstream;
using namespace KFS;

KfsClientPtr gKfsClient;

// Make the directory hierarchy in KFS defined by path.
bool doMkdirs(const char *path);

// generate sample data for testing
void generateData(char *buf, int numBytes);

int
main(int argc, char **argv)
{
    string serverHost = "";
    int port = -1;
    bool help = false;
    char optchar;
    struct stat statInfo;

    while ((optchar = getopt(argc, argv, "hp:s:")) != -1) {
        switch (optchar) {
            case 'p':
                port = atoi(optarg);
                break;
            case 's':
                serverHost = optarg;
                break;
            case 'h':
                help = true;
                break;
            default:
                cout << "Unrecognized flag " << optchar << endl;
                help = true;
                break;
        }
    }

    if (help || (serverHost == "") || (port < 0)) {
        cout << "Usage: " << argv[0] << " -s <meta server name> -p <port> "
             << endl;
        exit(0);
    }

    //
    // Get a handle to the KFS client object.  This is our entry into
    // the KFS namespace.
    //
    gKfsClient = getKfsClientFactory()->GetClient(serverHost, port);
    if (!gKfsClient) {
        cout << "kfs client failed to initialize...exiting" << endl;
        exit(-1);
    }

    // Now that the client is init'ed, do some file-I/O

    // Make /ctest
    string basedir = "ctest";
    if (!doMkdirs(basedir.c_str())) {
        exit(0);
    }

    // What we just created better be a directory
    if (!gKfsClient->IsDirectory(basedir.c_str())) {
        cout << "KFS doesn't think: " << basedir << " is a dir!" << endl;
        exit(-1);
    }

    // Create a simple file with default replication (at most 3)
    string tempFn(basedir + "/foo.1");
    int fd;

    // fd is our file-handle to the file we are creating; this
    // file handle should be used in subsequent I/O calls on
    // the file.
    if ((fd = gKfsClient->Create(tempFn.c_str())) < 0) {
        cout << "Create failed: " << ErrorCodeToStr(fd) << endl;
        exit(-1);
    }

    // Get the directory listings
    vector<string> entries;
    int res;

    if ((res = gKfsClient->Readdir(basedir.c_str(), entries)) < 0) {
        cout << "Readdir failed! " << ErrorCodeToStr(res) << endl;
        exit(-1);
    }

    cout << "Read dir returned: ";
    for (uint32_t i = 0; i < entries.size(); i++) {
        cout << entries[i] << endl;
    }

    // write something to the file
    int numBytes = 2048;
    char *dataBuf = new char[numBytes];

    generateData(dataBuf, numBytes);

    // make a copy and write out using the copy; we keep the original
    // so we can validate what we get back is what we wrote.
    char *d1 = new char[numBytes];
    memcpy(d1, dataBuf, numBytes);

    res = gKfsClient->Write(fd, dataBuf, numBytes);
    if (res != numBytes) {
        cout << "Was able to write only: " << res << " instead of " << numBytes << endl;
    }

    // flush out the changes
    gKfsClient->Sync(fd);

    // Close the file-handle
    gKfsClient->Close(fd);

    // Determine the file-size
    gKfsClient->Stat(tempFn.c_str(), statInfo);
    long sz = statInfo.st_size;

    if (sz != numBytes) {
        cout << "KFS thinks the file's size is: " << sz << " instead of " << numBytes << endl;
    }

    // rename the file
    string npath = basedir + "/foo.2";
    gKfsClient->Rename(tempFn.c_str(), npath.c_str());

    if (gKfsClient->Exists(tempFn.c_str())) {
        cout << tempFn << " still exists after rename!" << endl;
        exit(-1);
    }

    // Re-create the file and try a rename that should fail...
    int fd1 = gKfsClient->Create(tempFn.c_str());

    if (!gKfsClient->Exists(tempFn.c_str())) {
        cout << " After rec-create..., " << tempFn << " doesn't exist!" << endl;
        exit(-1);
    }

    gKfsClient->Close(fd1);

    // try to rename and don't allow overwrite
    if (gKfsClient->Rename(npath.c_str(), tempFn.c_str(), false) == 0) {
        cout << "Rename  with overwrite disabled succeeded...error!" << endl;
        exit(-1);
    }

    // Remove the file
    gKfsClient->Remove(tempFn.c_str());

    // Re-open the file
    if ((fd = gKfsClient->Open(npath.c_str(), O_RDWR)) < 0) {
        cout << "Open on : " << npath << " failed!" << ErrorCodeToStr(fd) << endl;
        exit(-1);
    }

    // read some bytes
    res = gKfsClient->Read(fd, d1, 128);

    // Verify what we read matches what we wrote
    for (int i = 0; i < 128; i++) {
        if (dataBuf[i] != d1[i]) {
            cout << "Data mismatch at : " << i << endl;
        }
    }

    // seek to offset 40
    gKfsClient->Seek(fd, 40);

    // Seek and verify that we are we think we are
    sz = gKfsClient->Tell(fd);
    if (sz != 40) {
        cout << "After seek, we are at: " << sz << " should be at 40 " << endl;
    }

    gKfsClient->Close(fd);

    // remove the file
    gKfsClient->Remove(npath.c_str());

    // remove the dir
    if ((res = gKfsClient->Rmdir(basedir.c_str())) < 0) {
        cout << "Unable to remove: " << basedir << " : " << ErrorCodeToStr(res) << endl;
    } else {
        cout << "Testts passed!" << endl;
    }
}

bool
doMkdirs(const char *path)
{
    int res;

    res = gKfsClient->Mkdirs((char *) path);
    if ((res < 0) && (res != -EEXIST)) {
        cout << "Mkdir failed: " << ErrorCodeToStr(res) << endl;
        return false;
    }
    return true;
}

void generateData(char *buf, int numBytes)
{
    int i;

    srand(100);
    for (i = 0; i < numBytes; i++) {
        buf[i] = (char) ('a' + (rand() % 26));
    }
}
<|endoftext|>


<commit_before>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace std;
using namespace cv;

const Scalar RED = Scalar(0,0,255);
const Scalar PINK = Scalar(230,130,255);
const Scalar BLUE = Scalar(255,0,0);
const Scalar LIGHTBLUE = Scalar(255,255,160);
const Scalar GREEN = Scalar(0,255,0);

const int BGD_KEY = CV_EVENT_FLAG_CTRLKEY;
const int FGD_KEY = CV_EVENT_FLAG_SHIFTKEY;
int iterCount;
static void getBinMask( const Mat& comMask, Mat& binMask )
{
      if( binMask.empty() || binMask.rows!=comMask.rows || binMask.cols!=comMask.cols )
        binMask.create( comMask.size(), CV_8UC1 );
    binMask = comMask & 1;
}

int main( int argc, char** argv )
{
   	VideoCapture cap;

   	if(argc<=1)
		cap.open(0);
 	else
 		cap.open(argv[1]);
    	if( !cap.isOpened() )
        		return -1;
        		const string winName = "image";
        	Mat image;

	cap>>image;
	if( image.empty() )
		return -1;
	resize(image, image, Size (640,630*image.rows/image.cols));
	Mat mask,res,binMask;
	Mat bgdModel, fgdModel;
	res.create(image.size(), CV_8UC3);
	res.setTo(Scalar(0,0,0));
	imshow(winName, res );
	binMask.setTo(0);

	mask.create( image.size(), CV_8UC1);
    	mask.setTo( GC_BGD );   //GC_BGD == 0
    	int n=0;
	Rect rect;
	rect.x=60;
	rect.y=40;
	rect.width=image.cols-100;
	rect.height=image.rows-80;
    	(mask(rect)).setTo( Scalar(GC_PR_FGD) );    //GC_PR_FGD == 3£¬
	grabCut( image, mask, rect, bgdModel, fgdModel, 1,GC_INIT_WITH_RECT );
	while(1)
	{
		cap>>image;
		resize(image, image, Size (640,630*image.rows/image.cols));
		//uncomment this line code the programe will be normal
		//grabCut( image, mask, rect, bgdModel, fgdModel, 1,GC_INIT_WITH_RECT );
		grabCut( image, mask, rect, bgdModel, fgdModel, 2,GC_EVAL );
		getBinMask( mask, binMask );
		image.copyTo( res, binMask );
		//rectangle( res, Point( rect.x, rect.y ), Point(rect.x + rect.width, rect.y + rect.height ), GREEN, 2);
		imshow( winName, res );
		char kk=waitKey(1);
		if (kk == 'q')break;
		else if(kk=='n')
		{
			cout<<n++<< "  ";
		}

	}

	destroyWindow( winName );
	return 0;
}
<commit_msg>Update grabCut.cpp<commit_after>// grubcut for video
// Author : reasonW
// Date   : 2016-12-29
// HomePage : http://github.com/reasonW
// Email  :charlewander@gmail.com
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace std;
using namespace cv;

const Scalar RED = Scalar(0,0,255);
const Scalar PINK = Scalar(230,130,255);
const Scalar BLUE = Scalar(255,0,0);
const Scalar LIGHTBLUE = Scalar(255,255,160);
const Scalar GREEN = Scalar(0,255,0);

const int BGD_KEY = CV_EVENT_FLAG_CTRLKEY;
const int FGD_KEY = CV_EVENT_FLAG_SHIFTKEY;
int iterCount;
static void getBinMask( const Mat& comMask, Mat& binMask )
{
      if( binMask.empty() || binMask.rows!=comMask.rows || binMask.cols!=comMask.cols )
        binMask.create( comMask.size(), CV_8UC1 );
    binMask = comMask & 1;
}

int main( int argc, char** argv )
{
   	VideoCapture cap;

   	if(argc<=1)
		cap.open(0);
 	else
 		cap.open(argv[1]);
    	if( !cap.isOpened() )
        		return -1;
        		const string winName = "image";
        	Mat image;

	cap>>image;
	if( image.empty() )
		return -1;
	resize(image, image, Size (640,630*image.rows/image.cols));
	Mat mask,res,binMask;
	Mat bgdModel, fgdModel;
	res.create(image.size(), CV_8UC3);
	res.setTo(Scalar(0,0,0));
	imshow(winName, res );
	binMask.setTo(0);

	mask.create( image.size(), CV_8UC1);
    	mask.setTo( GC_BGD );   //GC_BGD == 0
    	int n=0;
	Rect rect;
	rect.x=60;
	rect.y=40;
	rect.width=image.cols-100;
	rect.height=image.rows-80;
    	(mask(rect)).setTo( Scalar(GC_PR_FGD) );    //GC_PR_FGD == 3£¬
	grabCut( image, mask, rect, bgdModel, fgdModel, 1,GC_INIT_WITH_RECT );
	while(1)
	{
		cap>>image;
		resize(image, image, Size (640,630*image.rows/image.cols));
		//uncomment this line code the programe will be normal
		//grabCut( image, mask, rect, bgdModel, fgdModel, 1,GC_INIT_WITH_RECT );
		grabCut( image, mask, rect, bgdModel, fgdModel, 2,GC_EVAL );
		getBinMask( mask, binMask );
		image.copyTo( res, binMask );
		//rectangle( res, Point( rect.x, rect.y ), Point(rect.x + rect.width, rect.y + rect.height ), GREEN, 2);
		imshow( winName, res );
		char kk=waitKey(1);
		if (kk == 'q')break;
		else if(kk=='n')
		{
			cout<<n++<< "  ";
		}

	}

	destroyWindow( winName );
	return 0;
}
<|endoftext|>


<commit_before>/**
 * This file is part of the CernVM File System.
 */

#include "cvmfs_config.h"
#include "upload.h"

#include <vector>

#include "util_concurrency.h"

namespace upload {

Spooler* Spooler::Construct(const SpoolerDefinition &spooler_definition) {
  Spooler *result = new Spooler(spooler_definition);
  if (!result->Initialize()) {
    delete result;
    result = NULL;
  }
  return result;
}

Spooler::Spooler(const SpoolerDefinition &spooler_definition) :
  spooler_definition_(spooler_definition)
{}

Spooler::~Spooler() {
  uploader_->TearDown();
}

bool Spooler::Initialize() {
  // configure the uploader environment
  uploader_ = AbstractUploader::Construct(spooler_definition_);
  if (!uploader_) {
    LogCvmfs(kLogSpooler, kLogWarning, "Failed to initialize backend upload "
                                       "facility in Spooler.");
    return false;
  }

  // configure the file processor context
  file_processor_ = new FileProcessor(uploader_.weak_ref(),
                                      spooler_definition_);
  file_processor_->RegisterListener(&Spooler::ProcessingCallback, this);

  // all done...
  return true;
}

void Spooler::Process(const std::string &local_path,
                      const bool         allow_chunking) {
  file_processor_->Process(local_path, allow_chunking);
}

void Spooler::ProcessCatalog(const std::string &local_path) {
  file_processor_->Process(local_path, false, shash::kSuffixCatalog);
}

void Spooler::ProcessHistory(const std::string &local_path) {
  file_processor_->Process(local_path, false, shash::kSuffixHistory);
}

void Spooler::Upload(const std::string &local_path,
                     const std::string &remote_path) {
  uploader_->Upload(local_path,
                    remote_path,
                    AbstractUploader::MakeCallback(&Spooler::UploadingCallback,
                                                   this));
}

bool Spooler::Remove(const std::string &file_to_delete) {
  return uploader_->Remove(file_to_delete);
}

bool Spooler::Peek(const std::string &path) const {
  return uploader_->Peek(path);
}

void Spooler::ProcessingCallback(const SpoolerResult &data) {
  NotifyListeners(data);
}

void Spooler::UploadingCallback(const UploaderResults &data) {
  NotifyListeners(SpoolerResult(data.return_code,
                                data.local_path));
}

void Spooler::WaitForUpload() const {
  uploader_->WaitForUpload();
  file_processor_->WaitForProcessing();
}

unsigned int Spooler::GetNumberOfErrors() const {
  return uploader_->GetNumberOfErrors();
}

}  // namespace upload
<commit_msg>FIX: segfault on malformed spooler d'tor<commit_after>/**
 * This file is part of the CernVM File System.
 */

#include "cvmfs_config.h"
#include "upload.h"

#include <vector>

#include "util_concurrency.h"

namespace upload {

Spooler* Spooler::Construct(const SpoolerDefinition &spooler_definition) {
  Spooler *result = new Spooler(spooler_definition);
  if (!result->Initialize()) {
    delete result;
    result = NULL;
  }
  return result;
}

Spooler::Spooler(const SpoolerDefinition &spooler_definition) :
  spooler_definition_(spooler_definition)
{}

Spooler::~Spooler() {
  if (uploader_) {
    uploader_->TearDown();
  }
}

bool Spooler::Initialize() {
  // configure the uploader environment
  uploader_ = AbstractUploader::Construct(spooler_definition_);
  if (!uploader_) {
    LogCvmfs(kLogSpooler, kLogWarning, "Failed to initialize backend upload "
                                       "facility in Spooler.");
    return false;
  }

  // configure the file processor context
  file_processor_ = new FileProcessor(uploader_.weak_ref(),
                                      spooler_definition_);
  file_processor_->RegisterListener(&Spooler::ProcessingCallback, this);

  // all done...
  return true;
}

void Spooler::Process(const std::string &local_path,
                      const bool         allow_chunking) {
  file_processor_->Process(local_path, allow_chunking);
}

void Spooler::ProcessCatalog(const std::string &local_path) {
  file_processor_->Process(local_path, false, shash::kSuffixCatalog);
}

void Spooler::ProcessHistory(const std::string &local_path) {
  file_processor_->Process(local_path, false, shash::kSuffixHistory);
}

void Spooler::Upload(const std::string &local_path,
                     const std::string &remote_path) {
  uploader_->Upload(local_path,
                    remote_path,
                    AbstractUploader::MakeCallback(&Spooler::UploadingCallback,
                                                   this));
}

bool Spooler::Remove(const std::string &file_to_delete) {
  return uploader_->Remove(file_to_delete);
}

bool Spooler::Peek(const std::string &path) const {
  return uploader_->Peek(path);
}

void Spooler::ProcessingCallback(const SpoolerResult &data) {
  NotifyListeners(data);
}

void Spooler::UploadingCallback(const UploaderResults &data) {
  NotifyListeners(SpoolerResult(data.return_code,
                                data.local_path));
}

void Spooler::WaitForUpload() const {
  uploader_->WaitForUpload();
  file_processor_->WaitForProcessing();
}

unsigned int Spooler::GetNumberOfErrors() const {
  return uploader_->GetNumberOfErrors();
}

}  // namespace upload
<|endoftext|>


<commit_before>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "rpcnetwork.h"
#include "rpcservicepool.h"
#include "rpcsendv1.h"
#include "rpcsendv2.h"
#include "rpctargetpool.h"
#include "rpcnetworkparams.h"
#include <vespa/messagebus/errorcode.h>
#include <vespa/messagebus/iprotocol.h>
#include <vespa/messagebus/emptyreply.h>
#include <vespa/messagebus/routing/routingnode.h>
#include <vespa/slobrok/sbregister.h>
#include <vespa/slobrok/sbmirror.h>
#include <vespa/vespalib/component/vtag.h>
#include <vespa/vespalib/stllike/asciistream.h>
#include <vespa/vespalib/util/stringfmt.h>
#include <vespa/fnet/scheduler.h>
#include <vespa/fnet/transport.h>
#include <vespa/fnet/frt/supervisor.h>
#include <vespa/fastos/thread.h>
#include <thread>

#include <vespa/log/log.h>
LOG_SETUP(".rpcnetwork");

using vespalib::make_string;
using namespace std::chrono_literals;

namespace {

/**
 * Implements a helper class for {@link RPCNetwork#sync()}. It provides a
 * blocking method {@link #await()} that will wait until the internal state
 * of this object is set to 'done'. By scheduling this task in the network
 * thread and then calling this method, we achieve handshaking with the network
 * thread.
 */
class SyncTask : public FNET_Task {
private:
    vespalib::Gate _gate;

public:
    SyncTask(FNET_Scheduler &s) :
        FNET_Task(&s),
        _gate() {
        ScheduleNow();
    }
    ~SyncTask() override = default;

    void await() {
        _gate.await();
    }

    void PerformTask() override {
        _gate.countDown();
    }
};

} // namespace <unnamed>

namespace mbus {

RPCNetwork::SendContext::SendContext(RPCNetwork &net, const Message &msg,
                                     const std::vector<RoutingNode*> &recipients)
    : _net(net),
      _msg(msg),
      _traceLevel(msg.getTrace().getLevel()),
      _recipients(recipients),
      _hasError(false),
      _pending(_recipients.size()),
      _version(_net.getVersion())
{ }

void
RPCNetwork::SendContext::handleVersion(const vespalib::Version *version)
{
    bool shouldSend = false;
    {
        vespalib::LockGuard guard(_lock);
        if (version == nullptr) {
            _hasError = true;
        } else if (*version < _version) {
            _version = *version;
        }
        if (--_pending == 0) {
            shouldSend = true;
        }
    }
    if (shouldSend) {
        _net.send(*this);
        delete this;
    }
}

RPCNetwork::TargetPoolTask::TargetPoolTask(FNET_Scheduler &scheduler, RPCTargetPool &pool)
    : FNET_Task(&scheduler),
      _pool(pool)
{
    ScheduleNow();
}

void
RPCNetwork::TargetPoolTask::PerformTask()
{
    _pool.flushTargets(false);
    Schedule(1.0);
}

RPCNetwork::RPCNetwork(const RPCNetworkParams &params) :
    _owner(nullptr),
    _ident(params.getIdentity()),
    _threadPool(std::make_unique<FastOS_ThreadPool>(128000, 0)),
    _transport(std::make_unique<FNET_Transport>()),
    _orb(std::make_unique<FRT_Supervisor>(_transport.get())),
    _scheduler(*_transport->GetScheduler()),
    _targetPool(std::make_unique<RPCTargetPool>(params.getConnectionExpireSecs())),
    _targetPoolTask(_scheduler, *_targetPool),
    _servicePool(std::make_unique<RPCServicePool>(*this, 4096)),
    _slobrokCfgFactory(std::make_unique<slobrok::ConfiguratorFactory>(params.getSlobrokConfig())),
    _mirror(std::make_unique<slobrok::api::MirrorAPI>(*_orb, *_slobrokCfgFactory)),
    _regAPI(std::make_unique<slobrok::api::RegisterAPI>(*_orb, *_slobrokCfgFactory)),
    _requestedPort(params.getListenPort()),
    _executor(std::make_unique<vespalib::ThreadStackExecutor>(params.getNumThreads(), 65536)),
    _sendV1(std::make_unique<RPCSendV1>()),
    _sendV2(std::make_unique<RPCSendV2>()),
    _sendAdapters(),
    _compressionConfig(params.getCompressionConfig()),
    _allowDispatchForEncode(params.getDispatchOnEncode()),
    _allowDispatchForDecode(params.getDispatchOnDecode())
{
    _transport->SetMaxInputBufferSize(params.getMaxInputBufferSize());
    _transport->SetMaxOutputBufferSize(params.getMaxOutputBufferSize());
    _transport->SetTCPNoDelay(false);
}

RPCNetwork::~RPCNetwork()
{
    shutdown();
}

FRT_RPCRequest *
RPCNetwork::allocRequest()
{
    return _orb->AllocRPCRequest();
}

RPCTarget::SP
RPCNetwork::getTarget(const RPCServiceAddress &address)
{
    return _targetPool->getTarget(*_orb, address);
}

void
RPCNetwork::replyError(const SendContext &ctx, uint32_t errCode, const string &errMsg)
{
    for (RoutingNode * rnode : ctx._recipients) {
        Reply::UP reply(new EmptyReply());
        reply->setTrace(Trace(ctx._traceLevel));
        reply->addError(Error(errCode, errMsg));
        _owner->deliverReply(std::move(reply), *rnode);
    }
}

int RPCNetwork::getPort() const { return _orb->GetListenPort(); }

void
RPCNetwork::flushTargetPool()
{
    _targetPool->flushTargets(true);
}

const vespalib::Version &
RPCNetwork::getVersion() const
{
    return vespalib::Vtag::currentVersion;
}

void
RPCNetwork::attach(INetworkOwner &owner)
{
    LOG_ASSERT(_owner == nullptr);
    _owner = &owner;

    _sendV1->attach(*this);
    _sendV2->attach(*this);
    _sendAdapters[vespalib::Version(5)] = _sendV1.get();
    _sendAdapters[vespalib::Version(6, 149)] = _sendV2.get();

    FRT_ReflectionBuilder builder(_orb.get());
    builder.DefineMethod("mbus.getVersion", "", "s", FRT_METHOD(RPCNetwork::invoke), this);
    builder.MethodDesc("Retrieves the message bus version.");
    builder.ReturnDesc("version", "The message bus version.");
}

void
RPCNetwork::invoke(FRT_RPCRequest *req)
{
    req->GetReturn()->AddString(getVersion().toString().c_str());
}

const string
RPCNetwork::getConnectionSpec() const
{
    return make_string("tcp/%s:%d", _ident.getHostname().c_str(), _orb->GetListenPort());
}

RPCSendAdapter *
RPCNetwork::getSendAdapter(const vespalib::Version &version)
{
    if (version < _sendAdapters.begin()->first) {
        return nullptr;
    }
    return (--_sendAdapters.upper_bound(version))->second;
}

bool
RPCNetwork::start()
{
    if (!_transport->Start(_threadPool.get())) {
        return false;
    }
    if (!_orb->Listen(_requestedPort)) {
        return false;
    }
    return true;
}

bool
RPCNetwork::waitUntilReady(duration timeout) const
{
    slobrok::api::SlobrokList brokerList;
    slobrok::Configurator::UP configurator = _slobrokCfgFactory->create(brokerList);
    bool hasConfig = false;
    for (int64_t i = 0; i < vespalib::count_ms(timeout)/10; ++i) {
        if (configurator->poll()) {
            hasConfig = true;
        }
        if (_mirror->ready()) {
            return true;
        }
        std::this_thread::sleep_for(10ms);
    }
    if (! hasConfig) {
        LOG(error, "failed to get config for slobroks in %2.2f seconds", vespalib::to_s(timeout));
    } else if (! _mirror->ready()) {
        auto brokers = brokerList.logString();
        LOG(error, "mirror (of %s) failed to become ready in %2.2f seconds", brokers.c_str(), vespalib::to_s(timeout));
    }
    return false;
}

void
RPCNetwork::registerSession(const string &session)
{
    if (_ident.getServicePrefix().empty()) {
        LOG(warning, "The session (%s) will not be registered in the Slobrok since this network has no identity.",
            session.c_str());
        return;
    }
    string name = _ident.getServicePrefix();
    name += "/";
    name += session;
    _regAPI->registerName(name);
}

void
RPCNetwork::unregisterSession(const string &session)
{
    if (_ident.getServicePrefix().empty()) {
        return;
    }
    string name = _ident.getServicePrefix();
    name += "/";
    name += session;
    _regAPI->unregisterName(name);
}

bool
RPCNetwork::allocServiceAddress(RoutingNode &recipient)
{
    const Hop &hop = recipient.getRoute().getHop(0);
    string service = hop.getServiceName();
    Error error = resolveServiceAddress(recipient, service);
    if (error.getCode() == ErrorCode::NONE) {
        return true; // service address resolved
    }
    recipient.setError(error);
    return false; // service adddress not resolved
}

Error
RPCNetwork::resolveServiceAddress(RoutingNode &recipient, const string &serviceName)
{
    RPCServiceAddress::UP ret = _servicePool->resolve(serviceName);
    if ( ! ret) {
        return Error(ErrorCode::NO_ADDRESS_FOR_SERVICE,
                     make_string("The address of service '%s' could not be resolved. It is not currently "
                                 "registered with the Vespa name server. "
                                 "The service must be having problems, or the routing configuration is wrong. "
                                 "Address resolution attempted from host '%s'",
                                 serviceName.c_str(), getIdentity().getHostname().c_str()));
    }
    RPCTarget::SP target = _targetPool->getTarget(*_orb, *ret);
    if ( ! target) {
        return Error(ErrorCode::CONNECTION_ERROR,
                     make_string("Failed to connect to service '%s' from host '%s'.",
                                 serviceName.c_str(), getIdentity().getHostname().c_str()));
    }
    ret->setTarget(std::move(target)); // free by freeServiceAddress()
    recipient.setServiceAddress(std::move(ret));
    return Error();
}

void
RPCNetwork::freeServiceAddress(RoutingNode &recipient)
{
    recipient.setServiceAddress(IServiceAddress::UP());
}

void
RPCNetwork::send(const Message &msg, const std::vector<RoutingNode*> &recipients)
{
    SendContext &ctx = *(new SendContext(*this, msg, recipients)); // deletes self
    duration timeout = ctx._msg.getTimeRemainingNow();
    for (uint32_t i = 0, len = ctx._recipients.size(); i < len; ++i) {
        RoutingNode *&recipient = ctx._recipients[i];

        RPCServiceAddress &address = static_cast<RPCServiceAddress&>(recipient->getServiceAddress());
        LOG_ASSERT(address.hasTarget());

        address.getTarget().resolveVersion(timeout, ctx);
    }
}

namespace {

void
emit_recipient_endpoint(vespalib::asciistream& stream, const RoutingNode& recipient) {
    if (recipient.hasServiceAddress()) {
        // At this point the service addresses _should_ be RPCServiceAddress instances,
        // but stay on the safe side of the tracks anyway.
        const auto* rpc_addr = dynamic_cast<const RPCServiceAddress*>(&recipient.getServiceAddress());
        if (rpc_addr) {
            stream << rpc_addr->getServiceName() << " at " << rpc_addr->getConnectionSpec();
        } else {
            stream << "<non-RPC service address>";
        }
    } else {
        stream << "<unknown service address>";
    }
}

}

vespalib::string
RPCNetwork::buildRecipientListString(const SendContext& ctx) {
    vespalib::asciistream s;
    bool first = true;
    for (const auto* recipient : ctx._recipients) {
        if (!first) {
            s << ", ";
        }
        first = false;
        emit_recipient_endpoint(s, *recipient);
    }
    return s.str();
}

void
RPCNetwork::send(RPCNetwork::SendContext &ctx)
{
    if (ctx._hasError) {
        replyError(ctx, ErrorCode::HANDSHAKE_FAILED,
                make_string("An error occurred while resolving version of recipient(s) [%s] from host '%s'.",
                            buildRecipientListString(ctx).c_str(), getIdentity().getHostname().c_str()));
    } else {
        duration timeRemaining = ctx._msg.getTimeRemainingNow();
        Blob payload = _owner->getProtocol(ctx._msg.getProtocol())->encode(ctx._version, ctx._msg);
        RPCSendAdapter *adapter = getSendAdapter(ctx._version);
        if (adapter == nullptr) {
            replyError(ctx, ErrorCode::INCOMPATIBLE_VERSION,
                       make_string("Can not send to version '%s' recipient.", ctx._version.toString().c_str()));
        } else if (timeRemaining == 0ms) {
            replyError(ctx, ErrorCode::TIMEOUT, "Aborting transmission because zero time remains.");
        } else if (payload.size() == 0) {
            replyError(ctx, ErrorCode::ENCODE_ERROR,
                       make_string("Protocol '%s' failed to encode message.", ctx._msg.getProtocol().c_str()));
        } else if (ctx._recipients.size() == 1) {
            adapter->sendByHandover(*ctx._recipients.front(), ctx._version, std::move(payload), timeRemaining);
        } else {
            for (auto & recipient : ctx._recipients) {
                adapter->send(*recipient, ctx._version, payload, timeRemaining);
            }
        }
    }
}

void
RPCNetwork::sync()
{
    SyncTask task(_scheduler);
    _executor->sync();
    task.await();
}

void
RPCNetwork::shutdown()
{
    _transport->ShutDown(true);
    _threadPool->Close();
    _executor->shutdown();
    _executor->sync();
}

void
RPCNetwork::postShutdownHook()
{
    _scheduler.CheckTasks();
}

const slobrok::api::IMirrorAPI &
RPCNetwork::getMirror() const
{
    return *_mirror;
}

} // namespace mbus
<commit_msg>Not yet.<commit_after>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "rpcnetwork.h"
#include "rpcservicepool.h"
#include "rpcsendv1.h"
#include "rpcsendv2.h"
#include "rpctargetpool.h"
#include "rpcnetworkparams.h"
#include <vespa/messagebus/errorcode.h>
#include <vespa/messagebus/iprotocol.h>
#include <vespa/messagebus/emptyreply.h>
#include <vespa/messagebus/routing/routingnode.h>
#include <vespa/slobrok/sbregister.h>
#include <vespa/slobrok/sbmirror.h>
#include <vespa/vespalib/component/vtag.h>
#include <vespa/vespalib/stllike/asciistream.h>
#include <vespa/vespalib/util/stringfmt.h>
#include <vespa/fnet/scheduler.h>
#include <vespa/fnet/transport.h>
#include <vespa/fnet/frt/supervisor.h>
#include <vespa/fastos/thread.h>
#include <thread>

#include <vespa/log/log.h>
LOG_SETUP(".rpcnetwork");

using vespalib::make_string;
using namespace std::chrono_literals;

namespace {

/**
 * Implements a helper class for {@link RPCNetwork#sync()}. It provides a
 * blocking method {@link #await()} that will wait until the internal state
 * of this object is set to 'done'. By scheduling this task in the network
 * thread and then calling this method, we achieve handshaking with the network
 * thread.
 */
class SyncTask : public FNET_Task {
private:
    vespalib::Gate _gate;

public:
    SyncTask(FNET_Scheduler &s) :
        FNET_Task(&s),
        _gate() {
        ScheduleNow();
    }
    ~SyncTask() override = default;

    void await() {
        _gate.await();
    }

    void PerformTask() override {
        _gate.countDown();
    }
};

} // namespace <unnamed>

namespace mbus {

RPCNetwork::SendContext::SendContext(RPCNetwork &net, const Message &msg,
                                     const std::vector<RoutingNode*> &recipients)
    : _net(net),
      _msg(msg),
      _traceLevel(msg.getTrace().getLevel()),
      _recipients(recipients),
      _hasError(false),
      _pending(_recipients.size()),
      _version(_net.getVersion())
{ }

void
RPCNetwork::SendContext::handleVersion(const vespalib::Version *version)
{
    bool shouldSend = false;
    {
        vespalib::LockGuard guard(_lock);
        if (version == nullptr) {
            _hasError = true;
        } else if (*version < _version) {
            _version = *version;
        }
        if (--_pending == 0) {
            shouldSend = true;
        }
    }
    if (shouldSend) {
        _net.send(*this);
        delete this;
    }
}

RPCNetwork::TargetPoolTask::TargetPoolTask(FNET_Scheduler &scheduler, RPCTargetPool &pool)
    : FNET_Task(&scheduler),
      _pool(pool)
{
    ScheduleNow();
}

void
RPCNetwork::TargetPoolTask::PerformTask()
{
    _pool.flushTargets(false);
    Schedule(1.0);
}

RPCNetwork::RPCNetwork(const RPCNetworkParams &params) :
    _owner(nullptr),
    _ident(params.getIdentity()),
    _threadPool(std::make_unique<FastOS_ThreadPool>(128000, 0)),
    _transport(std::make_unique<FNET_Transport>()),
    _orb(std::make_unique<FRT_Supervisor>(_transport.get())),
    _scheduler(*_transport->GetScheduler()),
    _targetPool(std::make_unique<RPCTargetPool>(params.getConnectionExpireSecs())),
    _targetPoolTask(_scheduler, *_targetPool),
    _servicePool(std::make_unique<RPCServicePool>(*this, 4096)),
    _slobrokCfgFactory(std::make_unique<slobrok::ConfiguratorFactory>(params.getSlobrokConfig())),
    _mirror(std::make_unique<slobrok::api::MirrorAPI>(*_orb, *_slobrokCfgFactory)),
    _regAPI(std::make_unique<slobrok::api::RegisterAPI>(*_orb, *_slobrokCfgFactory)),
    _requestedPort(params.getListenPort()),
    _executor(std::make_unique<vespalib::ThreadStackExecutor>(params.getNumThreads(), 65536)),
    _sendV1(std::make_unique<RPCSendV1>()),
    _sendV2(std::make_unique<RPCSendV2>()),
    _sendAdapters(),
    _compressionConfig(params.getCompressionConfig()),
    _allowDispatchForEncode(params.getDispatchOnEncode()),
    _allowDispatchForDecode(params.getDispatchOnDecode())
{
    _transport->SetMaxInputBufferSize(params.getMaxInputBufferSize());
    _transport->SetMaxOutputBufferSize(params.getMaxOutputBufferSize());
}

RPCNetwork::~RPCNetwork()
{
    shutdown();
}

FRT_RPCRequest *
RPCNetwork::allocRequest()
{
    return _orb->AllocRPCRequest();
}

RPCTarget::SP
RPCNetwork::getTarget(const RPCServiceAddress &address)
{
    return _targetPool->getTarget(*_orb, address);
}

void
RPCNetwork::replyError(const SendContext &ctx, uint32_t errCode, const string &errMsg)
{
    for (RoutingNode * rnode : ctx._recipients) {
        Reply::UP reply(new EmptyReply());
        reply->setTrace(Trace(ctx._traceLevel));
        reply->addError(Error(errCode, errMsg));
        _owner->deliverReply(std::move(reply), *rnode);
    }
}

int RPCNetwork::getPort() const { return _orb->GetListenPort(); }

void
RPCNetwork::flushTargetPool()
{
    _targetPool->flushTargets(true);
}

const vespalib::Version &
RPCNetwork::getVersion() const
{
    return vespalib::Vtag::currentVersion;
}

void
RPCNetwork::attach(INetworkOwner &owner)
{
    LOG_ASSERT(_owner == nullptr);
    _owner = &owner;

    _sendV1->attach(*this);
    _sendV2->attach(*this);
    _sendAdapters[vespalib::Version(5)] = _sendV1.get();
    _sendAdapters[vespalib::Version(6, 149)] = _sendV2.get();

    FRT_ReflectionBuilder builder(_orb.get());
    builder.DefineMethod("mbus.getVersion", "", "s", FRT_METHOD(RPCNetwork::invoke), this);
    builder.MethodDesc("Retrieves the message bus version.");
    builder.ReturnDesc("version", "The message bus version.");
}

void
RPCNetwork::invoke(FRT_RPCRequest *req)
{
    req->GetReturn()->AddString(getVersion().toString().c_str());
}

const string
RPCNetwork::getConnectionSpec() const
{
    return make_string("tcp/%s:%d", _ident.getHostname().c_str(), _orb->GetListenPort());
}

RPCSendAdapter *
RPCNetwork::getSendAdapter(const vespalib::Version &version)
{
    if (version < _sendAdapters.begin()->first) {
        return nullptr;
    }
    return (--_sendAdapters.upper_bound(version))->second;
}

bool
RPCNetwork::start()
{
    if (!_transport->Start(_threadPool.get())) {
        return false;
    }
    if (!_orb->Listen(_requestedPort)) {
        return false;
    }
    return true;
}

bool
RPCNetwork::waitUntilReady(duration timeout) const
{
    slobrok::api::SlobrokList brokerList;
    slobrok::Configurator::UP configurator = _slobrokCfgFactory->create(brokerList);
    bool hasConfig = false;
    for (int64_t i = 0; i < vespalib::count_ms(timeout)/10; ++i) {
        if (configurator->poll()) {
            hasConfig = true;
        }
        if (_mirror->ready()) {
            return true;
        }
        std::this_thread::sleep_for(10ms);
    }
    if (! hasConfig) {
        LOG(error, "failed to get config for slobroks in %2.2f seconds", vespalib::to_s(timeout));
    } else if (! _mirror->ready()) {
        auto brokers = brokerList.logString();
        LOG(error, "mirror (of %s) failed to become ready in %2.2f seconds", brokers.c_str(), vespalib::to_s(timeout));
    }
    return false;
}

void
RPCNetwork::registerSession(const string &session)
{
    if (_ident.getServicePrefix().empty()) {
        LOG(warning, "The session (%s) will not be registered in the Slobrok since this network has no identity.",
            session.c_str());
        return;
    }
    string name = _ident.getServicePrefix();
    name += "/";
    name += session;
    _regAPI->registerName(name);
}

void
RPCNetwork::unregisterSession(const string &session)
{
    if (_ident.getServicePrefix().empty()) {
        return;
    }
    string name = _ident.getServicePrefix();
    name += "/";
    name += session;
    _regAPI->unregisterName(name);
}

bool
RPCNetwork::allocServiceAddress(RoutingNode &recipient)
{
    const Hop &hop = recipient.getRoute().getHop(0);
    string service = hop.getServiceName();
    Error error = resolveServiceAddress(recipient, service);
    if (error.getCode() == ErrorCode::NONE) {
        return true; // service address resolved
    }
    recipient.setError(error);
    return false; // service adddress not resolved
}

Error
RPCNetwork::resolveServiceAddress(RoutingNode &recipient, const string &serviceName)
{
    RPCServiceAddress::UP ret = _servicePool->resolve(serviceName);
    if ( ! ret) {
        return Error(ErrorCode::NO_ADDRESS_FOR_SERVICE,
                     make_string("The address of service '%s' could not be resolved. It is not currently "
                                 "registered with the Vespa name server. "
                                 "The service must be having problems, or the routing configuration is wrong. "
                                 "Address resolution attempted from host '%s'",
                                 serviceName.c_str(), getIdentity().getHostname().c_str()));
    }
    RPCTarget::SP target = _targetPool->getTarget(*_orb, *ret);
    if ( ! target) {
        return Error(ErrorCode::CONNECTION_ERROR,
                     make_string("Failed to connect to service '%s' from host '%s'.",
                                 serviceName.c_str(), getIdentity().getHostname().c_str()));
    }
    ret->setTarget(std::move(target)); // free by freeServiceAddress()
    recipient.setServiceAddress(std::move(ret));
    return Error();
}

void
RPCNetwork::freeServiceAddress(RoutingNode &recipient)
{
    recipient.setServiceAddress(IServiceAddress::UP());
}

void
RPCNetwork::send(const Message &msg, const std::vector<RoutingNode*> &recipients)
{
    SendContext &ctx = *(new SendContext(*this, msg, recipients)); // deletes self
    duration timeout = ctx._msg.getTimeRemainingNow();
    for (uint32_t i = 0, len = ctx._recipients.size(); i < len; ++i) {
        RoutingNode *&recipient = ctx._recipients[i];

        RPCServiceAddress &address = static_cast<RPCServiceAddress&>(recipient->getServiceAddress());
        LOG_ASSERT(address.hasTarget());

        address.getTarget().resolveVersion(timeout, ctx);
    }
}

namespace {

void
emit_recipient_endpoint(vespalib::asciistream& stream, const RoutingNode& recipient) {
    if (recipient.hasServiceAddress()) {
        // At this point the service addresses _should_ be RPCServiceAddress instances,
        // but stay on the safe side of the tracks anyway.
        const auto* rpc_addr = dynamic_cast<const RPCServiceAddress*>(&recipient.getServiceAddress());
        if (rpc_addr) {
            stream << rpc_addr->getServiceName() << " at " << rpc_addr->getConnectionSpec();
        } else {
            stream << "<non-RPC service address>";
        }
    } else {
        stream << "<unknown service address>";
    }
}

}

vespalib::string
RPCNetwork::buildRecipientListString(const SendContext& ctx) {
    vespalib::asciistream s;
    bool first = true;
    for (const auto* recipient : ctx._recipients) {
        if (!first) {
            s << ", ";
        }
        first = false;
        emit_recipient_endpoint(s, *recipient);
    }
    return s.str();
}

void
RPCNetwork::send(RPCNetwork::SendContext &ctx)
{
    if (ctx._hasError) {
        replyError(ctx, ErrorCode::HANDSHAKE_FAILED,
                make_string("An error occurred while resolving version of recipient(s) [%s] from host '%s'.",
                            buildRecipientListString(ctx).c_str(), getIdentity().getHostname().c_str()));
    } else {
        duration timeRemaining = ctx._msg.getTimeRemainingNow();
        Blob payload = _owner->getProtocol(ctx._msg.getProtocol())->encode(ctx._version, ctx._msg);
        RPCSendAdapter *adapter = getSendAdapter(ctx._version);
        if (adapter == nullptr) {
            replyError(ctx, ErrorCode::INCOMPATIBLE_VERSION,
                       make_string("Can not send to version '%s' recipient.", ctx._version.toString().c_str()));
        } else if (timeRemaining == 0ms) {
            replyError(ctx, ErrorCode::TIMEOUT, "Aborting transmission because zero time remains.");
        } else if (payload.size() == 0) {
            replyError(ctx, ErrorCode::ENCODE_ERROR,
                       make_string("Protocol '%s' failed to encode message.", ctx._msg.getProtocol().c_str()));
        } else if (ctx._recipients.size() == 1) {
            adapter->sendByHandover(*ctx._recipients.front(), ctx._version, std::move(payload), timeRemaining);
        } else {
            for (auto & recipient : ctx._recipients) {
                adapter->send(*recipient, ctx._version, payload, timeRemaining);
            }
        }
    }
}

void
RPCNetwork::sync()
{
    SyncTask task(_scheduler);
    _executor->sync();
    task.await();
}

void
RPCNetwork::shutdown()
{
    _transport->ShutDown(true);
    _threadPool->Close();
    _executor->shutdown();
    _executor->sync();
}

void
RPCNetwork::postShutdownHook()
{
    _scheduler.CheckTasks();
}

const slobrok::api::IMirrorAPI &
RPCNetwork::getMirror() const
{
    return *_mirror;
}

} // namespace mbus
<|endoftext|>


<commit_before>#include "CommandRequestProcessor.h"
#include "CommandRequest.h"

#include <sstream>

#include <FileXMLBufferReader.h>
#include <NMXmlParser.h>

using namespace opencog;

CommandRequestProcessor::~CommandRequestProcessor() {
}

CommandRequestProcessor::CommandRequestProcessor() {
}

std::string CommandRequestProcessor::load(std::string fileName)
{
    std::string msg = "load successful";
    AtomSpace *atomSpace = CogServer::getAtomSpace();
    std::vector<XMLBufferReader*> readers(1, new FileXMLBufferReader(fileName.c_str()));
    try {
        NMXmlParser::loadXML(readers, atomSpace);
    }
    catch (IOException &e)
    {
        msg = "load failed: ";
        msg += e.getMessage();
    }
    delete readers[0];
    return msg;
}

std::string CommandRequestProcessor::ls() {

    AtomSpace *atomSpace = CogServer::getAtomSpace();;

    ostringstream stream;
    atomSpace->print(stream, NODE, true);
    atomSpace->print(stream, LINK, true);
    std::string answer = stream.str();

    /*
    std::vector<Handle> nodes;
    atomSpace->getHandleSet(back_inserter(nodes), NODE, true);

    std::vector<Handle> links;
    atomSpace->getHandleSet(back_inserter(links), LINK, true);

    std::string answer;

    for (unsigned int i = 0; i < nodes.size(); i++) {
        answer.append(atomSpace->getName(atomSpace->getType(nodes[i])));
        answer.append(": ");
        answer.append(atomSpace->getName(nodes[i]));
        answer.append("\n");
    }

    for (unsigned int i = 0; i < links.size(); i++) {
        answer.append(atomSpace->getName(links[i]));
        answer.append("(");
        const HandleSeq &linkedAtoms = atomSpace->getOutgoing(links[i]);
        for (unsigned int i = 0; i < linkedAtoms.size(); i++) {
            if (atomSpace->isNode(linkedAtoms[i])) {
                answer.append(atomSpace->getName(linkedAtoms[i]));
            } else {
                answer.append("<link>");
            }
            if (i != (linkedAtoms.size() - 1)) {
                answer.append(" ");
            }
        }
        answer.append(")");
        answer.append("\n");
    }
    */

    return answer;

}

void CommandRequestProcessor::processRequest(CogServerRequest *request)
{
    std::string command = ((CommandRequest *) request)->getCommand();
    std::queue<std::string> args = ((CommandRequest *) request)->getArgs();
    std::string answer;

    if (command == "load") {
        if (args.size() != 1) {
            answer = "invalid command syntax";
        } else {
            answer = load(args.front());
        }
    } else if (command == "ls") {
        if (args.size() != 0) {
            answer = "invalid command syntax";
        } else {
            answer = ls();
        }
    } else if (command == "shutdown") {
        if (args.size() != 0) {
            answer = "invalid command syntax";
        } else {
            exit(0);
        }
    } else {
        answer = "unknown command\n\tAvailable commands: load ls shutdown";
    }

    ((CommandRequest *) request)->setAnswer(answer);
    request->callBack();

    /*
     // Debug code
    answer = "processed command " + command + "(";
    while (! args.empty()) {
        answer.append(args.front());
        args.pop();
        if (! args.empty()) {
            answer.append(",");
        }
    }
    answer.append(")");
    ((CommandRequest *) request)->setAnswer(answer);
    request->callBack();
    */
}
<commit_msg>broaden classes of exceptions that can be caught<commit_after>#include "CommandRequestProcessor.h"
#include "CommandRequest.h"

#include <sstream>

#include <FileXMLBufferReader.h>
#include <NMXmlParser.h>

using namespace opencog;

CommandRequestProcessor::~CommandRequestProcessor() {
}

CommandRequestProcessor::CommandRequestProcessor() {
}

std::string CommandRequestProcessor::load(std::string fileName)
{
    std::string msg = "load successful";
    AtomSpace *atomSpace = CogServer::getAtomSpace();
    std::vector<XMLBufferReader*> readers(1, new FileXMLBufferReader(fileName.c_str()));
    try {
        NMXmlParser::loadXML(readers, atomSpace);
    }
    // Can catch IOException, for file not found, or
    // RuntimeException, for bad file format.
    catch (StandardException &e)
    {
        msg = "xload failed: ";
        msg += e.getMessage();
    }
    delete readers[0];
    return msg;
}

std::string CommandRequestProcessor::ls() {

    AtomSpace *atomSpace = CogServer::getAtomSpace();;

    ostringstream stream;
    atomSpace->print(stream, NODE, true);
    atomSpace->print(stream, LINK, true);
    std::string answer = stream.str();

    /*
    std::vector<Handle> nodes;
    atomSpace->getHandleSet(back_inserter(nodes), NODE, true);

    std::vector<Handle> links;
    atomSpace->getHandleSet(back_inserter(links), LINK, true);

    std::string answer;

    for (unsigned int i = 0; i < nodes.size(); i++) {
        answer.append(atomSpace->getName(atomSpace->getType(nodes[i])));
        answer.append(": ");
        answer.append(atomSpace->getName(nodes[i]));
        answer.append("\n");
    }

    for (unsigned int i = 0; i < links.size(); i++) {
        answer.append(atomSpace->getName(links[i]));
        answer.append("(");
        const HandleSeq &linkedAtoms = atomSpace->getOutgoing(links[i]);
        for (unsigned int i = 0; i < linkedAtoms.size(); i++) {
            if (atomSpace->isNode(linkedAtoms[i])) {
                answer.append(atomSpace->getName(linkedAtoms[i]));
            } else {
                answer.append("<link>");
            }
            if (i != (linkedAtoms.size() - 1)) {
                answer.append(" ");
            }
        }
        answer.append(")");
        answer.append("\n");
    }
    */

    return answer;

}

void CommandRequestProcessor::processRequest(CogServerRequest *request)
{
    std::string command = ((CommandRequest *) request)->getCommand();
    std::queue<std::string> args = ((CommandRequest *) request)->getArgs();
    std::string answer;

    if (command == "load") {
        if (args.size() != 1) {
            answer = "invalid command syntax";
        } else {
            answer = load(args.front());
        }
    } else if (command == "ls") {
        if (args.size() != 0) {
            answer = "invalid command syntax";
        } else {
            answer = ls();
        }
    } else if (command == "shutdown") {
        if (args.size() != 0) {
            answer = "invalid command syntax";
        } else {
            exit(0);
        }
    } else {
        answer = "unknown command\n\tAvailable commands: load ls shutdown";
    }

    ((CommandRequest *) request)->setAnswer(answer);
    request->callBack();

    /*
     // Debug code
    answer = "processed command " + command + "(";
    while (! args.empty()) {
        answer.append(args.front());
        args.pop();
        if (! args.empty()) {
            answer.append(",");
        }
    }
    answer.append(")");
    ((CommandRequest *) request)->setAnswer(answer);
    request->callBack();
    */
}
<|endoftext|>


<commit_before>#include <GLUL/Logger.h>
#include <GLUL/GL++/Program.h>
#include <GLUL/GL++/VertexArray.h>
#include <GLUL/GL++/VertexBuffer.h>
#include <GLUL/GUI/Font.h>
#include <GLUL/GUI/Text.h>
#include <GLUL/GUI/Window.h>

#include <vector>

/**
 * Initialize functions
 */

void initFont(GLUL::GUI::Font& font, const std::string& fontName, int size) {
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    font.load("assets/fonts/" + fontName + ".ttf", size);
}

void initVertices(std::vector<glm::vec4>& vertices, const GLUL::GUI::Font& font) {
    // Display whole texture
    float xS = 0.0f;
    float xE = 1.0f;
    float yS = 1.0f;
    float yE = 0.0f;

    (void) font;

    /*
    // Display only one character
    char character = '@';
    float xS = font.getMetric(character).texPosStart.x;
    float yS = font.getMetric(character).texPosStart.y;
    float xE = font.getMetric(character).texPosEnd.x;
    float yE = font.getMetric(character).texPosEnd.y;
    */

    vertices.push_back(glm::vec4(-0.9f, -0.3f, xS, yS));
    vertices.push_back(glm::vec4( 0.9f, -0.3f, xE, yS));
    vertices.push_back(glm::vec4(-0.9f,  0.3f, xS, yE));

    vertices.push_back(glm::vec4(-0.9f,  0.3f, xS, yE));
    vertices.push_back(glm::vec4( 0.9f, -0.3f, xE, yS));
    vertices.push_back(glm::vec4( 0.9f,  0.3f, xE, yE));
}

void initProgram(GL::Program& program) {
    program.load(
        GL::Shader("assets/shaders/font.vp", GL::Shader::Type::VertexShader),
        GL::Shader("assets/shaders/font.fp", GL::Shader::Type::FragmentShader)
    );
}

void initVBO(GL::VertexBuffer& vbo, std::vector<glm::vec4>& vertices) {
    GL::VertexBuffer::Data vertexData;

    // VertexData
    vertexData.data = vertices.data();
    vertexData.size = sizeof(glm::vec4) * vertices.size();
    vertexData.pointers.push_back(GL::VertexAttrib(0, 4, GL_FLOAT, 0, 0));

    // VBO settings
    vbo.bind();
        vbo.setData(vertexData);
    vbo.unbind();
}

void initVAO(GL::VertexArray& vao, const GL::VertexBuffer& vbo, const std::vector<glm::vec4>& vertices) {
    vao.setDrawCount(vertices.size());
    vao.setDrawTarget(GL::VertexArray::DrawTarget::Triangles);

    vao.bind();
        vao.attachVBO(&vbo);
        vao.setAttribPointers();
    vao.unbind();
}

/**
 * Main loop
 */
void run() {
    GLUL::GUI::Window window(800, 600, "Title"); // Be advised - GUI-supporting Window is GLUL::GUI::Window, not GLUL::Window !

    GL::Program program;
    GL::VertexArray vao;
    GL::VertexBuffer vbo;
    std::vector<glm::vec4> vertices;

    GLUL::GUI::Font fontAtlas;
    GLUL::GUI::Font fontText1;
    GLUL::GUI::Font fontText2;
    GLUL::GUI::Text textHeader;
    GLUL::GUI::Text textFooter1;
    GLUL::GUI::Text textFooter2;

    window.create();
    window.getContext().setClearColor(glm::vec4(0.1f, 0.1, 0.1, 1.0f));

    // loading fonts
    initFont(fontAtlas, "arial", 128);
    initFont(fontText1, "verdanai", 16);
    initFont(fontText2, "verdanai", 32);

    // set textHeader object
    textHeader.setFont(fontText2);
    textHeader.setText("Hello world!\nSecond line. Tab: '\t'\n\nTexture with font's glyphs:");
    textHeader.setColor(glm::vec4(1.0f, 0.7f, 0.3f, 1.0f));
    textHeader.setPosition(glm::vec2(200.0f, 40.0f));
    textHeader.bindTo(window);

    // set textFooter1 object
    textFooter1.setFont(fontText1);
    textFooter1.setText("Text using font with size 16");
    textFooter1.setColor(glm::vec4(0.2f, 0.5f, 0.7f, 1.0f));
    textFooter1.setPosition(glm::vec2(200.0f, 480.0f));
    textFooter1.bindTo(window);

    // set textFooter2 object
    textFooter2.setFont(fontText2);
    textFooter2.setText("Text using font with size 32 scaled to 16");
    textFooter2.setColor(glm::vec4(0.2f, 0.5f, 0.7f, 1.0f));
    textFooter2.setPosition(glm::vec2(200.0f, 500.0f));
    textFooter2.setSize(16);
    textFooter2.bindTo(window);

    initVertices(vertices, fontAtlas);
    initProgram(program);
    initVBO(vbo, vertices);
    initVAO(vao, vbo, vertices);

    while(window.isCreated() && window.shouldClose() == false) {
        window.getContext().clearBuffers(GL::Context::BufferMask::Color);

        fontAtlas.getTexture().bind();

        program.use();
        program["texSampler"].setSampler(0);

            vao.bind();
            vao.drawArrays();
            vao.unbind();

        program.unbind();
        fontAtlas.getTexture().unbind();

        window.render();
        window.update();
    }
}

/**
 * Start of application
 */
int main() {
    try {
        run();

    } catch(const GLUL::Exception::FatalError& exception) {
        GLUL::Log::Stream("Example", "logExample.log") << "Cought fatal error exception: " + std::string(exception.what());
        return 1;

    } catch(const std::exception& exception) {
        GLUL::Log::Stream("Example", "logExample.log") << "Cought std::exception: " + std::string(exception.what());
        return 1;

    } catch(...) {
        GLUL::Log::Stream("Example", "logExample.log") << "Cought unknown exception!";
        return 1;
    }

    return 0;
}
<commit_msg>Fixed ambiguous VertexAttrib constructor call.<commit_after>#include <GLUL/Logger.h>
#include <GLUL/GL++/Program.h>
#include <GLUL/GL++/VertexArray.h>
#include <GLUL/GL++/VertexBuffer.h>
#include <GLUL/GUI/Font.h>
#include <GLUL/GUI/Text.h>
#include <GLUL/GUI/Window.h>

#include <vector>

/**
 * Initialize functions
 */

void initFont(GLUL::GUI::Font& font, const std::string& fontName, int size) {
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    font.load("assets/fonts/" + fontName + ".ttf", size);
}

void initVertices(std::vector<glm::vec4>& vertices, const GLUL::GUI::Font& font) {
    // Display whole texture
    float xS = 0.0f;
    float xE = 1.0f;
    float yS = 1.0f;
    float yE = 0.0f;

    (void) font;

    /*
    // Display only one character
    char character = '@';
    float xS = font.getMetric(character).texPosStart.x;
    float yS = font.getMetric(character).texPosStart.y;
    float xE = font.getMetric(character).texPosEnd.x;
    float yE = font.getMetric(character).texPosEnd.y;
    */

    vertices.push_back(glm::vec4(-0.9f, -0.3f, xS, yS));
    vertices.push_back(glm::vec4( 0.9f, -0.3f, xE, yS));
    vertices.push_back(glm::vec4(-0.9f,  0.3f, xS, yE));

    vertices.push_back(glm::vec4(-0.9f,  0.3f, xS, yE));
    vertices.push_back(glm::vec4( 0.9f, -0.3f, xE, yS));
    vertices.push_back(glm::vec4( 0.9f,  0.3f, xE, yE));
}

void initProgram(GL::Program& program) {
    program.load(
        GL::Shader("assets/shaders/font.vp", GL::Shader::Type::VertexShader),
        GL::Shader("assets/shaders/font.fp", GL::Shader::Type::FragmentShader)
    );
}

void initVBO(GL::VertexBuffer& vbo, std::vector<glm::vec4>& vertices) {
    GL::VertexBuffer::Data vertexData;

    // VertexData
    vertexData.data = vertices.data();
    vertexData.size = sizeof(glm::vec4) * vertices.size();
    vertexData.pointers.push_back(GL::VertexAttrib(0, 4, GL_FLOAT, 0, nullptr));

    // VBO settings
    vbo.bind();
        vbo.setData(vertexData);
    vbo.unbind();
}

void initVAO(GL::VertexArray& vao, const GL::VertexBuffer& vbo, const std::vector<glm::vec4>& vertices) {
    vao.setDrawCount(vertices.size());
    vao.setDrawTarget(GL::VertexArray::DrawTarget::Triangles);

    vao.bind();
        vao.attachVBO(&vbo);
        vao.setAttribPointers();
    vao.unbind();
}

/**
 * Main loop
 */
void run() {
    GLUL::GUI::Window window(800, 600, "Title"); // Be advised - GUI-supporting Window is GLUL::GUI::Window, not GLUL::Window !

    GL::Program program;
    GL::VertexArray vao;
    GL::VertexBuffer vbo;
    std::vector<glm::vec4> vertices;

    GLUL::GUI::Font fontAtlas;
    GLUL::GUI::Font fontText1;
    GLUL::GUI::Font fontText2;
    GLUL::GUI::Text textHeader;
    GLUL::GUI::Text textFooter1;
    GLUL::GUI::Text textFooter2;

    window.create();
    window.getContext().setClearColor(glm::vec4(0.1f, 0.1, 0.1, 1.0f));

    // loading fonts
    initFont(fontAtlas, "arial", 128);
    initFont(fontText1, "verdanai", 16);
    initFont(fontText2, "verdanai", 32);

    // set textHeader object
    textHeader.setFont(fontText2);
    textHeader.setText("Hello world!\nSecond line. Tab: '\t'\n\nTexture with font's glyphs:");
    textHeader.setColor(glm::vec4(1.0f, 0.7f, 0.3f, 1.0f));
    textHeader.setPosition(glm::vec2(200.0f, 40.0f));
    textHeader.bindTo(window);

    // set textFooter1 object
    textFooter1.setFont(fontText1);
    textFooter1.setText("Text using font with size 16");
    textFooter1.setColor(glm::vec4(0.2f, 0.5f, 0.7f, 1.0f));
    textFooter1.setPosition(glm::vec2(200.0f, 480.0f));
    textFooter1.bindTo(window);

    // set textFooter2 object
    textFooter2.setFont(fontText2);
    textFooter2.setText("Text using font with size 32 scaled to 16");
    textFooter2.setColor(glm::vec4(0.2f, 0.5f, 0.7f, 1.0f));
    textFooter2.setPosition(glm::vec2(200.0f, 500.0f));
    textFooter2.setSize(16);
    textFooter2.bindTo(window);

    initVertices(vertices, fontAtlas);
    initProgram(program);
    initVBO(vbo, vertices);
    initVAO(vao, vbo, vertices);

    while(window.isCreated() && window.shouldClose() == false) {
        window.getContext().clearBuffers(GL::Context::BufferMask::Color);

        fontAtlas.getTexture().bind();

        program.use();
        program["texSampler"].setSampler(0);

            vao.bind();
            vao.drawArrays();
            vao.unbind();

        program.unbind();
        fontAtlas.getTexture().unbind();

        window.render();
        window.update();
    }
}

/**
 * Start of application
 */
int main() {
    try {
        run();

    } catch(const GLUL::Exception::FatalError& exception) {
        GLUL::Log::Stream("Example", "logExample.log") << "Cought fatal error exception: " + std::string(exception.what());
        return 1;

    } catch(const std::exception& exception) {
        GLUL::Log::Stream("Example", "logExample.log") << "Cought std::exception: " + std::string(exception.what());
        return 1;

    } catch(...) {
        GLUL::Log::Stream("Example", "logExample.log") << "Cought unknown exception!";
        return 1;
    }

    return 0;
}
<|endoftext|>


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

#include "chrome/browser/views/location_bar/page_action_image_view.h"

#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/extensions/extension_browser_event_router.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/views/frame/browser_view.h"
#include "chrome/browser/views/location_bar/location_bar_view.h"
#include "chrome/browser/platform_util.h"
#include "chrome/common/extensions/extension_action.h"
#include "chrome/common/extensions/extension_resource.h"
#include "views/controls/menu/menu_2.h"

PageActionImageView::PageActionImageView(LocationBarView* owner,
                                         Profile* profile,
                                         ExtensionAction* page_action)
    : owner_(owner),
      profile_(profile),
      page_action_(page_action),
      ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)),
      current_tab_id_(-1),
      preview_enabled_(false),
      popup_(NULL) {
  const Extension* extension = profile->GetExtensionService()->
      GetExtensionById(page_action->extension_id(), false);
  DCHECK(extension);

  // Load all the icons declared in the manifest. This is the contents of the
  // icons array, plus the default_icon property, if any.
  std::vector<std::string> icon_paths(*page_action->icon_paths());
  if (!page_action_->default_icon_path().empty())
    icon_paths.push_back(page_action_->default_icon_path());

  for (std::vector<std::string>::iterator iter = icon_paths.begin();
       iter != icon_paths.end(); ++iter) {
    tracker_.LoadImage(extension, extension->GetResource(*iter),
                       gfx::Size(Extension::kPageActionIconMaxSize,
                                 Extension::kPageActionIconMaxSize),
                       ImageLoadingTracker::DONT_CACHE);
  }

  set_accessibility_focusable(true);
}

PageActionImageView::~PageActionImageView() {
  if (popup_)
    HidePopup();
}

void PageActionImageView::ExecuteAction(int button,
                                        bool inspect_with_devtools) {
  if (current_tab_id_ < 0) {
    NOTREACHED() << "No current tab.";
    return;
  }

  if (page_action_->HasPopup(current_tab_id_)) {
    // In tests, GetLastActive could return NULL, so we need to have
    // a fallback.
    // TODO(erikkay): Find a better way to get the Browser that this
    // button is in.
    Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
    if (!browser)
      browser = BrowserList::FindBrowserWithProfile(profile_);
    DCHECK(browser);

    bool popup_showing = popup_ != NULL;

    // Always hide the current popup. Only one popup at a time.
    HidePopup();

    // If we were already showing, then treat this click as a dismiss.
    if (popup_showing)
      return;

    gfx::Rect screen_bounds(GetImageBounds());
    gfx::Point origin(screen_bounds.origin());
    View::ConvertPointToScreen(this, &origin);
    screen_bounds.set_origin(origin);

    popup_ = ExtensionPopup::Show(
        page_action_->GetPopupUrl(current_tab_id_),
        browser,
        browser->profile(),
        browser->window()->GetNativeHandle(),
        screen_bounds,
        BubbleBorder::TOP_RIGHT,
        true,  // Activate the popup window.
        inspect_with_devtools,
        ExtensionPopup::BUBBLE_CHROME,
        this);  // ExtensionPopup::Observer
  } else {
    ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted(
        profile_, page_action_->extension_id(), page_action_->id(),
        current_tab_id_, current_url_.spec(), button);
  }
}

AccessibilityTypes::Role PageActionImageView::GetAccessibleRole() {
  return AccessibilityTypes::ROLE_PUSHBUTTON;
}

bool PageActionImageView::OnMousePressed(const views::MouseEvent& event) {
  // We want to show the bubble on mouse release; that is the standard behavior
  // for buttons.  (Also, triggering on mouse press causes bugs like
  // http://crbug.com/33155.)
  return true;
}

void PageActionImageView::OnMouseReleased(const views::MouseEvent& event,
                                          bool canceled) {
  if (canceled || !HitTest(event.location()))
    return;

  int button = -1;
  if (event.IsLeftMouseButton()) {
    button = 1;
  } else if (event.IsMiddleMouseButton()) {
    button = 2;
  } else if (event.IsRightMouseButton()) {
    // Get the top left point of this button in screen coordinates.
    gfx::Point menu_origin;
    ConvertPointToScreen(this, &menu_origin);
    // Make the menu appear below the button.
    menu_origin.Offset(0, height());
    ShowContextMenu(menu_origin, true);
    return;
  }

  ExecuteAction(button, false);  // inspect_with_devtools
}

bool PageActionImageView::OnKeyPressed(const views::KeyEvent& e) {
  if (e.GetKeyCode() == app::VKEY_SPACE ||
      e.GetKeyCode() == app::VKEY_RETURN) {
    ExecuteAction(1, false);
    return true;
  }
  return false;
}

void PageActionImageView::ShowContextMenu(const gfx::Point& p,
                                          bool is_mouse_gesture) {
  const Extension* extension = profile_->GetExtensionService()->
      GetExtensionById(page_action()->extension_id(), false);
  Browser* browser = BrowserView::GetBrowserViewForNativeWindow(
      platform_util::GetTopLevel(GetWidget()->GetNativeView()))->browser();
  context_menu_contents_ =
      new ExtensionContextMenuModel(extension, browser, this);
  context_menu_menu_.reset(new views::Menu2(context_menu_contents_.get()));
  context_menu_menu_->RunContextMenuAt(p);
}

void PageActionImageView::OnImageLoaded(
    SkBitmap* image, ExtensionResource resource, int index) {
  // We loaded icons()->size() icons, plus one extra if the page action had
  // a default icon.
  int total_icons = static_cast<int>(page_action_->icon_paths()->size());
  if (!page_action_->default_icon_path().empty())
    total_icons++;
  DCHECK(index < total_icons);

  // Map the index of the loaded image back to its name. If we ever get an
  // index greater than the number of icons, it must be the default icon.
  if (image) {
    if (index < static_cast<int>(page_action_->icon_paths()->size()))
      page_action_icons_[page_action_->icon_paths()->at(index)] = *image;
    else
      page_action_icons_[page_action_->default_icon_path()] = *image;
  }

  // During object construction (before the parent has been set) we are already
  // in a UpdatePageActions call, so we don't need to start another one (and
  // doing so causes crash described in http://crbug.com/57333).
  if (GetParent())
    owner_->UpdatePageActions();
}

void PageActionImageView::UpdateVisibility(TabContents* contents,
                                           const GURL& url) {
  // Save this off so we can pass it back to the extension when the action gets
  // executed. See PageActionImageView::OnMousePressed.
  current_tab_id_ = contents ? ExtensionTabUtil::GetTabId(contents) : -1;
  current_url_ = url;

  if (!contents ||
      (!preview_enabled_ && !page_action_->GetIsVisible(current_tab_id_))) {
    SetVisible(false);
    return;
  }

  // Set the tooltip.
  tooltip_ = page_action_->GetTitle(current_tab_id_);
  SetTooltipText(UTF8ToWide(tooltip_));

  // Set the image.
  // It can come from three places. In descending order of priority:
  // - The developer can set it dynamically by path or bitmap. It will be in
  //   page_action_->GetIcon().
  // - The developer can set it dynamically by index. It will be in
  //   page_action_->GetIconIndex().
  // - It can be set in the manifest by path. It will be in
  //   page_action_->default_icon_path().

  // First look for a dynamically set bitmap.
  SkBitmap icon = page_action_->GetIcon(current_tab_id_);
  if (icon.isNull()) {
    int icon_index = page_action_->GetIconIndex(current_tab_id_);
    std::string icon_path = (icon_index < 0) ?
        page_action_->default_icon_path() :
        page_action_->icon_paths()->at(icon_index);
    if (!icon_path.empty()) {
      PageActionMap::iterator iter = page_action_icons_.find(icon_path);
      if (iter != page_action_icons_.end())
        icon = iter->second;
    }
  }
  if (!icon.isNull())
    SetImage(&icon);

  SetVisible(true);
}

void PageActionImageView::InspectPopup(ExtensionAction* action) {
  ExecuteAction(1,  // left-click
                true);  // inspect_with_devtools
}

void PageActionImageView::ExtensionPopupIsClosing(ExtensionPopup* popup) {
  DCHECK_EQ(popup_, popup);
  // ExtensionPopup is ref-counted, so we don't need to delete it.
  popup_ = NULL;
}

void PageActionImageView::HidePopup() {
  if (popup_)
    popup_->Close();
}
<commit_msg>Make Page Action popup bubble anchor its arrow on the left for RTL languages.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/views/location_bar/page_action_image_view.h"

#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/extensions/extension_browser_event_router.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/views/frame/browser_view.h"
#include "chrome/browser/views/location_bar/location_bar_view.h"
#include "chrome/browser/platform_util.h"
#include "chrome/common/extensions/extension_action.h"
#include "chrome/common/extensions/extension_resource.h"
#include "views/controls/menu/menu_2.h"

PageActionImageView::PageActionImageView(LocationBarView* owner,
                                         Profile* profile,
                                         ExtensionAction* page_action)
    : owner_(owner),
      profile_(profile),
      page_action_(page_action),
      ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)),
      current_tab_id_(-1),
      preview_enabled_(false),
      popup_(NULL) {
  const Extension* extension = profile->GetExtensionService()->
      GetExtensionById(page_action->extension_id(), false);
  DCHECK(extension);

  // Load all the icons declared in the manifest. This is the contents of the
  // icons array, plus the default_icon property, if any.
  std::vector<std::string> icon_paths(*page_action->icon_paths());
  if (!page_action_->default_icon_path().empty())
    icon_paths.push_back(page_action_->default_icon_path());

  for (std::vector<std::string>::iterator iter = icon_paths.begin();
       iter != icon_paths.end(); ++iter) {
    tracker_.LoadImage(extension, extension->GetResource(*iter),
                       gfx::Size(Extension::kPageActionIconMaxSize,
                                 Extension::kPageActionIconMaxSize),
                       ImageLoadingTracker::DONT_CACHE);
  }

  set_accessibility_focusable(true);
}

PageActionImageView::~PageActionImageView() {
  if (popup_)
    HidePopup();
}

void PageActionImageView::ExecuteAction(int button,
                                        bool inspect_with_devtools) {
  if (current_tab_id_ < 0) {
    NOTREACHED() << "No current tab.";
    return;
  }

  if (page_action_->HasPopup(current_tab_id_)) {
    // In tests, GetLastActive could return NULL, so we need to have
    // a fallback.
    // TODO(erikkay): Find a better way to get the Browser that this
    // button is in.
    Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
    if (!browser)
      browser = BrowserList::FindBrowserWithProfile(profile_);
    DCHECK(browser);

    bool popup_showing = popup_ != NULL;

    // Always hide the current popup. Only one popup at a time.
    HidePopup();

    // If we were already showing, then treat this click as a dismiss.
    if (popup_showing)
      return;

    gfx::Rect screen_bounds(GetImageBounds());
    gfx::Point origin(screen_bounds.origin());
    View::ConvertPointToScreen(this, &origin);
    screen_bounds.set_origin(origin);

    BubbleBorder::ArrowLocation arrow_location = base::i18n::IsRTL() ?
        BubbleBorder::TOP_LEFT : BubbleBorder::TOP_RIGHT;

    popup_ = ExtensionPopup::Show(
        page_action_->GetPopupUrl(current_tab_id_),
        browser,
        browser->profile(),
        browser->window()->GetNativeHandle(),
        screen_bounds,
        arrow_location,
        true,  // Activate the popup window.
        inspect_with_devtools,
        ExtensionPopup::BUBBLE_CHROME,
        this);  // ExtensionPopup::Observer
  } else {
    ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted(
        profile_, page_action_->extension_id(), page_action_->id(),
        current_tab_id_, current_url_.spec(), button);
  }
}

AccessibilityTypes::Role PageActionImageView::GetAccessibleRole() {
  return AccessibilityTypes::ROLE_PUSHBUTTON;
}

bool PageActionImageView::OnMousePressed(const views::MouseEvent& event) {
  // We want to show the bubble on mouse release; that is the standard behavior
  // for buttons.  (Also, triggering on mouse press causes bugs like
  // http://crbug.com/33155.)
  return true;
}

void PageActionImageView::OnMouseReleased(const views::MouseEvent& event,
                                          bool canceled) {
  if (canceled || !HitTest(event.location()))
    return;

  int button = -1;
  if (event.IsLeftMouseButton()) {
    button = 1;
  } else if (event.IsMiddleMouseButton()) {
    button = 2;
  } else if (event.IsRightMouseButton()) {
    // Get the top left point of this button in screen coordinates.
    gfx::Point menu_origin;
    ConvertPointToScreen(this, &menu_origin);
    // Make the menu appear below the button.
    menu_origin.Offset(0, height());
    ShowContextMenu(menu_origin, true);
    return;
  }

  ExecuteAction(button, false);  // inspect_with_devtools
}

bool PageActionImageView::OnKeyPressed(const views::KeyEvent& e) {
  if (e.GetKeyCode() == app::VKEY_SPACE ||
      e.GetKeyCode() == app::VKEY_RETURN) {
    ExecuteAction(1, false);
    return true;
  }
  return false;
}

void PageActionImageView::ShowContextMenu(const gfx::Point& p,
                                          bool is_mouse_gesture) {
  const Extension* extension = profile_->GetExtensionService()->
      GetExtensionById(page_action()->extension_id(), false);
  Browser* browser = BrowserView::GetBrowserViewForNativeWindow(
      platform_util::GetTopLevel(GetWidget()->GetNativeView()))->browser();
  context_menu_contents_ =
      new ExtensionContextMenuModel(extension, browser, this);
  context_menu_menu_.reset(new views::Menu2(context_menu_contents_.get()));
  context_menu_menu_->RunContextMenuAt(p);
}

void PageActionImageView::OnImageLoaded(
    SkBitmap* image, ExtensionResource resource, int index) {
  // We loaded icons()->size() icons, plus one extra if the page action had
  // a default icon.
  int total_icons = static_cast<int>(page_action_->icon_paths()->size());
  if (!page_action_->default_icon_path().empty())
    total_icons++;
  DCHECK(index < total_icons);

  // Map the index of the loaded image back to its name. If we ever get an
  // index greater than the number of icons, it must be the default icon.
  if (image) {
    if (index < static_cast<int>(page_action_->icon_paths()->size()))
      page_action_icons_[page_action_->icon_paths()->at(index)] = *image;
    else
      page_action_icons_[page_action_->default_icon_path()] = *image;
  }

  // During object construction (before the parent has been set) we are already
  // in a UpdatePageActions call, so we don't need to start another one (and
  // doing so causes crash described in http://crbug.com/57333).
  if (GetParent())
    owner_->UpdatePageActions();
}

void PageActionImageView::UpdateVisibility(TabContents* contents,
                                           const GURL& url) {
  // Save this off so we can pass it back to the extension when the action gets
  // executed. See PageActionImageView::OnMousePressed.
  current_tab_id_ = contents ? ExtensionTabUtil::GetTabId(contents) : -1;
  current_url_ = url;

  if (!contents ||
      (!preview_enabled_ && !page_action_->GetIsVisible(current_tab_id_))) {
    SetVisible(false);
    return;
  }

  // Set the tooltip.
  tooltip_ = page_action_->GetTitle(current_tab_id_);
  SetTooltipText(UTF8ToWide(tooltip_));

  // Set the image.
  // It can come from three places. In descending order of priority:
  // - The developer can set it dynamically by path or bitmap. It will be in
  //   page_action_->GetIcon().
  // - The developer can set it dynamically by index. It will be in
  //   page_action_->GetIconIndex().
  // - It can be set in the manifest by path. It will be in
  //   page_action_->default_icon_path().

  // First look for a dynamically set bitmap.
  SkBitmap icon = page_action_->GetIcon(current_tab_id_);
  if (icon.isNull()) {
    int icon_index = page_action_->GetIconIndex(current_tab_id_);
    std::string icon_path = (icon_index < 0) ?
        page_action_->default_icon_path() :
        page_action_->icon_paths()->at(icon_index);
    if (!icon_path.empty()) {
      PageActionMap::iterator iter = page_action_icons_.find(icon_path);
      if (iter != page_action_icons_.end())
        icon = iter->second;
    }
  }
  if (!icon.isNull())
    SetImage(&icon);

  SetVisible(true);
}

void PageActionImageView::InspectPopup(ExtensionAction* action) {
  ExecuteAction(1,  // left-click
                true);  // inspect_with_devtools
}

void PageActionImageView::ExtensionPopupIsClosing(ExtensionPopup* popup) {
  DCHECK_EQ(popup_, popup);
  // ExtensionPopup is ref-counted, so we don't need to delete it.
  popup_ = NULL;
}

void PageActionImageView::HidePopup() {
  if (popup_)
    popup_->Close();
}
<|endoftext|>