<commit_before>#include <sstream>
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include "errno.h"
#include <string>
#include <list>
#include <string.h>
#include <vector>
#include <cstdlib>
#include <sys/wait.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//#include "redir.h"

using namespace std;
void fixing_spacing_command(char *org_prompt, int check_redir)
{
    char *fin_prompt = (char*)malloc(50000);
    char connect[4];
    connect[0] = ';';
    connect[1] = '&';
    connect[2] = '|';
    connect[3] = '#';
    connect[4] = '>';
    //x is passed in prompt
    //i is finished prompt after changing spaces
    for(int x = 0,i = 0; org_prompt[x] != '\0'; x++, i++)
    {
        if(org_prompt[x] == connect[3])
        {
            org_prompt[x] = '\0';
            fin_prompt[i] = '\0';
        }
        else if(org_prompt[x] == connect[0])
        {
            fin_prompt[i] = ' ';
            fin_prompt[++i] = ';';
            fin_prompt[++i] = ' ';
        }
        else if(org_prompt[x] == connect[1] && org_prompt[x + 1] == connect[1])
        {
            fin_prompt[i] = ' ';
            fin_prompt[++i] = '&';
            fin_prompt[++i] = '&';
            fin_prompt[++i] = ' ';
            ++x;
        }
        else if(org_prompt[x] == connect[3] && org_prompt[x + 1] == connect[3])
        {
            fin_prompt[i] = ' ';
            fin_prompt[++i] = '|';
            fin_prompt[++i] = '|';
            fin_prompt[++i] = ' ';
            ++x;
        }
        else if(org_prompt[x] == connect[4])
        {
            check_redir = 1;        //redir 1 means one output bracket
            fin_prompt[i] = ';';
            fin_prompt[++i] = ' ';
            fin_prompt[++i] = ' ';
            fin_prompt[++i] = ' ';
            ++x;
        }
        else
        {
            fin_prompt[i] = org_prompt[x];
        }
        if(org_prompt[x + 1] == '\0') fin_prompt[i + 1] = '\0';
    }
      strcpy(org_prompt, fin_prompt);        //copies altered version
}
int exec_status;
bool str_continue = true;
bool execute(char* command, char* command_list[], int conect_type, bool redir)
{
    cout << "conect:type: " << conect_type << endl;
    int status;
    int process_ID = fork();
    if(process_ID <= -1)
    {
        perror("Error occured during forking()");
        exit(1);
    }
    else if(process_ID == 0) //child process
    {
        if(redir)
        {
            cout << "did this output" << endl;
            int fd;
            if((fd = open("outfile", O_RDWR | O_CREAT | O_TRUNC, 0744)) == -1)
            {
                perror("open");
            }
            if(close(1) == -1)
            {
                perror("close");
            }
            if(dup(fd) == -1)
            {
                perror("dup");
            }
            exec_status = (execvp(command, command_list));
            //cout << "output exec status: " << exec_status << endl;
            if(exec_status == -1)
            {
                perror("error with passed in argument list");
                return exec_status;
                exit(1);
            }
        }
        else
        {
            cout << "this is wrong" << endl;
            exec_status = (execvp(command, command_list));
            //cout << "output exec status: " << exec_status << endl;
            if(exec_status == -1)
            {
                perror("error with passed in argument list");
                return exec_status;
                exit(1);
            }
        }
    }
    else if(process_ID > 0) //parent process
    {
        if(waitpid(process_ID, &status,0) == -1)
        {
            perror("error with waitpid()");
        }
    }
    return(!(status == 0 && conect_type == -1) ||( status > 0 && conect_type == 2));
}
int check_connections(char* check)
{
    if(!strcmp(check, ";")) return 0;
    else if(!strcmp(check, "||")) return 1;
    else if(!strcmp(check, "&&")) return 2;
    else if(!strcmp(check, ">")) return 3;
    else return -1;
}
void check_exit(char *str)
{
    if(!strcmp(str, "exit"))
    {
        exit(0);
    }
}

bool chk_redir(string s)
{
    for(int x = 0; x < s.size(); x++)
    {
        if(s.at(x) == '>')
        {
            return true;
        }
    }
    return false;
}

int main(int argc, char **argv)
{
    int check_redir = 0;
    ///////////////////////////////////////////////
    int sequence = 0; //sequence of which is executable and flags
    char* host = (char*)malloc(500);
    string userinfo;
    bool prompter = true;
    char* token; //will be bit of code strtok cuts off
    bool exec_result = true;
    //error checks the user
    if(getlogin() != NULL)
    {
        userinfo = getlogin();
    }
    else
    {
        perror("error getting user info");
    }
    if(gethostname(host, 500) == -1)
    {
        perror("Error getting host name");
    }
    //outputs the userinfo with login and host
    while(prompter)
    {
        cout << userinfo << "@" << host << " $ ";
        //////////////////////////////////////////////login part done, next is all shell commands
        char prompt_holder[50000];//orginal array to hold prompt
        char *comd_arr[50000];
        for(int x = 0; x < 50001; x++)
        {
            prompt_holder[x] = 0;
            comd_arr[x] = 0;
        }
        unsigned int comd_arr_cnt = 0;
        str_continue = true;
        //string converter; //converts all bits of string into one piece

        string to_be_tokenized;

        getline(cin, to_be_tokenized);
        bool to_redir;
        to_redir = chk_redir(to_be_tokenized);//checks if there is redirection sign in command
        for(unsigned int x = 0; x < to_be_tokenized.size(); x++)
        {
            prompt_holder[x] = to_be_tokenized.at(x);
        }
        fixing_spacing_command(prompt_holder, check_redir);
        int connect_check; //indicates which connection is in token
        token = strtok(prompt_holder, "\t ");
        //cout << "output token: " << token << endl;
        exec_result = true;
        while(token != NULL && exec_result && str_continue)
        {
            connect_check = check_connections(token);
            check_exit(token);
            if(connect_check == -1 && sequence < 1 && str_continue)
            {
                //cout << "does this come out on top" << endl;
                check_exit(token);
                comd_arr[comd_arr_cnt] = token;
                comd_arr_cnt++;
                sequence++; //increment only once to see which is executable
            }
            else if(sequence > 0 && connect_check == -1 && str_continue)
            {
                comd_arr[comd_arr_cnt] = token;
                comd_arr_cnt++;
            }
            else if(connect_check != -1)
            {
                check_exit(token);
                comd_arr[comd_arr_cnt] = '\0' ;
                sequence = 0;
                comd_arr_cnt = 0;
                //cout << "does it output second iteration " << endl;
                exec_result = execute(comd_arr[0], comd_arr, connect_check, to_redir);
                //cout << "output exec_status: " << exec_status << endl;
                //cout << "output exec_result tho: " << exec_result << endl;
                //cout << "connect_check: " << connect_check << endl;
                //cout << "str_continue: " << str_continue << endl;
                if(exec_status == 0)
                {
                    if(connect_check == 2)
                    {
                        str_continue = false;
                        //cout << "str_continue: " << str_continue << endl;
                    }
                    if(connect_check == 1)
                    {
                        str_continue = false;
                    }
                }
                if(exec_result == 1)
                {
                    if(connect_check == 2)
                    {
                        str_continue = true;
                    }
                }

            }
            token = strtok(NULL, "\t ");
            if(connect_check == -1 && token == NULL && exec_result && str_continue)
            {
            cout << "guess this executeisw ith this " << endl;
            comd_arr[comd_arr_cnt] = '\0';
            execute(comd_arr[0], comd_arr, connect_check, to_redir);
            }
        }
    }
}
/* || && ;
succeeds ||
notsucceed &&
ls -a
[ls] [-a]
exekcvp([ls],[[ls],[-a]])
char* argumentList[50000];
char executable[50000];
argumentList[0] = executable;
unsigned int size = 0;
ls -a \0
execvp(argumentList[0], argumentList);
*/
<commit_msg>got second redirection symbol working<commit_after>#include <sstream>
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include "errno.h"
#include <string>
#include <list>
#include <string.h>
#include <vector>
#include <cstdlib>
#include <sys/wait.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//#include "redir.h"

using namespace std;
void fixing_spacing_command(char *org_prompt, int check_redir)
{
    char *fin_prompt = (char*)malloc(50000);
    char connect[4];
    connect[0] = ';';
    connect[1] = '&';
    connect[2] = '|';
    connect[3] = '#';
    connect[4] = '>';
    //x is passed in prompt
    //i is finished prompt after changing spaces
    for(int x = 0,i = 0; org_prompt[x] != '\0'; x++, i++)
    {
        if(org_prompt[x] == connect[3])
        {
            org_prompt[x] = '\0';
            fin_prompt[i] = '\0';
        }
        else if(org_prompt[x] == connect[0])
        {
            fin_prompt[i] = ' ';
            fin_prompt[++i] = ';';
            fin_prompt[++i] = ' ';
        }
        else if(org_prompt[x] == connect[1] && org_prompt[x + 1] == connect[1])
        {
            fin_prompt[i] = ' ';
            fin_prompt[++i] = '&';
            fin_prompt[++i] = '&';
            fin_prompt[++i] = ' ';
            ++x;
        }
        else if(org_prompt[x] == connect[3] && org_prompt[x + 1] == connect[3])
        {
            fin_prompt[i] = ' ';
            fin_prompt[++i] = '|';
            fin_prompt[++i] = '|';
            fin_prompt[++i] = ' ';
            ++x;
        }
        else if(org_prompt[x] == connect[4])
        {
            check_redir = 1;        //redir 1 means one output bracket
            fin_prompt[i] = ';';
            fin_prompt[++i] = ' ';
            fin_prompt[++i] = ' ';
            fin_prompt[++i] = ' ';
            ++x;
        }
        else
        {
            fin_prompt[i] = org_prompt[x];
        }
        if(org_prompt[x + 1] == '\0') fin_prompt[i + 1] = '\0';
    }
      strcpy(org_prompt, fin_prompt);        //copies altered version
}
int exec_status;
bool str_continue = true;
bool execute(char* command, char* command_list[], int conect_type, int redir)
{
    cout << "conect:type: " << conect_type << endl;
    int status;
    int process_ID = fork();
    if(process_ID <= -1)
    {
        perror("Error occured during forking()");
        exit(1);
    }
    else if(process_ID == 0) //child process
    {
        if(redir == 1)
        {
            cout << "did this output" << endl;
            int fd;
            if((fd = open("outfile", O_RDWR | O_CREAT | O_TRUNC, 0744)) == -1)
            {
                perror("open");
            }
            if(close(1) == -1)
            {
                perror("close");
            }
            if(dup(fd) == -1)
            {
                perror("dup");
            }
            exec_status = (execvp(command, command_list));
            //cout << "output exec status: " << exec_status << endl;
            if(exec_status == -1)
            {
                perror("error with passed in argument list");
                return exec_status;
                exit(1);
            }
        }
        if(redir == 2)
        {
            cout << "yay this should output now" << endl;
            int fd;
            if((fd = open("outfile", O_RDWR | O_CREAT | O_APPEND, 0744)) == -1)
            {
                perror("open");
            }
            if(close(1) == -1)
            {
                perror("close");
            }
            if(dup(fd) == -1)
            {
                perror("dup");
            }
            exec_status = (execvp(command, command_list));
            //cout << "output exec status: " << exec_status << endl;
            if(exec_status == -1)
            {
                perror("error with passed in argument list");
                return exec_status;
                exit(1);
            }
        }
        else
        {
            cout << "this is wrong" << endl;
            exec_status = (execvp(command, command_list));
            //cout << "output exec status: " << exec_status << endl;
            if(exec_status == -1)
            {
                perror("error with passed in argument list");
                return exec_status;
                exit(1);
            }
        }
    }
    else if(process_ID > 0) //parent process
    {
        if(waitpid(process_ID, &status,0) == -1)
        {
            perror("error with waitpid()");
        }
    }
    return(!(status == 0 && conect_type == -1) ||( status > 0 && conect_type == 2));
}
int check_connections(char* check)
{
    if(!strcmp(check, ";")) return 0;
    else if(!strcmp(check, "||")) return 1;
    else if(!strcmp(check, "&&")) return 2;
    else if(!strcmp(check, ">")) return 3;
    else return -1;
}
void check_exit(char *str)
{
    if(!strcmp(str, "exit"))
    {
        exit(0);
    }
}

int chk_redir(string s)
{
    for(int x = 0; x < s.size(); x++)
    {
        //cout << "output x: " << x << endl;
        if(s.at(x) == '>')
        {
            //cout << "output x: " << endl;
            int y = x;
            if(y++ < s.size() && s.at(x) == '>')
            {
                return 2;
            }
            else
            {return 1;}
        }
    }
    return 0;
}

int main(int argc, char **argv)
{
    int check_redir = 0;
    ///////////////////////////////////////////////
    int sequence = 0; //sequence of which is executable and flags
    char* host = (char*)malloc(500);
    string userinfo;
    bool prompter = true;
    char* token; //will be bit of code strtok cuts off
    bool exec_result = true;
    //error checks the user
    if(getlogin() != NULL)
    {
        userinfo = getlogin();
    }
    else
    {
        perror("error getting user info");
    }
    if(gethostname(host, 500) == -1)
    {
        perror("Error getting host name");
    }
    //outputs the userinfo with login and host
    while(prompter)
    {
        cout << userinfo << "@" << host << " $ ";
        //////////////////////////////////////////////login part done, next is all shell commands
        char prompt_holder[50000];//orginal array to hold prompt
        char *comd_arr[50000];
        for(int x = 0; x < 50001; x++)
        {
            prompt_holder[x] = 0;
            comd_arr[x] = 0;
        }
        unsigned int comd_arr_cnt = 0;
        str_continue = true;
        //string converter; //converts all bits of string into one piece

        string to_be_tokenized;

        getline(cin, to_be_tokenized);
        int to_redir;           //certain number corresponds to what redirection it is
        to_redir = chk_redir(to_be_tokenized);//checks if there is redirection sign in command
        for(unsigned int x = 0; x < to_be_tokenized.size(); x++)
        {
            prompt_holder[x] = to_be_tokenized.at(x);
        }
        fixing_spacing_command(prompt_holder, check_redir);
        int connect_check; //indicates which connection is in token
        token = strtok(prompt_holder, "\t ");
        //cout << "output token: " << token << endl;
        exec_result = true;
        while(token != NULL && exec_result && str_continue)
        {
            connect_check = check_connections(token);
            check_exit(token);
            if(connect_check == -1 && sequence < 1 && str_continue)
            {
                //cout << "does this come out on top" << endl;
                check_exit(token);
                comd_arr[comd_arr_cnt] = token;
                comd_arr_cnt++;
                sequence++; //increment only once to see which is executable
            }
            else if(sequence > 0 && connect_check == -1 && str_continue)
            {
                comd_arr[comd_arr_cnt] = token;
                comd_arr_cnt++;
            }
            else if(connect_check != -1)
            {
                check_exit(token);
                comd_arr[comd_arr_cnt] = '\0' ;
                sequence = 0;
                comd_arr_cnt = 0;
                //cout << "does it output second iteration " << endl;
                exec_result = execute(comd_arr[0], comd_arr, connect_check, to_redir);
                //cout << "output exec_status: " << exec_status << endl;
                //cout << "output exec_result tho: " << exec_result << endl;
                //cout << "connect_check: " << connect_check << endl;
                //cout << "str_continue: " << str_continue << endl;
                if(exec_status == 0)
                {
                    if(connect_check == 2)
                    {
                        str_continue = false;
                        //cout << "str_continue: " << str_continue << endl;
                    }
                    if(connect_check == 1)
                    {
                        str_continue = false;
                    }
                }
                if(exec_result == 1)
                {
                    if(connect_check == 2)
                    {
                        str_continue = true;
                    }
                }

            }
            token = strtok(NULL, "\t ");
            if(connect_check == -1 && token == NULL && exec_result && str_continue)
            {
            cout << "guess this executeisw ith this " << endl;
            comd_arr[comd_arr_cnt] = '\0';
            execute(comd_arr[0], comd_arr, connect_check, to_redir);
            }
        }
    }
}
/* || && ;
succeeds ||
notsucceed &&
ls -a
[ls] [-a]
exekcvp([ls],[[ls],[-a]])
char* argumentList[50000];
char executable[50000];
argumentList[0] = executable;
unsigned int size = 0;
ls -a \0
execvp(argumentList[0], argumentList);
*/
<|endoftext|>


<commit_before>// Copyright (c) 2016, Baidu.com, Inc. All Rights Reserved
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sdk/tera_replication.h"

#include "common/mutex.h"
#include "types.h"
#include "utils/config_utils.h"

DEFINE_bool(tera_replication_read_try_all, false, "try to read all replicas instread of randomly choose one");
DEFINE_bool(tera_replication_write_need_all_success, false, "return OK only if all replicas write success");
DEFINE_string(tera_replication_conf_paths, "../conf/tera.flag", "paths for flag files. use \';\' to split");

namespace tera {

class RowMutationReplicateImpl : public RowMutationReplicate {
public:
    RowMutationReplicateImpl(const std::vector<RowMutation*>& row_mutations,
                             const std::vector<Table*>& tables)
        : _row_mutations(row_mutations),
          _tables(tables),
          _user_callback(NULL),
          _user_context(NULL),
          _finish_cond(&_mutex),
          _finish_count(0),
          _success_row_mutation(NULL),
          _fail_row_mutation(NULL) {
        CHECK_GT(_row_mutations.size(), 0u);
        for (size_t i = 0; i < _row_mutations.size(); i++) {
            _row_mutations[i]->SetCallBack(RowMutationCallback);
            _row_mutations[i]->SetContext(this);
        }
    }

    virtual ~RowMutationReplicateImpl() {
        for (size_t i = 0; i < _row_mutations.size(); i++) {
            delete _row_mutations[i];
        }
    }

    virtual const std::string& RowKey() {
        return _row_mutations[0]->RowKey();
    }

    virtual void Put(const std::string& value) {
        for (size_t i = 0; i < _row_mutations.size(); i++) {
            _row_mutations[i]->Put(value);
        }
    }

    virtual void Put(const std::string& value, int32_t ttl) {
        for (size_t i = 0; i < _row_mutations.size(); i++) {
            _row_mutations[i]->Put(value, ttl);
        }
    }

    virtual void DeleteRow() {
        for (size_t i = 0; i < _row_mutations.size(); i++) {
            _row_mutations[i]->DeleteRow();
        }
    }

    virtual void SetCallBack(Callback callback) {
        _user_callback = callback;
    }

    virtual Callback GetCallBack() {
        return _user_callback;
    }

    virtual void SetContext(void* context) {
        _user_context = context;
    }

    virtual void* GetContext() {
        return _user_context;
    }

    virtual const ErrorCode& GetError() {
        if (_fail_row_mutation == NULL) {
            CHECK_NOTNULL(_success_row_mutation);
            return _success_row_mutation->GetError();
        }
        if (_success_row_mutation == NULL) {
            CHECK_NOTNULL(_fail_row_mutation);
            return _fail_row_mutation->GetError();
        }
        if (FLAGS_tera_replication_write_need_all_success) {
            return _fail_row_mutation->GetError();
        } else {
            return _success_row_mutation->GetError();
        }
    }

public:
    const std::vector<RowMutation*>& GetRowMutationList() {
        return _row_mutations;
    }

    const std::vector<Table*>& GetTableList() {
        return _tables;
    }

    bool IsAsync() {
        return (_user_callback != NULL);
    }

    void Wait() {
        CHECK(_user_callback == NULL);
        MutexLock l(&_mutex);
        while (_finish_count < _row_mutations.size()) {
            _finish_cond.Wait();
        }
    }

private:
    RowMutationReplicateImpl(const RowMutationReplicateImpl&);
    void operator=(const RowMutationReplicateImpl&);

    static void RowMutationCallback(RowMutation* mutation) {
        RowMutationReplicateImpl* mutation_rep = (RowMutationReplicateImpl*)mutation->GetContext();
        mutation_rep->ProcessCallback(mutation);
    }

    void ProcessCallback(RowMutation* mutation) {
        _mutex.Lock();
        if (mutation->GetError().GetType() == tera::ErrorCode::kOK) {
            if (_success_row_mutation == NULL) {
                _success_row_mutation = mutation;
            }
        } else {
            if (_fail_row_mutation == NULL) {
                _fail_row_mutation = mutation;
            }
        }
        if (++_finish_count == _row_mutations.size()) {
            if (_user_callback != NULL) {
                _mutex.Unlock(); // remember to unlock
                _user_callback(this);
                return; // remember to return
            } else {
                _finish_cond.Signal();
            }
        }
        _mutex.Unlock();
    }

    std::vector<RowMutation*> _row_mutations;
    std::vector<Table*> _tables;
    RowMutationReplicate::Callback _user_callback;
    void* _user_context;

    Mutex _mutex;
    CondVar _finish_cond;
    uint32_t _finish_count;
    RowMutation* _success_row_mutation;
    RowMutation* _fail_row_mutation;
};

class RowReaderReplicateImpl : public RowReaderReplicate {
public:
    RowReaderReplicateImpl(const std::vector<RowReader*>& row_readers,
                           const std::vector<Table*>& tables)
        : _row_readers(row_readers),
          _tables(tables),
          _user_callback(NULL),
          _user_context(NULL),
          _finish_cond(&_mutex),
          _finish_count(0),
          _valid_row_reader(NULL) {
        CHECK_GT(_row_readers.size(), 0u);
        for (size_t i = 0; i < _row_readers.size(); i++) {
            _row_readers[i]->SetCallBack(RowReaderCallback);
            _row_readers[i]->SetContext(this);
        }
    }

    virtual ~RowReaderReplicateImpl() {
        for (size_t i = 0; i < _row_readers.size(); i++) {
            delete _row_readers[i];
        }
    }

    virtual const std::string& RowName() {
        return _row_readers[0]->RowName();
    }

    virtual void SetCallBack(Callback callback) {
        _user_callback = callback;
        for (size_t i = 0; i < _row_readers.size(); i++) {
            _row_readers[i]->SetCallBack(RowReaderCallback);
            _row_readers[i]->SetContext(this);
        }
    }

    virtual void SetContext(void* context) {
        _user_context = context;
    }

    virtual void* GetContext() {
        return _user_context;
    }

    virtual ErrorCode GetError() {
        CHECK_NOTNULL(_valid_row_reader);
        return _valid_row_reader->GetError();
    }

    virtual std::string Value() {
        CHECK_NOTNULL(_valid_row_reader);
        return _valid_row_reader->Value();
    }

public:
    const std::vector<RowReader*>& GetRowReaderList() {
        return _row_readers;
    }

    const std::vector<Table*>& GetTableList() {
        return _tables;
    }

    bool IsAsync() {
        return (_user_callback != NULL);
    }

    void Wait() {
        CHECK(_user_callback == NULL);
        MutexLock l(&_mutex);
        while (_finish_count < _row_readers.size()) {
            _finish_cond.Wait();
        }
    }

private:
    RowReaderReplicateImpl(const RowReaderReplicateImpl&);
    void operator=(const RowReaderReplicateImpl&);

    static void RowReaderCallback(RowReader* reader) {
        RowReaderReplicateImpl* reader_rep = (RowReaderReplicateImpl*)reader->GetContext();
        reader_rep->ProcessCallback(reader);
    }

    void ProcessCallback(RowReader* reader) {
        _mutex.Lock();
        if (_valid_row_reader == NULL && reader->GetError().GetType() == tera::ErrorCode::kOK) {
            _valid_row_reader = reader;
        }
        if (++_finish_count == _row_readers.size()) {
            // if all readers fail, use readers[0]
            if (_valid_row_reader == NULL) {
                _valid_row_reader = _row_readers[0];
            }
            if (_user_callback != NULL) {
                _mutex.Unlock(); // remember to unlock
                _user_callback(this);
                return; // remember to return
            } else {
                _finish_cond.Signal();
            }
        }
        _mutex.Unlock();
    }

    std::vector<RowReader*> _row_readers;
    std::vector<Table*> _tables;
    RowReaderReplicate::Callback _user_callback;
    void* _user_context;

    Mutex _mutex;
    CondVar _finish_cond;
    uint32_t _finish_count;
    RowReader* _valid_row_reader;
};

/// 表接口
class TableReplicateImpl : public TableReplicate {
public:
    TableReplicateImpl(std::vector<Table*> tables) : _tables(tables) {}
    virtual ~TableReplicateImpl() {
        for (size_t i = 0; i < _tables.size(); i++) {
            delete _tables[i];
        }
    }

    virtual RowMutationReplicate* NewRowMutation(const std::string& row_key) {
        std::vector<RowMutation*> row_mutations;
        for (size_t i = 0; i < _tables.size(); i++) {
            row_mutations.push_back(_tables[i]->NewRowMutation(row_key));
        }
        return new RowMutationReplicateImpl(row_mutations, _tables);
    }

    virtual void ApplyMutation(RowMutationReplicate* mutation_rep) {
        RowMutationReplicateImpl* mutation_rep_impl = (RowMutationReplicateImpl*)mutation_rep;
        bool is_async = mutation_rep_impl->IsAsync();
        const std::vector<RowMutation*>& mutation_list = mutation_rep_impl->GetRowMutationList();
        const std::vector<Table*>& table_list = mutation_rep_impl->GetTableList();
        for (size_t i = 0; i < mutation_list.size(); i++) {
            table_list[i]->ApplyMutation(mutation_list[i]);
        }
        if (!is_async) {
            mutation_rep_impl->Wait();
        }
    }

    virtual RowReaderReplicate* NewRowReader(const std::string& row_key) {
        std::vector<RowReader*> row_readers;
        std::vector<Table*> tables;
        if (FLAGS_tera_replication_read_try_all) {
            for (size_t i = 0; i < _tables.size(); i++) {
                row_readers.push_back(_tables[i]->NewRowReader(row_key));
                tables.push_back(_tables[i]);
            }
        } else {
            size_t i = random() % _tables.size();
            row_readers.push_back(_tables[i]->NewRowReader(row_key));
            tables.push_back(_tables[i]);
        }
        return new RowReaderReplicateImpl(row_readers, tables);
    }

    virtual void Get(RowReaderReplicate* reader_rep) {
        RowReaderReplicateImpl* reader_rep_impl = (RowReaderReplicateImpl*)reader_rep;
        bool is_async = reader_rep_impl->IsAsync();
        const std::vector<RowReader*>& reader_list = reader_rep_impl->GetRowReaderList();
        const std::vector<Table*>& table_list = reader_rep_impl->GetTableList();
        for (size_t i = 0; i < reader_list.size(); i++) {
            table_list[i]->Get(reader_list[i]);
        }
        if (!is_async) {
            reader_rep_impl->Wait();
        }
    }

private:
    TableReplicateImpl(const TableReplicateImpl&);
    void operator=(const TableReplicateImpl&);

    std::vector<Table*> _tables;
};

class ClientReplicateImpl : public ClientReplicate {
public:
    /// 打开表格, 失败返回NULL
    virtual TableReplicate* OpenTable(const std::string& table_name, ErrorCode* err) {
        std::vector<Table*> tables;
        for (size_t i = 0; i < _clients.size(); i++) {
            Table* table = _clients[i]->OpenTable(table_name, err);
            if (table == NULL) {
                for (size_t j = 0; j < tables.size(); j++) {
                    delete tables[j];
                }
                return NULL;
            }
            tables.push_back(table);
        }
        return new TableReplicateImpl(tables);
    }

    ClientReplicateImpl(const std::vector<Client*>& clients) : _clients(clients) {}
    virtual ~ClientReplicateImpl() {
        for (size_t i = 0; i < _clients.size(); i++) {
            delete _clients[i];
        }
    }

private:
    ClientReplicateImpl(const ClientReplicateImpl&);
    void operator=(const ClientReplicateImpl&);

    std::vector<Client*> _clients;
};

void ClientReplicate::SetGlogIsInitialized() {
    Client::SetGlogIsInitialized();
}

ClientReplicate* ClientReplicate::NewClient(const std::string& confpath,
                                            const std::string& log_prefix,
                                            ErrorCode* err) {
    utils::LoadFlagFile(confpath);
    std::string conf_paths = FLAGS_tera_replication_conf_paths;
    std::vector<std::string> confs;
    size_t token_pos = 0;
    while (token_pos < conf_paths.size()) {
        size_t delim_pos = conf_paths.find(';', token_pos);
        std::string token(conf_paths, token_pos, delim_pos - token_pos);
        if (!token.empty()) {
            confs.push_back(token);
        }
        if (delim_pos == std::string::npos) {
            break;
        }
        token_pos = delim_pos + 1;
    }

    std::vector<Client*> clients;
    for (size_t i = 0; i < confs.size(); i++) {
        Client* client = Client::NewClient(confs[i], log_prefix, err);
        if (client == NULL) {
            for (size_t j = 0; j < clients.size(); j++) {
                delete clients[j];
            }
            return NULL;
        }
        clients.push_back(client);
    }
    return new ClientReplicateImpl(clients);
}

ClientReplicate* ClientReplicate::NewClient(const std::string& confpath, ErrorCode* err) {
    return NewClient(confpath, "tera", err);
}

ClientReplicate* ClientReplicate::NewClient() {
    return NewClient("", NULL);
}

} // namespace tera

<commit_msg>issue=#907 bugfix of replication sdk<commit_after>// Copyright (c) 2016, Baidu.com, Inc. All Rights Reserved
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sdk/tera_replication.h"

#include "common/mutex.h"
#include "types.h"
#include "utils/config_utils.h"

DEFINE_bool(tera_replication_read_try_all, false, "try to read all replicas instread of randomly choose one");
DEFINE_bool(tera_replication_write_need_all_success, false, "return OK only if all replicas write success");
DEFINE_string(tera_replication_conf_paths, "../conf/tera.flag", "paths for flag files. use \';\' to split");

namespace tera {

class RowMutationReplicateImpl : public RowMutationReplicate {
public:
    RowMutationReplicateImpl(const std::vector<RowMutation*>& row_mutations,
                             const std::vector<Table*>& tables)
        : _row_mutations(row_mutations),
          _tables(tables),
          _user_callback(NULL),
          _user_context(NULL),
          _finish_cond(&_mutex),
          _finish_count(0),
          _success_row_mutation(NULL),
          _fail_row_mutation(NULL) {
        CHECK_GT(_row_mutations.size(), 0u);
        for (size_t i = 0; i < _row_mutations.size(); i++) {
            _row_mutations[i]->SetCallBack(RowMutationCallback);
            _row_mutations[i]->SetContext(this);
        }
    }

    virtual ~RowMutationReplicateImpl() {
        for (size_t i = 0; i < _row_mutations.size(); i++) {
            delete _row_mutations[i];
        }
    }

    virtual const std::string& RowKey() {
        return _row_mutations[0]->RowKey();
    }

    virtual void Put(const std::string& value) {
        for (size_t i = 0; i < _row_mutations.size(); i++) {
            _row_mutations[i]->Put(value);
        }
    }

    virtual void Put(const std::string& value, int32_t ttl) {
        for (size_t i = 0; i < _row_mutations.size(); i++) {
            _row_mutations[i]->Put(value, ttl);
        }
    }

    virtual void DeleteRow() {
        for (size_t i = 0; i < _row_mutations.size(); i++) {
            _row_mutations[i]->DeleteRow();
        }
    }

    virtual void SetCallBack(Callback callback) {
        _user_callback = callback;
    }

    virtual Callback GetCallBack() {
        return _user_callback;
    }

    virtual void SetContext(void* context) {
        _user_context = context;
    }

    virtual void* GetContext() {
        return _user_context;
    }

    virtual const ErrorCode& GetError() {
        if (_fail_row_mutation == NULL) {
            CHECK_NOTNULL(_success_row_mutation);
            return _success_row_mutation->GetError();
        }
        if (_success_row_mutation == NULL) {
            CHECK_NOTNULL(_fail_row_mutation);
            return _fail_row_mutation->GetError();
        }
        if (FLAGS_tera_replication_write_need_all_success) {
            return _fail_row_mutation->GetError();
        } else {
            return _success_row_mutation->GetError();
        }
    }

public:
    const std::vector<RowMutation*>& GetRowMutationList() {
        return _row_mutations;
    }

    const std::vector<Table*>& GetTableList() {
        return _tables;
    }

    bool IsAsync() {
        return (_user_callback != NULL);
    }

    void Wait() {
        CHECK(_user_callback == NULL);
        MutexLock l(&_mutex);
        while (_finish_count < _row_mutations.size()) {
            _finish_cond.Wait();
        }
    }

private:
    RowMutationReplicateImpl(const RowMutationReplicateImpl&);
    void operator=(const RowMutationReplicateImpl&);

    static void RowMutationCallback(RowMutation* mutation) {
        RowMutationReplicateImpl* mutation_rep = (RowMutationReplicateImpl*)mutation->GetContext();
        mutation_rep->ProcessCallback(mutation);
    }

    void ProcessCallback(RowMutation* mutation) {
        _mutex.Lock();
        if (mutation->GetError().GetType() == tera::ErrorCode::kOK) {
            if (_success_row_mutation == NULL) {
                _success_row_mutation = mutation;
            }
        } else {
            if (_fail_row_mutation == NULL) {
                _fail_row_mutation = mutation;
            }
        }
        if (++_finish_count == _row_mutations.size()) {
            if (_user_callback != NULL) {
                _mutex.Unlock(); // remember to unlock
                _user_callback(this);
                return; // remember to return
            } else {
                _finish_cond.Signal();
            }
        }
        _mutex.Unlock();
    }

    std::vector<RowMutation*> _row_mutations;
    std::vector<Table*> _tables;
    RowMutationReplicate::Callback _user_callback;
    void* _user_context;

    Mutex _mutex;
    CondVar _finish_cond;
    uint32_t _finish_count;
    RowMutation* _success_row_mutation;
    RowMutation* _fail_row_mutation;
};

class RowReaderReplicateImpl : public RowReaderReplicate {
public:
    RowReaderReplicateImpl(const std::vector<RowReader*>& row_readers,
                           const std::vector<Table*>& tables)
        : _row_readers(row_readers),
          _tables(tables),
          _user_callback(NULL),
          _user_context(NULL),
          _finish_cond(&_mutex),
          _finish_count(0),
          _valid_row_reader(NULL) {
        CHECK_GT(_row_readers.size(), 0u);
        for (size_t i = 0; i < _row_readers.size(); i++) {
            _row_readers[i]->SetCallBack(RowReaderCallback);
            _row_readers[i]->SetContext(this);
        }
    }

    virtual ~RowReaderReplicateImpl() {
        for (size_t i = 0; i < _row_readers.size(); i++) {
            delete _row_readers[i];
        }
    }

    virtual const std::string& RowName() {
        return _row_readers[0]->RowName();
    }

    virtual void SetCallBack(Callback callback) {
        _user_callback = callback;
    }

    virtual void SetContext(void* context) {
        _user_context = context;
    }

    virtual void* GetContext() {
        return _user_context;
    }

    virtual ErrorCode GetError() {
        CHECK_NOTNULL(_valid_row_reader);
        return _valid_row_reader->GetError();
    }

    virtual std::string Value() {
        CHECK_NOTNULL(_valid_row_reader);
        return _valid_row_reader->Value();
    }

public:
    const std::vector<RowReader*>& GetRowReaderList() {
        return _row_readers;
    }

    const std::vector<Table*>& GetTableList() {
        return _tables;
    }

    bool IsAsync() {
        return (_user_callback != NULL);
    }

    void Wait() {
        CHECK(_user_callback == NULL);
        MutexLock l(&_mutex);
        while (_finish_count < _row_readers.size()) {
            _finish_cond.Wait();
        }
    }

private:
    RowReaderReplicateImpl(const RowReaderReplicateImpl&);
    void operator=(const RowReaderReplicateImpl&);

    static void RowReaderCallback(RowReader* reader) {
        RowReaderReplicateImpl* reader_rep = (RowReaderReplicateImpl*)reader->GetContext();
        reader_rep->ProcessCallback(reader);
    }

    void ProcessCallback(RowReader* reader) {
        _mutex.Lock();
        if (_valid_row_reader == NULL && reader->GetError().GetType() == tera::ErrorCode::kOK) {
            _valid_row_reader = reader;
        }
        if (++_finish_count == _row_readers.size()) {
            // if all readers fail, use readers[0]
            if (_valid_row_reader == NULL) {
                _valid_row_reader = _row_readers[0];
            }
            if (_user_callback != NULL) {
                _mutex.Unlock(); // remember to unlock
                _user_callback(this);
                return; // remember to return
            } else {
                _finish_cond.Signal();
            }
        }
        _mutex.Unlock();
    }

    std::vector<RowReader*> _row_readers;
    std::vector<Table*> _tables;
    RowReaderReplicate::Callback _user_callback;
    void* _user_context;

    Mutex _mutex;
    CondVar _finish_cond;
    uint32_t _finish_count;
    RowReader* _valid_row_reader;
};

/// 表接口
class TableReplicateImpl : public TableReplicate {
public:
    TableReplicateImpl(std::vector<Table*> tables) : _tables(tables) {}
    virtual ~TableReplicateImpl() {
        for (size_t i = 0; i < _tables.size(); i++) {
            delete _tables[i];
        }
    }

    virtual RowMutationReplicate* NewRowMutation(const std::string& row_key) {
        std::vector<RowMutation*> row_mutations;
        for (size_t i = 0; i < _tables.size(); i++) {
            row_mutations.push_back(_tables[i]->NewRowMutation(row_key));
        }
        return new RowMutationReplicateImpl(row_mutations, _tables);
    }

    virtual void ApplyMutation(RowMutationReplicate* mutation_rep) {
        RowMutationReplicateImpl* mutation_rep_impl = (RowMutationReplicateImpl*)mutation_rep;
        bool is_async = mutation_rep_impl->IsAsync();
        const std::vector<RowMutation*>& mutation_list = mutation_rep_impl->GetRowMutationList();
        const std::vector<Table*>& table_list = mutation_rep_impl->GetTableList();
        // in async mode, after the last call of ApplyMutation, we should not access
        // 'mutation_rep_impl' anymore, that's why we assign the value of 'mutation_list.size()'
        // to a local variable 'mutation_num'
        size_t mutation_num = mutation_list.size();
        for (size_t i = 0; i < mutation_num; i++) {
            table_list[i]->ApplyMutation(mutation_list[i]);
        }
        if (!is_async) {
            mutation_rep_impl->Wait();
        }
    }

    virtual RowReaderReplicate* NewRowReader(const std::string& row_key) {
        std::vector<RowReader*> row_readers;
        std::vector<Table*> tables;
        if (FLAGS_tera_replication_read_try_all) {
            for (size_t i = 0; i < _tables.size(); i++) {
                row_readers.push_back(_tables[i]->NewRowReader(row_key));
                tables.push_back(_tables[i]);
            }
        } else {
            size_t i = random() % _tables.size();
            row_readers.push_back(_tables[i]->NewRowReader(row_key));
            tables.push_back(_tables[i]);
        }
        return new RowReaderReplicateImpl(row_readers, tables);
    }

    virtual void Get(RowReaderReplicate* reader_rep) {
        RowReaderReplicateImpl* reader_rep_impl = (RowReaderReplicateImpl*)reader_rep;
        bool is_async = reader_rep_impl->IsAsync();
        const std::vector<RowReader*>& reader_list = reader_rep_impl->GetRowReaderList();
        const std::vector<Table*>& table_list = reader_rep_impl->GetTableList();
        size_t reader_num = reader_list.size();
        for (size_t i = 0; i < reader_num; i++) {
            table_list[i]->Get(reader_list[i]);
        }
        if (!is_async) {
            reader_rep_impl->Wait();
        }
    }

private:
    TableReplicateImpl(const TableReplicateImpl&);
    void operator=(const TableReplicateImpl&);

    std::vector<Table*> _tables;
};

class ClientReplicateImpl : public ClientReplicate {
public:
    /// 打开表格, 失败返回NULL
    virtual TableReplicate* OpenTable(const std::string& table_name, ErrorCode* err) {
        std::vector<Table*> tables;
        for (size_t i = 0; i < _clients.size(); i++) {
            Table* table = _clients[i]->OpenTable(table_name, err);
            if (table == NULL) {
                for (size_t j = 0; j < tables.size(); j++) {
                    delete tables[j];
                }
                return NULL;
            }
            tables.push_back(table);
        }
        return new TableReplicateImpl(tables);
    }

    ClientReplicateImpl(const std::vector<Client*>& clients) : _clients(clients) {}
    virtual ~ClientReplicateImpl() {
        for (size_t i = 0; i < _clients.size(); i++) {
            delete _clients[i];
        }
    }

private:
    ClientReplicateImpl(const ClientReplicateImpl&);
    void operator=(const ClientReplicateImpl&);

    std::vector<Client*> _clients;
};

void ClientReplicate::SetGlogIsInitialized() {
    Client::SetGlogIsInitialized();
}

ClientReplicate* ClientReplicate::NewClient(const std::string& confpath,
                                            const std::string& log_prefix,
                                            ErrorCode* err) {
    utils::LoadFlagFile(confpath);
    std::string conf_paths = FLAGS_tera_replication_conf_paths;
    std::vector<std::string> confs;
    size_t token_pos = 0;
    while (token_pos < conf_paths.size()) {
        size_t delim_pos = conf_paths.find(';', token_pos);
        std::string token(conf_paths, token_pos, delim_pos - token_pos);
        if (!token.empty()) {
            confs.push_back(token);
        }
        if (delim_pos == std::string::npos) {
            break;
        }
        token_pos = delim_pos + 1;
    }

    std::vector<Client*> clients;
    for (size_t i = 0; i < confs.size(); i++) {
        Client* client = Client::NewClient(confs[i], log_prefix, err);
        if (client == NULL) {
            for (size_t j = 0; j < clients.size(); j++) {
                delete clients[j];
            }
            return NULL;
        }
        clients.push_back(client);
    }
    return new ClientReplicateImpl(clients);
}

ClientReplicate* ClientReplicate::NewClient(const std::string& confpath, ErrorCode* err) {
    return NewClient(confpath, "tera", err);
}

ClientReplicate* ClientReplicate::NewClient() {
    return NewClient("", NULL);
}

} // namespace tera

<|endoftext|>


<commit_before>/**
 *  Concept 4 : compile time constants.
 */

#include <iostream>

int main()
{
  constexpr uint32_t MEMORY_SIZE{ 512 };

}
<commit_msg>Update constexpr_variable.cpp<commit_after>/**
 *  Concept 4 : compile time constants.
 */

#include <iostream>

int main()
{
  constexpr uint32_t MEMORY_SIZE{ 512 };
  std::cout << MEMORY_SIZE << std::endl;
}
<|endoftext|>


<commit_before>#include "rhodes/JNIRhodes.h"

#include <common/rhoparams.h>

#undef DEFAULT_LOGCATEGORY
#define DEFAULT_LOGCATEGORY "MapView"

RHO_GLOBAL void mapview_create(rho_param *p)
{
#ifdef RHO_GOOGLE_API_KEY
    JNIEnv *env = jnienv();
    jclass clsMapView = getJNIClass(RHODES_JAVA_CLASS_MAPVIEW);
    if (!clsMapView) return;
    jmethodID midCreate = getJNIClassStaticMethod(env, clsMapView, "create", "(Ljava/lang/String;Ljava/util/Map;)V");
    if (!midCreate) return;

    if (p->type != RHO_PARAM_HASH) {
        RAWLOG_ERROR("create: wrong input parameter (expect Hash)");
        return;
    }

    jobject paramsObj = RhoValueConverter(env).createObject(p);
    jstring keyObj = rho_cast<jstring>(RHO_GOOGLE_API_KEY);
    env->CallStaticVoidMethod(clsMapView, midCreate, keyObj, paramsObj);
    env->DeleteLocalRef(keyObj);
    env->DeleteLocalRef(paramsObj);
#else
    RAWLOG_ERROR("MapView disabled at build time");
#endif
}

RHO_GLOBAL void mapview_close()
{
#ifdef RHO_GOOGLE_API_KEY
    JNIEnv *env = jnienv();
    jclass clsMapView = getJNIClass(RHODES_JAVA_CLASS_MAPVIEW);
    if (!clsMapView) return;
    jmethodID midClose = getJNIClassStaticMethod(env, clsMapView, "close", "()V");
    if (!midClose) return;

    env->CallStaticVoidMethod(clsMapView, midClose);
#endif
}

RHO_GLOBAL VALUE mapview_state_started()
{
#ifdef RHO_GOOGLE_API_KEY
    VALUE nil = rho_ruby_get_NIL();
    JNIEnv *env = jnienv();
    jclass cls = getJNIClass(RHODES_JAVA_CLASS_MAPVIEW);
    if (!cls) return nil;
    jmethodID mid = getJNIClassStaticMethod(env, cls, "isStarted", "()Z");
    if (!mid) return nil;

    return rho_ruby_create_boolean(env->CallStaticBooleanMethod(cls, mid));
#else
    return rho_ruby_create_boolean(0);
#endif
}

RHO_GLOBAL double mapview_state_center_lat()
{
#ifdef RHO_GOOGLE_API_KEY
    JNIEnv *env = jnienv();
    jclass cls = getJNIClass(RHODES_JAVA_CLASS_MAPVIEW);
    if (!cls) return 0;
    jmethod mid = getJNIClassStaticMethod(env, cls, "getCenterLatitude", "()D");
    if (!mid) return 0;

    return env->CallStaticDoubleMethod(cls, mid);
#else
    return 0;
#endif
}

RHO_GLOBAL double mapview_state_center_lon()
{
#ifdef RHO_GOOGLE_API_KEY
    JNIEnv *env = jnienv();
    jclass cls = getJNIClass(RHODES_JAVA_CLASS_MAPVIEW);
    if (!cls) return 0;
    jmethod mid = getJNIClassStaticMethod(env, cls, "getCenterLongitude", "()D");
    if (!mid) return 0;

    return env->CallStaticDoubleMethod(cls, mid);
#else
    return 0;
#endif
}

<commit_msg>fix compilation error when api key is included.<commit_after>#include "rhodes/JNIRhodes.h"

#include <common/rhoparams.h>

#undef DEFAULT_LOGCATEGORY
#define DEFAULT_LOGCATEGORY "MapView"

RHO_GLOBAL void mapview_create(rho_param *p)
{
#ifdef RHO_GOOGLE_API_KEY
    JNIEnv *env = jnienv();
    jclass clsMapView = getJNIClass(RHODES_JAVA_CLASS_MAPVIEW);
    if (!clsMapView) return;
    jmethodID midCreate = getJNIClassStaticMethod(env, clsMapView, "create", "(Ljava/lang/String;Ljava/util/Map;)V");
    if (!midCreate) return;

    if (p->type != RHO_PARAM_HASH) {
        RAWLOG_ERROR("create: wrong input parameter (expect Hash)");
        return;
    }

    jobject paramsObj = RhoValueConverter(env).createObject(p);
    jstring keyObj = rho_cast<jstring>(RHO_GOOGLE_API_KEY);
    env->CallStaticVoidMethod(clsMapView, midCreate, keyObj, paramsObj);
    env->DeleteLocalRef(keyObj);
    env->DeleteLocalRef(paramsObj);
#else
    RAWLOG_ERROR("MapView disabled at build time");
#endif
}

RHO_GLOBAL void mapview_close()
{
#ifdef RHO_GOOGLE_API_KEY
    JNIEnv *env = jnienv();
    jclass clsMapView = getJNIClass(RHODES_JAVA_CLASS_MAPVIEW);
    if (!clsMapView) return;
    jmethodID midClose = getJNIClassStaticMethod(env, clsMapView, "close", "()V");
    if (!midClose) return;

    env->CallStaticVoidMethod(clsMapView, midClose);
#endif
}

RHO_GLOBAL VALUE mapview_state_started()
{
#ifdef RHO_GOOGLE_API_KEY
    VALUE nil = rho_ruby_get_NIL();
    JNIEnv *env = jnienv();
    jclass cls = getJNIClass(RHODES_JAVA_CLASS_MAPVIEW);
    if (!cls) return nil;
    jmethodID mid = getJNIClassStaticMethod(env, cls, "isStarted", "()Z");
    if (!mid) return nil;

    return rho_ruby_create_boolean(env->CallStaticBooleanMethod(cls, mid));
#else
    return rho_ruby_create_boolean(0);
#endif
}

RHO_GLOBAL double mapview_state_center_lat()
{
#ifdef RHO_GOOGLE_API_KEY
    JNIEnv *env = jnienv();
    jclass cls = getJNIClass(RHODES_JAVA_CLASS_MAPVIEW);
    if (!cls) return 0;
    jmethodID mid = getJNIClassStaticMethod(env, cls, "getCenterLatitude", "()D");
    if (!mid) return 0;

    return env->CallStaticDoubleMethod(cls, mid);
#else
    return 0;
#endif
}

RHO_GLOBAL double mapview_state_center_lon()
{
#ifdef RHO_GOOGLE_API_KEY
    JNIEnv *env = jnienv();
    jclass cls = getJNIClass(RHODES_JAVA_CLASS_MAPVIEW);
    if (!cls) return 0;
    jmethodID mid = getJNIClassStaticMethod(env, cls, "getCenterLongitude", "()D");
    if (!mid) return 0;

    return env->CallStaticDoubleMethod(cls, mid);
#else
    return 0;
#endif
}

<|endoftext|>


<commit_before>/**
 * particles.cpp
 * \author Joshua Vasquez
 * \date May 1, 2014 to June 8, 2014
 */
#include "particles.hpp"
#include <limits>   ///< for representation of inifinity as a float

Particles::Particles(size_t numParticles)
:numParticles_{numParticles}
{
    // dynamically allocate an array of pointers to particles.
    theParticles_ = new Particle*[numParticles_];
    for (size_t eachPart = 0; eachPart < numParticles_; ++eachPart)
        theParticles_[eachPart] = new Particle{0,0,0};
}

Particles::~Particles()
{
    // Free our dynamically allocated memory.
    for (size_t eachPart = 0; eachPart< numParticles_; ++eachPart)
        delete theParticles_[eachPart];
    delete [] theParticles_;    // FIXME: is this a double-delete?
}

void Particles::scatterParticles(float xmax, float ymax)
{
    std::default_random_engine generator;
    //FIXME: change to real distributions, not int distributions.
    std::uniform_int_distribution<int> distributionX(0,xmax);
    std::uniform_int_distribution<int> distributionY(0,ymax);
    std::uniform_int_distribution<int> distributionTheta(0,360);

    for(size_t eachPart = 0; eachPart < numParticles_; ++eachPart)
    {
        theParticles_[eachPart]->xVal_ = distributionX(generator);
        theParticles_[eachPart]->yVal_ = distributionY(generator);
        theParticles_[eachPart]->theta_ = distributionTheta(generator);
    }

}

void Particles::propagateParticles()
{

}

void Particles::updateParticles()
{
}

// Particle Member functions
Particles::Particle::Particle(double xVal, double yVal, double weight)
:xVal_{xVal}, yVal_{yVal}, weight_{weight}
{
    // Nothing else to do!
}

Particles::Particle::~Particle()
{
    // Nothing to do!
}

void Particles::Particle::updateParticle(double lWheelDelta,
                                        double rWheelDelta,
                                        bool noise)
{
    double noiseLeftW = 0;
    double noiseRightW = 0;

    if (noise)
    {
        // TODO: create the generator once, not each time fn is called!
        std::default_random_engine generator;
        std::normal_distribution<double> distribution(-1.0, 1.0);
        // TODO: tweak noise function later!
        noiseLeftW = (lWheelDelta)*distribution(generator);
        noiseRightW = (rWheelDelta)*distribution(generator);
    }
    else
    {
        // Calc new x,y,theta through motion model. Check THETA usage.
        xVal_ += (robotParams::wheelRadius_ / 2) * (lWheelDelta + noiseLeftW +
                  rWheelDelta + noiseRightW) * cos(theta_*(M_PI/180));
        yVal_ += (robotParams::wheelRadius_ / 2) * (lWheelDelta + noiseLeftW +
                  rWheelDelta + noiseRightW) * sin(theta_*(M_PI/180));
        theta_ += (robotParams::wheelRadius_ / robotParams::wheelSpacing_) *
                  ((rWheelDelta + noiseRightW)- (lWheelDelta + noiseLeftW));
    }

}

float Particles::getWallDist( float scannerX, float scannerY, float scannerTheta,
                            float segX1, float segY1, float segX2, float segY2)
{

    // Compare Slopes:
    float laserM = round(tan(tuneAngle(scannerTheta)));
    float segmentM = (segY2 - segY1)/(segX2 - segX1);
    float intersectionX, intersectionY;

    // Handle the case where angles point in opposite vertical directions.
    if((laserM == std::numeric_limits<float>::infinity() ||
       (laserM == -std::numeric_limits<float>::infinity())) &&
       (segmentM == std::numeric_limits<float>::infinity() ||
       (segmentM == -std::numeric_limits<float>::infinity())))
        return std::numeric_limits<float>::infinity();

    // Handle the case where both lines are basically parallel.
    if (approxEqual(laserM, segmentM, 1))
        return std::numeric_limits<float>::infinity();

    // Use geometry when a vertical line is involved.
    // Old triangle formula: R = x/cos(theta).
    if(segmentM == std::numeric_limits<float>::infinity())
    {
        // FIXME: double-check if off-segment check works
        // FIXME: intersectionDist should be positive!!
        float intersectionDist = std::abs((std::max(segX1,scannerX) -
                                 std::min(segX1, scannerX))/
                                 cos(tuneAngle(scannerTheta)));
/*
        std::cout <<"intersectionDist:" <<  intersectionDist << std::endl;
*/
        intersectionX = round(scannerX +
                        intersectionDist *
                        std::abs(cos(tuneAngle(scannerTheta))));
        intersectionY = round(scannerY +
                        intersectionDist *
                        std::abs(sin(tuneAngle(scannerTheta))));
/*
        std::cout << "intersection: (" << intersectionX << ", "
                  << intersectionY << ")" << std::endl;
*/

        // Calculate if intersection is on wall segment.
        if (scanOffSegment(intersectionX, intersectionY,
                            segX1, segY1, segX2, segY2))
        {
/*
            std::cout << "scan off segment" << std::endl;
*/
            return std::numeric_limits<float>::infinity();
        }

        if (scanBackwards(scannerX, scannerY, scannerTheta, intersectionX,
                          intersectionY))
        {
/*
            std::cout << "scan backwards!" << std::endl;
*/
            return std::numeric_limits<float>::infinity();
        }

        return intersectionDist;
    }
    if(laserM == std::numeric_limits<float>::infinity())
    {
        // FIXME: double-check if off-segment check works
        float wallAngle = atan2((segY2 - segY1), (segX2 - segX1));
        float intersectionDist = std::abs((std::max(segX1,scannerX) -
                                 std::min(segX1, scannerX))/
                                 cos(wallAngle));
        intersectionX = round(scannerX +
                        intersectionDist *
                        std::abs(cos(tuneAngle(scannerTheta))));
        intersectionY = round(scannerY +
                        intersectionDist *
                        std::abs(sin(tuneAngle(scannerTheta))));
        if (scanOffSegment(intersectionX, intersectionY,
                    segX1, segY1, segX2, segY2))
            return std::numeric_limits<float>::infinity();

        if (scanBackwards(scannerX, scannerY, scannerTheta, intersectionX,
                          intersectionY))
            return std::numeric_limits<float>::infinity();

        else
            return intersectionDist;
    }
    // Use algebra for all other cases.
    float laserYInt = laserM*(-scannerX) + scannerY;
    float segmentYInt = segmentM * (-segX1) + segY1;
    intersectionX = (segmentYInt - laserYInt)/(laserM - segmentM);
    intersectionY = laserM*intersectionX + laserYInt;

    if (scanBackwards(scannerX, scannerY, scannerTheta, intersectionX,
                      intersectionY))
        return std::numeric_limits<float>::infinity();

    if (scanOffSegment(intersectionX, intersectionY, segX1, segY1, segX2,
                       segY2))
        return std::numeric_limits<float>::infinity();

    // translate to origin, and compute distance.
    return sqrt(pow((scannerX - intersectionX), 2) +
                pow((scannerY - intersectionY), 2));
}

float Particles::tuneAngle(float angleInDeg)
{
    float newAngle  = angleInDeg;
    // Map to circle range:
    while (newAngle > 360)
        newAngle -= 360;
    while (newAngle < -360)
        newAngle += 360;

    // Convert to -Pi/2 to Pi/2 range.
    if (newAngle > 180.)
        newAngle -= 360.;
    if (newAngle < -180.)
        newAngle += 360.;

    // Convert to radian.
    newAngle *= (M_PI/180.);
    return newAngle;

}

float Particles::round(float input)
{
    if (input > largeVal_)
        return std::numeric_limits<float>::infinity();
    if (input < -largeVal_)
        return -std::numeric_limits<float>::infinity();
    if (std::abs(input) < smallVal_)
        return 0.;
    return input;
}

bool Particles::approxEqual(float approxVal, float actualVal,
                            float percentError)
{
    if( round(actualVal) == 0.0)
    {
        return (round(approxVal) == 0.0);
    }

    return (((std::abs(approxVal - actualVal) / std::abs(actualVal)) * 100.0)
           < percentError);
}

bool Particles::scanBackwards(float scannerX, float scannerY,
                              float scannerTheta,
                              float intersectionX, float intersectionY)
{
    // Find angle of intersection point, relative to scanner point.
    // Translate laser scan line to intersect origin.
    // Take that angle with atan2
    float intersectionAngle = atan2( (intersectionY - scannerY),
                                     (intersectionX - scannerX));
/*
    std::cout << "intersectionAngle: " << intersectionAngle << std::endl;
    std::cout << "laser angle: " << tuneAngle(scannerTheta) << std::endl;
*/
    if (!approxEqual(intersectionAngle, tuneAngle(scannerTheta), 3))
    {
        return true;
    }
    return false;
}

bool Particles::scanOffSegment(float intersectionX, float intersectionY,
                           float segX1, float segY1, float segX2, float segY2)
{
    if ((intersectionX < std::min(segX1,segX2)) ||
          (intersectionX > std::max(segX1, segX2)))
    {
        // handle rounding error cases for narrow ranges of segX1 and segX2
        if (!(approxEqual(segX1, segX2, 3) &&
            approxEqual(segX1, intersectionX, 3)))
        {
            return true;
        }
    }
    if ((intersectionY < std::min(segY1,segY2)) ||
          (intersectionY > std::max(segY1,segY2)))
    {
        // handle rounding error cases for narrow ranges of segY1 and segY2
        if (!(approxEqual(segY1, segY2, 3) &&
            approxEqual(segY1, intersectionY, 3)))
        {
            return true;
        }
    }
    return false;
}
<commit_msg>getWallDist working for all tested cases thus far.<commit_after>/**
 * particles.cpp
 * \author Joshua Vasquez
 * \date May 1, 2014 to June 8, 2014
 */
#include "particles.hpp"
#include <limits>   ///< for representation of inifinity as a float

Particles::Particles(size_t numParticles)
:numParticles_{numParticles}
{
    // dynamically allocate an array of pointers to particles.
    theParticles_ = new Particle*[numParticles_];
    for (size_t eachPart = 0; eachPart < numParticles_; ++eachPart)
        theParticles_[eachPart] = new Particle{0,0,0};
}

Particles::~Particles()
{
    // Free our dynamically allocated memory.
    for (size_t eachPart = 0; eachPart< numParticles_; ++eachPart)
        delete theParticles_[eachPart];
    delete [] theParticles_;    // FIXME: is this a double-delete?
}

void Particles::scatterParticles(float xmax, float ymax)
{
    std::default_random_engine generator;
    //FIXME: change to real distributions, not int distributions.
    std::uniform_int_distribution<int> distributionX(0,xmax);
    std::uniform_int_distribution<int> distributionY(0,ymax);
    std::uniform_int_distribution<int> distributionTheta(0,360);

    for(size_t eachPart = 0; eachPart < numParticles_; ++eachPart)
    {
        theParticles_[eachPart]->xVal_ = distributionX(generator);
        theParticles_[eachPart]->yVal_ = distributionY(generator);
        theParticles_[eachPart]->theta_ = distributionTheta(generator);
    }

}

void Particles::propagateParticles()
{

}

void Particles::updateParticles()
{
}

// Particle Member functions
Particles::Particle::Particle(double xVal, double yVal, double weight)
:xVal_{xVal}, yVal_{yVal}, weight_{weight}
{
    // Nothing else to do!
}

Particles::Particle::~Particle()
{
    // Nothing to do!
}

void Particles::Particle::updateParticle(double lWheelDelta,
                                        double rWheelDelta,
                                        bool noise)
{
    double noiseLeftW = 0;
    double noiseRightW = 0;

    if (noise)
    {
        // TODO: create the generator once, not each time fn is called!
        std::default_random_engine generator;
        std::normal_distribution<double> distribution(-1.0, 1.0);
        // TODO: tweak noise function later!
        noiseLeftW = (lWheelDelta)*distribution(generator);
        noiseRightW = (rWheelDelta)*distribution(generator);
    }
    else
    {
        // Calc new x,y,theta through motion model. Check THETA usage.
        xVal_ += (robotParams::wheelRadius_ / 2) * (lWheelDelta + noiseLeftW +
                  rWheelDelta + noiseRightW) * cos(theta_*(M_PI/180));
        yVal_ += (robotParams::wheelRadius_ / 2) * (lWheelDelta + noiseLeftW +
                  rWheelDelta + noiseRightW) * sin(theta_*(M_PI/180));
        theta_ += (robotParams::wheelRadius_ / robotParams::wheelSpacing_) *
                  ((rWheelDelta + noiseRightW)- (lWheelDelta + noiseLeftW));
    }

}

//TODO: make this function shorter.
float Particles::getWallDist( float scannerX, float scannerY, float scannerTheta,
                            float segX1, float segY1, float segX2, float segY2)
{

    // Compare Slopes:
    float laserM = round(tan(tuneAngle(scannerTheta)));
    float segmentM = (segY2 - segY1)/(segX2 - segX1);
    float intersectionX, intersectionY;

    // Handle special case where parallel vertical lines could round to
    // opposite slopes.
    if((laserM == std::numeric_limits<float>::infinity() ||
       (laserM == -std::numeric_limits<float>::infinity())) &&
       (segmentM == std::numeric_limits<float>::infinity() ||
       (segmentM == -std::numeric_limits<float>::infinity())))
        return std::numeric_limits<float>::infinity();

    // Handle the case where both lines are basically parallel.
    if (approxEqual(laserM, segmentM, 1))
        return std::numeric_limits<float>::infinity();

    // Special easy-algebra cases when either scan line or wall is vertical.
    // TODO: shrink these two big if-blocks
    if(segmentM == std::numeric_limits<float>::infinity())
    {
        float laserYInt = laserM * (-scannerX) + scannerY;
        intersectionX = segX1;
        intersectionY = laserM * segX1 + laserYInt;

        float intersectionDist = sqrt(pow((scannerX - intersectionX), 2) +
                                      pow((scannerY - intersectionY), 2));
        std::cout << "intersectionDist: " << intersectionDist << std::endl;

        // Calculate if intersection is on wall segment.
        if (scanOffSegment(intersectionX, intersectionY,
                            segX1, segY1, segX2, segY2))
            return std::numeric_limits<float>::infinity();

        if (scanBackwards(scannerX, scannerY, scannerTheta, intersectionX,
                          intersectionY))
            return std::numeric_limits<float>::infinity();

        return intersectionDist;
    }

    if(laserM == std::numeric_limits<float>::infinity())
    {
        float wallYInt = segmentM * (-segX1) + segY1;

        intersectionX = scannerX;   ///< nice benefit of a vertical laser.
        intersectionY = segmentM * scannerX + wallYInt;
        float intersectionDist = sqrt(pow((scannerX - intersectionX), 2) +
                                      pow((scannerY - intersectionY), 2));

        if (scanOffSegment(intersectionX, intersectionY,
                    segX1, segY1, segX2, segY2))
            return std::numeric_limits<float>::infinity();
        if (scanBackwards(scannerX, scannerY, scannerTheta, intersectionX,
                          intersectionY))
            return std::numeric_limits<float>::infinity();

        return intersectionDist;
    }

    // Use slopes and intercepts with algebra for all other cases.
    float laserYInt = laserM*(-scannerX) + scannerY;
    float segmentYInt = segmentM * (-segX1) + segY1;
    intersectionX = (segmentYInt - laserYInt)/(laserM - segmentM);
    intersectionY = laserM*intersectionX + laserYInt;

    if (scanBackwards(scannerX, scannerY, scannerTheta, intersectionX,
                      intersectionY))
        return std::numeric_limits<float>::infinity();

    if (scanOffSegment(intersectionX, intersectionY, segX1, segY1, segX2,
                       segY2))
        return std::numeric_limits<float>::infinity();

    // translate to origin, and compute distance.
    return sqrt(pow((scannerX - intersectionX), 2) +
                pow((scannerY - intersectionY), 2));
}

float Particles::tuneAngle(float angleInDeg)
{
    float newAngle  = angleInDeg;
    // Map to circle range:
    while (newAngle > 360)
        newAngle -= 360;
    while (newAngle < -360)
        newAngle += 360;

    // Convert to -Pi/2 to Pi/2 range.
    if (newAngle > 180.)
        newAngle -= 360.;
    if (newAngle < -180.)
        newAngle += 360.;

    // Convert to radian.
    newAngle *= (M_PI/180.);
    return newAngle;

}

float Particles::round(float input)
{
    if (input > largeVal_)
        return std::numeric_limits<float>::infinity();
    if (input < -largeVal_)
        return -std::numeric_limits<float>::infinity();
    if (std::abs(input) < smallVal_)
        return 0.;
    return input;
}

bool Particles::approxEqual(float approxVal, float actualVal,
                            float percentError)
{
    if( round(actualVal) == 0.0)
    {
        return (round(approxVal) == 0.0);
    }

    return (((std::abs(approxVal - actualVal) / std::abs(actualVal)) * 100.0)
           < percentError);
}

bool Particles::scanBackwards(float scannerX, float scannerY,
                              float scannerTheta,
                              float intersectionX, float intersectionY)
{
    // Find angle of intersection point, relative to scanner point.
    // Translate laser scan line to intersect origin.
    // Take that angle with atan2
    float intersectionAngle = atan2( (intersectionY - scannerY),
                                     (intersectionX - scannerX));
/*
    std::cout << "intersectionAngle: " << intersectionAngle << std::endl;
    std::cout << "laser angle: " << tuneAngle(scannerTheta) << std::endl;
*/
    if (!approxEqual(intersectionAngle, tuneAngle(scannerTheta), 3))
    {
        return true;
    }
    return false;
}

bool Particles::scanOffSegment(float intersectionX, float intersectionY,
                           float segX1, float segY1, float segX2, float segY2)
{
    if ((intersectionX < std::min(segX1,segX2)) ||
          (intersectionX > std::max(segX1, segX2)))
    {
        // handle rounding error cases for narrow ranges of segX1 and segX2
        if (!(approxEqual(segX1, segX2, 3) &&
            approxEqual(segX1, intersectionX, 3)))
        {
            return true;
        }
    }
    if ((intersectionY < std::min(segY1,segY2)) ||
          (intersectionY > std::max(segY1,segY2)))
    {
        std::cout << "Y triggered" << std::endl;
        // handle rounding error cases for narrow ranges of segY1 and segY2
        if (!(approxEqual(segY1, segY2, 3) &&
            approxEqual(segY1, intersectionY, 3)))
        {
            return true;
        }
    }
    return false;
}
<|endoftext|>


<commit_before>// RUN: %clangxx_cfi -g -fsanitize-stats -o %t %s
// RUN: env SANITIZER_STATS_PATH=%t.stats %t
// RUN: sanstats %t.stats | FileCheck %s

struct ABase {};

struct A : ABase {
  virtual void vf() {}
  void nvf() {}
};

extern "C" __attribute__((noinline)) void vcall(A *a) {
  // CHECK: stats.cpp:[[@LINE+1]] vcall cfi-vcall 37
  a->vf();
}

extern "C" __attribute__((noinline)) void nvcall(A *a) {
  // CHECK: stats.cpp:[[@LINE+1]] nvcall cfi-nvcall 51
  a->nvf();
}

extern "C" __attribute__((noinline)) A *dcast(A *a) {
  // CHECK: stats.cpp:[[@LINE+1]] dcast cfi-derived-cast 24
  return (A *)(ABase *)a;
}

extern "C" __attribute__((noinline)) A *ucast(A *a) {
  // CHECK: stats.cpp:[[@LINE+1]] ucast cfi-unrelated-cast 81
  return (A *)(char *)a;
}

extern "C" __attribute__((noinline)) void unreachable(A *a) {
  // CHECK-NOT: unreachable
  a->vf();
}

int main() {
  A a;
  for (unsigned i = 0; i != 37; ++i)
    vcall(&a);
  for (unsigned i = 0; i != 51; ++i)
    nvcall(&a);
  for (unsigned i = 0; i != 24; ++i)
    dcast(&a);
  for (unsigned i = 0; i != 81; ++i)
    ucast(&a);
  for (unsigned i = 0; i != 0; ++i)
    unreachable(&a);
}
<commit_msg>Fix stats.cpp test on 32-bit Windows.<commit_after>// RUN: %clangxx_cfi -g -fsanitize-stats -o %t %s
// RUN: env SANITIZER_STATS_PATH=%t.stats %t
// RUN: sanstats %t.stats | FileCheck %s

struct ABase {};

struct A : ABase {
  virtual void vf() {}
  void nvf() {}
};

extern "C" __attribute__((noinline)) void vcall(A *a) {
  // CHECK: stats.cpp:[[@LINE+1]] {{_?}}vcall cfi-vcall 37
  a->vf();
}

extern "C" __attribute__((noinline)) void nvcall(A *a) {
  // CHECK: stats.cpp:[[@LINE+1]] {{_?}}nvcall cfi-nvcall 51
  a->nvf();
}

extern "C" __attribute__((noinline)) A *dcast(A *a) {
  // CHECK: stats.cpp:[[@LINE+1]] {{_?}}dcast cfi-derived-cast 24
  return (A *)(ABase *)a;
}

extern "C" __attribute__((noinline)) A *ucast(A *a) {
  // CHECK: stats.cpp:[[@LINE+1]] {{_?}}ucast cfi-unrelated-cast 81
  return (A *)(char *)a;
}

extern "C" __attribute__((noinline)) void unreachable(A *a) {
  // CHECK-NOT: unreachable
  a->vf();
}

int main() {
  A a;
  for (unsigned i = 0; i != 37; ++i)
    vcall(&a);
  for (unsigned i = 0; i != 51; ++i)
    nvcall(&a);
  for (unsigned i = 0; i != 24; ++i)
    dcast(&a);
  for (unsigned i = 0; i != 81; ++i)
    ucast(&a);
  for (unsigned i = 0; i != 0; ++i)
    unreachable(&a);
}
<|endoftext|>


<commit_before>// RUN: %clangxx_cfi -g -fsanitize-stats -o %t %s
// RUN: env SANITIZER_STATS_PATH=%t.stats %t
// RUN: sanstats %t.stats | FileCheck %s

// FIXME: We currently emit the wrong debug info under devirtualization.
// UNSUPPORTED: devirt

struct ABase {};

struct A : ABase {
  virtual void vf() {}
  void nvf() {}
};

extern "C" __attribute__((noinline)) void vcall(A *a) {
  // CHECK: stats.cpp:[[@LINE+1]] {{_?}}vcall cfi-vcall 37
  a->vf();
}

extern "C" __attribute__((noinline)) void nvcall(A *a) {
  // CHECK: stats.cpp:[[@LINE+1]] {{_?}}nvcall cfi-nvcall 51
  a->nvf();
}

extern "C" __attribute__((noinline)) A *dcast(A *a) {
  // CHECK: stats.cpp:[[@LINE+1]] {{_?}}dcast cfi-derived-cast 24
  return (A *)(ABase *)a;
}

extern "C" __attribute__((noinline)) A *ucast(A *a) {
  // CHECK: stats.cpp:[[@LINE+1]] {{_?}}ucast cfi-unrelated-cast 81
  return (A *)(char *)a;
}

extern "C" __attribute__((noinline)) void unreachable(A *a) {
  // CHECK-NOT: unreachable
  a->vf();
}

int main() {
  A a;
  for (unsigned i = 0; i != 37; ++i)
    vcall(&a);
  for (unsigned i = 0; i != 51; ++i)
    nvcall(&a);
  for (unsigned i = 0; i != 24; ++i)
    dcast(&a);
  for (unsigned i = 0; i != 81; ++i)
    ucast(&a);
  for (unsigned i = 0; i != 0; ++i)
    unreachable(&a);
}
<commit_msg>XFAIL cfi/stats.cpp on Windows until we fix our DIA usage<commit_after>// RUN: %clangxx_cfi -g -fsanitize-stats -o %t %s
// RUN: env SANITIZER_STATS_PATH=%t.stats %t
// RUN: sanstats %t.stats | FileCheck %s

// FIXME: We currently emit the wrong debug info under devirtualization.
// UNSUPPORTED: devirt

// FIXME: Currently failing on Windows with a DIA error, so we don't get any
// symbols.
// XFAIL: win32

struct ABase {};

struct A : ABase {
  virtual void vf() {}
  void nvf() {}
};

extern "C" __attribute__((noinline)) void vcall(A *a) {
  // CHECK: stats.cpp:[[@LINE+1]] {{_?}}vcall cfi-vcall 37
  a->vf();
}

extern "C" __attribute__((noinline)) void nvcall(A *a) {
  // CHECK: stats.cpp:[[@LINE+1]] {{_?}}nvcall cfi-nvcall 51
  a->nvf();
}

extern "C" __attribute__((noinline)) A *dcast(A *a) {
  // CHECK: stats.cpp:[[@LINE+1]] {{_?}}dcast cfi-derived-cast 24
  return (A *)(ABase *)a;
}

extern "C" __attribute__((noinline)) A *ucast(A *a) {
  // CHECK: stats.cpp:[[@LINE+1]] {{_?}}ucast cfi-unrelated-cast 81
  return (A *)(char *)a;
}

extern "C" __attribute__((noinline)) void unreachable(A *a) {
  // CHECK-NOT: unreachable
  a->vf();
}

int main() {
  A a;
  for (unsigned i = 0; i != 37; ++i)
    vcall(&a);
  for (unsigned i = 0; i != 51; ++i)
    nvcall(&a);
  for (unsigned i = 0; i != 24; ++i)
    dcast(&a);
  for (unsigned i = 0; i != 81; ++i)
    ucast(&a);
  for (unsigned i = 0; i != 0; ++i)
    unreachable(&a);
}
<|endoftext|>


<commit_before><commit_msg>Set needsLayout on WebViewPlugin's container when initialized<commit_after><|endoftext|>


<commit_before>// Copyright 2015 FMAW

#include "./player_ai.h"

#include <cstdlib>
#include <vector>
#include <map>
#include <algorithm>

#include "./constants.h"
#include "./unit.h"
#include "./cell.h"
#include "./turnManager.h"

#include "./FMAW.h"

#include <algorithm>

PlayerAI::PlayerAI(Grid *grid, std::function<void(void)> callback) :
    grid(grid),
    onFinishTurnCallback(callback),
    seed(42) {}

PlayerAI::PlayerAI(Grid *grid, std::function<void(void)> call, PlayerID ID) :
    Player(ID),
    grid(grid),
    onFinishTurnCallback(call),
    seed(42) {}

void PlayerAI::startTurn() {

    // Prevent user from interacting with grid.
    this->grid->dequeueCallbacks();

    IndexPath previousPositionOfCursor = this->grid->getSelectedPath();

    // Now we have to make some decisions...
    // We will call the following callback once each 1.5s.
    this->unitNumber = 0;
    auto moveSomeUnit = [this, previousPositionOfCursor](int ID) {
        // Here we will store the units of this AI player and the path where they
        // are located.
        std::vector<Unit *> IAunits;
        std::vector<IndexPath> IApaths;
        std::vector<Unit *> playerUnits;
        std::vector<IndexPath> playerPaths;
        std::vector<IndexPath> chosenPaths;

        // We have to check the full grid to know where are our units.
        for (int row = 0; row < this->grid->numRows(); row++) {
            for (int col = 0; col < this->grid->numCols(); col++)  {
                IndexPath path = { row, col };
                Cell *c = this->grid->cellAtIndexPath(path);
                if (c->isOccupied()) {
                    Unit *u = c->getCharacter();
                    if (u->getOwner() == this->ID) {
                        IAunits.push_back(u);
                        IApaths.push_back(path);
                    } else {
                        playerUnits.push_back(u);
                        playerPaths.push_back(path);
                    }
                }
            }
        }

        std::map<IndexPath, std::vector<IndexPath>> IAUnitCanAttack;
        std::map<IndexPath, std::vector<IndexPath>> PlayerUnitCanBeAttackedBy;

        std::map<IndexPath, std::vector<IndexPath>> IAUnitsPossibleMovements;
        std::map<IndexPath, int> distanceToNearestEnemyUnit;

        // Compute which units can attack which ones.
        for (IndexPath p : IApaths) {
            this->grid->setPickedUpCell(p);
            Cell *c = this->grid->cellAtIndexPath(p);
            if (c->getCharacter()->hasAvailableActions()) {
                for (IndexPath t : playerPaths) {
                    if (grid->pickedUpUnitCanAttackCharacterAtCell(t)) {
                        IAUnitCanAttack[p].push_back(t);
                        PlayerUnitCanBeAttackedBy[t].push_back(p);
                    }
                }
            }
        }

        // Compute where can be moved IA units.
        for (IndexPath p : IApaths) {
            for (int row = 0; row < this->grid->numRows(); row++) {
                for (int col = 0; col < this->grid->numCols(); col++)  {
                    IndexPath t = { row, col };
                    if (grid->canMoveCharacterFromCellToCell(p, t)) {
                        IAUnitsPossibleMovements[p].push_back(t);
                    }
                }
            }
        }

        // Compute distance to nearest visible enemy.
        for (int row = 0; row < this->grid->numRows(); row++) {
            for (int col = 0; col < this->grid->numCols(); col++) {
                IndexPath f = { row, col };
                Cell *from = grid->cellAtIndexPath(f);
                distanceToNearestEnemyUnit[f] = COST_CELL_INFINITY;
                for (int t_row = 0; t_row < this->grid->numRows(); t_row++) {
                    for (int t_col = 0; t_col < this->grid->numCols(); t_col++) {
                        IndexPath t = { t_row, t_col };
                        Cell *to = this->grid->cellAtIndexPath(t);
                        int distance = abs(t.row - f.row) + abs(t.col - f.col);
                        if (to->isOccupied()) {
                            Unit *u = to->getCharacter();
                            if (this->grid->canSeeCharacterAtCell(t) &&
                                    u->getOwner() != this->ID) {
                                distanceToNearestEnemyUnit[f] = distance;
                            }
                        }
                    }
                }
            }
        }

        // Helper function to compute best cell to move.
        auto nearestEnemy = [&distanceToNearestEnemyUnit](
                                IndexPath i, IndexPath j
        ) -> bool {
            return distanceToNearestEnemyUnit[i] < distanceToNearestEnemyUnit[j];
        };

        bool canDoSomething = false;
        for (Unit *u : IAunits) {
            if (u->hasAvailableActions()) {
                canDoSomething = true;
            }
        }
        if (canDoSomething) {
            while (!IAunits[this->unitNumber]->hasAvailableActions()) {
                this->unitNumber++;
                this->unitNumber %= IAunits.size();
            }
            //------------------------------------------------------------------
            // Actual AI script.
            //------------------------------------------------------------------
            bool actionDone = false;
            IndexPath path = IApaths[this->unitNumber];
            Unit *unit = IAunits[this->unitNumber];
            this->grid->setPickedUpCell(path);

            int row = path.row;
            int col = path.col;

            FMAW::printf("Choosing action for unit %d at %d %d",
                         this->unitNumber, row, col);

            std::vector<IndexPath> shouldAttack;
            std::vector<IndexPath> attackable;

            // If I'm the only one who can attack, I'll do (random on tie).

            attackable = IAUnitCanAttack[path];
            for (IndexPath t : attackable) {
                if (PlayerUnitCanBeAttackedBy[t].size() == 1) {
                    shouldAttack.push_back(t);
                }
            }

            FMAW::printf("\tI'm the only one that can attack %d units",
                         attackable.size());

            // If I'm not the only one, I attack to a random (random on tie).
            if (shouldAttack.size() == 0) {
                attackable = IAUnitCanAttack[path];
                for (IndexPath t : attackable) {
                    shouldAttack.push_back(t);
                }

                FMAW::printf("\tMe and others can attack %d units",
                             attackable.size());
            }

            // I'll attack if I can.
            if (shouldAttack.size() > 0) {
                while (shouldAttack.size() > 0) {
                    int rand = rand_r(&(this->seed)) % shouldAttack.size();
                    IndexPath tg = shouldAttack[rand];
                    if (this->grid->pickedUpUnitCanAttackCharacterAtCell(tg)) {
                        FMAW::printf("\tWill attack unit at %d %d",
                                     tg.row, tg.col);
                        this->grid->attackCharacterAtCell(path, tg,
                                                          ATTACK_DURATION);
                        actionDone = true;
                        break;
                    } else {
                        FMAW::printf("\tCouldn't to attack unit at %d %d",
                                     tg.row, tg.col);
                        shouldAttack.erase(shouldAttack.begin() + rand);
                    }
                }
            }

            // If I can't attack, I'll move to the nearest enemy unit (random
            // on tie).
            if (!actionDone) {
                FMAW::printf("\tI couldn't attack any unit, so I'll move");
                std::vector<IndexPath> availableMovements;
                for (int r = 0; r < this->grid->numRows(); r++) {
                    for (int c = 0; c < this->grid->numCols(); c++) {
                        IndexPath t = { r, c };
                        if (this->grid->canMoveCharacterFromCellToCell(path, t)) {
                            availableMovements.push_back(t);
                        }
                    }
                }

                FMAW::printf("\tI can move to %d cells",
                             availableMovements.size());

                std::sort(availableMovements.begin(), availableMovements.end(),
                          nearestEnemy);

                if (availableMovements.size() > 0) {
                    IndexPath chosen = availableMovements[0];
                    FMAW::printf("\tI'll move to %d %d",
                                 chosen.row, chosen.col);
                    this->grid->moveCharacterFromCellToCell(path, chosen,
                                                            MOVEMENT_DURATION);
                    IApaths[this->unitNumber] = chosen;
                }
            }

            FMAW::printf("\t-------------------------------------------------");

            //------------------------------------------------------------------
            // End of AI script.
            //------------------------------------------------------------------
            this->grid->selectCellAtIndexPath(previousPositionOfCursor);
        } else {
            FMAW::printf("\tI've finished!");
            this->grid->enqueueCallbacks();
            FMAW::Timer::dequeue_function(ID);
            this->onFinishTurnCallback();
        }
    };
    FMAW::Timer::enqueue_function(moveSomeUnit, 1500, true);
}

void PlayerAI::print() {
    FMAW::printf("I'm an AI player with ID=%d", this->ID);
}
<commit_msg>Improved AI performance.<commit_after>// Copyright 2015 FMAW

#include "./player_ai.h"

#include <cstdlib>
#include <vector>
#include <map>
#include <algorithm>

#include "./constants.h"
#include "./unit.h"
#include "./cell.h"
#include "./turnManager.h"

#include "./FMAW.h"

#include <algorithm>

PlayerAI::PlayerAI(Grid *grid, std::function<void(void)> callback) :
    grid(grid),
    onFinishTurnCallback(callback),
    seed(42) {}

PlayerAI::PlayerAI(Grid *grid, std::function<void(void)> call, PlayerID ID) :
    Player(ID),
    grid(grid),
    onFinishTurnCallback(call),
    seed(42) {}

void PlayerAI::startTurn() {

    // Prevent user from interacting with grid.
    this->grid->dequeueCallbacks();

    IndexPath previousPositionOfCursor = this->grid->getSelectedPath();

    bool recompute = true;
    std::map<IndexPath, int> distanceToNearestEnemyUnit;

    // Helper function to compute best cell to move.
    auto nearestEnemy = [&distanceToNearestEnemyUnit](IndexPath i, IndexPath j)
    -> bool {
        return distanceToNearestEnemyUnit[i] < distanceToNearestEnemyUnit[j];
    };

    // Now we have to make some decisions...
    // We will call the following callback once each 1.5s.
    this->unitNumber = 0;
    auto moveSomeUnit = [this, previousPositionOfCursor, &recompute,
    &distanceToNearestEnemyUnit, nearestEnemy](int ID) {
        FMAW::printf("Computing AI data...");
        // Here we will store the units of this AI player and the path where
        // they are located.
        std::vector<Unit *> IAunits;
        std::vector<IndexPath> IApaths;
        std::vector<Unit *> playerUnits;
        std::vector<IndexPath> playerPaths;
        std::vector<IndexPath> chosenPaths;

        // We have to check the full grid to know where are our units.
        for (int row = 0; row < this->grid->numRows(); row++) {
            for (int col = 0; col < this->grid->numCols(); col++)  {
                IndexPath path = { row, col };
                Cell *c = this->grid->cellAtIndexPath(path);
                if (c->isOccupied()) {
                    Unit *u = c->getCharacter();
                    if (u->getOwner() == this->ID) {
                        IAunits.push_back(u);
                        IApaths.push_back(path);
                    } else {
                        playerUnits.push_back(u);
                        playerPaths.push_back(path);
                    }
                }
            }
        }

        FMAW::printf("\tReady units");

        std::map<IndexPath, std::vector<IndexPath>> IAUnitCanAttack;
        std::map<IndexPath, std::vector<IndexPath>> PlayerUnitCanBeAttackedBy;

        // Compute which units can attack which ones.
        for (IndexPath p : IApaths) {
            this->grid->setPickedUpCell(p);
            Cell *c = this->grid->cellAtIndexPath(p);
            if (c->getCharacter()->hasAvailableActions()) {
                for (IndexPath t : playerPaths) {
                    if (grid->pickedUpUnitCanAttackCharacterAtCell(t)) {
                        IAUnitCanAttack[p].push_back(t);
                        PlayerUnitCanBeAttackedBy[t].push_back(p);
                    }
                }
            }
        }

        FMAW::printf("\tReady attacks");

        if (recompute) {
            // Compute distance to nearest visible enemy.
            for (int row = 0; row < this->grid->numRows(); row++) {
                for (int col = 0; col < this->grid->numCols(); col++) {
                    IndexPath f = { row, col };
                    Cell *from = grid->cellAtIndexPath(f);
                    distanceToNearestEnemyUnit[f] = COST_CELL_INFINITY;
                    for (int tr = 0; tr < this->grid->numRows(); tr++) {
                        for (int tc = 0; tc < this->grid->numCols(); tc++) {
                            IndexPath t = { tr, tc };
                            Cell *to = this->grid->cellAtIndexPath(t);
                            int distance = abs(t.row - f.row) +
                                           abs(t.col - f.col);
                            if (to->isOccupied()) {
                                Unit *u = to->getCharacter();
                                if (this->grid->canSeeCharacterAtCell(t) &&
                                        u->getOwner() != this->ID) {
                                    distanceToNearestEnemyUnit[f] = distance;
                                }
                            }
                        }
                    }
                }
            }
            recompute = false;
        }

        FMAW::printf("\tReady distances");

        bool canDoSomething = false;
        for (Unit *u : IAunits) {
            if (u->hasAvailableActions()) {
                canDoSomething = true;
            }
        }
        if (canDoSomething) {
            while (!IAunits[this->unitNumber]->hasAvailableActions()) {
                this->unitNumber++;
                this->unitNumber %= IAunits.size();
            }
            //------------------------------------------------------------------
            // Actual AI script.
            //------------------------------------------------------------------
            bool actionDone = false;
            IndexPath path = IApaths[this->unitNumber];
            Unit *unit = IAunits[this->unitNumber];
            this->grid->setPickedUpCell(path);

            int row = path.row;
            int col = path.col;

            FMAW::printf("Choosing action for unit %d at %d %d",
                         this->unitNumber, row, col);

            std::vector<IndexPath> shouldAttack;
            std::vector<IndexPath> attackable;

            // If I'm the only one who can attack, I'll do (random on tie).

            attackable = IAUnitCanAttack[path];
            for (IndexPath t : attackable) {
                if (PlayerUnitCanBeAttackedBy[t].size() == 1) {
                    shouldAttack.push_back(t);
                }
            }

            FMAW::printf("\tI'm the only one that can attack %d units",
                         attackable.size());

            // If I'm not the only one, I attack to a random (random on tie).
            if (shouldAttack.size() == 0) {
                attackable = IAUnitCanAttack[path];
                for (IndexPath t : attackable) {
                    shouldAttack.push_back(t);
                }

                FMAW::printf("\tMe and others can attack %d units",
                             attackable.size());
            }

            // I'll attack if I can.
            if (shouldAttack.size() > 0) {
                while (shouldAttack.size() > 0) {
                    int rand = rand_r(&(this->seed)) % shouldAttack.size();
                    IndexPath tg = shouldAttack[rand];
                    if (this->grid->pickedUpUnitCanAttackCharacterAtCell(tg)) {
                        FMAW::printf("\tWill attack unit at %d %d",
                                     tg.row, tg.col);
                        bool kill = this->grid->attackCharacterAtCell(
                                        path, tg, ATTACK_DURATION);
                        if (kill) {
                            recompute = true;
                        }
                        actionDone = true;
                        break;
                    } else {
                        FMAW::printf("\tCouldn't to attack unit at %d %d",
                                     tg.row, tg.col);
                        shouldAttack.erase(shouldAttack.begin() + rand);
                    }
                }
            }

            // If I can't attack, I'll move to the nearest enemy unit (random
            // on tie).
            if (!actionDone) {
                FMAW::printf("\tI couldn't attack any unit, so I'll move");
                std::vector<IndexPath> availableMovements;
                for (int r = 0; r < this->grid->numRows(); r++) {
                    for (int c = 0; c < this->grid->numCols(); c++) {
                        IndexPath t = { r, c };
                        if (this->grid->canMoveCharacterFromCellToCell(path, t)) {
                            availableMovements.push_back(t);
                        }
                    }
                }

                FMAW::printf("\tI can move to %d cells",
                             availableMovements.size());

                std::sort(availableMovements.begin(), availableMovements.end(),
                          nearestEnemy);

                if (availableMovements.size() > 0) {
                    IndexPath chosen = availableMovements[0];
                    FMAW::printf("\tI'll move to %d %d",
                                 chosen.row, chosen.col);
                    this->grid->moveCharacterFromCellToCell(path, chosen,
                                                            MOVEMENT_DURATION);
                    IApaths[this->unitNumber] = chosen;
                }
            }

            FMAW::printf("\t-------------------------------------------------");

            //------------------------------------------------------------------
            // End of AI script.
            //------------------------------------------------------------------
            this->grid->selectCellAtIndexPath(previousPositionOfCursor);
        } else {
            FMAW::printf("\tI've finished!");
            this->grid->enqueueCallbacks();
            FMAW::Timer::dequeue_function(ID);
            this->onFinishTurnCallback();
        }
    };
    FMAW::Timer::enqueue_function(moveSomeUnit, 1500, true);
}

void PlayerAI::print() {
    FMAW::printf("I'm an AI player with ID=%d", this->ID);
}
<|endoftext|>


<commit_before>#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>

void eratosthenes(int max, std::vector<bool> &val)
{
	val.resize(max, true);
	val[0]=val[1]=false;
	int n=sqrt(val.size());
	for(int i{2};i<=n;++i)
		if(val[i])
			for(int j=i*i+i;j<val.size();j+=i)
				val[j]=false;
}

int main()
{
	std::vector<bool> primes;
	eratosthenes(972, primes);
	int16_t num_primes{0}, sa, sb, n;

	for(int16_t a{-999};a<1000;a+=2)
	{
		for(int16_t b{3};b<998;b+=2)
		{
			if(!primes[b])
				continue;
			for(n=0;primes[std::abs((n*n)+(a*n)+b)];++n);
			if(n>num_primes)
			{
				sa=a;
				sb=b;
				num_primes=n;
			}
		}
	}
	std::cout<<sa*sb<<std::endl;
}
<commit_msg>More optimizations<commit_after>#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>

void eratosthenes(int max, std::vector<bool> &val)
{
	val.resize(max, true);
	val[0]=val[1]=false;
	int n=sqrt(val.size());
	for(int i{2};i<=n;++i)
		if(val[i])
			for(int j=i*i+i;j<val.size();j+=i)
				val[j]=false;
}

int main()
{
	std::vector<bool> primes;
	eratosthenes(972, primes);
	int16_t num_primes{0}, sa, sb, n;

	for(int16_t a{-999};a<999;a+=2)
	{
		for(int16_t b=(a>3)?a:3;b<998;b+=2)
		{
			if(!primes[b])
				continue;
			for(n=0;primes[std::abs((n*n)+(a*n)+b)];++n);
			if(n>num_primes)
			{
				sa=a;
				sb=b;
				num_primes=n;
			}
		}
	}
	std::cout<<sa*sb<<std::endl;
}
<|endoftext|>