Ejemplo n.º 1
0
Archivo: elua.c Proyecto: indie21/elua
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);
}
Ejemplo n.º 2
0
/*
 * 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);
}
Ejemplo n.º 3
0
/*
 * 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);
}
Ejemplo n.º 4
0
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);
}
Ejemplo n.º 5
0
/* 
 * 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);
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
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);  */
}
Ejemplo n.º 9
0
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;
}
Ejemplo n.º 10
0
Archivo: elua.c Proyecto: indie21/elua
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);
}
Ejemplo n.º 11
0
/*
 * 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);
}
Ejemplo n.º 12
0
// 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;
}
Ejemplo n.º 13
0
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;
}
Ejemplo n.º 14
0
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;
}
Ejemplo n.º 15
0
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;
}