void* (*leer_registro)(struct _emu_fs_t*, CLAVE, EMUFS_REG_SIZE*, int*); /**< Método para leer un registro */
void* (*leer_registro_raw)(struct _emu_fs_t*, EMUFS_REG_ID, EMUFS_REG_SIZE*, int *); /**< Método para leer un registro con todo su bloque asociado */
EMUFS_REG_ID (*grabar_registro)(struct _emu_fs_t*, void*, EMUFS_REG_SIZE, int*); /**< Método para grabar un registro */
- EMUFS_REG_ID (*modificar_registro)(struct _emu_fs_t*, CLAVE k, void*, EMUFS_REG_SIZE, int*); /**< Método para modificar un registro */
- int (*borrar_registro)(struct _emu_fs_t*, CLAVE); /**< Método para borrar un registro */
+ EMUFS_REG_ID (*modificar_registro)(struct _emu_fs_t*, CLAVE k, void*, EMUFS_REG_SIZE, int*, INDICE_DATO); /**< Método para modificar un registro */
+ int (*borrar_registro)(struct _emu_fs_t*, CLAVE, INDICE_DATO); /**< Método para borrar un registro */
EMUFS_Estadisticas (*leer_estadisticas)(struct _emu_fs_t *); /**< Método para obtener estádisticas sobre el archivo */
void (*compactar)(struct _emu_fs_t *); /**< Método para compactar el archivo reorganizándolo físicamente */
char *nombre; /**< Nombre del archivo */
static void abreviar_claves(INDICE *idx, B_NodoEntry *array, B_NodoHeader *header);
static void desabreviar_claves(INDICE *idx, B_NodoEntry *array, B_NodoHeader *header);
+int b_borrar_dup_clave(INDICE *idx, INDICE_DATO k, INDICE_DATO dato);
void emufs_indice_b_crear(INDICE *idx)
{
if (idx->tipo_dato == IDX_STRING) {
/* Tengo que sacar el texto repetido del archivo de textos */
- idx->emu_string->borrar_registro(idx->emu_string, clave);
+ idx->emu_string->borrar_registro(idx->emu_string, clave, dummy);
}
return 1;
} else {
return ret;
}
-int emufs_indice_b_borrar(INDICE *idx, CLAVE k)
+int emufs_indice_b_borrar(INDICE *idx, CLAVE k, INDICE_DATO dato)
{
/* Busco el nodo que contiene la clave,si es que esta existe */
char *nodo;
if (encontrado) {
PERR("Clave encontrada, borrando ...");
- fprintf(stderr, "La clave a borrar esta en el nodo %d\n", nodo_id);
- b_borrar_clave(idx, nodo, nodo_id, k);
+ fprintf(stderr, "%s: La clave a borrar esta en el nodo %d\n", idx->nombre, nodo_id);
+ if (idx->funcion != IND_PRIMARIO) {
+ /* Debo borrar primero la clave desde el archivo de
+ * claves repetidas, y si recien ahi me quedo sin claves,
+ * borrar la clave del arbol
+ */
+ PERR("Vamos a borrar duplicados");
+ encontrado = b_borrar_dup_clave(idx, claves[i].dato, dato);
+ fprintf(stderr, "Listo, encontrado = %d\n", encontrado);
+ }
+ if (encontrado) {
+ b_borrar_clave(idx, nodo, nodo_id, k);
+ }
} else {
PERR("Clave no encontrada");
}
{
FILE *fp;
char *out;
- B_NodoHeader header;
- B_NodoEntry *claves;
+ /*B_NodoHeader header;
+ B_NodoEntry *claves;*/
if (id < 0) return NULL;
static void b_grabar_nodo(INDICE *idx, int id, char *data)
{
FILE *fp;
- B_NodoHeader header;
- B_NodoEntry *claves;
+ /*B_NodoHeader header;
+ B_NodoEntry *claves;*/
/* Si las claves son de tipo string debo abreviar antes de guardar */
/* if (idx->tipo_dato == IDX_STRING) {
claves[i-1].hijo_derecho = hijo_izq;
claves[i].hijo_derecho = hijo_der;
}
- /*b_elegir_izquierdo(idx, nodo_header.hijo_izquierdo, hijo1);*/
b_actualizar_header(nodo, &nodo_header);
b_grabar_nodo(idx, nodo_id, nodo);
fprintf(stderr, "La clave esta en la pos = %d\n", pos);
if (header.hijo_izquierdo != -1) {
PERR("Nodo no es hoja, intercambio");
-/* if (pos == 0) {
- actual = b_leer_nodo(idx, nodo_header.hijo_izquierdo);
- else*/
actual = b_leer_nodo(idx, claves[pos].hijo_derecho);
actual_id = claves[pos].hijo_derecho;
p = claves[pos].hijo_derecho;
/* Se cumple la condicion de hijos? */
PERR("Dejo todo consistente");
fprintf(stderr, "Condicion : %d >= %d\n", header_actual.cant, MIN_HIJOS(idx));
- if (header_actual.cant >= MIN_HIJOS(idx)) {
+ if ((header_actual.cant >= MIN_HIJOS(idx)) && (actual_id != 0)) {
PERR("Borrar completo sin fundir");
return;
}
/* Tengo que pasar datos o fundir nodos :-( */
do {
padre_id = header.padre;
+ if (padre_id == -1) continue;
padre = b_leer_nodo(idx, padre_id);
b_leer_header(padre, &header_padre);
claves_padre = b_leer_claves(padre, &header_padre);
if (k.i_clave == -1) PERR("ALGO NO GRABO BIEN!!");
} else {
/* Modifico el que ya existia! */
+ INDICE_DATO dummy;
error = 0;
idx->emu_mult->modificar_registro(idx->emu_mult,
k,
leido,
cant*sizeof(INDICE_DATO)+sizeof(int),
- &error
+ &error,
+ dummy
);
}
/* Clean up! */
* mas de 2 letras iguales, si no no gano nada y complica las cosas
*/
if (iguales > 1) {
+ INDICE_DATO dummy1;
sprintf(salvar, "%d|%s", iguales, resto);
free(actual);
error = 0;
- idx->emu_string->modificar_registro(idx->emu_string, array[i].clave, salvar, strlen(salvar)+1, &error);
+ idx->emu_string->modificar_registro(idx->emu_string, array[i].clave, salvar, strlen(salvar)+1, &error, dummy1);
} else {
free(primera);
primera = actual;
}
iguales = strtol(actual, &resto, 10);
if ((iguales > 0) && (*resto == '|')) {
+ INDICE_DATO dummy2;
strncpy(salvar, primera, iguales);
salvar[iguales] = '\0';
strcat(salvar, resto+1); /* +1 para saltar el separador */
- idx->emu_string->modificar_registro(idx->emu_string, array[i].clave, salvar, strlen(salvar)+1, &error);
+ idx->emu_string->modificar_registro(idx->emu_string, array[i].clave, salvar, strlen(salvar)+1, &error, dummy2);
free(actual);
} else {
free(primera);
return salida;
}
+int b_borrar_dup_clave(INDICE *idx, INDICE_DATO k_dato, INDICE_DATO dato)
+{
+ int cant, pos, i;
+ EMUFS_REG_SIZE tam;
+ int error=0;
+ INDICE_DATO *array;
+ INDICE_DATO dummy1;
+ char *leido;
+ CLAVE k;
+
+ /* Leo el contenido actual */
+ error = 0;
+ k.i_clave = k_dato.id;
+ leido = (char *)idx->emu_mult->leer_registro(idx->emu_mult, k, &tam, &error);
+
+ cant = *((int *)leido);
+
+ /* Obtengo un nuevo lugar para el dato nuevo */
+ array = (INDICE_DATO *)(leido+sizeof(int));
+
+ /* busco pos de dato en array */
+ for(pos=0; pos<cant; pos++) {
+ if (array[pos].id == dato.id) break;
+ }
+
+ for(i=pos; i<cant-1; i++)
+ array[pos] = array[pos+1];
+
+ cant--;
+
+ if (cant == 0) {
+ free(leido);
+ /* No tengo mas cosas en esta clave, la borro */
+ idx->emu_mult->borrar_registro(idx->emu_mult, k, dummy1);
+ return 0;
+ }
+
+ /* Quito el elemento */
+ leido = realloc(leido, sizeof(int)+cant*sizeof(INDICE_DATO));
+
+ /* Actualizo la cantidad */
+ (*((int *)leido)) = cant;
+
+ error = 0;
+ idx->emu_mult->modificar_registro(idx->emu_mult,
+ k,
+ leido,
+ cant*sizeof(INDICE_DATO)+sizeof(int),
+ &error,
+ dummy1
+ );
+
+ free(leido);
+
+ return cant;
+}
+
int emufs_indice_b_insertar(INDICE *idx, CLAVE clave, INDICE_DATO dato);
/** Borra una entrada */
-int emufs_indice_b_borrar(INDICE *idx, CLAVE k);
+int emufs_indice_b_borrar(INDICE *idx, CLAVE k, INDICE_DATO dato);
/** Busca una clave, retorna ubicacion o -1 si no existe */
INDICE_DATO emufs_indice_b_buscar(INDICE *idx, CLAVE clave);
free(leido);
}
}
+
+
+void emufs_indice_borrar(INDICE *primero, CLAVE k, INDICE_DATO dato)
+{
+ INDICE *iter = primero;
+
+ while (iter) {
+ iter->borrar_entrada(iter, k, dato);
+ iter = iter->sig;
+ }
+}
* indice de forma ordenada
*/
int (*agregar_entrada)(struct _indices_h_ *idx, CLAVE k, INDICE_DATO dato);
- /** Borra del indice la clave k */
- int (*borrar_entrada)(struct _indices_h_ *idx, CLAVE k);
+ /** Borra del indice la clave k . Si el indice en multiple en dato
+ * se le debe pasar cual de los datos borrar. */
+ int (*borrar_entrada)(struct _indices_h_ *idx, CLAVE k, INDICE_DATO dato);
/** Determina si existe la clave k retornando su posicion o -1
* en caso fallido
*/
*/
void emufs_indice_agregar(INDICE *primero, char *data, INDICE_DATO dato);
+void emufs_indice_borrar(INDICE *primero, CLAVE k, INDICE_DATO dato);
+
INDICE_DATO emufs_indice_buscar(INDICE *primero, char *data);
CLAVE emufs_indice_generar_clave(INDICE *idx, char *data);
return header.id;
}
-int emufs_tipo1_borrar_registro(EMUFS* efs, CLAVE k)
+int emufs_tipo1_borrar_registro(EMUFS* efs, CLAVE k, INDICE_DATO dato1)
{
char* block; /* bloque leido (en donde está el registro a leer) */
EMUFS_BLOCK_ID block_id; /* id del bloque en donde esta el registro a leer */
return err;
}
+ emufs_indice_borrar(efs->indices, k, dato1);
/* Busco secuencialmente en el bloque el registro a leer */
offset = 0;
do {
}
EMUFS_REG_ID emufs_tipo1_modificar_registro(EMUFS* efs, CLAVE k,
- void *data, EMUFS_REG_SIZE size, int* err)
+ void *data, EMUFS_REG_SIZE size, int* err, INDICE_DATO dato)
{
- emufs_tipo1_borrar_registro(efs, k);
+ emufs_tipo1_borrar_registro(efs, k, dato);
return emufs_tipo1_grabar_registro(efs, data, size, err);
}
EMUFS_REG_ID emufs_tipo1_grabar_registro(EMUFS*, void*, EMUFS_REG_SIZE, int*);
/** Borra un registro de del archivo. */
-int emufs_tipo1_borrar_registro(EMUFS*, CLAVE);
+int emufs_tipo1_borrar_registro(EMUFS*, CLAVE, INDICE_DATO);
/** Método para modificar un registro. */
-EMUFS_REG_ID emufs_tipo1_modificar_registro(EMUFS *emu, CLAVE k, void*, EMUFS_REG_SIZE, int*);
+EMUFS_REG_ID emufs_tipo1_modificar_registro(EMUFS *emu, CLAVE k, void*, EMUFS_REG_SIZE, int*, INDICE_DATO);
/** Método para leer un registro con todo su bloque asociado. */
void* emufs_tipo1_leer_registro_raw(EMUFS *emu, EMUFS_REG_ID id, EMUFS_REG_SIZE *size, int *pos);
}
/* Borra un registro determinado y actualiza los archivos de Posicion Relativa (Indice-Offset) y el de Gaps */
-int emufs_tipo2_borrar_registro(EMUFS *efs, CLAVE k)
+int emufs_tipo2_borrar_registro(EMUFS *efs, CLAVE k, INDICE_DATO dato1)
{
EMUFS_OFFSET reg_offset,reg_size;
EMUFS_REG_ID id_reg;
if (id_reg == -1) return EMUFS_NOT_FOUND;
+ emufs_indice_borrar(efs->indices, k, dato1);
/* Obtenemos el Size del Registro en cuestion y hacemos un dummyfill*/
emufs_tipo2_get_regsize(efs,reg_offset,®_size);
emufs_tipo2_dummyfill(efs,reg_offset,reg_size);
}
/* Realiza la actualizacin de un registro ya existente */
-EMUFS_REG_ID emufs_tipo2_modificar_registro(EMUFS *efs, CLAVE k, void *data, EMUFS_REG_SIZE size, int *error)
+EMUFS_REG_ID emufs_tipo2_modificar_registro(EMUFS *efs, CLAVE k, void *data, EMUFS_REG_SIZE size, int *error, INDICE_DATO dato)
{
- emufs_tipo2_borrar_registro(efs, k);
+ emufs_tipo2_borrar_registro(efs, k, dato);
return emufs_tipo2_grabar_registro(efs, data, size, error);
}
* \param id_reg Id del registro que se quiere eliminar.
* \return \b int Indicador de exito de la operacion.
*/
-int emufs_tipo2_borrar_registro(EMUFS *efs, CLAVE k);
+int emufs_tipo2_borrar_registro(EMUFS *efs, CLAVE k, INDICE_DATO dato);
/** Devuelve el \em Size de un registro dado, en base a su \em ID.
*
int emufs_tipo2_dummyfill(EMUFS *efs, EMUFS_OFFSET reg_pos, EMUFS_REG_SIZE amount);
/** Método para modificar un registro */
-EMUFS_REG_ID emufs_tipo2_modificar_registro(EMUFS *efs, CLAVE k, void *data, EMUFS_REG_SIZE size, int *error);
+EMUFS_REG_ID emufs_tipo2_modificar_registro(EMUFS *efs, CLAVE k, void *data, EMUFS_REG_SIZE size, int *error, INDICE_DATO dato);
/** Método para recolectar/obtener la estadisticas del archivo tipo 2
*
}
/*borra un registro de un bloque y acomoda los registros que quedan*/
-int emufs_tipo3_borrar_registro(EMUFS *emu, CLAVE k)
+int emufs_tipo3_borrar_registro(EMUFS *emu, CLAVE k, INDICE_DATO dato1)
{
EMUFS_BLOCK_SIZE num_bloque;
EMUFS_BLOCK_SIZE ptr_elim;
return -1;
}
- PERR("Borrando clave");
- /* TODO Borrar en todos los indices!! */
- emu->indices->borrar_entrada(emu->indices, k);
/*apunto al registro que voy a eliminar*/
ptr_elim = 0;
while ( ptr_elim < emu->tam_bloque ){
}
free(bloque);
+ PERR("Borrando claves");
+ emufs_indice_borrar(emu->indices, k, dato1);
+ PERR("Clave borrada de todos los indices");
return 0;
}
return stats;
}
-EMUFS_REG_ID emufs_tipo3_modificar_registro(EMUFS *emu, CLAVE k, void *data, EMUFS_REG_SIZE size, int *error)
+EMUFS_REG_ID emufs_tipo3_modificar_registro(EMUFS *emu, CLAVE k, void *data, EMUFS_REG_SIZE size, int *error, INDICE_DATO dato)
{
- emufs_tipo3_borrar_registro(emu, k);
+ emufs_tipo3_borrar_registro(emu, k, dato);
return emufs_tipo3_grabar_registro(emu, data, size, error);
}
* \param emu Esructura para manejar los archivos.
* \param id_reg Id del registro a borrar.
*/
-int emufs_tipo3_borrar_registro(EMUFS *emu, CLAVE k);
+int emufs_tipo3_borrar_registro(EMUFS *emu, CLAVE k, INDICE_DATO dato);
/** Método para modificar un registro
* \param emu Esructura para manejar los archivos.
* \param ptr Cadena de datos que contiene el nuevo registro.
* \param err Codigo de error devuelto en caso de falla.
*/
-EMUFS_REG_ID emufs_tipo3_modificar_registro(EMUFS *emu, CLAVE k, void *ptr, EMUFS_REG_SIZE, int*err);
+EMUFS_REG_ID emufs_tipo3_modificar_registro(EMUFS *emu, CLAVE k, void *ptr, EMUFS_REG_SIZE, int*err, INDICE_DATO);
/** Completa una estructura del tipo EMUFS_Estadisticas con las estadísticas del
* archivo de datos, espacio libre total, cantidad de registros, cantidad de bloques,
tmp = procesar_guardar_articulo(articulo, &size, lst_articulos);
if (tmp) {
CLAVE k;
+ INDICE_DATO dummy1;
error = 0;
k = emufs_indice_generar_clave_desde_valor(lst_articulos->fp->indices, (char *)&articulo->numero);
- lst_articulos->fp->modificar_registro(lst_articulos->fp, k, tmp, size, &error);
+ /* dummy se pasa porque esto se hace por clave primaria, y el INDICE_DATO que se
+ * pasa solo es requerido cuando son claves multiples
+ */
+ lst_articulos->fp->modificar_registro(lst_articulos->fp, k, tmp, size, &error, dummy1);
free(tmp);
}
wrefresh(win);
getch();
} else {
+ INDICE_DATO dummy;
k = emufs_indice_generar_clave_desde_valor(lst_articulos->fp->indices, (char *)&(articulo->numero));
- lst_articulos->fp->borrar_registro(lst_articulos->fp, k);
+ PERR("Borrando ARTICULO")
+ lst_articulos->fp->borrar_registro(lst_articulos->fp, k, dummy);
+ PERR("LISTO BORRADO");
free(articulo);
}
sprintf(articulo.pvu, "%.2f", pvu);
tmp = procesar_guardar_articulo(&articulo, &size, lst_articulos);
error = 0;
- lst_articulos->fp->modificar_registro(lst_articulos->fp, k1, tmp, size, &error);
+ /* README : Aca si tengo que pasar el INDICE_DATO correcto, para que la funcion
+ * borrar sea capaz de eliminar solo el item que corresponde en las
+ * claves con repeticion
+ */
+ lst_articulos->fp->modificar_registro(lst_articulos->fp, k1, tmp, size, &error, datos[i]);
}
}
if (datos) free(datos);
t_Factura *fact;
EMUFS_REG_ID id;
CLAVE k;
+ INDICE_DATO dummy;
win = newwin(LINES-4, COLS-2, 2, 1);
box(win, 0, 0);
}
k = emufs_indice_generar_clave_desde_valor(lst_facturas->fp->indices, (char *)(&fact->numero));
- lst_facturas->fp->borrar_registro(lst_facturas->fp, k);
+ lst_facturas->fp->borrar_registro(lst_facturas->fp, k, dummy);
k.i_clave = fact->reg_nota;
- lst_facturas->fp_texto->borrar_registro(lst_facturas->fp_texto, k);
+ lst_facturas->fp_texto->borrar_registro(lst_facturas->fp_texto, k, dummy);
if (fact->items) free(fact->items);
if (fact->nota) free(fact->nota);
entrada = procesar_guardar_factura(fact, lst_facturas, &size);
if (entrada) {
CLAVE k;
+ INDICE_DATO dummy;
k = emufs_indice_generar_clave_desde_valor(lst_facturas->fp->indices, (char *)&fact->numero);
- lst_facturas->fp->modificar_registro(lst_facturas->fp, k, entrada, size, &error);
+ lst_facturas->fp->modificar_registro(lst_facturas->fp, k, entrada, size, &error, dummy);
k.i_clave = id_texto;
- id_texto = lst_facturas->fp_texto->modificar_registro(lst_facturas->fp_texto, k, fact->nota, strlen(fact->nota)+1, &error);
+ id_texto = lst_facturas->fp_texto->modificar_registro(lst_facturas->fp_texto, k, fact->nota, strlen(fact->nota)+1, &error, dummy);
free(entrada);
}