str* get_prefix(hash_t *ph, str* sd) { int hash_entry; unsigned int dhash; pd_t* it; if(ph==NULL || ph->dhash==NULL || ph->hash_size>MAX_HASH_SIZE) { LM_ERR("bad parameters\n"); return NULL; } dhash = pdt_compute_hash(sd); hash_entry = get_hash_entry(dhash, ph->hash_size); it = ph->dhash[hash_entry]; while(it!=NULL && it->dhash<=dhash) { if(it->dhash==dhash && it->domain.len==sd->len && strncasecmp(it->domain.s, sd->s, sd->len)==0) return &it->prefix; it = it->n; } return NULL; }
int check_pd(hash_t *ph, str *sp, str *sd) { unsigned int i; unsigned int dhash; pd_t* it; if(ph==NULL || sp==NULL || sd==NULL) { LM_ERR(" bad parameters\n"); return -1; } dhash = pdt_compute_hash(sd); for(i=0; i<ph->hash_size; i++) { it = ph->dhash[i]; while(it != NULL) { if((it->domain.len==sd->len && strncasecmp(it->domain.s, sd->s, sd->len)==0) || (it->prefix.len==sp->len && strncasecmp(it->prefix.s, sp->s, sp->len)==0)) return 1; it = it->n; } } return 0; }
str* pdt_get_prefix(pdt_hash_t *ph, str* sd) { int hash_entry; unsigned int dhash; pd_t* it; if(ph==NULL || ph->dhash==NULL || ph->hash_size>MAX_HASH_SIZE) { LOG(L_ERR, "PDT:pdt_get_prefix: bad parameters\n"); return NULL; } dhash = pdt_compute_hash(sd->s); hash_entry = get_hash_entry(dhash, ph->hash_size); lock_get(&ph->dhash[hash_entry].lock); it = ph->dhash[hash_entry].e; while(it!=NULL && it->dhash<=dhash) { if(it->dhash==dhash && it->domain.len==sd->len && strncasecmp(it->domain.s, sd->s, sd->len)==0) { lock_release(&ph->dhash[hash_entry].lock); return &it->prefix; } it = it->n; } lock_release(&ph->dhash[hash_entry].lock); return NULL; }
int pdt_remove_from_hash(pdt_hash_t *hash, str *sd) { int hash_entry=0; unsigned int dhash; pd_t *it, *tmp; if(sd==NULL) return 0; if(hash==NULL) { LOG(L_ERR, "PDT:pdt_remove_from_hash: bad parameters\n"); return -1; } /* find the list where the cell must be */ dhash = pdt_compute_hash(sd->s); hash_entry = get_hash_entry(dhash, hash->hash_size); lock_get(&hash->dhash[hash_entry].lock); /* first element of the list */ it = hash->dhash[hash_entry].e; /* find the cell in the list */ /* a double linked list in the hash is kept alphabetically * or numerical ordered */ tmp = NULL; while(it!=NULL) { if( it->dhash==dhash && it->domain.len==sd->len && strncasecmp(it->domain.s, sd->s, sd->len)==0) break; tmp = it; it = it->n; } if(it!=NULL) { if(tmp!=NULL) tmp->n = it->n; else hash->dhash[hash_entry].e = it->n; if(it->n) it->n->p = it->p; free_cell(it); } lock_release(&hash->dhash[hash_entry].lock); return 0; }
int pdt_add_to_hash(pdt_hash_t *hash, str *sp, str *sd) { int hash_entry=0; unsigned int dhash; pd_t *it, *tmp; pd_t *cell; if(hash==NULL || sp==NULL || sd==NULL) { LOG(L_ERR, "PDT:pdt_add_to_hash: bad parameters\n"); return -1; } dhash = pdt_compute_hash(sd->s); hash_entry = get_hash_entry(dhash, hash->hash_size); lock_get(&hash->dhash[hash_entry].lock); it = hash->dhash[hash_entry].e; tmp = NULL; while(it!=NULL && it->dhash < dhash) { tmp = it; it = it->n; } /* we need a new entry for this cell */ cell = new_cell(sp, sd); if(cell == NULL) { lock_release(&hash->dhash[hash_entry].lock); return -1; } if(tmp) tmp->n=cell; else hash->dhash[hash_entry].e = cell; cell->p=tmp; cell->n=it; if(it) it->p=cell; lock_release(&hash->dhash[hash_entry].lock); return 0; }
/* returns -1 if any error * returns 1 if does not exist in hash * returns 0 if deleted succesfully * */ int remove_from_hash(hash_t *hash, str *sd) { int hash_entry=0; unsigned int dhash; pd_t *it, *prev; if(hash==NULL || sd==NULL || sd->s==NULL) { LM_ERR("bad parameters\n"); return -1; /* error */ } /* find the list where the cell must be */ dhash = pdt_compute_hash(sd); hash_entry = get_hash_entry(dhash, hash->hash_size); /* first element of the list */ it = hash->dhash[hash_entry]; /* find the cell in the list */ /* a double linked list in the hash is kept alphabetically * or numerical ordered */ prev = NULL; while(it!=NULL) { if( it->dhash==dhash && it->domain.len==sd->len && strncasecmp(it->domain.s, sd->s, sd->len)==0) break; prev = it; it = it->n; } if(it==NULL) return 1; /* does not exist in hash, nothing to delete */ /* the prefix/domain pair exists and must be deleted */ if(prev!=NULL) prev->n = it->n; else hash->dhash[hash_entry] = it->n; if(it->n) it->n->p = it->p; // check who should do it // free_cell(it); return 0; }
pd_t* new_cell(str* p, str *d) { pd_t* cell = NULL; if(p==NULL || p->s==NULL || d==NULL || d->s==NULL) { LM_ERR("bad parameters\n"); return NULL; } /* the cell is in share memory */ cell = (pd_t*)shm_malloc(sizeof(pd_t)); /* if there is no space return just NULL */ if(cell==NULL) { LM_ERR("no more shm memory.\n"); return NULL; } memset(cell, 0, sizeof(pd_t)); cell->prefix.s = (char*)shm_malloc((1+p->len)*sizeof(char)); if(cell->prefix.s==NULL) { shm_free(cell); LM_ERR("no more shm memory\n"); return NULL; } strncpy(cell->prefix.s, p->s, p->len); cell->prefix.len = p->len; cell->prefix.s[p->len] = '\0'; cell->domain.s = (char*)shm_malloc((1+d->len)*sizeof(char)); if(cell->domain.s==NULL) { shm_free(cell->prefix.s); shm_free(cell); LM_ERR("no more shm memory!\n"); return NULL; } strncpy(cell->domain.s, d->s, d->len); cell->domain.len = d->len; cell->domain.s[d->len] = '\0'; cell->dhash = pdt_compute_hash(&cell->domain); /* return the newly allocated in share memory cell */ return cell; }
int add_to_hash(hash_t *hash, str *sp, str *sd) { int hash_entry=0; unsigned int dhash; pd_t *it, *prev, *cell; if(hash==NULL || sp==NULL || sp->s==NULL || sd==NULL || sd->s==NULL) { LM_ERR("bad parameters\n"); return -1; } dhash = pdt_compute_hash(sd); hash_entry = get_hash_entry(dhash, hash->hash_size); it = hash->dhash[hash_entry]; prev = NULL; while(it!=NULL && it->dhash < dhash) { prev = it; it = it->n; } /* we need a new entry for this cell */ cell = new_cell(sp, sd); if(cell == NULL) return -1; if(prev) prev->n=cell; else hash->dhash[hash_entry]= cell; cell->p=prev; cell->n=it; if(it) it->p=cell; return 0; }
int pdt_check_pd(pdt_hash_t *ph, str *sp, str *sd) { int i; unsigned int dhash; pd_t* it; if(ph==NULL || sp==NULL || sd==NULL) { LOG(L_ERR, "PDT:pdt_check_pd: bad parameters\n"); return -1; } dhash = pdt_compute_hash(sd->s); for(i=0; i<ph->hash_size; i++) { lock_get(&ph->dhash[i].lock); it = ph->dhash[i].e; while(it != NULL) { if((it->domain.len==sd->len && strncasecmp(it->domain.s, sd->s, sd->len)==0) || (it->prefix.len==sp->len && strncasecmp(it->prefix.s, sp->s, sp->len)==0)) { lock_release(&ph->dhash[i].lock); return 1; } it = it->n; } lock_release(&ph->dhash[i].lock); } return 0; }
static void rpc_delete(rpc_t* rpc, void* c) { str sd; unsigned int dhash; int hash_entry; pd_t *it; pd_op_t *ito, *tmp; db_key_t db_keys[1] = {domain_column}; db_val_t db_vals[1]; db_op_t db_ops[1] = {OP_EQ}; if(_dhash==NULL) { LOG(L_ERR, "PDT:pdt_fifo_delete: strange situation\n"); rpc->fault(c, 500, "Server Error"); return; } /* Use s to make sure the string is zero terminated */ if (rpc->scan(c, "s", &sd.s) < 1) { rpc->fault(c, 400, "Parameter Missing"); return; } sd.len = strlen(sd.s); if(*sd.s=='\0') { LOG(L_INFO, "PDT:pdt_fifo_delete: empty domain\n"); rpc->fault(c, 400, "Empty Parameter"); return; } dhash = pdt_compute_hash(sd.s); hash_entry = get_hash_entry(dhash, _dhash->hash_size); lock_get(&_dhash->diff_lock); lock_get(&_dhash->dhash[hash_entry].lock); it = _dhash->dhash[hash_entry].e; while(it!=NULL && it->dhash<=dhash) { if(it->dhash==dhash && it->domain.len==sd.len && strncasecmp(it->domain.s, sd.s, sd.len)==0) break; it = it->n; } if(it!=NULL) { if(it->p!=NULL) (it->p)->n = it->n; else _dhash->dhash[hash_entry].e = it->n; if(it->n) (it->n)->p = it->p; } lock_release(&_dhash->dhash[hash_entry].lock); if(it!=NULL) { tmp = new_pd_op(it, 0, PDT_DELETE); if(tmp==NULL) { LOG(L_ERR, "PDT:pdt_fifo_delete: no more shm!\n"); rpc->fault(c, 431, "No Shared Memory Left"); lock_release(&_dhash->diff_lock); return; } _dhash->max_id++; tmp->id = _dhash->max_id; if(_dhash->diff==NULL) { _dhash->diff = tmp; DBG("PDT:pdt_fifo_delete: op[%d]=%d...\n", tmp->id, tmp->op); goto done; } ito = _dhash->diff; while(ito->n!=NULL) ito = ito->n; ito->n = tmp; tmp->p = ito; DBG("PDT:pdt_fifo_delete: op[%d]=%d...\n", tmp->id, tmp->op); dhash = 1; } else { dhash = 0; } done: lock_release(&_dhash->diff_lock); if(dhash==0) { DBG("PDT:pdt_fifo_delete: prefix for domain [%s] not found\n", sd.s); rpc->fault(c, 404, "Domain Not Found"); } else { db_vals[0].type = DB_STR; db_vals[0].nul = 0; db_vals[0].val.str_val.s = sd.s; db_vals[0].val.str_val.len = sd.len; if(pdt_dbf.delete(db_con, db_keys, db_ops, db_vals, 1)<0) { LOG(L_ERR,"PDT:pdt_fifo_delete: database/cache are inconsistent\n"); rpc->fault(c, 502, "Database And Cache Are Inconsistent"); } } }