fixed: thread plugin didn't correctly set the last item and replies (in 'thread' table)

when deleting an answer
added: ThreadInfo::Repair() method
       will be used by 'fsck' winix function       
added: plugins/groupitem 
       directory for a new plugin: 'groupitem'
       


git-svn-id: svn://ttmath.org/publicrep/winix/trunk@725 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
2011-03-23 17:54:53 +00:00
parent ba63c8c661
commit d68731fd55
15 changed files with 498 additions and 50 deletions

View File

@@ -75,6 +75,7 @@ void AddMounts(PluginInfo & info)
void RemoveThread(PluginInfo & i)
{
thread_info.RemoveThread(i.l1);
thread_info.RemoveThreadAnswer(i.l1);
}
@@ -128,6 +129,18 @@ void EndRequest(PluginInfo & info)
}
// !! temporarily
void Rescan(PluginInfo & info)
{
if( info.config->Bool(L"thread_rescan", false) == true )
{
log << log1 << "---------- rescanning thread db ------------- " << logend;
thread_info.Repair();
log << log1 << "---------- thread db rescanning is finished ------------- " << logend;
}
}
} // namespace
@@ -152,6 +165,9 @@ using namespace Thread;
plugin.Assign(WINIX_PL_THREAD_SET_SORTTAB_INDEX, SetSortTabIndex);
plugin.Assign(WINIX_PL_THREAD_PREPARE_THREAD, PrepareThread);
// temporarily
plugin.Assign(WINIX_PLUGIN_INIT, Rescan);
tdb.SetConn(info.db->GetConn());
tdb.LogQueries(info.config->log_db_query);

View File

@@ -75,7 +75,7 @@ void Reply::MakePost()
// !! jak bedzie dostepne assert
// ASSERT(files_dir)
if( tdb->GetThreadByFileId(cur->request->item.id, thread) != WINIX_ERR_OK )
if( tdb->GetThread(cur->request->item.id, thread) != WINIX_ERR_OK )
{
thread.Clear();
thread.file_id = cur->request->item.id;
@@ -99,7 +99,7 @@ void Reply::MakePost()
cur->request->status = system->AddFile(answer);
if( cur->request->status == WINIX_ERR_OK )
cur->request->status = tdb->EditThreadAddItem(cur->request->item.id, answer.id);
cur->request->status = tdb->AddAnswer(cur->request->item.id, answer.id);
if( cur->request->status == WINIX_ERR_OK )

View File

@@ -58,7 +58,7 @@ void TDb::SetThread(PGresult * r, int col, Thread & thread)
Error TDb::GetThreadByFileId(long file_id, Thread & thread)
Error TDb::GetThread(long file_id, Thread & thread)
{
PGresult * r = 0;
Error status = WINIX_ERR_OK;
@@ -175,7 +175,7 @@ return status;
Error TDb::EditThreadAddItem(long file_id, long answer_id)
Error TDb::AddAnswer(long file_id, long answer_id)
{
query.Clear();
query << R("insert into plugins.thread_files (file_id, answer_id) values (")
@@ -200,7 +200,7 @@ return DoCommand(query);
long TDb::FindLastItem(long file_id)
long TDb::FindLastAnswer(long file_id)
{
PGresult * r = 0;
Error status = WINIX_ERR_OK;
@@ -231,7 +231,7 @@ return last_item_id;
Error TDb::EditThreadRemoveItem(long item_id)
Error TDb::RemoveAnswer(long answer_id)
{
PGresult * r1 = 0;
PGresult * r2 = 0;
@@ -239,10 +239,10 @@ Error TDb::EditThreadRemoveItem(long item_id)
try
{
// selecting files which have item_id as an answer
// selecting files which have answer_id as an answer
query.Clear();
query << R("select file_id from plugins.thread_files where answer_id = ")
<< item_id
<< answer_id
<< R(";");
r1 = AssertQuery(query);
@@ -254,10 +254,11 @@ Error TDb::EditThreadRemoveItem(long item_id)
for(int i=0 ; i<rows ; ++i)
file_id_tab[i] = AssertValueLong(r1, i, 0);
// deleting those answers
query.Clear();
query << R("delete from plugins.thread_files where answer_id = ")
<< item_id
<< answer_id
<< R(";");
r2 = AssertQuery(query);
@@ -269,7 +270,7 @@ Error TDb::EditThreadRemoveItem(long item_id)
log << log2 << "ThreadDb: deleted " << rows << " rows from plugins.thread_files" << logend;
// setting new last_items to the files
status = EditThreadRecalcFiles(file_id_tab);
status = RemoveAnswerRecalcLast(file_id_tab);
}
catch(const Error & e)
{
@@ -283,22 +284,28 @@ return status;
}
Error TDb::RemoveAnswerRecalcLast(long file_id)
{
long last_item_id = FindLastAnswer(file_id);
Error TDb::EditThreadRecalcFiles(const std::vector<long> & file_id_tab)
query.Clear();
query << R("update plugins.thread set (replies, last_item) = (replies-1,")
<< last_item_id
<< R(") where file_id=")
<< file_id
<< R(";");
return DoCommand(query);
}
Error TDb::RemoveAnswerRecalcLast(const std::vector<long> & file_id_tab)
{
for(size_t i=0 ; i<file_id_tab.size() ; ++i)
{
long file_id = file_id_tab[i];
long last_item_id = FindLastItem(file_id);
query.Clear();
query << R("update plugins.thread set (replies, last_item) = (replies-1,")
<< last_item_id
<< R(") where file_id=")
<< file_id
<< R(";");
Error status = DoCommand(query);
long file_id = file_id_tab[i];
Error status = RemoveAnswerRecalcLast(file_id);
if( status != WINIX_ERR_OK )
return status;
@@ -308,6 +315,49 @@ return WINIX_ERR_OK;
}
Error TDb::RecalcThread(long file_id)
{
long replies = CalcAnswers(file_id);
long last_item = FindLastAnswer(file_id);
query.Clear();
query << R("update plugins.thread set (replies, last_item) = (")
<< replies
<< last_item
<< R(") where file_id=")
<< file_id
<< R(";");
return DoCommand(query);
}
long TDb::CalcAnswers(long file_id)
{
PGresult * r = 0;
long answers = 0;
try
{
query.Clear();
query << R("select count(file_id) from plugins.thread_files where file_id=") << file_id << R(";");
r = AssertQuery(query);
AssertResult(r, PGRES_TUPLES_OK);
if( Rows(r) == 1 )
answers = AssertValueLong(r, 0, 0);
}
catch(const Error &)
{
}
ClearResult(r);
return answers;
}
@@ -354,6 +404,64 @@ return status;
Error TDb::RemoveAnswerOnly(long answer_id)
{
PGresult * r = 0;
Error status = WINIX_ERR_OK;
try
{
query.Clear();
query << R("delete from plugins.thread_files where answer_id=") << answer_id << R(";");
r = AssertQuery(query);
AssertResult(r, PGRES_COMMAND_OK);
long rows = AffectedRows(r);
if( rows > 0 )
log << log2 << "ThreadDb: deleted " << rows << " rows from plugins.thread_files" << logend;
}
catch(const Error & e)
{
status = e;
}
ClearResult(r);
return status;
}
void TDb::GetAllThreadsId(std::vector<long> & file_id)
{
PGresult * r = 0;
file_id.clear();
try
{
query.Clear();
query << R("select file_id from plugins.thread;");
r = AssertQuery(query);
AssertResult(r, PGRES_TUPLES_OK);
int rows = Rows(r);
file_id.resize(rows);
for(int i=0 ; i<rows ; ++i)
file_id[i] = AssertValueLong(r, i, 0);
}
catch(const Error &)
{
}
ClearResult(r);
}

View File

@@ -26,14 +26,42 @@ class TDb : public DbBase
{
public:
/*
high level interface
*/
Error AddThread(const Thread & thread);
Error GetThreadByFileId(long file_id, Thread & thread);
Error GetThread(long file_id, Thread & thread);
Error GetThreads(const std::vector<long> & file_id_tab, std::vector<Thread> & thread_tab);
Error GetAnswers(long file_id, std::vector<long> & answer_id_tab);
Error EditThreadAddItem(long file_id, long answer_id);
Error EditThreadRemoveItem(long file_id);
Error RemoveThread(long file_id);
long FindLastItem(long file_id);
Error AddAnswer(long file_id, long answer_id);
Error GetAnswers(long file_id, std::vector<long> & answer_id_tab);
Error RemoveAnswer(long answer_id);
/*
low level interface
*/
// looking for the last answer in a thread (in 'thread_files' table)
// this is not the value from 'thread' table
long FindLastAnswer(long file_id);
// returning all threads id (file_id) (from 'thread' table)
void GetAllThreadsId(std::vector<long> & file_id);
// removing only the answer in 'thread_files' table without updating 'thread' table
Error RemoveAnswerOnly(long answer_id);
// returning how many answers there are
// calculating from 'thread_files' table
// this is not the value from 'thread' table
long CalcAnswers(long file_id);
// recalculating last_item, replies in 'thread' table on a given thread
Error RecalcThread(long file_id);
private:
@@ -43,9 +71,10 @@ private:
Thread thread_temp;
std::vector<long> file_id_tab;
void SetThreadColumns(PGresult * r);
void SetThread(PGresult * r, int col, Thread & thread);
Error EditThreadRecalcFiles(const std::vector<long> & file_id_tab);
void SetThreadColumns(PGresult * r);
void SetThread(PGresult * r, int col, Thread & thread);
Error RemoveAnswerRecalcLast(long file_id);
Error RemoveAnswerRecalcLast(const std::vector<long> & file_id_tab);
};

View File

@@ -71,6 +71,67 @@ void ThreadInfo::RemoveThread(long file_id)
void ThreadInfo::RemoveThreadAnswer(long answer_id)
{
tdb->RemoveAnswer(answer_id);
}
void ThreadInfo::RepairAnswer(long answer_id)
{
iq.Clear();
iq.SetAll(false, false);
iq.WhereId(answer_id);
iq.WhereType(Item::file); // !! moze w przyszlosci pozwolic takze na symlinki?
if( db->GetItem(repair_item, iq) == WINIX_ERR_NO_ITEM )
{
log << log3 << "ThreadInfo: there is no a file for thread answer_id: " << answer_id << logend;
tdb->RemoveAnswerOnly(answer_id);
}
}
void ThreadInfo::RepairAnswers(long file_id)
{
tdb->GetAnswers(file_id, repair_answer_tab);
for(size_t i=0 ; i<repair_answer_tab.size() ; ++i)
RepairAnswer(repair_answer_tab[i]);
}
void ThreadInfo::Repair(long file_id)
{
iq.Clear();
iq.SetAll(false, false);
iq.WhereId(file_id);
iq.WhereType(Item::file); // !! moze w przyszlosci pozwolic takze na symlinki?
if( db->GetItem(repair_item, iq) == WINIX_ERR_NO_ITEM )
{
log << log3 << "ThreadInfo: there is no a file for thread file_id: " << file_id << logend;
tdb->RemoveThread(file_id);
}
else
{
RepairAnswers(file_id);
tdb->RecalcThread(file_id);
}
}
void ThreadInfo::Repair()
{
tdb->GetAllThreadsId(repair_id_tab);
for(size_t i=0 ; i<repair_id_tab.size() ; ++i)
Repair(repair_id_tab[i]);
}
} // namespace

View File

@@ -64,7 +64,10 @@ public:
void RemoveThread(long file_id);
void RemoveThreadAnswer(long answer_id);
// repairing the database
void Repair();
private:
@@ -73,9 +76,13 @@ private:
System * system;
std::vector<Item*> out_dir_tab;
std::vector<long> remove_answer_id_tab;
Item out_item;
std::vector<long> remove_answer_id_tab, repair_id_tab, repair_answer_tab;
Item out_item, repair_item;
DbItemQuery iq;
void RepairAnswer(long answer_id);
void RepairAnswers(long file_id);
void Repair(long file_id);
};