source: tags/arb_5.5/ARBDB/adname.c

Last change on this file was 6101, checked in by westram, 16 years ago
  • fix warning "format not a string literal and no format arguments"
    • GB_warning → GB_warning/GB_warningf
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.2 KB
Line 
1/* ============================================================ */
2/*                                                              */
3/*   File      : adname.c                                       */
4/*   Purpose   : species names                                  */
5/*                                                              */
6/*   Institute of Microbiology (Technical University Munich)    */
7/*   www.arb-home.de                                            */
8/*                                                              */
9/* ============================================================ */
10
11#include <string.h>
12#include <stdlib.h>
13#include <ctype.h>
14
15#include <adlocal.h>
16#include <arbdbt.h>
17#include <ad_config.h>
18
19/********************************************************************************************
20                Rename one or many species (only one session at a time/ uses
21                commit abort transaction)
22********************************************************************************************/
23struct gbt_renamed_struct {
24    int     used_by;
25    char    data[1];
26
27};
28
29struct gbt_rename_struct {
30    GB_HASH *renamed_hash;
31    GB_HASH *old_species_hash;
32    GBDATA *gb_main;
33    GBDATA *gb_species_data;
34    int all_flag;
35} gbtrst;
36
37GB_ERROR GBT_begin_rename_session(GBDATA *gb_main, int all_flag) {
38    /* Starts a rename session.
39     * If whole database shall be renamed, set 'all_flag' == 1.
40     * Use GBT_abort_rename_session() or GBT_commit_rename_session() to end the session.
41     */
42   
43    GB_ERROR error = GB_push_transaction(gb_main);
44    if (!error) {
45        gbtrst.gb_main         = gb_main;
46        gbtrst.gb_species_data = GB_search(gb_main,"species_data",GB_CREATE_CONTAINER);
47
48        if (!all_flag) { // this is meant to be used for single or few species
49            int hash_size = 256;
50
51            gbtrst.renamed_hash     = GBS_create_dynaval_hash(hash_size, GB_MIND_CASE, GBS_dynaval_free);
52            gbtrst.old_species_hash = 0;
53        }
54        else {
55            int hash_size = GBT_get_species_hash_size(gb_main);
56
57            gbtrst.renamed_hash     = GBS_create_dynaval_hash(hash_size, GB_MIND_CASE, GBS_dynaval_free);
58            gbtrst.old_species_hash = GBT_create_species_hash(gb_main);
59        }
60        gbtrst.all_flag = all_flag;
61    }
62    return error;
63}
64
65GB_ERROR GBT_rename_species(const char *oldname, const  char *newname, GB_BOOL ignore_protection)
66{
67    GBDATA   *gb_species;
68    GBDATA   *gb_name;
69    GB_ERROR  error;
70
71    if (strcmp(oldname, newname) == 0)
72        return 0;
73
74#if defined(DEBUG) && 1
75    if (isdigit(oldname[0])) {
76        printf("oldname='%s' newname='%s'\n", oldname, newname);
77    }
78#endif
79
80    if (gbtrst.all_flag) {
81        gb_assert(gbtrst.old_species_hash);
82        gb_species = (GBDATA *)GBS_read_hash(gbtrst.old_species_hash,oldname);
83    }
84    else {
85        GBDATA *gb_found_species;
86
87        gb_assert(gbtrst.old_species_hash == 0);
88        gb_found_species = GBT_find_species_rel_species_data(gbtrst.gb_species_data, newname);
89        gb_species       = GBT_find_species_rel_species_data(gbtrst.gb_species_data, oldname);
90
91        if (gb_found_species && gb_species != gb_found_species) {
92            return GB_export_errorf("A species named '%s' already exists.",newname);
93        }
94    }
95
96    if (!gb_species) {
97        return GB_export_errorf("Expected that a species named '%s' exists (maybe there are duplicate species, database might be corrupt)",oldname);
98    }
99
100    gb_name = GB_entry(gb_species,"name");
101    if (ignore_protection) GB_push_my_security(gbtrst.gb_main);
102    error   = GB_write_string(gb_name,newname);
103    if (ignore_protection) GB_pop_my_security(gbtrst.gb_main);
104
105    if (!error){
106        struct gbt_renamed_struct *rns;
107        if (gbtrst.old_species_hash) {
108            GBS_write_hash(gbtrst.old_species_hash, oldname, 0);
109        }
110        rns = (struct gbt_renamed_struct *)GB_calloc(strlen(newname) + sizeof (struct gbt_renamed_struct),sizeof(char));
111        strcpy(&rns->data[0],newname);
112        GBS_write_hash(gbtrst.renamed_hash,oldname,(long)rns);
113    }
114    return error;
115}
116
117static void gbt_free_rename_session_data(void) {
118    if (gbtrst.renamed_hash) {
119        GBS_free_hash(gbtrst.renamed_hash);
120        gbtrst.renamed_hash = 0;
121    }
122    if (gbtrst.old_species_hash) {
123        GBS_free_hash(gbtrst.old_species_hash);
124        gbtrst.old_species_hash = 0;
125    }
126}
127
128GB_ERROR GBT_abort_rename_session(void) {
129    gbt_free_rename_session_data();
130    return GB_abort_transaction(gbtrst.gb_main);
131}
132
133static const char *currentTreeName = 0;
134
135GB_ERROR gbt_rename_tree_rek(GBT_TREE *tree,int tree_index){
136    char buffer[256];
137    static int counter = 0;
138    if (!tree) return 0;
139    if (tree->is_leaf){
140        if (tree->name){
141            struct gbt_renamed_struct *rns = (struct gbt_renamed_struct *)GBS_read_hash(gbtrst.renamed_hash,tree->name);
142            if (rns){
143                char *newname;
144                if (rns->used_by == tree_index){ /* species more than once in the tree */
145                    sprintf(buffer,"%s_%i", rns->data, counter++);
146                    GB_warningf("Species '%s' more than once in '%s', creating zombie '%s'",
147                                tree->name, currentTreeName, buffer);
148                    newname = buffer;
149                }
150                else {
151                    newname = &rns->data[0];
152                }
153                freedup(tree->name, newname);
154                rns->used_by = tree_index;
155            }
156        }
157    }else{
158        gbt_rename_tree_rek(tree->leftson,tree_index);
159        gbt_rename_tree_rek(tree->rightson,tree_index);
160    }
161    return 0;
162}
163
164#ifdef __cplusplus
165extern "C"
166#endif
167GB_ERROR GBT_commit_rename_session(int (*show_status)(double gauge), int (*show_status_text)(const char *)){
168    GB_ERROR error = 0;
169
170    // rename species in trees
171    {
172        int tree_count;
173        char **tree_names = GBT_get_tree_names_and_count(gbtrst.gb_main, &tree_count);
174
175        if (tree_names) {
176            int count;
177            gb_assert(tree_count); // otherwise tree_names should be zero
178
179            if (show_status_text) show_status_text(GBS_global_string("Renaming species in %i tree%c", tree_count, "s"[tree_count<2]));
180            if (show_status) show_status(0.0);
181
182            for (count = 0; count<tree_count; ++count) {
183                char     *tname = tree_names[count];
184                GBT_TREE *tree  = GBT_read_tree(gbtrst.gb_main,tname,-sizeof(GBT_TREE));
185
186                if (tree) {
187                    currentTreeName = tname; // provide tree name (used for error message)
188                    gbt_rename_tree_rek(tree, count+1);
189                    currentTreeName = 0;
190
191                    GBT_write_tree(gbtrst.gb_main, 0, tname, tree);
192                    GBT_delete_tree(tree);
193                }
194                if (show_status) show_status((double)(count+1)/tree_count);
195            }
196            GBT_free_names(tree_names);
197        }
198    }
199    // rename configurations
200    if (!error) {
201        int config_count;
202        char **config_names = GBT_get_configuration_names_and_count(gbtrst.gb_main, &config_count);
203
204        if (config_names) {
205            int count;
206            gb_assert(config_count); // otherwise config_names should be zero
207
208            if (show_status_text) show_status_text(GBS_global_string("Renaming species in %i config%c", config_count, "s"[config_count<2]));
209            if (show_status) show_status(0.0);
210
211            for (count = 0; !error && count<config_count; ++count) {
212                GBT_config *config = GBT_load_configuration_data(gbtrst.gb_main, config_names[count], &error);
213                if (!error) {
214                    int need_save = 0;
215                    int mode;
216
217                    for (mode = 0; !error && mode<2; ++mode) {
218                        char              **configStrPtr = (mode == 0 ? &config->top_area : &config->middle_area);
219                        GBT_config_parser  *parser       = GBT_start_config_parser(*configStrPtr);
220                        GBT_config_item    *item         = GBT_create_config_item();
221                        void               *strstruct    = GBS_stropen(1000);
222
223                        error = GBT_parse_next_config_item(parser, item);
224                        while (!error && item->type != CI_END_OF_CONFIG) {
225                            if (item->type == CI_SPECIES) {
226                                struct gbt_renamed_struct *rns = (struct gbt_renamed_struct *)GBS_read_hash(gbtrst.renamed_hash, item->name);
227                                if (rns) { // species was renamed
228                                    freedup(item->name, rns->data);
229                                    need_save = 1;
230                                }
231                            }
232                            GBT_append_to_config_string(item, strstruct);
233                            error = GBT_parse_next_config_item(parser, item);
234                        }
235
236                        if (!error) freeset(*configStrPtr, GBS_strclose(strstruct));
237
238                        GBT_free_config_item(item);
239                        GBT_free_config_parser(parser);
240                    }
241
242                    if (!error && need_save) error = GBT_save_configuration_data(config, gbtrst.gb_main, config_names[count]);
243                }
244                if (show_status) show_status((double)(count+1)/config_count);
245            }
246            GBT_free_names(config_names);
247        }
248    }
249
250    // rename links in pseudo-species
251    if (!error && GEN_is_genome_db(gbtrst.gb_main, -1)) {
252        GBDATA *gb_pseudo;
253        for (gb_pseudo = GEN_first_pseudo_species(gbtrst.gb_main);
254             gb_pseudo && !error;
255             gb_pseudo = GEN_next_pseudo_species(gb_pseudo))
256        {
257            GBDATA *gb_origin_organism = GB_entry(gb_pseudo, "ARB_origin_species");
258            if (gb_origin_organism) {
259                const char                *origin = GB_read_char_pntr(gb_origin_organism);
260                struct gbt_renamed_struct *rns    = (struct gbt_renamed_struct *)GBS_read_hash(gbtrst.renamed_hash, origin);
261                if (rns) {          // species was renamed
262                    const char *newname = &rns->data[0];
263                    error               = GB_write_string(gb_origin_organism, newname);
264                }
265            }
266        }
267    }
268
269    gbt_free_rename_session_data();
270
271    error = GB_pop_transaction(gbtrst.gb_main);
272    return error;
273}
274
Note: See TracBrowser for help on using the repository browser.