Hello,
After asking my question the first time (a few month ago) Andrew and JoaquĆn both tried to help me, but unfortunately I still didn't find problem's root cause / solution. Partially it might be because I did not supplied enough information therefore I wrote a short-simple-single threaded console app that might help you reproduce the problem / find my mistake (this of course not a production app therefore there are a lot of hard-coded constants etc.).
The apps code contains 3 files " BoostTestingApp.cpp", " DataContainer.h", and "DataContainer.cpp" which could be found below.
But first the instructions:
To create the "damaged" data file use the following input:
2 (insert)
-1 (maximum)
5 (empty) - during this operation kill proc manually from the program manager (yes I am using windows) which simulates the crush.
To reproduce the problem (assertion window pops up) use the following inputs (restart the app using debug after creating the damaged file) :
Input #1:
4 (delete all)
Input #2:
3 (delete)
500000 (this particular record)
The program :
BoostTestingApp.cpp
------------------
#include "stdafx.h"
#include "DataContainer.h"
#include <iostream>
#include
using namespace std;
int ID;
void insert(CDataContainer* dataContainer)
{
cout<<"how many rows"<>rows;
rows = (rows==-1)?1300000:rows;
bool success = true;
for (int i=0;iInsert(data);
ID++;
}
if (success)
{
cout<<"command finished successfully"<>key.id;
if (dataContainer->GetAndDelete(key,&entry,true))
cout<<"command finished successfully"<m_dataTable->size()!=0)
{
CDataContainer::MainIDIndex& idx= dataContainer->m_dataTable->get();
CDataContainer::MainIDIndex::const_iterator it = idx.begin();
dataContainer->m_dataTable->erase(it);
}
cout<<"command finished successfully"<Initialize();
int option;
int max_size =0;
bool loop = true;
while (loop)
{
cout<<"options:"<>option;
switch(option)
{
case 1:
cout<<"current size : "<<(int)dataContainer->m_dataTable->size()<m_dataTable->clear();
cout<<"finished"<
#include
#include
#include
#include
#include
#include
#include "Windows.h"
#include "stdafx.h"
using boost::multi_index_container;
using namespace boost::multi_index;
typedef struct
{
int id;//key1
int key2;
int key3;
int key4;
int key5;
char text[20];
}
DataBasicStructure;
struct DataKey
{
DataKey(){}
DataKey(int pid):id(pid){}
int id;
};
struct DataEntry{
DataBasicStructure data;
int ID()const
{
return data.id;
}
int Key2()const
{
return data.key2;
}
int Key3()const
{
return data.key3;
}
int Key4()const
{
return data.key4;
}
int Key5()const
{
return data.key5;
}
char Text() const
{
return data.text[0];
}
};
class ContainerLocker;
typedef indexed_by<
ordered_unique,
ordered_non_unique,
ordered_non_unique,
ordered_non_unique,
ordered_non_unique>
ContainerIndexSpecifierList;
typedef boost::interprocess::allocator ContainerAllocator;
typedef multi_index_container data_container;
#define MAIN_ID 0
#define KEY_2 1
#define KEY_3 2
#define KEY_4 3
#define KEY_5 4
typedef nth_index_iterator::type Data_Iterator;
class CDataContainer
{
public:
typedef nth_index::type MainIDIndex;
typedef nth_index::type Key2Index;
typedef nth_index::type Key3Index;
typedef nth_index::type Key4Index;
typedef nth_index::type Key5Index;
bool m_isInitialized;
long DataTableMaxEntries;
boost::interprocess::managed_mapped_file *m_containerMapFile;
data_container *m_dataTable;
bool Init(const char *fileName);
void BackUpFile( const char * fileName );
class IteratorLocation
{
friend class CDataContainer;
public:
bool regetRange;
IteratorLocation() { regetRange = true; }
std::pair m_MainIDIterator;
std::pair m_key2Iterator;
std::pair m_key3Iterator;
std::pair m_key4Iterator;
std::pair m_key5Iterator;
};
BOOL Initialize();
bool Insert( const DataBasicStructure &data);
bool GetAndDelete(DataKey key, DataEntry *data, bool del);
};
DataContainer.cpp
-----------------
#include "DataContainer.h"
bool CDataContainer::Init( IN const char *fileName)
{
bool returnStatus = true;
int count = 0;
int dataRequiredSize = DataTableMaxEntries*sizeof(DataEntry);
dataRequiredSize += ((int)(0.1*dataRequiredSize) > 100*1024*1024) ? (int)(0.1*dataRequiredSize) : 100*1024*1024;
dataRequiredSize *= 3;
try
{
m_containerMapFile = new boost::interprocess::managed_mapped_file(boost::interprocess::open_only,fileName);
bool suc = true;
suc &= (m_containerMapFile != NULL);
suc &= (m_containerMapFile->get_size()== dataRequiredSize);
suc &= m_containerMapFile->check_sanity();
if (suc)
{
bool initSucceed = true;
m_dataTable = m_containerMapFile->find_or_construct(fileName)(
data_container::ctor_args_list(),
data_container::allocator_type(m_containerMapFile->get_segment_manager()));
if (NULL!=m_dataTable)
{
if (m_dataTable->size() > DataTableMaxEntries)
m_containerMapFile = NULL;
}
initSucceed = (NULL!=m_containerMapFile)?true:false;
if (!initSucceed)
m_containerMapFile = NULL;
}
else
m_containerMapFile = NULL;
}
catch (...)
{
m_containerMapFile = NULL;
}
try
{
if (m_containerMapFile == NULL)
{
std::string backupFile(fileName);
backupFile.append("_bak");
remove(backupFile.c_str());
rename(fileName, backupFile.c_str());
m_containerMapFile = new boost::interprocess::managed_mapped_file(
boost::interprocess::create_only,fileName,
dataRequiredSize);
m_dataTable = m_containerMapFile->construct(fileName)(
data_container::ctor_args_list(),
data_container::allocator_type(m_containerMapFile->get_segment_manager()));
}
m_isInitialized = true;
}
catch (...)
{
m_isInitialized = false;
returnStatus = false;
}
return returnStatus;
}
void CDataContainer::BackUpFile( const char * fileName )
{
std::string backupFile(fileName);
backupFile.append("_bak");
remove(backupFile.c_str());
rename(fileName, backupFile.c_str());
}
bool CDataContainer::Insert( IN const DataBasicStructure &data)
{
bool rv = true;
if ((int)m_dataTable->size() < DataTableMaxEntries)
{
DataEntry entry;
entry.data = data;
try
{
m_dataTable->insert(entry);
}
catch (...)
{
rv = false;
}
}
else
{
rv = false;
}
return rv;
}
bool CDataContainer::GetAndDelete( DataKey key, DataEntry *data,bool del)
{
bool rc = true;
MainIDIndex& idx=m_dataTable->get();
MainIDIndex::iterator it = idx.find(key.id);
if (it == idx.end())
rc = false;
else
{
*data = *it;
if (del)
{
idx.erase(it);
}
}
return rc;
}
BOOL CDataContainer::Initialize()
{
BOOL result = TRUE;
DataTableMaxEntries = 1300000;
if (Init("boost_Testing") != true)
return FALSE;
return result;
}
Thank you very much,
Eli.