source: tags/ms_r18q1/PROBE_SET/ps_database.cxx

Last change on this file was 15738, checked in by westram, 7 years ago
  • rename only
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.1 KB
Line 
1
2#include "ps_database.hxx"
3
4using namespace std;
5
6void 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
19void 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
41void 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
55void 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
61void PS_Database::writeTree(PS_FileBuffer *_file) {
62    if (db_rootnode.isNull()) return;                     // no tree, no write
63    db_rootnode->save(_file);
64}
65
66bool 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
74void PS_Database::writeHeader(PS_FileBuffer *_file) {
75    _file->put(FILE_ID.c_str(), FILE_ID.size());
76}
77
78void 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
115bool 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}
Note: See TracBrowser for help on using the repository browser.