s_persistency.c

Go to the documentation of this file.
00001 /*
00002  * $Id: s_persistency.c 236 2007-04-18 12:53:40Z vingarzan $
00003  *
00004  * Copyright (C) 2004-2007 FhG Fokus
00005  *
00006  * This file is part of Open IMS Core - an open source IMS CSCFs & HSS
00007  * implementation
00008  *
00009  * Open IMS Core is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * For a license to use the Open IMS Core software under conditions
00015  * other than those described here, or to purchase support for this
00016  * software, please contact Fraunhofer FOKUS by e-mail at the following
00017  * addresses:
00018  *     info@open-ims.org
00019  *
00020  * Open IMS Core is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  * GNU General Public License for more details.
00024  *
00025  * It has to be noted that this Open Source IMS Core System is not
00026  * intended to become or act as a product in a commercial context! Its
00027  * sole purpose is to provide an IMS core reference implementation for
00028  * IMS technology testing and IMS application prototyping for research
00029  * purposes, typically performed in IMS test-beds.
00030  *
00031  * Users of the Open Source IMS Core System have to be aware that IMS
00032  * technology may be subject of patents and licence terms, as being
00033  * specified within the various IMS-related IETF, ITU-T, ETSI, and 3GPP
00034  * standards. Thus all Open IMS Core users have to take notice of this
00035  * fact and have to agree to check out carefully before installing,
00036  * using and extending the Open Source IMS Core System, if related
00037  * patents and licences may become applicable to the intended usage
00038  * context.
00039  *
00040  * You should have received a copy of the GNU General Public License
00041  * along with this program; if not, write to the Free Software
00042  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00043  *
00044  */
00045 
00058 #include "s_persistency.h"
00059 
00060 extern persistency_mode_t scscf_persistency_mode;
00061 extern char* scscf_persistency_location;        
00064 extern auth_hash_slot_t *auth_data;             
00065 extern int auth_data_hash_size;                 
00066 extern int r_hash_size;                     
00067 extern r_hash_slot *registrar;              
00068 extern int s_dialogs_hash_size;                     
00069 extern s_dialog_hash_slot *s_dialogs;               
00072 /*****  DB related stuff *****/
00073 extern db_con_t* scscf_db; 
00074 extern db_func_t scscf_dbf; 
00075 extern int* auth_snapshot_version;
00076 extern int* auth_step_version;
00077 extern int* dialogs_snapshot_version;
00078 extern int* dialogs_step_version;
00079 extern int* registrar_snapshot_version;
00080 extern int* registrar_step_version;
00081 extern gen_lock_t* db_lock; 
00082 extern char* scscf_name;
00083 
00084 int s_dump(bin_data* x, char* location, char* prepend_fname, data_type_t dt);
00085 int bin_dump_to_db(bin_data *x, data_type_t dt);
00086 int bin_dump_registrar_to_table(bin_data *x, int snapshot_version, int step_version);
00087 int bin_dump_dialogs_to_table(bin_data *x, int snapshot_version, int step_version);
00088 int bin_dump_auth_to_table(bin_data *x, int snapshot_version, int step_version);
00089 int bin_bulk_dump_to_table(data_type_t dt, int snapshot_version, int step_version, bin_data *x);
00090 int bin_cache_dump_registrar_to_table(int snapshot_version, int step_version);
00091 int bin_cache_dump_dialogs_to_table(int snapshot_version, int step_version);
00092 int bin_cache_dump_auth_to_table(int snapshot_version, int step_version);
00093 int delete_older_snapshots(char* table, char* node_id, data_type_t dt, int current_snapshot);
00094 
00095 int s_load(bin_data *x, char* location, char* prepend_fname, data_type_t dt);
00096 int bin_load_from_db(bin_data *x, data_type_t dt);
00097 int bin_load_registrar_from_table(bin_data *x);
00098 int bin_load_dialogs_from_table(bin_data *x);
00099 int bin_load_auth_from_table(bin_data *x);
00100 int bin_bulk_load_from_table(data_type_t dt, bin_data* x);
00101 int bin_cache_load_registrar_from_table();
00102 int bin_cache_load_dialogs_from_table();
00103 int bin_cache_load_auth_from_table();
00104 int db_get_last_snapshot_version(char* table, char* node_id, data_type_t dt, int* version);
00105 int set_versions(data_type_t dt, int snapshot_version, int step_version);
00106 /*********************/
00107 
00112 int make_snapshot_authdata()
00113 {
00114     bin_data x;
00115     auth_userdata *aud;
00116     int i;
00117     
00118     /*In WITH_DATABASE_CACHE mode, serialize each hashtable element separately */
00119     if(scscf_persistency_mode!=WITH_DATABASE_CACHE){    
00120         if (!bin_alloc(&x,256)) goto error;
00121         for(i=0;i<auth_data_hash_size;i++){
00122             auth_data_lock(i);
00123             aud = auth_data[i].head;
00124             while(aud){
00125                 if (!bin_encode_auth_userdata(&x,aud)) goto error;
00126                 aud = aud->next;
00127             }
00128             auth_data_unlock(i);
00129         }
00130         //bin_print(&x);
00131     }
00132     i=s_dump(&x,scscf_persistency_location,"authdata", S_AUTH);
00133     //i = bin_dump(&x,scscf_persistency_mode,scscf_persistency_location,"authdata");        
00134     if(scscf_persistency_mode!=WITH_DATABASE_CACHE){
00135         bin_free(&x);
00136     }
00137     return i;
00138 error:
00139     return 0;
00140 }
00141   
00142 
00147 int load_snapshot_authdata()
00148 {
00149     bin_data x;
00150     auth_userdata *aud;
00151     if (!s_load(&x,scscf_persistency_location,"authdata", S_AUTH)) goto error;
00152     //if (!bin_load(&x,scscf_persistency_mode,scscf_persistency_location,"authdata")) goto error;
00153     
00154     if(scscf_persistency_mode!=WITH_DATABASE_CACHE){
00155         //bin_print(&x);
00156         x.max=0;
00157         LOG(L_INFO,"INFO:"M_NAME":load_snapshot_auth: max %d len %d\n",x.max,x.len);
00158         while(x.max<x.len){
00159             aud = bin_decode_auth_userdata(&x);     
00160             if (!aud) return 0;
00161             LOG(L_INFO,"INFO:"M_NAME":load_snapshot_auth: Loaded auth_userdata for <%.*s>\n",aud->private_identity.len,aud->private_identity.s);
00162             auth_data_lock(aud->hash);
00163             aud->prev = auth_data[aud->hash].tail;
00164             aud->next = 0;
00165             if (auth_data[aud->hash].tail) auth_data[aud->hash].tail->next = aud;
00166             auth_data[aud->hash].tail = aud;
00167             if (!auth_data[aud->hash].head) auth_data[aud->hash].head = aud;
00168             auth_data_unlock(aud->hash);
00169         }
00170         bin_free(&x);
00171     }
00172     return 1;
00173 error:
00174     return 0;
00175 }
00176 
00182 void persistency_timer_authdata(unsigned int ticks, void* param)
00183 {
00184     make_snapshot_authdata();
00185     
00186     if (auth_snapshot_version) (*auth_snapshot_version)++;  
00187 }
00188 
00189 
00190 
00195 int make_snapshot_dialogs()
00196 {
00197     bin_data x;
00198     s_dialog *d;
00199     int i;  
00200     
00201     /*In WITH_DATABASE_CACHE mode, serialize each hashtable element separately */
00202     if(scscf_persistency_mode!=WITH_DATABASE_CACHE){
00203         if (!bin_alloc(&x,256)) goto error;     
00204         for(i=0;i<s_dialogs_hash_size;i++){
00205             d_lock(i);
00206             d = s_dialogs[i].head;
00207             while(d){
00208                 if (!bin_encode_s_dialog(&x,d)) goto error;
00209                 d = d->next;
00210             }
00211             d_unlock(i);
00212         }
00213         //bin_print(&x);
00214     }
00215     i=s_dump(&x,scscf_persistency_location,"sdialogs",S_DIALOGS);
00216     //i = bin_dump(&x,scscf_persistency_mode,scscf_persistency_location,"sdialogs");        
00217     if(scscf_persistency_mode!=WITH_DATABASE_CACHE){
00218         bin_free(&x);
00219     }
00220     return i;
00221 error:
00222     return 0;
00223 }  
00224 
00229 int load_snapshot_dialogs()
00230 {
00231     bin_data x;
00232     s_dialog *d;
00233     if (!s_load(&x,scscf_persistency_location,"sdialogs",S_DIALOGS)) goto error;
00234     //if (!bin_load(&x,scscf_persistency_mode,scscf_persistency_location,"sdialogs")) goto error;
00235     
00236     if(scscf_persistency_mode!=WITH_DATABASE_CACHE){
00237         //bin_print(&x);
00238         x.max=0;
00239         LOG(L_INFO,"INFO:"M_NAME":load_snapshot_dlg: max %d len %d\n",x.max,x.len);
00240         while(x.max<x.len){
00241             d = bin_decode_s_dialog(&x);
00242             if (!d) return 0;
00243             LOG(L_INFO,"INFO:"M_NAME":load_snapshot_dlg: Loaded s_dialog for <%.*s>\n",d->aor.len,d->aor.s);
00244             d_lock(d->hash);
00245             d->prev = s_dialogs[d->hash].tail;
00246             d->next = 0;
00247             if (s_dialogs[d->hash].tail) s_dialogs[d->hash].tail->next = d;
00248             s_dialogs[d->hash].tail = d;
00249             if (!s_dialogs[d->hash].head) s_dialogs[d->hash].head = d;
00250             d_unlock(d->hash);
00251         }
00252         bin_free(&x);
00253     }
00254     return 1;
00255 error:
00256     return 0;
00257 }
00258 
00259 
00265 void persistency_timer_dialogs(unsigned int ticks, void* param)
00266 {
00267     make_snapshot_dialogs();
00268     
00269     if (dialogs_snapshot_version) (*dialogs_snapshot_version)++;        
00270 }
00271 
00272 
00277 int make_snapshot_registrar()
00278 {
00279     bin_data x;
00280     r_public *p;
00281     int i;
00282     
00283     /*In WITH_DATABASE_CACHE mode, serialize each hashtable element separately */
00284     if(scscf_persistency_mode!=WITH_DATABASE_CACHE){
00285         if (!bin_alloc(&x,256)) goto error;     
00286         for(i=0;i<r_hash_size;i++){
00287             r_lock(i);
00288             p = registrar[i].head;
00289             while(p){
00290                 if (!bin_encode_r_public(&x,p)) goto error;
00291                 p = p->next;
00292             }
00293             r_unlock(i);
00294         }
00295         //bin_print(&x);
00296     }
00297     i = s_dump(&x,scscf_persistency_location,"sregistrar",S_REGISTRAR);
00298     //i = bin_dump(&x,scscf_persistency_mode,scscf_persistency_location,"sregistrar");      
00299     if(scscf_persistency_mode!=WITH_DATABASE_CACHE){
00300         bin_free(&x);
00301     }
00302     return i;
00303 error:
00304     return 0;
00305 }  
00306 
00311 int load_snapshot_registrar()
00312 {
00313     bin_data x;
00314     r_public *p;
00315     if (!s_load(&x,scscf_persistency_location,"sregistrar",S_REGISTRAR)) goto error;
00316     //if (!bin_load(&x,scscf_persistency_mode,scscf_persistency_location,"sregistrar")) goto error;
00317     
00318     if(scscf_persistency_mode!=WITH_DATABASE_CACHE){
00319         //bin_print(&x);
00320         x.max=0;
00321         LOG(L_INFO,"INFO:"M_NAME":load_snapshot_registrar: max %d len %d\n",x.max,x.len);
00322         while(x.max<x.len){
00323             p = bin_decode_r_public(&x);
00324             if (!p) return 0;
00325             LOG(L_INFO,"INFO:"M_NAME":load_snapshot_registrar: Loaded r_public for <%.*s>\n",p->aor.len,p->aor.s);
00326             r_lock(p->hash);
00327             p->prev = registrar[p->hash].tail;
00328             p->next = 0;
00329             if (registrar[p->hash].tail) registrar[p->hash].tail->next = p;
00330             registrar[p->hash].tail = p;
00331             if (!registrar[p->hash].head) registrar[p->hash].head = p;
00332             r_unlock(p->hash);
00333         }
00334         bin_free(&x);
00335     }
00336     return 1;
00337 error:
00338     return 0;
00339     
00340 }
00341 
00342 
00348 void persistency_timer_registrar(unsigned int ticks, void* param)
00349 {
00350     make_snapshot_registrar();
00351     
00352     if (registrar_snapshot_version) (*registrar_snapshot_version)++;
00353 }
00354 
00355 
00356 /******  DB related functions  *****/
00357 
00358     /* Dump related functions*/
00359     
00369 int s_dump(bin_data* x, char* location, char* prepend_fname, data_type_t dt){
00370     
00371     switch (scscf_persistency_mode){
00372         case NO_PERSISTENCY:
00373             LOG(L_ERR,"ERR:"M_NAME":s_dump: Snapshot done but persistency was disabled...\n");
00374             return 0;
00375         case WITH_FILES:
00376             return bin_dump_to_file(x,location,prepend_fname);
00377         case WITH_DATABASE_BULK:
00378             return bin_dump_to_db(x, dt);
00379         case WITH_DATABASE_CACHE:
00380             return bin_dump_to_db(NULL, dt);//ignore x, x is empty
00381         default:
00382             LOG(L_ERR,"ERR:"M_NAME":s_dump: Snapshot done but no such mode %d\n",scscf_persistency_mode);
00383             return 0;
00384     }
00385 }
00386 
00394 int bin_dump_to_db(bin_data *x, data_type_t dt){
00395     
00396     int snapshot_version;
00397     int step_version;
00398     
00399     switch(dt){
00400         case S_REGISTRAR:
00401             snapshot_version=*registrar_snapshot_version;
00402             step_version=*registrar_step_version;
00403             return bin_dump_registrar_to_table(x, snapshot_version, step_version);
00404         case S_DIALOGS:
00405             snapshot_version=*dialogs_snapshot_version;
00406             step_version=*dialogs_step_version;
00407             return bin_dump_dialogs_to_table(x, snapshot_version, step_version);
00408         case S_AUTH:
00409             snapshot_version=*auth_snapshot_version;
00410             step_version=*auth_step_version;
00411             return bin_dump_auth_to_table(x, snapshot_version, step_version);
00412         default:
00413             LOG(L_ERR,"ERR:"M_NAME":bin_dump_to_db: No such information to dump %d\n", dt);
00414             return 0;
00415     }
00416 }
00417 
00426 int bin_dump_registrar_to_table(bin_data *x, int snapshot_version, int step_version){
00427     
00428     if(x){//whole hashtable serialized to x
00429         return bin_bulk_dump_to_table(S_REGISTRAR, snapshot_version, step_version, x);
00430     }
00431     else{//serialize and dump each hashtable element separately
00432         return bin_cache_dump_registrar_to_table(snapshot_version, step_version);
00433     }
00434 }
00435 
00444 int bin_dump_dialogs_to_table(bin_data *x, int snapshot_version, int step_version){
00445     
00446     if(x){//whole hashtable serialized to x
00447         return bin_bulk_dump_to_table(S_DIALOGS, snapshot_version, step_version, x);
00448     }
00449     else{//serialize and dump each hashtable element separately
00450         return bin_cache_dump_dialogs_to_table(snapshot_version, step_version);
00451     }
00452 }
00453 
00462 int bin_dump_auth_to_table(bin_data *x, int snapshot_version, int step_version){
00463     
00464     if(x){//whole hashtable serialized to x
00465         return bin_bulk_dump_to_table(S_AUTH, snapshot_version, step_version, x);
00466     }
00467     else{//serialize and dump each hashtable element separately
00468         return bin_cache_dump_auth_to_table(snapshot_version, step_version);
00469     }
00470 }
00471 
00480 int bin_bulk_dump_to_table(data_type_t dt, int snapshot_version, int step_version, bin_data *x){
00481     db_key_t keys[5];
00482     db_val_t vals[5];
00483     int len;
00484 
00485     /* id auto incremented */
00486     keys[0] = "node_id";
00487     keys[1] = "data_type";
00488     keys[2] = "snapshot_version";
00489     keys[3] = "step_version";
00490     /* record_id_1/2/3/4=NULL */
00491     keys[4] = "data";
00492     
00493     vals[0].type = DB_STR;
00494     vals[0].nul = 0;
00495     vals[0].val.str_val.s=scscf_name;
00496     len = strlen(scscf_name);
00497     vals[0].val.str_val.len=MIN(len, 64);
00498 
00499     vals[1].type = DB_INT;
00500     vals[1].nul = 0;
00501     vals[1].val.int_val=dt;
00502 
00503     vals[2].type = DB_INT;
00504     vals[2].nul = 0;
00505     vals[2].val.int_val=snapshot_version;
00506     
00507     vals[3].type = DB_INT;
00508     vals[3].nul = 0;
00509     vals[3].val.int_val=step_version;
00510 
00511     str d = {x->s, x->len};
00512     vals[4].type = DB_BLOB;
00513     vals[4].nul = 0;
00514     vals[4].val.blob_val = d;
00515 
00516     //lock
00517     lock_get(db_lock);
00518 
00519     if (scscf_dbf.use_table(scscf_db, "snapshot") < 0) {
00520         LOG(L_ERR, "ERR:"M_NAME":bin_bulk_dump_to_table(): Error in use_table\n");
00521         lock_release(db_lock);//unlock
00522         return 0;
00523     }
00524 
00525     if (scscf_dbf.insert(scscf_db, keys, vals, 5) < 0) {
00526         LOG(L_ERR, "ERR:"M_NAME":bin_bulk_dump_to_table(): Error while inserting on snapshot table\n");
00527         lock_release(db_lock);//unlock
00528         return 0;
00529     }
00530     
00531     //delete older snapshots
00532     if (delete_older_snapshots("snapshot", scscf_name, dt, snapshot_version)!=1){
00533         LOG(L_ERR, "ERR:"M_NAME":bin_bulk_dump_to_table(): Error while deleting older snapshots from snapshot table\n");
00534         lock_release(db_lock);//unlock
00535         return 0;
00536     }
00537     
00538     //unlock
00539     lock_release(db_lock);
00540     
00541     return 1;
00542 }
00543 
00551 int bin_cache_dump_registrar_to_table(int snapshot_version, int step_version){
00552     bin_data x;
00553     r_public *p;
00554     int i;
00555     int len;
00556     
00557     //lock
00558     lock_get(db_lock);
00559 
00560     if (scscf_dbf.use_table(scscf_db, "snapshot") < 0) {
00561         LOG(L_ERR, "ERR:"M_NAME":bin_cache_dump_registrar_to_table(): Error in use_table\n");
00562         goto error;
00563     }
00564     
00565     for(i=0;i<r_hash_size;i++){
00566         r_lock(i);
00567         p = registrar[i].head;
00568         while(p){
00569             if (!bin_alloc(&x,128)){
00570                 r_unlock(i);
00571                 goto error;
00572             }
00573             if (!bin_encode_r_public(&x,p)){
00574                 r_unlock(i);
00575                 goto error;
00576             }
00577             
00578             db_key_t keys[6];
00579             db_val_t vals[6];
00580             
00581             /* id auto incremented */
00582             keys[0] = "node_id";
00583             keys[1] = "data_type";
00584             keys[2] = "snapshot_version";
00585             keys[3] = "step_version";
00586             keys[4] = "record_id_1"; /* aor */
00587             /* record_id_2/3/4=NULL */
00588             keys[5] = "data";
00589             
00590             vals[0].type = DB_STR;
00591             vals[0].nul = 0;
00592             vals[0].val.str_val.s=scscf_name;
00593             len = strlen(scscf_name);
00594             vals[0].val.str_val.len=MIN(len, 64);
00595 
00596             vals[1].type = DB_INT;
00597             vals[1].nul = 0;
00598             vals[1].val.int_val=S_REGISTRAR;
00599 
00600             vals[2].type = DB_INT;
00601             vals[2].nul = 0;
00602             vals[2].val.int_val=snapshot_version;
00603     
00604             vals[3].type = DB_INT;
00605             vals[3].nul = 0;
00606             vals[3].val.int_val=step_version;
00607     
00608             vals[4].type = DB_STR;
00609             vals[4].nul = 0;
00610             vals[4].val.str_val.s=p->aor.s;
00611             vals[4].val.str_val.len=MIN(p->aor.len, 256);
00612         
00613             vals[5].type = DB_BLOB;
00614             vals[5].nul = 0;
00615             str data={x.s, x.len};
00616             vals[5].val.blob_val = data;
00617             
00618             if (scscf_dbf.insert(scscf_db, keys, vals, 6) < 0) {
00619                 LOG(L_ERR, "ERR:"M_NAME":bin_cache_dump_registrar_to_table(): Error while inserting on snapshot table\n");
00620                 r_unlock(i);
00621                 goto error;
00622             }
00623             bin_free(&x);
00624             
00625             p=p->next;
00626         }
00627         r_unlock(i);
00628     }   
00629     
00630     //delete older snapshots
00631     if (delete_older_snapshots("snapshot", scscf_name, S_REGISTRAR, snapshot_version)!=1){
00632         LOG(L_ERR, "ERR:"M_NAME":bin_cache_dump_registrar_to_table(): Error while deleting older snapshots from snapshot table\n");
00633         goto error;
00634     }
00635     
00636     //unlock
00637     lock_release(db_lock);
00638     
00639     return 1;
00640 
00641 error:
00642     lock_release(db_lock);//unlock
00643     return 0;
00644 }
00645 
00653 int bin_cache_dump_dialogs_to_table(int snapshot_version, int step_version){
00654     bin_data x;
00655     s_dialog *dialog;
00656     int i;
00657     int len;
00658     
00659     //lock
00660     lock_get(db_lock);
00661 
00662     if (scscf_dbf.use_table(scscf_db, "snapshot") < 0) {
00663         LOG(L_ERR, "ERR:"M_NAME":bin_cache_dump_dialogs_to_table(): Error in use_table\n");
00664         goto error;
00665     }
00666     
00667     for(i=0;i<s_dialogs_hash_size;i++){
00668         d_lock(i);
00669         dialog = s_dialogs[i].head;
00670         while(dialog){
00671             if (!bin_alloc(&x,128)){
00672                 d_unlock(i);
00673                 goto error;
00674             }
00675             if (!bin_encode_s_dialog(&x,dialog)){
00676                 d_unlock(i);
00677                 goto error;
00678             }
00679             
00680             db_key_t keys[7];
00681             db_val_t vals[7];
00682             
00683             /* id auto incremented */
00684             keys[0] = "node_id";
00685             keys[1] = "data_type";
00686             keys[2] = "snapshot_version";
00687             keys[3] = "step_version";
00688             keys[4] = "record_id_1"; /* call-id */
00689             keys[5] = "record_id_2"; /* aor */
00690             /* record_id_3/4=NULL */
00691             keys[6] = "data";
00692             
00693             vals[0].type = DB_STR;
00694             vals[0].nul = 0;
00695             vals[0].val.str_val.s=scscf_name;
00696             len = strlen(scscf_name);
00697             vals[0].val.str_val.len=MIN(len, 64);
00698 
00699             vals[1].type = DB_INT;
00700             vals[1].nul = 0;
00701             vals[1].val.int_val=S_DIALOGS;
00702 
00703             vals[2].type = DB_INT;
00704             vals[2].nul = 0;
00705             vals[2].val.int_val=snapshot_version;
00706     
00707             vals[3].type = DB_INT;
00708             vals[3].nul = 0;
00709             vals[3].val.int_val=step_version;
00710     
00711             vals[4].type = DB_STR;
00712             vals[4].nul = 0;
00713             vals[4].val.str_val.s=dialog->call_id.s;
00714             vals[4].val.str_val.len=MIN(dialog->call_id.len, 256);
00715     
00716             vals[5].type = DB_STR;
00717             vals[5].nul = 0;
00718             vals[5].val.str_val.s=dialog->aor.s;
00719             vals[5].val.str_val.len=MIN(dialog->aor.len, 256);
00720     
00721             vals[6].type = DB_BLOB;
00722             vals[6].nul = 0;
00723             str data={x.s, x.len};
00724             vals[6].val.blob_val = data;
00725             
00726             if (scscf_dbf.insert(scscf_db, keys, vals, 7) < 0) {
00727                 LOG(L_ERR, "ERR:"M_NAME":bin_cache_dump_dialogs_to_table(): Error while inserting on snapshot table\n");
00728                 d_unlock(i);
00729                 goto error;
00730             }
00731             bin_free(&x);
00732             
00733             dialog = dialog->next;
00734         }
00735         d_unlock(i);
00736     }   
00737     
00738     //delete older snapshots
00739     if (delete_older_snapshots("snapshot", scscf_name, S_DIALOGS, snapshot_version)!=1){
00740         LOG(L_ERR, "ERR:"M_NAME":bin_cache_dump_dialogs_to_table(): Error while deleting older snapshots from snapshot table\n");
00741         goto error;
00742     }
00743     
00744     //unlock
00745     lock_release(db_lock);
00746     
00747     return 1;
00748 
00749 error:
00750     lock_release(db_lock);//unlock
00751     return 0;
00752 }
00753 
00761 int bin_cache_dump_auth_to_table(int snapshot_version, int step_version){
00762     bin_data x;
00763     auth_userdata *aud;
00764     int i;
00765     int len;
00766     
00767     //lock
00768     lock_get(db_lock);
00769 
00770     if (scscf_dbf.use_table(scscf_db, "snapshot") < 0) {
00771         LOG(L_ERR, "ERR:"M_NAME":bin_cache_dump_auth_to_table(): Error in use_table\n");
00772         goto error;
00773     }
00774     
00775     for(i=0;i<auth_data_hash_size;i++){
00776         auth_data_lock(i);
00777         aud = auth_data[i].head;
00778         while(aud){
00779             if (!bin_alloc(&x,128)){
00780                 auth_data_unlock(i);
00781                 goto error;
00782             }
00783             if (!bin_encode_auth_userdata(&x,aud)){
00784                 auth_data_unlock(i);
00785                 goto error;
00786             }
00787             
00788             db_key_t keys[7];
00789             db_val_t vals[7];
00790             
00791             /* id auto incremented */
00792             keys[0] = "node_id";
00793             keys[1] = "data_type";
00794             keys[2] = "snapshot_version";
00795             keys[3] = "step_version";
00796             keys[4] = "record_id_1"; /* private */
00797             keys[5] = "record_id_2"; /* public */
00798             /* record_id_3/4=NULL*/
00799             keys[6] = "data";
00800             
00801             vals[0].type = DB_STR;
00802             vals[0].nul = 0;
00803             vals[0].val.str_val.s=scscf_name;
00804             len = strlen(scscf_name);
00805             vals[0].val.str_val.len=MIN(len, 64);
00806 
00807             vals[1].type = DB_INT;
00808             vals[1].nul = 0;
00809             vals[1].val.int_val=S_AUTH;
00810 
00811             vals[2].type = DB_INT;
00812             vals[2].nul = 0;
00813             vals[2].val.int_val=snapshot_version;
00814     
00815             vals[3].type = DB_INT;
00816             vals[3].nul = 0;
00817             vals[3].val.int_val=step_version;
00818     
00819             vals[4].type = DB_STR;
00820             vals[4].nul = 0;
00821             vals[4].val.str_val.s=aud->private_identity.s;
00822             vals[4].val.str_val.len=MIN(aud->private_identity.len, 256);
00823             
00824             vals[5].type = DB_STR;
00825             vals[5].nul = 0;
00826             vals[5].val.str_val.s=aud->public_identity.s;
00827             vals[5].val.str_val.len=MIN(aud->public_identity.len, 256);
00828     
00829             vals[6].type = DB_BLOB;
00830             vals[6].nul = 0;
00831             str data={x.s, x.len};
00832             vals[6].val.blob_val = data;
00833             
00834             if (scscf_dbf.insert(scscf_db, keys, vals, 7) < 0) {
00835                 LOG(L_ERR, "ERR:"M_NAME":bin_cache_dump_auth_to_table(): Error while inserting on snapshot table\n");
00836                 auth_data_unlock(i);
00837                 goto error;
00838             }
00839             bin_free(&x);
00840             
00841             aud = aud->next;
00842         }
00843         auth_data_unlock(i);
00844     }   
00845     
00846     //delete older snapshots
00847     if (delete_older_snapshots("snapshot", scscf_name, S_AUTH, snapshot_version)!=1){
00848         LOG(L_ERR, "ERR:"M_NAME":bin_cache_dump_auth_to_table(): Error while deleting older snapshots from snapshot table\n");
00849         goto error;
00850     }
00851     
00852     //unlock
00853     lock_release(db_lock);
00854     
00855     return 1;
00856 
00857 error:
00858     lock_release(db_lock);//unlock
00859     return 0;
00860 }
00861 
00862 
00863 int bin_db_keep_count=1; 
00874 int delete_older_snapshots(char* table, char* node_id, data_type_t dt, int current_snapshot){
00875 
00876     db_key_t query_cols[3];
00877     db_op_t  query_ops[3];
00878     db_val_t query_vals[3];
00879     int len;
00880 
00881     query_cols[0] = "snapshot_version";
00882     query_ops[0] = OP_LEQ;
00883     query_vals[0].type = DB_INT;
00884     query_vals[0].nul = 0;
00885     query_vals[0].val.int_val = current_snapshot - bin_db_keep_count;
00886     
00887     query_cols[1] = "node_id";
00888     query_ops[1] = OP_EQ;
00889     query_vals[1].type = DB_STR;
00890     query_vals[1].nul = 0;
00891     len = strlen(node_id);
00892     query_vals[1].val.str_val.s=node_id;
00893     query_vals[1].val.str_val.len=MIN(len, 256);
00894     
00895     query_cols[2] = "data_type";
00896     query_ops[2] = OP_EQ;
00897     query_vals[2].type = DB_INT;
00898     query_vals[2].nul = 0;
00899     query_vals[2].val.int_val = dt;
00900 
00901     if (scscf_dbf.use_table(scscf_db, table) < 0) {
00902         LOG(L_ERR, "ERR:"M_NAME":delete_older_snapshots(): Error in use_table\n");
00903         return 0;
00904     }
00905 
00906     if (scscf_dbf.delete(scscf_db, query_cols, query_ops, query_vals, 3) < 0) {
00907         LOG(L_ERR, "ERR:"M_NAME":delete_older_snapshots(): Error while deleting older snapshots\n");
00908         return 0;
00909     }
00910     
00911     return 1;
00912 }
00913 
00914 
00915     /* Load related functions*/
00916     
00928 int s_load(bin_data *x, char* location, char* prepend_fname, data_type_t dt){
00929     switch (scscf_persistency_mode){
00930         case NO_PERSISTENCY:
00931             LOG(L_ERR,"ERR:"M_NAME":s_load: Persistency support was disabled\n");
00932             return 0;
00933         case WITH_FILES:
00934             return bin_load_from_file(x,location,prepend_fname);        
00935         case WITH_DATABASE_BULK:
00936             return bin_load_from_db(x, dt);
00937         case WITH_DATABASE_CACHE:
00938             return bin_load_from_db(NULL, dt); //ignore x, x is empty
00939         default:
00940             LOG(L_ERR,"ERR:"M_NAME":s_load: Can't resume because no such mode %d\n",scscf_persistency_mode);
00941             return 0;
00942     }
00943 }
00944 
00951 int bin_load_from_db(bin_data *x, data_type_t dt){
00952     switch(dt){
00953         case S_REGISTRAR:
00954             return bin_load_registrar_from_table(x);
00955         case S_DIALOGS:
00956             return bin_load_dialogs_from_table(x);
00957         case S_AUTH:
00958             return bin_load_auth_from_table(x);
00959         default:
00960             LOG(L_ERR,"ERR:"M_NAME":bin_load_from_db: No such information to load %d\n", dt);
00961             return 0;
00962     }
00963 }
00964 
00970 int bin_load_registrar_from_table(bin_data *x){
00971     if(x){//whole hashtable dumped to db
00972         return bin_bulk_load_from_table(S_REGISTRAR, x);
00973     }
00974     else{//each hashtable element dumped to DB separately
00975         return bin_cache_load_registrar_from_table();
00976     }
00977 }
00978 
00984 int bin_load_dialogs_from_table(bin_data *x){
00985     if(x){//whole hashtable dumped to db
00986         return bin_bulk_load_from_table(S_DIALOGS, x);
00987     }
00988     else{//each hashtable element dumped to DB separately
00989         return bin_cache_load_dialogs_from_table();
00990     }
00991 }
00992 
00998 int bin_load_auth_from_table(bin_data *x){
00999     if(x){//whole hashtable dumped to db
01000         return bin_bulk_load_from_table(S_AUTH, x);
01001     }
01002     else{//each hashtable element dumped to DB separately
01003         return bin_cache_load_auth_from_table();
01004     }
01005 }
01006 
01013 int bin_bulk_load_from_table(data_type_t dt, bin_data* x){
01014     int snapshot_version;
01015     int r;
01016     int len;
01017     bin_alloc(x,1024);
01018     
01019     //lock
01020     lock_get(db_lock);
01021     
01022     if((r=db_get_last_snapshot_version("snapshot", scscf_name, dt, &snapshot_version))==0){
01023         LOG(L_ERR,"ERR:"M_NAME":bin_bulk_load_from_table: Error while getting snapshot version\n");
01024         lock_release(db_lock);//unlock
01025         return 0;
01026     }
01027     else if(r==-1){//empty table, nothing to load
01028             LOG(L_INFO,"INFO:"M_NAME":bin_bulk_load_from_table: snapshot table empty\n");
01029             lock_release(db_lock);//unlock
01030             return 1;
01031         }
01032         
01033     //set snapshot/step versions
01034     set_versions(dt, snapshot_version+1, 0);
01035         
01036     db_key_t keys[3];
01037     db_val_t vals[3];
01038     db_op_t ops[3];
01039     db_key_t result_cols[1];
01040     
01041     db_res_t *res = NULL;
01042     
01043     keys[0] = "node_id";
01044     keys[1] = "data_type";
01045     keys[2] = "snapshot_version";
01046     
01047     ops[0] = OP_EQ;
01048     ops[1] = OP_EQ;
01049     ops[2] = OP_EQ;
01050 
01051     vals[0].type = DB_STR;
01052     vals[0].nul = 0;
01053     vals[0].val.str_val.s = scscf_name;
01054     len = strlen(scscf_name);
01055     vals[0].val.str_val.len = MIN(len, 256);
01056     
01057     vals[1].type = DB_INT;
01058     vals[1].nul = 0;
01059     vals[1].val.int_val = dt;
01060 
01061     vals[2].type = DB_INT;
01062     vals[2].nul = 0;
01063     vals[2].val.int_val = snapshot_version;
01064     
01065     result_cols[0]="data";
01066     
01067     if (scscf_dbf.use_table(scscf_db, "snapshot") < 0) {
01068         LOG(L_ERR, "ERR:"M_NAME":bin_bulk_load_from_table(): Error in use_table\n");
01069         lock_release(db_lock);//unlock
01070         return 0;
01071     }
01072     
01073     if (scscf_dbf.query(scscf_db, keys, ops, vals, result_cols, 3, 1, 0, &res) < 0) {
01074         LOG(L_ERR, "ERR:"M_NAME":bin_bulk_load_from_table(): Error while querying snapshot table\n");
01075         lock_release(db_lock);//unlock