text:
using std::list;
using std::map;
using std::string;
using std::vector;

namespace palo {

// Process push command, the main logical is as follows:
//    a. related tables not exist:
//        current table isn't in schemachange state, only push for current table
//    b. related tables exist
//       I.  current table is old table:
//           push for current table and than convert data for related tables
//       II. current table is new table:
//           this usually means schema change is over,
//           clear schema change info in both current table and related tables,
//           finally we will only push for current tables
OLAPStatus PushHandler::process(
        SmartOLAPTable olap_table,
        const TPushReq& request,
        PushType push_type,
        vector<TTabletInfo>* tablet_info_vec) {
    OLAP_LOG_INFO("begin to push data. [table='%s' version=%ld]",
                   olap_table->full_name().c_str(), request.version);

    OLAPStatus res = OLAP_SUCCESS;
    _request = request;
    _olap_table_arr.clear();
    _olap_table_arr.push_back(olap_table);
    vector<TableVars> table_infoes(1);
    table_infoes[0].olap_table = olap_table;

    bool is_push_locked = false;
    bool is_new_tablet = false;
    bool is_new_tablet_effective = false;

    // 1. Get related tablets first if tablet in alter table status,
    TTabletId tablet_id;
    TSchemaHash schema_hash;
    AlterTabletType alter_table_type;
    SmartOLAPTable related_olap_table;
    _obtain_header_rdlock();
    bool is_schema_changing = olap_table->get_schema_change_request(
            &tablet_id, &schema_hash, NULL, &alter_table_type);
    _release_header_lock();

    if (is_schema_changing) {
        related_olap_table = OLAPEngine::get_instance()->get_table(tablet_id, schema_hash);
        if (NULL == related_olap_table.get()) {
            OLAP_LOG_WARNING("can't find olap table, clear invalid schema change info."
                             "[table=%ld schema_hash=%d]", tablet_id, schema_hash);
            _obtain_header_wrlock();
            olap_table->clear_schema_change_request();
            _release_header_lock();
            is_schema_changing = false;
        } else {
            // _olap_table_arr is used to obtain header lock,
            // to avoid deadlock, we must lock tablet header in time order.
            if (related_olap_table->creation_time() < olap_table->creation_time()) {
                _olap_table_arr.push_front(related_olap_table);
            } else {
                _olap_table_arr.push_back(related_olap_table);
            }
        }
    }

    // Obtain push lock to avoid simultaneously PUSH and
    // conflict with alter table operations.
    for (SmartOLAPTable table : _olap_table_arr) {
        table->obtain_push_lock();
        table->set_push_status(PUSH_RUNNING, _request.version);
    }
    is_push_locked = true;

    if (is_schema_changing) {
        _obtain_header_rdlock();
        is_schema_changing = olap_table->get_schema_change_request(
                &tablet_id, &schema_hash, NULL, &alter_table_type);
        _release_header_lock();

        if (!is_schema_changing) {
            OLAP_LOG_INFO("schema change info is cleared after base table get related tablet, "
                          "maybe new tablet reach at the same time and load firstly. ",
                          "[base_table='%s' table='%s' version=%ld]",
                          olap_table->full_name().c_str(),
                          related_olap_table->full_name().c_str(),
                          _request.version);
        } else if (related_olap_table->creation_time() > olap_table->creation_time()) {
            // If current table is old table, append it to table_infoes
            table_infoes.push_back(TableVars());
            TableVars& new_item = table_infoes.back();
            new_item.olap_table = related_olap_table;
        } else {
            // if current table is new table, clear schema change info
            res = _clear_alter_table_info(olap_table, related_olap_table);
            if (res != OLAP_SUCCESS) {
                OLAP_LOG_WARNING("fail to clear schema change info. [res=%d]", res);
                goto EXIT;
            }

            OLAP_LOG_INFO("data of new table is generated, stop convert from base table. "
                          "[base_table='%s' table='%s' version=%ld]",
                          related_olap_table->full_name().c_str(),
                          olap_table->full_name().c_str(),
                          _request.version);
            is_new_tablet_effective = true;
        }
    }

    // To keep logic of alter_table/rollup_table consistent
    if (table_infoes.size() == 1) {
        table_infoes.resize(2);
    }

    // 2. validate request: version and version_hash chek
    _obtain_header_rdlock();
    res = _validate_request(table_infoes[0].olap_table,
                            table_infoes[1].olap_table,
                            is_new_tablet_effective,
                            push_type);
    _release_header_lock();
    if (res != OLAP_SUCCESS) {
        OLAP_LOG_WARNING("fail to validate request. [res=%d table='%s' version=%ld]",
                         res, olap_table->full_name().c_str(), _request.version);
        goto EXIT;
    }

    // 3. Remove reverted version including delta and cumulative,
    //    which will be deleted by background thread
    _obtain_header_wrlock();
    for (TableVars& table_var : table_infoes) {
        if (NULL == table_var.olap_table.get()) {
            continue;
        }

        res = _get_versions_reverted(table_var.olap_table,
                                     is_new_tablet,
                                     push_type,
                                     &(table_var.unused_versions));
        if (res != OLAP_SUCCESS) {
            OLAP_LOG_WARNING("failed to get reverted versions. "
                             "[res=%d table='%s' version=%ld]",
                             res, table_var.olap_table->full_name().c_str(), _request.version);
            goto EXIT;
        }

        if (table_var.unused_versions.size() != 0) {
            res = _update_header(table_var.olap_table,
                                 &(table_var.unused_versions),
                                 &(table_var.added_indices),
                                 &(table_var.unused_indices));
            if (res != OLAP_SUCCESS) {
                OLAP_LOG_WARNING("fail to update header for revert. "
                                 "[res=%d table='%s' version=%ld]",
                                 res, table_var.olap_table->full_name().c_str(), _request.version);
                goto EXIT;
            }

            _delete_old_indices(&(table_var.unused_indices));
        }

        // If there are more than one table, others is doing alter table
        is_new_tablet = true;
    }
    _release_header_lock();

    // 4. Save delete condition when push for delete
    if (push_type == PUSH_FOR_DELETE) {
        _obtain_header_wrlock();
        DeleteConditionHandler del_cond_handler;

        for (TableVars& table_var : table_infoes) {
            if (table_var.olap_table.get() == NULL) {
                continue;
            }

            res = del_cond_handler.store_cond(
                    table_var.olap_table, request.version, request.delete_conditions);
            if (res != OLAP_SUCCESS) {
                OLAP_LOG_WARNING("fail to store delete condition. [res=%d table='%s']",
                                 res, table_var.olap_table->full_name().c_str());
                goto EXIT;
            }

            res = table_var.olap_table->save_header();
            if (res != OLAP_SUCCESS) {
                OLAP_LOG_WARNING("fail to save header. [res=%d table='%s']",
                                 res, table_var.olap_table->full_name().c_str());
                goto EXIT;
            }
        }

        _release_header_lock();
    }

    // 5. Convert local data file into delta_file and build index,
    //    which may take a long time
    res = _convert(table_infoes[0].olap_table,
                   table_infoes[1].olap_table,
                   &(table_infoes[0].added_indices),
                   &(table_infoes[1].added_indices),
                   alter_table_type);
    if (res != OLAP_SUCCESS) {
        OLAP_LOG_WARNING("fail to convert data. [res=%d]", res);
        goto EXIT;
    }

    // Update table header: add new version and remove reverted version
    _obtain_header_wrlock();
    for (TableVars& table_var : table_infoes) {
        if (NULL == table_var.olap_table.get()) {
            continue;
        }

        res = _update_header(table_var.olap_table,
                             &(table_var.unused_versions),
                             &(table_var.added_indices),
                             &(table_var.unused_indices));
        if (res != OLAP_SUCCESS) {
            OLAP_LOG_WARNING("fail to update header of new delta."
                             "[res=%d table='%s' version=%ld]",
                             res, table_var.olap_table->full_name().c_str(), _request.version);
            goto EXIT;
        }
    }
    _release_header_lock();

    // 6. Delete unused versions which include delta and commulative,
    //    which, in fact, is added to list and deleted by background thread
    for (TableVars& table_var : table_infoes) {
        if (NULL == table_var.olap_table.get()) {
            continue;
        }

        _delete_old_indices(&(table_var.unused_indices));
    }

EXIT:
    _release_header_lock();

    // Get tablet infos for output
    if (res == OLAP_SUCCESS || res == OLAP_ERR_PUSH_VERSION_ALREADY_EXIST) {
        if (tablet_info_vec != NULL) {
            _get_tablet_infos(table_infoes, tablet_info_vec);
        }
        res = OLAP_SUCCESS;
    }

    // Clear added_indices when error happens
    for (TableVars& table_var : table_infoes) {
        if (table_var.olap_table.get() == NULL) {
            continue;
        }

        for (OLAPIndex* olap_index : table_var.added_indices) {
            olap_index->delete_all_files();
            SAFE_DELETE(olap_index);
        }
    }

    // Release push lock
    if (is_push_locked) {
        for (SmartOLAPTable table : _olap_table_arr) {
            table->release_push_lock();
            table->set_push_status(PUSH_WAITING, -1);
        }
    }
    _olap_table_arr.clear();

    OLAP_LOG_INFO("finish to process push. [res=%d]", res);

    return res;
}

void PushHandler::_get_tablet_infos(
        const vector<TableVars>& table_infoes,
        vector<TTabletInfo>* tablet_info_vec) {
    for (const TableVars& table_var : table_infoes) {
        if (table_var.olap_table.get() == NULL) {
            continue;
        }

        TTabletInfo tablet_info;
        tablet_info.tablet_id = table_var.olap_table->tablet_id();
        tablet_info.schema_hash = table_var.olap_table->schema_hash();
        OLAPEngine::get_instance()->report_tablet_info(&tablet_info);
        tablet_info_vec->push_back(tablet_info);
    }
}

OLAPStatus PushHandler::_convert(
        SmartOLAPTable curr_olap_table,
        SmartOLAPTable new_olap_table,
        Indices* curr_olap_indices,
        Indices* new_olap_indices,
        AlterTabletType alter_table_type) {
    OLAPStatus res = OLAP_SUCCESS;
    RowCursor row;
    BinaryFile raw_file;
    IBinaryReader* reader = NULL;
    IWriter* writer = NULL;
    OLAPIndex* delta_index = NULL;
    uint32_t  num_rows = 0;

    do {
        OLAP_LOG_DEBUG("start to convert delta file.");

        std::vector<FieldInfo> tablet_schema = curr_olap_table->tablet_schema();

        //curr_olap_table->set_tablet_schema();
        tablet_schema = curr_olap_table->tablet_schema();

        // 1. Init BinaryReader to read raw file if exist,
        //    in case of empty push and delete data, this will be skipped.
        if (_request.__isset.http_file_path) {
            // open raw file
            if (OLAP_SUCCESS != (res = raw_file.init(_request.http_file_path.c_str()))) {
                OLAP_LOG_WARNING("failed to read raw file. [res=%d file='%s']",
                                 res, _request.http_file_path.c_str());
                res = OLAP_ERR_INPUT_PARAMETER_ERROR;
                break;
            }

            // create BinaryReader
            bool need_decompress = false;
            if (_request.__isset.need_decompress && _request.need_decompress) {
                need_decompress = true;
            }
            if (NULL == (reader = IBinaryReader::create(need_decompress))) {
                OLAP_LOG_WARNING("fail to create reader. [table='%s' file='%s']",
                                 curr_olap_table->full_name().c_str(),
                                 _request.http_file_path.c_str());
                res = OLAP_ERR_MALLOC_ERROR;
                break;
            }

            // init BinaryReader
            if (OLAP_SUCCESS != (res = reader->init(curr_olap_table, &raw_file))) {
                OLAP_LOG_WARNING("fail to init reader. [res=%d table='%s' file='%s']",
                                 res,
                                 curr_olap_table->full_name().c_str(),
                                 _request.http_file_path.c_str());
                res = OLAP_ERR_PUSH_INIT_ERROR;
                break;
            }
        }

        // 2. New OLAPIndex of curr_olap_table for current push
        OLAP_LOG_DEBUG("init OLAPIndex.");

        if (NULL == (delta_index = new(std::nothrow) OLAPIndex(
                curr_olap_table.get(),
                Version(_request.version, _request.version),
                _request.version_hash,
                (_request.push_type == TPushType::LOAD_DELETE),
                0, 0))) {
            OLAP_LOG_WARNING("fail to malloc OLAPIndex. [table='%s' size=%ld]",
                             curr_olap_table->full_name().c_str(), sizeof(OLAPIndex));
            res = OLAP_ERR_MALLOC_ERROR;
            break;
        }
        curr_olap_indices->push_back(delta_index);

        // 3. New Writer to write data into OLAPIndex
        OLAP_LOG_DEBUG("init writer. [table='%s' block_row_size=%lu]",
                       curr_olap_table->full_name().c_str(),
                       curr_olap_table->num_rows_per_row_block());

        if (NULL == (writer = IWriter::create(curr_olap_table, delta_index, true))) {
            OLAP_LOG_WARNING("fail to create writer. [table='%s']",
                             curr_olap_table->full_name().c_str());
            res = OLAP_ERR_MALLOC_ERROR;
            break;
        } else if (OLAP_SUCCESS != (res = writer->init())) {
            OLAP_LOG_WARNING(
                    "fail to init writer. [res=%d table='%s' version=%u version_hash=%lu]",
                    res, curr_olap_table->full_name().c_str(),
                    _request.version, _request.version_hash);
            break;
        }

        MemPool* mem_pool = writer->mem_pool();
        // 4. Init RowCursor
        if (OLAP_SUCCESS != (res = row.init(curr_olap_table->tablet_schema()))) {
            OLAP_LOG_WARNING("fail to init rowcursor. [res=%d]", res);
            break;
        }

        // 5. Read data from raw file and write into OLAPIndex of curr_olap_table
        if (_request.__isset.http_file_path) {
            // Convert from raw to delta
            OLAP_LOG_DEBUG("start to convert row file to delta.");

            while (!reader->eof()) {
                if (OLAP_SUCCESS != (res = writer->attached_by(&row))) {
                    OLAP_LOG_WARNING(
                            "fail to attach row to writer. [res=%d table='%s' read_rows=%u]",
                            res, curr_olap_table->full_name().c_str(), num_rows);
                    break;
                }

                res = reader->next(&row, mem_pool);
                if (OLAP_SUCCESS != res) {
                    OLAP_LOG_WARNING("read next row failed. [res=%d read_rows=%u]",
                                     res, num_rows);
                    break;
                } else {
                    writer->next(row);
                    num_rows++;
                }
            }

            reader->finalize();

            if (false == reader->validate_checksum()) {
                OLAP_LOG_WARNING("pushed delta file has wrong checksum.");
                res = OLAP_ERR_PUSH_BUILD_DELTA_ERROR;
                break;
            }
        }

        if (OLAP_SUCCESS != (res = writer->finalize())) {
            OLAP_LOG_WARNING("fail to finalize writer. [res=%d]", res);
            break;
        }

        OLAP_LOG_DEBUG("load the index.");

        if (OLAP_SUCCESS != (res = delta_index->load())) {
            OLAP_LOG_WARNING("fail to load index. [res=%d table='%s' version=%ld]",
                             res, curr_olap_table->full_name().c_str(), _request.version);
            break;
        }
        _write_bytes += delta_index->data_size();
        _write_rows += delta_index->num_rows();

        // 7. Convert data for schema change tables
        OLAP_LOG_TRACE("load to related tables of schema_change if possible. ");
        if (NULL != new_olap_table.get()) {
            SchemaChangeHandler schema_change;
            res = schema_change.schema_version_convert(
                    curr_olap_table,
                    new_olap_table,
                    curr_olap_indices,
                    new_olap_indices);
            if (res != OLAP_SUCCESS) {
                OLAP_LOG_WARNING("failed to change schema version for delta."
                                 "[res=%d new_table='%s']",
                                 res, new_olap_table->full_name().c_str());
            }

        }
    } while (0);

    SAFE_DELETE(reader);
    SAFE_DELETE(writer);
    OLAP_LOG_NOTICE_PUSH("processed_rows", "%d", num_rows);
    OLAP_LOG_TRACE("convert delta file end. [table='%s' res=%d]",
                   curr_olap_table->full_name().c_str(), res);

    return res;
}

OLAPStatus PushHandler::_validate_request(
        SmartOLAPTable olap_table_for_raw,
        SmartOLAPTable olap_table_for_schema_change,
        bool is_new_tablet_effective,
        PushType push_type) {
    const FileVersionMessage* latest_delta = olap_table_for_raw->lastest_delta();

    if (NULL == latest_delta) {
        const FileVersionMessage* latest_version = olap_table_for_raw->latest_version();

        // PUSH the first version when the version is 0, or
        // tablet is in alter table status.
        if (NULL == latest_version
                && (0 == _request.version || NULL != olap_table_for_schema_change.get())) {
            return OLAP_SUCCESS;
        } else if (NULL != latest_version
                && (latest_version->end_version() + 1 == _request.version)) {
            return OLAP_SUCCESS;
        }

        OLAP_LOG_WARNING("no last pushed delta, the comming version should be 0. [table='%s']",
                         olap_table_for_raw->full_name().c_str());
        return OLAP_ERR_PUSH_VERSION_INCORRECT;
    }

    if (is_new_tablet_effective) {
        OLAP_LOG_INFO("maybe a alter tablet has already created from base tablet. "
                       "[table='%s' version=%d]",
                       olap_table_for_raw->full_name().c_str(),
                       _request.version);
        if (push_type == PUSH_FOR_DELETE
                && _request.version == latest_delta->start_version()
                && _request.version_hash == latest_delta->version_hash()) {
            OLAP_LOG_INFO("base tablet has already convert delete version for new tablet. "
                          "[version=%ld version_hash=%lu]",
                          _request.version, _request.version_hash);
            return OLAP_ERR_PUSH_VERSION_ALREADY_EXIST;
        }
    } else {
        // Never allow two push has same version and version hash,
        // but same verson and different version hash is allowed.
        if (_request.version < latest_delta->start_version()
                || _request.version > latest_delta->start_version() + 1) {
            OLAP_LOG_WARNING(
                    "try to push a delta with incorrect version. "
                    "[new_version=%ld latest_version=%u "
                    "new_version_hash=%ld latest_version_hash=%lu]",
                    _request.version, latest_delta->start_version(),
                    _request.version_hash, latest_delta->version_hash());
            return OLAP_ERR_PUSH_VERSION_INCORRECT;
        } else if (_request.version == latest_delta->start_version()
                && _request.version_hash == latest_delta->version_hash()) {
            OLAP_LOG_WARNING(
                    "try to push a already exist delta. "
                    "[new_version=%ld latest_version=%u "
                    "new_version_hash=%ld latest_version_hash=%lu]",
                    _request.version, latest_delta->start_version(),
                    _request.version_hash, latest_delta->version_hash());
            return OLAP_ERR_PUSH_VERSION_ALREADY_EXIST;
        }
    }

    return OLAP_SUCCESS;
}

// The latest version can be reverted for following scene:
// user submit a push job and cancel it soon, but some
// tablets already push success.
OLAPStatus PushHandler::_get_versions_reverted(
        SmartOLAPTable olap_table,
        bool is_new_tablet,
        PushType push_type,
        Versions* unused_versions) {
    const FileVersionMessage* latest_delta = olap_table->lastest_delta();

    if (NULL == latest_delta) {
        const FileVersionMessage* latest_version = olap_table->latest_version();

        // PUSH the first version, and the version is 0
        if ((NULL == latest_version
                && (0 == _request.version || is_new_tablet))) {
            return OLAP_SUCCESS;
        } else if (NULL != latest_version
                && latest_version->end_version() + 1 == _request.version) {
            return OLAP_SUCCESS;
        }

        OLAP_LOG_WARNING("no last pushed delta, the comming version should be 0. [table='%s']",
                         olap_table->full_name().c_str());
        return OLAP_ERR_PUSH_VERSION_INCORRECT;
    }

    OLAP_LOG_DEBUG("latest deltas was founded. [table='%s' version=%d-%d]",
                   olap_table->full_name().c_str(),
                   latest_delta->start_version(), latest_delta->end_version());

    // Remove the cumulative delta that end_version == request.version()
    if (_request.version == latest_delta->start_version()) {
        Versions all_versions;
        olap_table->list_versions(&all_versions);

        for (Versions::const_iterator v = all_versions.begin(); v != all_versions.end(); ++v) {
            if (v->second == _request.version) {
                unused_versions->push_back(*v);
                OLAP_LOG_DEBUG("Add unused version. [table='%s' version=%d-%d]",
                               olap_table->full_name().c_str(), v->first, v->second);
            }
        }

        // Remove delete condition if current type is PUSH_FOR_DELETE,
        // this occurs when user cancel delete_data soon after submit it.
        if (push_type != PUSH_FOR_DELETE) {
            DeleteConditionHandler del_cond_handler;
            del_cond_handler.delete_cond(olap_table, _request.version, false);
        }
    }

    return OLAP_SUCCESS;
}

OLAPStatus PushHandler::_update_header(
        SmartOLAPTable olap_table,
        Versions* unused_versions,
        Indices* new_indices,
        Indices* unused_indices) {
    OLAPStatus res = OLAP_SUCCESS;

    res = olap_table->replace_data_sources(
            unused_versions,
            new_indices,
            unused_indices);
    if (res != OLAP_SUCCESS) {
        OLAP_LOG_FATAL("fail to replace data sources. [res=%d table='%s']",
                       res, olap_table->full_name().c_str());
        return res;
    }

    // Avoid double update
    new_indices->clear();
    unused_versions->clear();

    // Save header fail will not impact service for memory state
    // has already changed, but some data may lost when OLAPEngine restart;
    // Note we don't return fail here.
    res = olap_table->save_header();
    if (res != OLAP_SUCCESS) {
        OLAP_LOG_FATAL("fail to save header. [res=%d table='%s']",
                       res, olap_table->full_name().c_str());
    }

    return res;
}

void PushHandler::_delete_old_indices(Indices* unused_indices) {
    if (!unused_indices->empty()) {
        OLAPUnusedIndex* unused_index = OLAPUnusedIndex::get_instance();

        for (Indices::iterator it = unused_indices->begin();
                it != unused_indices->end(); ++it) {
            unused_index->add_unused_index(*it);
        }
    }
}

OLAPStatus PushHandler::_clear_alter_table_info(
        SmartOLAPTable tablet,
        SmartOLAPTable related_tablet) {
    OLAPStatus res = OLAP_SUCCESS;
    _obtain_header_wrlock();

    do {
        res = SchemaChangeHandler::clear_schema_change_single_info(
                tablet, NULL, false, false);
        if (res != OLAP_SUCCESS) {
            OLAP_LOG_FATAL("fail to clear schema change info of new table. [res=%d table='%s']",
                           res, tablet->full_name().c_str());
            break;
        }

        res = tablet->save_header();
        if (res != OLAP_SUCCESS) {
            OLAP_LOG_FATAL("fail to save header. [res=%d table='%s']",
                           res, tablet->full_name().c_str());
            break;
        }

        TTabletId tablet_id;
        TSchemaHash schema_hash;
        bool is_sc = related_tablet->get_schema_change_request(
                &tablet_id, &schema_hash, NULL, NULL);
        if (is_sc && tablet_id == tablet->tablet_id() && schema_hash == tablet->schema_hash()) {
            res = SchemaChangeHandler::clear_schema_change_single_info(
                    related_tablet, NULL, false, false);
            if (res != OLAP_SUCCESS) {
                OLAP_LOG_FATAL("fail to clear schema change info of old table. [res=%d table='%s']",
                               res, related_tablet->full_name().c_str());
                break;
            }

            res = related_tablet->save_header();
            if (res != OLAP_SUCCESS) {
                OLAP_LOG_FATAL("fail to save header. [res=%d table='%s']",
                               res, related_tablet->full_name().c_str());
                break;
            }
        }
    } while (0);

    _release_header_lock();
    return res;
}

OLAPStatus BinaryFile::init(const char* path) {
    // open file
    if (OLAP_SUCCESS != open(path, "rb")) {
        OLAP_LOG_WARNING("fail to open file. [file='%s']", path);
        return OLAP_ERR_IO_ERROR;
    }

    // load header
    if (OLAP_SUCCESS != _header.unserialize(this)) {
        OLAP_LOG_WARNING("fail to read file header. [file='%s']", path);
        close();
        return OLAP_ERR_PUSH_INIT_ERROR;
    }

    return OLAP_SUCCESS;
}

IBinaryReader* IBinaryReader::create(bool need_decompress) {
    IBinaryReader* reader = NULL;
    if (need_decompress) {
        reader = new(std::nothrow) LzoBinaryReader();
    } else {
        reader = new(std::nothrow) BinaryReader();
    }
    return reader;
}

BinaryReader::BinaryReader()
    : IBinaryReader(),
      _row_buf(NULL),
      _row_buf_size(0) {
}

OLAPStatus BinaryReader::init(
        SmartOLAPTable table,
        BinaryFile* file) {
    OLAPStatus res = OLAP_SUCCESS;

    do {
        _file = file;
        _content_len = _file->file_length() - _file->header_size();
        _row_buf_size = table->get_row_size();

        if (NULL == (_row_buf = new(std::nothrow) char[_row_buf_size])) {
            OLAP_LOG_WARNING("fail to malloc one row buf. [size=%zu]", _row_buf_size);
            res = OLAP_ERR_MALLOC_ERROR;
            break;
        }

        if (-1 == _file->seek(_file->header_size(), SEEK_SET)) {
            OLAP_LOG_WARNING("skip header, seek fail.");
            res = OLAP_ERR_IO_ERROR;
            break;
        }

        _table = table;
        _ready = true;
    } while (0);

    if (res != OLAP_SUCCESS) {
        SAFE_DELETE_ARRAY(_row_buf);
    }
    return res;
}

OLAPStatus BinaryReader::finalize() {
    _ready = false;
    SAFE_DELETE_ARRAY(_row_buf);
    return OLAP_SUCCESS;
}

OLAPStatus BinaryReader::next(RowCursor* row, MemPool* mem_pool) {
    OLAPStatus res = OLAP_SUCCESS;

    if (!_ready || NULL == row) {
        // Here i assume _ready means all states were set up correctly
        return OLAP_ERR_INPUT_PARAMETER_ERROR;
    }

    const vector<FieldInfo>& schema = _table->tablet_schema();
    size_t offset = 0;
    size_t field_size = 0;
    size_t num_null_bytes = (_table->num_null_fields() + 7) / 8;

    if (OLAP_SUCCESS != (res = _file->read(_row_buf + offset, num_null_bytes))) {
        OLAP_LOG_WARNING("read file for one row fail. [res=%d]", res);
        return res;
    }

    size_t p  = 0;
    for (size_t i = 0; i < schema.size(); ++i) {
        row->set_not_null(i);
        if (schema[i].is_allow_null) {
            bool is_null = false;
            is_null = (_row_buf[p/8] >> ((num_null_bytes * 8 - p - 1) % 8)) & 1;
            if (is_null) {
                row->set_null(i);
            }
            p++;
        }
    }
    offset += num_null_bytes;

    for (uint32_t i = 0; i < schema.size(); i++) {
        if (row->is_null(i)) {
            continue;
        }
        if (schema[i].type == OLAP_FIELD_TYPE_VARCHAR || schema[i].type == OLAP_FIELD_TYPE_HLL) {
            // Read varchar length buffer first
            if (OLAP_SUCCESS != (res = _file->read(_row_buf + offset,
                        sizeof(StringLengthType)))) {
                OLAP_LOG_WARNING("read file for one row fail. [res=%d]", res);
                return res;
            }

            // Get varchar field size
            field_size = *reinterpret_cast<StringLengthType*>(_row_buf + offset);
            offset += sizeof(StringLengthType);
            if (field_size > schema[i].length - sizeof(StringLengthType)) {
                OLAP_LOG_WARNING("invalid data length for VARCHAR! [max_len=%d real_len=%d]",
                                 schema[i].length - sizeof(StringLengthType),
                                 field_size);
                return OLAP_ERR_PUSH_INPUT_DATA_ERROR;
            }
        } else {
            field_size = schema[i].length;
        }

        // Read field content according to field size
        if (OLAP_SUCCESS != (res = _file->read(_row_buf + offset, field_size))) {
            OLAP_LOG_WARNING("read file for one row fail. [res=%d]", res);
            return res;
        }

        if (schema[i].type == OLAP_FIELD_TYPE_CHAR
                || schema[i].type == OLAP_FIELD_TYPE_VARCHAR
                || schema[i].type == OLAP_FIELD_TYPE_HLL) {
            StringSlice slice(_row_buf + offset, field_size);
            row->set_field_content(i, reinterpret_cast<char*>(&slice), mem_pool);
        } else {
            row->set_field_content(i, _row_buf + offset, mem_pool);
        }
        offset += field_size;
    }
    _curr += offset;

    // Calculate checksum for validate when push finished.
    _adler_checksum = olap_adler32(_adler_checksum, _row_buf, offset);
    return res;
}

LzoBinaryReader::LzoBinaryReader()
    : IBinaryReader(),
      _row_buf(NULL),
      _row_compressed_buf(NULL),
      _row_info_buf(NULL),
      _max_row_num(0),
      _max_row_buf_size(0),
      _max_compressed_buf_size(0),
      _row_num(0),
      _next_row_start(0) {
}

OLAPStatus LzoBinaryReader::init(
        SmartOLAPTable table,
        BinaryFile* file) {
    OLAPStatus res = OLAP_SUCCESS;

    do {
        _file = file;
        _content_len = _file->file_length() - _file->header_size();

        size_t row_info_buf_size = sizeof(RowNumType) + sizeof(CompressedSizeType);
        if (NULL == (_row_info_buf = new(std::nothrow) char[row_info_buf_size])) {
            OLAP_LOG_WARNING("fail to malloc rows info buf. [size=%zu]", row_info_buf_size);
            res = OLAP_ERR_MALLOC_ERROR;
            break;
        }

        if (-1 == _file->seek(_file->header_size(), SEEK_SET)) {
            OLAP_LOG_WARNING("skip header, seek fail.");
            res = OLAP_ERR_IO_ERROR;
            break;
        }

        _table = table;
        _ready = true;
    } while (0);

    if (res != OLAP_SUCCESS) {
        SAFE_DELETE_ARRAY(_row_info_buf);
    }
    return res;
}

OLAPStatus LzoBinaryReader::finalize() {
    _ready = false;
    SAFE_DELETE_ARRAY(_row_buf);
    SAFE_DELETE_ARRAY(_row_compressed_buf);
    SAFE_DELETE_ARRAY(_row_info_buf);
    return OLAP_SUCCESS;
}

OLAPStatus LzoBinaryReader::next(RowCursor* row, MemPool* mem_pool) {
    OLAPStatus res = OLAP_SUCCESS;

    if (!_ready || NULL == row) {
        // Here i assume _ready means all states were set up correctly
        return OLAP_ERR_INPUT_PARAMETER_ERROR;
    }

    if (_row_num == 0) {
        // read next block
        if (OLAP_SUCCESS != (res = _next_block())) {
            return res;
        }
    }

    const vector<FieldInfo>& schema = _table->tablet_schema();
    size_t offset = 0;
    size_t field_size = 0;
    size_t num_null_bytes = (_table->num_null_fields() + 7) / 8;

    size_t p = 0;
    for (size_t i = 0; i < schema.size(); ++i) {
        row->set_not_null(i);
        if (schema[i].is_allow_null) {
            bool is_null = false;
            is_null = (_row_buf[_next_row_start + p/8] >> ((num_null_bytes * 8 - p - 1) % 8)) & 1;
            if (is_null) {
                row->set_null(i);
            }
            p++;
        }
    }
    offset += num_null_bytes;

    for (uint32_t i = 0; i < schema.size(); i++) {
        if (row->is_null(i)) {
            continue;
        }

        if (schema[i].type == OLAP_FIELD_TYPE_VARCHAR || schema[i].type == OLAP_FIELD_TYPE_HLL) {
            // Get varchar field size
            field_size = *reinterpret_cast<StringLengthType*>(_row_buf + _next_row_start + offset);
            offset += sizeof(StringLengthType);

            if (field_size > schema[i].length - sizeof(StringLengthType)) {
                OLAP_LOG_WARNING("invalid data length for VARCHAR! [max_len=%d real_len=%d]",
                                 schema[i].length - sizeof(StringLengthType),
                                 field_size);
                return OLAP_ERR_PUSH_INPUT_DATA_ERROR;
            }
        } else {
            field_size = schema[i].length;
        }

        if (schema[i].type == OLAP_FIELD_TYPE_CHAR
                || schema[i].type == OLAP_FIELD_TYPE_VARCHAR
                || schema[i].type == OLAP_FIELD_TYPE_HLL) {
            StringSlice slice(_row_buf + _next_row_start + offset, field_size);
            row->set_field_content(i, reinterpret_cast<char*>(&slice), mem_pool);
        } else {
            row->set_field_content(i, _row_buf + _next_row_start + offset, mem_pool);
        }

        offset += field_size;
    }

    // Calculate checksum for validate when push finished.
    _adler_checksum = olap_adler32(_adler_checksum, _row_buf + _next_row_start, offset);

    _next_row_start += offset;
    --_row_num;
    return res;
}

OLAPStatus LzoBinaryReader::_next_block() {
    OLAPStatus res = OLAP_SUCCESS;

    // Get row num and compressed data size
    size_t row_info_buf_size = sizeof(RowNumType) + sizeof(CompressedSizeType);
    if (OLAP_SUCCESS != (res = _file->read(_row_info_buf, row_info_buf_size))) {
        OLAP_LOG_WARNING("read rows info fail. [res=%d]", res);
        return res;
    }

    RowNumType* rows_num_ptr = reinterpret_cast<RowNumType*>(_row_info_buf);
    _row_num = *rows_num_ptr;
    CompressedSizeType* compressed_size_ptr = reinterpret_cast<CompressedSizeType*>(
        _row_info_buf + sizeof(RowNumType));
    CompressedSizeType compressed_size = *compressed_size_ptr;

    if (_row_num > _max_row_num) {
        // renew rows buf
        SAFE_DELETE_ARRAY(_row_buf);

        _max_row_num = _row_num;
        _max_row_buf_size = _max_row_num * _table->get_row_size();
        if (NULL == (_row_buf = new(std::nothrow) char[_max_row_buf_size])) {
            OLAP_LOG_WARNING("fail to malloc rows buf. [size=%zu]", _max_row_buf_size);
            res = OLAP_ERR_MALLOC_ERROR;
            return res;
        }
    }

    if (compressed_size > _max_compressed_buf_size) {
        // renew rows compressed buf
        SAFE_DELETE_ARRAY(_row_compressed_buf);

        _max_compressed_buf_size = compressed_size;
        if (NULL == (_row_compressed_buf = new(std::nothrow) char[_max_compressed_buf_size])) {
            OLAP_LOG_WARNING("fail to malloc rows compressed buf. [size=%zu]", _max_compressed_buf_size);
            res = OLAP_ERR_MALLOC_ERROR;
            return res;
        }
    }

    if (OLAP_SUCCESS != (res = _file->read(_row_compressed_buf, compressed_size))) {
        OLAP_LOG_WARNING("read compressed rows fail. [res=%d]", res);
        return res;
    }

    // python lzo use lzo1x to compress
    // and add 5 bytes header (\xf0 + 4 bytes(uncompress data size))
    size_t written_len = 0;
    size_t block_header_size = 5;
    if (OLAP_SUCCESS != (res = olap_decompress(_row_compressed_buf + block_header_size,
                                               compressed_size - block_header_size,
                                               _row_buf,
                                               _max_row_buf_size,
                                               &written_len,
                                               OLAP_COMP_TRANSPORT))) {
        OLAP_LOG_WARNING("olap decompress fail. [res=%d]", res);
        return res;
    }

    _curr += row_info_buf_size + compressed_size;
    _next_row_start = 0;
    return res;
}

string PushHandler::_debug_version_list(const Versions& versions) const {
    std::ostringstream txt;
    txt << "Versions: ";

    for (Versions::const_iterator it = versions.begin(); it != versions.end(); ++it) {
        txt << "[" << it->first << "~" << it->second << "],";
    }

    return txt.str();
}

}  // namespace palo


text:
package de.softwareforge.pgpsigner.key;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Iterator;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.bouncycastle.bcpg.ArmoredOutputStream;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSignature;

/**
 * A wrapper around a PGPPublicKey object to manage application state information.
 *
 * @author Henning P. Schmiedehausen
 * @version $Id$
 */

public class PublicKey extends Key
{

    private PGPPublicKey pgpPublicKey;

    private boolean visible = true;

    private boolean signed = false;

    private boolean mailed = false;

    private boolean uploaded = false;

    public PublicKey(final PGPPublicKey pgpPublicKey)
    {
        super(pgpPublicKey.getKeyID());
        this.pgpPublicKey = pgpPublicKey;
    }

    public PGPPublicKey getPGPPublicKey()
    {
        return pgpPublicKey;
    }

    public void setPGPPublicKey(final PGPPublicKey pgpPublicKey)
    {
        this.pgpPublicKey = pgpPublicKey;
        setMailed(false);
        setUploaded(false);
    }

    public Iterator getUserIds()
    {
        return pgpPublicKey.getUserIDs();
    }

    public boolean isSignedWith(final SecretKey signKey)
    {

        if (signKey == null)
        {
            return false;
        }

        PGPSecretKey pgpSecretKey = signKey.getPGPSecretKey();

        for (Iterator it = pgpPublicKey.getSignatures(); it.hasNext();)
        {
            PGPSignature sig = (PGPSignature) it.next();

            if (pgpSecretKey.getKeyID() == sig.getKeyID())
            {
                return true;
            }
        }

        return false;
    }

    public void resetAllFlags()
    {
        setMailed(false);
        setSigned(false);
        setUploaded(false);
        setVisible(false);
    }

    public boolean isMailed()
    {
        return this.mailed;
    }

    public void setMailed(final boolean mailed)
    {
        this.mailed = mailed;
    }

    public boolean isSigned()
    {
        return this.signed;
    }

    public void setSigned(final boolean signed)
    {
        this.signed = signed;
    }

    public boolean isUploaded()
    {
        return this.uploaded;
    }

    public void setUploaded(final boolean uploaded)
    {
        this.uploaded = uploaded;
    }

    public boolean isVisible()
    {
        return this.visible;
    }

    public void setVisible(final boolean visible)
    {
        this.visible = visible;
    }

    public byte[] getArmor() throws IOException
    {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ArmoredOutputStream aos = null;
        try
        {
            aos = new ArmoredOutputStream(baos);
            pgpPublicKey.encode(aos);
            aos.flush();
        }
        finally
        {
            IOUtils.closeQuietly(aos);
        }
        return baos.toByteArray();
    }

    public String toString()
    {
        return new ToStringBuilder(this).appendSuper(super.toString()).append("key", toString(null).toString()).toString();
    }

    public StringBuffer toString(final StringBuffer buf)
    {
        StringBuffer sb = (buf != null) ? buf : new StringBuffer();

        sb.append(getKeyId()).append(" | ");

        sb.append(isVisible() ? "V" : " ");
        sb.append(isSigned() ? "S" : " ");
        sb.append(isMailed() ? "M" : " ");
        sb.append(isUploaded() ? "U" : " ");

        sb.append(" | ");

        Iterator it = getUserIds();
        if (it.hasNext())
        {
            sb.append(it.next());
        }

        return sb;
    }
}

redpajama_set_name: RedPajamaGithub


text:
"use strict";
var $ = require("jquery"),
    iconUtils = require("../core/utils/icon"),
    devices = require("../core/devices"),
    registerComponent = require("../core/component_registrator"),
    ValidationMixin = require("./validation/validation_mixin"),
    ValidationEngine = require("./validation_engine"),
    Widget = require("./widget/ui.widget"),
    inkRipple = require("./widget/utils.ink_ripple"),
    eventUtils = require("../events/utils"),
    themes = require("./themes"),
    clickEvent = require("../events/click"),
    FunctionTemplate = require("./widget/function_template");
var BUTTON_CLASS = "dx-button",
    BUTTON_CONTENT_CLASS = "dx-button-content",
    BUTTON_HAS_TEXT_CLASS = "dx-button-has-text",
    BUTTON_HAS_ICON_CLASS = "dx-button-has-icon",
    TEMPLATE_WRAPPER_CLASS = "dx-template-wrapper",
    BUTTON_TEXT_CLASS = "dx-button-text",
    ANONYMOUS_TEMPLATE_NAME = "content",
    BUTTON_FEEDBACK_HIDE_TIMEOUT = 100;
var Button = Widget.inherit({
    _supportedKeys: function() {
        var that = this,
            click = function(e) {
                e.preventDefault();
                that._executeClickAction(e)
            };
        return $.extend(this.callBase(), {
            space: click,
            enter: click
        })
    },
    _setDeprecatedOptions: function() {
        this.callBase();
        $.extend(this._deprecatedOptions, {
            iconSrc: {
                since: "15.1",
                alias: "icon"
            }
        })
    },
    _getDefaultOptions: function() {
        return $.extend(this.callBase(), {
            hoverStateEnabled: true,
            onClick: null,
            type: "normal",
            text: "",
            icon: "",
            validationGroup: void 0,
            activeStateEnabled: true,
            template: "content",
            useSubmitBehavior: false,
            useInkRipple: false
        })
    },
    _defaultOptionsRules: function() {
        return this.callBase().concat([{
            device: function() {
                return "desktop" === devices.real().deviceType && !devices.isSimulator()
            },
            options: {
                focusStateEnabled: true
            }
        }, {
            device: function() {
                return /android5/.test(themes.current())
            },
            options: {
                useInkRipple: true
            }
        }])
    },
    _getAnonymousTemplateName: function() {
        return ANONYMOUS_TEMPLATE_NAME
    },
    _feedbackHideTimeout: BUTTON_FEEDBACK_HIDE_TIMEOUT,
    _initTemplates: function() {
        this.callBase();
        this._defaultTemplates.content = new FunctionTemplate(function(options) {
            var data = options.model,
                $iconElement = iconUtils.getImageContainer(data && data.icon),
                $textContainer = data && data.text ? $("<span>").text(data.text).addClass(BUTTON_TEXT_CLASS) : void 0;
            options.container.append($iconElement).append($textContainer)
        }, this)
    },
    _render: function() {
        this.element().addClass(BUTTON_CLASS);
        this._renderType();
        this.option("useInkRipple") && this._renderInkRipple();
        this._renderClick();
        this.setAria("role", "button");
        this._updateAriaLabel();
        this.callBase()
    },
    _renderInkRipple: function() {
        var isOnlyIconButton = !this.option("text") && this.option("icon") || "back" === this.option("type"),
            config = {};
        if (isOnlyIconButton) {
            $.extend(config, {
                waveSizeCoefficient: 1,
                useHoldAnimation: false,
                isCentered: true
            })
        }
        this._inkRipple = inkRipple.render(config)
    },
    _toggleActiveState: function($element, value, e) {
        this.callBase.apply(this, arguments);
        if (!this._inkRipple) {
            return
        }
        var config = {
            element: this._$content,
            jQueryEvent: e
        };
        if (value) {
            this._inkRipple.showWave(config)
        } else {
            this._inkRipple.hideWave(config)
        }
    },
    _renderContentImpl: function() {
        var $element = this.element(),
            data = this._getContentData();
        if (this._$content) {
            this._$content.empty()
        } else {
            this._$content = $("<div>").addClass(BUTTON_CONTENT_CLASS).appendTo($element)
        }
        $element.toggleClass(BUTTON_HAS_ICON_CLASS, !!data.icon).toggleClass(BUTTON_HAS_TEXT_CLASS, !!data.text);
        var template = this._getTemplateByOption("template"),
            $result = template.render({
                model: data,
                container: this._$content
            });
        if ($result.hasClass(TEMPLATE_WRAPPER_CLASS)) {
            this._$content.replaceWith($result);
            this._$content = $result;
            this._$content.addClass(BUTTON_CONTENT_CLASS)
        }
        if (this.option("useSubmitBehavior")) {
            this._renderSubmitInput()
        }
    },
    _renderSubmitInput: function() {
        var submitAction = this._createAction(function(args) {
            var e = args.jQueryEvent,
                validationGroup = ValidationEngine.getGroupConfig(args.component._findGroup());
            if (validationGroup && !validationGroup.validate().isValid) {
                e.preventDefault()
            }
            e.stopPropagation()
        });
        this._$submitInput = $("<input>").attr("type", "submit").addClass("dx-button-submit-input").appendTo(this._$content).on("click", function(e) {
            submitAction({
                jQueryEvent: e
            })
        })
    },
    _getContentData: function() {
        var icon = this.option("icon"),
            text = this.option("text"),
            back = "back" === this.option("type");
        if (back && !icon) {
            icon = "back"
        }
        return {
            icon: icon,
            text: text
        }
    },
    _renderClick: function() {
        var that = this,
            eventName = eventUtils.addNamespace(clickEvent.name, this.NAME),
            actionConfig = {};
        if (this.option("useSubmitBehavior")) {
            actionConfig.afterExecute = function(e) {
                setTimeout(function() {
                    e.component._$submitInput.get(0).click()
                })
            }
        }
        this._clickAction = this._createActionByOption("onClick", actionConfig);
        this.element().off(eventName).on(eventName, function(e) {
            that._executeClickAction(e)
        })
    },
    _executeClickAction: function(e) {
        this._clickAction({
            jQueryEvent: e,
            validationGroup: ValidationEngine.getGroupConfig(this._findGroup())
        })
    },
    _updateAriaLabel: function() {
        var icon = this.option("icon"),
            text = this.option("text");
        if ("image" === iconUtils.getImageSourceType(icon)) {
            if (icon.indexOf("base64") === -1) {
                icon = icon.replace(/.+\/([^\.]+)\..+$/, "$1")
            } else {
                icon = "Base64"
            }
        }
        var ariaLabel = text || icon;
        this.setAria("label", $.trim(ariaLabel))
    },
    _renderType: function() {
        var type = this.option("type");
        if (type) {
            this.element().addClass("dx-button-" + type)
        }
    },
    _refreshType: function(prevType) {
        var type = this.option("type");
        prevType && this.element().removeClass("dx-button-" + prevType).addClass("dx-button-" + type);
        if (!this.element().hasClass(BUTTON_HAS_ICON_CLASS) && "back" === type) {
            this._renderContentImpl()
        }
    },
    _optionChanged: function(args) {
        switch (args.name) {
            case "onClick":
                this._renderClick();
                break;
            case "icon":
            case "text":
                this._renderContentImpl();
                this._updateAriaLabel();
                break;
            case "type":
                this._refreshType(args.previousValue);
                this._renderContentImpl();
                this._updateAriaLabel();
                break;
            case "template":
                this._renderContentImpl();
                break;
            case "useInkRipple":
                this._invalidate();
                break;
            case "useSubmitBehavior":
                this._invalidate();
                break;
            default:
                this.callBase(args)
        }
    },
    _clean: function() {
        this.callBase();
        delete this._$content
    }
}).include(ValidationMixin);
registerComponent("dxButton", Button);
module.exports = Button;
module.exports.default = module.exports;


text:
require 'rails_helper.rb'
require "shared.rb"

feature 'tutorial' do

  include_context "shared functions"

  before do
    register_user_and_create_password
  end

  scenario 'user logs in for first time -> is shown tutorial', :js => true do

    # validate that user has not yet finished tutorial
    expect(@user.has_finished_tutorial).to be false

    # Log In
    visit login_path
    fill_in 'email', with: @user.email
    fill_in 'password', with: @PASSWORD
    click_button 'Log In', match: :first

    # validate that user is shown tutorial
    expect(page).to have_content("tutorial")
    click_button "Next"
    expect(page).to have_content("Step 1")
    click_button "Next"
    expect(page).to have_content("Step 2")
    click_button "Next"
    expect(page).to have_content("Step 3")
    click_button "Next"
    expect(page).to have_content("Step 4")
    click_button "Done"

    # validate that user has finished tutorial
    expect(@user.has_finished_tutorial).to be true

  end

  scenario "user logs in for second time after interrupting tutorial -> is shown tutorial again", :js => true  do

    # validate that user has not yet finished tutorial
    expect(@user.has_finished_tutorial).to be false

    # Log In
    visit login_path
    fill_in 'email', with: @user.email
    fill_in 'password', with: @PASSWORD
    click_button 'Log In', match: :first

    # Show Tutorial
    expect(page).to have_content("tutorial")
    click_button "Next"
    expect(page).to have_content("Step 1")
    click_button "Next"

    # Interrupt Tutorial
    visit logout_path

    # Log In
    visit login_path
    fill_in 'email', with: @user.email
    fill_in 'password', with: @PASSWORD
    click_button 'Log In', match: :first

    # validate that user sees tutorial agian
    expect(page).to have_content("tutorial")

  end

  scenario "user logs in for second time after completing tutorial -> is not shown tutorial", :js => true  do

    # Log In
    visit login_path
    fill_in 'email', with: @user.email
    fill_in 'password', with: @PASSWORD
    click_button 'Log In', match: :first

    # finish tutorial
    expect(page).to have_content("tutorial")
    click_button "Next"
    expect(page).to have_content("Step 1")
    click_button "Next"
    expect(page).to have_content("Step 2")
    click_button "Next"
    expect(page).to have_content("Step 3")
    click_button "Next"
    expect(page).to have_content("Step 4")
    click_button "Done"

    # validate that user has finished tutorial
    expect(@user.has_finished_tutorial).to be true

    # log user out
    visit logout_path

    # Log In again
    visit login_path
    fill_in 'email', with: @user.email
    fill_in 'password', with: @PASSWORD
    click_button 'Log In', match: :first

    # validate that tutorial is not being shown again
    expect(page).not_to have_content("tutorial")

  end

end


text:
class CreateGradeEntryStudentsTas < ActiveRecord::Migration
  def self.up
  	create_table :grade_entry_students_tas, :id => false do |t|
      t.integer  :grade_entry_student_id
      t.integer  :ta_id
  	end
  end

  def self.down
  	drop_table :grade_entry_students_tas
  end
end


text:
import {
  isObject,
  sortBy
} from 'min-dash';

import {
  pointDistance
} from '../util/Geometry';

import intersectPaths from 'path-intersection';

export function roundBounds(bounds) {
  return {
    x: Math.round(bounds.x),
    y: Math.round(bounds.y),
    width: Math.round(bounds.width),
    height: Math.round(bounds.height)
  };
}

export function roundPoint(point) {

  return {
    x: Math.round(point.x),
    y: Math.round(point.y)
  };
}

/**
 * Convert the given bounds to a { top, left, bottom, right } descriptor.
 *
 * @param {Bounds|Point} bounds
 *
 * @return {Object}
 */
export function asTRBL(bounds) {
  return {
    top: bounds.y,
    right: bounds.x + (bounds.width || 0),
    bottom: bounds.y + (bounds.height || 0),
    left: bounds.x
  };
}

/**
 * Convert a { top, left, bottom, right } to an objects bounds.
 *
 * @param {Object} trbl
 *
 * @return {Bounds}
 */
export function asBounds(trbl) {
  return {
    x: trbl.left,
    y: trbl.top,
    width: trbl.right - trbl.left,
    height: trbl.bottom - trbl.top
  };
}

/**
 * Get the mid of the given bounds or point.
 *
 * @param {Bounds|Point} bounds
 *
 * @return {Point}
 */
export function getMid(bounds) {
  return roundPoint({
    x: bounds.x + (bounds.width || 0) / 2,
    y: bounds.y + (bounds.height || 0) / 2
  });
}

// orientation utils //////////////////////

/**
 * Get orientation of the given rectangle with respect to
 * the reference rectangle.
 *
 * A padding (positive or negative) may be passed to influence
 * horizontal / vertical orientation and intersection.
 *
 * @param {Bounds} rect
 * @param {Bounds} reference
 * @param {Point|Number} padding
 *
 * @return {String} the orientation; one of top, top-left, left, ..., bottom, right or intersect.
 */
export function getOrientation(rect, reference, padding) {

  padding = padding || 0;

  // make sure we can use an object, too
  // for individual { x, y } padding
  if (!isObject(padding)) {
    padding = { x: padding, y: padding };
  }

  var rectOrientation = asTRBL(rect),
      referenceOrientation = asTRBL(reference);

  var top = rectOrientation.bottom + padding.y <= referenceOrientation.top,
      right = rectOrientation.left - padding.x >= referenceOrientation.right,
      bottom = rectOrientation.top - padding.y >= referenceOrientation.bottom,
      left = rectOrientation.right + padding.x <= referenceOrientation.left;

  var vertical = top ? 'top' : (bottom ? 'bottom' : null),
      horizontal = left ? 'left' : (right ? 'right' : null);

  if (horizontal && vertical) {
    return vertical + '-' + horizontal;
  } else {
    return horizontal || vertical || 'intersect';
  }
}

// intersection utils //////////////////////

/**
 * Get intersection between an element and a line path.
 *
 * @param {PathDef} elementPath
 * @param {PathDef} linePath
 * @param {Boolean} cropStart crop from start or end
 *
 * @return {Point}
 */
export function getElementLineIntersection(elementPath, linePath, cropStart) {

  var intersections = getIntersections(elementPath, linePath);

  // recognize intersections
  // only one -> choose
  // two close together -> choose first
  // two or more distinct -> pull out appropriate one
  // none -> ok (fallback to point itself)
  if (intersections.length === 1) {
    return roundPoint(intersections[0]);
  } else if (intersections.length === 2 && pointDistance(intersections[0], intersections[1]) < 1) {
    return roundPoint(intersections[0]);
  } else if (intersections.length > 1) {

    // sort by intersections based on connection segment +
    // distance from start
    intersections = sortBy(intersections, function(i) {
      var distance = Math.floor(i.t2 * 100) || 1;

      distance = 100 - distance;

      distance = (distance < 10 ? '0' : '') + distance;

      // create a sort string that makes sure we sort
      // line segment ASC + line segment position DESC (for cropStart)
      // line segment ASC + line segment position ASC (for cropEnd)
      return i.segment2 + '#' + distance;
    });

    return roundPoint(intersections[cropStart ? 0 : intersections.length - 1]);
  }

  return null;
}

export function getIntersections(a, b) {
  return intersectPaths(a, b);
}


text:
"""Define version."""

import pathlib
import subprocess

here = pathlib.Path(__file__).resolve().parent

__all__ = ["__version__", "__branch__"]

# read from VERSION file
with open(str(here / "VERSION")) as f:
    __version__ = f.read().strip()

try:
    __branch__ = (
        subprocess.run(
            ["git", "branch", "--show-current"], capture_output=True, cwd=here
        )
        .stdout.strip()
        .decode()
    )
except:
    __branch__ = ""

if __branch__:
    __version__ += "+" + __branch__


text:
module ObjectSpace::AllocationTracer
  VERSION = "0.6.3"
end


text:
Tables Info演示列表项信息与操作

        <form class="form-horizontal" onsubmit="return false">

                Domain

                    <input type="text" placeholder="Domain" class="input-xxlarge"
                        bg-model="info.Domain">

                Price

                    <input type="text" placeholder="Price" class="input-xxlarge"
                        bg-model="info.Price">

                Clicks

                    <input type="text" placeholder="Clicks" class="input-xxlarge"
                        bg-model="info.Clicks">

                Update

                    <input type="text" placeholder="Update" class="input-xxlarge"
                        bg-model="info.Update">

                <button class="btn btn-info" bg-click="save">
                    Submit</button>

        </form>


text:
<resources>

    <style name="MyCustomTheme" parent="@android:style/Theme.Holo.Light">
        <item name="android:actionBarStyle">@style/MyActionBarTheme</item>
    </style>

    <style name="MyActionBarTheme" parent="@android:style/Widget.Holo.Light.ActionBar">
        <item name="android:background">#008bcb</item>
    </style>
</resources>


text:
Project created to React course 2: Componentes and Container.

## Modules:
* React core modules: react and react-dom
* React-Router 3
* Pubsub-js

### Steps
* Download backend at: https://github.com/alberto-alura/instalura-api/raw/master/instalura.jar
* To run: java -jar -Dspring.datasource.password=<mysql_password> instalura.jar
* Request the URL http://localhost:8080/gera/dados to generate the data
* Users: alots 123456 ; vitor 123456

#### Tool
This project was bootstrapped with [Create React App](https://github.com/facebookincubator/create-react-app).
Below you will find some information on how to perform common tasks.<br>
You can find the most recent version of this guide [here](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md).