void CPPClientStubGenerator::generateAssignments(Procedure &proc)
{
    string assignment;
    parameterNameList_t list = proc.GetParameters();
    if(list.size() > 0)
    {
        for (parameterNameList_t::iterator it = list.begin(); it != list.end(); it++)
        {

            if(proc.GetParameterDeclarationType() == PARAMS_BY_NAME)
            {
                assignment = TEMPLATE_NAMED_ASSIGNMENT;
            }
            else
            {
                assignment = TEMPLATE_POSITION_ASSIGNMENT;
            }
            replaceAll2(assignment, "<paramname>", it->first);
            cg.writeLine(assignment);
        }
    }
    else
    {
        cg.writeLine("p = Json::nullValue;");
    }

}
void CPPClientStubGenerator::generateMethod(Procedure &proc)
{
    string procsignature = TEMPLATE_CPPCLIENT_SIGMETHOD;
    string returntype = CPPHelper::toCppType(proc.GetReturnType());
    if (proc.GetProcedureType() == RPC_NOTIFICATION)
        returntype = "void";

    replaceAll2(procsignature, "<returntype>", returntype);
    replaceAll2(procsignature, "<methodname>", CPPHelper::normalizeString(proc.GetProcedureName()));
    replaceAll2(procsignature, "<parameters>", CPPHelper::generateParameterDeclarationList(proc));

    cg.writeLine(procsignature);
    cg.writeLine("{");
    cg.increaseIndentation();

    cg.writeLine("Json::Value p;");

    generateAssignments(proc);
    generateProcCall(proc);

    cg.decreaseIndentation();
    cg.writeLine("}");


}
Пример #3
0
void RpcProtocolServer::ProcessRequest(const Json::Value& request,
                                       Json::Value& response)
{
    Procedure* method = (*this->procedures)[request[KEY_REQUEST_METHODNAME].asString()];
    Json::Value result;

    if (method->GetProcedureType() == RPC_METHOD)
    {
        server->handleMethodCall(method, request[KEY_REQUEST_PARAMETERS],
                                 result);
        response[KEY_REQUEST_VERSION] = JSON_RPC_VERSION;
        response[KEY_RESPONSE_RESULT] = result;
        response[KEY_REQUEST_ID] = request[KEY_REQUEST_ID];
        if (this->authManager != NULL)
        {
            this->authManager->ProcessAuthentication(
                request[KEY_AUTHENTICATION],
                response[KEY_AUTHENTICATION]);
        }
    }
    else
    {
        server->handleNotificationCall(method, request[KEY_REQUEST_PARAMETERS]);
        response = Json::Value::null;
    }
}
Пример #4
0
void generateToAir(Procedure& procedure, Air::Code& code)
{
    TimingScope timingScope("generateToAir");
    
    // We don't require the incoming IR to have predecessors computed.
    procedure.resetReachability();
    
    if (shouldValidateIR())
        validate(procedure);

    // If we're doing super verbose dumping, the phase scope of any phase will already do a dump.
    if (shouldDumpIR() && !shouldDumpIRAtEachPhase()) {
        dataLog("Initial B3:\n");
        dataLog(procedure);
    }

    reduceStrength(procedure);
    
    // FIXME: Add more optimizations here.
    // https://bugs.webkit.org/show_bug.cgi?id=150507

    moveConstants(procedure);

    if (shouldValidateIR())
        validate(procedure);
    
    // If we're doing super verbose dumping, the phase scope of any phase will already do a dump.
    // Note that lowerToAir() acts like a phase in this regard.
    if (shouldDumpIR() && !shouldDumpIRAtEachPhase()) {
        dataLog("B3 after ", procedure.lastPhaseName(), ", before generation:\n");
        dataLog(procedure);
    }

    lowerToAir(procedure, code);
}
Пример #5
0
bool ProcedureController::RemoveProcedure(const ProcedureCacheKey &id, const Procedure &procedure)
{
    if(procedure.IsTemplateProcedure() && !procedure.IsPureTemplateProcedure())
    {
        qint32 procedureId = procedure.GetProcedureId();

        if(m_proceduresFromTemplate.count(procedureId) != 0)
        {
            std::set<qint32> &procedureSet = m_proceduresFromTemplate.at(procedureId);
            procedureSet.erase(procedure.GetProjectProcedureId());

            if(procedureSet.size() == 0)
            {
                m_proceduresFromTemplate.erase(procedureId);
                // procedureSet is now invalid.
            }
        }
        //else
        //{
        //  // Should never happen.
        //}
    }

    return m_cache.Remove(id);
}
void CPPClientStubGenerator::generateProcCall(Procedure &proc)
{
    string call;
    if (proc.GetProcedureType() == RPC_METHOD)
    {
        call = TEMPLATE_METHODCALL;
        cg.writeLine(replaceAll(call, "<name>", proc.GetProcedureName()));
        call = TEMPLATE_RETURNCHECK;
        replaceAll2(call,"<cast>", CPPHelper::isCppConversion(proc.GetReturnType()));
        cg.writeLine(call);
        cg.increaseIndentation();
        call = TEMPLATE_RETURN;
        replaceAll2(call,"<cast>", CPPHelper::toCppConversion(proc.GetReturnType()));
        cg.writeLine(call);
        cg.decreaseIndentation();
        cg.writeLine("else");
        cg.increaseIndentation();
        cg.writeLine("throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());");
        cg.decreaseIndentation();
    }
    else
    {
        call = TEMPLATE_NOTIFICATIONCALL;
        replaceAll2(call, "<name>", proc.GetProcedureName());
        cg.writeLine(call);
    }

}
vector<Procedure>   SpecificationParser::GetProceduresFromString(const string &content) throw(JsonRpcException)
{

    Json::Reader reader;
    Json::Value val;
    if(!reader.parse(content,val))
    {
        throw JsonRpcException(Errors::ERROR_RPC_JSON_PARSE_ERROR, " specification file contains syntax errors");
    }

    if (!val.isArray())
    {
        throw JsonRpcException(Errors::ERROR_SERVER_PROCEDURE_SPECIFICATION_SYNTAX, " top level json value is not an array");
    }

    vector<Procedure> result;
    map<string, Procedure> procnames;
    for (unsigned int i = 0; i < val.size(); i++)
    {
        Procedure proc;
        GetProcedure(val[i], proc);
        if (procnames.find(proc.GetProcedureName()) != procnames.end())
        {
            throw JsonRpcException(Errors::ERROR_SERVER_PROCEDURE_SPECIFICATION_SYNTAX, "Procedurename not uniqe: " + proc.GetProcedureName());
        }
        procnames[proc.GetProcedureName()] = proc;
        result.push_back(proc);
    }
    return result;
}
Пример #8
0
void IRParser::putAction(ActionTag* tag, Action* action){
    if (tag->isEmpty()){
        Procedure* body = action->getBody();
        untaggedActions.insert(pair<Function*, Action*>(body->getFunction(), action));
    } else {
        actions.insert(pair<std::string, Action*>(tag->getIdentifier(), action));
    }

}
Пример #9
0
void generateToAir(Procedure& procedure, unsigned optLevel)
{
    TimingScope timingScope("generateToAir");
    
    if (shouldDumpIR(B3Mode) && !shouldDumpIRAtEachPhase(B3Mode)) {
        dataLog("Initial B3:\n");
        dataLog(procedure);
    }

    // We don't require the incoming IR to have predecessors computed.
    procedure.resetReachability();
    
    if (shouldValidateIR())
        validate(procedure);

    if (optLevel >= 1) {
        reduceDoubleToFloat(procedure);
        reduceStrength(procedure);
        eliminateCommonSubexpressions(procedure);
        inferSwitches(procedure);
        duplicateTails(procedure);
        fixSSA(procedure);
        foldPathConstants(procedure);
        
        // FIXME: Add more optimizations here.
        // https://bugs.webkit.org/show_bug.cgi?id=150507
    }

    lowerMacros(procedure);

    if (optLevel >= 1) {
        reduceStrength(procedure);

        // FIXME: Add more optimizations here.
        // https://bugs.webkit.org/show_bug.cgi?id=150507
    }

    lowerMacrosAfterOptimizations(procedure);
    legalizeMemoryOffsets(procedure);
    moveConstants(procedure);

    // FIXME: We should run pureCSE here to clean up some platform specific changes from the previous phases.
    // https://bugs.webkit.org/show_bug.cgi?id=164873

    if (shouldValidateIR())
        validate(procedure);
    
    // If we're doing super verbose dumping, the phase scope of any phase will already do a dump.
    // Note that lowerToAir() acts like a phase in this regard.
    if (shouldDumpIR(B3Mode) && !shouldDumpIRAtEachPhase(B3Mode)) {
        dataLog("B3 after ", procedure.lastPhaseName(), ", before generation:\n");
        dataLog(procedure);
    }

    lowerToAir(procedure);
}
Пример #10
0
map<string, Procedure*>* IRWriter::writeProcedures(map<string, Procedure*>* procs){
    map<string, Procedure*>::iterator it;
    map<string, Procedure*>* newProcs = new map<string, Procedure*>();


    //Creation of procedure must be done in two times because function can call other functions
    for (it = procs->begin(); it != procs->end(); ++it){
        Procedure* proc = (*it).second;
        Function* newFunction = NULL;

        //Write declaration of the function
        if (proc->isExternal()){
            newFunction = writer->addFunctionProtosExternal(proc->getFunction());
        }else{
            newFunction = writer->addFunctionProtosInternal(proc->getFunction());
        }

        //Create a new procedure
        Procedure* newProc = new Procedure(proc->getName(), proc->getExternal(), newFunction);
        newProcs->insert(pair<string, Procedure*>(proc->getName(), newProc));
    }

    //Link body of the procedure
    for (it = procs->begin(); it != procs->end(); ++it){
        Procedure* proc = (*it).second;
        writer->linkProcedureBody(proc->getFunction());
    }

    return newProcs;
}
Пример #11
0
ProcedureController::ProcedureCacheKey ProcedureController::GetCacheKey(const Procedure &procedure)
{
    if(!procedure.IsPureTemplateProcedure())
    {
        return ProcedureCacheKey(ProcedureType::PT_PROJECT, procedure.GetProjectProcedureId());
    }
    else
    {
        return ProcedureCacheKey(ProcedureType::PT_PROJECT_TYPE, procedure.GetProcedureId());
    }
}
Пример #12
0
// method to test the assigning and retrieval of grades
void ProcTableTest::testInsertProc(){
	// verify the insertion and return index is correct
	myProcTable = new ProcTable;

	proc1.setEndProgLine(30);
	proc2.setEndProgLine(45);

	CPPUNIT_ASSERT_EQUAL(1,myProcTable->insertProc(new Procedure(proc1)));
	CPPUNIT_ASSERT_EQUAL(2,myProcTable->insertProc(new Procedure(proc2)));
	//attempt to add a procedure with existing name
	CPPUNIT_ASSERT_EQUAL(1,myProcTable->insertProc(new Procedure(proc1)));
}
//! recreate html page if something changes
void MetadataItemPropertiesPanel::update()
{
    Database* db = dynamic_cast<Database*>(objectM);
    if (db && !db->isConnected())
    {
        objectM = 0;
        if (MetadataItemPropertiesFrame* f = getParentFrame())
            f->Close();

        // MB: This code used to use:
        //f->removePanel(this);
        // which would allow us to mix property pages from different
        // databases in the same Frame, but there are some mysterious
        // reasons why it causes heap corruption with MSVC

        return;
    }

    // if table or view columns change, we need to reattach
    if (objectM->getType() == ntTable || objectM->getType() == ntView)  // also observe columns
    {
        Relation* r = dynamic_cast<Relation*>(objectM);
        if (!r)
            return;

        SubjectLocker locker(r);
        r->ensureChildrenLoaded();
        for (ColumnPtrs::iterator it = r->begin(); it != r->end(); ++it)
            (*it)->attachObserver(this, false);
    }

    // if description of procedure params change, we need to reattach
    if (objectM->getType() == ntProcedure)
    {
        Procedure* p = dynamic_cast<Procedure*>(objectM);
        if (!p)
            return;

        SubjectLocker locker(p);
        p->ensureChildrenLoaded();
        for (ParameterPtrs::iterator it = p->begin(); it != p->end(); ++it)
            (*it)->attachObserver(this, false);
    }

    // with this set to false updates to the same page do not show the
    // "Please wait while the data is being loaded..." temporary page
    // this results in less flicker, but may also seem less responsive
    if (!htmlReloadRequestedM)
        requestLoadPage(false);
}
Пример #14
0
bool ProcedureController::UpdateProcedure(const Procedure &procedure)
{
    QSqlQuery procedureUpdate = GetDb().CreateQuery();
    procedureUpdate.prepare("UPDATE \"Procedure\" "
        "SET \"Description\"=:description "
        "WHERE \"ProcedureId\"=:procedureId;");
    procedureUpdate.bindValue(":procedureId", procedure.GetProcedureId());
    procedureUpdate.bindValue(":description", procedure.GetDescription());
    if(!procedureUpdate.exec())
    {
        return false;
    }

    if(!procedure.IsTemplateProcedure())
    {
        QSqlQuery projectProcedureUpdate = GetDb().CreateQuery();
        projectProcedureUpdate.prepare("UPDATE \"ProjectProcedure\" "
            "SET \"IsDone\"=:isDone "
            "WHERE \"ProjectProcedureId\"=:projectProcedureId;");
        projectProcedureUpdate.bindValue(":projectProcedureId", procedure.GetProjectProcedureId());
        projectProcedureUpdate.bindValue(":isDone", procedure.GetDoneState() ? 1 : 0);
        if(!projectProcedureUpdate.exec())
        {
            return false;
        }

        emit sigProcedureModified(procedure);
    }

    // Update linked project procedures from template.
    if(procedure.IsPureTemplateProcedure())
    {
        qint32 templateProcedureId = procedure.GetProcedureId();
        if(m_proceduresFromTemplate.count(templateProcedureId) != 0)
        {
            std::set<qint32> &procedureSet = m_proceduresFromTemplate.at(templateProcedureId);

            for(auto it = procedureSet.begin(); it != procedureSet.end(); it++)
            {
                qint32 projectProcedureId = *it;
                ProcedureCacheKey key(ProcedureType::PT_PROJECT, projectProcedureId);

                std::shared_ptr<Procedure> projectProcedure = m_cache.Lookup(key);
                if(!projectProcedure)
                {
                    continue;
                }

                projectProcedure->SetDescription(procedure.GetDescription());
                emit sigProcedureModified(*projectProcedure);
            }
        }

        emit sigProcedureModified(procedure);
    }

    return true;
}
Пример #15
0
void prepareForGeneration(Procedure& procedure, unsigned optLevel)
{
    TimingScope timingScope("prepareForGeneration");

    generateToAir(procedure, optLevel);
    Air::prepareForGeneration(procedure.code());
}
Пример #16
0
void prepareForGeneration(Procedure& procedure)
{
    TimingScope timingScope("prepareForGeneration");

    generateToAir(procedure);
    Air::prepareForGeneration(procedure.code());
}
void breakCriticalEdges(Procedure& proc)
{
    BlockInsertionSet insertionSet(proc);
    
    for (BasicBlock* block : proc) {
        // Non-void terminals that are the moral equivalent of jumps trigger critical edge breaking
        // because of fixSSA's demoteValues.
        if (block->numSuccessors() <= 1
            && block->last()->type() == Void)
            continue;

        for (BasicBlock*& successor : block->successorBlocks()) {
            if (successor->numPredecessors() <= 1)
                continue;

            BasicBlock* pad =
                insertionSet.insertBefore(successor, successor->frequency());
            pad->appendNew<Value>(proc, Jump, successor->at(0)->origin());
            pad->setSuccessors(FrequentedBlock(successor));
            pad->addPredecessor(block);
            successor->replacePredecessor(block, pad);
            successor = pad;
        }
    }

    if (insertionSet.execute())
        proc.invalidateCFG();
}
void                SpecificationParser::GetNamedParameters(Json::Value &val, Procedure &result)
{
    vector<string> parameters = val[KEY_SPEC_PROCEDURE_PARAMETERS].getMemberNames();
    for (unsigned int i=0; i < parameters.size(); ++i)
    {
        result.AddParameter(parameters.at(i), toJsonType(val[KEY_SPEC_PROCEDURE_PARAMETERS][parameters.at(i)]));
    }
}
Пример #19
0
int RpcProtocolServer::ValidateRequest(const Json::Value& request)
{
    int error = 0;
    Procedure* proc;
    if (!(request.isMember(KEY_REQUEST_METHODNAME)
            && request.isMember(KEY_REQUEST_VERSION)
            && request.isMember(KEY_REQUEST_PARAMETERS)))
    {
        error = Errors::ERROR_RPC_INVALID_REQUEST;
    }
    else
    {
        map<string, Procedure*>::iterator it = procedures->find(request[KEY_REQUEST_METHODNAME].asString());
        if (it != this->procedures->end())
        {
            proc = (*this->procedures)[request[KEY_REQUEST_METHODNAME].asString()];
            if(request.isMember(KEY_REQUEST_ID) && proc->GetProcedureType() == RPC_NOTIFICATION)
            {
                error = Errors::ERROR_SERVER_PROCEDURE_IS_NOTIFICATION;
            }
            else if(!request.isMember(KEY_REQUEST_ID) && proc->GetProcedureType() == RPC_METHOD)
            {
                error = Errors::ERROR_SERVER_PROCEDURE_IS_METHOD;
            }
            else if (proc->ValdiateParameters(request[KEY_REQUEST_PARAMETERS]))
            {
                if (this->authManager != NULL)
                {
                    error = this->authManager->CheckPermission(
                                request[KEY_AUTHENTICATION],
                                proc->GetProcedureName());
                }
            }
            else
            {
                error = Errors::ERROR_RPC_INVALID_PARAMS;
            }
        }
        else
        {
            error = Errors::ERROR_RPC_METHOD_NOT_FOUND;
        }
    }
    return error;
}
    procedurelist_t *SpecificationParser::GetProceduresFromString(const string &content) throw(JsonRpcException)
    {

        Json::Reader reader;
        Json::Value val;
        if(!reader.parse(content,val)) {
            throw JsonRpcException(Errors::ERROR_RPC_JSON_PARSE_ERROR, " specification file contains syntax errors");
        }

        procedurelist_t* procedures = new procedurelist_t();
        Procedure* proc;
        for (unsigned int i = 0; i < val.size(); i++)
        {
            proc = GetProcedure(val[i]);
            (*procedures)[proc->GetProcedureName()] = proc;
        }
        return procedures;
    }
Пример #21
0
Compilation::Compilation(VM& vm, Procedure& proc, unsigned optLevel)
{
    CCallHelpers jit(&vm);
    generate(proc, jit, optLevel);
    LinkBuffer linkBuffer(vm, jit, nullptr);

    m_codeRef = FINALIZE_CODE(linkBuffer, ("B3::Compilation"));
    m_byproducts = proc.takeByproducts();
}
void        SpecificationWriter::procedureToJsonValue   (const Procedure &procedure, Json::Value &target)
{
    target[KEY_SPEC_PROCEDURE_NAME] = procedure.GetProcedureName();
    if(procedure.GetProcedureType() == RPC_METHOD)
    {
        target[KEY_SPEC_RETURN_TYPE] = toJsonLiteral(procedure.GetReturnType());
    }
    for(parameterNameList_t::const_iterator it = procedure.GetParameters().begin(); it != procedure.GetParameters().end(); ++it)
    {
        if(procedure.GetParameterDeclarationType() == PARAMS_BY_NAME)
        {
            target[KEY_SPEC_PROCEDURE_PARAMETERS][it->first] = toJsonLiteral(it->second);
        }
        else
        {
            target[KEY_SPEC_PROCEDURE_PARAMETERS].append(toJsonLiteral(it->second));
        }
    }
}
void                SpecificationParser::GetPositionalParameters(Json::Value &val, Procedure &result)
{
    //Positional parameters
    for (unsigned int i=0; i < val[KEY_SPEC_PROCEDURE_PARAMETERS].size(); i++)
    {
        stringstream paramname;
        paramname << "param" << (i+1);
        result.AddParameter(paramname.str(), toJsonType(val[KEY_SPEC_PROCEDURE_PARAMETERS][i]));
    }
}
Пример #24
0
Compilation compile(VM& vm, Procedure& proc, unsigned optLevel)
{
    TimingScope timingScope("Compilation");
    
    prepareForGeneration(proc, optLevel);
    
    CCallHelpers jit(&vm);
    generate(proc, jit);
    LinkBuffer linkBuffer(vm, jit, nullptr);

    return Compilation(FINALIZE_CODE(linkBuffer, ("B3::Compilation")), proc.releaseByproducts());
}
Пример #25
0
UseCounts::UseCounts(Procedure& procedure)
    : m_counts(procedure.values().size())
{
    Vector<Value*, 64> children;
    for (Value* value : procedure.values()) {
        children.shrink(0);
        for (Value* child : value->children()) {
            m_counts[child].numUses++;
            children.append(child);
        }
        std::sort(children.begin(), children.end());
        Value* last = nullptr;
        for (Value* child : children) {
            if (child == last)
                continue;

            m_counts[child].numUsingInstructions++;
            last = child;
        }
    }
}
Пример #26
0
bool ProcedureController::RemoveProcedure(const Procedure &procedure)
{
    if(!procedure.IsTemplateProcedure())
    {
        QSqlQuery procedureProjectDelete = GetDb().CreateQuery();
        procedureProjectDelete.prepare("DELETE FROM \"ProjectProcedure\" "
            "WHERE \"ProjectProcedureId\"=:projectProcedureId;");
        procedureProjectDelete.bindValue(":projectProcedureId", procedure.GetProjectProcedureId());
        if(!procedureProjectDelete.exec())
        {
            return false;
        }
    }

    QSqlQuery procedureDelete = GetDb().CreateQuery();
    procedureDelete.prepare("DELETE FROM \"Procedure\" "
        "WHERE \"ProcedureId\"=:procedureId;");
    procedureDelete.bindValue(":procedureId", procedure.GetProcedureId());
    if(!procedureDelete.exec())
    {
        return false;
    }

    ProcedureCacheKey key = GetCacheKey(procedure);
    auto removedProcedure = m_cache.Lookup(key);
    if(removedProcedure)
    {
        m_cache.Remove(key);

        emit sigProcedureRemoved(*removedProcedure);

        if(procedure.IsPureTemplateProcedure())
        {
            RemoveProjectProceduresOfTemplate(procedure.GetProcedureId());
        }
        return true;
    }

    return false;
}
Пример #27
0
void BasicBlock::removeNops(Procedure& procedure)
{
    unsigned sourceIndex = 0;
    unsigned targetIndex = 0;
    while (sourceIndex < size()) {
        Value* value = m_values[sourceIndex++];
        if (value->opcode() == Nop)
            procedure.deleteValue(value);
        else
            m_values[targetIndex++] = value;
    }
    m_values.resize(targetIndex);
}
SubmitPartialDecryptionDialog::SubmitPartialDecryptionDialog
(Client* client, Procedure proc, 
 QString user_id, QString password,
 QWidget *parent)
    : QDialog(parent), client(client), proc(proc), user_id(user_id), password(password)
{
    setAttribute(Qt::WA_DeleteOnClose);

    not_done = 2; // There are two things to get before enabled the submit button.

    connect(client, SIGNAL(got_cipher_sum(Client::Error, QString)),
            this, SLOT(got_cipher_sum(Client::Error, QString)));
    connect(client, SIGNAL(got_num_votes(Client::Error, int)),
            this, SLOT(got_num_votes(Client::Error, int)));
    connect(client, SIGNAL(sent_sum(Client::Error)),
            this, SLOT(sent_sum(Client::Error)));
    
    client->get_cipher_sum(proc.get_id().c_str());
    client->get_num_votes(proc.get_id().c_str());

    ui.setupUi(this);
}
Пример #29
0
string  CPPHelper::generateParameterDeclarationList (Procedure &proc)
{
    stringstream param_string;
    parameterNameList_t list = proc.GetParameters();
    for (parameterNameList_t::iterator it = list.begin(); it != list.end();)
    {
        param_string << toCppParamType(it->second) << " " << it->first;
        if (++it != list.end())
        {
            param_string << ", ";
        }
    }
    return param_string.str();
}
Пример #30
0
InvocationResponse ClientImpl::invoke(Procedure &proc) throw (voltdb::Exception, voltdb::NoConnectionsException, voltdb::UninitializedParamsException, voltdb::LibEventException) {
    if (m_bevs.empty()) {
        throw voltdb::NoConnectionsException();
    }
    int32_t messageSize = proc.getSerializedSize();
    ScopedByteBuffer sbb(messageSize);
    int64_t clientData = m_nextRequestId++;
    proc.serializeTo(&sbb, clientData);
    struct bufferevent *bev = m_bevs[m_nextConnectionIndex++ % m_bevs.size()];
    InvocationResponse response;
    boost::shared_ptr<ProcedureCallback> callback(new SyncCallback(&response));
    struct evbuffer *evbuf = bufferevent_get_output(bev);
    if (evbuffer_add(evbuf, sbb.bytes(), static_cast<size_t>(sbb.remaining()))) {
        throw voltdb::LibEventException();
    }
    m_outstandingRequests++;
    (*m_callbacks[bev])[clientData] = callback;
    if (event_base_dispatch(m_base) == -1) {
        throw voltdb::LibEventException();
    }
    m_loopBreakRequested = false;
    return response;
}