static ERL_NIF_TERM elua_newstate_async(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { msg_t *msg; ErlNifPid pid; if(argc != 2) { return enif_make_badarg(env); } // ref if(!enif_is_ref(env, argv[0])){ return make_error_tuple(env, "invalid_ref"); } // dest pid if(!enif_get_local_pid(env, argv[1], &pid)) { return make_error_tuple(env, "invalid_pid"); } msg = msg_create(); if(!msg) { return make_error_tuple(env, "command_create_failed"); } msg->type = msg_newstate; msg->ref = enif_make_copy(msg->env, argv[0]); msg->pid = pid; msg->hold_env = env; msg->res=NULL; return push_command(env, NULL, msg); }
/* * Prepare the sql statement */ static ERL_NIF_TERM esqlite_prepare(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { esqlite_connection *conn; esqlite_command *cmd = NULL; ErlNifPid pid; if(argc != 4) return enif_make_badarg(env); if(!enif_get_resource(env, argv[0], esqlite_connection_type, (void **) &conn)) return enif_make_badarg(env); if(!enif_is_ref(env, argv[1])) return make_error_tuple(env, "invalid_ref"); if(!enif_get_local_pid(env, argv[2], &pid)) return make_error_tuple(env, "invalid_pid"); cmd = command_create(); if(!cmd) return make_error_tuple(env, "command_create_failed"); cmd->type = cmd_prepare; cmd->ref = enif_make_copy(cmd->env, argv[1]); cmd->pid = pid; cmd->arg = enif_make_copy(cmd->env, argv[3]); return push_command(env, conn, cmd); }
/* * Step to a prepared statement */ static ERL_NIF_TERM esqlite_column_names(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { esqlite_statement *stmt; esqlite_command *cmd = NULL; ErlNifPid pid; if(argc != 3) return enif_make_badarg(env); if(!enif_get_resource(env, argv[0], esqlite_statement_type, (void **) &stmt)) return enif_make_badarg(env); if(!enif_is_ref(env, argv[1])) return make_error_tuple(env, "invalid_ref"); if(!enif_get_local_pid(env, argv[2], &pid)) return make_error_tuple(env, "invalid_pid"); if(!stmt->statement) return make_error_tuple(env, "no_prepared_statement"); cmd = command_create(); if(!cmd) return make_error_tuple(env, "command_create_failed"); cmd->type = cmd_column_names; cmd->ref = enif_make_copy(cmd->env, argv[1]); cmd->pid = pid; cmd->stmt = stmt->statement; if(!stmt->connection) return make_error_tuple(env, "no_connection"); if(!stmt->connection->commands) return make_error_tuple(env, "no_command_queue"); return push_command(env, stmt->connection, cmd); }
void update_callback(void *arg, int sqlite_operation_type, char const *sqlite_database, char const *sqlite_table, sqlite3_int64 sqlite_rowid) { esqlite_connection *db = (esqlite_connection *)arg; esqlite_command *cmd = NULL; ERL_NIF_TERM type, table, rowid; cmd = command_create(); if(db == NULL) return; if(!cmd) return; rowid = enif_make_int64(cmd->env, sqlite_rowid); table = enif_make_string(cmd->env, sqlite_table, ERL_NIF_LATIN1); switch(sqlite_operation_type) { case SQLITE_INSERT: type = make_atom(cmd->env, "insert"); break; case SQLITE_DELETE: type = make_atom(cmd->env, "delete"); break; case SQLITE_UPDATE: type = make_atom(cmd->env, "update"); break; default: return; } cmd->type = cmd_notification; cmd->arg = enif_make_tuple3(cmd->env, type, table, rowid); push_command(cmd->env, db, cmd); }
/* * Open the database */ static ERL_NIF_TERM esqlite_open(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { esqlite_connection *db; esqlite_command *cmd = NULL; ErlNifPid pid; if(argc != 4) return enif_make_badarg(env); if(!enif_get_resource(env, argv[0], esqlite_connection_type, (void **) &db)) return enif_make_badarg(env); if(!enif_is_ref(env, argv[1])) return make_error_tuple(env, "invalid_ref"); if(!enif_get_local_pid(env, argv[2], &pid)) return make_error_tuple(env, "invalid_pid"); /* Note, no check is made for the type of the argument */ cmd = command_create(); if(!cmd) return make_error_tuple(env, "command_create_failed"); cmd->type = cmd_open; cmd->ref = enif_make_copy(cmd->env, argv[1]); cmd->pid = pid; cmd->arg = enif_make_copy(cmd->env, argv[3]); return push_command(env, db, cmd); }
static int wxe_driver_control(ErlDrvData handle, unsigned op, char* buf, int count, char** res, int res_size) { wxe_data *sd = ((wxe_data *)handle); push_command(op,buf,count,sd); (*res) = NULL; return 0; }
static ErlDrvSSizeT wxe_driver_control(ErlDrvData handle, unsigned op, char* buf, ErlDrvSizeT count, char** res, ErlDrvSizeT res_size) { wxe_data *sd = ((wxe_data *)handle); push_command(op,buf,count,sd); return 0; }
void wxe_process_died(ErlDrvData handle, ErlDrvMonitor *monitor) { /* Callback is active for the dead process */ wxe_data *sd = ((wxe_data *)handle); push_command(WXE_CB_RETURN,NULL,0,sd); /* ErlDrvTermData pid; */ /* pid = driver_get_monitored_process(sd->port, monitor); */ /* fprintf(stderr, "Process died %d \r\n", (int) pid); */ }
errcode_t prm_pagefault(virt_addr_t addr) { prm_command_t* cmd = new_prm_command(addr); DEBUG2("(%d:%d)\n", VIRT_ADDR_PID(addr), VIRT_ADDR_PAGE(addr)); assert(worker_thread_is_running(&prm_thread)); push_command(cmd); wait_for_completion(cmd); //blocks delete_prm_command(cmd); return ecSuccess; }
static ERL_NIF_TERM elua_gencall_async(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { elua_t *res; msg_t *msg; ErlNifPid pid; if(argc != 6) { return enif_make_badarg(env); } // first arg: ref if(!enif_get_resource(env, argv[0], RES_SYNC, (void**) &res)) { return enif_make_badarg(env); } // ref if(!enif_is_ref(env, argv[1])) { return make_error_tuple(env, "invalid_ref"); } // dest pid if(!enif_get_local_pid(env, argv[2], &pid)) { return make_error_tuple(env, "invalid_pid"); } // fourth arg: list of input args if(!enif_is_list(env, argv[5])) { return enif_make_badarg(env); } msg = msg_create(); if(!msg) { return make_error_tuple(env, "command_create_failed"); } msg->type = msg_gencall; msg->ref = enif_make_copy(msg->env, argv[1]); msg->pid = pid; msg->arg1 = enif_make_copy(msg->env, argv[3]); msg->arg2 = enif_make_copy(msg->env, argv[4]); msg->arg3 = enif_make_copy(msg->env, argv[5]); msg->res = res; return push_command(env, res, msg); }
/* * Multi step to a prepared statement */ static ERL_NIF_TERM esqlite_multi_step(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { esqlite_connection *conn; esqlite_statement *stmt; esqlite_command *cmd = NULL; ErlNifPid pid; int chunk_size = 0; if(argc != 5) return enif_make_badarg(env); if(!enif_get_resource(env, argv[0], esqlite_connection_type, (void **) &conn)) return enif_make_badarg(env); if(!enif_get_resource(env, argv[1], esqlite_statement_type, (void **) &stmt)) return enif_make_badarg(env); if(!enif_get_int(env, argv[2], &chunk_size)) return make_error_tuple(env, "invalid_chunk_size"); if(!enif_is_ref(env, argv[3])) return make_error_tuple(env, "invalid_ref"); if(!enif_get_local_pid(env, argv[4], &pid)) return make_error_tuple(env, "invalid_pid"); if(!stmt->statement) return make_error_tuple(env, "no_prepared_statement"); cmd = command_create(); if(!cmd) return make_error_tuple(env, "command_create_failed"); cmd->type = cmd_multi_step; cmd->ref = enif_make_copy(cmd->env, argv[3]); cmd->pid = pid; cmd->stmt = enif_make_copy(cmd->env, argv[1]); cmd->arg = enif_make_copy(cmd->env, argv[2]); return push_command(env, conn, cmd); }
// 1. Figure out actor index, create one if it does not exist // 2. check info for evnum/evterm data int sqlite3WalOpen(sqlite3_vfs *pVfs, sqlite3_file *pDbFd, const char *zWalName,int bNoShm, i64 mxWalSize, Wal **ppWal) { MDB_val key, data; int rc; #if ATOMIC db_thread *thr = g_tsd_thread; db_connection *conn = g_tsd_conn; #else db_thread* thr = enif_tsd_get(g_tsd_thread); db_connection* conn = enif_tsd_get(g_tsd_conn); #endif mdbinf * const mdb = &thr->mdb; Wal *pWal = &conn->wal; MDB_dbi actorsdb, infodb; MDB_txn *txn = mdb->txn; int offset = 0, cutoff = 0, nmLen = 0; actorsdb = mdb->actorsdb; infodb = mdb->infodb; if (zWalName[0] == '/') offset = 1; nmLen = strlen(zWalName+offset); if (zWalName[offset+nmLen-1] == 'l' && zWalName[offset+nmLen-2] == 'a' && zWalName[offset+nmLen-3] == 'w' && zWalName[offset+nmLen-4] == '-') cutoff = 4; DBG("Wal name=%s %lld",zWalName,(i64)txn); // shorten size to ignore "-wal" at the end key.mv_size = nmLen-cutoff; key.mv_data = (void*)(zWalName+offset);//thr->curConn->dbpath; rc = mdb_get(txn,actorsdb,&key,&data); // This is new actor, assign an index if (rc == MDB_NOTFOUND) { i64 index = 0; // MDB_val key1 = {1,(void*)"?"}; #ifndef _TESTAPP_ qitem *item; db_command *cmd; item = command_create(conn->wthreadind,-1,g_pd); cmd = (db_command*)item->cmd; cmd->type = cmd_actorsdb_add; #if ATOMIC index = atomic_fetch_add_explicit(&g_pd->actorIndexes[thr->nEnv], 1, memory_order_relaxed); #else enif_mutex_lock(g_pd->actorIndexesMtx[thr->nEnv]); index = g_pd->actorIndexes[thr->nEnv]++; enif_mutex_unlock(g_pd->actorIndexesMtx[thr->nEnv]); #endif pWal->index = index; cmd->arg = enif_make_string(item->env,zWalName,ERL_NIF_LATIN1); cmd->arg1 = enif_make_uint64(item->env, index); push_command(conn->wthreadind, -1, g_pd, item); #else if (thr->isreadonly) { return SQLITE_ERROR; } else { #if ATOMIC char filename[MAX_PATHNAME]; sprintf(filename,"%.*s",(int)(nmLen-cutoff),zWalName+offset); index = atomic_fetch_add_explicit(&g_pd->actorIndexes[thr->nEnv], 1, memory_order_relaxed); pWal->index = index; if (register_actor(index, filename) != SQLITE_OK) return SQLITE_ERROR; #else return SQLITE_ERROR; #endif } #endif } // Actor exists, read evnum/evterm info else if (rc == MDB_SUCCESS) { // data contains index key = data; pWal->index = *(i64*)data.mv_data; DBG("Actor at index %lld",pWal->index); rc = mdb_get(txn,infodb,&key,&data); if (rc == MDB_SUCCESS) { if (*(u8*)data.mv_data != 1) { return SQLITE_ERROR; } memcpy(&pWal->firstCompleteTerm, ((u8*)data.mv_data)+1, sizeof(u64)); memcpy(&pWal->firstCompleteEvnum,((u8*)data.mv_data)+1+sizeof(u64), sizeof(u64)); memcpy(&pWal->lastCompleteTerm, ((u8*)data.mv_data)+1+sizeof(u64)*2, sizeof(u64)); memcpy(&pWal->lastCompleteEvnum, ((u8*)data.mv_data)+1+sizeof(u64)*3, sizeof(u64)); memcpy(&pWal->inProgressTerm, ((u8*)data.mv_data)+1+sizeof(u64)*4, sizeof(u64)); memcpy(&pWal->inProgressEvnum, ((u8*)data.mv_data)+1+sizeof(u64)*5, sizeof(u64)); memcpy(&pWal->mxPage, ((u8*)data.mv_data)+1+sizeof(u64)*6, sizeof(u32)); memcpy(&pWal->allPages, ((u8*)data.mv_data)+1+sizeof(u64)*6+sizeof(u32),sizeof(u32)); pWal->readSafeTerm = pWal->lastCompleteTerm; pWal->readSafeEvnum = pWal->lastCompleteEvnum; pWal->readSafeMxPage = pWal->mxPage; // if (pWal->inProgressTerm != 0) // { // doundo(pWal,NULL,NULL,1); // } } else if (rc == MDB_NOTFOUND) { // DBG("Info for actor not found")); } } else { DBG("Error open=%d",rc); thr->forceCommit = 2; return SQLITE_ERROR; } conn->changed = 1; if (ppWal != NULL) (*ppWal) = pWal; return SQLITE_OK; }
static void produce_command(void) { static int target_surface = 0; static int cmd_index = 0; Command *command; if (has_secondary) target_surface = 1; ASSERT(g_num_commands); command = &g_commands[cmd_index]; if (command->cb) { command->cb(command); } switch (command->command) { case SLEEP: printf("sleep %u seconds\n", command->sleep.secs); sleep(command->sleep.secs); break; case PATH_PROGRESS: path_progress(&path); break; case SIMPLE_UPDATE: { QXLRect rect = {.left = 0, .right = (target_surface == 0 ? test_width : SURF_WIDTH), .top = 0, .bottom = (target_surface == 0 ? test_height : SURF_HEIGHT)}; qxl_worker->update_area(qxl_worker, target_surface, &rect, NULL, 0, 1); break; } /* Drawing commands, they all push a command to the command ring */ case SIMPLE_COPY_BITS: case SIMPLE_DRAW_SOLID: case SIMPLE_DRAW_BITMAP: case SIMPLE_DRAW: { SimpleSpiceUpdate *update; if (has_automated_tests) { if (control == 0) { return; } regression_test(); } switch (command->command) { case SIMPLE_COPY_BITS: update = test_spice_create_update_copy_bits(0); break; case SIMPLE_DRAW: update = test_spice_create_update_draw(0, path.t); break; case SIMPLE_DRAW_BITMAP: update = test_spice_create_update_from_bitmap(command->bitmap.surface_id, command->bitmap.bbox, command->bitmap.bitmap, command->bitmap.num_clip_rects, command->bitmap.clip_rects); break; case SIMPLE_DRAW_SOLID: update = test_spice_create_update_solid(command->solid.surface_id, command->solid.bbox, command->solid.color); break; } push_command(&update->ext); break; } case SIMPLE_CREATE_SURFACE: { SimpleSurfaceCmd *update; target_surface = MAX_SURFACE_NUM - 1; update = create_surface(target_surface, SURF_WIDTH, SURF_HEIGHT, g_secondary_surface); push_command(&update->ext); has_secondary = 1; break; } case SIMPLE_DESTROY_SURFACE: { SimpleSurfaceCmd *update; has_secondary = 0; update = destroy_surface(target_surface); target_surface = 0; push_command(&update->ext); break; } case DESTROY_PRIMARY: qxl_worker->destroy_primary_surface(qxl_worker, 0); break; case CREATE_PRIMARY: create_primary_surface(qxl_worker, command->create_primary.width, command->create_primary.height); break; } cmd_index = (cmd_index + 1) % g_num_commands; } SpiceTimer *wakeup_timer; int wakeup_ms = 50; SpiceCoreInterface *g_core; static int req_cmd_notification(QXLInstance *qin) { g_core->timer_start(wakeup_timer, wakeup_ms); return TRUE; }
static void produce_command(Test *test) { Command *command; QXLWorker *qxl_worker = test->qxl_worker; spice_assert(qxl_worker); if (test->has_secondary) test->target_surface = 1; if (!test->num_commands) { usleep(1000); return; } command = &test->commands[test->cmd_index]; if (command->cb) { command->cb(test, command); } switch (command->command) { case SLEEP: printf("sleep %u seconds\n", command->sleep.secs); sleep(command->sleep.secs); break; case PATH_PROGRESS: path_progress(&path); break; case SIMPLE_UPDATE: { QXLRect rect = { .left = 0, .right = (test->target_surface == 0 ? test->primary_width : test->width), .top = 0, .bottom = (test->target_surface == 0 ? test->primary_height : test->height) }; if (rect.right > 0 && rect.bottom > 0) { spice_qxl_update_area(&test->qxl_instance, test->target_surface, &rect, NULL, 0, 1); } break; } /* Drawing commands, they all push a command to the command ring */ case SIMPLE_COPY_BITS: case SIMPLE_DRAW_SOLID: case SIMPLE_DRAW_BITMAP: case SIMPLE_DRAW: { SimpleSpiceUpdate *update; if (has_automated_tests) { if (control == 0) { return; } regression_test(); } switch (command->command) { case SIMPLE_COPY_BITS: update = test_spice_create_update_copy_bits(test, 0); break; case SIMPLE_DRAW: update = test_spice_create_update_draw(test, 0, path.t); break; case SIMPLE_DRAW_BITMAP: update = test_spice_create_update_from_bitmap(command->bitmap.surface_id, command->bitmap.bbox, command->bitmap.bitmap, command->bitmap.num_clip_rects, command->bitmap.clip_rects); break; case SIMPLE_DRAW_SOLID: update = test_spice_create_update_solid(command->solid.surface_id, command->solid.bbox, command->solid.color); break; default: /* Just to shut up GCC warning (-Wswitch) */ break; } push_command(&update->ext); break; } case SIMPLE_CREATE_SURFACE: { SimpleSurfaceCmd *update; if (command->create_surface.data) { spice_assert(command->create_surface.surface_id > 0); spice_assert(command->create_surface.surface_id < MAX_SURFACE_NUM); spice_assert(command->create_surface.surface_id == 1); update = create_surface(command->create_surface.surface_id, command->create_surface.format, command->create_surface.width, command->create_surface.height, command->create_surface.data); } else { update = create_surface(test->target_surface, SPICE_SURFACE_FMT_32_xRGB, SURF_WIDTH, SURF_HEIGHT, test->secondary_surface); } push_command(&update->ext); test->has_secondary = 1; break; } case SIMPLE_DESTROY_SURFACE: { SimpleSurfaceCmd *update; test->has_secondary = 0; update = destroy_surface(test->target_surface); test->target_surface = 0; push_command(&update->ext); break; } case DESTROY_PRIMARY: spice_qxl_destroy_primary_surface(&test->qxl_instance, 0); break; case CREATE_PRIMARY: create_primary_surface(test, command->create_primary.width, command->create_primary.height); break; } test->cmd_index = (test->cmd_index + 1) % test->num_commands; } static int req_cmd_notification(QXLInstance *qin) { Test *test = SPICE_CONTAINEROF(qin, Test, qxl_instance); test->core->timer_start(test->wakeup_timer, test->wakeup_ms); return TRUE; }
int main(void) { entry* entry_head = calloc(sizeof(entry), 1); snapshot* snapshot_head = calloc(sizeof(snapshot), 1); int latest_snapshotID = 1; char buffer[MAX_LINE_LENGTH]; printf("> "); while(fgets(buffer, sizeof(buffer), stdin)) { struct command_struct *command = get_command_struct(buffer); if(!command) continue; if(strcmp(command->args_malloc_ptr[0], "bye") == 0) { bye_command(snapshot_head, entry_head); free_command(command); printf("bye"); return 0; } else if(strcmp(command->args_malloc_ptr[0], "help") == 0) { print_help_string(); } else if(strcmp(command->args_malloc_ptr[0], "list") == 0) { list_command(command, entry_head, snapshot_head); } else if(strcmp(command->args_malloc_ptr[0], "get") == 0) { get_command(command, entry_head); } else if(strcmp(command->args_malloc_ptr[0], "del") == 0) { del_command(command, entry_head); } else if(strcmp(command->args_malloc_ptr[0], "purge") == 0) { purge_command(command, entry_head, snapshot_head); } else if(strcmp(command->args_malloc_ptr[0], "set") == 0) { set_command(command, entry_head); } else if(strcmp(command->args_malloc_ptr[0], "push") == 0) { push_command(command, entry_head); } else if(strcmp(command->args_malloc_ptr[0], "append") == 0) { append_command(command, entry_head); } else if(strcmp(command->args_malloc_ptr[0], "pick") == 0) { pick_command(command, entry_head); } else if(strcmp(command->args_malloc_ptr[0], "pluck") == 0) { pluck_command(command, entry_head); } else if(strcmp(command->args_malloc_ptr[0], "pop") == 0) { pop_command(command, entry_head); } else if(strcmp(command->args_malloc_ptr[0], "drop") == 0) { drop_command(command, snapshot_head); } else if(strcmp(command->args_malloc_ptr[0], "rollback") == 0) { rollback_command(command, snapshot_head, entry_head); } else if(strcmp(command->args_malloc_ptr[0], "checkout") == 0) { checkout_command(command, snapshot_head, entry_head); } else if(strcmp(command->args_malloc_ptr[0], "snapshot") == 0) { snapshot_command(snapshot_head, entry_head, &latest_snapshotID); } else if(strcmp(command->args_malloc_ptr[0], "min") == 0) { min_command(command, entry_head); } else if(strcmp(command->args_malloc_ptr[0], "max") == 0) { max_command(command, entry_head); } else if(strcmp(command->args_malloc_ptr[0], "sum") == 0) { sum_command(command, entry_head); } else if(strcmp(command->args_malloc_ptr[0], "len") == 0) { len_command(command, entry_head); } else if(strcmp(command->args_malloc_ptr[0], "rev") == 0) { rev_command(command, entry_head); } else if(strcmp(command->args_malloc_ptr[0], "uniq") == 0) { uniq_command(command, entry_head); } else if(strcmp(command->args_malloc_ptr[0], "sort") == 0) { sort_command(command, entry_head); } printf("\n> "); free_command(command); } bye_command(snapshot_head, entry_head); return 0; }