void kv_attr(struct writer *w, const char *tag, const char *descr, const char *value) { if (!strcmp(tag, "name") || !strcmp(tag, "type")) { /* Special case for name, replace the last prefix */ kv_end(w); kv_start(w, value, NULL); } else { kv_start(w, tag, NULL); kv_data(w, value); kv_end(w); } }
/* * @brief Écrit une entrée dans le .h * * @param kv descripteur d'accès à la base * @param offset_h index dans le .h * @param offset_blk index dans le .blk (à écrire) */ int write_h(KV *kv, len_t offset_h, len_t offset_blk) { kv_start(kv); if(lseek(kv->fd1, offset_h * 4, SEEK_CUR) < 0) { return -1; } if(write(kv->fd1, &offset_blk, 4) == -1) { return -1; } return 42; }
/* * @brief Lecture d'une entrée dans le .h * * @param kv descripteur d'accès à la base * @param offset_h index dans le .h * @param offset_blk index dans le .blk modifié par effet de bord */ int read_h(KV *kv, len_t offset_h, len_t * val_h) { kv_start(kv); if(lseek(kv->fd1, offset_h * 4, SEEK_CUR) < 0) { return -1; } int n = read(kv->fd1, val_h, 4); if(n == -1) { return -1; } return n; }
/* * @brief Cherche la 1ère position dans laquelle écrire dans le .dkv * * @param kv descripteur d'accès à la base * @param offset_dkv index dans le .dkv modifié par effet de bord */ int search_pos_dkv(KV *kv, len_t *offset_dkv) { kv_start(kv); len_t emplacement_libre; off_t offset; while(read(kv->fd4, &emplacement_libre, sizeof(int))) { if(emplacement_libre == 2) // si le bit d'occupation est à 2 on peut réecrire dessus { offset = lseek(kv->fd4, 0, SEEK_CUR); if(offset == -1) { return -1; } else { *offset_dkv = offset - sizeof(int); return 42; } } else { if(lseek(kv->fd4, 2 * 4, SEEK_CUR) < 0) { return -1; } } } // sinon on renvoie l'index de la fin du fichier off_t int_descripteur_max = lseek(kv->fd4, 0, SEEK_END); if(int_descripteur_max == -1) { return -1; } *offset_dkv = (len_t)int_descripteur_max; return 42; }
/* * @brief Recherche de la clé dans la base et renvoi de l'offset correspondant * * @param kv descripteur d'accès à la base * @param key clé * @param offset index modifié par effet de bord */ int offset_cle(KV * kv, const kv_datum * key, len_t * offset) { kv_start(kv); int val_hash = hash(key->ptr, kv); len_t bloc_courant = 0, bloc_suivant = 0; if(lseek(kv->fd1, val_hash * 4 , SEEK_CUR) < 0) { return -1; } if(read(kv->fd1, &bloc_courant, 4) < 0) { return -1; } if(!bloc_courant) { errno = ENOENT; return -1; } int boucle = 0; while(boucle == 0) { if(lseek(kv->fd2, bloc_courant, SEEK_SET) < 0) { return -1; } if(read(kv->fd2, &bloc_suivant, 4) < 0) { return -1; } int i; for(i=0; i<1023; i++) { len_t lg_cle, pos_cle; if(read(kv->fd2, &pos_cle, 4) < 0) { return -1; } if(pos_cle != 0) { if(lseek(kv->fd3, pos_cle, SEEK_SET) < 0) { return -1; } if(read(kv->fd3, &lg_cle, 4) < 0) { return -1; } if(lg_cle == key->len) { char * cle_lue = malloc(lg_cle + 1); if(read(kv->fd3, cle_lue, lg_cle) < 0) { return -1; } cle_lue[lg_cle]= '\0'; if(strcmp(key->ptr, cle_lue) == 0) { free(cle_lue); *offset= lseek(kv->fd3, 0, SEEK_CUR); return 1; } else { free(cle_lue); } } } } if(bloc_suivant && bloc_suivant !=0) { bloc_courant = bloc_suivant; } else { boucle =1; } } return -1; }
/* * @brief Suppression de la clé dans la base * * Remet à zéro l'index adéquat dans le .blk * * Fusionne si besoin les emplacements dans le .dkv et met le bit d'occupation à 2 * pour les emplacements potentiellement restants et non utilisés * * On évite de décaler tous les descripteurs dans le .dkv * * @param kv descripteur d'accès à la base * @param key clé */ int kv_del(KV * kv, const kv_datum * key) { kv_start(kv); int val_hash = hash(key->ptr, kv); len_t bloc_courant, bloc_suivant=0; if(lseek(kv->fd1, val_hash*4 , SEEK_CUR) <0) { return -1; } if(read(kv->fd1, &bloc_courant, 4) <0) { return -1; } if(!bloc_courant) { errno= ENOENT; return -1; } int boucle=0; while(boucle == 0) { if(lseek(kv->fd2, bloc_courant, SEEK_SET) <0) { return -1; } if(read(kv->fd2, &bloc_suivant, 4) <0) { return -1; } int i; for(i=0; i<1023; i++) { len_t lg_cle, pos_cle; if(read(kv->fd2, &pos_cle, 4) <0) { return -1; } if(pos_cle !=0) { if(lseek(kv->fd3, pos_cle, SEEK_SET) < 0) { return -1; } if(read(kv->fd3, &lg_cle, 4) < 0) { return -1; } if(lg_cle == key->len) { char * cle_lue = malloc(lg_cle + 1); if(read(kv->fd3, cle_lue, lg_cle) < 0) { return -1; } cle_lue[lg_cle] = '\0'; if(strcmp(key->ptr, cle_lue) == 0) { free(cle_lue); len_t zero = 0; if(lseek(kv->fd2, -4, SEEK_CUR) == -1) { return -1; } if(write(kv->fd2, &zero, 4) < 0) { return -1; } len_t off_lue; int libre; len_t lg_atruncate; lseek(kv->fd4, taille_header_f, SEEK_SET); while(read(kv->fd4, &libre, sizeof(int))) { if(lseek(kv->fd4, 4, SEEK_CUR) < 0) { return -1; } if(read(kv->fd4, &off_lue, 4) < 0) { return -1; } if(off_lue == pos_cle) { int zero_int =0; if(lseek(kv->fd4, -12, SEEK_CUR) == -1) { return -1; } if(write(kv->fd4, &zero_int, 4) < 0) { return -1; } if(read(kv->fd4, &lg_atruncate, 4) != 4) { return -1; } len_t atruncate=lseek(kv->fd4, -8, SEEK_CUR); // printf("on cherche: \n"); // printf("e: %" PRIu16 " lg %" PRIu16 " off %" PRIu16 "\n", libre, lg_atruncate, pos_cle); if(lseek(kv->fd4, taille_header_f, SEEK_SET) == -1) { return -1; } int existe; int flag_while=0; while((read(kv->fd4, &existe, sizeof(int))) && (flag_while != 2)) { if(existe==0) { len_t lg, off; if(read(kv->fd4, &lg, 4) < 4) { return -1; } if(read(kv->fd4, &off, 4) < 4) { return -1; } if(lg+off == off_lue) { // printf("a fusionner: \n"); // printf("e: %" PRIu16 " lg %" PRIu16 " off %" PRIu16 "\n", existe, lg, off); //modifier lg clé il faut ajouter la longueur total et pas celle de la clé lg_atruncate= lg+lg_atruncate; len_t pos_tmp; if(lseek(kv->fd4, -8, SEEK_CUR) == -1) { return -1; } if(write(kv->fd4, &lg_atruncate, 4) != 4) { return -1; } pos_tmp=lseek(kv->fd4, 4, SEEK_CUR); if(lseek(kv->fd4, atruncate, SEEK_SET) == -1) { return -1; } int deux = 2; if(write(kv->fd4, &deux, 4) != 4) { return -1; } atruncate=pos_tmp-12; off_lue= off; flag_while++; if(lseek(kv->fd4, pos_tmp, SEEK_SET) == -1) { return -1; } // printf("e: %" PRIu16 " lg %" PRIu16 " off %" PRIu16 "\n", existe, lg_atruncate, off_lue); } else if(off == off_lue + lg_atruncate) { // printf("a fusionner: \n"); // printf("e: %" PRIu16 " lg %" PRIu16 " off %" PRIu16 "\n", existe, lg, off); //modifier lg clé il faut ajouter la longueur total et pas celle de la clé lg_atruncate= lg + lg_atruncate; len_t pos_tmp; if(lseek(kv->fd4, -8, SEEK_CUR) == -1) { return -1; } if(write(kv->fd4, &lg_atruncate, 4) != 4) { return -1; } if(write(kv->fd4, &off_lue, 4) != 4) { return -1; } pos_tmp=lseek(kv->fd4, 0, SEEK_CUR); if(lseek(kv->fd4, atruncate, SEEK_SET) == -1) { return -1; } int deux = 2; if(write(kv->fd4, &deux, 4) != 4) { return -1; } atruncate=pos_tmp-12; flag_while++; if(lseek(kv->fd4, pos_tmp, SEEK_SET) == -1) { return -1; } // printf("e: %" PRIu16 " lg %" PRIu16 " off %" PRIu16 "\n", existe, lg_atruncate, off_lue); } } else { if(lseek(kv->fd4, 8, SEEK_CUR) == -1) { return -1; } } } return 0; } } } else free(cle_lue); } } } if(bloc_suivant && bloc_suivant != 0) { bloc_courant = bloc_suivant; } else { boucle =-1; } } errno = ENOENT; return -1; }