|
/****************************************************************************
|
|
* This file is part of the project AqFinance.
|
|
* AqFinance (c) by 2009 Martin Preuss, all rights reserved.
|
|
*
|
|
* The license for this file can be found in the file COPYING which you
|
|
* should have received along with this file.
|
|
****************************************************************************/
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
|
|
#include "rollback_p.h"
|
|
#include "dbdir_l.h"
|
|
#include "table_l.h"
|
|
#include <aqdatabase/aqdb_db_be.h>
|
|
#include <aqdatabase/aqdb_object_be.h>
|
|
#include <aqdatabase/aqdb_sessionlog.h>
|
|
#include <aqdatabase/aqdb_sessiondescr.h>
|
|
|
|
#include <gwenhywfar/misc.h>
|
|
#include <gwenhywfar/debug.h>
|
|
#include <gwenhywfar/directory.h>
|
|
#include <gwenhywfar/idlist64.h>
|
|
|
|
|
|
|
|
|
|
int GWENHYWFAR_CB AQDB_DbDir_GetRollbackSessions(AQDB_DB *db,
|
|
uint32_t aflags,
|
|
AQDB_SESSION_DESCR_LIST *sl) {
|
|
AQDB_ID qid=0;
|
|
int rv;
|
|
AQDB_ID oids[16];
|
|
int len;
|
|
char qexpr[256];
|
|
|
|
snprintf(qexpr, sizeof(qexpr)-1, "$type==%d", AQDB_SessionLogType_EndEdit);
|
|
|
|
/* query */
|
|
rv=AQDB_DB_QuerySubmit(db,
|
|
AQDB_DB_DIR_TID_ROLLBACKLOG,
|
|
0,
|
|
qexpr,
|
|
0, /* query flags */
|
|
&qid);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
|
|
/* browse all objects */
|
|
len=16;
|
|
rv=AQDB_DB_QueryGetFirst(db, qid, oids, &len);
|
|
while(rv==0) {
|
|
int i;
|
|
|
|
for (i=0; i<len; i++) {
|
|
AQDB_OBJECT *o=NULL;
|
|
AQDB_SESSION_LOG *sessionLog=NULL;
|
|
const void *p;
|
|
uint32_t l;
|
|
|
|
rv=AQDB_DB_ReadObject(db,
|
|
AQDB_DB_DIR_TID_ROLLBACKLOG,
|
|
oids[i],
|
|
&o);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "Error reading object %d (%d)", oids[i], rv);
|
|
AQDB_DB_QueryClose(db, qid);
|
|
return rv;
|
|
}
|
|
|
|
/* get session log */
|
|
rv=AQDB_SessionLog_fromObject(o, &sessionLog);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "Error reading session log from object %d (%d)", oids[i], rv);
|
|
AQDB_Object_free(o);
|
|
AQDB_DB_QueryClose(db, qid);
|
|
return rv;
|
|
}
|
|
AQDB_Object_free(o);
|
|
|
|
/* get session description */
|
|
p=AQDB_SessionLog_GetDataPtr(sessionLog);
|
|
l=AQDB_SessionLog_GetDataLen(sessionLog);
|
|
|
|
if (p && l) {
|
|
AQDB_SESSION_DESCR *sd=NULL;
|
|
int cnt;
|
|
|
|
cnt=AQDB_DbDir_GetColumnCount(db, AQDB_DB_DIR_TID_ROLLBACKLOG);
|
|
if (cnt<1) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", cnt);
|
|
AQDB_SessionLog_free(sessionLog);
|
|
AQDB_DB_QueryClose(db, qid);
|
|
return cnt;
|
|
}
|
|
|
|
/* read session descriptor object from session log */
|
|
o=AQDB_DbDir_Object_fromBuffer(AQDB_DB_DIR_TID_ROLLBACKLOG, oids[i], cnt, p, l);
|
|
if (o==NULL) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "Error reading session description object %d (%d)", oids[i], rv);
|
|
AQDB_SessionLog_free(sessionLog);
|
|
AQDB_DB_QueryClose(db, qid);
|
|
return rv;
|
|
}
|
|
|
|
/* read session descriptor from object */
|
|
rv=AQDB_SessionDescr_fromObject(o, &sd);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "Error reading session description from object %d (%d)", oids[i], rv);
|
|
AQDB_Object_free(o);
|
|
AQDB_SessionLog_free(sessionLog);
|
|
AQDB_DB_QueryClose(db, qid);
|
|
return rv;
|
|
}
|
|
AQDB_Object_free(o);
|
|
|
|
/* add session description */
|
|
AQDB_SessionDescr_List_Add(sd, sl);
|
|
}
|
|
AQDB_SessionLog_free(sessionLog);
|
|
} /* for */
|
|
|
|
len=16;
|
|
rv=AQDB_DB_QueryGetNext(db, qid, oids, &len);
|
|
}
|
|
|
|
AQDB_DB_QueryClose(db, qid);
|
|
if (rv<0) {
|
|
if (rv!=GWEN_ERROR_NOT_FOUND) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int AQDB_DbDir__GetSessionObjectIds(AQDB_DB *db, AQDB_ID sid, GWEN_IDLIST64 *idlist) {
|
|
AQDB_ID qid=0;
|
|
int rv;
|
|
AQDB_ID oids[16];
|
|
int len;
|
|
char qexpr[256];
|
|
|
|
snprintf(qexpr, sizeof(qexpr)-1, "$sessionid>=%lu", (unsigned long) sid);
|
|
|
|
/* query */
|
|
rv=AQDB_DB_QuerySubmit(db,
|
|
AQDB_DB_DIR_TID_ROLLBACKLOG,
|
|
0,
|
|
qexpr,
|
|
0, /* query flags */
|
|
&qid);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
|
|
/* append all object ids */
|
|
len=16;
|
|
rv=AQDB_DB_QueryGetFirst(db, qid, oids, &len);
|
|
while(rv==0) {
|
|
int i;
|
|
|
|
for (i=0; i<len; i++)
|
|
GWEN_IdList64_AddId(idlist, oids[i]);
|
|
|
|
len=16;
|
|
rv=AQDB_DB_QueryGetNext(db, qid, oids, &len);
|
|
}
|
|
|
|
AQDB_DB_QueryClose(db, qid);
|
|
if (rv<0) {
|
|
if (rv!=GWEN_ERROR_NOT_FOUND) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int AQDB_DbDir__WriteObjectFromLog(AQDB_DB *db, const AQDB_SESSION_LOG *sl) {
|
|
AQDB_DBDIR_TABLE *table=NULL;
|
|
AQDB_ID tid=0;
|
|
AQDB_ID oid=0;
|
|
int rv;
|
|
const void *p;
|
|
uint32_t l;
|
|
|
|
/* get current table id */
|
|
rv=AQDB_DbDir_FindTableByName(db, AQDB_SessionLog_GetTableName(sl), &table);
|
|
if (rv>=0)
|
|
tid=AQDB_DbDir_Table_GetId(table);
|
|
else if (rv<0) {
|
|
if (rv==GWEN_ERROR_NOT_FOUND) {
|
|
/* name not in list, open the table */
|
|
rv=AQDB_DB_OpenTable(db, AQDB_SessionLog_GetTableName(sl),
|
|
AQDB_ACTION_FLAGS_READ | AQDB_ACTION_FLAGS_WRITE,
|
|
&tid);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
}
|
|
else {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
/* get object id */
|
|
oid=AQDB_SessionLog_GetObjectId(sl);
|
|
|
|
/* get data */
|
|
p=AQDB_SessionLog_GetDataPtr(sl);
|
|
l=AQDB_SessionLog_GetDataLen(sl);
|
|
|
|
if (p && l) {
|
|
AQDB_OBJECT *o=NULL;
|
|
int cnt;
|
|
|
|
cnt=AQDB_DbDir_GetColumnCount(db, tid);
|
|
if (cnt<1) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", cnt);
|
|
return cnt;
|
|
}
|
|
|
|
/* read object from session log */
|
|
o=AQDB_DbDir_Object_fromBuffer(tid, oid, cnt, p, l);
|
|
if (o==NULL) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "Error reading object %d (%d)", oid, rv);
|
|
return rv;
|
|
}
|
|
|
|
/* write object to DB */
|
|
rv=AQDB_DbDir_ReallyWriteObject(db, o);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
AQDB_Object_free(o);
|
|
return rv;
|
|
}
|
|
AQDB_Object_free(o);
|
|
}
|
|
else {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int AQDB_DbDir__DeleteObjectFromLog(AQDB_DB *db, const AQDB_SESSION_LOG *sl) {
|
|
AQDB_DBDIR_TABLE *table=NULL;
|
|
AQDB_ID tid=0;
|
|
AQDB_ID oid=0;
|
|
int rv;
|
|
|
|
/* get current table id */
|
|
rv=AQDB_DbDir_FindTableByName(db, AQDB_SessionLog_GetTableName(sl), &table);
|
|
if (rv>=0) {
|
|
tid=AQDB_DbDir_Table_GetId(table);
|
|
}
|
|
else if (rv<0) {
|
|
if (rv==GWEN_ERROR_NOT_FOUND) {
|
|
/* name not in list, open the table */
|
|
rv=AQDB_DB_OpenTable(db, AQDB_SessionLog_GetTableName(sl),
|
|
AQDB_ACTION_FLAGS_READ | AQDB_ACTION_FLAGS_WRITE,
|
|
&tid);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
}
|
|
else {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
/* get object id */
|
|
oid=AQDB_SessionLog_GetObjectId(sl);
|
|
|
|
/* delete object from DB */
|
|
rv=AQDB_DbDir_ReallyDeleteObject(db, tid, oid);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int AQDB_DbDir__UndoSession(AQDB_DB *db, AQDB_ID sid, GWEN_IDLIST64 *idlist) {
|
|
GWEN_IDLIST64_ITERATOR *it;
|
|
uint64_t id;
|
|
|
|
it=GWEN_IdList64_Iterator_new(idlist);
|
|
id=GWEN_IdList64_Iterator_GetFirstId(it);
|
|
while(id!=0) {
|
|
AQDB_OBJECT *o=NULL;
|
|
AQDB_SESSION_LOG *sessionLog=NULL;
|
|
int rv;
|
|
|
|
rv=AQDB_DbDir_ReallyReadObject(db, AQDB_DB_DIR_TID_ROLLBACKLOG, id, &o);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "Error reading object %lu (%d)", (unsigned long) id, rv);
|
|
GWEN_IdList64_Iterator_free(it);
|
|
return rv;
|
|
}
|
|
|
|
/* get session log */
|
|
rv=AQDB_SessionLog_fromObject(o, &sessionLog);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "Error reading session log from object %lu (%d)", (unsigned long) id, rv);
|
|
AQDB_Object_free(o);
|
|
GWEN_IdList64_Iterator_free(it);
|
|
return rv;
|
|
}
|
|
AQDB_Object_free(o);
|
|
|
|
switch(AQDB_SessionLog_GetType(sessionLog)) {
|
|
case AQDB_SessionLogType_BeginEdit:
|
|
case AQDB_SessionLogType_EndEdit:
|
|
break;
|
|
|
|
case AQDB_SessionLogType_AddObject:
|
|
/* add given object */
|
|
rv=AQDB_DbDir__WriteObjectFromLog(db, sessionLog);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
GWEN_IdList64_Iterator_free(it);
|
|
return rv;
|
|
}
|
|
break;
|
|
|
|
case AQDB_SessionLogType_DelObject:
|
|
/* remove given object */
|
|
rv=AQDB_DbDir__DeleteObjectFromLog(db, sessionLog);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
GWEN_IdList64_Iterator_free(it);
|
|
return rv;
|
|
}
|
|
break;
|
|
|
|
case AQDB_SessionLogType_ChgObject:
|
|
/* modify given object */
|
|
rv=AQDB_DbDir__WriteObjectFromLog(db, sessionLog);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
GWEN_IdList64_Iterator_free(it);
|
|
return rv;
|
|
}
|
|
break;
|
|
} /* switch */
|
|
|
|
AQDB_SessionLog_free(sessionLog);
|
|
|
|
/* delete log entry */
|
|
/* DBG_ERROR(0, "Deleting log entry %lu", (unsigned long int) id); */
|
|
rv=AQDB_DbDir_ReallyDeleteObject(db, AQDB_DB_DIR_TID_ROLLBACKLOG, id);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
GWEN_IdList64_Iterator_free(it);
|
|
return rv;
|
|
}
|
|
|
|
id=GWEN_IdList64_Iterator_GetNextId(it);
|
|
}
|
|
GWEN_IdList64_Iterator_free(it);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int AQDB_DbDir_UndoSessionForUser(AQDB_DB *db, AQDB_ID sid, const char *userName) {
|
|
GWEN_IDLIST64 *idlist;
|
|
int rv;
|
|
|
|
rv=AQDB_DbDir_BeginEdit(db, AQDB_DB_DIR_SESSION_FLAGS_ROLLBACK, userName);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
|
|
idlist=GWEN_IdList64_newWithSteps(AQDB_DBDIR_IDLIST_ENTRIES);
|
|
rv=AQDB_DbDir__GetSessionObjectIds(db, sid, idlist);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
AQDB_DB_EndEdit(db, AQDB_ACTION_FLAGS_ABORT);
|
|
GWEN_IdList64_free(idlist);
|
|
return rv;
|
|
}
|
|
|
|
/* reverse-sort the list */
|
|
rv=GWEN_IdList64_ReverseSort(idlist);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
AQDB_DB_EndEdit(db, AQDB_ACTION_FLAGS_ABORT);
|
|
GWEN_IdList64_free(idlist);
|
|
return rv;
|
|
}
|
|
|
|
/* now undo the session */
|
|
rv=AQDB_DbDir__UndoSession(db, sid, idlist);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
AQDB_DB_EndEdit(db, AQDB_ACTION_FLAGS_ABORT);
|
|
GWEN_IdList64_free(idlist);
|
|
return rv;
|
|
}
|
|
GWEN_IdList64_free(idlist);
|
|
|
|
rv=AQDB_DB_EndEdit(db, 0);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
AQDB_DB_EndEdit(db, AQDB_ACTION_FLAGS_ABORT);
|
|
return rv;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int GWENHYWFAR_CB AQDB_DbDir_UndoSession(AQDB_DB *db, AQDB_ID sid) {
|
|
int rv;
|
|
|
|
rv=AQDB_DbDir_UndoSessionForUser(db, sid, "unknown");
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|