text:
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// 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/.

#include <config.h>

#include <mysql/mysql_connection.h>
#include <mysql/testutils/mysql_schema.h>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <gtest/gtest.h>
#include <array>

using namespace isc::db;
using namespace isc::db::test;

namespace {

/// @brief Test fixture class for @c MySqlConnection class.
class MySqlConnectionTest : public ::testing::Test {
public:

    /// @brief Indexes of prepared statements used within the tests.
    enum StatementIndex {
        GET_BY_INT_VALUE,
        DELETE_BY_INT_VALUE,
        INSERT_VALUE,
        NUM_STATEMENTS
    };

    /// @brief Array of tagged MySQL statements.
    typedef std::array<TaggedStatement, NUM_STATEMENTS>
    TaggedStatementArray;

    /// @brief Prepared MySQL statements used in the tests.
    TaggedStatementArray tagged_statements = { {
            { GET_BY_INT_VALUE,
              "SELECT tinyint_value, int_value, bigint_value, string_value,"
              " blob_value, timestamp_value"
              " FROM mysql_connection_test WHERE int_value = ?" },

            { DELETE_BY_INT_VALUE,
              "DELETE FROM mysql_connection_test WHERE int_value = ?" },

            { INSERT_VALUE,
              "INSERT INTO mysql_connection_test (tinyint_value, int_value,"
              "bigint_value, string_value, blob_value, timestamp_value)"
              " VALUES (?, ?, ?, ?, ?, ?)" }
    }
    };

    /// @brief Constructor.
    ///
    /// Re-creates database schema, opens new database connection and creates
    /// prepared statements used in tests. Created schema contains a test
    /// table @c mysql_connection_test which includes 6 columns of various
    /// types.
    MySqlConnectionTest()
        : conn_(DatabaseConnection::parse(validMySQLConnectionString())) {

        try {
            // Open new connection.
            conn_.openDatabase();
            my_bool result = mysql_autocommit(conn_.mysql_, 1);
            if (result != 0) {
                isc_throw(DbOperationError, "failed to set autocommit option "
                          "for test MySQL connection");
            }

            // Create mysql_connection_test table.
            createTestTable();

            // Created prepared statements for basic queries to test table.
            conn_.prepareStatements(tagged_statements.begin(),
                                    tagged_statements.end());

        } catch (...) {
            std::cerr << "*** ERROR: unable to open database. The test\n"
                         "*** environment is broken and must be fixed before\n"
                         "*** the MySQL tests will run correctly.\n"
                         "*** The reason for the problem is described in the\n"
                         "*** accompanying exception output.\n";
            throw;
        }
    }

    /// @brief Destructor
    ///
    /// Removes test table from the database.
    virtual ~MySqlConnectionTest() {
        conn_.rollback();
        dropTestTable();
    }

    /// @brief Creates test table @c mysql_connection_test.
    ///
    /// The new table contains 6 columns of various data types. All of
    /// the columns accept null values.
    void createTestTable() {
        runQuery("CREATE TABLE IF NOT EXISTS mysql_connection_test ("
                 "tinyint_value TINYINT NULL,"
                 "int_value INT NULL,"
                 "bigint_value BIGINT NULL,"
                 "string_value TEXT NULL,"
                 "blob_value BLOB NULL,"
                 "timestamp_value TIMESTAMP NULL"
                 ")");
    }

    /// @brief Drops test table.
    void dropTestTable() {
        runQuery("DROP TABLE IF EXISTS mysql_connection_test");
    }

    /// @brief Runs MySQL query on the opened connection.
    ///
    /// @param sql Query in the textual form.
    void runQuery(const std::string& sql) {
        MYSQL_STMT *stmt = mysql_stmt_init(conn_.mysql_);
        if (stmt == NULL) {
            isc_throw(DbOperationError, "unable to allocate MySQL prepared "
                  "statement structure, reason: " << mysql_error(conn_.mysql_));
        }

        int status = mysql_stmt_prepare(stmt, sql.c_str(), sql.length());
        if (status != 0) {
            isc_throw(DbOperationError, "unable to prepare MySQL statement <"
                      << sql << ">, reason: " << mysql_errno(conn_.mysql_));
        }

        // Execute the prepared statement.
        if (mysql_stmt_execute(stmt) != 0) {
            isc_throw(DbOperationError, "cannot execute MySQL query <"
                  << sql << ">, reason: " << mysql_errno(conn_.mysql_));
        }

        // Discard the statement and its resources
        mysql_stmt_close(stmt);
    }

    /// @brief Tests inserting and retrieving data from the database.
    ///
    /// In this test data carried in the bindings is inserted into the database.
    /// Then this data is retrieved from the database and compared with the
    /// orginal.
    ///
    /// @param in_bindings Collection of bindings encapsulating the data to
    /// be inserted into the database and then retrieved.
    void testInsertSelect(const MySqlBindingCollection& in_bindings) {
        // Expecting 6 bindings because we have 6 columns in our table.
        ASSERT_EQ(6, in_bindings.size());
        // We are going to select by int_value so this value must not be null.
        ASSERT_FALSE(in_bindings[1]->amNull());

        // Store data in the database.
        ASSERT_NO_THROW(conn_.insertQuery(MySqlConnectionTest::INSERT_VALUE,
                                          in_bindings));

        // Create input binding for select query.
        MySqlBindingCollection bindings =
            { MySqlBinding::createInteger<uint32_t>(in_bindings[1]->getInteger<uint32_t>()) };

        // Also, create output (placeholder) bindings for receiving data.
        MySqlBindingCollection out_bindings = {
            MySqlBinding::createInteger<uint8_t>(),
            MySqlBinding::createInteger<uint32_t>(),
            MySqlBinding::createInteger<int64_t>(),
            MySqlBinding::createString(512),
            MySqlBinding::createBlob(512),
            MySqlBinding::createTimestamp()
        };

        // Execute select statement. We expect one row to be returned. For this
        // returned row the lambda provided as 4th argument should be executed.
        ASSERT_NO_THROW(conn_.selectQuery(MySqlConnectionTest::GET_BY_INT_VALUE,
                                          bindings, out_bindings,
                                          [&](MySqlBindingCollection& out_bindings) {

            // Compare received data with input data assuming they are both non-null.

            if (!out_bindings[0]->amNull() && !in_bindings[0]->amNull()) {
                EXPECT_EQ(static_cast<int>(in_bindings[0]->getInteger<uint8_t>()),
                          static_cast<int>(out_bindings[0]->getInteger<uint8_t>()));
            }

            if (!out_bindings[1]->amNull() && !in_bindings[1]->amNull()) {
                EXPECT_EQ(in_bindings[1]->getInteger<uint32_t>(),
                          out_bindings[1]->getInteger<uint32_t>());
            }

            if (!out_bindings[2]->amNull() && !in_bindings[2]->amNull()) {
                EXPECT_EQ(in_bindings[2]->getInteger<int64_t>(),
                          out_bindings[2]->getInteger<int64_t>());
            }

            if (!out_bindings[3]->amNull() && !in_bindings[3]->amNull()) {
                EXPECT_EQ(in_bindings[3]->getString(),
                          out_bindings[3]->getString());
            }

            if (!out_bindings[4]->amNull() && !in_bindings[4]->amNull()) {
                EXPECT_EQ(in_bindings[4]->getBlob(),
                          out_bindings[4]->getBlob());
            }

            if (!out_bindings[5]->amNull() && !in_bindings[5]->amNull()) {
                EXPECT_TRUE(in_bindings[5]->getTimestamp() ==
                            out_bindings[5]->getTimestamp());
            }
        }));

        // Make sure that null values were returned for columns for which null
        // was set.
        ASSERT_EQ(in_bindings.size(), out_bindings.size());
        for (auto i = 0; i < in_bindings.size(); ++i) {
            EXPECT_EQ(in_bindings[i]->amNull(), out_bindings[i]->amNull())
                << "null value test failed for binding #" << i;
        }
    }

    /// @brief Test MySQL connection.
    MySqlConnection conn_;

};

// Test that non-null values of various types can be inserted and retrieved
// from the dataabse.
TEST_F(MySqlConnectionTest, select) {
    std::string blob = "myblob";
    MySqlBindingCollection in_bindings = {
        MySqlBinding::createInteger<uint8_t>(123),
        MySqlBinding::createInteger<uint32_t>(1024),
        MySqlBinding::createInteger<int64_t>(-4096),
        MySqlBinding::createString("shellfish"),
        MySqlBinding::createBlob(blob.begin(), blob.end()),
        MySqlBinding::createTimestamp(boost::posix_time::microsec_clock::universal_time())
    };

    testInsertSelect(in_bindings);
}

// Test that null value can be inserted to a column having numeric type and
// retrieved.
TEST_F(MySqlConnectionTest, selectNullInteger) {
    std::string blob = "myblob";
    MySqlBindingCollection in_bindings = {
        MySqlBinding::createNull(),
        MySqlBinding::createInteger<uint32_t>(1024),
        MySqlBinding::createInteger<int64_t>(-4096),
        MySqlBinding::createString("shellfish"),
        MySqlBinding::createBlob(blob.begin(), blob.end()),
        MySqlBinding::createTimestamp(boost::posix_time::microsec_clock::universal_time())
    };

    testInsertSelect(in_bindings);
}

// Test that null value can be inserted to a column having string type and
// retrieved.
TEST_F(MySqlConnectionTest, selectNullString) {
    std::string blob = "myblob";

    MySqlBindingCollection in_bindings = {
        MySqlBinding::createInteger<uint8_t>(123),
        MySqlBinding::createInteger<uint32_t>(1024),
        MySqlBinding::createInteger<int64_t>(-4096),
        MySqlBinding::createNull(),
        MySqlBinding::createBlob(blob.begin(), blob.end()),
        MySqlBinding::createTimestamp(boost::posix_time::microsec_clock::universal_time())
    };

    testInsertSelect(in_bindings);
}

// Test that null value can be inserted to a column having blob type and
// retrieved.
TEST_F(MySqlConnectionTest, selectNullBlob) {
    MySqlBindingCollection in_bindings = {
        MySqlBinding::createInteger<uint8_t>(123),
        MySqlBinding::createInteger<uint32_t>(1024),
        MySqlBinding::createInteger<int64_t>(-4096),
        MySqlBinding::createString("shellfish"),
        MySqlBinding::createNull(),
        MySqlBinding::createTimestamp(boost::posix_time::microsec_clock::universal_time())
    };

    testInsertSelect(in_bindings);
}

// Test that null value can be inserted to a column having timestamp type and
// retrieved.
TEST_F(MySqlConnectionTest, selectNullTimestamp) {
    std::string blob = "myblob";
    MySqlBindingCollection in_bindings = {
        MySqlBinding::createInteger<uint8_t>(123),
        MySqlBinding::createInteger<uint32_t>(1024),
        MySqlBinding::createInteger<int64_t>(-4096),
        MySqlBinding::createString("shellfish"),
        MySqlBinding::createBlob(blob.begin(), blob.end()),
        MySqlBinding::createNull()
    };

    testInsertSelect(in_bindings);
}

// Test that empty string and empty blob can be inserted to a database.
TEST_F(MySqlConnectionTest, selectEmptyStringBlob) {
    std::string blob = "";
    MySqlBindingCollection in_bindings = {
        MySqlBinding::createInteger<uint8_t>(123),
        MySqlBinding::createInteger<uint32_t>(1024),
        MySqlBinding::createInteger<int64_t>(-4096),
        MySqlBinding::createString(""),
        MySqlBinding::createBlob(blob.begin(), blob.end()),
        MySqlBinding::createTimestamp(boost::posix_time::microsec_clock::universal_time())
    };

    testInsertSelect(in_bindings);
}

// Test that a row can be deleted from the database.
TEST_F(MySqlConnectionTest, deleteByValue) {
    // Insert a row with numeric values.
    MySqlBindingCollection in_bindings = {
        MySqlBinding::createInteger<uint8_t>(123),
        MySqlBinding::createInteger<uint32_t>(1024),
        MySqlBinding::createInteger<int64_t>(-4096),
        MySqlBinding::createNull(),
        MySqlBinding::createNull(),
        MySqlBinding::createNull()
    };
    ASSERT_NO_THROW(conn_.insertQuery(MySqlConnectionTest::INSERT_VALUE,
                                      in_bindings));

    // This variable will be checked to see if the row has been deleted
    // from the database.
    bool deleted = false;

    // Execute delete query but use int_value of non existing row.
    // The row should not be deleted.
    in_bindings = { MySqlBinding::createInteger<uint32_t>(1) };
    ASSERT_NO_THROW(deleted = conn_.updateDeleteQuery(MySqlConnectionTest::DELETE_BY_INT_VALUE,
                                                      in_bindings));
    ASSERT_FALSE(deleted);

    // This time use the correct value.
    in_bindings = { MySqlBinding::createInteger<uint32_t>(1024) };
    ASSERT_NO_THROW(deleted = conn_.updateDeleteQuery(MySqlConnectionTest::DELETE_BY_INT_VALUE,
                                                      in_bindings));
    // The row should have been deleted.
    ASSERT_TRUE(deleted);

    // Let's confirm that it has been deleted by issuing a select query.
    MySqlBindingCollection out_bindings = {
        MySqlBinding::createInteger<uint8_t>(),
        MySqlBinding::createInteger<uint32_t>(),
        MySqlBinding::createInteger<int64_t>(),
        MySqlBinding::createString(512),
        MySqlBinding::createBlob(512),
        MySqlBinding::createTimestamp()
    };

    ASSERT_NO_THROW(conn_.selectQuery(MySqlConnectionTest::GET_BY_INT_VALUE,
                                      in_bindings, out_bindings,
                                      [&deleted](MySqlBindingCollection& out_bindings) {
        // This will be executed if the row is returned as a result of
        // select query. We expect that this is not executed.
        deleted = false;
    }));
    // Make sure that select query returned nothing.
    EXPECT_TRUE(deleted);
}

}

ext: cc

max_stars_repo_name: mcr/kea

max_issues_repo_name: jxiaobin/kea

max_forks_repo_name: jxiaobin/kea


text:
//
//  SettingsPanel.cpp
//  Kepler
//
//  Created by Tom Carden on 8/25/11.
//  Copyright 2013 Smithsonian Institution. All rights reserved.
//

#include <boost/foreach.hpp>
#include "SettingsPanel.h"
#include "Globals.h"
#include "BloomGl.h" // for batch drawing
#include "BloomScene.h" // for mRoot

using namespace ci;
using namespace ci::app;
using namespace std;

void SettingsPanel::setup( const Vec2f &interfaceSize, ipod::Player *player, const Font &font, const gl::Texture &uiSmallButtonsTex )
{
    // create, add, and position everything...
    createChildren( font, uiSmallButtonsTex );
    setInterfaceSize( interfaceSize );

    // set initial state...
    setOrbitsOn( G_DRAW_RINGS );
    setLabelsOn( G_DRAW_TEXT );
    setHelpOn( false ); // this is the default in KeplerApp
    setDebugOn( G_DEBUG );
    setShuffleOn( player->getShuffleMode() != ipod::Player::ShuffleModeOff );
    setRepeatMode( player->getRepeatMode() );

    if( G_IS_IPAD2 ) {
        setGyroOn( G_USE_GYRO );
    }
}

void SettingsPanel::createChildren( const Font &font, const gl::Texture &uiSmallButtonsTex )
{
    // !!! SMALL BUTTONS !!!
	float x0 = 350.0f;
	float x1 = 390.0f;
	float x2 = 430.0f;
	float x3 = 470.0f;
	float x4 = 510.0f;

	float y0 = 300.0f;
	float y1 = 340.0f;
	float y2 = 380.0f;
	float y3 = 420.0f;
	float y4 = 460.0f;
	float y5 = 500.0f;

    mHelpButton = new ToggleButton(			HELP,
											false,
											uiSmallButtonsTex,
											Area( x0, y1, x1, y2 ),  // on texture
											Area( x0, y0, x1, y1 ) ); // off texture

    if( G_IS_IPAD2 ){
        mGyroButton = new ToggleButton(		USE_GYRO,
											false,
											uiSmallButtonsTex,
											Area( x1, y1, x2, y2 ),  // on texture
											Area( x1, y0, x2, y1 ) ); // off texture
    }

	mOrbitsButton = new ToggleButton(		DRAW_RINGS,
											false,
											uiSmallButtonsTex,
											Area( x2, y1, x3, y2 ),  // on texture
											Area( x2, y0, x3, y1 ) ); // off texture

	mLabelsButton = new ToggleButton(		DRAW_TEXT,
											false,
											uiSmallButtonsTex,
											Area( x3, y1, x4, y2 ),  // on texture
											Area( x3, y0, x4, y1 ) ); // off texture

	mDebugButton = new ToggleButton(		DEBUG_FEATURE,
											false,
											uiSmallButtonsTex,
											Area( x0, y3, x1, y4 ),  // on texture
											Area( x0, y2, x1, y3 ) ); // off texture

    mScreensaverButton = new ToggleButton(	AUTO_MOVE,
											false,
											uiSmallButtonsTex,
											Area( x1, y3, x2, y4 ),
											Area( x1, y2, x2, y3 ) );

    mShuffleButton = new ToggleButton(		SHUFFLE,
											false,
											uiSmallButtonsTex,
											Area( x2, y3, x3, y4 ),  // on texture
											Area( x2, y2, x3, y3 ) ); // off texture

    mRepeatButton = new ThreeStateButton(	REPEAT,
											0,
											uiSmallButtonsTex,
											Area( x3, y2, x4, y3 ),   // first texture  (off)
											Area( x3, y3, x4, y4 ),   // second texture (repeat all)
											Area( x3, y4, x4, y5 ) ); // third texture  (repeat one)

    ///////
	// TODO: add initial value
	mParamSlider1 = new Slider(				PARAMSLIDER1,          // ID
											uiSmallButtonsTex,
											Area( 351, 460, 358, 500 ),  // bg texture
											Area( 362, 460, 369, 500 ),  // fg texture
											Area( 390, 460, 430, 500 ),  // thumb on texture
											Area( 430, 460, 470, 500 ) ); // thumb off texture

	mParamSlider1->setValue( 0.25f );
	mParamSlider1Label = new TextLabel( NO_BUTTON, font, BRIGHT_BLUE );
	mParamSlider1Label->setText( "Scale" );

	mParamSlider2 = new Slider(				PARAMSLIDER2,          // ID
											uiSmallButtonsTex,
											Area( 351, 460, 358, 500 ),  // bg texture
											Area( 362, 460, 369, 500 ),  // fg texture
											Area( 390, 460, 430, 500 ),  // thumb on texture
											Area( 430, 460, 470, 500 ) ); // thumb off texture

	mParamSlider2->setValue( 0.15f );
	mParamSlider2Label = new TextLabel( NO_BUTTON, font, BRIGHT_BLUE );
	mParamSlider2Label->setText( "Speed" );
}

bool SettingsPanel::addedToScene()
{
    // now mRoot is valid we can add children
    addChildren(); // FIXME: make it so you can add children even if mRoot is invalid
    return false;
}

void SettingsPanel::addChildren()
{
    addChild( BloomNodeRef(mShuffleButton) );
    addChild( BloomNodeRef(mRepeatButton) );
	addChild( BloomNodeRef(mScreensaverButton) );
    addChild( BloomNodeRef(mHelpButton) );
    addChild( BloomNodeRef(mOrbitsButton) );
    addChild( BloomNodeRef(mLabelsButton) );
//    addChild( BloomNodeRef(mDebugButton) );
    if( G_IS_IPAD2 ) addChild( BloomNodeRef(mGyroButton) );
	addChild( BloomNodeRef(mParamSlider1) );
	addChild( BloomNodeRef(mParamSlider2) );
	addChild( BloomNodeRef(mParamSlider1Label) );
    addChild( BloomNodeRef(mParamSlider2Label) );
}

void SettingsPanel::setInterfaceSize( const Vec2f &interfaceSize )
{
    mInterfaceSize = interfaceSize;

	const float topBorder	 = 5.0f;
	const float sideBorder	 = 10.0f;
    const float bSizeSmall	 = 40.0f;
	const bool  landscape    = interfaceSize.x > interfaceSize.y;
	float y1 = topBorder;
    float y2 = y1 + bSizeSmall;

    // SHUFFLE TOGGLE BUTTON
	float x1 = interfaceSize.x - sideBorder - bSizeSmall - 3.0f;
	float x2 = x1 + bSizeSmall;
    mShuffleButton->setRect( x1, y1, x2, y2 );

    // REPEAT TOGGLE BUTTON
	x1 -= bSizeSmall;
	x2 = x1 + bSizeSmall;
    mRepeatButton->setRect( x1, y1, x2, y2 );

    // TEXT LABELS TOGGLE BUTTON
	float gap = landscape ? 110.0f : 35.0f;
	x1 -= bSizeSmall + gap;
	x2 = x1 + bSizeSmall;
    mLabelsButton->setRect( x1, y1, x2, y2 );

    // ORBIT RING TOGGLE BUTTON
	x1 -= bSizeSmall;
	x2 = x1 + bSizeSmall;
    mOrbitsButton->setRect( x1, y1, x2, y2 );

    // GYRO TOGGLE BUTTON
	if( G_IS_IPAD2 ){
		x1 -= bSizeSmall;
		x2 = x1 + bSizeSmall;
		mGyroButton->setRect( x1, y1, x2, y2 );
	}

    // DEBUG TOGGLE BUTTON
//	x1 -= bSizeSmall;
//	x2 = x1 + bSizeSmall;
//    mDebugButton->setRect( x1, y1, x2, y2 );

    // SCREENSAVER TOGGLE BUTTON
	x1 -= bSizeSmall;
	x2 = x1 + bSizeSmall;
    mScreensaverButton->setRect( x1, y1, x2, y2 );

    //// HELP TOGGLE BUTTON
    x1 -= bSizeSmall;
	x2 = x1 + bSizeSmall;
    mHelpButton->setRect( x1, y1, x2, y2 );

	const float paramSliderWidth = landscape ? 200.0f : 120.0f;
	const float slider1X         = 60.0f;
	const float slider2X         = slider1X + paramSliderWidth + 75.0f;
	const float sliderYOff       = 16.0f;
    const float sliderHeight     = 20.0f;

    mParamSlider1->setRect( slider1X, sliderYOff, slider1X + paramSliderWidth, sliderYOff + sliderHeight );
    mParamSlider2->setRect( slider2X, sliderYOff, slider2X + paramSliderWidth, sliderYOff + sliderHeight );

	mParamSlider1Label->setRect( slider1X - 40.0f, sliderYOff, slider1X, sliderYOff + sliderHeight );
	mParamSlider2Label->setRect( slider2X - 45.0f, sliderYOff, slider2X, sliderYOff + sliderHeight);
}

void SettingsPanel::update()
{
    Vec2f interfaceSize = getRoot()->getInterfaceSize();
    if ( mInterfaceSize != interfaceSize ) {
        setInterfaceSize( interfaceSize );
    }
}

void SettingsPanel::deepDraw()
{
    if (mVisible) {
        glPushMatrix();
        glMultMatrixf(mTransform);

        // draw background so we can't see alpha/playlist chooser behind us in transitions
		gl::color( Color::black() );
        gl::drawSolidRect( Rectf( Vec2f( 0.0f, 0.0f ), Vec2f( mInterfaceSize.x, getHeight() ) ) );

        // draw line at the top (as for each ui panel)
		gl::color( ColorA( BRIGHT_BLUE, 0.125f ) );
        gl::drawLine( Vec2f( 0.0f, 0.0f ), Vec2f( mInterfaceSize.x, 0.0f ) );

        // tint children
		gl::color( ColorA( 1, 1, 1, mOpacity ) ); // mOpacity comes from UiLayer

        bloom::gl::beginBatch();
        // draw children
        BOOST_FOREACH(BloomNodeRef child, mChildren) {
            child->deepDraw();
        }
        bloom::gl::endBatch();
        glPopMatrix();
    }
}

//bool SettingsPanel::onBloomNodeTouchEnded( BloomNodeRef nodeRef )
//{
//    if ( nodeRef->getId() > NO_BUTTON && nodeRef->getId() < LAST_BUTTON ) {
//        mCallbacksButtonPressed.call(ButtonId(nodeRef->getId()));
//    }
//    return false;
//}

float SettingsPanel::getHeight()
{
    return 50.0f;
}

ext: cpp

max_stars_repo_name: cooperhewitt/Planetary

max_issues_repo_name: bobwol/Planetary

max_forks_repo_name: bobwol/Planetary


text:
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE libmace
#define BOOST_TEST_NO_MAIN
#include <boost/test/unit_test.hpp>
#include "ContextService.h"
#include "AccessLine.h"
#include "MaceKey.h"
#include "HeadEventDispatch.h"

namespace mace{
  class __ServiceStackEvent__;
  class __ScopedTransition__;
  class __ScopedRoutine__;
};
// LocalService is for non-distributed service.
using mace::__CheckTransition__;
class __LocalTransition__;
class LocalService: public ContextService {
friend class __LocalTransition__;
public:
  LocalService():  ContextService()
  {
    mace::map<mace::MaceAddr ,mace::list<mace::string > > servContext;
    loadContextMapping( servContext);
  }
protected:
  virtual void dispatchDeferredMessages(MaceKey const& dest, mace::string const& message,  registration_uid_t const rid ) {}// no messages
  virtual void executeDeferredUpcall(  mace::ApplicationUpcall_Message* const upcall, mace::string& returnValue ) {}
};
class __LocalTransition__{
public:
    __LocalTransition__( LocalService* service, int8_t const eventType, mace::string const& targetContextName = "", mace::vector< mace::string > const& snapshotContextNames = mace::vector< mace::string >() ) {
      mace::vector< uint32_t > snapshotContextIDs;
      mace::__ServiceStackEvent__ sse( eventType, service, targetContextName );
      const mace::ContextMapping& currentMapping = service->contextMapping.getSnapshot();
      const uint32_t targetContextID = currentMapping.findIDByName( targetContextName );
      for_each( snapshotContextNames.begin(), snapshotContextNames.end(), mace::addSnapshotContextID( currentMapping, snapshotContextIDs ) );
      mace::AccessLine al( service->instanceUniqueID, targetContextID, currentMapping );

      p = new mace::__ScopedTransition__( service, targetContextID );
    }
    ~__LocalTransition__(){
      delete p;
    }

private:
  mace::__ScopedTransition__* p;
};

// InContextService is similar to mace-incontext system
template< class GlobalContextType >
class InContextService: public LocalService {
friend class mace::__ServiceStackEvent__;
public:
  InContextService():  LocalService(), globalContext(NULL) { }
private:
  GlobalContextType* globalContext;
  mace::ContextBaseClass* createContextObject( mace::string const& contextTypeName ){
    ASSERT( contextTypeName.empty() );
    ASSERT( globalContext == NULL );

    globalContext = new GlobalContextType();
    return globalContext;

  }
};
namespace mace {
  // a specialized message type. This message is used for storing information and passed around between threads, therefore it will not do serialization
  class LocalMessage: public mace::AsyncEvent_Message, public mace::PrintPrintable{
    virtual void print( std::ostream& __out ) const {
      __out << "LocalMessage()";
    }
    virtual void serialize( std::string& str ) const{ } // empty
    virtual int deserialize( std::istream& __in ) throw (mace::SerializationException){ return 0;}
  };

}
struct __async_req: public mace::LocalMessage{
  static const uint8_t messageType =12;
  uint8_t getType() const{ return messageType; }
  __asyncExtraField& getExtra() { return extra; }
  mace::Event& getEvent() { return event; }
  mace::Event event;
  mace::__asyncExtraField extra;
};
template< class GlobalContextType >
class Test1Service: public InContextService< GlobalContextType > {
public:
  Test1Service():  InContextService< GlobalContextType >() { }
  void maceInit(){ // access the global context
    this->registerInstanceID();
    //__LocalTransition__ lt( this, mace::Event::STARTEVENT );
    __CheckTransition__ cm( this, mace::Event::STARTEVENT, "" );
    __real_maceInit();

  }
  void maceExit(){ // access the global context
    //__LocalTransition__ lt( this, mace::Event::ENDEVENT );
    __CheckTransition__ cm( this, mace::Event::ENDEVENT, "" );
    __real_maceExit();
  }
private:
  void __real_maceInit(){
    async_test();
  }
  void __real_maceExit(){

  }
  void async_test(){

    __async_req* req = new __async_req;
    this->addEventRequest( req );
  }
  void test( __async_req* msg){

    async_test();

  }
  int deserializeMethod( std::istream& is, mace::Message*& eventObject   )  {
    uint8_t msgNum_s = static_cast<uint8_t>(is.peek() ) ;
    switch( msgNum_s  ){
      case __async_req::messageType: {
        eventObject = new __async_req;
        return mace::deserialize( is, eventObject );
        break;
      }
      default:
        ABORT("message type not found");
    }
  };
  void executeEvent( mace::AsyncEvent_Message* __param ){
    this->__beginRemoteMethod( __param->getEvent() );
    mace::__ScopedTransition__ st(this, __param->getExtra() );

    mace::Message *msg = static_cast< mace::Message* >( __param ) ;
    switch( msg->getType()  ){
      case __async_req::messageType: {
        __async_req* __msg = static_cast< __async_req *>( msg ) ;
        test( __msg );
        break;
      }
    }
    delete __param;
  }
  void executeRoutine(mace::Routine_Message* __param, mace::MaceAddr const & source){

  }

};
class GlobalContext: public mace::ContextBaseClass{
public:
  GlobalContext( const mace::string& contextName="", const uint64_t eventID=0, const uint8_t instanceUniqueID=0, const uint32_t contextID=0 ):
    mace::ContextBaseClass( contextName, eventID, instanceUniqueID, contextID ){
  }
private:
  // declare context variables here
};

int main(int argc, char* argv[]){
  mace::Init( argc, argv );
  const char *_argv[] = {""};
  int _argc = 1;
  ::boost::unit_test::unit_test_main( &init_unit_test, _argc, const_cast<char**>(_argv) );

  mace::Shutdown();
}

BOOST_AUTO_TEST_SUITE( lib_ContextService )

BOOST_AUTO_TEST_CASE( Case1 )
{ // test single services
  // test: create start event, async event, timer event, message delivery event, downcall event, upcall event,
  //       test routines (local)
  BOOST_TEST_CHECKPOINT("Constructor");
  Test1Service<GlobalContext> service1;
  BOOST_TEST_CHECKPOINT("maceInit");
  service1.maceInit();
  SysUtil::sleep( 10 );
  BOOST_TEST_CHECKPOINT("maceExit");
  service1.maceExit();
}
BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: jojochuang/eventwave

max_issues_repo_name: jojochuang/eventwave

max_forks_repo_name: jojochuang/eventwave


text:
/// \file
// --------------------------------------------------------------------------
// This file is part of the reference implementation for the paper
//    QFib: Fast and Efficient Brain Tractogram Compression
//    C. Mercier*, S. Rousseau*, P. Gori, I. Bloch and T. Boubekeur
//    NeuroInformatics 2020
//    DOI: 10.1007/s12021-020-09452-0
//
// All rights reserved. Use of this source code is governed by a
// MIT license that can be found in the LICENSE file.
// --------------------------------------------------------------------------
#pragma once

#include <Eigen/Core>
#include <Eigen/Sparse>
#include <Eigen/Geometry>
#include <Eigen/Dense>

#include "saveload.hpp"
#include <vector>

namespace utl
{
///
/// \brief meanMaxError Function to compute average and maximum error between two sets of fibers containing the exact same number of points and fibers
/// \param fibersA Vector containing the first set of fibers
/// \param fibersB Vector containing the second set of fibers
/// \param meanError Average error
/// \param maxError Maximum error
/// \param totalNbPts Variable containing the total number of points in the bundle, used for average error computation
///

void meanMaxError(const std::vector< std::vector<Vector3f> > & fibersA, const std::vector< std::vector<Vector3f> > & fibersB, double & meanError, float & maxError, uint64_t & totalNbPts)
{
	meanError = 0;
	maxError = 0.f;
	assert(fibersA.size() == fibersB.size());
	for(unsigned f = 0; f < fibersA.size(); ++f)
	{
		assert(fibersA[f].size() == fibersB[f].size());
		for(unsigned p = 0; p < fibersA[f].size(); ++p)
		{
			float err = (fibersA[f][p] - fibersB[f][p]).norm();
			maxError = err > maxError ? err : maxError;
			meanError  += err / double(totalNbPts);
		}
	}
}

///
/// \brief error Function to compute the error between two sets of fibers with the exact same number of points and fibers
/// This error is computed depending on the length of the fibers
/// \param fibersA Vector containing the first set of fibers
/// \param fibersB Vector containing the second set of fibers
/// \param minError Minimum error
/// \param meanError Average error
/// \param maxError Maximum error
/// \param minEndPointError Minimum error on every end point
/// \param meanEndPointError Average error on every end point
/// \param maxEndPointError Maximum error on every end point
/// \param totalNbPts Variable containing the total number of points in the bundle, used for average error computation
/// \param steps Number of length separation to perform
/// \param minValue Minimum length to consider
/// \param maxValue Maximum length to consider
///

void error(const std::vector<std::vector<Vector3f> > & fibersA, const std::vector< std::vector<Vector3f> > & fibersB,
		   vector<float>& minError, vector<double>& meanError, vector<float>& maxError,
		   float & minEndPointError, float & meanEndPointError, float & maxEndPointError, uint64_t & totalNbPts,
		   unsigned steps = 10, float minValue = 35, float maxValue = 260)
{
	minEndPointError = std::numeric_limits<float>::max();
	meanEndPointError = 0.f;
	maxEndPointError = 0.f;
	unsigned nbSteps = (maxValue - minValue)/steps;
	minError.resize(nbSteps, std::numeric_limits<float>::max());
	meanError.resize(nbSteps, 0);
	maxError.resize(nbSteps, 0);

	unsigned nbEndPoints = fibersA.size();
	assert(fibersA.size() == fibersB.size());
	for(unsigned f = 0; f < fibersA.size(); ++f)
	{
		unsigned tablePos = (float)((fibersA[f].size() - 1) * (fibersA[f][1]-fibersA[f][0]).norm() - minValue) / (float)(maxValue - minValue) * (nbSteps-1);
		if (tablePos>nbSteps-1) tablePos = nbSteps - 1;
		assert(fibersA[f].size() == fibersB[f].size());
		for(unsigned p = 0; p < fibersA[f].size()-1; ++p)
		{
			float err = (fibersA[f][p] - fibersB[f][p]).norm();
			meanError[tablePos]  += err / double(totalNbPts);
			maxError[tablePos] = err > maxError[tablePos] ? err : maxError[tablePos];
			minError[tablePos] = err < minError[tablePos] ? err : minError[tablePos];
		}
		float err = (fibersA[f][fibersA[f].size()-1] - fibersB[f][fibersA[f].size()-1]).norm();
		meanError[tablePos]  += err / double(totalNbPts);
		maxError[tablePos] = err > maxError[tablePos] ? err : maxError[tablePos];
		minError[tablePos] = err < minError[tablePos] ? err : minError[tablePos];
		minEndPointError = err < minEndPointError ? err : minEndPointError;
		meanEndPointError += err / double(nbEndPoints);
		maxEndPointError = err > maxEndPointError ? err : maxEndPointError;
	}
}
}

ext: hpp

max_stars_repo_name: syrousseau/qfib

max_issues_repo_name: syrousseau/qfib

max_forks_repo_name: syrousseau/qfib


text:
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
// ------------------------------------------------------------

#include "stdafx.h"

#include <boost/test/unit_test.hpp>
#include "Common/boost-taef.h"
#include <Common/ErrorCode.h>

Common::StringLiteral const TraceType("ErrorCodeTest");

using namespace std;

namespace Common
{
    struct LoopbackStream : public ByteStream<LoopbackStream>
    {
        void WriteBytes(void const * buf, size_t size)
        {
            Trace.WriteInfo(TraceType, "writing {0} bytes", size);
            byte const * begin = reinterpret_cast<byte const*>(buf);
            q_.insert(q_.end(), begin, begin + size);
        }
        void ReadBytes(void * buf, size_t size)
        {
            Trace.WriteInfo(TraceType, "reading {0} bytes", size);
            byte * begin = reinterpret_cast<byte*>(buf);
            q_.pop_front_n(size, begin);
        }
        bool empty() { return q_.empty(); }
    private:
        bique<byte> q_;
    };

    class TestErrorCode
    {
    protected:
        ErrorCode GetErrorCode()
        {
            return ErrorCode();
        }
    };

    BOOST_FIXTURE_TEST_SUITE(ErrorCodeTests,TestErrorCode)

    BOOST_AUTO_TEST_CASE(BasicErrorCodeTest)
    {
        ErrorCode successErrorCode;
        VERIFY_IS_TRUE(successErrorCode.IsSuccess());

        ErrorCode timeoutErrorCode(ErrorCodeValue::Timeout);
        VERIFY_IS_FALSE(timeoutErrorCode.IsSuccess());

        ErrorCode faultErrorCode(ErrorCodeValue::RoutingNodeDoesNotMatchFault);
        VERIFY_IS_FALSE(faultErrorCode.IsSuccess());

        // Ensure that we have not used all reserved HRESULT values.
        auto firstInternal = static_cast<int>(ErrorCodeValue::FIRST_INTERNAL_ERROR_CODE_MINUS_ONE) + 1;
        auto lastPublic = static_cast<int>(::FABRIC_E_LAST_USED_HRESULT);
        VERIFY_IS_TRUE(lastPublic < firstInternal);

        // Ensure that internal HRESULT values are at the end of our reserved range.
        auto lastInternal = static_cast<int>(ErrorCodeValue::LAST_INTERNAL_ERROR_CODE);
        auto lastReserved = static_cast<int>(FABRIC_E_LAST_RESERVED_HRESULT);
        if (lastInternal != lastReserved)
        {
            auto actualCount = (lastInternal + 1) - firstInternal;
            auto specifiedCount = static_cast<int>(ErrorCodeValue::INTERNAL_ERROR_CODE_COUNT);

            Trace.WriteError(
                TraceType,
                "ErrorCodeValue::INTERNAL_ERROR_CODE_COUNT is {0} but should be {1}.  Please fix it before checking in.",
                specifiedCount,
                actualCount);

            VERIFY_FAIL(wformatString(
                    "ErrorCodeValue::INTERNAL_ERROR_CODE_COUNT is %d but should be %d.  Please fix it before checking in.",
                    specifiedCount,
                    actualCount).c_str());
        }
    }

    BOOST_AUTO_TEST_CASE(TransferErrorCodeTest)
    {
        Trace.WriteInfo(TraceType, "Copy via assignment -- error1A should end up as 'read'");
        ErrorCode error1A;
        ErrorCode error2A = error1A;
        VERIFY_IS_TRUE(error2A.IsSuccess());

        Trace.WriteInfo(TraceType, "Copy via constructor -- error1B should end up as 'read'");
        ErrorCode error1B;
        ErrorCode error2B(error1B);
        VERIFY_IS_TRUE(error2B.IsSuccess());

        Trace.WriteInfo(TraceType, "Copy from function call -- inside of function, should end up as 'read'");
        ErrorCode fromFunctionCall = GetErrorCode();
        VERIFY_IS_TRUE(fromFunctionCall.IsSuccess());
    }

    BOOST_AUTO_TEST_CASE(UnreadErrorCodeTest)
    {
        Trace.WriteInfo(TraceType, "Verify overwriting empty ErrorCode does not throw, but then subsequent overwrite throws.");
        ErrorCode error2;
        error2 = ErrorCode::Success();

        {
            Assert::DisableDebugBreakInThisScope disableDebugBreakInThisScope;
            VERIFY_THROWS({ error2 = ErrorCode::Success(); }, std::system_error);
        }

        error2.ReadValue();
    }

    BOOST_AUTO_TEST_CASE(InternalErrorCodePositionTest)
    {
        // ensure that the value of the following internal error code does not change
        // as the new internal error code are added at the top of the internal error code range
        // see comment in ErrorCodeValue.h

        auto lastInternal = static_cast<int>(ErrorCodeValue::LAST_INTERNAL_ERROR_CODE);
        auto abandonedFileWriteLockFoundError = static_cast<int>(ErrorCodeValue::AbandonedFileWriteLockFound);

        if (lastInternal != abandonedFileWriteLockFoundError)
        {
              Trace.WriteError(
                TraceType,
                "ErrorCodeValue::LAST_INTERNAL_ERROR_CODE MUST BE AbandonedFileWriteLockFound to maintain compatibility. Please add internal error code at the top of the INTERNAL error code range.");
        }
    }

    BOOST_AUTO_TEST_CASE(ThreadErrorMessageTest)
    {
        LONG threadCount = 200;

        int minSleep = 0;
        int maxSleep = 50;

        atomic_long completedCount(threadCount);
        ManualResetEvent completedEvent(false);

        Random rand(static_cast<int>(DateTime::Now().Ticks));

        for (auto ix=0; ix<threadCount; ++ix)
        {
            LONG index = ix;
            Threadpool::Post([&, index]()
            {
                auto inData = wformatString("error message {0}", index);

                Sleep(rand.Next(minSleep, maxSleep));

                {
                    ErrorCode error(ErrorCodeValue::OperationFailed, wformatString(inData));

                    error.SetThreadErrorMessage();

                    Sleep(rand.Next(minSleep, maxSleep));

                    wstring outData1 = FabricGlobals::Get().GetThreadErrorMessages().GetMessage();

                    VERIFY_IS_TRUE(outData1 == inData, wformatString("[{0}] read '{1}'", index, outData1).c_str());
                }

                Sleep(rand.Next(minSleep, maxSleep));

                wstring outData2 = FabricGlobals::Get().GetThreadErrorMessages().GetMessage();

                VERIFY_IS_TRUE(outData2.empty(), wformatString("[{0}] read '{1}'", index, outData2).c_str());

                if (--completedCount == 0)
                {
                    completedEvent.Set();
                }
            });
        }

        completedEvent.WaitOne();

        // test copy
        {
            wstring msg(L"my error message 1");
            ErrorCode error1(ErrorCodeValue::OperationFailed, wformatString(msg));

            ErrorCode error2(error1);
            VERIFY_IS_TRUE(error1.Message == error2.Message, wformatString("{0} == {1}", error1.Message, error2.Message).c_str());
            VERIFY_IS_TRUE(error2.Message == msg);
            VERIFY_IS_TRUE(error2.IsError(ErrorCodeValue::OperationFailed));

            ErrorCode error3 = error1;
            VERIFY_IS_TRUE(error1.Message == error3.Message, wformatString("{0} == {1}", error1.Message, error3.Message).c_str());
            VERIFY_IS_TRUE(error3.Message == msg);
            VERIFY_IS_TRUE(error3.IsError(ErrorCodeValue::OperationFailed));

            ErrorCode error4;
            error4.Overwrite(error1);
            VERIFY_IS_TRUE(error1.Message == error4.Message, wformatString("{0} == {1}", error1.Message, error4.Message).c_str());
            VERIFY_IS_TRUE(error4.Message == msg);
            VERIFY_IS_TRUE(error4.IsError(ErrorCodeValue::OperationFailed));
        }

        // test move
        {
            wstring msg(L"my error message 2");
            ErrorCode error1(ErrorCodeValue::OperationFailed, wformatString(msg));

            ErrorCode error2(move(error1));
            VERIFY_IS_TRUE(error1.Message != error2.Message, wformatString("{0} != {1}", error1.Message, error2.Message).c_str());
            VERIFY_IS_TRUE(error1.Message.empty());
            VERIFY_IS_TRUE(error2.Message == msg);
            VERIFY_IS_TRUE(error2.IsError(ErrorCodeValue::OperationFailed));

            ErrorCode error3 = move(error2);
            VERIFY_IS_TRUE(error2.Message != error3.Message, wformatString("{0} != {1}", error2.Message, error3.Message).c_str());
            VERIFY_IS_TRUE(error2.Message.empty());
            VERIFY_IS_TRUE(error3.Message == msg);
            VERIFY_IS_TRUE(error3.IsError(ErrorCodeValue::OperationFailed));

            ErrorCode error4;
            error4.Overwrite(move(error3));
            VERIFY_IS_TRUE(error3.Message != error4.Message, wformatString("{0} != {1}", error3.Message, error4.Message).c_str());
            VERIFY_IS_TRUE(error3.Message.empty());
            VERIFY_IS_TRUE(error4.Message == msg);
            VERIFY_IS_TRUE(error4.IsError(ErrorCodeValue::OperationFailed));
        }
    }

    BOOST_AUTO_TEST_SUITE_END()

    class TestFirstErrorTracker
    {};

    BOOST_FIXTURE_TEST_SUITE(FirstErrorTrackerTests, TestFirstErrorTracker)

    BOOST_AUTO_TEST_CASE(BasicFirstErrorTrackerTest)
    {
        FirstErrorTracker errorTracker;
        VERIFY_IS_TRUE(errorTracker.ReadValue() == ErrorCodeValue::Success);

        errorTracker.Update(ErrorCodeValue::Success);
        VERIFY_IS_TRUE(errorTracker.ReadValue() == ErrorCodeValue::Success);

        errorTracker.Update(ErrorCodeValue::StaleRequest);
        VERIFY_IS_TRUE(errorTracker.ReadValue() == ErrorCodeValue::StaleRequest);

        errorTracker.Update(ErrorCodeValue::Success);
        VERIFY_IS_TRUE(errorTracker.ReadValue() == ErrorCodeValue::StaleRequest);
    }

    BOOST_AUTO_TEST_SUITE_END()
}


text:
#include <tr064/Service.hh>
#include <tr064/ResourceRetrieval.hh>

#include "Tr064Exception.hh"
#include "Utils.hh"

// c lib
#include <strings.h>

// boost
#include <boost/foreach.hpp>

// std lib
#include <iostream>
#include <sstream>

using namespace tr064;

//------------------------------------------------------------------------------

Service::Service()
{

}

//------------------------------------------------------------------------------

bool
Service::empty() const
{
  return _type.empty() &&
         _name.empty() &&
         _id.empty() &&
         _control_url.empty() &&
         _event_subscription_url.empty() &&
         _scpd_url.empty() &&
         _actions.empty();
}

//------------------------------------------------------------------------------

std::string
Service::dump() const
{
  std::stringstream ss;
  ss << "---------- SERVICE ----------" << std::endl
     << "type: " << _type << std::endl
     << "name: " << _name << std::endl
     << "id: " << _id << std::endl
     << "control_url: " << _control_url << std::endl
     << "event_sub_url: " << _event_subscription_url << std::endl
     << "scpd_url: " << _scpd_url << std::endl
     << "---------- END SERVICE ----------" << std::endl;

  return ss.str();
}
//------------------------------------------------------------------------------

Service::ActionSearchResult
Service::find_action_by_name(const std::string& name) const
{
  for ( auto action : _actions )
  {
    if ( action->name() == name )
    {
      return std::make_tuple(true, action);
    }
  }

  return std::make_tuple(true, ServiceAction::Ptr());
}

//------------------------------------------------------------------------------
// Serializeable
//------------------------------------------------------------------------------

void
Service::serialize_json(boost::property_tree::ptree& parent_pt) const
{
  parent_pt.put("type", _type);
  parent_pt.put("name", _name);
  parent_pt.put("id", _id);
  parent_pt.put("control_url", _control_url);
  parent_pt.put("event_subscription_url", _event_subscription_url);
  parent_pt.put("scpd_url", _scpd_url);

  serialize_json_container_member<ServiceAction::Vector>(
      "actions", _actions, parent_pt);
}

//------------------------------------------------------------------------------

void
Service::deserialize_json(boost::property_tree::ptree& parent_pt)
{
  /*
   * {
   *   "name" : "value",
   *   "another" : "value",
   *   ...
   * }
   */
  find_and_set_member<Service, std::string>(
      parent_pt, this,
      &Service::_type, "type");
  find_and_set_member<Service, std::string>(
      parent_pt, this,
      &Service::_name, "name");
  find_and_set_member<Service, std::string>(
      parent_pt, this,
      &Service::_id, "id");
  find_and_set_member<Service, std::string>(
      parent_pt, this,
      &Service::_control_url, "control_url");
  find_and_set_member<Service, std::string>(
      parent_pt, this,
      &Service::_event_subscription_url, "event_subscription_url");
  find_and_set_member<Service, std::string>(
      parent_pt, this,
      &Service::_scpd_url, "scpd_url");

  auto actions =
    parent_pt.get_child("actions", boost::property_tree::ptree());

  BOOST_FOREACH(auto& action, actions)
  {
    ServiceAction::Ptr cpeaction(new ServiceAction());
    cpeaction->deserialize_json(action.second);
    if ( !cpeaction->empty() )
    {
      this->add_action(cpeaction);
    }
  }
}


text:
#ifndef MBGL_UTIL_STRING
#define MBGL_UTIL_STRING

#include <string>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#include <boost/lexical_cast.hpp>
#pragma GCC diagnostic pop

namespace mbgl {
namespace util {

template <typename... Args>
inline std::string toString(Args&&... args) {
    return boost::lexical_cast<std::string>(::std::forward<Args>(args)...);
}

// boost::lexical_cast() treats this as a character, but we are using it as number types.
inline std::string toString(int8_t num) {
    return boost::lexical_cast<std::string>(int(num));
}

template<size_t max, typename... Args>
inline std::string sprintf(const char *msg, Args... args) {
    char res[max];
    int len = snprintf(res, sizeof(res), msg, args...);
    return std::string(res, len);
}

template<size_t max, typename... Args>
inline std::string sprintf(const std::string &msg, Args... args) {
    return sprintf<max>(msg.c_str(), args...);
}

}
}

#endif

max_stars_repo_name: donpark/mapbox-gl-native

max_issues_repo_name: donpark/mapbox-gl-native

max_forks_repo_name: donpark/mapbox-gl-native


text:
//==============================================================================
//         Copyright 2003 - 2012   LASMEA UMR 6602 CNRS/Univ. Clermont II
//         Copyright 2009 - 2012   LRI    UMR 8623 CNRS/Univ Paris Sud XI
//
//          Distributed under the Boost Software License, Version 1.0.
//                 See accompanying file LICENSE.txt or copy at
//                     http://www.boost.org/LICENSE_1_0.txt
//==============================================================================
#include <nt2/table.hpp>
#include <nt2/include/functions/rows.hpp>
#include <nt2/include/functions/size.hpp>

#include <nt2/sdk/unit/module.hpp>
#include <nt2/sdk/unit/tests/basic.hpp>
#include <nt2/sdk/unit/tests/relation.hpp>
#include <nt2/sdk/unit/tests/type_expr.hpp>
#include <nt2/sdk/unit/tests/exceptions.hpp>
#include <boost/dispatch/meta/nth_hierarchy.hpp>

NT2_TEST_CASE_TPL( _0d, NT2_TYPES )
{
  using boost::mpl::_;
  using nt2::meta::value_type_;
 typedef std::complex<T> cT;

  nt2::table<cT> x1 = nt2::rows( cT(42) );
  NT2_TEST_EXPR_TYPE( ( nt2::rows( cT(42) )), (value_type_<_>), (cT) );
  NT2_TEST_EQUAL( nt2::extent(x1), nt2::of_size(1) );
  NT2_TEST_EQUAL( x1(1),cT(42) );
}

NT2_TEST_CASE_TPL( square, NT2_TYPES )
{
  using boost::mpl::_;
  using nt2::meta::value_type_;
  typedef std::complex<T> cT;

  cT s = cT(42);
  nt2::table<cT> ref( nt2::of_size(3,3) );
  for(int i=1;i<= 3;++i)
    for(int j=1;j<= 3;++j)
      ref(i,j) = cT(i-1)+s;

  nt2::table<cT> x0 = nt2::rows(3,s);

  NT2_TEST_EXPR_TYPE( ( nt2::rows( 3,s )), (value_type_<_>), (cT) );
  NT2_TEST_EQUAL( nt2::extent(x0), nt2::of_size(3,3) );
  NT2_TEST_EQUAL( x0,ref );
}

NT2_TEST_CASE_TPL( nd, NT2_TYPES )
{
  using boost::mpl::_;
  using nt2::meta::value_type_;
  typedef std::complex<T> cT;

  cT s = cT(42);

  nt2::table<cT> ref( nt2::of_size(8,8) );
  for(int j=1;j<= 8;++j)
    for(int i=1;i<= 8;++i)
      ref(i,j) = cT(i-1)+s;

  nt2::table<cT> x1 = nt2::rows(nt2::of_size(8, 8), s );

  NT2_TEST_EXPR_TYPE( ( nt2::rows(nt2::of_size(8, 8), s ) ), (value_type_<_>), (cT) );
  NT2_TEST_EQUAL(x1,ref);

  nt2::table<cT> x2 = nt2::rows(8, 8, s );
  NT2_TEST_EQUAL(x2,ref);

  nt2::table<cT> x3 = nt2::rows(8, s );
  NT2_TEST_EQUAL(x3,ref);
}

NT2_TEST_CASE_TPL( typed_expr, NT2_TYPES )
{
  using boost::mpl::_;
  using nt2::meta::value_type_;
  typedef std::complex<T> cT;

  cT s = cT(42);
  nt2::table<cT> ref( nt2::of_size(8,8) );
  for(int j=1;j<= 8;++j)
    for(int i=1;i<= 8;++i)
      ref(i,j) = cT(i-1)+s;

  nt2::table<int> t1(nt2::of_size(1) );
  t1(1) = 8;

  nt2::table<cT> x1 = nt2::rows( t1, s );
  NT2_TEST_EXPR_TYPE( ( nt2::rows(t1, s ) ), (value_type_<_>), (cT) );
  NT2_TEST_EQUAL(x1,ref);

  nt2::table<int> t2(nt2::of_size(1,2) );
  t2(1) = 4;
  t2(2) = 3;

  ref.resize( nt2::of_size(4,3) );
  for(int j=1;j<= 3;++j)
    for(int i=1;i<= 4;++i)
      ref(i,j) = cT(i-1)+s;

  nt2::table<cT> x2 = nt2::rows( t2, s );
  NT2_TEST_EQUAL(x2,ref);
}


text:
#include <iostream>
#include <cmath>
using namespace std;

#include <Eigen/Core>
// Eigen Geometry module
#include <Eigen/Geometry>

/****************************
* This program demonstrates how to use Eigen geometry module
****************************/

int main ( int argc, char** argv )
{
    // Eigen/Geometry The module provides various representations of rotation and translation
    // 3D rotation matrix directly use Matrix3d or Matrix3f
    Eigen::Matrix3d rotation_matrix = Eigen::Matrix3d::Identity();
    // Rotation vector uses AngleAxis, its underlying layer is not directly Matrix,
    // but the operation can be treated as a matrix (because the operator is overloaded)
    //Rotate 45 degrees along the Z axis
    Eigen::AngleAxisd rotation_vector ( M_PI/4, Eigen::Vector3d ( 0,0,1 ) );
    cout .precision(3);
    //Use matrix() to convert to a matrix
    cout<<"rotation matrix =\n"<<rotation_vector.matrix() <<endl;
    // You can also assign directly
    rotation_matrix = rotation_vector.toRotationMatrix();
    // Coordinate transformation can be performed with AngleAxis
    Eigen::Vector3d v ( 1,0,0 );
    Eigen::Vector3d v_rotated = rotation_vector * v;
    cout<<"(1,0,0) after rotation = "<<v_rotated.transpose()<<endl;
    // Or use the rotation matrix
    v_rotated = rotation_matrix * v;
    cout<<"(1,0,0) after rotation = "<<v_rotated.transpose()<<endl;

    // Euler angle: The rotation matrix can be directly converted into Euler angle
    // ZYX order, that is, roll pitch yaw order
    Eigen::Vector3d euler_angles = rotation_matrix.eulerAngles ( 2,1,0 );
    cout<<"yaw pitch roll = "<<euler_angles.transpose()<<endl;

    // Euclidean transformation matrix uses Eigen::Isometry
    // Although it is called 3d, it is essentially a 4*4 matrix
    Eigen::Isometry3d T=Eigen::Isometry3d::Identity();
    // Rotate according to rotation_vector
    T.rotate ( rotation_vector );
    // Set the translation vector to (1,3,4)
    T.pretranslate ( Eigen::Vector3d ( 1,3,4 ) );
    cout << "Transform matrix = \n" << T.matrix() <<endl;

    // Use transformation matrix for coordinate transformation
    // equivalent to R*v+t
    Eigen::Vector3d v_transformed = T*v;
    cout<<"v tranformed = "<<v_transformed.transpose()<<endl;

    // For affine and projective transformations, use Eigen::Affine3d and Eigen::Projective3d.
    // Quaternion
    // You can directly assign AngleAxis to a quaternion, and vice versa
    Eigen::Quaterniond q = Eigen::Quaterniond ( rotation_vector );
    // Please note that the order of coeffs is (x,y,z,w), w is the real part, and
    // the first three are the imaginary part
    cout<<"quaternion = \n"<<q.coeffs() <<endl;
    // You can also assign the rotation matrix to it
    q = Eigen::Quaterniond ( rotation_matrix );
    cout<<"quaternion = \n"<<q.coeffs() <<endl;
    // Use a quaternion to rotate a vector and use overloaded multiplication
    // Note that mathematically it is qvq^{-1}
    v_rotated = q*v;
    cout<<"(1,0,0) after rotation = "<<v_rotated.transpose()<<endl;

    return 0;
}

max_stars_repo_name: zoumson/Eigen

max_stars_repo_licenses: Unlicense MIT

max_issues_repo_name: zoumson/Eigen

max_issues_repo_licenses: Unlicense MIT

max_forks_repo_name: zoumson/Eigen

max_forks_repo_licenses: Unlicense MIT


text:
/***************************************************************************
 *
 * Copyright (c) 2014 Baidu.com, Inc. All Rights Reserved
 *
 **************************************************************************/
#include "group_task.h"

#include <fstream>

#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/system/error_code.hpp>
#include <libtorrent/bencode.hpp>
#include <libtorrent/create_torrent.hpp>
#include <libtorrent/entry.hpp>
#include <libtorrent/session.hpp>

#include "bbts/ErrorCategory.h"
#include "bbts/host_info_util.h"
#include "bbts/log.h"
#include "bbts/number_util.h"
#include "bbts/path.h"
#include "bbts/Syms.h"
#include "bbts/encode.h"

#include "GroupConf.pb.h"
#include "group_manager.h"
#include "utils.h"

using boost::posix_time::seconds;
using boost::shared_ptr;
using boost::system::error_code;

using libtorrent::add_torrent_params;
using libtorrent::cluster_config_entry;
using libtorrent::torrent_info;
using libtorrent::torrent_status;
using libtorrent::symlink_file;

using bbts::group::GroupManager;

extern ::bbts::GroupConfig kGroupConfig;

extern void SetSignalAction();

namespace bbts {
namespace group {

GroupTask::GroupTask()
    : control_status_(CONTROL_STATUS_NORMAL),
      seeding_timer_(GroupManager::GetInstance().io_service()),
      timeout_timer_(GroupManager::GetInstance().io_service()),
      has_pre_allocate_thread_start_(false),
      last_check_time_(time(NULL)),
      last_check_downloaded_(0),
      is_timeout_(false),
      is_mem_exceed_(false),
      low_downrate_times_(0),
      is_torrent_url_(false) {
  // do nothing
}

GroupTask::~GroupTask() {
  StopClusterTask();
  Persist();
  DEBUG_LOG("task delete");
}

void GroupTask::Persist() {
  if (control_status_ == CONTROL_STATUS_CANCELED ||
      control_status_ == CONTROL_STATUS_FINISHED) {
    // canceled or finished, delete resume file
    DeleteResumeFile();
  } else {
    GenerateResumeFile();
  }
}

int GroupTask::Create(
    const DownloadParam &param,
    const UserCred &cred) {
  params_ = param;
  cred_   = cred;
  task_status_.uid = cred.uid;

  // set signal action first
  SetSignalAction();

  if (params_.save_path.empty() || !check_and_mkdir_r(params_.save_path, 0755)) {
    FATAL_LOG("save path(%s) not correct or can not create.", params_.save_path.c_str());
    return -1;
  }
  task_status_.save_path = params_.save_path;

  error_code ec;
  add_torrent_params torrent_params;
  if (!params_.torrent_path.empty()) {
    int64_t size = libtorrent::file_size(params_.torrent_path.c_str());
    if (size <= 0 || size > kGroupConfig.max_metadata_size()) {
      FATAL_LOG("file(%s) size(%d)invalid.", params_.torrent_path.c_str(), size);
      return -1;
    }

    torrent_params.ti = new torrent_info(params_.torrent_path, ec, 0, params_.new_name);
    if (ec) {
      FATAL_LOG("pares torrent file(%s) failed, ret(%d): %s.",
                 params_.torrent_path.c_str(), ec.value(), ec.message().c_str());
      return -1;
    }
    if (params_.patition_download) {
      ParseNeedDownloadFiles<uint8_t>(params_.include_regex,
                                      params_.exclude_regex,
                                      *(torrent_params.ti),
                                      &torrent_params.file_priorities);
       pre_file_priorities_.resize(torrent_params.file_priorities.size(), 0);
       std::copy(torrent_params.file_priorities.begin(), torrent_params.file_priorities.end(), pre_file_priorities_.begin());
    } else {
      // all files will be downloaded
      pre_file_priorities_.resize(torrent_params.ti->num_files(), 1);
    }
    SetOrgPieces(torrent_params.ti);
  } else if (!params_.torrent_url.empty()) {
    torrent_params.url = params_.torrent_url;
    params_.need_save_resume = false;
    params_.need_down_to_tmp_first = false;
    is_torrent_url_ = true;
  } else if (!params_.infohash.empty()) {
    if (!params_.save_torrent_path.empty()) {
      std::ofstream ofs(params_.save_torrent_path.c_str());
      if (!ofs) {
        FATAL_LOG("can't create torrent file(%s) for save.", params_.save_torrent_path.c_str());
        return -1;
      }
      ofs.close();
    }
    std::string bytes;
    if (params_.infohash.length() != 40 || !bbts::HexstrToBytes(params_.infohash, &bytes)) {
      FATAL_LOG("infohash(%s) not correct.", params_.infohash.c_str());
      return -1;
    }
    torrent_params.info_hash.assign(bytes);
    torrent_params.ti = new torrent_info(torrent_params.info_hash, 0, params_.new_name);
  } else {
    FATAL_LOG("not set infohash or torrent file or torrent_url");
    return -1;
  }
  if (!is_torrent_url_) {
    infohash_ = libtorrent::to_hex(torrent_params.ti->info_hash().to_string());
  }

  std::vector<std::pair<std::string, int> > trackers;
  TurnTrackersListToStdList(params_.trackers, &trackers);
  if (trackers.empty()) {
    GroupManager::GetInstance().thrift_tracker().GetTrackersByInfohash(infohash_, &trackers);
  }
  torrent_params.thrift_trackers = trackers;

  if (is_torrent_url_) {
    // use torrent url path as infohash first
    infohash_ = params_.torrent_url;
  }
  params_.infohash = infohash_;

  if (params_.need_down_to_tmp_first) {
    tmp_save_path_ = params_.save_path + "/.gko3_" + params_.infohash + "_" + params_.new_name + ".tmp";
    if (!check_and_mkdir(tmp_save_path_, 0755)) {
      FATAL_LOG("[%s] tmp save path(%s) can not create.", infohash_.c_str(), tmp_save_path_.c_str());
      return -1;
    }
  } else {
    tmp_save_path_ = params_.save_path;
  }
  torrent_params.save_path = tmp_save_path_;

  std::vector<char> buffer;
  if (params_.need_save_resume) {
    resume_file_ = tmp_save_path_ + "/.gko3_" + params_.infohash + "_" + params_.new_name + ".resume";
    struct stat statbuf;
    if (stat(resume_file_.c_str(), &statbuf) == 0 && (statbuf.st_mode & S_IFREG)) {
      std::ifstream ifs(resume_file_.c_str(), std::ios::binary);
      if (ifs) {
        buffer.resize(statbuf.st_size);
        ifs.read(&buffer[0], statbuf.st_size);
        ifs.close();
        torrent_params.resume_data.swap(buffer);
      } else {
        WARNING_LOG("[%s] can't open resume file: %s, ignore", infohash_.c_str(), resume_file_.c_str());
      }
    }
  }

  if (params_.storage_pre_allocate) {
    torrent_params.storage_mode = libtorrent::storage_mode_allocate;
  }

  torrent_params.flags |= add_torrent_params::flag_duplicate_is_error;
  torrent_params.flags |= add_torrent_params::flag_override_resume_data;
  torrent_params.flags |= add_torrent_params::flag_paused;
  torrent_params.flags &= ~add_torrent_params::flag_auto_managed;

  torrent_params.download_limit = params_.download_limit;
  torrent_params.upload_limit = params_.upload_limit;
  torrent_params.max_connections = params_.connections_limit;
  torrent_params.url_seeds = params_.web_seeds;
  torrent_handle_ = GroupManager::GetInstance().session()->add_torrent(torrent_params, ec);

  if (ec) {
    FATAL_LOG("[%s] add torrent failed: %s.", infohash_.c_str(), ec.message().c_str());
    return -1;
  }

  if (params_.dynamic_allocate >= 0) {
    // set share mode first, so all pieces won't be downloaded before
    // unset share mode
    torrent_handle_.set_share_mode(true);
  }

  if (!params_.cluster_config.prefix_path.empty()) {
    if (!ParseSyms()) {
      NOTICE_LOG("[%s] Not support cluster(hadoop) download.", infohash_.c_str());
      return -1;
    }
    cluster_config_entry cluster_config;
    TurnClusterParamToClusterConfigEntry(params_.cluster_config, &cluster_config);
    NOTICE_LOG("[%s] support cluster(hadoop) download.", infohash_.c_str());
    DEBUG_LOG("[%s] cluster path: hdfs://%s@%s:%d%s", infohash_.c_str(),
               cluster_config.user.c_str(),cluster_config.host.c_str(), cluster_config.port,
               cluster_config.prefix_path.c_str());
    cluster_task_.reset(new GroupClusterTask(cluster_config,
                                              torrent_handle_,
                                              params_.cluster_thread_num,
                                              params_.ignore_hdfs_error));
  }

  std::string down_limit, up_limit;
  BytesToReadable(params_.download_limit, &down_limit);
  BytesToReadable(params_.upload_limit, &up_limit);
  TRACE_LOG("[%s] downlimit: %s, uplimit: %s, maxconn: %d",
             infohash_.c_str(), down_limit.c_str(), up_limit.c_str(), torrent_handle_.max_connections());

  // set task_status_ info
  task_status_.start_time = static_cast<int64_t>(time(NULL));
  task_status_.infohash = infohash_;
  task_status_.download_limit = params_.download_limit;
  task_status_.upload_limit = params_.upload_limit;
  if (torrent_params.ti.get() != NULL) {
    // if ti(torrent_info) is NULL, means torrent_url assign
    task_status_.num_files = torrent_params.ti->num_files();
    task_status_.num_paths = torrent_params.ti->get_paths().size();
    task_status_.num_symlinks = torrent_params.ti->files().get_symlink_file().size();
    task_status_.num_pieces = torrent_params.ti->num_pieces();
    task_status_.piece_length = torrent_params.ti->piece_length();
  }

  // Resume file
  GenerateResumeFile();

  // resume task
  Resume();

  // set timer
  if (params_.timeout > 0) {
    timeout_timer_.expires_from_now(seconds(params_.timeout));
    timeout_timer_.async_wait(boost::bind(&GroupTask::TimeoutTimerCallback, this, _1));
  }

  return 0;
}

int GroupTask::CreateFromResumeFile(
    const std::string &resume_file,
    int64_t file_size) {
  // load data from resume_file
  std::ifstream ifs(resume_file.c_str(), std::ios::binary);
  if (!ifs) {
    WARNING_LOG("can't open resume file: %s", resume_file.c_str());
    return -1;
  }
  boost::scoped_array<char> buffer(new char[file_size]);
  ifs.read(buffer.get(), file_size);
  ifs.close();
  libtorrent::entry resume_data = libtorrent::bdecode(buffer.get(), buffer.get() + file_size);
  if (resume_data.type() != libtorrent::entry::dictionary_t) {
    WARNING_LOG("bdecode resume file failed: %s, type: %d", resume_file.c_str(), resume_data.type());
    return -1;
  }

  libtorrent::entry &cred_e = resume_data["cred"];
  UserCred cred;
  cred.pid = cred_e["pid"].integer();
  cred.uid = cred_e["uid"].integer();
  cred.gid = cred_e["gid"].integer();

  // check if task has been canceled or finished
  control_status_ = static_cast<ControlTaskStatus>(resume_data["control_status"].integer());
  if (control_status_ == CONTROL_STATUS_CANCELED ||
      control_status_ == CONTROL_STATUS_FINISHED) {
    WARNING_LOG("task has been canceled or finished!");
    return -1;
  }

  // modify status
  seeding_time_ = resume_data["seeding_time"].integer();
  last_check_downloaded_ = resume_data["last_check_downloaded"].integer();
  last_check_time_ = static_cast<time_t>(resume_data["last_check_time"].integer());
  UnSerializedTaskStatus(resume_data["task_status"].string(), &task_status_);

  DownloadParam param;
  UnSerializedDownParam(resume_data["down_param"].string(), &param);

  // create at last because this will general resume file again
  if (Create(param, cred) != 0) {
    WARNING_LOG("[%s] load from resume file failed.", params_.infohash.c_str());
    return -1;
  }

  return 0;
}

int GroupTask::SetOptions(
    const TaskOptions &options) {
  if (!options.infohash.empty() &&
      options.infohash != infohash_) {
    WARNING_LOG("[%s] options is not empty, but not match this task!",
                 infohash_.c_str(), options.infohash.c_str());
    return -1;
  }

  if (options.download_limit > 0) {
    torrent_handle_.set_download_limit(options.download_limit);
    params_.__set_download_limit(options.download_limit);
  }

  if (options.upload_limit > 0) {
    torrent_handle_.set_upload_limit(options.upload_limit);
    params_.__set_upload_limit(options.upload_limit);
  }

  if (options.connections_limit > 0) {
    torrent_handle_.set_max_connections(options.connections_limit);
    params_.__set_connections_limit(options.connections_limit);
  }
  return 0;
}

int GroupTask::GetOptions(
    TaskOptions *options) {
  if (options == NULL) {
    return -1;
  }

  options->__set_infohash(infohash_);
  options->__set_download_limit(torrent_handle_.download_limit());
  options->__set_upload_limit(torrent_handle_.upload_limit());
  options->__set_connections_limit(torrent_handle_.max_connections());

  return 0;
}

void GroupTask::GenerateResumeTaskString(
    std::string *serialized_str) const {
  assert(serialized_str != NULL);
  SerializedTaskStatus(task_status_, serialized_str);
}

void GroupTask::GenerateResumeFile() const {
  if (infohash_.empty()) {
    return;
  }

  libtorrent::entry resume_data;
  libtorrent::entry &cred_e = resume_data["cred"];
  cred_e["pid"] = cred_.pid;
  cred_e["uid"] = cred_.uid;
  cred_e["gid"] = cred_.gid;
  resume_data["infohash"] = infohash_;
  resume_data["seeding_time"] = seeding_time_;
  resume_data["last_check_downloaded"] = last_check_downloaded_;
  resume_data["last_check_time"] = static_cast<int64_t>(last_check_time_);
  resume_data["control_status"] = control_status_;

  if (!trackers_.empty()) {
    libtorrent::entry &trackers_e = resume_data["trackers"];
    std::vector<std::pair<std::string, int> >::const_iterator it = trackers_.begin();
    for (; it != trackers_.end(); ++it) {
      libtorrent::entry tracker_e;
      tracker_e["host"] = it->first;
      tracker_e["port"] = it->second;
      trackers_e.list().push_back(tracker_e);
    }
  }

  std::string serialized_str;
  SerializedDownParam(params_, &serialized_str);
  resume_data["down_param"] = serialized_str;

  // task status
  GenerateResumeTaskString(&serialized_str);
  resume_data["task_status"] = serialized_str;

  std::string task_resume_file_name = kGroupConfig.resume_dir();
  task_resume_file_name += "/" + infohash_ + ".resume";
  std::ofstream ofs(task_resume_file_name.c_str(), std::ios::binary);
  if (!ofs) {
    WARNING_LOG("[%s] open file failed: %s.", infohash_.c_str(), task_resume_file_name.c_str());
    return;
  }

  libtorrent::bencode(std::ostream_iterator<char>(ofs), resume_data);
  ofs.close();
  NOTICE_LOG("[%s] generate resume data to file: %s", infohash_.c_str(), task_resume_file_name.c_str());
  return;
}

void GroupTask::DeleteResumeFile() const {
  std::string task_resume_file_name = kGroupConfig.resume_dir();
  task_resume_file_name += "/" + infohash_ + ".resume";
  unlink(task_resume_file_name.c_str());
  NOTICE_LOG("[%s] delete resume data file:%s", infohash_.c_str(), task_resume_file_name.c_str());

  if (!resume_file_.empty()) {
    unlink(resume_file_.c_str());
  }

  if (!tmp_save_path_.empty()) {
    rmdir(tmp_save_path_.c_str());
  }
}

int GroupTask::CheckCred(
    const UserCred &cred) const {
  // if operated by root or task's owner
  if (cred.uid == 0 || cred.uid == cred_.uid) {
    return 0;
  }
  return -1;
}

void GroupTask::Resume() {
  torrent_handle_.resume();
  torrent_handle_.auto_managed(true);
}

void GroupTask::Pause() {
  torrent_handle_.auto_managed(false);
  torrent_handle_.pause();
}

void GroupTask::ControlTask(ControlTaskType::type type) {
  switch (type) {
    case ControlTaskType::CANCEL:
      control_status_ = CONTROL_STATUS_CANCELED;
      RemoveTorrent(true);    // remove by user
      break;

    case ControlTaskType::PAUSE:
      control_status_ = CONTROL_STATUS_PAUSED;
      Pause();
      break;

    case ControlTaskType::RESUME:
      control_status_ = CONTROL_STATUS_RESUME;
      Resume();
      break;

    default:
      WARNING_LOG("[%s] control task ,but type[%d] is unknown.", infohash_.c_str(), type);
  }
}

void GroupTask::StopClusterTask() {
  if (cluster_task_) {
    torrent_status ts = torrent_handle_.status(0);
    cluster_task_->StopDownload();
    if (torrent_handle_.is_valid()) {
      stat_.downloaded_from_hdfs = cluster_task_->cluster_total_download();
      NOTICE_LOG("[%s] hadoop download: %lld, p2p download: %lld",
                  infohash_.c_str(), stat_.downloaded_from_hdfs,
                  ts.total_payload_download - stat_.downloaded_from_hdfs);
    }
  }
}

void GroupTask::RemoveTorrent(bool is_remove_by_user) {
  StopClusterTask();
  torrent_status ts = torrent_handle_.status(0);
  if (torrent_handle_.is_valid()) {
    UpdateTaskStatus();
    stat_.payload_downloaded = ts.total_payload_download;
    stat_.payload_uploaded = ts.total_payload_upload;
    stat_.progress_ppm = ts.progress_ppm;
    if (stat_.time_for_download) {
      stat_.time_for_seeding  = time(NULL) - stat_.start_time - stat_.time_for_download_metadata
          - stat_.time_for_check_files - stat_.time_for_download;
    }

    // if comes here, means seeding end, we can assert seeding finished
    GroupManager::GetInstance().RemoveTorrentTmp(torrent_handle_, infohash_);
    task_status_.is_task_finished = true;
    task_status_.time_for_seeding = stat_.time_for_seeding;
    task_status_.end_time = static_cast<int64_t>(time(NULL));

    if (!is_remove_by_user) {
      // normal removed
      task_status_.state = torrent_status::finished;
      task_status_.state_string = "FINISHED";
      control_status_ = CONTROL_STATUS_FINISHED;
    } else {
      task_status_.state = static_cast<int32_t>(CONTROL_STATUS_CANCELED);
      task_status_.state_string = "CANCELED";
      control_status_ = CONTROL_STATUS_CANCELED;
    }

    if (is_timeout_) {
      task_status_.state = static_cast<int32_t>(CONTROL_STATUS_TIMEOUT);
      task_status_.state_string = "TIMEOUT";
    }

    // persit it, so if finished but terminate, resume will keep the latest state
    Persist();
  }
}

void GroupTask::SeedingTimerCallback(const error_code &ec) {
  if (ec) {
    DEBUG_LOG("[%s] seeding timer canceled, %s.", infohash_.c_str(), ec.message().c_str());
    return;
  }
  NOTICE_LOG("[%s] download finished, will quit.", infohash_.c_str());
  RemoveTorrent(false);
}

void GroupTask::UpdateTaskStatus() {
  torrent_status ts = torrent_handle_.status(0);
  task_status_.payload_downloaded = ts.total_payload_download;
  task_status_.payload_uploaded = ts.total_payload_upload;
  task_status_.state = ts.state;
  task_status_.download_rate = ts.download_rate;
  task_status_.upload_rate = ts.upload_rate;
  task_status_.progress = ts.progress;
  task_status_.progress_ppm = ts.progress_ppm;

  // update state string
  switch (ts.state) {
    case torrent_status::queued_for_checking:
      task_status_.state_string = "CHECKQ";
      break;
    case torrent_status::checking_files:
      task_status_.state_string = "CHECKING";
      break;
    case torrent_status::downloading_metadata:
      task_status_.state_string = "DTORRENT";
      break;
    case torrent_status::downloading:
      task_status_.state_string = "DOWNLOAD";
      break;
    case torrent_status::finished:
      task_status_.state_string = "FINISHED";
      break;
    case torrent_status::seeding:
      task_status_.state_string = "SEEDING";
      break;
    case torrent_status::allocating:
      task_status_.state_string = "ALLOCATING";
      break;
    case torrent_status::checking_resume_data:
      task_status_.state_string = "CHECKRESUME";
      break;
    default:
      task_status_.state_string = "UNKNOWN";
      break;
  }

  if (control_status_ == CONTROL_STATUS_PAUSED) {
    task_status_.state = static_cast<int32_t>(CONTROL_STATUS_PAUSED);
    task_status_.state_string = "PAUSED";
  }

}

void GroupTask::ToSeeding() {
  torrent_status ts = torrent_handle_.status(0);
  LogProgress(ts);
  UpdateTaskStatus();
  if (params_.seeding_time == -1) {
    NOTICE_LOG("[%s] seeding for infinite", infohash_.c_str());
    return;
  }

  int seeding_time = 0;
  if (params_.seeding_time >= 0) {
    seeding_time = params_.seeding_time;
  } else {
    int upload_limit = ts.uploads_limit > 0 ? ts.uploads_limit : kGroupConfig.upload_rate_limit();
    seeding_time = (ts.num_peers + 1) * ts.total_payload_download / (1 + ts.num_seeds) / (upload_limit + 1) / 2;
    int tmp = ts.total_download / (ts.download_rate + 1);
    if (tmp < seeding_time) {
      seeding_time = tmp;
    }
  }
  NOTICE_LOG("[%s] seeding for %d seconds", infohash_.c_str(), seeding_time);
  seeding_timer_.expires_from_now(seconds(seeding_time));
  seeding_timer_.async_wait(boost::bind(&GroupTask::SeedingTimerCallback, this, _1));
}

void GroupTask::TimeoutTimerCallback(const error_code &ec) {
  if (ec) {
    DEBUG_LOG("[%s] timeout timer canceled.", infohash_.c_str());
    return;
  }
  WARNING_LOG("[%s] download timeout, will quit.", infohash_.c_str());
  if (!torrent_handle_.status(0).is_finished) {
    is_timeout_ = true;
  }
  RemoveTorrent(false);
  error_code timer_ec;
  timeout_timer_.cancel(timer_ec);
}

void GroupTask::HangCheckCallback() {
  torrent_status ts = torrent_handle_.status(0);
  LogProgress(ts);
  UpdateTaskStatus();
  if (params_.need_save_resume && ts.has_metadata && ts.need_save_resume) {
    torrent_handle_.save_resume_data();
  }
  if (ts.progress_ppm == 1000000) {
    return;
  }

  time_t now = time(NULL);
  if ((ts.state == torrent_status::downloading && ts.total_payload_download == last_check_downloaded_)
      || (ts.state == torrent_status::downloading_metadata &&
          !GroupManager::GetInstance().thrift_tracker().HaveSeed())) {
    if (last_check_time_ + params_.hang_timeout - now <= 0) {
      FATAL_LOG("download timeout, maybe noseeder.");
      is_timeout_ = true;
      RemoveTorrent(false);
      return;
    }
  } else {
    last_check_time_ = now;
    last_check_downloaded_ = ts.total_payload_download;
  }

  // if download limit more than 2M, and down_rate less than 800K in 10 times, reconnect
  if (params_.download_limit > 2048 * 1024 &&
      ts.download_rate < 800 * 1024 &&
      control_status_ != CONTROL_STATUS_PAUSED) {
    ++low_downrate_times_;
    if (low_downrate_times_ > 9) {
      torrent_handle_.pause();
      torrent_handle_.resume();
      low_downrate_times_ = 0;
    }
  }

  // check mem limit
  if (params_.mem_limit > 0) {
    static const long PAGE_SIZE = sysconf(_SC_PAGESIZE);
    long virt, rss;
    FILE *fp = fopen("/proc/self/statm", "r");
    fscanf(fp, "%ld%ld", &virt, &rss);
    fclose(fp);
    rss = rss * PAGE_SIZE / 1024 / 1024;
    if (rss > params_.mem_limit) {
      FATAL_LOG("rss(%ldM) exceed memery limit(%d)\n", rss, params_.mem_limit);
      is_mem_exceed_ = true;
      RemoveTorrent(false);
      return;
    }
  }
}

int GroupTask::OnTorrentFinished() {
  if (params_.dynamic_allocate >= 0) {
    // check if is really finished
    libtorrent::bitfield pieces = torrent_handle_.status(0).pieces;
    DEBUG_LOG("pieces.count() = %d, org.count() = %d", pieces.count(), org_pieces_.count());
    boost::intrusive_ptr<torrent_info const> ti = torrent_handle_.torrent_file();
    int num_pieces = ti->num_pieces();  // defend for empty file
    if (pieces.count() < org_pieces_.count() && num_pieces > 0) {
      // not really finished
      return 0;
    }
  }

  stat_.time_for_download = time(NULL) - stat_.start_time
      - stat_.time_for_download_metadata - stat_.time_for_check_files;
  task_status_.time_for_download = stat_.time_for_download;
  if (params_.need_down_to_tmp_first) {
    NOTICE_LOG("mv data from %s to %s", tmp_save_path_.c_str(), params_.save_path.c_str());
    torrent_handle_.move_storage(params_.save_path);
    return 0;
  }
  return OnStorageMoved();
}

int GroupTask::OnStorageMoved() {
  if (CorrectModeAndSymlinks() != 0) {
    return -1;
  }
  ToSeeding();
  return 0;
}

int GroupTask::OnHashFailed(const libtorrent::hash_failed_alert *alert) {
  WARNING_LOG("alert: %s.", alert->message().c_str());
  if (cluster_task_) {
    cluster_task_->AddHashFailedPiece(alert->piece_index);
  }

  return 0;
}

int GroupTask::OnSaveResumeData(
    const libtorrent::save_resume_data_alert *alert) {
  std::ofstream ofs(resume_file_.c_str(), std::ios::binary);
  if (!ofs) {
    WARNING_LOG("open file failed: %s.", resume_file_.c_str());
    return -1;
  }
  libtorrent::bencode(std::ostream_iterator<char>(ofs), *(alert->resume_data));
  ofs.close();
  return 0;
}

int GroupTask::OnStateChanged(const libtorrent::state_changed_alert *alert) {
  boost::intrusive_ptr<torrent_info const> ti = torrent_handle_.torrent_file();
  if (alert->state != torrent_status::downloading_metadata && ti &&
      params_.dynamic_allocate >= 0 && !has_pre_allocate_thread_start_) {
    boost::thread tmp_thread(boost::bind(&GroupTask::PreAllocateThread, this));
    allocate_threads_.swap(tmp_thread);
    has_pre_allocate_thread_start_ = true;
  }

  if (alert->state != torrent_status::downloading) {
    return 0;
  }

  stat_.time_for_check_files = time(NULL) - stat_.start_time - stat_.time_for_download_metadata;
  task_status_.time_for_check_files = stat_.time_for_check_files;

  if (params_.debug && params_.patition_download) {
    std::vector<int> file_priorities = torrent_handle_.file_priorities();
    for (unsigned i = 0; i < file_priorities.size(); ++i) {
      DEBUG_LOG("[%s] file %d priorities: %d", infohash_.c_str(), i, file_priorities[i]);
    }
  }

  cluster_config_entry cluster_config;
  if (ti) {
      BytesToHex(ti->info_hash().to_string(), &stat_.infohash);
      stat_.total_size = ti->total_size();
      stat_.piece_length = ti->piece_length();
      stat_.num_files = ti->num_files();
      stat_.num_paths = ti->get_paths().size();
      stat_.num_symlinks = ti->files().get_symlink_file().size();
      stat_.num_pieces = ti->num_pieces();
      cluster_config = ti->cluster_config();
  }

  if (cluster_task_.get() == NULL) {
    if (cluster_config.port != 0 && !cluster_config.host.empty() &&
        !cluster_config.user.empty() && !cluster_config.passwd.empty()) {
      if (!ParseSyms()) {
        NOTICE_LOG("[%s] Not support cluster(hadoop) download.", infohash_.c_str());
        return false;
      }
      NOTICE_LOG("[%s] Support hadoop download, will download from hadoop.", infohash_.c_str());
      stat_.is_hdfs_download = true;
      std::stringstream strm;
      strm << "hdfs://" << cluster_config.user << ':' << cluster_config.passwd << '@'
           << cluster_config.host << ':' << cluster_config.port << cluster_config.prefix_path;
      stat_.hdfs_address = strm.str();
      cluster_task_.reset(new GroupClusterTask(cluster_config,
                                               torrent_handle_,
                                               params_.cluster_thread_num,
                                               params_.ignore_hdfs_error));
    }
  }

  if (cluster_task_.get() != NULL) {
    NOTICE_LOG("[%s] will start cluster thread.", infohash_.c_str());
    if (!cluster_task_->StartDownload()) {
      FATAL_LOG("[%s] start cluster download failed.", infohash_.c_str());
      RemoveTorrent(false);
      return false;
    }

    // push it into queue here, so cluster_task_ will not be delete until task finished
    GroupManager::GetInstance().PushClusterThreadQueue(cluster_task_);
    // need set signal action again, because hdfs will set itself
    SetSignalAction();
  }

  return 0;
}

int GroupTask::OnMetadataReceived() {
  stat_.time_for_download_metadata = time(NULL) - stat_.start_time;
  boost::intrusive_ptr<torrent_info const> ti = torrent_handle_.torrent_file();

  // update infohash_ for web url
  if (is_torrent_url_) {
    infohash_ = libtorrent::to_hex(ti->info_hash().to_string());
    params_.infohash = infohash_;
    task_status_.infohash = infohash_;
    // TODO need update group manager
    GroupManager::GetInstance().UpdateInfohashByTorrentUrl(params_.torrent_url, infohash_);
  }
  pre_file_priorities_.resize(ti->num_files(), 1);
  if (params_.patition_download) {
    std::vector<int> file_priorities;
    ParseNeedDownloadFiles<int>(params_.include_regex, params_.exclude_regex, *ti, &file_priorities);
    torrent_handle_.prioritize_files(file_priorities);
    pre_file_priorities_ = file_priorities;
  }
  SetOrgPieces(ti);

  if (!params_.save_torrent_path.empty()) {
    libtorrent::create_torrent ct(*ti);
    libtorrent::entry te = ct.generate();
    if (!params_.save_torrent_path.empty()) {
      std::ofstream ofs(params_.save_torrent_path.c_str());
      if (!ofs) {
        WARNING_LOG("open file(%s) to save torrent failed", params_.save_torrent_path.c_str());
      } else {
        libtorrent::bencode(std::ostream_iterator<char>(ofs), te);
        ofs.close();
      }
    }
  }
  return 0;
}

void GroupTask::SetOrgPieces(const boost::intrusive_ptr<torrent_info const> ti) {
    // all files should be pre-allocate before download
    // store org_pieces
    int num_pieces = ti->num_pieces();
    if (num_pieces <= 0) {
      num_pieces = 1;  // empty files, num_pieces is 0, we should protect this situation
    }
    org_pieces_.resize(num_pieces, false);

    for (unsigned i = 0; i < pre_file_priorities_.size(); ++i) {
      libtorrent::file_entry fe = ti->file_at(i);
      int first_piece = ti->map_file(i, 0, 0).piece;
      int last_piece = ti->map_file(i, (std::max)(fe.size - 1, libtorrent::size_type(0)), 0).piece;
      // because this state is not downloading, if we just use torrent_.status(0),pieces
      // all bitmask will be set to 0, and this is not true, so we have to set manually
      for (int j = first_piece; j <= last_piece; ++j) {
        if (pre_file_priorities_[i] > 0 || org_pieces_.get_bit(j)) {
          org_pieces_.set_bit(j);
        } else {
          org_pieces_.clear_bit(j);
        }  // if pre_file_priorities_[i] > 0
      }  // for j
    }  // for i
}

int GroupTask::CorrectModeAndSymlinks() {
  std::string save_path = params_.save_path;
  boost::intrusive_ptr<torrent_info const> ti = torrent_handle_.torrent_file();
  if (!ti) {
      FATAL_LOG("[%s] can't get torrent info", infohash_.c_str());
      return -1;
  }
  // create and change directory mode
  if (MakeCorrectDir(*ti) != 0) {
    FATAL_LOG("[%s] make dir failed", infohash_.c_str());
    return -1;
  }

  // file chmod
  std::vector<int> file_priorities;
  if (params_.dynamic_allocate >= 0) {
    file_priorities = pre_file_priorities_;
  } else {
    file_priorities = torrent_handle_.file_priorities();
  }

  for (int i = 0; i < ti->num_files(); ++i) {
    libtorrent::file_entry fe = ti->file_at(i);
    std::string file_name = save_path + "/" + fe.path;
    if (file_priorities[i] == 0) {
      unlink(file_name.c_str());  // delete over files, ignore fail
      DEBUG_LOG("unlink file %s", file_name.c_str());
      continue;
    }
    if (chmod(file_name.c_str(), fe.mode) != 0) {
      FATAL_LOG("[%s] file(%s) chmod to %o failed, error[%d]:%s", infohash_.c_str(),
              file_name.c_str(), fe.mode, errno, strerror(errno));
      return -1;
    }
  }

  // create symlinks files
  const std::vector<symlink_file> &symlinks = ti->files().get_symlink_file();

  std::vector<boost::regex> include_regex, exclude_regex;
  TurnStdListToRegexList(params_.include_regex, &include_regex);
  TurnStdListToRegexList(params_.exclude_regex, &exclude_regex);

  for (std::vector<symlink_file>::const_iterator it = symlinks.begin(); it != symlinks.end(); ++it) {
    bool need = false;
    if (params_.patition_download) {
      RegexMatch regex_m(it->path);
      if (include_regex.empty() ||
          std::find_if(include_regex.begin(), include_regex.end(), regex_m) != include_regex.end()) {
        need = true;
      }
      if (std::find_if(exclude_regex.begin(), exclude_regex.end(), regex_m) !=exclude_regex.end()) {
        need = false;
      }
    } else {
      need = true;
    }
    if (!need) {
      continue;
    }

    std::string path = save_path + "/" + it->path;
    if (symlink(it->symlink_path.c_str(), path.c_str()) < 0) {
      FATAL_LOG("[%s] create symlink file %s -> %s failed.", infohash_.c_str(), path.c_str(), it->symlink_path.c_str());
      return -1;
    }
    TRACE_LOG("[%s] create symlink file %s -> %s success.", infohash_.c_str(), path.c_str(), it->symlink_path.c_str());
  }  // for std::vector

  return 0;
}

// is_before_download: if true, means mkdir before download,
// else means mkdir after download finished
int GroupTask::MakeCorrectDir(const torrent_info &ti, bool is_before_download) {
  std::string save_path = params_.save_path;
  const std::vector<std::string>& paths = ti.get_paths();
  const std::vector<mode_t>& modes = ti.get_paths_mode();
  int path_len = paths.size();

  std::vector<boost::regex> include_regex, exclude_regex;
  TurnStdListToRegexList(params_.include_regex, &include_regex);
  TurnStdListToRegexList(params_.exclude_regex, &exclude_regex);

  for (int i = 0; i < path_len; ++i) {
    std::string path = save_path + "/" + paths[i];
    mode_t mode = modes[i];
    struct stat statbuf;
    if (stat(path.c_str(), &statbuf) != 0) {
      bool need = false;
      if (params_.patition_download) {
        RegexMatch regex_m(paths[i]);
        if (include_regex.empty() ||
            std::find_if(include_regex.begin(), include_regex.end(), regex_m) != include_regex.end()) {
          need = true;
        }
        if (std::find_if(exclude_regex.begin(), exclude_regex.end(), regex_m) != exclude_regex.end()) {
          need = false;
        }
      } else {
        need = true;
      }
      if (is_before_download && !need) {
        continue;
      }
      if (!check_and_mkdir_r(path.c_str(), mode) != 0) {
        WARNING_LOG("[%s] mkdir %s(%o) failed.", infohash_.c_str(), path.c_str(), mode);
        return -1;
      }
    } else if (statbuf.st_mode & S_IFDIR) {
      if (chmod(path.c_str(), mode) != 0) {
        WARNING_LOG("[%s] path(%s) chmod to %o failed.", infohash_.c_str(), path.c_str(), mode);
        return -1;
      }
    } else {
      WARNING_LOG("[%s] path %s is not a dir, can't change mode.", infohash_.c_str(), path.c_str());
      return -1;
    }
  }

  return 0;
}

void GroupTask::PreAllocateThread() {
  DEBUG_LOG("[%s] start PreAllocateThread...", infohash_.c_str());
  const int kDefaultMultiple = 50;
  boost::intrusive_ptr<torrent_info const> ti = torrent_handle_.torrent_file();

  std::string save_path = params_.save_path;
  int num_pieces = ti->num_pieces();
  int piece_length = ti->piece_length();

  // if dynamic_allocate is 0 or error, use default
  int multiple = params_.dynamic_allocate > 0 ? params_.dynamic_allocate : kDefaultMultiple;
  const off_t kEachLength = multiple * piece_length;
  int last_download_index = 0;

  std::vector<int> piece_priority(num_pieces, 0);
  torrent_handle_.set_share_mode(false);
  // after set_share_mode called, all file_priorities will be set to 1, so we should set again
  torrent_handle_.prioritize_files(pre_file_priorities_);
  // set all piece's priority to 0, thus all piece won't been download before set 1 again.
  torrent_handle_.prioritize_pieces(piece_priority);

  // first, mkdir
  MakeCorrectDir(*ti, true);

  // allocate each file
  for (int i = 0; i < ti->num_files(); ++i) {
    libtorrent::file_entry fe = ti->file_at(i);
    if (pre_file_priorities_[i] == 0 || fe.pad_file) {
      continue;
    }

    std::string file_name = save_path + "/" + fe.path;
    int first_piece = ti->map_file(i, 0, 0).piece;
    int last_piece = ti->map_file(i, (std::max)(fe.size - 1, libtorrent::size_type(0)), 0).piece;
    // check if file exists and file size. if file has correct size, then we just continue
    // because if we allocate again, libtorrent may think all pieces of this file has been downloaded,
    // so after allocate this file, libtorrent won't download again, thus we may get an empty file.
    struct stat file_buf;
    if (stat(file_name.c_str(), &file_buf) == 0 && file_buf.st_size == fe.size) {
      NOTICE_LOG("[%s] file %s has size:%ld, and goat size is %ld, so don't allocate again",
                  infohash_.c_str(), file_name.c_str(), file_buf.st_size, fe.size);
      // set piece correct priority
      for (int i = first_piece; i <= last_piece; ++i) {
        piece_priority[i] = 1;
      }
      torrent_handle_.prioritize_pieces(piece_priority);
      last_download_index = last_piece;
      continue;
    }

    int fd = open(file_name.c_str(), O_RDWR | O_CREAT | O_TRUNC, fe.mode);
    if (fd < 0) {
      // if one file allocate failed, all_allocate_size will be error if continue,
      // so, just break and don't use dynamic pre-allocate mode
      WARNING_LOG("[%s] open file %s failed, don't use dynamic pre-allocate mode, use normal mode:errno[%d]:%s",
                   infohash_.c_str(), file_name.c_str(), errno, strerror(errno));
      close(fd);
      break;
    }
    DEBUG_LOG("[%s] open file %s success, size is %ld", infohash_.c_str(), file_name.c_str(), fe.size);

    int file_download_index = first_piece;
    off_t current_offset = 0;
    while (current_offset < fe.size) {
      off_t each_len = kEachLength;
      if ((current_offset + kEachLength) > fe.size) {
        each_len = fe.size - current_offset;
      }
      int fallocate_ret = posix_fallocate(fd, current_offset, each_len);
      if (fallocate_ret != 0 && fallocate_ret != EINVAL) {
          WARNING_LOG("[%s] posix_fallocate failed:ret=%d, offset=%ld, len=%ld, file=%s\n",
                 infohash_.c_str(), fallocate_ret, current_offset, each_len, file_name.c_str());
          break;
      }
      DEBUG_LOG("[%s] allocate current_offset:%ld", infohash_.c_str(), current_offset);

      current_offset += each_len;
      if (current_offset >= fe.size) {
        // this file has been success allocate, goto next one
        DEBUG_LOG("[%s] current_offset size is %ld", infohash_.c_str(), current_offset);
        break;
      }

      int current_index = current_offset / piece_length;
      for (int i = file_download_index; i <= (current_index + first_piece); ++i) {
        piece_priority[i] = 1;
      }
      torrent_handle_.prioritize_pieces(piece_priority);
      file_download_index = current_index + first_piece;
    }  // while

    close(fd);

    // ensure all pieces of this file can be download
    if (file_download_index < last_piece) {
      for (int i = file_download_index; i <= last_piece; ++i) {
        piece_priority[i] = 1;
      }
      torrent_handle_.prioritize_pieces(piece_priority);
      file_download_index = last_piece;
    }
    last_download_index = last_piece;
  }  // for

  // set pieces again, because pre allocate may be failed,
  // so set pieces again, ensure all piece can be download
  if (last_download_index < num_pieces) {
    for (int i = last_download_index; i < num_pieces; ++i) {
      if (org_pieces_.get_bit(i)) {
        piece_priority[i] = 1;
      }
    }
    torrent_handle_.prioritize_pieces(piece_priority);
  }

  NOTICE_LOG("[%s] pre allocate thread exit", infohash_.c_str());
}

}  // namespace group
}  // namespace bbts


text:
// Copyright 2011 Dean Michael Berris (dberris@google.com).
// Copyright 2011 Google, Inc.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_20110819
#define NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_20110819

#include <memory>
#include <boost/asio/ssl.hpp>
#include <network/protocol/http/client/connection/connection_delegate.hpp>
#include <network/protocol/http/client/options.hpp>
#include <boost/enable_shared_from_this.hpp>

namespace boost {
namespace asio {
class io_service;
}  // namespace asio
}  // namespace boost

namespace network {
namespace http {

struct ssl_delegate : connection_delegate, boost::enable_shared_from_this<ssl_delegate> {
  ssl_delegate(boost::asio::io_service & service,
               client_options const &options);

  virtual void connect(boost::asio::ip::tcp::endpoint & endpoint,
                       std::string const &host,
                       std::function<void(boost::system::error_code const &)> handler);
  virtual void write(boost::asio::streambuf & command_streambuf,
                     std::function<void(boost::system::error_code const &, size_t)> handler);
  virtual void read_some(boost::asio::mutable_buffers_1 const & read_buffer,
                         std::function<void(boost::system::error_code const &, size_t)> handler);
  ~ssl_delegate();

 private:
  boost::asio::io_service & service_;
  client_options options_;
  std::unique_ptr<boost::asio::ssl::context> context_;
  std::unique_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> socket_;

  ssl_delegate(ssl_delegate const &);  // = delete
  ssl_delegate& operator=(ssl_delegate);  // = delete

  void handle_connected(boost::system::error_code const & ec,
                        std::function<void(boost::system::error_code const &)> handler);
};

}  // namespace http
}  // namespace network

#endif /* NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_20110819 */

max_stars_repo_name: iBeacons/cpp-netlib

max_issues_repo_name: iBeacons/cpp-netlib

max_forks_repo_name: iBeacons/cpp-netlib