<commit_before>#include <string.h>
#include <v8.h>
#include <node.h>
#include <node_events.h>

#include "macros.h"
#include "database.h"
#include "statement.h"

using namespace node_sqlite3;

Persistent<FunctionTemplate> Database::constructor_template;

void Database::Init(Handle<Object> target) {
    HandleScope scope;

    Local<FunctionTemplate> t = FunctionTemplate::New(New);

    constructor_template = Persistent<FunctionTemplate>::New(t);
    constructor_template->Inherit(EventEmitter::constructor_template);
    constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
    constructor_template->SetClassName(String::NewSymbol("Database"));

    NODE_SET_PROTOTYPE_METHOD(constructor_template, "close", Close);
    NODE_SET_PROTOTYPE_METHOD(constructor_template, "exec", Exec);
    NODE_SET_PROTOTYPE_METHOD(constructor_template, "serialize", Serialize);
    NODE_SET_PROTOTYPE_METHOD(constructor_template, "parallelize", Parallelize);
    NODE_SET_PROTOTYPE_METHOD(constructor_template, "configure", Configure);

    target->Set(String::NewSymbol("Database"),
        constructor_template->GetFunction());
}

void Database::Process() {
    if (!open && locked && !queue.empty()) {
        EXCEPTION(String::New("Database handle is closed"), SQLITE_MISUSE, exception);
        Local<Value> argv[] = { exception };
        bool called = false;

        // Call all callbacks with the error object.
        while (!queue.empty()) {
            Call* call = queue.front();
            if (!call->baton->callback.IsEmpty() && call->baton->callback->IsFunction()) {
                TRY_CATCH_CALL(handle_, call->baton->callback, 1, argv);
                called = true;
            }
            queue.pop();
            // We don't call the actual callback, so we have to make sure that
            // the baton gets destroyed.
            delete call->baton;
            delete call;
        }

        // When we couldn't call a callback function, emit an error on the
        // Database object.
        if (!called) {
            Local<Value> args[] = { String::NewSymbol("error"), exception };
            EMIT_EVENT(handle_, 2, args);
        }
        return;
    }

    while (open && (!locked || pending == 0) && !queue.empty()) {
        Call* call = queue.front();

        if (call->exclusive && pending > 0) {
            break;
        }

        queue.pop();
        locked = call->exclusive;
        call->callback(call->baton);
        delete call;

        if (locked) break;
    }
}

void Database::Schedule(EIO_Callback callback, Baton* baton, bool exclusive) {
    if (!open && locked) {
        EXCEPTION(String::New("Database is closed"), SQLITE_MISUSE, exception);
        if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
            Local<Value> argv[] = { exception };
            TRY_CATCH_CALL(handle_, baton->callback, 1, argv);
        }
        else {
            Local<Value> argv[] = { String::NewSymbol("error"), exception };
            EMIT_EVENT(handle_, 2, argv);
        }
        return;
    }

    if (!open || ((locked || exclusive || serialize) && pending > 0)) {
        queue.push(new Call(callback, baton, exclusive || serialize));
    }
    else {
        locked = exclusive;
        callback(baton);
    }
}

Handle<Value> Database::New(const Arguments& args) {
    HandleScope scope;

    if (!Database::HasInstance(args.This())) {
        return ThrowException(Exception::TypeError(
            String::New("Use the new operator to create new Database objects"))
        );
    }

    REQUIRE_ARGUMENT_STRING(0, filename);
    int pos = 1;

    int mode = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
    if (args.Length() >= pos && args[pos]->IsInt32()) {
        mode = args[pos++]->Int32Value();
    }

    Local<Function> callback;
    if (args.Length() >= pos && args[pos]->IsFunction()) {
        callback = Local<Function>::Cast(args[pos++]);
    }

    Database* db = new Database();
    db->Wrap(args.This());

    args.This()->Set(String::NewSymbol("filename"), args[0]->ToString(), ReadOnly);
    args.This()->Set(String::NewSymbol("mode"), Integer::New(mode), ReadOnly);

    // Start opening the database.
    OpenBaton* baton = new OpenBaton(db, callback, *filename, SQLITE_OPEN_FULLMUTEX | mode);
    EIO_BeginOpen(baton);

    return args.This();
}

void Database::EIO_BeginOpen(Baton* baton) {
    eio_custom(EIO_Open, EIO_PRI_DEFAULT, EIO_AfterOpen, baton);
}

int Database::EIO_Open(eio_req *req) {
    OpenBaton* baton = static_cast<OpenBaton*>(req->data);
    Database* db = baton->db;

    baton->status = sqlite3_open_v2(
        baton->filename.c_str(),
        &db->handle,
        baton->mode,
        NULL
    );

    if (baton->status != SQLITE_OK) {
        baton->message = std::string(sqlite3_errmsg(db->handle));
        sqlite3_close(db->handle);
        db->handle = NULL;
    }

    return 0;
}

int Database::EIO_AfterOpen(eio_req *req) {
    HandleScope scope;
    OpenBaton* baton = static_cast<OpenBaton*>(req->data);
    Database* db = baton->db;

    Local<Value> argv[1];
    if (baton->status != SQLITE_OK) {
        EXCEPTION(String::New(baton->message.c_str()), baton->status, exception);
        argv[0] = exception;
    }
    else {
        db->open = true;
        argv[0] = Local<Value>::New(Null());
    }

    if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
        TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv);
    }
    else if (!db->open) {
        Local<Value> args[] = { String::NewSymbol("error"), argv[0] };
        EMIT_EVENT(db->handle_, 2, args);
    }

    if (db->open) {
        Local<Value> args[] = { String::NewSymbol("open") };
        EMIT_EVENT(db->handle_, 1, args);
        db->Process();
    }

    delete baton;
    return 0;
}

Handle<Value> Database::Close(const Arguments& args) {
    HandleScope scope;
    Database* db = ObjectWrap::Unwrap<Database>(args.This());
    OPTIONAL_ARGUMENT_FUNCTION(0, callback);

    Baton* baton = new Baton(db, callback);
    db->Schedule(EIO_BeginClose, baton, true);

    return args.This();
}

void Database::EIO_BeginClose(Baton* baton) {
    assert(baton->db->locked);
    assert(baton->db->open);
    assert(baton->db->handle);
    assert(baton->db->pending == 0);
    eio_custom(EIO_Close, EIO_PRI_DEFAULT, EIO_AfterClose, baton);
}

int Database::EIO_Close(eio_req *req) {
    Baton* baton = static_cast<Baton*>(req->data);
    Database* db = baton->db;

    baton->status = sqlite3_close(db->handle);

    if (baton->status != SQLITE_OK) {
        baton->message = std::string(sqlite3_errmsg(db->handle));
    }
    else {
        db->handle = NULL;
    }
    return 0;
}

int Database::EIO_AfterClose(eio_req *req) {
    HandleScope scope;
    Baton* baton = static_cast<Baton*>(req->data);
    Database* db = baton->db;

    Local<Value> argv[1];
    if (baton->status != SQLITE_OK) {
        EXCEPTION(String::New(baton->message.c_str()), baton->status, exception);
        argv[0] = exception;
    }
    else {
        db->open = false;
        // Leave db->locked to indicate that this db object has reached
        // the end of its life.
        argv[0] = Local<Value>::New(Null());
    }

    // Fire callbacks.
    if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
        TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv);
    }
    else if (db->open) {
        Local<Value> args[] = { String::NewSymbol("error"), argv[0] };
        EMIT_EVENT(db->handle_, 2, args);
    }

    assert(baton->db->locked);
    assert(!baton->db->open);
    assert(!baton->db->handle);
    assert(baton->db->pending == 0);

    if (!db->open) {
        Local<Value> args[] = { String::NewSymbol("close"), argv[0] };
        EMIT_EVENT(db->handle_, 1, args);
        db->Process();
    }

    delete baton;
    return 0;
}

Handle<Value> Database::Serialize(const Arguments& args) {
    HandleScope scope;
    Database* db = ObjectWrap::Unwrap<Database>(args.This());
    OPTIONAL_ARGUMENT_FUNCTION(0, callback);

    bool before = db->serialize;
    db->serialize = true;

    if (!callback.IsEmpty() && callback->IsFunction()) {
        TRY_CATCH_CALL(args.This(), callback, 0, NULL);
        db->serialize = before;
    }

    db->Process();

    return args.This();
}

Handle<Value> Database::Parallelize(const Arguments& args) {
    HandleScope scope;
    Database* db = ObjectWrap::Unwrap<Database>(args.This());
    OPTIONAL_ARGUMENT_FUNCTION(0, callback);

    bool before = db->serialize;
    db->serialize = false;

    if (!callback.IsEmpty() && callback->IsFunction()) {
        TRY_CATCH_CALL(args.This(), callback, 0, NULL);
        db->serialize = before;
    }

    db->Process();

    return args.This();
}

Handle<Value> Database::Configure(const Arguments& args) {
    HandleScope scope;
    Database* db = ObjectWrap::Unwrap<Database>(args.This());

    REQUIRE_ARGUMENTS(2);

    if (args[0]->Equals(String::NewSymbol("trace"))) {
        Local<Function> handle;
        Baton* baton = new Baton(db, handle);
        db->Schedule(RegisterTraceCallback, baton);
    }
    else {
        ThrowException(Exception::Error(String::Concat(
            args[0]->ToString(),
            String::NewSymbol(" is not a valid configuration option")
        )));
    }

    return args.This();
}

void Database::RegisterTraceCallback(Baton* baton) {
    assert(baton->db->open);
    assert(baton->db->handle);
    Database* db = baton->db;

    if (db->debug_trace == NULL) {
        // Add it.
        db->debug_trace = new AsyncTrace(db, TraceCallback);
        sqlite3_trace(db->handle, TraceCallback, db);
    }
    else {
        // Remove it.
        sqlite3_trace(db->handle, NULL, NULL);
        delete db->debug_trace;
        db->debug_trace = NULL;
    }

    delete baton;
}

void Database::TraceCallback(void* db, const char* sql) {
    // Note: This function is called in the thread pool.
    // Note: Some queries, such as "EXPLAIN" queries, are not sent through this.
    static_cast<Database*>(db)->debug_trace->send(std::string(sql));
}

void Database::TraceCallback(EV_P_ ev_async *w, int revents) {
    // Note: This function is called in the main V8 thread.
    HandleScope scope;
    AsyncTrace* async = static_cast<AsyncTrace*>(w->data);

    std::vector<std::string> queries = async->get();
    for (int i = 0; i < queries.size(); i++) {
        Local<Value> argv[] = {
            String::NewSymbol("trace"),
            String::New(queries[i].c_str())
        };
        EMIT_EVENT(async->parent->handle_, 2, argv);
    }
    queries.clear();
}

Handle<Value> Database::Exec(const Arguments& args) {
    HandleScope scope;
    Database* db = ObjectWrap::Unwrap<Database>(args.This());

    REQUIRE_ARGUMENT_STRING(0, sql);
    OPTIONAL_ARGUMENT_FUNCTION(1, callback);

    Baton* baton = new ExecBaton(db, callback, *sql);
    db->Schedule(EIO_BeginExec, baton, true);

    return args.This();
}

void Database::EIO_BeginExec(Baton* baton) {
    assert(baton->db->locked);
    assert(baton->db->open);
    assert(baton->db->handle);
    assert(baton->db->pending == 0);
    eio_custom(EIO_Exec, EIO_PRI_DEFAULT, EIO_AfterExec, baton);
}

int Database::EIO_Exec(eio_req *req) {
    ExecBaton* baton = static_cast<ExecBaton*>(req->data);

    char* message = NULL;
    baton->status = sqlite3_exec(
        baton->db->handle,
        baton->sql.c_str(),
        NULL,
        NULL,
        &message
    );

    if (baton->status != SQLITE_OK && message != NULL) {
        baton->message = std::string(message);
        sqlite3_free(message);
    }

    return 0;
}

int Database::EIO_AfterExec(eio_req *req) {
    HandleScope scope;
    ExecBaton* baton = static_cast<ExecBaton*>(req->data);
    Database* db = baton->db;

    if (baton->status != SQLITE_OK) {
        EXCEPTION(String::New(baton->message.c_str()), baton->status, exception);

        if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
            Local<Value> argv[] = { exception };
            TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv);
        }
        else {
            Local<Value> args[] = { String::NewSymbol("error"), exception };
            EMIT_EVENT(db->handle_, 2, args);
        }
    }
    else if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
        Local<Value> argv[] = { Local<Value>::New(Null()) };
        TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv);
    }

    db->Process();

    delete baton;
    return 0;
}

/**
 * Override this so that we can properly close the database when this object
 * gets garbage collected.
 */
void Database::Wrap(Handle<Object> handle) {
    assert(handle_.IsEmpty());
    assert(handle->InternalFieldCount() > 0);
    handle_ = Persistent<Object>::New(handle);
    handle_->SetPointerInInternalField(0, this);
    handle_.MakeWeak(this, Destruct);
}

inline void Database::MakeWeak (void) {
    handle_.MakeWeak(this, Destruct);
}

void Database::Unref() {
    assert(!handle_.IsEmpty());
    assert(!handle_.IsWeak());
    assert(refs_ > 0);
    if (--refs_ == 0) { MakeWeak(); }
}

void Database::Destruct(Persistent<Value> value, void *data) {
    Database* db = static_cast<Database*>(data);
    if (db->handle) {
        eio_custom(EIO_Destruct, EIO_PRI_DEFAULT, EIO_AfterDestruct, db);
        ev_ref(EV_DEFAULT_UC);
    }
    else {
        delete db;
    }
}

int Database::EIO_Destruct(eio_req *req) {
    Database* db = static_cast<Database*>(req->data);

    sqlite3_close(db->handle);
    db->handle = NULL;

    return 0;
}

int Database::EIO_AfterDestruct(eio_req *req) {
    Database* db = static_cast<Database*>(req->data);
    ev_unref(EV_DEFAULT_UC);
    delete db;
    return 0;
}
<commit_msg>make sure that the async handler is properly stopped when the database is closed or destructed<commit_after>#include <string.h>
#include <v8.h>
#include <node.h>
#include <node_events.h>

#include "macros.h"
#include "database.h"
#include "statement.h"

using namespace node_sqlite3;

Persistent<FunctionTemplate> Database::constructor_template;

void Database::Init(Handle<Object> target) {
    HandleScope scope;

    Local<FunctionTemplate> t = FunctionTemplate::New(New);

    constructor_template = Persistent<FunctionTemplate>::New(t);
    constructor_template->Inherit(EventEmitter::constructor_template);
    constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
    constructor_template->SetClassName(String::NewSymbol("Database"));

    NODE_SET_PROTOTYPE_METHOD(constructor_template, "close", Close);
    NODE_SET_PROTOTYPE_METHOD(constructor_template, "exec", Exec);
    NODE_SET_PROTOTYPE_METHOD(constructor_template, "serialize", Serialize);
    NODE_SET_PROTOTYPE_METHOD(constructor_template, "parallelize", Parallelize);
    NODE_SET_PROTOTYPE_METHOD(constructor_template, "configure", Configure);

    target->Set(String::NewSymbol("Database"),
        constructor_template->GetFunction());
}

void Database::Process() {
    if (!open && locked && !queue.empty()) {
        EXCEPTION(String::New("Database handle is closed"), SQLITE_MISUSE, exception);
        Local<Value> argv[] = { exception };
        bool called = false;

        // Call all callbacks with the error object.
        while (!queue.empty()) {
            Call* call = queue.front();
            if (!call->baton->callback.IsEmpty() && call->baton->callback->IsFunction()) {
                TRY_CATCH_CALL(handle_, call->baton->callback, 1, argv);
                called = true;
            }
            queue.pop();
            // We don't call the actual callback, so we have to make sure that
            // the baton gets destroyed.
            delete call->baton;
            delete call;
        }

        // When we couldn't call a callback function, emit an error on the
        // Database object.
        if (!called) {
            Local<Value> args[] = { String::NewSymbol("error"), exception };
            EMIT_EVENT(handle_, 2, args);
        }
        return;
    }

    while (open && (!locked || pending == 0) && !queue.empty()) {
        Call* call = queue.front();

        if (call->exclusive && pending > 0) {
            break;
        }

        queue.pop();
        locked = call->exclusive;
        call->callback(call->baton);
        delete call;

        if (locked) break;
    }
}

void Database::Schedule(EIO_Callback callback, Baton* baton, bool exclusive) {
    if (!open && locked) {
        EXCEPTION(String::New("Database is closed"), SQLITE_MISUSE, exception);
        if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
            Local<Value> argv[] = { exception };
            TRY_CATCH_CALL(handle_, baton->callback, 1, argv);
        }
        else {
            Local<Value> argv[] = { String::NewSymbol("error"), exception };
            EMIT_EVENT(handle_, 2, argv);
        }
        return;
    }

    if (!open || ((locked || exclusive || serialize) && pending > 0)) {
        queue.push(new Call(callback, baton, exclusive || serialize));
    }
    else {
        locked = exclusive;
        callback(baton);
    }
}

Handle<Value> Database::New(const Arguments& args) {
    HandleScope scope;

    if (!Database::HasInstance(args.This())) {
        return ThrowException(Exception::TypeError(
            String::New("Use the new operator to create new Database objects"))
        );
    }

    REQUIRE_ARGUMENT_STRING(0, filename);
    int pos = 1;

    int mode = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
    if (args.Length() >= pos && args[pos]->IsInt32()) {
        mode = args[pos++]->Int32Value();
    }

    Local<Function> callback;
    if (args.Length() >= pos && args[pos]->IsFunction()) {
        callback = Local<Function>::Cast(args[pos++]);
    }

    Database* db = new Database();
    db->Wrap(args.This());

    args.This()->Set(String::NewSymbol("filename"), args[0]->ToString(), ReadOnly);
    args.This()->Set(String::NewSymbol("mode"), Integer::New(mode), ReadOnly);

    // Start opening the database.
    OpenBaton* baton = new OpenBaton(db, callback, *filename, SQLITE_OPEN_FULLMUTEX | mode);
    EIO_BeginOpen(baton);

    return args.This();
}

void Database::EIO_BeginOpen(Baton* baton) {
    eio_custom(EIO_Open, EIO_PRI_DEFAULT, EIO_AfterOpen, baton);
}

int Database::EIO_Open(eio_req *req) {
    OpenBaton* baton = static_cast<OpenBaton*>(req->data);
    Database* db = baton->db;

    baton->status = sqlite3_open_v2(
        baton->filename.c_str(),
        &db->handle,
        baton->mode,
        NULL
    );

    if (baton->status != SQLITE_OK) {
        baton->message = std::string(sqlite3_errmsg(db->handle));
        sqlite3_close(db->handle);
        db->handle = NULL;
    }

    return 0;
}

int Database::EIO_AfterOpen(eio_req *req) {
    HandleScope scope;
    OpenBaton* baton = static_cast<OpenBaton*>(req->data);
    Database* db = baton->db;

    Local<Value> argv[1];
    if (baton->status != SQLITE_OK) {
        EXCEPTION(String::New(baton->message.c_str()), baton->status, exception);
        argv[0] = exception;
    }
    else {
        db->open = true;
        argv[0] = Local<Value>::New(Null());
    }

    if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
        TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv);
    }
    else if (!db->open) {
        Local<Value> args[] = { String::NewSymbol("error"), argv[0] };
        EMIT_EVENT(db->handle_, 2, args);
    }

    if (db->open) {
        Local<Value> args[] = { String::NewSymbol("open") };
        EMIT_EVENT(db->handle_, 1, args);
        db->Process();
    }

    delete baton;
    return 0;
}

Handle<Value> Database::Close(const Arguments& args) {
    HandleScope scope;
    Database* db = ObjectWrap::Unwrap<Database>(args.This());
    OPTIONAL_ARGUMENT_FUNCTION(0, callback);

    Baton* baton = new Baton(db, callback);
    db->Schedule(EIO_BeginClose, baton, true);

    return args.This();
}

void Database::EIO_BeginClose(Baton* baton) {
    assert(baton->db->locked);
    assert(baton->db->open);
    assert(baton->db->handle);
    assert(baton->db->pending == 0);
    eio_custom(EIO_Close, EIO_PRI_DEFAULT, EIO_AfterClose, baton);
}

int Database::EIO_Close(eio_req *req) {
    Baton* baton = static_cast<Baton*>(req->data);
    Database* db = baton->db;

    if (db->debug_trace) {
        delete db->debug_trace;
        db->debug_trace = NULL;
    }

    baton->status = sqlite3_close(db->handle);

    if (baton->status != SQLITE_OK) {
        baton->message = std::string(sqlite3_errmsg(db->handle));
    }
    else {
        db->handle = NULL;
    }
    return 0;
}

int Database::EIO_AfterClose(eio_req *req) {
    HandleScope scope;
    Baton* baton = static_cast<Baton*>(req->data);
    Database* db = baton->db;

    Local<Value> argv[1];
    if (baton->status != SQLITE_OK) {
        EXCEPTION(String::New(baton->message.c_str()), baton->status, exception);
        argv[0] = exception;
    }
    else {
        db->open = false;
        // Leave db->locked to indicate that this db object has reached
        // the end of its life.
        argv[0] = Local<Value>::New(Null());
    }

    // Fire callbacks.
    if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
        TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv);
    }
    else if (db->open) {
        Local<Value> args[] = { String::NewSymbol("error"), argv[0] };
        EMIT_EVENT(db->handle_, 2, args);
    }

    assert(baton->db->locked);
    assert(!baton->db->open);
    assert(!baton->db->handle);
    assert(baton->db->pending == 0);

    if (!db->open) {
        Local<Value> args[] = { String::NewSymbol("close"), argv[0] };
        EMIT_EVENT(db->handle_, 1, args);
        db->Process();
    }

    delete baton;
    return 0;
}

Handle<Value> Database::Serialize(const Arguments& args) {
    HandleScope scope;
    Database* db = ObjectWrap::Unwrap<Database>(args.This());
    OPTIONAL_ARGUMENT_FUNCTION(0, callback);

    bool before = db->serialize;
    db->serialize = true;

    if (!callback.IsEmpty() && callback->IsFunction()) {
        TRY_CATCH_CALL(args.This(), callback, 0, NULL);
        db->serialize = before;
    }

    db->Process();

    return args.This();
}

Handle<Value> Database::Parallelize(const Arguments& args) {
    HandleScope scope;
    Database* db = ObjectWrap::Unwrap<Database>(args.This());
    OPTIONAL_ARGUMENT_FUNCTION(0, callback);

    bool before = db->serialize;
    db->serialize = false;

    if (!callback.IsEmpty() && callback->IsFunction()) {
        TRY_CATCH_CALL(args.This(), callback, 0, NULL);
        db->serialize = before;
    }

    db->Process();

    return args.This();
}

Handle<Value> Database::Configure(const Arguments& args) {
    HandleScope scope;
    Database* db = ObjectWrap::Unwrap<Database>(args.This());

    REQUIRE_ARGUMENTS(2);

    if (args[0]->Equals(String::NewSymbol("trace"))) {
        Local<Function> handle;
        Baton* baton = new Baton(db, handle);
        db->Schedule(RegisterTraceCallback, baton);
    }
    else {
        ThrowException(Exception::Error(String::Concat(
            args[0]->ToString(),
            String::NewSymbol(" is not a valid configuration option")
        )));
    }

    return args.This();
}

void Database::RegisterTraceCallback(Baton* baton) {
    assert(baton->db->open);
    assert(baton->db->handle);
    Database* db = baton->db;

    if (db->debug_trace == NULL) {
        // Add it.
        db->debug_trace = new AsyncTrace(db, TraceCallback);
        sqlite3_trace(db->handle, TraceCallback, db);
    }
    else {
        // Remove it.
        sqlite3_trace(db->handle, NULL, NULL);
        delete db->debug_trace;
        db->debug_trace = NULL;
    }

    delete baton;
}

void Database::TraceCallback(void* db, const char* sql) {
    // Note: This function is called in the thread pool.
    // Note: Some queries, such as "EXPLAIN" queries, are not sent through this.
    static_cast<Database*>(db)->debug_trace->send(std::string(sql));
}

void Database::TraceCallback(EV_P_ ev_async *w, int revents) {
    // Note: This function is called in the main V8 thread.
    HandleScope scope;
    AsyncTrace* async = static_cast<AsyncTrace*>(w->data);

    std::vector<std::string> queries = async->get();
    for (int i = 0; i < queries.size(); i++) {
        Local<Value> argv[] = {
            String::NewSymbol("trace"),
            String::New(queries[i].c_str())
        };
        EMIT_EVENT(async->parent->handle_, 2, argv);
    }
    queries.clear();
}

Handle<Value> Database::Exec(const Arguments& args) {
    HandleScope scope;
    Database* db = ObjectWrap::Unwrap<Database>(args.This());

    REQUIRE_ARGUMENT_STRING(0, sql);
    OPTIONAL_ARGUMENT_FUNCTION(1, callback);

    Baton* baton = new ExecBaton(db, callback, *sql);
    db->Schedule(EIO_BeginExec, baton, true);

    return args.This();
}

void Database::EIO_BeginExec(Baton* baton) {
    assert(baton->db->locked);
    assert(baton->db->open);
    assert(baton->db->handle);
    assert(baton->db->pending == 0);
    eio_custom(EIO_Exec, EIO_PRI_DEFAULT, EIO_AfterExec, baton);
}

int Database::EIO_Exec(eio_req *req) {
    ExecBaton* baton = static_cast<ExecBaton*>(req->data);

    char* message = NULL;
    baton->status = sqlite3_exec(
        baton->db->handle,
        baton->sql.c_str(),
        NULL,
        NULL,
        &message
    );

    if (baton->status != SQLITE_OK && message != NULL) {
        baton->message = std::string(message);
        sqlite3_free(message);
    }

    return 0;
}

int Database::EIO_AfterExec(eio_req *req) {
    HandleScope scope;
    ExecBaton* baton = static_cast<ExecBaton*>(req->data);
    Database* db = baton->db;

    if (baton->status != SQLITE_OK) {
        EXCEPTION(String::New(baton->message.c_str()), baton->status, exception);

        if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
            Local<Value> argv[] = { exception };
            TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv);
        }
        else {
            Local<Value> args[] = { String::NewSymbol("error"), exception };
            EMIT_EVENT(db->handle_, 2, args);
        }
    }
    else if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
        Local<Value> argv[] = { Local<Value>::New(Null()) };
        TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv);
    }

    db->Process();

    delete baton;
    return 0;
}

/**
 * Override this so that we can properly close the database when this object
 * gets garbage collected.
 */
void Database::Wrap(Handle<Object> handle) {
    assert(handle_.IsEmpty());
    assert(handle->InternalFieldCount() > 0);
    handle_ = Persistent<Object>::New(handle);
    handle_->SetPointerInInternalField(0, this);
    handle_.MakeWeak(this, Destruct);
}

inline void Database::MakeWeak (void) {
    handle_.MakeWeak(this, Destruct);
}

void Database::Unref() {
    assert(!handle_.IsEmpty());
    assert(!handle_.IsWeak());
    assert(refs_ > 0);
    if (--refs_ == 0) { MakeWeak(); }
}

void Database::Destruct(Persistent<Value> value, void *data) {
    Database* db = static_cast<Database*>(data);
    if (db->handle) {
        eio_custom(EIO_Destruct, EIO_PRI_DEFAULT, EIO_AfterDestruct, db);
        ev_ref(EV_DEFAULT_UC);
    }
    else {
        delete db;
    }
}

int Database::EIO_Destruct(eio_req *req) {
    Database* db = static_cast<Database*>(req->data);

    if (db->debug_trace) {
        delete db->debug_trace;
        db->debug_trace = NULL;
    }

    sqlite3_close(db->handle);
    db->handle = NULL;

    return 0;
}

int Database::EIO_AfterDestruct(eio_req *req) {
    Database* db = static_cast<Database*>(req->data);
    ev_unref(EV_DEFAULT_UC);
    delete db;
    return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#include "gtest/gtest.h"
#include "core/eager/ort_kernel_invoker.h"
#include "core/common/logging/sinks/clog_sink.h"
#include "core/providers/cpu/cpu_execution_provider.h"
#include "test/framework/test_utils.h"

namespace onnxruntime {
namespace test {

TEST(InvokerTest, Basic) {
  std::unique_ptr<IExecutionProvider> cpu_execution_provider = onnxruntime::make_unique<CPUExecutionProvider>(CPUExecutionProviderInfo(false));
  const std::string logger_id{"InvokerTest"};
  auto logging_manager = onnxruntime::make_unique<logging::LoggingManager>(
      std::unique_ptr<logging::ISink>{new logging::CLogSink{}},
      logging::Severity::kVERBOSE, false,
      logging::LoggingManager::InstanceType::Default,
      &logger_id);
  std::unique_ptr<Environment> env;
  Environment::Create(std::move(logging_manager), env);
  ORTInvoker kernel_invoker(std::move(cpu_execution_provider), env->GetLoggingManager()->DefaultLogger());

  std::vector<int64_t> dims_mul_x = {3, 2};
  std::vector<float> values_mul_x = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
  OrtValue A, B;
  CreateMLValue<float>(kernel_invoker.GetCurrentExecutionProvider().GetAllocator(0, OrtMemTypeDefault), dims_mul_x, values_mul_x,
                       &A);
  CreateMLValue<float>(kernel_invoker.GetCurrentExecutionProvider().GetAllocator(0, OrtMemTypeDefault), dims_mul_x, values_mul_x,
                       &B);
  std::vector<OrtValue> result(1);
  auto status = kernel_invoker.Invoke("Add", {A, B}, result, nullptr);
  ASSERT_TRUE(status.IsOK());
  const Tensor& C = result.back().Get<Tensor>();
  auto& c_shape = C.Shape();
  EXPECT_EQ(c_shape.GetDims(), dims_mul_x);

  std::vector<float> expected_result = {2.0f, 4.0f, 6.0f, 8.0f, 10.0f, 12.0f};
  auto* c_data = C.Data<float>();
  for (auto i = 0; i < c_shape.Size(); ++i) {
    EXPECT_EQ(c_data[i], expected_result[i]);
  }
}

TEST(InvokerTest, Inplace) {
  std::unique_ptr<IExecutionProvider> cpu_execution_provider = onnxruntime::make_unique<CPUExecutionProvider>(CPUExecutionProviderInfo(false));
  const std::string logger_id{"InvokerTest"};
  auto logging_manager = onnxruntime::make_unique<logging::LoggingManager>(
      std::unique_ptr<logging::ISink>{new logging::CLogSink{}},
      logging::Severity::kVERBOSE, false,
      logging::LoggingManager::InstanceType::Default,
      &logger_id);
  std::unique_ptr<Environment> env;
  Environment::Create(std::move(logging_manager), env);
  ORTInvoker kernel_invoker(std::move(cpu_execution_provider), env->GetLoggingManager()->DefaultLogger());

  std::vector<int64_t> dims_mul_x = {3, 2};
  std::vector<float> values_mul_x = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
  OrtValue A, B;
  CreateMLValue<float>(kernel_invoker.GetCurrentExecutionProvider().GetAllocator(0, OrtMemTypeDefault), dims_mul_x, values_mul_x,
                       &A);
  CreateMLValue<float>(kernel_invoker.GetCurrentExecutionProvider().GetAllocator(0, OrtMemTypeDefault), dims_mul_x, values_mul_x,
                       &B);
  std::vector<OrtValue> result;
  result.push_back(A);
  auto status = kernel_invoker.Invoke("Add", {A, B}, result, nullptr);

  std::vector<float> expected_result = {2.0f, 4.0f, 6.0f, 8.0f, 10.0f, 12.0f};
  auto* a_data = A.Get<Tensor>().Data<float>();
  for (size_t i = 0; i < expected_result.size(); ++i) {
    EXPECT_EQ(a_data[i], expected_result[i]);
  }
}

}  // namespace test
}  // namespace onnxruntime
<commit_msg>fix broken tests (#7909)<commit_after>// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#include "gtest/gtest.h"
#include "core/eager/ort_kernel_invoker.h"
#include "core/common/logging/sinks/clog_sink.h"
#include "core/providers/cpu/cpu_execution_provider.h"
#include "test/framework/test_utils.h"

namespace onnxruntime {
namespace test {

TEST(InvokerTest, Basic) {
  std::unique_ptr<IExecutionProvider> cpu_execution_provider = std::make_unique<CPUExecutionProvider>(CPUExecutionProviderInfo(false));
  const std::string logger_id{"InvokerTest"};
  auto logging_manager = std::make_unique<logging::LoggingManager>(
      std::unique_ptr<logging::ISink>{new logging::CLogSink{}},
      logging::Severity::kVERBOSE, false,
      logging::LoggingManager::InstanceType::Default,
      &logger_id);
  std::unique_ptr<Environment> env;
  Environment::Create(std::move(logging_manager), env);
  ORTInvoker kernel_invoker(std::move(cpu_execution_provider), env->GetLoggingManager()->DefaultLogger());

  std::vector<int64_t> dims_mul_x = {3, 2};
  std::vector<float> values_mul_x = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
  OrtValue A, B;
  CreateMLValue<float>(kernel_invoker.GetCurrentExecutionProvider().GetAllocator(0, OrtMemTypeDefault), dims_mul_x, values_mul_x,
                       &A);
  CreateMLValue<float>(kernel_invoker.GetCurrentExecutionProvider().GetAllocator(0, OrtMemTypeDefault), dims_mul_x, values_mul_x,
                       &B);
  std::vector<OrtValue> result(1);
  auto status = kernel_invoker.Invoke("Add", {A, B}, result, nullptr);
  ASSERT_TRUE(status.IsOK());
  const Tensor& C = result.back().Get<Tensor>();
  auto& c_shape = C.Shape();
  EXPECT_EQ(c_shape.GetDims(), dims_mul_x);

  std::vector<float> expected_result = {2.0f, 4.0f, 6.0f, 8.0f, 10.0f, 12.0f};
  auto* c_data = C.Data<float>();
  for (auto i = 0; i < c_shape.Size(); ++i) {
    EXPECT_EQ(c_data[i], expected_result[i]);
  }
}

TEST(InvokerTest, Inplace) {
  std::unique_ptr<IExecutionProvider> cpu_execution_provider = std::make_unique<CPUExecutionProvider>(CPUExecutionProviderInfo(false));
  const std::string logger_id{"InvokerTest"};
  auto logging_manager = std::make_unique<logging::LoggingManager>(
      std::unique_ptr<logging::ISink>{new logging::CLogSink{}},
      logging::Severity::kVERBOSE, false,
      logging::LoggingManager::InstanceType::Default,
      &logger_id);
  std::unique_ptr<Environment> env;
  Environment::Create(std::move(logging_manager), env);
  ORTInvoker kernel_invoker(std::move(cpu_execution_provider), env->GetLoggingManager()->DefaultLogger());

  std::vector<int64_t> dims_mul_x = {3, 2};
  std::vector<float> values_mul_x = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
  OrtValue A, B;
  CreateMLValue<float>(kernel_invoker.GetCurrentExecutionProvider().GetAllocator(0, OrtMemTypeDefault), dims_mul_x, values_mul_x,
                       &A);
  CreateMLValue<float>(kernel_invoker.GetCurrentExecutionProvider().GetAllocator(0, OrtMemTypeDefault), dims_mul_x, values_mul_x,
                       &B);
  std::vector<OrtValue> result;
  result.push_back(A);
  auto status = kernel_invoker.Invoke("Add", {A, B}, result, nullptr);

  std::vector<float> expected_result = {2.0f, 4.0f, 6.0f, 8.0f, 10.0f, 12.0f};
  auto* a_data = A.Get<Tensor>().Data<float>();
  for (size_t i = 0; i < expected_result.size(); ++i) {
    EXPECT_EQ(a_data[i], expected_result[i]);
  }
}

}  // namespace test
}  // namespace onnxruntime
<|endoftext|>


<commit_before>/*
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * 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.
 */
#if !defined(XALANMEMMGRAUTOPTR_HEADER_GUARD_1357924680)
#define XALANMEMMGRAUTOPTR_HEADER_GUARD_1357924680

// Base include file.  Must be first.
#include <xalanc/PlatformSupport/PlatformSupportDefinitions.hpp>

#include <xalanc/Include/XalanMemoryManagement.hpp>

#include <cstddef>

#include <cassert>

#include <utility>

XALAN_CPP_NAMESPACE_BEGIN

// We're using our own auto_ptr-like class due to wide
// variations amongst the varous platforms we have to
// support
template<	class	Type,
			bool	toCallDestructor = true>
class XalanMemMgrAutoPtr
{
public:

	typedef XALAN_STD_QUALIFIER pair<MemoryManagerType*, Type*> AutoPtrPairType;

	class MemMgrAutoPtrData : public AutoPtrPairType
	{
	public:
		MemMgrAutoPtrData():
			AutoPtrPairType(0,0)
		{
		}

		MemMgrAutoPtrData(
			MemoryManagerType* memoryManager,
			Type* dataPointer):
			AutoPtrPairType(memoryManager, dataPointer)
		{
			invariants();
		}

		bool
		isInitilized()const
		{
			return ( (this->first != 0) && (this->second != 0) )? true : false;
		}

		void
		deallocate()
		{
			invariants();

			if ( isInitilized() )
			{
				if ( toCallDestructor )
				{
					this->second->~Type();
				}

				this->first->deallocate(this->second);
			}
		}

		void
		reset(	MemoryManagerType* m_memoryManager ,
				Type*	m_dataPointer )
		{
			invariants();

			this->first = m_memoryManager;

			this->second = m_dataPointer;

			invariants();
		}
	private:
		void
		invariants()const
		{
			assert( isInitilized() ||
					( (this->first == 0) && (this->second ==0) ) );
		}

	};

	XalanMemMgrAutoPtr(
			MemoryManagerType&  theManager,
			Type* ptr  ) :
		m_pointerInfo(&theManager, ptr)
	{
	}

	XalanMemMgrAutoPtr() :
		m_pointerInfo()
	{
	}

	XalanMemMgrAutoPtr(const XalanMemMgrAutoPtr<Type,toCallDestructor>&	theSource) :
		m_pointerInfo(((XalanMemMgrAutoPtr<Type>&)theSource).release())
	{
	}

	XalanMemMgrAutoPtr<Type,toCallDestructor>&
	operator=(XalanMemMgrAutoPtr<Type,toCallDestructor>&	theRHS)
	{
		if (this != &theRHS)
		{
			m_pointerInfo.deallocate();

			m_pointerInfo = theRHS.release();
		}

		return *this;
	}

	~XalanMemMgrAutoPtr()
	{
		m_pointerInfo.deallocate();
	}

	Type&
	operator*() const
	{
		return *m_pointerInfo.second;
	}

	Type*
	operator->() const
	{
		return m_pointerInfo.second;
	}

	Type*
	get() const
	{
		return m_pointerInfo.second;
	}

	MemMgrAutoPtrData
	release()
	{
		MemMgrAutoPtrData tmp = m_pointerInfo;

		m_pointerInfo.reset( 0 , 0 );

		return MemMgrAutoPtrData(tmp);
	}

	Type*
	releasePtr()
	{
		MemMgrAutoPtrData tmp = release();

		return tmp.second;
	}

	void
	reset(	MemoryManagerType*  theManager = 0,
			Type*		thePointer = 0 )
	{
		m_pointerInfo.deallocate();

		m_pointerInfo.reset ( theManager , thePointer );
	}

private:

// data member
	MemMgrAutoPtrData m_pointerInfo;
};

template<	class Type>
class XalanMemMgrAutoPtrArray
{
public:

	typedef unsigned int size_type;

	class MemMgrAutoPtrArrayData
	{
	public:
		MemMgrAutoPtrArrayData():
			m_memoryManager(0),
			m_dataArray(0),
			m_size(0)
		{
		}

		MemMgrAutoPtrArrayData(
				MemoryManagerType*	memoryManager,
				Type*				dataPointer,
				size_type				size):
			m_memoryManager(memoryManager),
			m_dataArray(dataPointer),
			m_size(size)
		{
			invariants();
		}

		bool
		isInitilized()const
		{
			return ( (m_memoryManager != 0) && (m_dataArray != 0)  && (m_size != 0) )? true : false;
		}

		void
		deallocate()
		{
			invariants();

			if ( isInitilized() )
			{
				assert ( m_dataArray != 0 );

				for ( size_type i = 0; i < m_size ; ++i )
				{
					m_dataArray[i].~Type();
				}
				m_memoryManager->deallocate ( m_dataArray);
			}
		}

		void
		reset(	MemoryManagerType*	memoryManager ,
				Type*				dataPointer,
				size_type				size)
		{
			invariants();

			m_memoryManager = memoryManager;

			m_dataArray =	dataPointer;

			m_size = size;

			invariants();
		}

		MemoryManagerType*		m_memoryManager;
		Type*					m_dataArray;
		size_type					m_size;

	private:
		void
		invariants()const
		{
			assert( isInitilized() ||
					( (m_memoryManager == 0) && (m_dataArray ==0) && (m_size == 0)) );
		}
	};

	XalanMemMgrAutoPtrArray(
			MemoryManagerType&  theManager,
			Type*				ptr,
			size_type			size) :
		m_pointerInfo(&theManager, ptr, size)
	{
	}

	XalanMemMgrAutoPtrArray() :
		m_pointerInfo()
	{
	}

	XalanMemMgrAutoPtrArray(const XalanMemMgrAutoPtrArray<Type>&	theSource) :
		m_pointerInfo(((XalanMemMgrAutoPtr<Type>&)theSource).release())
	{
	}

	XalanMemMgrAutoPtrArray<Type>&
	operator=(XalanMemMgrAutoPtrArray<Type>&	theRHS)
	{
		if (this != &theRHS)
		{
			m_pointerInfo.deallocate();

			m_pointerInfo = theRHS.release();
		}

		return *this;
	}

	~XalanMemMgrAutoPtrArray()
	{
		m_pointerInfo.deallocate();
	}

	Type&
	operator*() const
	{
		return *m_pointerInfo.m_dataArray;
	}

	Type*
	operator->() const
	{
		return m_pointerInfo.m_dataArray;
	}

	Type*
	get() const
	{
		return m_pointerInfo.m_dataArray;
	}

	size_type
	getSize()const
	{
		return m_pointerInfo.m_size;
	}

	XalanMemMgrAutoPtrArray<Type>&
	operator++ ()
	{
		++m_pointerInfo.m_size;

		return *this;
	}

	XalanMemMgrAutoPtrArray<Type>
	operator++ (int)
	{
		XalanMemMgrAutoPtrArray<Type> temp = *this;
		++*this;

		return temp;
	}

	MemMgrAutoPtrArrayData
	release()
	{
		MemMgrAutoPtrArrayData tmp = m_pointerInfo;

		m_pointerInfo.reset( 0 , 0 , 0);

		return MemMgrAutoPtrArrayData(tmp);
	}

	Type*
	releasePtr()
	{
		MemMgrAutoPtrArrayData tmp = release();

		return tmp.dataPointer;
	}

	void
	reset(	MemoryManagerType*  theManager = 0,
			Type*				thePointer = 0 ,
			size_type				size = 0)
	{
		m_pointerInfo.deallocate();

		m_pointerInfo.reset ( theManager , thePointer , size );
	}

	Type&
	operator[](size_type	index) const
	{
		return m_pointerInfo.m_dataArray[index];
	}

private:

	// data member
	MemMgrAutoPtrArrayData m_pointerInfo;
};

XALAN_CPP_NAMESPACE_END

#endif	// if !defined(XALANMEMMGRAUTOPTR_HEADER_GUARD_1357924680)
<commit_msg>Added accessors to get to memory managers and commented out questionable post-increment operator.<commit_after>/*
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * 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.
 */
#if !defined(XALANMEMMGRAUTOPTR_HEADER_GUARD_1357924680)
#define XALANMEMMGRAUTOPTR_HEADER_GUARD_1357924680

// Base include file.  Must be first.
#include <xalanc/PlatformSupport/PlatformSupportDefinitions.hpp>

#include <xalanc/Include/XalanMemoryManagement.hpp>

#include <cstddef>

#include <cassert>

#include <utility>

XALAN_CPP_NAMESPACE_BEGIN

// We're using our own auto_ptr-like class due to wide
// variations amongst the varous platforms we have to
// support
template<	class	Type,
			bool	toCallDestructor = true>
class XalanMemMgrAutoPtr
{
public:

	typedef XALAN_STD_QUALIFIER pair<MemoryManagerType*, Type*> AutoPtrPairType;

	class MemMgrAutoPtrData : public AutoPtrPairType
	{
	public:
		MemMgrAutoPtrData():
			AutoPtrPairType(0,0)
		{
		}

		MemMgrAutoPtrData(
			MemoryManagerType* memoryManager,
			Type* dataPointer):
			AutoPtrPairType(memoryManager, dataPointer)
		{
			invariants();
		}

		bool
		isInitilized()const
		{
			return ( (this->first != 0) && (this->second != 0) )? true : false;
		}

		void
		deallocate()
		{
			invariants();

			if ( isInitilized() )
			{
				if ( toCallDestructor )
				{
					this->second->~Type();
				}

				this->first->deallocate(this->second);
			}
		}

		void
		reset(	MemoryManagerType* m_memoryManager ,
				Type*	m_dataPointer )
		{
			invariants();

			this->first = m_memoryManager;

			this->second = m_dataPointer;

			invariants();
		}
	private:
		void
		invariants()const
		{
			assert( isInitilized() ||
					( (this->first == 0) && (this->second ==0) ) );
		}

	};

	XalanMemMgrAutoPtr(
			MemoryManagerType&  theManager,
			Type* ptr  ) :
		m_pointerInfo(&theManager, ptr)
	{
	}

	XalanMemMgrAutoPtr() :
		m_pointerInfo()
	{
	}

	XalanMemMgrAutoPtr(const XalanMemMgrAutoPtr<Type,toCallDestructor>&	theSource) :
		m_pointerInfo(((XalanMemMgrAutoPtr<Type>&)theSource).release())
	{
	}

	XalanMemMgrAutoPtr<Type,toCallDestructor>&
	operator=(XalanMemMgrAutoPtr<Type,toCallDestructor>&	theRHS)
	{
		if (this != &theRHS)
		{
			m_pointerInfo.deallocate();

			m_pointerInfo = theRHS.release();
		}

		return *this;
	}

	~XalanMemMgrAutoPtr()
	{
		m_pointerInfo.deallocate();
	}

	Type&
	operator*() const
	{
		return *m_pointerInfo.second;
	}

	Type*
	operator->() const
	{
		return m_pointerInfo.second;
	}

	Type*
	get() const
	{
		return m_pointerInfo.second;
	}

    MemoryManagerType*
    getMemoryManager()
    {
        return m_pointerInfo.first;
    }

    const MemoryManagerType*
    getMemoryManager() const
    {
        return m_pointerInfo.first;
    }

	MemMgrAutoPtrData
	release()
	{
		MemMgrAutoPtrData tmp = m_pointerInfo;

		m_pointerInfo.reset( 0 , 0 );

		return MemMgrAutoPtrData(tmp);
	}

	Type*
	releasePtr()
	{
		MemMgrAutoPtrData tmp = release();

		return tmp.second;
	}

	void
	reset(	MemoryManagerType*  theManager = 0,
			Type*		thePointer = 0 )
	{
		m_pointerInfo.deallocate();

		m_pointerInfo.reset ( theManager , thePointer );
	}

private:

// data member
	MemMgrAutoPtrData m_pointerInfo;
};

template<	class Type>
class XalanMemMgrAutoPtrArray
{
public:

	typedef unsigned int size_type;

	class MemMgrAutoPtrArrayData
	{
	public:
		MemMgrAutoPtrArrayData():
			m_memoryManager(0),
			m_dataArray(0),
			m_size(0)
		{
		}

		MemMgrAutoPtrArrayData(
				MemoryManagerType*	memoryManager,
				Type*				dataPointer,
				size_type				size):
			m_memoryManager(memoryManager),
			m_dataArray(dataPointer),
			m_size(size)
		{
			invariants();
		}

		bool
		isInitilized()const
		{
			return ( (m_memoryManager != 0) && (m_dataArray != 0)  && (m_size != 0) )? true : false;
		}

		void
		deallocate()
		{
			invariants();

			if ( isInitilized() )
			{
				assert ( m_dataArray != 0 );

				for ( size_type i = 0; i < m_size ; ++i )
				{
					m_dataArray[i].~Type();
				}
				m_memoryManager->deallocate ( m_dataArray);
			}
		}

		void
		reset(	MemoryManagerType*	memoryManager ,
				Type*				dataPointer,
				size_type				size)
		{
			invariants();

			m_memoryManager = memoryManager;

			m_dataArray =	dataPointer;

			m_size = size;

			invariants();
		}

		MemoryManagerType*		m_memoryManager;
		Type*					m_dataArray;
		size_type					m_size;

	private:
		void
		invariants()const
		{
			assert( isInitilized() ||
					( (m_memoryManager == 0) && (m_dataArray ==0) && (m_size == 0)) );
		}
	};

	XalanMemMgrAutoPtrArray(
			MemoryManagerType&  theManager,
			Type*				ptr,
			size_type			size) :
		m_pointerInfo(&theManager, ptr, size)
	{
	}

	XalanMemMgrAutoPtrArray() :
		m_pointerInfo()
	{
	}

	XalanMemMgrAutoPtrArray(const XalanMemMgrAutoPtrArray<Type>&	theSource) :
		m_pointerInfo(((XalanMemMgrAutoPtr<Type>&)theSource).release())
	{
	}

	XalanMemMgrAutoPtrArray<Type>&
	operator=(XalanMemMgrAutoPtrArray<Type>&	theRHS)
	{
		if (this != &theRHS)
		{
			m_pointerInfo.deallocate();

			m_pointerInfo = theRHS.release();
		}

		return *this;
	}

	~XalanMemMgrAutoPtrArray()
	{
		m_pointerInfo.deallocate();
	}

	Type&
	operator*() const
	{
		return *m_pointerInfo.m_dataArray;
	}

	Type*
	operator->() const
	{
		return m_pointerInfo.m_dataArray;
	}

	Type*
	get() const
	{
		return m_pointerInfo.m_dataArray;
	}

	size_type
	getSize()const
	{
		return m_pointerInfo.m_size;
	}

    MemoryManagerType*
    getMemoryManager()
    {
        return m_pointerInfo.m_memoryManager;
    }

    const MemoryManagerType*
    getMemoryManager() const
    {
        return m_pointerInfo.m_memoryManager;
    }

	XalanMemMgrAutoPtrArray<Type>&
	operator++ ()
	{
		++m_pointerInfo.m_size;

		return *this;
	}

    /* Since this class is not reference-counted, I don't see how this
       could work, since the destruction of the temporary will free
       the controlled pointer.
	XalanMemMgrAutoPtrArray<Type>
	operator++ (int)
	{
		XalanMemMgrAutoPtrArray<Type> temp = *this;
		++*this;

		return temp;
	}
    */

	MemMgrAutoPtrArrayData
	release()
	{
		MemMgrAutoPtrArrayData tmp = m_pointerInfo;

		m_pointerInfo.reset( 0 , 0 , 0);

		return MemMgrAutoPtrArrayData(tmp);
	}

	Type*
	releasePtr()
	{
		MemMgrAutoPtrArrayData tmp = release();

		return tmp.dataPointer;
	}

	void
	reset(	MemoryManagerType*  theManager = 0,
			Type*				thePointer = 0 ,
			size_type				size = 0)
	{
		m_pointerInfo.deallocate();

		m_pointerInfo.reset ( theManager , thePointer , size );
	}

	Type&
	operator[](size_type	index) const
	{
		return m_pointerInfo.m_dataArray[index];
	}

private:

	// data member
	MemMgrAutoPtrArrayData m_pointerInfo;
};

XALAN_CPP_NAMESPACE_END

#endif	// if !defined(XALANMEMMGRAUTOPTR_HEADER_GUARD_1357924680)
<|endoftext|>


<commit_before>#pragma once

#include <iostream>
#include <iomanip>
#include <string.h>

// void print(const int it, const double energy);

template<typename T>
std::string to_string(const T& t)
{
    std::ostringstream strs;
    strs << std::scientific << std::setprecision(3) << t;
    return strs.str();
}

template<typename T>
std::string red(const T& t)
{
    return "\033[31m" + to_string(t) + "\033[0m";
}

template<typename T>
std::string green(const T& t)
{
    return "\033[32m" + to_string(t) + "\033[0m";
}

template<typename T>
std::string yellow(const T& t)
{
    return "\033[33m" + to_string(t) + "\033[0m";
}

template<typename T>
std::string blue(const T& t)
{
    return "\033[34m" + to_string(t) + "\033[0m";
}

template<typename T>
std::string white(const T& t)
{
    return "\033[37m" + to_string(t) + "\033[0m";
}

std::string red(const std::string& s);
std::string green(const std::string& s);
std::string yellow(const std::string& s);
std::string blue(const std::string& s);
std::string white(const std::string& s);

void bar();

// template<typename Solver, typename Color>
// template<typename Solver, typename T, typename Color = std::string (*Color)(T&)>
// template<typename T, std::string (*Color)(const T&), typename Solver>
// void print(
//       const Solver& s
//     // , const Color& c
//     )
// {
//     std::cout << Color(s.current_it) << "\t";
//     std::cout << Color(s.current_temperature) << "\t";
//     std::cout << Color(s.current_temperature - s.temperature(s.current_temperature)) << "\t";
//     std::cout << Color(s.current_energy) << "\t";
//     // // std::cout << s.d_energy << "\t";
//     std::cout << std::endl;
// }

struct Accepted{};
struct Rejected{};

template<typename Solver>
void print(
      const Solver& s
    , Accepted
    )
{
    // std::cout << green(s.current_it) << "\t";
    std::cout << green(s.current_temperature) << "\t";
    std::cout << green(s.current_temperature - s.temperature()) << "\t";
    std::cout << green(s.current_energy) << "\t";
    // // std::cout << s.d_energy << "\t";
    std::cout << std::endl;
}

template<typename Solver>
void print(
      const Solver& s
    , Rejected
    )
{
    // std::cout << red(s.current_it) << "\t";
    std::cout << red(s.current_temperature) << "\t";
    std::cout << red(s.current_temperature - s.temperature()) << "\t";
    std::cout << red(s.current_energy) << "\t";
    // // std::cout << s.d_energy << "\t";

    // std::cout << std::string(60, '\b');
    std::cout << std::endl;
}

template<typename Solver>
void final_print(const Solver& s)
{
    std::cout << std::endl;
    std::cout << "Final temperature: " << s.current_temperature << "\n";
    std::cout << "Final energy: " << s.current_energy << "\n";
    std::cout << std::endl;
}
<commit_msg>[display] display is now on one line<commit_after>#pragma once

#include <iostream>
#include <iomanip>
#include <string.h>

// void print(const int it, const double energy);

template<typename T>
std::string to_string(const T& t)
{
    std::ostringstream strs;
    strs << std::scientific << std::setprecision(3) << t;
    return strs.str();
}

template<typename T>
std::string red(const T& t)
{
    return "\033[31m" + to_string(t) + "\033[0m";
}

template<typename T>
std::string green(const T& t)
{
    return "\033[32m" + to_string(t) + "\033[0m";
}

template<typename T>
std::string yellow(const T& t)
{
    return "\033[33m" + to_string(t) + "\033[0m";
}

template<typename T>
std::string blue(const T& t)
{
    return "\033[34m" + to_string(t) + "\033[0m";
}

template<typename T>
std::string white(const T& t)
{
    return "\033[37m" + to_string(t) + "\033[0m";
}

std::string red(const std::string& s);
std::string green(const std::string& s);
std::string yellow(const std::string& s);
std::string blue(const std::string& s);
std::string white(const std::string& s);

void bar();

// template<typename Solver, typename Color>
// template<typename Solver, typename T, typename Color = std::string (*Color)(T&)>
// template<typename T, std::string (*Color)(const T&), typename Solver>
// void print(
//       const Solver& s
//     // , const Color& c
//     )
// {
//     std::cout << Color(s.current_it) << "\t";
//     std::cout << Color(s.current_temperature) << "\t";
//     std::cout << Color(s.current_temperature - s.temperature(s.current_temperature)) << "\t";
//     std::cout << Color(s.current_energy) << "\t";
//     // // std::cout << s.d_energy << "\t";
//     std::cout << std::endl;
// }

struct Accepted{};
struct Rejected{};

template<typename Solver>
void print(
      const Solver& s
    , Accepted
    )
{
    // std::cout << green(s.current_it) << "\t";
    std::cout << green(s.current_temperature) << "\t";
    std::cout << green(s.current_temperature - s.temperature()) << "\t";
    std::cout << green(s.current_energy) << "\t";
    // // std::cout << s.d_energy << "\t";

    std::cout << "\n\r\e[A";
    std::cout << std::string(100, ' ');
    std::cout << "\r";

    // std::cout << "\n\r\e[A";
}

template<typename Solver>
void print(
      const Solver& s
    , Rejected
    )
{
    // std::cout << red(s.current_it) << "\t";
    std::cout << red(s.current_temperature) << "\t";
    std::cout << red(s.current_temperature - s.temperature()) << "\t";
    std::cout << red(s.current_energy) << "\t";
    // // std::cout << s.d_energy << "\t";

    std::cout << "\n\r\e[A";
    std::cout << std::string(100, ' ');
    std::cout << "\r";
}

template<typename Solver>
void final_print(const Solver& s)
{
    std::cout << std::endl;
    std::cout << "Final temperature: " << s.current_temperature << "\n";
    std::cout << "Final energy: " << s.current_energy << "\n";
    std::cout << std::endl;
}
<|endoftext|>


<commit_before>/***********************************************
 * Author: Jun Jiang - jiangjun4@sina.com
 * Create: 2017-08-19 18:50
 * Last modified : 2017-08-19 18:50
 * Filename      : DNN.cpp
 * Description   :
 **********************************************/
#include "dnn/DNN.h"
#include "dnn/Layer.h"
#include "utils/Log.h"
#include "utils/Shuffler.h"
#include <vector>

namespace abcdl{
namespace dnn{

void DNN::train(const abcdl::algebra::Mat& train_data,
                const abcdl::algebra::Mat& train_label,
                const abcdl::algebra::Mat& test_data,
                const abcdl::algebra::Mat& test_label){
    LOG(INFO) << "dnn start training...";

    size_t layer_size = _layers.size();
    size_t num_train_data = train_data.rows();

    CHECK(num_train_data == train_label.rows());
    CHECK(train_data.cols() == _layers[0]->get_input_dim());
    CHECK(train_label.cols() == _layers[_layers.size() -1]->get_output_dim());

    abcdl::utils::Shuffler shuffler(num_train_data);
    abcdl::algebra::Mat data;
    abcdl::algebra::Mat label;

    for(size_t i = 0; i != _epoch; i++){
        shuffler.shuffle();
        for(size_t j = 0; j != num_train_data; j++){
            train_data.get_row(&data, shuffler.get_row(j));
            train_label.get_row(&label, shuffler.get_row(j));

            for(size_t k = 0; k != layer_size; k++){
                if(k == 0){
                    ((InputLayer*)_layers[k])->set_x(data);
                }
                _layers[k]->forward(_layers[k-1]);
            }

            for(size_t k = layer_size - 1; k > 0; k--){
                if(k == layer_size - 1){
                    ((OutputLayer*)_layers[k])->set_y(label);
                    _layers[k]->backward(_layers[k-1], nullptr);
                }else{
                    _layers[k]->backward(_layers[k-1], _layers[k+1]);
                }

                //mini_batch_update
                if(j % _batch_size == _batch_size - 1 || j == num_train_data - 1){
                    _layers[k]->update_gradient(j % _batch_size + 1, _alpha, _lamda);
                }
            }

            if(j % 100 == 0){
                printf("Epoch[%ld/%ld] Train[%ld/%ld]\r", i + 1, _epoch, j, num_train_data);
            }
        }

        if(test_data.rows() > 0){
            size_t num = evaluate(test_data, test_label);
            printf("Epoch[%ld][%ld/%ld] rate[%f]\n", i + 1, num, test_data.rows(), num/(real)test_data.rows());
        }
    }
}

size_t DNN::evaluate(const abcdl::algebra::Mat& test_data, const abcdl::algebra::Mat& test_label){
    CHECK(test_data.cols() == _layers[0]->get_input_dim());
    CHECK(test_data.rows() == test_label.rows());
    CHECK(test_label.cols() == _layers[_layers.size() - 1]->get_output_dim());

    size_t rows = test_data.rows();
    size_t predict_num = 0;
    abcdl::algebra::Mat mat;

    for(size_t i = 0; i != rows; i++){
        predict(mat, test_data.get_row(i));
        if(mat.argmax() == test_label.get_row(i).argmax()){
            ++predict_num;
        }
    }
    return predict_num;
}

void DNN::predict(abcdl::algebra::Mat& result, const abcdl::algebra::Mat& predict_data){
    CHECK(predict_data.cols() == _layers[0]->get_input_dim());
    size_t layer_size = _layers.size();
    for(size_t k = 0; k != layer_size; k++){
        if(k == 0){
            ((InputLayer*)_layers[k])->set_x(predict_data);
        }
        _layers[k]->forward(_layers[k-1]);
    }
    result = _layers[layer_size - 1]->get_activate_data();
}

bool DNN::load_model(const std::string& path){
    std::vector<abcdl::algebra::Mat*> models;
    if(!model_loader.read<real>(path, &models, "DNNMODEL") || models.size() % 2 != 0){
        for(auto& model : models){
            delete model;
        }
        models.clear();
        return false;
    }

    for(auto& layer : _layers){
        delete layer;
    }
    _layers.clear();

    for(size_t i = 0; i != models.size() / 2; i++){
        if(i == 0){
            _layers.push_back(new InputLayer(models[0]->rows()));
        }
        if(i == models.size() / 2 - 1){
            _layers.push_back(new OutputLayer(models[i * 2]->rows(), models[i * 2]->cols(), new SigmoidActivateFunc(), new CrossEntropyCost(), *models[i * 2], *models[i * 2 + 1]));
        }else{
            _layers.push_back(new FullConnLayer(models[i * 2]->rows(), models[i * 2]->cols(), new SigmoidActivateFunc(), *models[i * 2], *models[i * 2 + 1]));
        }
    }

    for(auto& model : models){
        delete model;
    }
    models.clear();
    return true;
}
bool DNN::write_model(const std::string& path){
    std::vector<abcdl::algebra::Mat*> models;
    for(size_t i = 1; i != _layers.size(); i++){
        models.push_back(&_layers[i]->get_weight());
        models.push_back(&_layers[i]->get_bias());
    }
    return model_loader.write<real>(models, path, "DNNMODEL", false);
}

}//namespace dnn
}//namespace abcdl
<commit_msg>initialized<commit_after>/***********************************************
 * Author: Jun Jiang - jiangjun4@sina.com
 * Create: 2017-08-19 18:50
 * Last modified : 2017-08-19 18:50
 * Filename      : DNN.cpp
 * Description   :
 **********************************************/
#include "dnn/DNN.h"
#include "dnn/Layer.h"
#include "utils/Log.h"
#include "utils/Shuffler.h"
#include <vector>

namespace abcdl{
namespace dnn{

void DNN::train(const abcdl::algebra::Mat& train_data,
                const abcdl::algebra::Mat& train_label,
                const abcdl::algebra::Mat& test_data,
                const abcdl::algebra::Mat& test_label){
    LOG(INFO) << "dnn start training...";

    size_t layer_size = _layers.size();
    size_t num_train_data = train_data.rows();

    CHECK(num_train_data == train_label.rows());
    CHECK(train_data.cols() == _layers[0]->get_input_dim());
    CHECK(train_label.cols() == _layers[_layers.size() -1]->get_output_dim());

    abcdl::utils::Shuffler shuffler(num_train_data);
    abcdl::algebra::Mat data;
    abcdl::algebra::Mat label;

    for(size_t i = 0; i != _epoch; i++){
        shuffler.shuffle();
        for(size_t j = 0; j != num_train_data; j++){
            train_data.get_row(&data, shuffler.get_row(j));
            train_label.get_row(&label, shuffler.get_row(j));

            for(size_t k = 0; k != layer_size; k++){
                if(k == 0){
                    ((InputLayer*)_layers[k])->set_x(data);
                }
                _layers[k]->forward(_layers[k-1]);
            }

            for(size_t k = layer_size - 1; k > 0; k--){
                if(k == layer_size - 1){
                    ((OutputLayer*)_layers[k])->set_y(label);
                    _layers[k]->backward(_layers[k-1], nullptr);
                }else{
                    _layers[k]->backward(_layers[k-1], _layers[k+1]);
                }

                //mini_batch_update
                if(j % _batch_size == _batch_size - 1 || j == num_train_data - 1){
                    _layers[k]->update_gradient(j % _batch_size + 1, _alpha, _lamda);
                }
            }

            if(j % 100 == 0){
                printf("Epoch[%ld/%ld] Train[%ld/%ld]\r", i + 1, _epoch, j, num_train_data);
            }
        }

        if(test_data.rows() > 0){
            size_t num = evaluate(test_data, test_label);
            printf("Epoch[%ld][%ld/%ld] rate[%f]\n", i + 1, num, test_data.rows(), num/(real)test_data.rows());
        }
    }
}

size_t DNN::evaluate(const abcdl::algebra::Mat& test_data, const abcdl::algebra::Mat& test_label){
    CHECK(test_data.cols() == _layers[0]->get_input_dim());
    CHECK(test_data.rows() == test_label.rows());
    CHECK(test_label.cols() == _layers[_layers.size() - 1]->get_output_dim());

    size_t rows = test_data.rows();
    size_t predict_num = 0;
    abcdl::algebra::Mat mat;

    for(size_t i = 0; i != rows; i++){
        predict(mat, test_data.get_row(i));
        if(mat.argmax() == test_label.get_row(i).argmax()){
            ++predict_num;
        }
    }
    return predict_num;
}

void DNN::predict(abcdl::algebra::Mat& result, const abcdl::algebra::Mat& predict_data){
    CHECK(predict_data.cols() == _layers[0]->get_input_dim());
    size_t layer_size = _layers.size();
    for(size_t k = 0; k != layer_size; k++){
        if(k == 0){
            ((InputLayer*)_layers[k])->set_x(predict_data);
        }
        _layers[k]->forward(_layers[k-1]);
    }
    result = _layers[layer_size - 1]->get_activate_data();
}

bool DNN::load_model(const std::string& path){
    std::vector<abcdl::algebra::Mat*> models;
    if(!_model_loader.read<real>(path, &models, "DNNMODEL") || models.size() % 2 != 0){
        for(auto& model : models){
            delete model;
        }
        models.clear();
        return false;
    }

    for(auto& layer : _layers){
        delete layer;
    }
    _layers.clear();

    for(size_t i = 0; i != models.size() / 2; i++){
        if(i == 0){
            _layers.push_back(new InputLayer(models[0]->rows()));
        }
        if(i == models.size() / 2 - 1){
            _layers.push_back(new OutputLayer(models[i * 2]->rows(), models[i * 2]->cols(), new SigmoidActivateFunc(), new CrossEntropyCost(), *models[i * 2], *models[i * 2 + 1]));
        }else{
            _layers.push_back(new FullConnLayer(models[i * 2]->rows(), models[i * 2]->cols(), new SigmoidActivateFunc(), *models[i * 2], *models[i * 2 + 1]));
        }
    }

    for(auto& model : models){
        delete model;
    }
    models.clear();
    return true;
}
bool DNN::write_model(const std::string& path){
    std::vector<abcdl::algebra::Mat*> models;
    for(size_t i = 1; i != _layers.size(); i++){
        models.push_back(&_layers[i]->get_weight());
        models.push_back(&_layers[i]->get_bias());
    }
    return _model_loader.write<real>(models, path, "DNNMODEL", false);
}

}//namespace dnn
}//namespace abcdl
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include "stx/SHA1.h"
#include "stx/http/HTTPSSEResponseHandler.h"
#include "zbase/mapreduce/tasks/MapTableTask.h"
#include "zbase/mapreduce/MapReduceScheduler.h"
#include <zbase/z1stats.h>

using namespace stx;

namespace zbase {

MapTableTask::MapTableTask(
    const AnalyticsSession& session,
    const TSDBTableRef& table_ref,
    const String& map_function,
    const String& globals,
    const String& params,
    MapReduceShardList* shards,
    AnalyticsAuth* auth,
    zbase::PartitionMap* pmap,
    zbase::ReplicationScheme* repl) :
    session_(session),
    table_ref_(table_ref),
    map_function_(map_function),
    globals_(globals),
    params_(params),
    auth_(auth),
    pmap_(pmap),
    repl_(repl) {
  auto table = pmap_->findTable(session_.customer(), table_ref_.table_key);
  if (table.isEmpty()) {
    RAISEF(kNotFoundError, "table not found: $0", table_ref_.table_key);
  }

  auto partitioner = table.get()->partitioner();
  auto partitions = partitioner->listPartitions();

  for (const auto& partition : partitions) {
    auto shard = mkRef(new MapTableTaskShard());
    shard->task = this;
    shard->table_ref = table_ref_;
    shard->table_ref.partition_key = partition;

    addShard(shard.get(), shards);
  }
}

Option<MapReduceShardResult> MapTableTask::execute(
    RefPtr<MapReduceTaskShard> shard_base,
    RefPtr<MapReduceScheduler> job) {
  auto shard = shard_base.asInstanceOf<MapTableTaskShard>();

  Vector<String> errors;
  auto hosts = repl_->replicasFor(shard->table_ref.partition_key.get());
  for (const auto& host : hosts) {
    try {
      return executeRemote(shard, job, host);
    } catch (const StandardException& e) {
      logError(
          "z1.mapreduce",
          e,
          "MapTableTask::execute failed");

      errors.emplace_back(e.what());
    }
  }

  RAISEF(
      kRuntimeError,
      "MapTableTask::execute failed: $0",
      StringUtil::join(errors, ", "));
}

Option<MapReduceShardResult> MapTableTask::executeRemote(
    RefPtr<MapTableTaskShard> shard,
    RefPtr<MapReduceScheduler> job,
    const ReplicaRef& host) {
  logDebug(
      "z1.mapreduce",
      "Executing map table shard on $0/$1/$2 on $3",
      session_.customer(),
      shard->table_ref.table_key,
      shard->table_ref.partition_key.get().toString(),
      host.addr.hostAndPort());

  auto url = StringUtil::format(
      "http://$0/api/v1/mapreduce/tasks/map_partition",
      host.addr.ipAndPort());

  auto params = StringUtil::format(
      "table=$0&partition=$1&map_function=$2&globals=$3&params=$4",
      URI::urlEncode(shard->table_ref.table_key),
      shard->table_ref.partition_key.get().toString(),
      URI::urlEncode(map_function_),
      URI::urlEncode(globals_),
      URI::urlEncode(params_));

  auto api_token = auth_->encodeAuthToken(session_);

  Option<MapReduceShardResult> result;
  Vector<String> errors;
  auto event_handler = [&] (const http::HTTPSSEEvent& ev) {
    if (ev.name.isEmpty()) {
      return;
    }

    if (ev.name.get() == "result_id") {
      result = Some(MapReduceShardResult {
        .host = host,
        .result_id = SHA1Hash::fromHexString(ev.data)
      });
    }

    else if (ev.name.get() == "log") {
      job->sendLogline(URI::urlDecode(ev.data));
    }

    else if (ev.name.get() == "error") {
      errors.emplace_back(ev.data);
    }
  };

  http::HTTPMessage::HeaderList auth_headers;
  auth_headers.emplace_back(
      "Authorization",
      StringUtil::format("Token $0", api_token));

  http::HTTPClient http_client(&z1stats()->http_client_stats);
  auto req = http::HTTPRequest::mkPost(url, params, auth_headers);
  auto res = http_client.executeRequest(
      req,
      http::HTTPSSEResponseHandler::getFactory(event_handler));

  if (!errors.empty()) {
    RAISE(kRuntimeError, StringUtil::join(errors, "; "));
  }

  if (res.statusCode() != 200) {
    RAISEF(kRuntimeError, "HTTP Error: $0", url);
  }

  return result;
}

} // namespace zbase

<commit_msg>fix partition list w/o constraints in MapTableTask<commit_after>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include "stx/SHA1.h"
#include "stx/http/HTTPSSEResponseHandler.h"
#include "zbase/mapreduce/tasks/MapTableTask.h"
#include "zbase/mapreduce/MapReduceScheduler.h"
#include <zbase/z1stats.h>

using namespace stx;

namespace zbase {

MapTableTask::MapTableTask(
    const AnalyticsSession& session,
    const TSDBTableRef& table_ref,
    const String& map_function,
    const String& globals,
    const String& params,
    MapReduceShardList* shards,
    AnalyticsAuth* auth,
    zbase::PartitionMap* pmap,
    zbase::ReplicationScheme* repl) :
    session_(session),
    table_ref_(table_ref),
    map_function_(map_function),
    globals_(globals),
    params_(params),
    auth_(auth),
    pmap_(pmap),
    repl_(repl) {
  auto table = pmap_->findTable(session_.customer(), table_ref_.table_key);
  if (table.isEmpty()) {
    RAISEF(kNotFoundError, "table not found: $0", table_ref_.table_key);
  }

  Vector<csql::ScanConstraint> constraints;
  if (!table_ref.timerange_begin.isEmpty()) {
    csql::ScanConstraint constraint;
    constraint.column_name = "time";
    constraint.type = csql::ScanConstraintType::GREATER_THAN_OR_EQUAL_TO;
    constraint.value = csql::SValue(csql::SValue::IntegerType(
        table_ref.timerange_begin.get().unixMicros()));
    constraints.emplace_back(constraint);
  }

  if (!table_ref.timerange_limit.isEmpty()) {
    csql::ScanConstraint constraint;
    constraint.column_name = "time";
    constraint.type = csql::ScanConstraintType::GREATER_THAN_OR_EQUAL_TO;
    constraint.value = csql::SValue(csql::SValue::IntegerType(
        table_ref.timerange_limit.get().unixMicros()));
    constraints.emplace_back(constraint);
  }

  auto partitioner = table.get()->partitioner();
  auto partitions = partitioner->listPartitions(constraints);

  for (const auto& partition : partitions) {
    auto shard = mkRef(new MapTableTaskShard());
    shard->task = this;
    shard->table_ref = table_ref_;
    shard->table_ref.partition_key = partition;

    addShard(shard.get(), shards);
  }
}

Option<MapReduceShardResult> MapTableTask::execute(
    RefPtr<MapReduceTaskShard> shard_base,
    RefPtr<MapReduceScheduler> job) {
  auto shard = shard_base.asInstanceOf<MapTableTaskShard>();

  Vector<String> errors;
  auto hosts = repl_->replicasFor(shard->table_ref.partition_key.get());
  for (const auto& host : hosts) {
    try {
      return executeRemote(shard, job, host);
    } catch (const StandardException& e) {
      logError(
          "z1.mapreduce",
          e,
          "MapTableTask::execute failed");

      errors.emplace_back(e.what());
    }
  }

  RAISEF(
      kRuntimeError,
      "MapTableTask::execute failed: $0",
      StringUtil::join(errors, ", "));
}

Option<MapReduceShardResult> MapTableTask::executeRemote(
    RefPtr<MapTableTaskShard> shard,
    RefPtr<MapReduceScheduler> job,
    const ReplicaRef& host) {
  logDebug(
      "z1.mapreduce",
      "Executing map table shard on $0/$1/$2 on $3",
      session_.customer(),
      shard->table_ref.table_key,
      shard->table_ref.partition_key.get().toString(),
      host.addr.hostAndPort());

  auto url = StringUtil::format(
      "http://$0/api/v1/mapreduce/tasks/map_partition",
      host.addr.ipAndPort());

  auto params = StringUtil::format(
      "table=$0&partition=$1&map_function=$2&globals=$3&params=$4",
      URI::urlEncode(shard->table_ref.table_key),
      shard->table_ref.partition_key.get().toString(),
      URI::urlEncode(map_function_),
      URI::urlEncode(globals_),
      URI::urlEncode(params_));

  auto api_token = auth_->encodeAuthToken(session_);

  Option<MapReduceShardResult> result;
  Vector<String> errors;
  auto event_handler = [&] (const http::HTTPSSEEvent& ev) {
    if (ev.name.isEmpty()) {
      return;
    }

    if (ev.name.get() == "result_id") {
      result = Some(MapReduceShardResult {
        .host = host,
        .result_id = SHA1Hash::fromHexString(ev.data)
      });
    }

    else if (ev.name.get() == "log") {
      job->sendLogline(URI::urlDecode(ev.data));
    }

    else if (ev.name.get() == "error") {
      errors.emplace_back(ev.data);
    }
  };

  http::HTTPMessage::HeaderList auth_headers;
  auth_headers.emplace_back(
      "Authorization",
      StringUtil::format("Token $0", api_token));

  http::HTTPClient http_client(&z1stats()->http_client_stats);
  auto req = http::HTTPRequest::mkPost(url, params, auth_headers);
  auto res = http_client.executeRequest(
      req,
      http::HTTPSSEResponseHandler::getFactory(event_handler));

  if (!errors.empty()) {
    RAISE(kRuntimeError, StringUtil::join(errors, "; "));
  }

  if (res.statusCode() != 200) {
    RAISEF(kRuntimeError, "HTTP Error: $0", url);
  }

  return result;
}

} // namespace zbase

<|endoftext|>


<commit_before>#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<errno.h>
#include<fcntl.h>
#include<string.h>
#include<unistd.h>

#include<sys/ioctl.h>
#include<linux/i2c.h>
#include<linux/i2c-dev.h>

//#define DEVC "/dev/i2c-1" <-- this is the real I2C device you need with the scale model
#define DEVC "/dev/simudrv"
using namespace std;

int main() {
int file=open(DEVC, O_RDWR);

ioctl(file, I2C_SLAVE, 0x08);

// declare writeBuffer
int writeBuffer[10];
writeBuffer[0]=0xCC;
int readBuffer[10];
write(file, writeBuffer, 1);

read(file, readBuffer, 1);
int output = readBuffer[0];

cout << output << endl;
close(file);

return 0;
}

<commit_msg>duplicated file<commit_after><|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright NumFOCUS
 *
 *  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.txt
 *
 *  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 "itkGaussianImageSource.h"
#include "itkLinearInterpolateImageFunction.h"
#include "itkKullbackLeiblerCompareHistogramImageToImageMetric.h"
#include "itkTranslationTransform.h"

/** This test uses two 2D-Gaussians (standard deviation RegionSize/2).
    This test computes the mutual information between the two images.
*/
int
itkCompareHistogramImageToImageMetricTest(int, char *[])
{
  try
  {
    // Create two simple images.
    constexpr unsigned int ImageDimension = 2;
    using PixelType = double;
    using CoordinateRepresentationType = double;

    // Allocate Images
    using MovingImageType = itk::Image<PixelType, ImageDimension>;
    using FixedImageType = itk::Image<PixelType, ImageDimension>;

    // Declare Gaussian Sources
    using MovingImageSourceType = itk::GaussianImageSource<MovingImageType>;
    using FixedImageSourceType = itk::GaussianImageSource<FixedImageType>;

    // Note: the following declarations are classical arrays
    FixedImageType::SizeValueType  fixedImageSize[] = { 100, 100 };
    MovingImageType::SizeValueType movingImageSize[] = { 100, 100 };

    FixedImageType::SpacingValueType  fixedImageSpacing[] = { 1.0f, 1.0f };
    MovingImageType::SpacingValueType movingImageSpacing[] = { 1.0f, 1.0f };

    FixedImageType::PointValueType  fixedImageOrigin[] = { 0.0f, 0.0f };
    MovingImageType::PointValueType movingImageOrigin[] = { 0.0f, 0.0f };

    MovingImageSourceType::Pointer movingImageSource = MovingImageSourceType::New();
    FixedImageSourceType::Pointer  fixedImageSource = FixedImageSourceType::New();

    movingImageSource->SetSize(movingImageSize);
    movingImageSource->SetOrigin(movingImageOrigin);
    movingImageSource->SetSpacing(movingImageSpacing);
    movingImageSource->SetNormalized(false);
    movingImageSource->SetScale(250.0f);

    fixedImageSource->SetSize(fixedImageSize);
    fixedImageSource->SetOrigin(fixedImageOrigin);
    fixedImageSource->SetSpacing(fixedImageSpacing);
    fixedImageSource->SetNormalized(false);
    fixedImageSource->SetScale(250.0f);

    movingImageSource->Update(); // Force the filter to run
    fixedImageSource->Update();  // Force the filter to run

    MovingImageType::Pointer movingImage = movingImageSource->GetOutput();
    FixedImageType::Pointer  fixedImage = fixedImageSource->GetOutput();

    // Set up the metric.
    using MetricType = itk::KullbackLeiblerCompareHistogramImageToImageMetric<FixedImageType, MovingImageType>;
    using TransformBaseType = MetricType::TransformType;
    using ScalesType = MetricType::ScalesType;
    using ParametersType = TransformBaseType::ParametersType;

    MetricType::Pointer metric = MetricType::New();

    unsigned int                        nBins = 256;
    MetricType::HistogramType::SizeType histSize;

    histSize.SetSize(2);

    histSize[0] = nBins;
    histSize[1] = nBins;
    metric->SetHistogramSize(histSize);

    // Plug the images into the metric.
    metric->SetFixedImage(fixedImage);
    metric->SetMovingImage(movingImage);

    // Set up a transform.
    using TransformType = itk::TranslationTransform<CoordinateRepresentationType, ImageDimension>;

    TransformType::Pointer transform = TransformType::New();
    metric->SetTransform(transform);

    // Set up an interpolator.
    using InterpolatorType = itk::LinearInterpolateImageFunction<MovingImageType, double>;

    InterpolatorType::Pointer interpolator = InterpolatorType::New();
    interpolator->SetInputImage(movingImage);
    metric->SetInterpolator(interpolator);

    // Define the region over which the metric will be computed.
    metric->SetFixedImageRegion(fixedImage->GetBufferedRegion());

    // Set up transform parameters.
    ParametersType parameters(transform->GetNumberOfParameters());

    for (unsigned int k = 0; k < ImageDimension; ++k)
      parameters[k] = 0.0f;

    // Set scales for derivative calculation.
    ScalesType scales(transform->GetNumberOfParameters());

    for (unsigned int k = 0; k < transform->GetNumberOfParameters(); ++k)
      scales[k] = 1;

    metric->SetDerivativeStepLengthScales(scales);

    // Now set up the Training Stuff
    metric->SetTrainingTransform(transform);
    metric->SetTrainingFixedImage(fixedImage);
    metric->SetTrainingFixedImageRegion(fixedImage->GetBufferedRegion());
    metric->SetTrainingMovingImage(movingImage);
    metric->SetTrainingInterpolator(interpolator);

    // Initialize the metric.
    metric->Initialize();

    // Print out metric value and derivative.
    MetricType::MeasureType    measure = metric->GetValue(parameters);
    MetricType::DerivativeType derivative;
    metric->GetDerivative(parameters, derivative);

    std::cout << "Metric value = " << measure << std::endl << "Derivative = " << derivative << std::endl;

    // Exercise Print() method.
    metric->Print(std::cout);

    std::cout << "Test passed." << std::endl;
  }
  catch (const itk::ExceptionObject & ex)
  {
    std::cerr << "Exception caught!" << std::endl;
    std::cerr << ex << std::endl;
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}
<commit_msg>ENH: Improve KLCompareHistogramImageToImageMetric coverage<commit_after>/*=========================================================================
 *
 *  Copyright NumFOCUS
 *
 *  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.txt
 *
 *  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 "itkGaussianImageSource.h"
#include "itkLinearInterpolateImageFunction.h"
#include "itkKullbackLeiblerCompareHistogramImageToImageMetric.h"
#include "itkTranslationTransform.h"
#include "itkTestingMacros.h"

/** This test uses two 2D-Gaussians (standard deviation RegionSize/2).
    This test computes the mutual information between the two images.
*/
int
itkCompareHistogramImageToImageMetricTest(int, char *[])
{

  // Create two simple images.
  constexpr unsigned int ImageDimension = 2;
  using PixelType = double;
  using CoordinateRepresentationType = double;

  // Allocate Images
  using MovingImageType = itk::Image<PixelType, ImageDimension>;
  using FixedImageType = itk::Image<PixelType, ImageDimension>;

  // Declare Gaussian Sources
  using MovingImageSourceType = itk::GaussianImageSource<MovingImageType>;
  using FixedImageSourceType = itk::GaussianImageSource<FixedImageType>;

  // Note: the following declarations are classical arrays
  FixedImageType::SizeValueType  fixedImageSize[] = { 100, 100 };
  MovingImageType::SizeValueType movingImageSize[] = { 100, 100 };

  FixedImageType::SpacingValueType  fixedImageSpacing[] = { 1.0f, 1.0f };
  MovingImageType::SpacingValueType movingImageSpacing[] = { 1.0f, 1.0f };

  FixedImageType::PointValueType  fixedImageOrigin[] = { 0.0f, 0.0f };
  MovingImageType::PointValueType movingImageOrigin[] = { 0.0f, 0.0f };

  MovingImageSourceType::Pointer movingImageSource = MovingImageSourceType::New();
  FixedImageSourceType::Pointer  fixedImageSource = FixedImageSourceType::New();

  movingImageSource->SetSize(movingImageSize);
  movingImageSource->SetOrigin(movingImageOrigin);
  movingImageSource->SetSpacing(movingImageSpacing);
  movingImageSource->SetNormalized(false);
  movingImageSource->SetScale(250.0f);

  fixedImageSource->SetSize(fixedImageSize);
  fixedImageSource->SetOrigin(fixedImageOrigin);
  fixedImageSource->SetSpacing(fixedImageSpacing);
  fixedImageSource->SetNormalized(false);
  fixedImageSource->SetScale(250.0f);

  ITK_TRY_EXPECT_NO_EXCEPTION(movingImageSource->Update()); // Force the filter to run
  ITK_TRY_EXPECT_NO_EXCEPTION(fixedImageSource->Update());  // Force the filter to run

  MovingImageType::Pointer movingImage = movingImageSource->GetOutput();
  FixedImageType::Pointer  fixedImage = fixedImageSource->GetOutput();

  // Set up the metric.
  using MetricType = itk::KullbackLeiblerCompareHistogramImageToImageMetric<FixedImageType, MovingImageType>;
  using TransformBaseType = MetricType::TransformType;
  using ScalesType = MetricType::ScalesType;
  using ParametersType = TransformBaseType::ParametersType;

  MetricType::Pointer metric = MetricType::New();

  ITK_EXERCISE_BASIC_OBJECT_METHODS(
    metric, KullbackLeiblerCompareHistogramImageToImageMetric, CompareHistogramImageToImageMetric);

  auto epsilon = 1e-12;
  ITK_TEST_SET_GET_VALUE(epsilon, metric->GetEpsilon());

  unsigned int                        nBins = 256;
  MetricType::HistogramType::SizeType histSize;

  histSize.SetSize(2);

  histSize[0] = nBins;
  histSize[1] = nBins;
  metric->SetHistogramSize(histSize);

  // Plug the images into the metric.
  metric->SetFixedImage(fixedImage);
  metric->SetMovingImage(movingImage);

  // Set up a transform.
  using TransformType = itk::TranslationTransform<CoordinateRepresentationType, ImageDimension>;

  TransformType::Pointer transform = TransformType::New();
  metric->SetTransform(transform);

  // Set up an interpolator.
  using InterpolatorType = itk::LinearInterpolateImageFunction<MovingImageType, double>;

  InterpolatorType::Pointer interpolator = InterpolatorType::New();
  interpolator->SetInputImage(movingImage);
  metric->SetInterpolator(interpolator);

  // Define the region over which the metric will be computed.
  metric->SetFixedImageRegion(fixedImage->GetBufferedRegion());

  // Set up transform parameters.
  ParametersType parameters(transform->GetNumberOfParameters());

  for (unsigned int k = 0; k < ImageDimension; ++k)
  {
    parameters[k] = 0.0f;
  }

  // Set scales for derivative calculation.
  ScalesType scales(transform->GetNumberOfParameters());

  for (unsigned int k = 0; k < transform->GetNumberOfParameters(); ++k)
  {
    scales[k] = 1;
  }

  metric->SetDerivativeStepLengthScales(scales);

  // Now set up the Training Stuff
  metric->SetTrainingTransform(transform);
  metric->SetTrainingFixedImage(fixedImage);
  metric->SetTrainingFixedImageRegion(fixedImage->GetBufferedRegion());
  metric->SetTrainingMovingImage(movingImage);
  metric->SetTrainingInterpolator(interpolator);

  // Initialize the metric.
  metric->Initialize();

  // Print out metric value and derivative.
  MetricType::MeasureType    measure = metric->GetValue(parameters);
  MetricType::DerivativeType derivative;
  metric->GetDerivative(parameters, derivative);

  std::cout << "Metric value = " << measure << std::endl << "Derivative = " << derivative << std::endl;

  std::cout << "Test finished." << std::endl;
  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>//
// example.hpp
// ***********
//
// Copyright (c) 2019 Sharon W (sharon at aegis dot gg)
//
// Distributed under the MIT License. (See accompanying file LICENSE)
//

#pragma once

#include <aegis.hpp>
#include <string>
#include <stdint.h>
#include <nlohmann/json.hpp>

namespace example_bot
{

using json = nlohmann::json;
using namespace aegis;
using namespace aegis::gateway::events;

class example
{
public:
    example(core & bot) : bot(bot) {};
    ~example() = default;

    core & bot;

    template<typename Out>
    void split(const std::string &s, char delim, Out result)
    {
        std::stringstream ss;
        ss.str(s);
        std::string item;
        while (std::getline(ss, item, delim))
        {
            if (!item.empty())
                *(result++) = item;
        }
    }

    const json make_info_obj(aegis::core & bot, aegis::shards::shard * _shard);

    std::vector<std::string> split(const std::string &s, char delim)
    {
        std::vector<std::string> elems;
        split(s, delim, std::back_inserter(elems));
        return elems;
    }

    // Messages you want to process
    void attach()
    {
        bot.set_on_message_create(std::bind(&example::MessageCreate, this, std::placeholders::_1));
    }

    snowflake get_snowflake(const std::string name, aegis::guild & _guild) const noexcept
    {
        if (name.empty())
            return 0;
        try
        {
            if (name[0] == '<')
            {
                //mention param

                std::string::size_type pos = name.find_first_of('>');
                if (pos == std::string::npos)
                    return { 0 };
                if (name[2] == '!')//mobile mention. strip <@!
                    return std::stoull(std::string{ name.substr(3, pos - 1) });
                else  if (name[2] == '&')//role mention. strip <@&
                    return std::stoull(std::string{ name.substr(3, pos - 1) });
                else  if (name[1] == '#')//channel mention. strip <#
                    return std::stoull(std::string{ name.substr(2, pos - 1) });
                else//regular mention. strip <@
                    return std::stoull(std::string{ name.substr(2, pos - 1) });
            }
            else if (std::isdigit(name[0]))
            {
                //snowflake param
                return std::stoull(std::string{ name });
            }
            else
            {
                //most likely username#discriminator param
                std::string::size_type n = name.find('#');
                if (n != std::string::npos)
                {
                    //found # separator
                    for (auto & m : _guild.get_members())
                        if (m.second->get_full_name() == name)
                            return { m.second->get_id() };
                    return 0;
                }
                return 0;//# not found. unknown parameter. unicode may trigger this.
            }
        }
        catch (std::invalid_argument &)
        {
            return 0;
        }
    }

    const snowflake bot_owner_id = 171000788183678976LL;

    std::string prefix = "?";

    // All the hooks in the websocket stream
    void TypingStart(typing_start obj);

    void MessageCreate(message_create msg);

    void MessageCreateDM(message_create msg);

    void MessageUpdate(message_update obj);

    void MessageDelete(message_delete obj);

    void MessageDeleteBulk(message_delete_bulk obj);

    void GuildCreate(guild_create);

    void GuildUpdate(guild_update obj);

    void GuildDelete(guild_delete obj);

    void UserUpdate(user_update obj);

    void Ready(ready obj);

    void Resumed(resumed obj);

    void ChannelCreate(channel_create obj);

    void ChannelUpdate(channel_update obj);

    void ChannelDelete(channel_delete obj);

    void GuildBanAdd(guild_ban_add obj);

    void GuildBanRemove(guild_ban_remove obj);

    void GuildEmojisUpdate(guild_emojis_update obj);

    void GuildIntegrationsUpdate(guild_integrations_update obj);

    void GuildMemberAdd(guild_member_add obj);

    void GuildMemberRemove(guild_member_remove obj);

    void GuildMemberUpdate(guild_member_update obj);

    void GuildMemberChunk(guild_members_chunk obj);

    void GuildRoleCreate(guild_role_create obj);

    void GuildRoleUpdate(guild_role_update obj);

    void GuildRoleDelete(guild_role_delete obj);

    void PresenceUpdate(presence_update obj);

    void VoiceStateUpdate(voice_state_update obj);

    void VoiceServerUpdate(voice_server_update obj);

    const json make_info_obj(shard * _shard, core * bot);
};

}
<commit_msg>Example fix<commit_after>//
// example.hpp
// ***********
//
// Copyright (c) 2019 Sharon W (sharon at aegis dot gg)
//
// Distributed under the MIT License. (See accompanying file LICENSE)
//

#pragma once

#include <aegis.hpp>
#include <string>
#include <stdint.h>
#include <nlohmann/json.hpp>

namespace example_bot
{

using json = nlohmann::json;
using namespace aegis;
using namespace aegis::gateway::events;

class example
{
public:
    example(core & bot) : bot(bot) {};
    ~example() = default;

    core & bot;

    template<typename Out>
    void split(const std::string &s, char delim, Out result)
    {
        std::stringstream ss;
        ss.str(s);
        std::string item;
        while (std::getline(ss, item, delim))
        {
            if (!item.empty())
                *(result++) = item;
        }
    }

    const json make_info_obj(aegis::core & bot, aegis::shards::shard * _shard);

    std::vector<std::string> split(const std::string &s, char delim)
    {
        std::vector<std::string> elems;
        split(s, delim, std::back_inserter(elems));
        return elems;
    }

    // Messages you want to process
    void attach()
    {
        bot.set_on_message_create(std::bind(&example::MessageCreate, this, std::placeholders::_1));
    }

    snowflake get_snowflake(const std::string name, aegis::guild & _guild) const noexcept
    {
        if (name.empty())
            return 0;
        try
        {
            if (name[0] == '<')
            {
                //mention param

                std::string::size_type pos = name.find_first_of('>');
                if (pos == std::string::npos)
                    return 0;
                if (name[2] == '!')//mobile mention. strip <@!
                    return std::stoull(std::string{ name.substr(3, pos - 1) });
                else  if (name[2] == '&')//role mention. strip <@&
                    return std::stoull(std::string{ name.substr(3, pos - 1) });
                else  if (name[1] == '#')//channel mention. strip <#
                    return std::stoull(std::string{ name.substr(2, pos - 1) });
                else//regular mention. strip <@
                    return std::stoull(std::string{ name.substr(2, pos - 1) });
            }
            else if (std::isdigit(name[0]))
            {
                //snowflake param
                return std::stoull(std::string{ name });
            }
            else
            {
                //most likely username#discriminator param
                std::string::size_type n = name.find('#');
                if (n != std::string::npos)
                {
                    //found # separator
                    for (auto & m : _guild.get_members())
                        if (m.second->get_full_name() == name)
                            return { m.second->get_id() };
                    return 0;
                }
                return 0;//# not found. unknown parameter. unicode may trigger this.
            }
        }
        catch (std::invalid_argument &)
        {
            return 0;
        }
    }

    const snowflake bot_owner_id = 171000788183678976LL;

    std::string prefix = "?";

    // All the hooks in the websocket stream
    void TypingStart(typing_start obj);

    void MessageCreate(message_create msg);

    void MessageCreateDM(message_create msg);

    void MessageUpdate(message_update obj);

    void MessageDelete(message_delete obj);

    void MessageDeleteBulk(message_delete_bulk obj);

    void GuildCreate(guild_create);

    void GuildUpdate(guild_update obj);

    void GuildDelete(guild_delete obj);

    void UserUpdate(user_update obj);

    void Ready(ready obj);

    void Resumed(resumed obj);

    void ChannelCreate(channel_create obj);

    void ChannelUpdate(channel_update obj);

    void ChannelDelete(channel_delete obj);

    void GuildBanAdd(guild_ban_add obj);

    void GuildBanRemove(guild_ban_remove obj);

    void GuildEmojisUpdate(guild_emojis_update obj);

    void GuildIntegrationsUpdate(guild_integrations_update obj);

    void GuildMemberAdd(guild_member_add obj);

    void GuildMemberRemove(guild_member_remove obj);

    void GuildMemberUpdate(guild_member_update obj);

    void GuildMemberChunk(guild_members_chunk obj);

    void GuildRoleCreate(guild_role_create obj);

    void GuildRoleUpdate(guild_role_update obj);

    void GuildRoleDelete(guild_role_delete obj);

    void PresenceUpdate(presence_update obj);

    void VoiceStateUpdate(voice_state_update obj);

    void VoiceServerUpdate(voice_server_update obj);

    const json make_info_obj(shard * _shard, core * bot);
};

}
<|endoftext|>