Changeset 6648

Show
Ignore:
Timestamp:
11/05/10 15:16:05 (21 months ago)
Author:
westram
Message:
  • stuffed all direct memory leaks in GB_open/GB_close
    • call gbcm_logout for main-user
    • free dates
    • gb_delete_main_entry -> gb_delete_dummy_father
    • free key data
    • free command hash
    • splitted up gb_delete_entry into GBDATA- and GBCONTAINER-version
    • destroy DB indices when destroying GBCONTAINER
Location:
trunk
Files:
9 modified

Legend:

Unmodified
Added
Removed
  • trunk/ARBDB/ad_core.cxx

    r6646 r6648  
    268268 
    269269char *gb_destroy_main(GB_MAIN_TYPE *Main) { 
     270    gb_assert(!Main->dummy_father); 
     271    gb_assert(!Main->data); 
     272 
    270273    gb_destroy_cache(Main); 
    271274    gb_release_main_idx(Main); 
    272     if (Main->path) free(Main->path); 
     275 
     276    if (Main->command_hash) GBS_free_hash(Main->command_hash); 
     277 
     278    gb_free_all_keys(Main); 
     279     
     280    if (Main->key_2_index_hash) GBS_free_hash(Main->key_2_index_hash); 
     281    freenull(Main->keys); 
     282 
    273283    gb_free_undo_stack(Main); 
     284 
     285    for (int j = 0; j<ALLOWED_DATES; ++j) freenull(Main->dates[j]); 
     286 
     287    free(Main->path); 
     288    free(Main->qs.quick_save_disabled); 
     289     
    274290    gbm_free_mem((char *)Main, sizeof(*Main), 0); 
    275291 
     
    419435void gb_pre_delete_entry(GBDATA *gbd) { 
    420436    // Reduce an entry to its absolute minimum and remove it from database 
    421     GB_MAIN_TYPE   *Main = GB_MAIN(gbd); 
    422     long    type = GB_TYPE(gbd); 
     437    GB_MAIN_TYPE *Main = GB_MAIN_NO_FATHER(gbd); 
     438    long          type = GB_TYPE(gbd); 
    423439 
    424440    struct gb_callback *cb, *cb2; 
     
    436452        gbm_free_mem((char *) cb, sizeof(struct gb_callback), gbm_index); 
    437453    } 
    438     gb_write_key(gbd, 0); 
     454 
     455    if (GB_FATHER(gbd)) { 
     456        gb_write_key(gbd, 0); 
     457    } 
    439458    gb_unlink_entry(gbd); 
    440459 
     
    455474 
    456475void gb_delete_entry(GBDATA **gbd_ptr) { 
    457     GBDATA *gbd  = *gbd_ptr; 
    458     long    gbm_index; 
    459     long    type = GB_TYPE(gbd); 
    460  
    461     gbm_index = GB_GBM_INDEX(gbd); 
     476    GBDATA *gbd       = *gbd_ptr; 
     477    long    type      = GB_TYPE(gbd); 
    462478 
    463479    if (type == GB_DB) { 
    464         int          index; 
    465         GBDATA      *gbd2; 
    466         GBCONTAINER *gbc = ((GBCONTAINER *) gbd); 
    467  
    468         for (index = 0; index < gbc->d.nheader; index++) { 
    469             if ((gbd2 = GBCONTAINER_ELEM(gbc, index))!=NULL) { 
    470                 gb_delete_entry(&gbd2); 
    471             } 
    472         }; 
    473     } 
    474     gb_pre_delete_entry(gbd); 
    475  
    476     // what is left now, is the core database entry! 
    477  
    478     if (type == GB_DB) { 
    479         GBCONTAINER                  *gbc = ((GBCONTAINER *) gbd); 
    480         struct gb_header_list_struct *hls; 
    481  
    482         if ((hls=GB_DATA_LIST_HEADER(gbc->d))!=NULL) { 
    483             gbm_free_mem((char *)hls, 
    484                          sizeof(struct gb_header_list_struct) * gbc->d.headermemsize, 
    485                          GBM_HEADER_INDEX); 
    486         } 
    487         gbm_free_mem((char *) gbd, sizeof(GBCONTAINER), gbm_index); 
     480        gb_delete_entry((GBCONTAINER**)gbd_ptr); 
    488481    } 
    489482    else { 
     483        long gbm_index = GB_GBM_INDEX(gbd); 
     484 
     485        gb_pre_delete_entry(gbd); 
    490486        if (type >= GB_BITS) GB_FREEDATA(gbd); 
    491487        gbm_free_mem((char *) gbd, sizeof(GBDATA), gbm_index); 
    492     } 
    493  
    494     *gbd_ptr = 0; // avoid further usage 
    495 } 
    496  
    497 void gb_delete_main_entry(GBDATA **gbd_ptr) { 
    498     GBDATA *gbd  = *gbd_ptr; 
    499     long    type = GB_TYPE(gbd); 
    500  
    501     gb_assert(type == GB_DB); 
    502     if (type == GB_DB) { 
    503         int          index; 
    504         int          pass; 
    505         GBDATA      *gbd2; 
    506         GBCONTAINER *gbc = ((GBCONTAINER *) gbd); 
    507  
    508         GBQUARK sys_quark = GB_key_2_quark(gbd, GB_SYSTEM_FOLDER); 
    509  
    510         for (pass = 1; pass <= 2; pass++) { 
    511             for (index = 0; index < gbc->d.nheader; index++) { 
    512                 if ((gbd2 = GBCONTAINER_ELEM(gbc, index)) != NULL) { 
    513                     if (pass == 2 || GB_KEY_QUARK(gbd2) != sys_quark) { // delay deletion of system folder to pass 2 
    514 #if defined(DEBUG) && 0 
    515                         fprintf(stderr, "Deleting root node '%s'\n", GB_get_db_path(gbd2)); 
    516 #endif // DEBUG 
    517                         gb_delete_entry(&gbd2); 
    518                     } 
    519                 } 
    520             } 
    521         } 
    522         gb_delete_entry(gbd_ptr); 
    523     } 
     488         
     489        *gbd_ptr = 0;                               // avoid further usage 
     490    } 
     491} 
     492 
     493void gb_delete_entry(GBCONTAINER **gbc_ptr) { 
     494    GBCONTAINER *gbc       = *gbc_ptr; 
     495    long         gbm_index = GB_GBM_INDEX(gbc); 
     496 
     497    gb_assert(GB_TYPE(gbc) == GB_DB); 
     498 
     499    for (long index = 0; index < gbc->d.nheader; index++) { 
     500        GBDATA *gbd = GBCONTAINER_ELEM(gbc, index); 
     501        if (gbd) { 
     502            gb_delete_entry(&gbd); 
     503            SET_GBCONTAINER_ELEM(gbc, index, NULL); 
     504        } 
     505    } 
     506 
     507    gb_pre_delete_entry((GBDATA*)gbc); 
     508 
     509    // what is left now, is the core database entry! 
     510 
     511    gb_destroy_indices(gbc); 
     512    struct gb_header_list_struct *hls; 
     513     
     514    if ((hls=GB_DATA_LIST_HEADER(gbc->d)) != NULL) { 
     515        gbm_free_mem((char *)hls, 
     516                     sizeof(struct gb_header_list_struct) * gbc->d.headermemsize, 
     517                     GBM_HEADER_INDEX); 
     518    } 
     519    gbm_free_mem((char *) gbc, sizeof(GBCONTAINER), gbm_index); 
     520 
     521    *gbc_ptr = 0;                                   // avoid further usage 
     522} 
     523 
     524static void gb_delete_main_entry(GBCONTAINER **gb_main_ptr) { 
     525    GBCONTAINER *gb_main  = *gb_main_ptr; 
     526     
     527    gb_assert(GB_TYPE(gb_main) == GB_DB); 
     528 
     529    GBQUARK sys_quark = GB_key_2_quark((GBDATA*)gb_main, GB_SYSTEM_FOLDER); 
     530 
     531    for (int pass = 1; pass <= 2; pass++) { 
     532        for (int index = 0; index < gb_main->d.nheader; index++) { 
     533            GBDATA *gbd = GBCONTAINER_ELEM(gb_main, index); 
     534            if (gbd) { 
     535                // delay deletion of system folder to pass 2: 
     536                if (pass == 2 || GB_KEY_QUARK(gbd) != sys_quark) {  
     537                    gb_delete_entry(&gbd); 
     538                    SET_GBCONTAINER_ELEM(gb_main, index, NULL); 
     539                } 
     540            } 
     541        } 
     542    } 
     543    gb_delete_entry(gb_main_ptr); 
     544} 
     545 
     546void gb_delete_dummy_father(GBCONTAINER **dummy_father) { 
     547    GBCONTAINER  *gbc  = *dummy_father; 
     548    GB_MAIN_TYPE *Main = GB_MAIN(gbc); 
     549 
     550    gb_assert(GB_TYPE(gbc)   == GB_DB); 
     551    gb_assert(GB_FATHER(gbc) == NULL); 
     552 
     553    for (int index = 0; index < gbc->d.nheader; index++) { 
     554        GBCONTAINER *gb_main = (GBCONTAINER*)GBCONTAINER_ELEM(gbc, index); 
     555        if (gb_main) { 
     556            gb_assert(GB_TYPE(gb_main) == GB_DB); 
     557            gb_assert(gb_main == Main->data); 
     558            gb_delete_main_entry((GBCONTAINER**)&gb_main); 
     559 
     560            SET_GBCONTAINER_ELEM(gbc, index, NULL); 
     561            Main->data = NULL; 
     562        } 
     563    } 
     564 
     565    gb_delete_entry(dummy_father); 
    524566} 
    525567 
     
    740782 
    741783void gb_free_all_keys(GB_MAIN_TYPE *Main) { 
    742     long index; 
    743     if (!Main->keys) return; 
    744     for (index = 1; index < Main->keycnt; index++) { 
    745         if (Main->keys[index].key) { 
    746             GBS_write_hash(Main->key_2_index_hash, Main->keys[index].key, 0); 
    747             freenull(Main->keys[index].key); 
    748         } 
    749         Main->keys[index].nref = 0; 
    750         Main->keys[index].next_free_key = 0; 
    751     } 
    752     Main->first_free_key = 0; 
    753     Main->keycnt = 1; 
     784    if (Main->keys) { 
     785        for (long index = 1; index < Main->keycnt; index++) { 
     786            if (Main->keys[index].key) { 
     787                GBS_write_hash(Main->key_2_index_hash, Main->keys[index].key, 0); 
     788                freenull(Main->keys[index].key); 
     789            } 
     790            Main->keys[index].nref = 0; 
     791            Main->keys[index].next_free_key = 0; 
     792        } 
     793        freenull(Main->keys[0].key); // "main" 
     794        Main->first_free_key = 0; 
     795        Main->keycnt         = 1; 
     796    } 
    754797} 
    755798 
  • trunk/ARBDB/ad_load.cxx

    r6629 r6648  
    369369 
    370370        for (i=Main->last_updated; i<=lu; ++i) { 
    371             Main->dates[i] = strdup("unknown date"); 
     371            gb_assert(i<ALLOWED_DATES); 
     372            Main->dates[i]     = strdup("unknown date"); 
    372373            Main->last_updated = lu+1; 
    373374        } 
     
    11351136        return 1; 
    11361137    } 
    1137     for (j=0; j<255; j++) {         // read times 
     1138    for (j=0; j<(ALLOWED_DATES-1); j++) {         // read times 
    11381139        p = buffer; 
    11391140        for (k=0; k<256; k++) { 
     
    11501151        freedup(Main->dates[j], buffer); 
    11511152    } 
    1152     if (j>=255) { 
    1153         gb_read_bin_error(in, (GBDATA *)gbd, "more than 255 dates are not allowed"); 
     1153    if (j>=(ALLOWED_DATES-1)) { 
     1154        gb_read_bin_error(in, (GBDATA *)gbd, "too many date entries"); 
    11541155        return 1; 
    11551156    } 
     
    14561457    if (strchr(opent, 'R')) Main->allow_corrupt_file_recovery = 1; 
    14571458 
    1458     gb_create_key(Main, "main", false); 
     1459    ASSERT_RESULT(long, gb_create_key(Main, "main", false), 0); 
    14591460 
    14601461    Main->dummy_father            = gb_make_container(NULL, 0, -1, 0); // create "main" 
     
    16321633 
    16331634    if (error) { 
    1634         gb_release_main_idx(Main); 
     1635        gbcm_logout(Main, user); 
     1636        gb_delete_dummy_father(&Main->dummy_father); 
     1637        gbd        = NULL; 
     1638        gb_destroy_main(Main); 
     1639 
    16351640        GB_export_error(error); 
    1636         gbd = 0; 
    16371641    } 
    16381642    else { 
  • trunk/ARBDB/adcomm.cxx

    r6640 r6648  
    11911191} 
    11921192 
    1193 static GB_ERROR gbcm_logout(GBCONTAINER *gb_main, char *user) 
    1194 { 
    1195     long i; 
    1196     GB_MAIN_TYPE *Main = GBCONTAINER_MAIN(gb_main); 
    1197  
    1198     for (i = 0; i<GB_MAX_USERS; i++) { 
    1199         if (!Main->users[i]) continue; 
    1200         if (!strcmp(user, Main->users[i]->username)) { 
    1201             Main->users[i]->nusers--; 
    1202             if (Main->users[i]->nusers<=0) { // kill user and his projects 
    1203                 free(Main->users[i]->username); 
    1204                 freenull(Main->users[i]); 
    1205                 fprintf(stdout, "The User %s has logged out\n", user); 
    1206             } 
    1207             return 0; 
    1208         } 
    1209     } 
    1210     return GB_export_errorf("User '%s' not logged in", user); 
    1211 } 
    1212  
    12131193bool GBCMS_accept_calls(GBDATA *gbd, bool wait_extra_time) { 
    12141194    // returns true if served 
     
    13141294                } 
    13151295                if (si->username) { 
    1316                     gbcm_logout((GBCONTAINER *)hs->gb_main, si->username); 
     1296                    gbcm_logout(Main, si->username); 
    13171297                } 
    13181298                g_bcms_delete_Socinf(si); 
     
    19031883 
    19041884 
    1905 GB_ERROR gbcm_login(GBCONTAINER *gb_main, const char *user) 
     1885GB_ERROR gbcm_login(GBCONTAINER *gb_main, const char *loginname) { 
    19061886     // look for any free user and set this_user 
    1907 { 
    19081887    int i; 
    19091888    GB_MAIN_TYPE *Main = GBCONTAINER_MAIN(gb_main); 
    19101889 
    19111890    for (i = 0; i<GB_MAX_USERS; i++) { 
    1912         if (!Main->users[i]) continue; 
    1913         if (!strcmp(user, Main->users[i]->username)) { 
    1914             Main->this_user = Main->users[i]; 
    1915             Main->users[i]->nusers++; 
     1891        gb_user_struct *user = Main->users[i]; 
     1892        if (user && strcmp(loginname, user->username) == 0) { 
     1893            Main->this_user = user; 
     1894            user->nusers++; 
    19161895            return 0; 
    19171896        } 
    19181897    } 
    19191898    for (i = 0; i<GB_MAX_USERS; i++) { 
    1920         if (Main->users[i]) continue; 
    1921         Main->users[i] = (struct gb_user_struct *) GB_calloc(sizeof(struct gb_user_struct), 1); 
    1922         Main->users[i]->username = strdup(user); 
    1923         Main->users[i]->userid = i; 
    1924         Main->users[i]->userbit = 1<<i; 
    1925         Main->users[i]->nusers = 1; 
    1926         Main->this_user = Main->users[i]; 
    1927         return 0; 
    1928     } 
    1929     return GB_export_errorf("Too many users in this database: User '%s' ", user); 
     1899        gb_user_struct*& user = Main->users[i]; 
     1900        if (!user) { 
     1901            user = (gb_user_struct *) GB_calloc(sizeof(gb_user_struct), 1); 
     1902             
     1903            user->username = strdup(loginname); 
     1904            user->userid   = i; 
     1905            user->userbit  = 1<<i; 
     1906            user->nusers   = 1; 
     1907 
     1908            Main->this_user = user; 
     1909 
     1910            return 0; 
     1911        } 
     1912    } 
     1913    return GB_export_errorf("Too many users in this database: User '%s' ", loginname); 
    19301914} 
    19311915 
     
    19491933    return GBCM_SERVER_OK; 
    19501934} 
     1935 
     1936GB_ERROR gbcm_logout(GB_MAIN_TYPE *Main, const char *loginname) { 
     1937    // if 'loginname' is NULL, the first logged-in user will be logged out 
     1938 
     1939    if (!loginname) { 
     1940        loginname = Main->users[0]->username; 
     1941        gb_assert(loginname); 
     1942    } 
     1943 
     1944    for (long i = 0; i<GB_MAX_USERS; i++) { 
     1945        gb_user_struct*& user = Main->users[i]; 
     1946        if (user && strcmp(loginname, user->username) == 0) { 
     1947            user->nusers--; 
     1948            if (user->nusers<=0) { // kill user and his projects 
     1949                if (i) fprintf(stdout, "User '%s' has logged out\n", loginname); 
     1950                free(user->username); 
     1951                freenull(user); 
     1952            } 
     1953            return 0; 
     1954        } 
     1955    } 
     1956    return GB_export_errorf("User '%s' not logged in", loginname); 
     1957} 
     1958 
    19511959 
    19521960GB_CSTR GB_get_hostname() { 
  • trunk/ARBDB/adindex.cxx

    r6640 r6648  
    173173    } 
    174174    return error; 
     175} 
     176 
     177void gb_destroy_indices(GBCONTAINER *gbc) { 
     178    gb_index_files_struct *ifs = GBCONTAINER_IFS(gbc); 
     179 
     180    while (ifs) { 
     181        GB_REL_IFES *if_entries = GB_INDEX_FILES_ENTRIES(ifs); 
     182 
     183        for (int index = 0; index<ifs->hash_table_size; index++) { 
     184            gb_if_entries *ifes = GB_ENTRIES_ENTRY(if_entries, index); 
     185 
     186            while (ifes) { 
     187                gb_if_entries *ifes_next = GB_IF_ENTRIES_NEXT(ifes); 
     188 
     189                gbm_free_mem((char*)ifes, sizeof(*ifes), GB_GBM_INDEX(gbc)); 
     190                ifes = ifes_next; 
     191            } 
     192        } 
     193        free(if_entries); 
     194 
     195        gb_index_files_struct *ifs_next = GB_INDEX_FILES_NEXT(ifs); 
     196        free(ifs); 
     197        ifs = ifs_next; 
     198    } 
    175199} 
    176200 
  • trunk/ARBDB/arbdb.cxx

    r6645 r6648  
    413413 
    414414    if (!Main->local_mode) { 
    415         long result = gbcmc_close(Main->c_link); 
     415        long result            = gbcmc_close(Main->c_link); 
    416416        if (result != 0) error = GBS_global_string("gbcmc_close returns %li", result); 
    417417    } 
    418418 
     419    gbcm_logout(Main, NULL);                        // logout default user 
     420     
    419421    if (!error) { 
    420422        gb_assert((GBDATA*)Main->data == gbd); 
     
    423425        Main->close_callbacks = 0; 
    424426 
    425         gb_delete_main_entry(&gbd); 
     427        gb_delete_dummy_father(&Main->dummy_father); 
     428        Main->data = NULL; 
    426429 
    427430        /* ARBDB applications using awars easily crash in gb_do_callback_list(), 
     
    431434         * If that doesn't help, test Main->data (often aka as GLOBAL_gb_main) 
    432435         */ 
    433         Main->data = NULL; 
    434436        gb_do_callback_list(Main);                  // do all callbacks 
    435  
    436437        gb_destroy_main(Main); 
    437438    } 
  • trunk/ARBDB/gb_data.h

    r6646 r6648  
    160160 
    161161inline GB_TYPES GB_TYPE(GBDATA *gbd)      { return GB_TYPES(gbd->flags.type); } 
    162 inline GB_TYPES GB_TYPE(GBCONTAINER *gbd) { return GB_TYPES(gbd->flags.type); } 
     162inline GB_TYPES GB_TYPE(GBCONTAINER *gbc) { return GB_TYPES(gbc->flags.type); } 
    163163 
    164164// ---------------------- 
     
    179179inline GB_MAIN_TYPE *GB_MAIN(GBDATA *gbd)               { return GBCONTAINER_MAIN(GB_FATHER(gbd)); } 
    180180inline GB_MAIN_TYPE *GB_MAIN(GBCONTAINER *gbc)          { return GBCONTAINER_MAIN(gbc); } 
     181inline GB_MAIN_TYPE *GB_MAIN_NO_FATHER(GBDATA *gbd)     { return GB_TYPE(gbd) == GB_DB ? GBCONTAINER_MAIN((GBCONTAINER*)gbd) : GB_MAIN(gbd); } 
    181182 
    182183// ----------------------- 
  • trunk/ARBDB/gb_main.h

    r6646 r6648  
    7676//      root structure (one for each database) 
    7777 
    78 #define ALLOWED_KEYS 15000 
     78#define ALLOWED_KEYS  15000 
     79#define ALLOWED_DATES 256 
    7980 
    8081struct GB_MAIN_TYPE { 
     
    116117    g_b_undo_mgr_struct *undo; 
    117118 
    118     char         *dates[256]; 
     119    char         *dates[ALLOWED_DATES];           // @@@ saved to DB, but never used 
    119120    unsigned int  security_level; 
    120121    int           old_security_level; 
  • trunk/ARBDB/gb_prot.h

    r6646 r6648  
    6969GB_ERROR gbcmc_send_undo_commands(GBDATA *gbd, enum gb_undo_commands command) __ATTR__USERESULT; 
    7070char *gbcmc_send_undo_info_commands(GBDATA *gbd, enum gb_undo_commands command); 
    71 GB_ERROR gbcm_login(GBCONTAINER *gb_main, const char *user); 
     71GB_ERROR gbcm_login(GBCONTAINER *gb_main, const char *loginname); 
    7272GBCM_ServerResult gbcmc_close(struct gbcmc_comm *link); 
     73GB_ERROR gbcm_logout(GB_MAIN_TYPE *Main, const char *loginname); 
    7374 
    7475/* adhash.cxx */ 
     
    155156void gb_pre_delete_entry(GBDATA *gbd); 
    156157void gb_delete_entry(GBDATA **gbd_ptr); 
    157 void gb_delete_main_entry(GBDATA **gbd_ptr); 
     158void gb_delete_entry(GBCONTAINER **gbc_ptr); 
     159void gb_delete_dummy_father(GBCONTAINER **dummy_father); 
    158160struct gb_transaction_save *gb_new_gb_transaction_save(GBDATA *gbd); 
    159161void gb_add_ref_gb_transaction_save(struct gb_transaction_save *ts); 
     
    193195char *gb_index_check_in(GBDATA *gbd); 
    194196void gb_index_check_out(GBDATA *gbd); 
     197void gb_destroy_indices(GBCONTAINER *gbc); 
    195198GBDATA *gb_index_find(GBCONTAINER *gbf, struct gb_index_files_struct *ifs, GBQUARK quark, const char *val, GB_CASE case_sens, int after_index); 
    196199void gb_init_undo_stack(GB_MAIN_TYPE *Main); 
  • trunk/Makefile

    r6612 r6648  
    15791579        @echo "$(SEP) Running unit tests" 
    15801580        $(MAKE) $(TESTED_UNITS) 
    1581         @echo "All unit tests passed"  
     1581        @echo "$(SEP) All unit tests passed"  
    15821582 
    15831583ut: unit_tests