aboutsummaryrefslogtreecommitdiff
path: root/lib/lua/src/print.c
blob: e240cfc3c6087105bb8a04d861e590a52f2b2911 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
/*
** $Id: print.c,v 1.55a 2006/05/31 13:30:05 lhf Exp $
** print bytecodes
** See Copyright Notice in lua.h
*/

#include <ctype.h>
#include <stdio.h>

#define luac_c
#define LUA_CORE

#include "ldebug.h"
#include "lobject.h"
#include "lopcodes.h"
#include "lundump.h"

#define PrintFunction	luaU_print

#define Sizeof(x)	((int)sizeof(x))
#define VOID(p)		((const void*)(p))

static void PrintString(const TString* ts)
{
 const char* s=getstr(ts);
 size_t i,n=ts->tsv.len;
 putchar('"');
 for (i=0; i<n; i++)
 {
  int c=s[i];
  switch (c)
  {
   case '"': printf("\\\""); break;
   case '\\': printf("\\\\"); break;
   case '\a': printf("\\a"); break;
   case '\b': printf("\\b"); break;
   case '\f': printf("\\f"); break;
   case '\n': printf("\\n"); break;
   case '\r': printf("\\r"); break;
   case '\t': printf("\\t"); break;
   case '\v': printf("\\v"); break;
   default:	if (isprint((unsigned char)c))
   			putchar(c);
		else
			printf("\\%03u",(unsigned char)c);
  }
 }
 putchar('"');
}

static void PrintConstant(const Proto* f, int i)
{
 const TValue* o=&f->k[i];
 switch (ttype(o))
 {
  case LUA_TNIL:
	printf("nil");
	break;
  case LUA_TBOOLEAN:
	printf(bvalue(o) ? "true" : "false");
	break;
  case LUA_TNUMBER:
	printf(LUA_NUMBER_FMT,nvalue(o));
	break;
  case LUA_TSTRING:
	PrintString(rawtsvalue(o));
	break;
  default:				/* cannot happen */
	printf("? type=%d",ttype(o));
	break;
 }
}

static void PrintCode(const Proto* f)
{
 const Instruction* code=f->code;
 int pc,n=f->sizecode;
 for (pc=0; pc<n; pc++)
 {
  Instruction i=code[pc];
  OpCode o=GET_OPCODE(i);
  int a=GETARG_A(i);
  int b=GETARG_B(i);
  int c=GETARG_C(i);
  int bx=GETARG_Bx(i);
  int sbx=GETARG_sBx(i);
  int line=getline(f,pc);
  printf("\t%d\t",pc+1);
  if (line>0) printf("[%d]\t",line); else printf("[-]\t");
  printf("%-9s\t",luaP_opnames[o]);
  switch (getOpMode(o))
  {
   case iABC:
    printf("%d",a);
    if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (-1-INDEXK(b)) : b);
    if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (-1-INDEXK(c)) : c);
    break;
   case iABx:
    if (getBMode(o)==OpArgK) printf("%d %d",a,-1-bx); else printf("%d %d",a,bx);
    break;
   case iAsBx:
    if (o==OP_JMP) printf("%d",sbx); else printf("%d %d",a,sbx);
    break;
  }
  switch (o)
  {
   case OP_LOADK:
    printf("\t; "); PrintConstant(f,bx);
    break;
   case OP_GETUPVAL:
   case OP_SETUPVAL:
    printf("\t; %s", (f->sizeupvalues>0) ? getstr(f->upvalues[b]) : "-");
    break;
   case OP_GETGLOBAL:
   case OP_SETGLOBAL:
    printf("\t; %s",svalue(&f->k[bx]));
    break;
   case OP_GETTABLE:
   case OP_SELF:
    if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); }
    break;
   case OP_SETTABLE:
   case OP_ADD:
   case OP_SUB:
   case OP_MUL:
   case OP_DIV:
   case OP_POW:
   case OP_EQ:
   case OP_LT:
   case OP_LE:
    if (ISK(b) || ISK(c))
    {
     printf("\t; ");
     if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-");
     printf(" ");
     if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-");
    }
    break;
   case OP_JMP:
   case OP_FORLOOP:
   case OP_FORPREP:
    printf("\t; to %d",sbx+pc+2);
    break;
   case OP_CLOSURE:
    printf("\t; %p",VOID(f->p[bx]));
    break;
   case OP_SETLIST:
    if (c==0) printf("\t; %d",(int)code[++pc]);
    else printf("\t; %d",c);
    break;
   default:
    break;
  }
  printf("\n");
 }
}

#define SS(x)	(x==1)?"":"s"
#define S(x)	x,SS(x)

static void PrintHeader(const Proto* f)
{
 const char* s=getstr(f->source);
 if (*s=='@' || *s=='=')
  s++;
 else if (*s==LUA_SIGNATURE[0])
  s="(bstring)";
 else
  s="(string)";
 printf("\n%s <%s:%d,%d> (%d instruction%s, %d bytes at %p)\n",
 	(f->linedefined==0)?"main":"function",s,
	f->linedefined,f->lastlinedefined,
	S(f->sizecode),f->sizecode*Sizeof(Instruction),VOID(f));
 printf("%d%s param%s, %d slot%s, %d upvalue%s, ",
	f->numparams,f->is_vararg?"+":"",SS(f->numparams),
	S(f->maxstacksize),S(f->nups));
 printf("%d local%s, %d constant%s, %d function%s\n",
	S(f->sizelocvars),S(f->sizek),S(f->sizep));
}

static void PrintConstants(const Proto* f)
{
 int i,n=f->sizek;
 printf("constants (%d) for %p:\n",n,VOID(f));
 for (i=0; i<n; i++)
 {
  printf("\t%d\t",i+1);
  PrintConstant(f,i);
  printf("\n");
 }
}

static void PrintLocals(const Proto* f)
{
 int i,n=f->sizelocvars;
 printf("locals (%d) for %p:\n",n,VOID(f));
 for (i=0; i<n; i++)
 {
  printf("\t%d\t%s\t%d\t%d\n",
  i,getstr(f->locvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1);
 }
}

static void PrintUpvalues(const Proto* f)
{
 int i,n=f->sizeupvalues;
 printf("upvalues (%d) for %p:\n",n,VOID(f));
 if (f->upvalues==NULL) return;
 for (i=0; i<n; i++)
 {
  printf("\t%d\t%s\n",i,getstr(f->upvalues[i]));
 }
}

void PrintFunction(const Proto* f, int full)
{
 int i,n=f->sizep;
 PrintHeader(f);
 PrintCode(f);
 if (full)
 {
  PrintConstants(f);
  PrintLocals(f);
  PrintUpvalues(f);
 }
 for (i=0; i<n; i++) PrintFunction(f->p[i],full);
}
an class="hl opt">; sqlite3_stmt* dbs_select_range; sqlite3_stmt* dbs_select_withActor; sqlite3_stmt* dbs_knownActor_select; sqlite3_stmt* dbs_knownActor_insert; sqlite3_stmt* dbs_knownNode_select; sqlite3_stmt* dbs_knownNode_insert; struct Stack { int node; int quantity; }; struct ActionRow { int id; int actor; time_t timestamp; int type; std::string location, list; int index, add; Stack stack; int nodeMeta; int x, y, z; int oldNode; int oldParam1, oldParam2; std::string oldMeta; int newNode; int newParam1, newParam2; std::string newMeta; int guessed; }; struct Entity { int id; std::string name; }; typedef std::vector<Entity> Entities; Entities KnownActors; Entities KnownNodes; void registerNewActor(int id, std::string name) { Entity newActor; newActor.id = id; newActor.name = name; KnownActors.push_back(newActor); //std::cout << "New actor registered: " << id << " | " << name << std::endl; } void registerNewNode(int id, std::string name) { Entity newNode; newNode.id = id; newNode.name = name; KnownNodes.push_back(newNode); //std::cout << "New node registered: " << id << " | " << name << std::endl; } int getActorId(std::string name) { Entities::const_iterator iter; for (iter = KnownActors.begin(); iter != KnownActors.end(); ++iter) if (iter->name == name) { return iter->id; } sqlite3_reset(dbs_knownActor_insert); sqlite3_bind_text(dbs_knownActor_insert, 1, name.c_str(), -1, NULL); sqlite3_step(dbs_knownActor_insert); int id = sqlite3_last_insert_rowid(dbh); //std::cout << "Actor ID insert returns " << insert << std::endl; registerNewActor(id, name); return id; } int getNodeId(std::string name) { Entities::const_iterator iter; for (iter = KnownNodes.begin(); iter != KnownNodes.end(); ++iter) if (iter->name == name) { return iter->id; } sqlite3_reset(dbs_knownNode_insert); sqlite3_bind_text(dbs_knownNode_insert, 1, name.c_str(), -1, NULL); sqlite3_step(dbs_knownNode_insert); int id = sqlite3_last_insert_rowid(dbh); registerNewNode(id, name); return id; } const char * getActorName(int id) { Entities::const_iterator iter; //std::cout << "getActorName of id " << id << std::endl; for (iter = KnownActors.begin(); iter != KnownActors.end(); ++iter) if (iter->id == id) { return iter->name.c_str(); } return ""; } const char * getNodeName(int id) { Entities::const_iterator iter; //std::cout << "getNodeName of id " << id << std::endl; for (iter = KnownNodes.begin(); iter != KnownNodes.end(); ++iter) if (iter->id == id) { return iter->name.c_str(); } return ""; } Stack getStackFromString(std::string text) { Stack stack; size_t off = text.find_last_of(" "); stack.node = getNodeId(text.substr(0, off)); stack.quantity = atoi(text.substr(off + 1).c_str()); return stack; } std::string getStringFromStack(Stack stack) { std::string text; text.append(getNodeName(stack.node)); text.append(" "); text.append(itos(stack.quantity)); return text; } bool SQL_createDatabase(void) { infostream << "CreateDB:" << dbp << std::endl; int dbs = sqlite3_exec(dbh, "CREATE TABLE IF NOT EXISTS `actor` (" "`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," "`name` TEXT NOT NULL);" "CREATE TABLE IF NOT EXISTS `node` (" "`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," "`name` TEXT NOT NULL);" "CREATE TABLE IF NOT EXISTS `action` (" "`id` INTEGER PRIMARY KEY AUTOINCREMENT," "`actor` INTEGER NOT NULL," "`timestamp` TIMESTAMP NOT NULL," "`type` INTEGER NOT NULL," "`list` TEXT," "`index` INTEGER," "`add` INTEGER," "`stackNode` INTEGER," "`stackQuantity` INTEGER," "`nodeMeta` INTEGER," "`x` INT," "`y` INT," "`z` INT," "`oldNode` INTEGER," "`oldParam1` INTEGER," "`oldParam2` INTEGER," "`oldMeta` TEXT," "`newNode` INTEGER," "`newParam1` INTEGER," "`newParam2` INTEGER," "`newMeta` TEXT," "`guessedActor` INTEGER," "FOREIGN KEY (`actor`) REFERENCES `actor`(`id`)," "FOREIGN KEY (`oldNode`) REFERENCES `node`(`id`)," "FOREIGN KEY (`newNode`) REFERENCES `node`(`id`));" "CREATE INDEX IF NOT EXISTS `actionActor` ON `action`(`actor`);" "CREATE INDEX IF NOT EXISTS `actionTimestamp` ON `action`(`timestamp`);", NULL, NULL, NULL); if (dbs == SQLITE_ABORT) { throw FileNotGoodException("Could not create sqlite3 database structure"); } else if (dbs != 0) { throw FileNotGoodException("SQL Rollback: Exec statement to create table structure returned a non-zero value"); } else { infostream << "SQL Rollback: SQLite3 database structure was created" << std::endl; } return true; } void SQL_databaseCheck(void) { if (dbh) { return; } infostream << "Database connection setup" << std::endl; bool needsCreate = !fs::PathExists(dbp); int dbo = sqlite3_open_v2(dbp.c_str(), &dbh, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL); if (dbo != SQLITE_OK) { infostream << "SQLROLLBACK: SQLite3 database failed to open: " << sqlite3_errmsg(dbh) << std::endl; throw FileNotGoodException("Cannot open database file"); } if (needsCreate) { SQL_createDatabase(); } int dbr; dbr = sqlite3_prepare_v2(dbh, "INSERT INTO `action` (" " `actor`, `timestamp`, `type`," " `list`, `index`, `add`, `stackNode`, `stackQuantity`, `nodeMeta`," " `x`, `y`, `z`," " `oldNode`, `oldParam1`, `oldParam2`, `oldMeta`," " `newNode`, `newParam1`, `newParam2`, `newMeta`," " `guessedActor`" ") VALUES (" " ?, ?, ?," " ?, ?, ?, ?, ?, ?," " ?, ?, ?," " ?, ?, ?, ?," " ?, ?, ?, ?," " ?" ");", -1, &dbs_insert, NULL); if (dbr != SQLITE_OK) { throw FileNotGoodException(sqlite3_errmsg(dbh)); } dbr = sqlite3_prepare_v2(dbh, "REPLACE INTO `action` (" " `actor`, `timestamp`, `type`," " `list`, `index`, `add`, `stackNode`, `stackQuantity`, `nodeMeta`," " `x`, `y`, `z`," " `oldNode`, `oldParam1`, `oldParam2`, `oldMeta`," " `newNode`, `newParam1`, `newParam2`, `newMeta`," " `guessedActor`, `id`" ") VALUES (" " ?, ?, ?," " ?, ?, ?, ?, ?, ?," " ?, ?, ?," " ?, ?, ?, ?," " ?, ?, ?, ?," " ?, ?" ");", -1, &dbs_replace, NULL); if (dbr != SQLITE_OK) { throw FileNotGoodException(sqlite3_errmsg(dbh)); } dbr = sqlite3_prepare_v2(dbh, "SELECT" " `actor`, `timestamp`, `type`," " `list`, `index`, `add`, `stackNode`, `stackQuantity`, `nodemeta`," " `x`, `y`, `z`," " `oldNode`, `oldParam1`, `oldParam2`, `oldMeta`," " `newNode`, `newParam1`, `newParam2`, `newMeta`," " `guessedActor`" " FROM `action`" " WHERE `timestamp` >= ?" " ORDER BY `timestamp` DESC, `id` DESC", -1, &dbs_select, NULL); if (dbr != SQLITE_OK) { throw FileNotGoodException(itos(dbr).c_str()); } dbr = sqlite3_prepare_v2(dbh, "SELECT" " `actor`, `timestamp`, `type`," " `list`, `index`, `add`, `stackNode`, `stackQuantity`, `nodemeta`," " `x`, `y`, `z`," " `oldNode`, `oldParam1`, `oldParam2`, `oldMeta`," " `newNode`, `newParam1`, `newParam2`, `newMeta`," " `guessedActor`" " FROM `action`" " WHERE `timestamp` >= ?" " AND `x` IS NOT NULL" " AND `y` IS NOT NULL" " AND `z` IS NOT NULL" " AND ABS(`x` - ?) <= ?" " AND ABS(`y` - ?) <= ?" " AND ABS(`z` - ?) <= ?" " ORDER BY `timestamp` DESC, `id` DESC" " LIMIT 0,?", -1, &dbs_select_range, NULL); if (dbr != SQLITE_OK) { throw FileNotGoodException(itos(dbr).c_str()); } dbr = sqlite3_prepare_v2(dbh, "SELECT" " `actor`, `timestamp`, `type`," " `list`, `index`, `add`, `stackNode`, `stackQuantity`, `nodemeta`," " `x`, `y`, `z`," " `oldNode`, `oldParam1`, `oldParam2`, `oldMeta`," " `newNode`, `newParam1`, `newParam2`, `newMeta`," " `guessedActor`" " FROM `action`" " WHERE `timestamp` >= ?" " AND `actor` = ?" " ORDER BY `timestamp` DESC, `id` DESC", -1, &dbs_select_withActor, NULL); if (dbr != SQLITE_OK) { throw FileNotGoodException(itos(dbr).c_str()); } dbr = sqlite3_prepare_v2(dbh, "SELECT `id`, `name` FROM `actor`", -1, &dbs_knownActor_select, NULL); if (dbr != SQLITE_OK) { throw FileNotGoodException(itos(dbr).c_str()); } dbr = sqlite3_prepare_v2(dbh, "INSERT INTO `actor` (`name`) VALUES (?)", -1, &dbs_knownActor_insert, NULL); if (dbr != SQLITE_OK) { throw FileNotGoodException(itos(dbr).c_str()); } dbr = sqlite3_prepare_v2(dbh, "SELECT `id`, `name` FROM `node`", -1, &dbs_knownNode_select, NULL); if (dbr != SQLITE_OK) { throw FileNotGoodException(itos(dbr).c_str()); } dbr = sqlite3_prepare_v2(dbh, "INSERT INTO `node` (`name`) VALUES (?)", -1, &dbs_knownNode_insert, NULL); if (dbr != SQLITE_OK) { throw FileNotGoodException(itos(dbr).c_str()); } infostream << "SQL prepared statements setup correctly" << std::endl; int select; sqlite3_reset(dbs_knownActor_select); while (SQLITE_ROW == (select = sqlite3_step(dbs_knownActor_select))) registerNewActor( sqlite3_column_int(dbs_knownActor_select, 0), reinterpret_cast<const char *>(sqlite3_column_text(dbs_knownActor_select, 1)) ); sqlite3_reset(dbs_knownNode_select); while (SQLITE_ROW == (select = sqlite3_step(dbs_knownNode_select))) registerNewNode( sqlite3_column_int(dbs_knownNode_select, 0), reinterpret_cast<const char *>(sqlite3_column_text(dbs_knownNode_select, 1)) ); return; } bool SQL_registerRow(ActionRow row) { SQL_databaseCheck(); sqlite3_stmt * dbs_do = (row.id) ? dbs_replace : dbs_insert; /* std::cout << (row.id? "Replacing": "Inserting") << " ActionRow" << std::endl; */ sqlite3_reset(dbs_do); int bind [22], ii = 0; bool nodeMeta = false; bind[ii++] = sqlite3_bind_int(dbs_do, 1, row.actor); bind[ii++] = sqlite3_bind_int64(dbs_do, 2, row.timestamp); bind[ii++] = sqlite3_bind_int(dbs_do, 3, row.type); if (row.type == RollbackAction::TYPE_MODIFY_INVENTORY_STACK) { std::string loc = row.location; std::string locType = loc.substr(0, loc.find(":")); nodeMeta = (locType == "nodemeta"); bind[ii++] = sqlite3_bind_text(dbs_do, 4, row.list.c_str(), row.list.size(), NULL); bind[ii++] = sqlite3_bind_int(dbs_do, 5, row.index); bind[ii++] = sqlite3_bind_int(dbs_do, 6, row.add); bind[ii++] = sqlite3_bind_int(dbs_do, 7, row.stack.node); bind[ii++] = sqlite3_bind_int(dbs_do, 8, row.stack.quantity); bind[ii++] = sqlite3_bind_int(dbs_do, 9, (int) nodeMeta); if (nodeMeta) { std::string x, y, z; int l, r; l = loc.find(':') + 1; r = loc.find(','); x = loc.substr(l, r - l); l = r + 1; r = loc.find(',', l); y = loc.substr(l, r - l); z = loc.substr(r + 1); bind[ii++] = sqlite3_bind_int(dbs_do, 10, atoi(x.c_str())); bind[ii++] = sqlite3_bind_int(dbs_do, 11, atoi(y.c_str())); bind[ii++] = sqlite3_bind_int(dbs_do, 12, atoi(z.c_str())); } } else { bind[ii++] = sqlite3_bind_null(dbs_do, 4); bind[ii++] = sqlite3_bind_null(dbs_do, 5); bind[ii++] = sqlite3_bind_null(dbs_do, 6); bind[ii++] = sqlite3_bind_null(dbs_do, 7); bind[ii++] = sqlite3_bind_null(dbs_do, 8); bind[ii++] = sqlite3_bind_null(dbs_do, 9); } if (row.type == RollbackAction::TYPE_SET_NODE) { bind[ii++] = sqlite3_bind_int(dbs_do, 10, row.x); bind[ii++] = sqlite3_bind_int(dbs_do, 11, row.y); bind[ii++] = sqlite3_bind_int(dbs_do, 12, row.z); bind[ii++] = sqlite3_bind_int(dbs_do, 13, row.oldNode); bind[ii++] = sqlite3_bind_int(dbs_do, 14, row.oldParam1); bind[ii++] = sqlite3_bind_int(dbs_do, 15, row.oldParam2); bind[ii++] = sqlite3_bind_text(dbs_do, 16, row.oldMeta.c_str(), row.oldMeta.size(), NULL); bind[ii++] = sqlite3_bind_int(dbs_do, 17, row.newNode); bind[ii++] = sqlite3_bind_int(dbs_do, 18, row.newParam1); bind[ii++] = sqlite3_bind_int(dbs_do, 19, row.newParam2); bind[ii++] = sqlite3_bind_text(dbs_do, 20, row.newMeta.c_str(), row.newMeta.size(), NULL); bind[ii++] = sqlite3_bind_int(dbs_do, 21, row.guessed ? 1 : 0); } else { if (!nodeMeta) { bind[ii++] = sqlite3_bind_null(dbs_do, 10); bind[ii++] = sqlite3_bind_null(dbs_do, 11); bind[ii++] = sqlite3_bind_null(dbs_do, 12); } bind[ii++] = sqlite3_bind_null(dbs_do, 13); bind[ii++] = sqlite3_bind_null(dbs_do, 14); bind[ii++] = sqlite3_bind_null(dbs_do, 15); bind[ii++] = sqlite3_bind_null(dbs_do, 16); bind[ii++] = sqlite3_bind_null(dbs_do, 17); bind[ii++] = sqlite3_bind_null(dbs_do, 18); bind[ii++] = sqlite3_bind_null(dbs_do, 19); bind[ii++] = sqlite3_bind_null(dbs_do, 20); bind[ii++] = sqlite3_bind_null(dbs_do, 21); } if (row.id) { bind[ii++] = sqlite3_bind_int(dbs_do, 22, row.id); } for (ii = 0; ii < 20; ++ii) if (bind[ii] != SQLITE_OK) infostream << "WARNING: failed to bind param " << ii + 1 << " when inserting an entry in table setnode" << std::endl; /* std::cout << "========DB-WRITTEN==========" << std::endl; std::cout << "id: " << row.id << std::endl; std::cout << "actor: " << row.actor << std::endl; std::cout << "time: " << row.timestamp << std::endl; std::cout << "type: " << row.type << std::endl; if (row.type == RollbackAction::TYPE_MODIFY_INVENTORY_STACK) { std::cout << "Location: " << row.location << std::endl; std::cout << "List: " << row.list << std::endl; std::cout << "Index: " << row.index << std::endl; std::cout << "Add: " << row.add << std::endl; std::cout << "Stack: " << row.stack << std::endl; } if (row.type == RollbackAction::TYPE_SET_NODE) { std::cout << "x: " << row.x << std::endl; std::cout << "y: " << row.y << std::endl; std::cout << "z: " << row.z << std::endl; std::cout << "oldNode: " << row.oldNode << std::endl; std::cout << "oldParam1: " << row.oldParam1 << std::endl; std::cout << "oldParam2: " << row.oldParam2 << std::endl; std::cout << "oldMeta: " << row.oldMeta << std::endl; std::cout << "newNode: " << row.newNode << std::endl; std::cout << "newParam1: " << row.newParam1 << std::endl; std::cout << "newParam2: " << row.newParam2 << std::endl; std::cout << "newMeta: " << row.newMeta << std::endl; std::cout << "DESERIALIZE" << row.newMeta.c_str() << std::endl; std::cout << "guessed: " << row.guessed << std::endl; } */ int written = sqlite3_step(dbs_do); return written == SQLITE_DONE; //if (written != SQLITE_DONE) // std::cout << "WARNING: rollback action not written: " << sqlite3_errmsg(dbh) << std::endl; //else std::cout << "Action correctly inserted via SQL" << std::endl; } std::list<ActionRow> actionRowsFromSelect(sqlite3_stmt* stmt) { std::list<ActionRow> rows; const unsigned char * text; size_t size; while (SQLITE_ROW == sqlite3_step(stmt)) { ActionRow row; row.actor = sqlite3_column_int(stmt, 0); row.timestamp = sqlite3_column_int64(stmt, 1); row.type = sqlite3_column_int(stmt, 2); if (row.type == RollbackAction::TYPE_MODIFY_INVENTORY_STACK) { text = sqlite3_column_text(stmt, 3); size = sqlite3_column_bytes(stmt, 3); row.list = std::string(reinterpret_cast<const char*>(text), size); row.index = sqlite3_column_int(stmt, 4); row.add = sqlite3_column_int(stmt, 5); row.stack.node = sqlite3_column_int(stmt, 6); row.stack.quantity = sqlite3_column_int(stmt, 7); row.nodeMeta = sqlite3_column_int(stmt, 8); } if (row.type == RollbackAction::TYPE_SET_NODE || row.nodeMeta) { row.x = sqlite3_column_int(stmt, 9); row.y = sqlite3_column_int(stmt, 10); row.z = sqlite3_column_int(stmt, 11); } if (row.type == RollbackAction::TYPE_SET_NODE) { row.oldNode = sqlite3_column_int(stmt, 12); row.oldParam1 = sqlite3_column_int(stmt, 13); row.oldParam2 = sqlite3_column_int(stmt, 14); text = sqlite3_column_text(stmt, 15); size = sqlite3_column_bytes(stmt, 15); row.oldMeta = std::string(reinterpret_cast<const char*>(text), size); row.newNode = sqlite3_column_int(stmt, 16); row.newParam1 = sqlite3_column_int(stmt, 17); row.newParam2 = sqlite3_column_int(stmt, 18); text = sqlite3_column_text(stmt, 19); size = sqlite3_column_bytes(stmt, 19); row.newMeta = std::string(reinterpret_cast<const char*>(text), size); row.guessed = sqlite3_column_int(stmt, 20); } row.location = row.nodeMeta ? "nodemeta:" : getActorName(row.actor); if (row.nodeMeta) { row.location.append(itos(row.x)); row.location.append(","); row.location.append(itos(row.y)); row.location.append(","); row.location.append(itos(row.z)); } /* std::cout << "=======SELECTED==========" << "\n"; std::cout << "Actor: " << row.actor << "\n"; std::cout << "Timestamp: " << row.timestamp << "\n"; if (row.type == RollbackAction::TYPE_MODIFY_INVENTORY_STACK) { std::cout << "list: " << row.list << "\n"; std::cout << "index: " << row.index << "\n"; std::cout << "add: " << row.add << "\n"; std::cout << "stackNode: " << row.stack.node << "\n"; std::cout << "stackQuantity: " << row.stack.quantity << "\n"; if (row.nodeMeta) { std::cout << "X: " << row.x << "\n"; std::cout << "Y: " << row.y << "\n"; std::cout << "Z: " << row.z << "\n"; } std::cout << "Location: " << row.location << "\n"; } else { std::cout << "X: " << row.x << "\n"; std::cout << "Y: " << row.y << "\n"; std::cout << "Z: " << row.z << "\n"; std::cout << "oldNode: " << row.oldNode << "\n"; std::cout << "oldParam1: " << row.oldParam1 << "\n"; std::cout << "oldParam2: " << row.oldParam2 << "\n"; std::cout << "oldMeta: " << row.oldMeta << "\n"; std::cout << "newNode: " << row.newNode << "\n"; std::cout << "newParam1: " << row.newParam1 << "\n"; std::cout << "newParam2: " << row.newParam2 << "\n"; std::cout << "newMeta: " << row.newMeta << "\n"; std::cout << "guessed: " << row.guessed << "\n"; } */ rows.push_back(row); } return rows; } ActionRow actionRowFromRollbackAction(RollbackAction action) { ActionRow row; row.id = 0; row.actor = getActorId(action.actor); row.timestamp = action.unix_time; row.type = action.type; if (row.type == RollbackAction::TYPE_MODIFY_INVENTORY_STACK) { row.location = action.inventory_location; row.list = action.inventory_list; row.index = action.inventory_index; row.add = action.inventory_add; row.stack = getStackFromString(action.inventory_stack); } else { row.x = action.p.X; row.y = action.p.Y; row.z = action.p.Z; row.oldNode = getNodeId(action.n_old.name); row.oldParam1 = action.n_old.param1; row.oldParam2 = action.n_old.param2; row.oldMeta = action.n_old.meta; row.newNode = getNodeId(action.n_new.name); row.newParam1 = action.n_new.param1; row.newParam2 = action.n_new.param2; row.newMeta = action.n_new.meta; row.guessed = action.actor_is_guess; } return row; } std::list<RollbackAction> rollbackActionsFromActionRows(std::list<ActionRow> rows) { std::list<RollbackAction> actions; std::list<ActionRow>::const_iterator it; for (it = rows.begin(); it != rows.end(); ++it) { RollbackAction action; action.actor = (it->actor) ? getActorName(it->actor) : ""; action.unix_time = it->timestamp; action.type = static_cast<RollbackAction::Type>(it->type); switch (action.type) { case RollbackAction::TYPE_MODIFY_INVENTORY_STACK: action.inventory_location = it->location.c_str(); action.inventory_list = it->list; action.inventory_index = it->index; action.inventory_add = it->add; action.inventory_stack = getStringFromStack(it->stack); break; case RollbackAction::TYPE_SET_NODE: action.p = v3s16(it->x, it->y, it->z); action.n_old.name = getNodeName(it->oldNode); action.n_old.param1 = it->oldParam1; action.n_old.param2 = it->oldParam2; action.n_old.meta = it->oldMeta; action.n_new.name = getNodeName(it->newNode); action.n_new.param1 = it->newParam1; action.n_new.param2 = it->newParam2; action.n_new.meta = it->newMeta; break; default: throw ("W.T.F."); break; } actions.push_back(action); } return actions; } std::list<ActionRow> SQL_getRowsSince(time_t firstTime, std::string actor = "") { sqlite3_stmt *dbs_stmt = (!actor.length()) ? dbs_select : dbs_select_withActor; sqlite3_reset(dbs_stmt); sqlite3_bind_int64(dbs_stmt, 1, firstTime); if (actor.length()) { sqlite3_bind_int(dbs_stmt, 2, getActorId(actor)); } return actionRowsFromSelect(dbs_stmt); } std::list<ActionRow> SQL_getRowsSince_range(time_t firstTime, v3s16 p, int range, int limit) { sqlite3_stmt *stmt = dbs_select_range; sqlite3_reset(stmt); sqlite3_bind_int64(stmt, 1, firstTime); sqlite3_bind_int(stmt, 2, (int) p.X); sqlite3_bind_int(stmt, 3, range); sqlite3_bind_int(stmt, 4, (int) p.Y); sqlite3_bind_int(stmt, 5, range); sqlite3_bind_int(stmt, 6, (int) p.Z); sqlite3_bind_int(stmt, 7, range); sqlite3_bind_int(stmt, 8, limit); return actionRowsFromSelect(stmt); } std::list<RollbackAction> SQL_getActionsSince_range(time_t firstTime, v3s16 p, int range, int limit) { std::list<ActionRow> rows = SQL_getRowsSince_range(firstTime, p, range, limit); return rollbackActionsFromActionRows(rows); } std::list<RollbackAction> SQL_getActionsSince(time_t firstTime, std::string actor = "") { std::list<ActionRow> rows = SQL_getRowsSince(firstTime, actor); return rollbackActionsFromActionRows(rows); } void TXT_migrate(std::string filepath) { std::cout << "Migrating from rollback.txt to rollback.sqlite" << std::endl; SQL_databaseCheck(); std::ifstream fh(filepath.c_str(), std::ios::in | std::ios::ate); if (!fh.good()) { throw ("DIE"); } std::streampos filesize = fh.tellg(); if (filesize > 10) { fh.seekg(0); std::string bit; int i = 0; int id = 1; time_t t = 0; do { ActionRow row; row.id = id; // Get the timestamp std::getline(fh, bit, ' '); bit = trim(bit); if (!atoi(trim(bit).c_str())) { std::getline(fh, bit); continue; } row.timestamp = atoi(bit.c_str()); // Get the actor row.actor = getActorId(trim(deSerializeJsonString(fh))); // Get the action type std::getline(fh, bit, '['); std::getline(fh, bit, ' '); if (bit == "modify_inventory_stack") { row.type = RollbackAction::TYPE_MODIFY_INVENTORY_STACK; } if (bit == "set_node") { row.type = RollbackAction::TYPE_SET_NODE; } if (row.type == RollbackAction::TYPE_MODIFY_INVENTORY_STACK) { row.location = trim(deSerializeJsonString(fh));