ARB
ps_database.cxx
Go to the documentation of this file.
1 
2 #include "ps_database.hxx"
3 
4 using namespace std;
5 
6 void PS_Database::reinit(const char *_name, bool _readonly) {
7  if (db_file) {
8  db_file->reinit(_name, _readonly);
9  }
10  else {
11  db_file = new PS_FileBuffer(_name, _readonly);
12  }
13  db_name2id_map.clear();
14  db_id2name_map.clear();
15  if (!db_rootnode.isNull()) db_rootnode.setNull();
16  db_rootnode = new PS_Node(-1);
17 }
18 
19 void PS_Database::readMappings(PS_FileBuffer *_file, ID2NameMap &_id2name_map, Name2IDMap &_name2id_map) {
20  char *buffer = (char *)malloc(_file->BUFFER_SIZE);
21  // read number of species
22  unsigned long int number_of_species = 0;
23  _file->get_ulong(number_of_species);
24  // read mappings
25  for (unsigned long int i = 0; i < number_of_species; ++i) {
26  // read id
27  SpeciesID id;
28  _file->get(&id, sizeof(SpeciesID));
29  // read name
30  unsigned int length_of_name;
31  _file->get_uint(length_of_name);
32  _file->get(buffer, length_of_name);
33  // store in mappings
34  string name(buffer, length_of_name);
35  _id2name_map[id] = name;
36  _name2id_map[name] = id;
37  }
38  free(buffer);
39 }
40 
41 void PS_Database::writeMappings(PS_FileBuffer *_file, ID2NameMap &_id2name_map) {
42  // write number of species
43  _file->put_ulong(_id2name_map.size());
44  // write mappings
45  for (ID2NameMapCIter i = _id2name_map.begin(); i != _id2name_map.end(); ++i) {
46  // write id
47  _file->put(&(i->first), sizeof(SpeciesID));
48  // write name
49  unsigned int length_of_name = i->second.size();
50  _file->put_uint(length_of_name);
51  _file->put(i->second.c_str(), length_of_name);
52  }
53 }
54 
55 void PS_Database::readTree(PS_FileBuffer *_file) {
56  if (!db_rootnode.isNull()) db_rootnode.setNull(); // discard old tree
57  db_rootnode = new PS_Node(-1);
58  db_rootnode->load(_file);
59 }
60 
61 void PS_Database::writeTree(PS_FileBuffer *_file) {
62  if (db_rootnode.isNull()) return; // no tree, no write
63  db_rootnode->save(_file);
64 }
65 
66 bool PS_Database::readHeader(PS_FileBuffer *_file) {
67  char *buffer = (char *) malloc(FILE_ID.size());
68  _file->get(buffer, FILE_ID.size());
69  bool file_ok = (FILE_ID.compare(buffer) == 0);
70  if (buffer) free(buffer);
71  return file_ok;
72 }
73 
74 void PS_Database::writeHeader(PS_FileBuffer *_file) {
75  _file->put(FILE_ID.c_str(), FILE_ID.size());
76 }
77 
78 void PS_Database::callback(void *_caller) {
79  //
80  // return if node has no probes
81  //
82  if (!((PS_Node *)_caller)->hasProbes()) return;
83 
84  //
85  // convert IDs from file to DB-IDs
86  //
87  IDSet path;
88  PS_NodePtr current_node = db_path;
89  while (current_node->hasChildren()) {
90  // get next node in path
91  pair<bool, PS_NodePtr> child = current_node->getChild(0);
92  ps_assert(child.first);
93  current_node = child.second;
94  // get ID from node
95  SpeciesID id = current_node->getNum();
96  // store ID in ID-Set
97  ID2IDMapCIter db_id = db_file2db_id_map.find(id);
98  path.insert((db_id == db_file2db_id_map.end()) ? id : db_id->second);
99  }
100 
101  //
102  // assert path
103  //
104  current_node = db_rootnode;
105  for (IDSetCIter id=path.begin(); id != path.end(); ++id) {
106  current_node = current_node->assertChild(*id);
107  }
108 
109  //
110  // append probes
111  //
112  current_node->addProbes(((PS_Node *)_caller)->getProbesBegin(), ((PS_Node *)_caller)->getProbesEnd());
113 }
114 
115 bool PS_Database::merge(const char *_other_db_name) {
116  //
117  // read other DB's mappings
118  //
119  PS_FileBuffer *other_db_file = new PS_FileBuffer(_other_db_name, PS_FileBuffer::READONLY);
120  Name2IDMap other_name2id_map;
121  ID2NameMap other_id2name_map;
122 
123  if (!readHeader(other_db_file)) return false; // not a file i wrote
124  readMappings(other_db_file, other_id2name_map, other_name2id_map);
125 
126  //
127  // get next assignable ID from highest used ID in mappings
128  //
129  SpeciesID next_usable_ID = (db_id2name_map.rbegin()->first > other_id2name_map.rbegin()->first) ? db_id2name_map.rbegin()->first + 1 : other_id2name_map.rbegin()->first + 1;
130 
131  //
132  // iterate over DB names
133  //
134  db_file2db_id_map.clear();
135  for (Name2IDMapCIter i=db_name2id_map.begin(); i != db_name2id_map.end(); ++i) {
136  // lookup name in other mapping
137  Name2IDMapIter other_i = other_name2id_map.find(i->first);
138 
139  // if name not in other mapping
140  if (other_i == other_name2id_map.end()) {
141  // lookup ID in other mapping
142  ID2NameMapIter other_i2 = other_id2name_map.find(i->second);
143 
144  // if ID is used for other name in other_mappings
145  if (other_i2 != other_id2name_map.end()) {
146  // lookup other name in DB mapping
147  Name2IDMapIter i2 = db_name2id_map.find(other_i2->second);
148 
149  // if other name is not in DB mapping
150  if (i2 == db_name2id_map.end()) {
151  // store file->DB ID mapping
152  db_file2db_id_map[other_i2->first] = next_usable_ID;
153  ++next_usable_ID;
154  // erase handled name
155  other_name2id_map.erase(other_i2->second);
156  }
157  }
158  }
159  // if name in other mapping with different ID
160  else if (other_i->second != i->second) {
161  // store file->DB ID mapping
162  db_file2db_id_map[other_i->second] = i->second;
163  // erase handled name
164  other_name2id_map.erase(other_i);
165  }
166  // if name in other mapping with same ID
167  else {
168  // erase handled name
169  other_name2id_map.erase(other_i);
170  }
171  }
172 
173  //
174  // iterate over remaining file names
175  //
176  for (Name2IDMapCIter other_i=other_name2id_map.begin(); other_i != other_name2id_map.end(); ++other_i) {
177  db_file2db_id_map[other_i->second] = next_usable_ID;
178  ++next_usable_ID;
179  }
180  db_MAX_ID = next_usable_ID-1;
181 
182  // append tree if mappings are equal
183  if (db_file2db_id_map.empty()) {
184  return db_rootnode->append(other_db_file);
185  }
186  // merge in tree if mappings differ
187  else {
188  if (db_path.isNull()) db_path = new PS_Node(-1);
189  return db_path->read(other_db_file, this);
190  }
191 }
void put_ulong(unsigned long int _ul)
void get(void *_data, int _length)
static const bool READONLY
Name2IDMap::const_iterator Name2IDMapCIter
Definition: ps_defs.hxx:24
const char * id
Definition: AliAdmin.cxx:17
std::set< SpeciesID > IDSet
Definition: ps_defs.hxx:39
SpeciesID getNum() const
Definition: ps_node.hxx:72
PS_NodePtr assertChild(SpeciesID _id)
Definition: ps_node.hxx:89
void addProbes(PS_ProbeSetCIter _begin, PS_ProbeSetCIter _end)
Definition: ps_node.hxx:138
STL namespace.
ID2IDMap::const_iterator ID2IDMapCIter
Definition: ps_defs.hxx:48
ID2NameMap::iterator ID2NameMapIter
Definition: ps_defs.hxx:26
char buffer[MESSAGE_BUFFERSIZE]
Definition: seq_search.cxx:34
void put_uint(unsigned int _ui)
void get_uint(unsigned int &_ui)
void put(const void *_data, int _length)
bool read(PS_FileBuffer *_fb, PS_Callback *_call_destination)
Definition: ps_node.cxx:197
bool hasChildren() const
Definition: ps_node.hxx:112
static const int BUFFER_SIZE
std::map< std::string, SpeciesID > Name2IDMap
Definition: ps_defs.hxx:22
Name2IDMap::iterator Name2IDMapIter
Definition: ps_defs.hxx:23
void get_ulong(unsigned long int &_ul)
ID2NameMap::const_iterator ID2NameMapCIter
Definition: ps_defs.hxx:27
pair< bool, PS_NodePtr > getChild(SpeciesID id)
Definition: ps_node.hxx:101
#define ps_assert(cond)
Definition: ps_assert.hxx:18
std::map< SpeciesID, std::string > ID2NameMap
Definition: ps_defs.hxx:25
IDSet::const_iterator IDSetCIter
Definition: ps_defs.hxx:41