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

#include <limits.h>
#include <string.h>

#include <iostream>
#include <sstream>

#include "Host.h"
#include "NebulaLog.h"

/* ************************************************************************ */
/* Host :: Constructor/Destructor                                           */
/* ************************************************************************ */

Host::Host(
    int     id,
    string _hostname,
    string _im_mad_name,
    string _vmm_mad_name,
    string _tm_mad_name):
        PoolObjectSQL(id),
        hostname(_hostname),
        state(INIT),
        im_mad_name(_im_mad_name),
        vmm_mad_name(_vmm_mad_name),
        tm_mad_name(_tm_mad_name),
        last_monitored(time(0)),
        host_template(id)
        {};

Host::~Host(){};

/* ************************************************************************ */
/* Host :: Database Access Functions                                        */
/* ************************************************************************ */

const char * Host::table = "host_pool";

const char * Host::db_names = "(oid,host_name,state,im_mad,vm_mad,"
                              "tm_mad,last_mon_time)";

const char * Host::db_bootstrap = "CREATE TABLE host_pool ("
    "oid INTEGER PRIMARY KEY,host_name VARCHAR(512), state INTEGER,"
    "im_mad VARCHAR(256),vm_mad VARCHAR(256),tm_mad VARCHAR(256),"
    "last_mon_time INTEGER, UNIQUE(host_name, im_mad, vm_mad, tm_mad) )";

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::select_cb(void * nil, int num, char **values, char ** names)
{
    if ((!values[OID]) ||
        (!values[HOST_NAME]) ||
        (!values[STATE]) ||
        (!values[IM_MAD]) ||
        (!values[VM_MAD]) ||
        (!values[TM_MAD]) ||
        (!values[LAST_MON_TIME]) ||
        (num != LIMIT ))
    {
        return -1;
    }

    oid      = atoi(values[OID]);
    hostname = values[HOST_NAME];
    state    = static_cast<HostState>(atoi(values[STATE]));

    im_mad_name  = values[IM_MAD];
    vmm_mad_name = values[VM_MAD];
    tm_mad_name  = values[TM_MAD];

    last_monitored = static_cast<time_t>(atoi(values[LAST_MON_TIME]));

    host_template.id = oid;
    host_share.hsid  = oid;

    return 0;
}

/* ------------------------------------------------------------------------ */

int Host::select(SqlDB *db)
{
    ostringstream   oss;
    int             rc;
    int             boid;

    set_callback(static_cast<Callbackable::Callback>(&Host::select_cb));

    oss << "SELECT * FROM " << table << " WHERE oid = " << oid;

    boid = oid;
    oid  = -1;

    rc = db->exec(oss, this);

    if ((rc != 0) || (oid != boid ))
    {
        return -1;
    }

    // Get the template

    rc = host_template.select(db);

    if ( rc != 0 )
    {
        return -1;
    }

    // Select the host shares from the DB

    rc = host_share.select(db);

    if ( rc != 0 )
    {
        return rc;
    }

    return 0;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::insert(SqlDB *db)
{
    int rc;
    map<int,HostShare *>::iterator iter;

    // Set up the template ID, to insert it
    if ( host_template.id == -1 )
    {
        host_template.id = oid;
    }

    // Set up the share ID, to insert it
    if ( host_share.hsid == -1 )
    {
        host_share.hsid = oid;
    }

    // Update the Template
    rc = host_template.insert(db);

    if ( rc != 0 )
    {
        return rc;
    }

    // Update the HostShare
    rc = host_share.insert(db);

    if ( rc != 0 )
    {
        host_template.drop(db);
        return rc;
    }

    //Insert the Host
    rc = insert_replace(db, false);

    if ( rc != 0 )
    {
        host_template.drop(db);
        host_share.drop(db);

        return rc;
    }

    return 0;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::update(SqlDB *db)
{
    int    rc;

    // Update the Template
    rc = host_template.update(db);

    if ( rc != 0 )
    {
        return rc;
    }

    // Update the HostShare
    rc = host_share.update(db);

    if ( rc != 0 )
    {
        return rc;
    }

    rc = insert_replace(db, true);

    if ( rc != 0 )
    {
        return rc;
    }

    return 0;

}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::insert_replace(SqlDB *db, bool replace)
{
    ostringstream   oss;

    int    rc;

    char * sql_hostname;
    char * sql_im_mad_name;
    char * sql_tm_mad_name;
    char * sql_vmm_mad_name;

   // Update the Host

    sql_hostname = db->escape_str(hostname.c_str());

    if ( sql_hostname == 0 )
    {
        goto error_hostname;
    }

    sql_im_mad_name = db->escape_str(im_mad_name.c_str());

    if ( sql_im_mad_name == 0 )
    {
        goto error_im;
    }

    sql_tm_mad_name = db->escape_str(tm_mad_name.c_str());

    if ( sql_tm_mad_name == 0 )
    {
        goto error_tm;
    }

    sql_vmm_mad_name = db->escape_str(vmm_mad_name.c_str());

    if ( sql_vmm_mad_name == 0 )
    {
        goto error_vmm;
    }

    if(replace)
    {
        oss << "REPLACE";
    }
    else
    {
        oss << "INSERT";
    }

    // Construct the SQL statement to Insert or Replace

    oss <<" INTO "<< table <<" "<< db_names <<" VALUES ("
        << oid << ","
        << "'" << sql_hostname << "',"
        << state << ","
        << "'" << sql_im_mad_name << "',"
        << "'" << sql_vmm_mad_name << "',"
        << "'" << sql_tm_mad_name << "',"
        << last_monitored << ")";

    rc = db->exec(oss);

    db->free_str(sql_hostname);
    db->free_str(sql_im_mad_name);
    db->free_str(sql_tm_mad_name);
    db->free_str(sql_vmm_mad_name);

    return rc;

error_vmm:
    db->free_str(sql_tm_mad_name);
error_tm:
    db->free_str(sql_im_mad_name);
error_im:
    db->free_str(sql_hostname);
error_hostname:
    return -1;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::dump(ostringstream& oss, int num, char **values, char **names)
{
    if ((!values[OID]) ||
        (!values[HOST_NAME]) ||
        (!values[STATE]) ||
        (!values[IM_MAD]) ||
        (!values[VM_MAD]) ||
        (!values[TM_MAD]) ||
        (!values[LAST_MON_TIME]) ||
        (num != LIMIT + HostShare::LIMIT ))
    {
        return -1;
    }

    oss <<
        "<HOST>" <<
            "<ID>"           << values[OID]          <<"</ID>"           <<
            "<NAME>"         << values[HOST_NAME]    <<"</NAME>"         <<
            "<STATE>"        << values[STATE]        <<"</STATE>"        <<
            "<IM_MAD>"       << values[IM_MAD]       <<"</IM_MAD>"       <<
            "<VM_MAD>"       << values[VM_MAD]       <<"</VM_MAD>"       <<
            "<TM_MAD>"       << values[TM_MAD]       <<"</TM_MAD>"       <<
            "<LAST_MON_TIME>"<< values[LAST_MON_TIME]<<"</LAST_MON_TIME>";

    HostShare::dump(oss,num - LIMIT, values + LIMIT, names + LIMIT);

    oss << "</HOST>";

    return 0;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::drop(SqlDB * db)
{
    ostringstream oss;
    int rc;

    host_template.drop(db);

    host_share.drop(db);

    oss << "DELETE FROM " << table << " WHERE oid=" << oid;

    rc = db->exec(oss);

    if ( rc == 0 )
    {
        set_valid(false);
    }

    return rc;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::update_info(string &parse_str)
{
    char *  error_msg;
    int     rc;

    rc = host_template.parse(parse_str, &error_msg);

    if ( rc != 0 )
    {
        NebulaLog::log("ONE", Log::ERROR, error_msg);

        free(error_msg);
        return -1;
    }

    get_template_attribute("TOTALCPU",host_share.max_cpu);
    get_template_attribute("TOTALMEMORY",host_share.max_mem);

    get_template_attribute("FREECPU",host_share.free_cpu);
    get_template_attribute("FREEMEMORY",host_share.free_mem);

    get_template_attribute("USEDCPU",host_share.used_cpu);
    get_template_attribute("USEDMEMORY",host_share.used_mem);

    return 0;
}

/* ************************************************************************ */
/* Host :: Misc                                                             */
/* ************************************************************************ */

ostream& operator<<(ostream& os, Host& host)
{
	string host_str;

	os << host.to_xml(host_str);

    return os;
};

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

string& Host::to_xml(string& xml) const
{
    string template_xml;
	string share_xml;
    ostringstream   oss;

    oss <<
    "<HOST>"
       "<ID>"            << oid       	   << "</ID>"            <<
       "<NAME>"          << hostname 	   << "</NAME>"          <<
       "<STATE>"         << state          << "</STATE>"         <<
       "<IM_MAD>"        << im_mad_name    << "</IM_MAD>"        <<
       "<VM_MAD>"        << vmm_mad_name   << "</VM_MAD>"        <<
       "<TM_MAD>"        << tm_mad_name    << "</TM_MAD>"        <<
       "<LAST_MON_TIME>" << last_monitored << "</LAST_MON_TIME>" <<
 	   host_share.to_xml(share_xml)  <<
       host_template.to_xml(template_xml) <<
	"</HOST>";

    xml = oss.str();

    return xml;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

string& Host::to_str(string& str) const
{
    string template_str;
	string share_str;

    ostringstream   os;

    os <<
		"ID      =  "  << oid            << endl <<
    	"NAME = "      << hostname       << endl <<
    	"STATE    = "  << state          << endl <<
    	"IM MAD   = "  << im_mad_name    << endl <<
    	"VMM MAD  = "  << vmm_mad_name   << endl <<
    	"TM MAD   = "  << tm_mad_name    << endl <<
    	"LAST_MON = "  << last_monitored << endl <<
        "ATTRIBUTES"   << endl << host_template.to_str(template_str) << endl <<
        "HOST SHARES"  << endl << host_share.to_str(share_str) <<endl;

	str = os.str();

	return str;
}

/* ************************************************************************ */
/* Host :: Parse functions to compute rank and evaluate requirements        */
/* ************************************************************************ */

pthread_mutex_t Host::lex_mutex = PTHREAD_MUTEX_INITIALIZER;

extern "C"
{
    typedef struct yy_buffer_state * YY_BUFFER_STATE;

    int host_requirements_parse(Host * host, bool& result, char ** errmsg);

    int host_rank_parse(Host * host, int& result, char ** errmsg);

    int host_lex_destroy();

    YY_BUFFER_STATE host__scan_string(const char * str);

    void host__delete_buffer(YY_BUFFER_STATE);
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::match(const string& requirements, bool& result, char **errmsg)
{
    YY_BUFFER_STATE     str_buffer = 0;
    const char *        str;
    int                 rc;

    pthread_mutex_lock(&lex_mutex);

    *errmsg = 0;

    str = requirements.c_str();

    str_buffer = host__scan_string(str);

    if (str_buffer == 0)
    {
        goto error_yy;
    }

    rc = host_requirements_parse(this,result,errmsg);

    host__delete_buffer(str_buffer);

    host_lex_destroy();

    pthread_mutex_unlock(&lex_mutex);

    return rc;

error_yy:

    *errmsg=strdup("Error setting scan buffer");

    pthread_mutex_unlock(&lex_mutex);

    return -1;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::rank(const string& rank, int& result, char **errmsg)
{
    YY_BUFFER_STATE     str_buffer = 0;
    const char *        str;
    int                 rc;

    pthread_mutex_lock(&lex_mutex);

    *errmsg = 0;

    str = rank.c_str();

    str_buffer = host__scan_string(str);

    if (str_buffer == 0)
    {
        goto error_yy;
    }

    rc = host_rank_parse(this,result,errmsg);

    host__delete_buffer(str_buffer);

    host_lex_destroy();

    pthread_mutex_unlock(&lex_mutex);

    return rc;

error_yy:

    *errmsg=strdup("Error setting scan buffer");

    pthread_mutex_unlock(&lex_mutex);

    return -1;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
<commit_msg>feature-#206: Rolling back augmented mad name size, mysql index cannot be over 1000 bytes<commit_after>/* ------------------------------------------------------------------------ */
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org)           */
/*                                                                          */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may  */
/* not use this file except in compliance with the License. You may obtain  */
/* a copy of the License at                                                 */
/*                                                                          */
/* http://www.apache.org/licenses/LICENSE-2.0                               */
/*                                                                          */
/* Unless required by applicable law or agreed to in writing, software      */
/* distributed under the License is distributed on an "AS IS" BASIS,        */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and      */
/* limitations under the License.                                           */
/* ------------------------------------------------------------------------ */

#include <limits.h>
#include <string.h>

#include <iostream>
#include <sstream>

#include "Host.h"
#include "NebulaLog.h"

/* ************************************************************************ */
/* Host :: Constructor/Destructor                                           */
/* ************************************************************************ */

Host::Host(
    int     id,
    string _hostname,
    string _im_mad_name,
    string _vmm_mad_name,
    string _tm_mad_name):
        PoolObjectSQL(id),
        hostname(_hostname),
        state(INIT),
        im_mad_name(_im_mad_name),
        vmm_mad_name(_vmm_mad_name),
        tm_mad_name(_tm_mad_name),
        last_monitored(time(0)),
        host_template(id)
        {};

Host::~Host(){};

/* ************************************************************************ */
/* Host :: Database Access Functions                                        */
/* ************************************************************************ */

const char * Host::table = "host_pool";

const char * Host::db_names = "(oid,host_name,state,im_mad,vm_mad,"
                              "tm_mad,last_mon_time)";

const char * Host::db_bootstrap = "CREATE TABLE host_pool ("
    "oid INTEGER PRIMARY KEY,host_name VARCHAR(512), state INTEGER,"
    "im_mad VARCHAR(128),vm_mad VARCHAR(128),tm_mad VARCHAR(128),"
    "last_mon_time INTEGER, UNIQUE(host_name, im_mad, vm_mad, tm_mad) )";

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::select_cb(void * nil, int num, char **values, char ** names)
{
    if ((!values[OID]) ||
        (!values[HOST_NAME]) ||
        (!values[STATE]) ||
        (!values[IM_MAD]) ||
        (!values[VM_MAD]) ||
        (!values[TM_MAD]) ||
        (!values[LAST_MON_TIME]) ||
        (num != LIMIT ))
    {
        return -1;
    }

    oid      = atoi(values[OID]);
    hostname = values[HOST_NAME];
    state    = static_cast<HostState>(atoi(values[STATE]));

    im_mad_name  = values[IM_MAD];
    vmm_mad_name = values[VM_MAD];
    tm_mad_name  = values[TM_MAD];

    last_monitored = static_cast<time_t>(atoi(values[LAST_MON_TIME]));

    host_template.id = oid;
    host_share.hsid  = oid;

    return 0;
}

/* ------------------------------------------------------------------------ */

int Host::select(SqlDB *db)
{
    ostringstream   oss;
    int             rc;
    int             boid;

    set_callback(static_cast<Callbackable::Callback>(&Host::select_cb));

    oss << "SELECT * FROM " << table << " WHERE oid = " << oid;

    boid = oid;
    oid  = -1;

    rc = db->exec(oss, this);

    if ((rc != 0) || (oid != boid ))
    {
        return -1;
    }

    // Get the template

    rc = host_template.select(db);

    if ( rc != 0 )
    {
        return -1;
    }

    // Select the host shares from the DB

    rc = host_share.select(db);

    if ( rc != 0 )
    {
        return rc;
    }

    return 0;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::insert(SqlDB *db)
{
    int rc;
    map<int,HostShare *>::iterator iter;

    // Set up the template ID, to insert it
    if ( host_template.id == -1 )
    {
        host_template.id = oid;
    }

    // Set up the share ID, to insert it
    if ( host_share.hsid == -1 )
    {
        host_share.hsid = oid;
    }

    // Update the Template
    rc = host_template.insert(db);

    if ( rc != 0 )
    {
        return rc;
    }

    // Update the HostShare
    rc = host_share.insert(db);

    if ( rc != 0 )
    {
        host_template.drop(db);
        return rc;
    }

    //Insert the Host
    rc = insert_replace(db, false);

    if ( rc != 0 )
    {
        host_template.drop(db);
        host_share.drop(db);

        return rc;
    }

    return 0;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::update(SqlDB *db)
{
    int    rc;

    // Update the Template
    rc = host_template.update(db);

    if ( rc != 0 )
    {
        return rc;
    }

    // Update the HostShare
    rc = host_share.update(db);

    if ( rc != 0 )
    {
        return rc;
    }

    rc = insert_replace(db, true);

    if ( rc != 0 )
    {
        return rc;
    }

    return 0;

}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::insert_replace(SqlDB *db, bool replace)
{
    ostringstream   oss;

    int    rc;

    char * sql_hostname;
    char * sql_im_mad_name;
    char * sql_tm_mad_name;
    char * sql_vmm_mad_name;

   // Update the Host

    sql_hostname = db->escape_str(hostname.c_str());

    if ( sql_hostname == 0 )
    {
        goto error_hostname;
    }

    sql_im_mad_name = db->escape_str(im_mad_name.c_str());

    if ( sql_im_mad_name == 0 )
    {
        goto error_im;
    }

    sql_tm_mad_name = db->escape_str(tm_mad_name.c_str());

    if ( sql_tm_mad_name == 0 )
    {
        goto error_tm;
    }

    sql_vmm_mad_name = db->escape_str(vmm_mad_name.c_str());

    if ( sql_vmm_mad_name == 0 )
    {
        goto error_vmm;
    }

    if(replace)
    {
        oss << "REPLACE";
    }
    else
    {
        oss << "INSERT";
    }

    // Construct the SQL statement to Insert or Replace

    oss <<" INTO "<< table <<" "<< db_names <<" VALUES ("
        << oid << ","
        << "'" << sql_hostname << "',"
        << state << ","
        << "'" << sql_im_mad_name << "',"
        << "'" << sql_vmm_mad_name << "',"
        << "'" << sql_tm_mad_name << "',"
        << last_monitored << ")";

    rc = db->exec(oss);

    db->free_str(sql_hostname);
    db->free_str(sql_im_mad_name);
    db->free_str(sql_tm_mad_name);
    db->free_str(sql_vmm_mad_name);

    return rc;

error_vmm:
    db->free_str(sql_tm_mad_name);
error_tm:
    db->free_str(sql_im_mad_name);
error_im:
    db->free_str(sql_hostname);
error_hostname:
    return -1;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::dump(ostringstream& oss, int num, char **values, char **names)
{
    if ((!values[OID]) ||
        (!values[HOST_NAME]) ||
        (!values[STATE]) ||
        (!values[IM_MAD]) ||
        (!values[VM_MAD]) ||
        (!values[TM_MAD]) ||
        (!values[LAST_MON_TIME]) ||
        (num != LIMIT + HostShare::LIMIT ))
    {
        return -1;
    }

    oss <<
        "<HOST>" <<
            "<ID>"           << values[OID]          <<"</ID>"           <<
            "<NAME>"         << values[HOST_NAME]    <<"</NAME>"         <<
            "<STATE>"        << values[STATE]        <<"</STATE>"        <<
            "<IM_MAD>"       << values[IM_MAD]       <<"</IM_MAD>"       <<
            "<VM_MAD>"       << values[VM_MAD]       <<"</VM_MAD>"       <<
            "<TM_MAD>"       << values[TM_MAD]       <<"</TM_MAD>"       <<
            "<LAST_MON_TIME>"<< values[LAST_MON_TIME]<<"</LAST_MON_TIME>";

    HostShare::dump(oss,num - LIMIT, values + LIMIT, names + LIMIT);

    oss << "</HOST>";

    return 0;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::drop(SqlDB * db)
{
    ostringstream oss;
    int rc;

    host_template.drop(db);

    host_share.drop(db);

    oss << "DELETE FROM " << table << " WHERE oid=" << oid;

    rc = db->exec(oss);

    if ( rc == 0 )
    {
        set_valid(false);
    }

    return rc;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::update_info(string &parse_str)
{
    char *  error_msg;
    int     rc;

    rc = host_template.parse(parse_str, &error_msg);

    if ( rc != 0 )
    {
        NebulaLog::log("ONE", Log::ERROR, error_msg);

        free(error_msg);
        return -1;
    }

    get_template_attribute("TOTALCPU",host_share.max_cpu);
    get_template_attribute("TOTALMEMORY",host_share.max_mem);

    get_template_attribute("FREECPU",host_share.free_cpu);
    get_template_attribute("FREEMEMORY",host_share.free_mem);

    get_template_attribute("USEDCPU",host_share.used_cpu);
    get_template_attribute("USEDMEMORY",host_share.used_mem);

    return 0;
}

/* ************************************************************************ */
/* Host :: Misc                                                             */
/* ************************************************************************ */

ostream& operator<<(ostream& os, Host& host)
{
	string host_str;

	os << host.to_xml(host_str);

    return os;
};

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

string& Host::to_xml(string& xml) const
{
    string template_xml;
	string share_xml;
    ostringstream   oss;

    oss <<
    "<HOST>"
       "<ID>"            << oid       	   << "</ID>"            <<
       "<NAME>"          << hostname 	   << "</NAME>"          <<
       "<STATE>"         << state          << "</STATE>"         <<
       "<IM_MAD>"        << im_mad_name    << "</IM_MAD>"        <<
       "<VM_MAD>"        << vmm_mad_name   << "</VM_MAD>"        <<
       "<TM_MAD>"        << tm_mad_name    << "</TM_MAD>"        <<
       "<LAST_MON_TIME>" << last_monitored << "</LAST_MON_TIME>" <<
 	   host_share.to_xml(share_xml)  <<
       host_template.to_xml(template_xml) <<
	"</HOST>";

    xml = oss.str();

    return xml;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

string& Host::to_str(string& str) const
{
    string template_str;
	string share_str;

    ostringstream   os;

    os <<
		"ID      =  "  << oid            << endl <<
    	"NAME = "      << hostname       << endl <<
    	"STATE    = "  << state          << endl <<
    	"IM MAD   = "  << im_mad_name    << endl <<
    	"VMM MAD  = "  << vmm_mad_name   << endl <<
    	"TM MAD   = "  << tm_mad_name    << endl <<
    	"LAST_MON = "  << last_monitored << endl <<
        "ATTRIBUTES"   << endl << host_template.to_str(template_str) << endl <<
        "HOST SHARES"  << endl << host_share.to_str(share_str) <<endl;

	str = os.str();

	return str;
}

/* ************************************************************************ */
/* Host :: Parse functions to compute rank and evaluate requirements        */
/* ************************************************************************ */

pthread_mutex_t Host::lex_mutex = PTHREAD_MUTEX_INITIALIZER;

extern "C"
{
    typedef struct yy_buffer_state * YY_BUFFER_STATE;

    int host_requirements_parse(Host * host, bool& result, char ** errmsg);

    int host_rank_parse(Host * host, int& result, char ** errmsg);

    int host_lex_destroy();

    YY_BUFFER_STATE host__scan_string(const char * str);

    void host__delete_buffer(YY_BUFFER_STATE);
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::match(const string& requirements, bool& result, char **errmsg)
{
    YY_BUFFER_STATE     str_buffer = 0;
    const char *        str;
    int                 rc;

    pthread_mutex_lock(&lex_mutex);

    *errmsg = 0;

    str = requirements.c_str();

    str_buffer = host__scan_string(str);

    if (str_buffer == 0)
    {
        goto error_yy;
    }

    rc = host_requirements_parse(this,result,errmsg);

    host__delete_buffer(str_buffer);

    host_lex_destroy();

    pthread_mutex_unlock(&lex_mutex);

    return rc;

error_yy:

    *errmsg=strdup("Error setting scan buffer");

    pthread_mutex_unlock(&lex_mutex);

    return -1;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

int Host::rank(const string& rank, int& result, char **errmsg)
{
    YY_BUFFER_STATE     str_buffer = 0;
    const char *        str;
    int                 rc;

    pthread_mutex_lock(&lex_mutex);

    *errmsg = 0;

    str = rank.c_str();

    str_buffer = host__scan_string(str);

    if (str_buffer == 0)
    {
        goto error_yy;
    }

    rc = host_rank_parse(this,result,errmsg);

    host__delete_buffer(str_buffer);

    host_lex_destroy();

    pthread_mutex_unlock(&lex_mutex);

    return rc;

error_yy:

    *errmsg=strdup("Error setting scan buffer");

    pthread_mutex_unlock(&lex_mutex);

    return -1;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
<|endoftext|>


<commit_before>// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/browser/javascript_environment.h"

#include <string>

#include "atom/browser/microtasks_runner.h"
#include "atom/common/node_includes.h"
#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
#include "base/task/task_scheduler/initialization_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/public/common/content_switches.h"
#include "gin/array_buffer.h"
#include "gin/v8_initializer.h"
#include "tracing/trace_event.h"

namespace atom {

JavascriptEnvironment::JavascriptEnvironment(uv_loop_t* event_loop)
    : isolate_(Initialize(event_loop)),
      isolate_holder_(base::ThreadTaskRunnerHandle::Get(),
                      gin::IsolateHolder::kSingleThread,
                      gin::IsolateHolder::kAllowAtomicsWait,
                      gin::IsolateHolder::IsolateType::kUtility,
                      gin::IsolateHolder::IsolateCreationMode::kNormal,
                      isolate_),
      isolate_scope_(isolate_),
      locker_(isolate_),
      handle_scope_(isolate_),
      context_(isolate_, v8::Context::New(isolate_)),
      context_scope_(v8::Local<v8::Context>::New(isolate_, context_)) {}

JavascriptEnvironment::~JavascriptEnvironment() = default;

v8::Isolate* JavascriptEnvironment::Initialize(uv_loop_t* event_loop) {
  auto* cmd = base::CommandLine::ForCurrentProcess();

  // --js-flags.
  std::string js_flags = cmd->GetSwitchValueASCII(switches::kJavaScriptFlags);
  if (!js_flags.empty())
    v8::V8::SetFlagsFromString(js_flags.c_str(), js_flags.size());

  // The V8Platform of gin relies on Chromium's task schedule, which has not
  // been started at this point, so we have to rely on Node's V8Platform.
  auto* tracing_agent = node::CreateAgent();
  auto* tracing_controller = tracing_agent->GetTracingController();
  node::tracing::TraceEventHelper::SetAgent(tracing_agent);
  platform_ = node::CreatePlatform(
      base::RecommendedMaxNumberOfThreadsInPool(3, 8, 0.1, 0),
      tracing_controller);

  v8::V8::InitializePlatform(platform_);
  gin::IsolateHolder::Initialize(gin::IsolateHolder::kNonStrictMode,
                                 gin::ArrayBufferAllocator::SharedInstance(),
                                 nullptr /* external_reference_table */,
                                 false /* create_v8_platform */);

  v8::Isolate* isolate = v8::Isolate::Allocate();
  platform_->RegisterIsolate(isolate, event_loop);

  return isolate;
}

void JavascriptEnvironment::OnMessageLoopCreated() {
  DCHECK(!microtasks_runner_);
  microtasks_runner_.reset(new MicrotasksRunner(isolate()));
  base::MessageLoopCurrent::Get()->AddTaskObserver(microtasks_runner_.get());
}

void JavascriptEnvironment::OnMessageLoopDestroying() {
  DCHECK(microtasks_runner_);
  base::MessageLoopCurrent::Get()->RemoveTaskObserver(microtasks_runner_.get());
  platform_->UnregisterIsolate(isolate_);
}

NodeEnvironment::NodeEnvironment(node::Environment* env) : env_(env) {}

NodeEnvironment::~NodeEnvironment() {
  node::FreeEnvironment(env_);
}

}  // namespace atom
<commit_msg>fix: drain tasks before shutting down isolate (#17879)<commit_after>// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/browser/javascript_environment.h"

#include <string>

#include "atom/browser/microtasks_runner.h"
#include "atom/common/node_includes.h"
#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
#include "base/task/task_scheduler/initialization_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/public/common/content_switches.h"
#include "gin/array_buffer.h"
#include "gin/v8_initializer.h"
#include "tracing/trace_event.h"

namespace atom {

JavascriptEnvironment::JavascriptEnvironment(uv_loop_t* event_loop)
    : isolate_(Initialize(event_loop)),
      isolate_holder_(base::ThreadTaskRunnerHandle::Get(),
                      gin::IsolateHolder::kSingleThread,
                      gin::IsolateHolder::kAllowAtomicsWait,
                      gin::IsolateHolder::IsolateType::kUtility,
                      gin::IsolateHolder::IsolateCreationMode::kNormal,
                      isolate_),
      isolate_scope_(isolate_),
      locker_(isolate_),
      handle_scope_(isolate_),
      context_(isolate_, v8::Context::New(isolate_)),
      context_scope_(v8::Local<v8::Context>::New(isolate_, context_)) {}

JavascriptEnvironment::~JavascriptEnvironment() = default;

v8::Isolate* JavascriptEnvironment::Initialize(uv_loop_t* event_loop) {
  auto* cmd = base::CommandLine::ForCurrentProcess();

  // --js-flags.
  std::string js_flags = cmd->GetSwitchValueASCII(switches::kJavaScriptFlags);
  if (!js_flags.empty())
    v8::V8::SetFlagsFromString(js_flags.c_str(), js_flags.size());

  // The V8Platform of gin relies on Chromium's task schedule, which has not
  // been started at this point, so we have to rely on Node's V8Platform.
  auto* tracing_agent = node::CreateAgent();
  auto* tracing_controller = tracing_agent->GetTracingController();
  node::tracing::TraceEventHelper::SetAgent(tracing_agent);
  platform_ = node::CreatePlatform(
      base::RecommendedMaxNumberOfThreadsInPool(3, 8, 0.1, 0),
      tracing_controller);

  v8::V8::InitializePlatform(platform_);
  gin::IsolateHolder::Initialize(gin::IsolateHolder::kNonStrictMode,
                                 gin::ArrayBufferAllocator::SharedInstance(),
                                 nullptr /* external_reference_table */,
                                 false /* create_v8_platform */);

  v8::Isolate* isolate = v8::Isolate::Allocate();
  platform_->RegisterIsolate(isolate, event_loop);

  return isolate;
}

void JavascriptEnvironment::OnMessageLoopCreated() {
  DCHECK(!microtasks_runner_);
  microtasks_runner_.reset(new MicrotasksRunner(isolate()));
  base::MessageLoopCurrent::Get()->AddTaskObserver(microtasks_runner_.get());
}

void JavascriptEnvironment::OnMessageLoopDestroying() {
  DCHECK(microtasks_runner_);
  base::MessageLoopCurrent::Get()->RemoveTaskObserver(microtasks_runner_.get());
  platform_->DrainTasks(isolate_);
  platform_->UnregisterIsolate(isolate_);
}

NodeEnvironment::NodeEnvironment(node::Environment* env) : env_(env) {}

NodeEnvironment::~NodeEnvironment() {
  node::FreeEnvironment(env_);
}

}  // namespace atom
<|endoftext|>


<commit_before>#include <string>
#include <fstream>
#include <iostream>
#include <sstream>
#include <map>
#include <stdexcept>
#include <vigra/array_vector.hxx>
#include <tclap/CmdLine.h>
#include "../../include/vigra/hdf5impex.hxx"
#include <set>
using namespace std;
using namespace vigra;

/** various enums used
 */
enum IDS_ {NUMERAL, LITERAL, ORDINAL, NOMINAL, IFSTRING, INPUT, OUTPUT,TAG, DUNNO};
void ARFF2HDF5(std::string arff, std::string hdf5)
{
}

std::string stripstr(std::string in)
{
    std::string out = "";
    for(int ii = 0; ii < int(in.size()); ++ii)
    {
        if(out.size() == 0  && (in[ii] == ' ' || in [ii] == '\t'))
            continue;
        else if(*out.rbegin() == ' ' && (in[ii] == ' ' || in [ii] == '\t'))
            continue;
        else if(in[ii] == '\t' || in[ii] == ' ')
            out = out + ' ';
        else
            out = out + in[ii];
    }
    return out;
}

/** tokenize a string given delimiter string
 */
void tokenize(std::string  str, ArrayVector<std::string> & in, std::string delim = ",")
{
    if(delim == "w")
    {
        str = stripstr(str);
        delim = " ";
    }
    if(str.size() < delim.size() || str.rfind(delim) != str.size() - delim.size())
        str = str+delim;

    while(str.size() != 0)

    {
        if(str.find(delim) != string::npos)
        {
            in.push_back(str.substr(0, str.find(delim)));
            str = str.substr(str.find(delim)+delim.size(), str.size());
        }
    }
}

bool isInteger(std::string a)
{
    return false;
}
bool isInteger(double a)
{
    return double(int(a)) == a;
}
/** write the attributes of a dataset column
 */
template <class T, class C>
void writeColAttr(std::string filename,
                  std::string path,
                  MultiArrayView<2, T, C> ar,
                  IDS_ type,
                  IDS_ in,
                  int number)
{
    //write precedence number
    ArrayVector<int> order(size_t(1), number);
    writeHDF5Attr(filename, path + ".order" , order);

    //write column type
    ArrayVector<std::string> col_type;
    if(in == INPUT)
        col_type.push_back("INPUT");
    else if (in == OUTPUT)
        col_type.push_back("OUTPUT");
    else
    {
		ArrayVector<std::string> tmp(1, "na");
        writeHDF5Attr(filename, path+".scale", tmp);
        writeHDF5Attr(filename, path+".domain", tmp);
        col_type.push_back("TAGS");
        writeHDF5Attr(filename, path+".type", col_type);
        return;
    }
    writeHDF5Attr(filename, path+".type", col_type);

    //write domain and scale of the columns
	if(type == NOMINAL)
	{
		ArrayVector<std::string> scale(1, "NOMINAL");
        writeHDF5Attr(filename, path+".scale", scale);

	    std::set<T> a;
        for(int ii = 0 ; ii < ar.size() ; ++ii)
		    a.insert(ar[ii]);
		ArrayVector<T> cat(a.begin(), a.end());
        writeHDF5Attr(filename, path+".domain", cat);
    }
	else
	{
		ArrayVector<std::string> scale(1, "ORDINAL");
        writeHDF5Attr(filename, path+".scale", scale);

        bool isInt = true;
        for(int ii = 0; ii < ar.size(); ++ii)
            isInt = isInt && isInteger(ar[ii]);
        ArrayVector<std::string> domain;
        if(isInt)
            domain.push_back("INTEGER");
        else
            domain.push_back("REAL");
        writeHDF5Attr(filename, path + ".domain", domain);
	}
}

/** processes the name string delivered by cmd
 */
void processCSVname(std::string in,
					std::string& name,
                    int last_col_index,
					int & beg,
					int & end,
					IDS_ & type,
					IDS_ & in_)
{
	ArrayVector<std::string>  tokens;
	tokenize(in, tokens, "::");

    name = tokens[0];
    type = DUNNO;
    in_  = DUNNO;
    beg  = last_col_index + 1;
    end  = beg ;

    for(int ii = 1; ii < int(tokens.size()); ++ii)
    {
        if      (tokens[ii] == "IN")
            in_ = INPUT;
        else if (tokens[ii] == "OUT")
            in_ = OUTPUT;
        else if (tokens[ii] == "TAG")
            in_ = TAG;
        else if (tokens[ii] == "NOMINAL")
            type = NOMINAL;
        else if (tokens[ii] == "ORDINAL")
            type = ORDINAL;
        else if (tokens[ii] == "all")
            beg = -1;
        else
        {
            double tmp;
            std::istringstream sin(tokens[ii]);
            sin >> tmp;
            if(sin.fail() && tokens[ii].find(":") == string::npos)
                throw std::runtime_error("could not parse name");
		    ArrayVector<std::string>  tokensloc;
		    tokenize(tokens[ii], tokensloc, ":");
	    	beg = atoi(tokensloc[0].c_str());
		    if(tokensloc.size() < 2)
			    end = beg;
		    else
			    end = atoi(tokensloc[1].c_str());
        }
    }
}

struct DlmInfo
{
	std::string 				csvFile;

	ArrayVector<IDS_>			type_;
    ArrayVector<int>            offsets_;
    std::string					delim_;

	int							doubleCount_;
	int							stringCount_;
	int							rowCount_;

	int							h_count_;
	int							t_count_;
	ArrayVector<std::string>	names_;

	int colCount()
	{
		return doubleCount_ + stringCount_;
	}
	DlmInfo(std::string name, std::string delim = ",",
			int headercount		= 0,
			int trailercount	= -1)
	:
		csvFile(name),
		delim_(delim),
		doubleCount_(0),
		stringCount_(0),
		rowCount_(0),
		h_count_(headercount),
		t_count_(0)
	{
		string 		line;
		ifstream 	fin(name.c_str(), ios::in);
		int			count = 0;

		//get the first line!
		while(!getline(fin, line).eof() && count <= h_count_)
			++count;

		ArrayVector<string> tokens;
		tokenize(line, tokens, delim);
		ArrayVector<std::string>::iterator iter;
		for(iter = tokens.begin(); iter != tokens.end(); ++iter)
		{
            std::istringstream sin(*iter);
			double in;
			sin >> in;
			if(sin.fail())
			{
				type_.push_back(LITERAL);
                offsets_.push_back(stringCount_);
				++stringCount_;
			}
			else
			{
				type_.push_back(NUMERAL);
                offsets_.push_back(doubleCount_);
				++doubleCount_;
			}
		}
        bool found_blank_line = false;
		while(!getline(fin, line).eof())
        {
            if(stripstr(line) == "")
            {
                found_blank_line = true;
                break;
            }
			++count;
        }
        if(found_blank_line)
            t_count_ = count;
        else
		    t_count_ = count - trailercount;
		rowCount_ = t_count_ - h_count_;
		fin.close();
	}
};

/**read a delimmited table into a double matrix and an optional
 * string matrix
 */
template<class T, class C1, class C2>
void dlmread(DlmInfo & info,
			 MultiArrayView<2, T, C1> & dblMult,
			 MultiArrayView<2, std::string, C2> strMult
                        = MultiArrayView<2, std::string, C2>())
{
    //precondtion checking
	if(info.stringCount_ != 0)
	vigra_precondition(dblMult.shape(0) == strMult.shape(0),
					   "row Mismatch");
	vigra_precondition(dblMult.shape(0) == info.rowCount_,
					   "row_Mismatch2");
	vigra_precondition(dblMult.shape(1) == info.doubleCount_,
					   "dbl col mismatch");
	if(info.stringCount_ != 0)
	vigra_precondition(strMult.shape(1) == info.stringCount_,
					   "str col mismatch");

	ifstream 	fin(info.csvFile.c_str(), ios::in);
	int			count = 0;
	std::string line;

	//get the first line!
	while(count < info.h_count_ && !getline(fin, line).eof())
		++count;

	for(int ii = 0; ii < info.rowCount_; ++ii)
	{
		getline(fin, line);
		ArrayVector<std::string> tokens;
		tokenize(line, tokens, info.delim_);
		int str_jj = 0, dbl_jj= 0;
		for(int jj = 0; jj < info.colCount(); ++jj)
		{
			if(info.type_[jj] == NUMERAL)
			{
                std::istringstream sin(tokens[jj]);
                double a;
				sin >> a;
                dblMult(ii, dbl_jj) = a;
				++dbl_jj;
			}
			else
			{
				strMult(ii, str_jj) = tokens[jj];
				++str_jj;
			}
		}
	}
}

void CSV2HDF5(std::string csv,
              std::string hdf5,
              std::string path,
              std::vector<string> const & names,
              int headerCt = 0,
              int trailerCt = 0,

              std::string delim = ",")
{
	typedef MultiArrayShape<2>::type Shp;

	//get information for the seperated file and read
    std::cerr << "getting file info" <<std::endl;
	DlmInfo info(csv,delim, headerCt, trailerCt);
	MultiArray<2, double> dblArr(Shp(info.rowCount_, info.doubleCount_));
	MultiArray<2, string> strArr(Shp(info.rowCount_, info.stringCount_), "");
    std::cerr << "loading text file "<<info.doubleCount_ <<" "<< info.rowCount_<< " " <<  info.stringCount_ << std::endl;
	dlmread(info, dblArr, strArr);

    int beg = 0, end = 0, last_end = -1, last_beg = 0;
	std::string r_name;
	IDS_ type, in_;
    bool first_string_column = true;

    //user has supplied column data.
	if(names.size() != 0)
	{
		for(int ii = 0; ii < int(names.size()); ++ii)
		{
            std::cerr << "writing " << names[ii] << std::endl;
			processCSVname(names[ii], r_name, last_end, beg, end, type, in_);
            if(beg == -1)
            {
                beg = 0;
                end = dblArr.shape(1);
            }
            else
            {
                last_end = end;
                last_beg = beg;
                end = end - beg;
                beg = info.offsets_[beg];
                end = beg + end + 1;
            }
            std::string col_path = path + "/" + r_name;
			if(info.type_[last_beg] == NUMERAL)
			{
				writeToHDF5File(hdf5.c_str(),
                                col_path.c_str(),
                                dblArr.subarray(Shp(0, beg),
									            Shp(info.rowCount_, end)));
				if(type == DUNNO)
					type = ORDINAL;
				if(in_ == DUNNO)
					in_ = INPUT;
				writeColAttr(hdf5.c_str(),
							 col_path.c_str(),
							 dblArr.subarray(Shp(0, beg),
                                             Shp(info.rowCount_, end)),
							 type,
							 in_,
                             ii);
			}
			else
			{
                if(end - beg == 1)
				    writeToHDF5File(hdf5.c_str(),
                                    col_path.c_str(),
                                    strArr.subarray(Shp(0, beg),
								    				Shp(info.rowCount_, end)).bindOuter(0));
                else
				    writeToHDF5File(hdf5.c_str(),
                                    col_path.c_str(),
                                    strArr.subarray(Shp(0, beg),
							    					Shp(info.rowCount_, end)));
				if(type == DUNNO)
					type = NOMINAL;
				if( in_ == DUNNO && first_string_column)
				{
					in_ = OUTPUT;
					first_string_column = false;
				}
				else if(in_ == DUNNO)
					in_ = TAG;

				writeColAttr(hdf5.c_str(),
							 col_path.c_str(),
							 strArr.subarray(Shp(0, beg),
                                             Shp(info.rowCount_, end)),
							 type,
							 in_,
                             ii);
			}
        std::cerr << "done " << names[ii] << std::endl;
		}
	}
	else
	{
        if(dblArr.size() > 0)
        {
		writeToHDF5File(hdf5.c_str(),
                        (path+"/doubleCols").c_str(),
                        dblArr);
		writeColAttr(hdf5,
                     path + "/doubleCols",
                     dblArr,
                     ORDINAL,
                     INPUT,
                     0);
        }
        if(strArr.size() > 0)
        {
		writeToHDF5File(hdf5.c_str(),
                        (path+"/stringCols").c_str(),
                        strArr);
		writeColAttr(hdf5,
                     path + "/stringCols",
                     strArr,
                     DUNNO,
                     TAG,
                     1);
        }
	}
}

void INFO2HDF5(std::string info,
              std::string hdf5,
              std::string name)
{

	ifstream 	fin(info.c_str(), ios::in);
	std::string line;
    MultiArray<1, std::string> text_file(MultiArrayShape<1>::type(1), "");

	//get the first line!
	while(!getline(fin, line).eof())
		text_file[0] = text_file[0] +"\n" + line;

    name = "_" + name;
    writeToHDF5File(hdf5.c_str(), name.c_str(),  text_file);
}
int main(int argc, char** argv)
{
    TCLAP::CmdLine cmd("Command description message", ' ', "0.9");
    TCLAP::SwitchArg isARFF("","isARFF","input is ARFF file", cmd, false);
    TCLAP::SwitchArg isCSV("","isCSV","input is CSV file", cmd, false);
    TCLAP::SwitchArg isSparse("","isSparse","input is Sparse csv file", cmd, false);
    TCLAP::SwitchArg isINFO("","isINFO","input is txt information", cmd, false);
    TCLAP::ValueArg<std::string> input("i","input","inputfile", true,"a.in",    "string");
    cmd.add(input);
    TCLAP::ValueArg<std::string> output("o","output","outputfile", true,"a.hdf5","string");
    cmd.add(output);
    TCLAP::ValueArg<std::string> delim("d","delim","csv delimiter", false, ",", "string");
    cmd.add(delim);
    TCLAP::ValueArg<std::string> src("s","source","source", false, "dataset", "string");
    cmd.add(src);
    TCLAP::ValueArg<int> header("t","topper","header lines", false, 0, "int");
    cmd.add(header);
    TCLAP::ValueArg<int> footer("f","footer","footer lines", false, 0, "int");
    cmd.add(footer);
    TCLAP::MultiArg<std::string> names("n", "names", "column names", false, "string");
    cmd.add(names);
    cmd.parse( argc, argv );
    bool iscsv = isCSV.getValue();
    if(iscsv == false && !isARFF.getValue() && !isINFO.getValue())
        iscsv = true;

    ifstream fin(input.getValue().c_str());
    if(fin.fail())
    {
        throw std::runtime_error("could not find inputfile");
    }
    else
        fin.close();
    std::cerr<< "loading file :" << input.getValue() <<std::endl;
	if(isARFF.getValue())
		ARFF2HDF5(input.getValue(), output.getValue());
    if(isSparse.getValue())
        std::cerr << "Sparse Matrix representation currently not supported" <<std::endl;
	else if(iscsv)
		CSV2HDF5(input.getValue(),
                 output.getValue(),
                 src.getValue(),
                 names.getValue(),
                 header.getValue(),
                 footer.getValue(),
                 delim.getValue());
    else if(isINFO.getValue())
        INFO2HDF5(input.getValue(),
                  output.getValue(),
                  src.getValue());
	return 0;
}
<commit_msg>Minor merge<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: statusindicatorinterfacewrapper.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 00:47:31 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef __FRAMEWORK_UIELEMENT_STATUSINDICATORINTERFACEWRAPPER_HXX_
#define __FRAMEWORK_UIELEMENT_STATUSINDICATORINTERFACEWRAPPER_HXX_

//_________________________________________________________________________________________________________________
//  my own includes
//_________________________________________________________________________________________________________________

#ifndef __FRAMEWORK_THREADHELP_THREADHELPBASE_HXX_
#include <threadhelp/threadhelpbase.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_GENERIC_HXX_
#include <macros/generic.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_XINTERFACE_HXX_
#include <macros/xinterface.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_XTYPEPROVIDER_HXX_
#include <macros/xtypeprovider.hxx>
#endif

//_________________________________________________________________________________________________________________
//  interface includes
//_________________________________________________________________________________________________________________

#ifndef _COM_SUN_STAR_TASK_XSTATUSINDICATOR_HPP_
#include <com/sun/star/task/XStatusIndicator.hpp>
#endif

#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_
#include <com/sun/star/beans/PropertyValue.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XCOMPONENT_HPP_
#include <com/sun/star/lang/XComponent.hpp>
#endif

//_________________________________________________________________________________________________________________
//  other includes
//_________________________________________________________________________________________________________________

#ifndef _RTL_OUSTRING_HXX_
#include <rtl/ustring.hxx>
#endif

#ifndef _CPPUHELPER_WEAK_HXX_
#include <cppuhelper/weak.hxx>
#endif

#include <vector>

namespace framework
{

class StatusIndicatorInterfaceWrapper :   public ::com::sun::star::lang::XTypeProvider       ,
                                          public ::com::sun::star::task::XStatusIndicator    ,
                                          public ::cppu::OWeakObject
{
    public:
        StatusIndicatorInterfaceWrapper( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& rStatusIndicatorImpl );
        virtual ~StatusIndicatorInterfaceWrapper();

        //---------------------------------------------------------------------------------------------------------
        //  XInterface, XTypeProvider
        //---------------------------------------------------------------------------------------------------------
        DECLARE_XINTERFACE
        DECLARE_XTYPEPROVIDER

        //---------------------------------------------------------------------------------------------------------
        //  XStatusIndicator
        //---------------------------------------------------------------------------------------------------------
        virtual void SAL_CALL start   ( const ::rtl::OUString& sText  ,
                                              sal_Int32        nRange ) throw( ::com::sun::star::uno::RuntimeException );
        virtual void SAL_CALL end     (                               ) throw( ::com::sun::star::uno::RuntimeException );
        virtual void SAL_CALL reset   (                               ) throw( ::com::sun::star::uno::RuntimeException );
        virtual void SAL_CALL setText ( const ::rtl::OUString& sText  ) throw( ::com::sun::star::uno::RuntimeException );
        virtual void SAL_CALL setValue(       sal_Int32        nValue ) throw( ::com::sun::star::uno::RuntimeException );

    private:
        StatusIndicatorInterfaceWrapper();

        ::com::sun::star::uno::WeakReference< ::com::sun::star::lang::XComponent > m_xStatusIndicatorImpl;
};

}

#endif // __FRAMEWORK_UIELEMENT_STATUSINDICATORINTERFACEWRAPPER_HXX_
<commit_msg>INTEGRATION: CWS warnings01 (1.3.32); FILE MERGED 2005/10/28 14:48:22 cd 1.3.32.1: #i55991# Warning free code changes for gcc<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: statusindicatorinterfacewrapper.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 11:05:50 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef __FRAMEWORK_UIELEMENT_STATUSINDICATORINTERFACEWRAPPER_HXX_
#define __FRAMEWORK_UIELEMENT_STATUSINDICATORINTERFACEWRAPPER_HXX_

//_________________________________________________________________________________________________________________
//  my own includes
//_________________________________________________________________________________________________________________

#ifndef __FRAMEWORK_THREADHELP_THREADHELPBASE_HXX_
#include <threadhelp/threadhelpbase.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_GENERIC_HXX_
#include <macros/generic.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_XINTERFACE_HXX_
#include <macros/xinterface.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_XTYPEPROVIDER_HXX_
#include <macros/xtypeprovider.hxx>
#endif

//_________________________________________________________________________________________________________________
//  interface includes
//_________________________________________________________________________________________________________________

#ifndef _COM_SUN_STAR_TASK_XSTATUSINDICATOR_HPP_
#include <com/sun/star/task/XStatusIndicator.hpp>
#endif

#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_
#include <com/sun/star/beans/PropertyValue.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XCOMPONENT_HPP_
#include <com/sun/star/lang/XComponent.hpp>
#endif

//_________________________________________________________________________________________________________________
//  other includes
//_________________________________________________________________________________________________________________

#ifndef _RTL_OUSTRING_HXX_
#include <rtl/ustring.hxx>
#endif

#ifndef _CPPUHELPER_WEAK_HXX_
#include <cppuhelper/weak.hxx>
#endif

#include <vector>

namespace framework
{

class StatusIndicatorInterfaceWrapper :   public ::com::sun::star::lang::XTypeProvider       ,
                                          public ::com::sun::star::task::XStatusIndicator    ,
                                          public ::cppu::OWeakObject
{
    public:
        StatusIndicatorInterfaceWrapper( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& rStatusIndicatorImpl );
        virtual ~StatusIndicatorInterfaceWrapper();

        //---------------------------------------------------------------------------------------------------------
        //  XInterface, XTypeProvider
        //---------------------------------------------------------------------------------------------------------
        FWK_DECLARE_XINTERFACE
        FWK_DECLARE_XTYPEPROVIDER

        //---------------------------------------------------------------------------------------------------------
        //  XStatusIndicator
        //---------------------------------------------------------------------------------------------------------
        virtual void SAL_CALL start   ( const ::rtl::OUString& sText  ,
                                              sal_Int32        nRange ) throw( ::com::sun::star::uno::RuntimeException );
        virtual void SAL_CALL end     (                               ) throw( ::com::sun::star::uno::RuntimeException );
        virtual void SAL_CALL reset   (                               ) throw( ::com::sun::star::uno::RuntimeException );
        virtual void SAL_CALL setText ( const ::rtl::OUString& sText  ) throw( ::com::sun::star::uno::RuntimeException );
        virtual void SAL_CALL setValue(       sal_Int32        nValue ) throw( ::com::sun::star::uno::RuntimeException );

    private:
        StatusIndicatorInterfaceWrapper();

        ::com::sun::star::uno::WeakReference< ::com::sun::star::lang::XComponent > m_xStatusIndicatorImpl;
};

}

#endif // __FRAMEWORK_UIELEMENT_STATUSINDICATORINTERFACEWRAPPER_HXX_
<|endoftext|>


<commit_before>// Copyright (c) 2015 Chaobin Zhang. All rights reserved.
// Use of this source code is governed by the BSD license that can be
// found in the LICENSE file.

#include "slave/slave_file_thread.h"

#include "base/bind.h"
#include "common/options.h"
#include "thread/ninja_thread.h"

namespace {
static bool g_should_quit_pool = false;
}  // namespace

namespace slave {

// static
void SlaveFileThread::QuitPool() {
  DCHECK(NinjaThread::CurrentlyOn(NinjaThread::FILE));
  g_should_quit_pool = true;
}

SlaveFileThread::SlaveFileThread()
    : weak_factory_(this) {
  NinjaThread::SetDelegate(NinjaThread::FILE, this);
}

SlaveFileThread::~SlaveFileThread() {
  NinjaThread::SetDelegate(NinjaThread::FILE, NULL);
}

void SlaveFileThread::Init() {
  server_ = mg_create_server(NULL, NULL);
  mg_set_option(server_, "document_root", ".");      // Serve current directory

  CHECK(mg_set_option(server_, "listening_port", options::kMongooseServerPort))
      << "Failed to set listening_port option with value "
      << options::kMongooseServerPort;
}

void SlaveFileThread::InitAsync() {
  NinjaThread::PostTask(
      NinjaThread::FILE,
      FROM_HERE,
      base::Bind(&SlaveFileThread::PoolMongooseServer,
                 weak_factory_.GetWeakPtr()));
}

void SlaveFileThread::CleanUp() {
  mg_destroy_server(&server_);
}

void SlaveFileThread::PoolMongooseServer() {
  if (g_should_quit_pool)
    return;

  mg_poll_server(server_, 1000);
  NinjaThread::PostTask(
      NinjaThread::FILE,
      FROM_HERE,
      base::Bind(&SlaveFileThread::PoolMongooseServer,
                  weak_factory_.GetWeakPtr()));
}

}  // namespace slave
<commit_msg>[Slave] mg_set_option() returns NULL if option was set successfully.<commit_after>// Copyright (c) 2015 Chaobin Zhang. All rights reserved.
// Use of this source code is governed by the BSD license that can be
// found in the LICENSE file.

#include "slave/slave_file_thread.h"

#include "base/bind.h"
#include "common/options.h"
#include "thread/ninja_thread.h"

namespace {
static bool g_should_quit_pool = false;
}  // namespace

namespace slave {

// static
void SlaveFileThread::QuitPool() {
  DCHECK(NinjaThread::CurrentlyOn(NinjaThread::FILE));
  g_should_quit_pool = true;
}

SlaveFileThread::SlaveFileThread()
    : weak_factory_(this) {
  NinjaThread::SetDelegate(NinjaThread::FILE, this);
}

SlaveFileThread::~SlaveFileThread() {
  NinjaThread::SetDelegate(NinjaThread::FILE, NULL);
}

void SlaveFileThread::Init() {
  server_ = mg_create_server(NULL, NULL);
  mg_set_option(server_, "document_root", ".");      // Serve current directory

  CHECK(mg_set_option(server_, "listening_port",
                      options::kMongooseServerPort) == NULL)
      << "Failed to set listening_port option with value "
      << options::kMongooseServerPort;
}

void SlaveFileThread::InitAsync() {
  NinjaThread::PostTask(
      NinjaThread::FILE,
      FROM_HERE,
      base::Bind(&SlaveFileThread::PoolMongooseServer,
                 weak_factory_.GetWeakPtr()));
}

void SlaveFileThread::CleanUp() {
  mg_destroy_server(&server_);
}

void SlaveFileThread::PoolMongooseServer() {
  if (g_should_quit_pool)
    return;

  mg_poll_server(server_, 1000);
  NinjaThread::PostTask(
      NinjaThread::FILE,
      FROM_HERE,
      base::Bind(&SlaveFileThread::PoolMongooseServer,
                  weak_factory_.GetWeakPtr()));
}

}  // namespace slave
<|endoftext|>


<commit_before>//===- Inliner.cpp - Code common to all inliners --------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the mechanics required to implement inlining without
// missing any calls and updating the call graph.  The decisions of which calls
// are profitable to inline are implemented elsewhere.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "inline"
#include "llvm/Module.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/IPO/InlinerPass.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/Statistic.h"
#include <set>
using namespace llvm;

STATISTIC(NumInlined, "Number of functions inlined");
STATISTIC(NumDeleted, "Number of functions deleted because all callers found");

static cl::opt<int>
InlineLimit("inline-threshold", cl::Hidden, cl::init(200),
        cl::desc("Control the amount of inlining to perform (default = 200)"));

Inliner::Inliner(void *ID)
  : CallGraphSCCPass(ID), InlineThreshold(InlineLimit) {}

Inliner::Inliner(void *ID, int Threshold)
  : CallGraphSCCPass(ID), InlineThreshold(Threshold) {}

/// getAnalysisUsage - For this class, we declare that we require and preserve
/// the call graph.  If the derived class implements this method, it should
/// always explicitly call the implementation here.
void Inliner::getAnalysisUsage(AnalysisUsage &Info) const {
  Info.addRequired<TargetData>();
  CallGraphSCCPass::getAnalysisUsage(Info);
}

// InlineCallIfPossible - If it is possible to inline the specified call site,
// do so and update the CallGraph for this operation.
static bool InlineCallIfPossible(CallSite CS, CallGraph &CG,
                                 const std::set<Function*> &SCCFunctions,
                                 const TargetData &TD) {
  Function *Callee = CS.getCalledFunction();
  if (!InlineFunction(CS, &CG, &TD)) return false;

  // If we inlined the last possible call site to the function, delete the
  // function body now.
  if (Callee->use_empty() && Callee->hasInternalLinkage() &&
      !SCCFunctions.count(Callee)) {
    DOUT << "    -> Deleting dead function: " << Callee->getName() << "\n";
    CallGraphNode *CalleeNode = CG[Callee];

    // Remove any call graph edges from the callee to its callees.
    CalleeNode->removeAllCalledFunctions();

    // Removing the node for callee from the call graph and delete it.
    delete CG.removeFunctionFromModule(CalleeNode);
    ++NumDeleted;
  }
  return true;
}

/// shouldInline - Return true if the inliner should attempt to inline
/// at the given CallSite.
bool Inliner::shouldInline(CallSite CS) {
  InlineCost IC = getInlineCost(CS);
  float FudgeFactor = getInlineFudgeFactor(CS);

  if (IC.isAlways()) {
    DOUT << "    Inlining: cost=always"
         << ", Call: " << *CS.getInstruction();
    return true;
  }

  if (IC.isNever()) {
    DOUT << "    NOT Inlining: cost=never"
         << ", Call: " << *CS.getInstruction();
    return false;
  }

  int Cost = IC.getValue();
  int CurrentThreshold = InlineThreshold;
  Function *Fn = CS.getCaller();
  if (Fn && !Fn->isDeclaration()
      && Fn->hasFnAttr(Attribute::OptimizeForSize)
      && InlineThreshold != 50) {
    CurrentThreshold = 50;
  }

  if (Cost >= (int)(CurrentThreshold * FudgeFactor)) {
    DOUT << "    NOT Inlining: cost=" << Cost
         << ", Call: " << *CS.getInstruction();
    return false;
  } else {
    DOUT << "    Inlining: cost=" << Cost
         << ", Call: " << *CS.getInstruction();
    return true;
  }
}

bool Inliner::runOnSCC(const std::vector<CallGraphNode*> &SCC) {
  CallGraph &CG = getAnalysis<CallGraph>();

  std::set<Function*> SCCFunctions;
  DOUT << "Inliner visiting SCC:";
  for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
    Function *F = SCC[i]->getFunction();
    if (F) SCCFunctions.insert(F);
    DOUT << " " << (F ? F->getName() : "INDIRECTNODE");
  }

  // Scan through and identify all call sites ahead of time so that we only
  // inline call sites in the original functions, not call sites that result
  // from inlining other functions.
  std::vector<CallSite> CallSites;

  for (unsigned i = 0, e = SCC.size(); i != e; ++i)
    if (Function *F = SCC[i]->getFunction())
      for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
        for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) {
          CallSite CS = CallSite::get(I);
          if (CS.getInstruction() && (!CS.getCalledFunction() ||
                                      !CS.getCalledFunction()->isDeclaration()))
            CallSites.push_back(CS);
        }

  DOUT << ": " << CallSites.size() << " call sites.\n";

  // Now that we have all of the call sites, move the ones to functions in the
  // current SCC to the end of the list.
  unsigned FirstCallInSCC = CallSites.size();
  for (unsigned i = 0; i < FirstCallInSCC; ++i)
    if (Function *F = CallSites[i].getCalledFunction())
      if (SCCFunctions.count(F))
        std::swap(CallSites[i--], CallSites[--FirstCallInSCC]);

  // Now that we have all of the call sites, loop over them and inline them if
  // it looks profitable to do so.
  bool Changed = false;
  bool LocalChange;
  do {
    LocalChange = false;
    // Iterate over the outer loop because inlining functions can cause indirect
    // calls to become direct calls.
    for (unsigned CSi = 0; CSi != CallSites.size(); ++CSi)
      if (Function *Callee = CallSites[CSi].getCalledFunction()) {
        // Calls to external functions are never inlinable.
        if (Callee->isDeclaration() ||
            CallSites[CSi].getInstruction()->getParent()->getParent() ==Callee){
          if (SCC.size() == 1) {
            std::swap(CallSites[CSi], CallSites.back());
            CallSites.pop_back();
          } else {
            // Keep the 'in SCC / not in SCC' boundary correct.
            CallSites.erase(CallSites.begin()+CSi);
          }
          --CSi;
          continue;
        }

        // If the policy determines that we should inline this function,
        // try to do so.
        CallSite CS = CallSites[CSi];
        if (shouldInline(CS)) {
          // Attempt to inline the function...
          if (InlineCallIfPossible(CS, CG, SCCFunctions,
                                   getAnalysis<TargetData>())) {
            // Remove this call site from the list.  If possible, use
            // swap/pop_back for efficiency, but do not use it if doing so would
            // move a call site to a function in this SCC before the
            // 'FirstCallInSCC' barrier.
            if (SCC.size() == 1) {
              std::swap(CallSites[CSi], CallSites.back());
              CallSites.pop_back();
            } else {
              CallSites.erase(CallSites.begin()+CSi);
            }
            --CSi;

            ++NumInlined;
            Changed = true;
            LocalChange = true;
          }
        }
      }
  } while (LocalChange);

  return Changed;
}

// doFinalization - Remove now-dead linkonce functions at the end of
// processing to avoid breaking the SCC traversal.
bool Inliner::doFinalization(CallGraph &CG) {
  return removeDeadFunctions(CG);
}

  /// removeDeadFunctions - Remove dead functions that are not included in
  /// DNR (Do Not Remove) list.
bool Inliner::removeDeadFunctions(CallGraph &CG,
                                 SmallPtrSet<const Function *, 16> *DNR) {
  std::set<CallGraphNode*> FunctionsToRemove;

  // Scan for all of the functions, looking for ones that should now be removed
  // from the program.  Insert the dead ones in the FunctionsToRemove set.
  for (CallGraph::iterator I = CG.begin(), E = CG.end(); I != E; ++I) {
    CallGraphNode *CGN = I->second;
    if (Function *F = CGN ? CGN->getFunction() : 0) {
      // If the only remaining users of the function are dead constants, remove
      // them.
      F->removeDeadConstantUsers();

      if (DNR && DNR->count(F))
        continue;

      if ((F->hasLinkOnceLinkage() || F->hasInternalLinkage()) &&
          F->use_empty()) {

        // Remove any call graph edges from the function to its callees.
        CGN->removeAllCalledFunctions();

        // Remove any edges from the external node to the function's call graph
        // node.  These edges might have been made irrelegant due to
        // optimization of the program.
        CG.getExternalCallingNode()->removeAnyCallEdgeTo(CGN);

        // Removing the node for callee from the call graph and delete it.
        FunctionsToRemove.insert(CGN);
      }
    }
  }

  // Now that we know which functions to delete, do so.  We didn't want to do
  // this inline, because that would invalidate our CallGraph::iterator
  // objects. :(
  bool Changed = false;
  for (std::set<CallGraphNode*>::iterator I = FunctionsToRemove.begin(),
         E = FunctionsToRemove.end(); I != E; ++I) {
    delete CG.removeFunctionFromModule(*I);
    ++NumDeleted;
    Changed = true;
  }

  return Changed;
}
<commit_msg>If the function being inlined has a higher stack protection level than the inlining function, then increase the stack protection level on the inlining function.<commit_after>//===- Inliner.cpp - Code common to all inliners --------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the mechanics required to implement inlining without
// missing any calls and updating the call graph.  The decisions of which calls
// are profitable to inline are implemented elsewhere.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "inline"
#include "llvm/Module.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/IPO/InlinerPass.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/Statistic.h"
#include <set>
using namespace llvm;

STATISTIC(NumInlined, "Number of functions inlined");
STATISTIC(NumDeleted, "Number of functions deleted because all callers found");

static cl::opt<int>
InlineLimit("inline-threshold", cl::Hidden, cl::init(200),
        cl::desc("Control the amount of inlining to perform (default = 200)"));

Inliner::Inliner(void *ID)
  : CallGraphSCCPass(ID), InlineThreshold(InlineLimit) {}

Inliner::Inliner(void *ID, int Threshold)
  : CallGraphSCCPass(ID), InlineThreshold(Threshold) {}

/// getAnalysisUsage - For this class, we declare that we require and preserve
/// the call graph.  If the derived class implements this method, it should
/// always explicitly call the implementation here.
void Inliner::getAnalysisUsage(AnalysisUsage &Info) const {
  Info.addRequired<TargetData>();
  CallGraphSCCPass::getAnalysisUsage(Info);
}

// InlineCallIfPossible - If it is possible to inline the specified call site,
// do so and update the CallGraph for this operation.
static bool InlineCallIfPossible(CallSite CS, CallGraph &CG,
                                 const std::set<Function*> &SCCFunctions,
                                 const TargetData &TD) {
  Function *Callee = CS.getCalledFunction();
  if (!InlineFunction(CS, &CG, &TD)) return false;

  // If the inlined function had a higher stack protection level than the
  // calling function, then bump up the caller's stack protection level.
  Function *Caller = CS.getCaller();
  if (Callee->hasFnAttr(Attribute::StackProtectReq))
    Caller->addFnAttr(Attribute::StackProtectReq);
  else if (Callee->hasFnAttr(Attribute::StackProtect) &&
           !Caller->hasFnAttr(Attribute::StackProtectReq))
    Caller->addFnAttr(Attribute::StackProtect);

  // If we inlined the last possible call site to the function, delete the
  // function body now.
  if (Callee->use_empty() && Callee->hasInternalLinkage() &&
      !SCCFunctions.count(Callee)) {
    DOUT << "    -> Deleting dead function: " << Callee->getName() << "\n";
    CallGraphNode *CalleeNode = CG[Callee];

    // Remove any call graph edges from the callee to its callees.
    CalleeNode->removeAllCalledFunctions();

    // Removing the node for callee from the call graph and delete it.
    delete CG.removeFunctionFromModule(CalleeNode);
    ++NumDeleted;
  }
  return true;
}

/// shouldInline - Return true if the inliner should attempt to inline
/// at the given CallSite.
bool Inliner::shouldInline(CallSite CS) {
  InlineCost IC = getInlineCost(CS);
  float FudgeFactor = getInlineFudgeFactor(CS);

  if (IC.isAlways()) {
    DOUT << "    Inlining: cost=always"
         << ", Call: " << *CS.getInstruction();
    return true;
  }

  if (IC.isNever()) {
    DOUT << "    NOT Inlining: cost=never"
         << ", Call: " << *CS.getInstruction();
    return false;
  }

  int Cost = IC.getValue();
  int CurrentThreshold = InlineThreshold;
  Function *Fn = CS.getCaller();
  if (Fn && !Fn->isDeclaration()
      && Fn->hasFnAttr(Attribute::OptimizeForSize)
      && InlineThreshold != 50) {
    CurrentThreshold = 50;
  }

  if (Cost >= (int)(CurrentThreshold * FudgeFactor)) {
    DOUT << "    NOT Inlining: cost=" << Cost
         << ", Call: " << *CS.getInstruction();
    return false;
  } else {
    DOUT << "    Inlining: cost=" << Cost
         << ", Call: " << *CS.getInstruction();
    return true;
  }
}

bool Inliner::runOnSCC(const std::vector<CallGraphNode*> &SCC) {
  CallGraph &CG = getAnalysis<CallGraph>();

  std::set<Function*> SCCFunctions;
  DOUT << "Inliner visiting SCC:";
  for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
    Function *F = SCC[i]->getFunction();
    if (F) SCCFunctions.insert(F);
    DOUT << " " << (F ? F->getName() : "INDIRECTNODE");
  }

  // Scan through and identify all call sites ahead of time so that we only
  // inline call sites in the original functions, not call sites that result
  // from inlining other functions.
  std::vector<CallSite> CallSites;

  for (unsigned i = 0, e = SCC.size(); i != e; ++i)
    if (Function *F = SCC[i]->getFunction())
      for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
        for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) {
          CallSite CS = CallSite::get(I);
          if (CS.getInstruction() && (!CS.getCalledFunction() ||
                                      !CS.getCalledFunction()->isDeclaration()))
            CallSites.push_back(CS);
        }

  DOUT << ": " << CallSites.size() << " call sites.\n";

  // Now that we have all of the call sites, move the ones to functions in the
  // current SCC to the end of the list.
  unsigned FirstCallInSCC = CallSites.size();
  for (unsigned i = 0; i < FirstCallInSCC; ++i)
    if (Function *F = CallSites[i].getCalledFunction())
      if (SCCFunctions.count(F))
        std::swap(CallSites[i--], CallSites[--FirstCallInSCC]);

  // Now that we have all of the call sites, loop over them and inline them if
  // it looks profitable to do so.
  bool Changed = false;
  bool LocalChange;
  do {
    LocalChange = false;
    // Iterate over the outer loop because inlining functions can cause indirect
    // calls to become direct calls.
    for (unsigned CSi = 0; CSi != CallSites.size(); ++CSi)
      if (Function *Callee = CallSites[CSi].getCalledFunction()) {
        // Calls to external functions are never inlinable.
        if (Callee->isDeclaration() ||
            CallSites[CSi].getInstruction()->getParent()->getParent() ==Callee){
          if (SCC.size() == 1) {
            std::swap(CallSites[CSi], CallSites.back());
            CallSites.pop_back();
          } else {
            // Keep the 'in SCC / not in SCC' boundary correct.
            CallSites.erase(CallSites.begin()+CSi);
          }
          --CSi;
          continue;
        }

        // If the policy determines that we should inline this function,
        // try to do so.
        CallSite CS = CallSites[CSi];
        if (shouldInline(CS)) {
          // Attempt to inline the function...
          if (InlineCallIfPossible(CS, CG, SCCFunctions,
                                   getAnalysis<TargetData>())) {
            // Remove this call site from the list.  If possible, use
            // swap/pop_back for efficiency, but do not use it if doing so would
            // move a call site to a function in this SCC before the
            // 'FirstCallInSCC' barrier.
            if (SCC.size() == 1) {
              std::swap(CallSites[CSi], CallSites.back());
              CallSites.pop_back();
            } else {
              CallSites.erase(CallSites.begin()+CSi);
            }
            --CSi;

            ++NumInlined;
            Changed = true;
            LocalChange = true;
          }
        }
      }
  } while (LocalChange);

  return Changed;
}

// doFinalization - Remove now-dead linkonce functions at the end of
// processing to avoid breaking the SCC traversal.
bool Inliner::doFinalization(CallGraph &CG) {
  return removeDeadFunctions(CG);
}

  /// removeDeadFunctions - Remove dead functions that are not included in
  /// DNR (Do Not Remove) list.
bool Inliner::removeDeadFunctions(CallGraph &CG,
                                 SmallPtrSet<const Function *, 16> *DNR) {
  std::set<CallGraphNode*> FunctionsToRemove;

  // Scan for all of the functions, looking for ones that should now be removed
  // from the program.  Insert the dead ones in the FunctionsToRemove set.
  for (CallGraph::iterator I = CG.begin(), E = CG.end(); I != E; ++I) {
    CallGraphNode *CGN = I->second;
    if (Function *F = CGN ? CGN->getFunction() : 0) {
      // If the only remaining users of the function are dead constants, remove
      // them.
      F->removeDeadConstantUsers();

      if (DNR && DNR->count(F))
        continue;

      if ((F->hasLinkOnceLinkage() || F->hasInternalLinkage()) &&
          F->use_empty()) {

        // Remove any call graph edges from the function to its callees.
        CGN->removeAllCalledFunctions();

        // Remove any edges from the external node to the function's call graph
        // node.  These edges might have been made irrelegant due to
        // optimization of the program.
        CG.getExternalCallingNode()->removeAnyCallEdgeTo(CGN);

        // Removing the node for callee from the call graph and delete it.
        FunctionsToRemove.insert(CGN);
      }
    }
  }

  // Now that we know which functions to delete, do so.  We didn't want to do
  // this inline, because that would invalidate our CallGraph::iterator
  // objects. :(
  bool Changed = false;
  for (std::set<CallGraphNode*>::iterator I = FunctionsToRemove.begin(),
         E = FunctionsToRemove.end(); I != E; ++I) {
    delete CG.removeFunctionFromModule(*I);
    ++NumDeleted;
    Changed = true;
  }

  return Changed;
}
<|endoftext|>