From 8ed872279800f018aa1dfa690d646428d68820c1 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Sun, 30 May 2004 09:01:41 +0000 Subject: [PATCH] Se amplia MERGEFILE para poder usarlo de salida tambien (al crear los chunks). Antes se podia usar solo para entrada (al hacer el merge). Gracias a esto ahora se implementa usando tmpfile() para los archivos temporales. --- emufs/external_sort/mergefile.c | 66 ++++++++++++--------------------- emufs/external_sort/mergefile.h | 15 ++++---- emufs/external_sort/sort_test.c | 47 ++++++++++++++--------- 3 files changed, 60 insertions(+), 68 deletions(-) diff --git a/emufs/external_sort/mergefile.c b/emufs/external_sort/mergefile.c index 2d59fb1..f5bf0b0 100644 --- a/emufs/external_sort/mergefile.c +++ b/emufs/external_sort/mergefile.c @@ -41,51 +41,18 @@ #include #include -char* mergefile_makefilename(int i) -{ - size_t size = sizeof(MERGEFILE_TEMPLATE) + 8; /* 8 más para el int */ - char* filename = malloc(size); - if (!filename) return 0; - /* Hasta que me de la memoria para crear el nombre del archivo */ - while (snprintf(filename, size, MERGEFILE_TEMPLATE, i) >= size) { - char* new; - size += 8; - new = realloc(filename, size); - if (new) { - filename = new; - } else { - free(filename); - return 0; - } - } - return filename; -} - -MERGEFILE* mergefile_new(int i) +MERGEFILE* mergefile_new() { MERGEFILE* mf = malloc(sizeof(MERGEFILE)); if (!mf) { return 0; } - /* asigno el nombre de archivo */ - if (!(mf->filename = mergefile_makefilename(i))) { - free(mf); - return 0; - } /* abre archivo */ - if (!(mf->fp = fopen(mf->filename, "rb"))) { - free(mf->filename); - free(mf); - return 0; - } - /* obtiene dato */ - if (fscanf(mf->fp, "%i", &(mf->next)) <= 0) { - fclose(mf->fp); - free(mf->filename); + if (!(mf->fp = tmpfile())) { free(mf); return 0; } - mf->more = 1; + mf->more = 0; return mf; } @@ -93,22 +60,27 @@ void mergefile_delete(MERGEFILE* mf) { assert(mf); assert(mf->fp); - assert(mf->filename); fclose(mf->fp); - remove(mf->filename); - free(mf->filename); free(mf); } -int mergefile_peek_next(MERGEFILE* mf) +int mergefile_switch_to_input(MERGEFILE* mf) +{ + /* obtiene dato, debe tener al menos uno para ser un mergefile */ + if (fseek(mf->fp, 0L, SEEK_SET)) return 0; + if (fscanf(mf->fp, "%i", &(mf->next)) <= 0) return 0; + mf->more = 1; + return 1; /* OK */ +} + +int mergefile_push(MERGEFILE* mf, int data) { assert(mf); assert(mf->fp); - assert(mf->more); - return mf->next; + return fprintf(mf->fp, "%i\n", data); } -int mergefile_pop_next(MERGEFILE* mf) +int mergefile_pop(MERGEFILE* mf) { int ret; assert(mf); @@ -120,6 +92,14 @@ int mergefile_pop_next(MERGEFILE* mf) return ret; } +int mergefile_peek(MERGEFILE* mf) +{ + assert(mf); + assert(mf->fp); + assert(mf->more); + return mf->next; +} + int mergefile_has_more(MERGEFILE* mf) { assert(mf); diff --git a/emufs/external_sort/mergefile.h b/emufs/external_sort/mergefile.h index 1183d14..44c5fdd 100644 --- a/emufs/external_sort/mergefile.h +++ b/emufs/external_sort/mergefile.h @@ -40,26 +40,25 @@ #include -#define MERGEFILE_TEMPLATE "sorted_chunk.%i" - typedef struct { FILE* fp; - char* filename; int next; int more; } MERGEFILE; -char* mergefile_makefilename(int i); - -MERGEFILE* mergefile_new(int i); +MERGEFILE* mergefile_new(); void mergefile_delete(MERGEFILE* mf); -int mergefile_peek_next(MERGEFILE* mf); +int mergefile_switch_to_input(MERGEFILE* mf); + +int mergefile_push(MERGEFILE* mf, int data); + +int mergefile_pop(MERGEFILE* mf); -int mergefile_pop_next(MERGEFILE* mf); +int mergefile_peek(MERGEFILE* mf); int mergefile_has_more(MERGEFILE* mf); diff --git a/emufs/external_sort/sort_test.c b/emufs/external_sort/sort_test.c index 65c653d..234e571 100644 --- a/emufs/external_sort/sort_test.c +++ b/emufs/external_sort/sort_test.c @@ -35,6 +35,7 @@ void buffer_dump(BUFFORD* b) int main(int argc, char* argv[]) { + MERGEFILE** mfpool = 0; FILE* fp; int i; BUFFORD* b = bufford_new(8, sizeof(int), &cmp); @@ -57,11 +58,21 @@ int main(int argc, char* argv[]) while (!bufford_empty(b)) { int* c; int x; - FILE* fpo; - char filename[32]; - snprintf(filename, sizeof(filename), "sorted_chunk.%i", i); - if (!(fpo = fopen(filename, "w"))) { + MERGEFILE** mfpool_new = realloc(mfpool, sizeof(MERGEFILE) * (i+1)); + if (!mfpool_new) { + int j; + for (j = 0; j < i; j++) mergefile_delete(mfpool[j]); + free(mfpool); + bufford_delete(b); + return 3; + } else { + mfpool = mfpool_new; + } + if (!(mfpool[i] = mergefile_new())) { + int j; fclose(fp); + for (j = 0; j < i; j++) mergefile_delete(mfpool[j]); + free(mfpool); bufford_delete(b); return 3; } @@ -71,7 +82,9 @@ int main(int argc, char* argv[]) if (!feof(fp)) fscanf(fp, "%i", &x); if (!feof(fp) && !bufford_push(b, &x)) { /* ERROR: no se pudo insertar */ - fclose(fpo); + int j; + for (j = 0; j < i+1; j++) mergefile_delete(mfpool[j]); + free(mfpool); fclose(fp); bufford_delete(b); return 4; @@ -79,29 +92,29 @@ int main(int argc, char* argv[]) x = *c; free(c); printf("%- 8i\t", x); - fprintf(fpo, "%i\n", x); + if (!mergefile_push(mfpool[i], x)) printf("No se pudo escribir en el mergefile %i\n", i); buffer_dump(b); } printf("Lote %i finalizado!\n\n", i); i++; - fclose(fpo); } fclose(fp); /* Mezclo lotes */ { int n, min; - MERGEFILE** mfpool = malloc(sizeof(MERGEFILE) * i); MERGEFILE* min_mf; FILE* fp = fopen("salida.txt", "w"); assert(fp); - assert(mfpool); printf("Abriendo archivos y buscando mínimo...\n"); for (n = 0; n < i; n++) { - mfpool[n] = mergefile_new(n); + if (!mergefile_switch_to_input(mfpool[n])) { + printf("No se pudo pasar a modo entrada el mfpool %i.\n", n); + return 15; + } assert(mfpool[n]); - printf("Archivo %i: leído = %i\n", n, mergefile_peek_next(mfpool[n])); - if (!n || mergefile_peek_next(mfpool[n]) < min) { - min = mergefile_peek_next(mfpool[n]); + printf("Archivo %i: leído = %i\n", n, mergefile_peek(mfpool[n])); + if (!n || mergefile_peek(mfpool[n]) < min) { + min = mergefile_peek(mfpool[n]); min_mf = mfpool[n]; printf("min = %i\n", min); } @@ -111,17 +124,17 @@ int main(int argc, char* argv[]) int assigned = 0; /* guardo el mínimo en el archivo de salida */ fprintf(fp, "%i\n", min); - mergefile_pop_next(min_mf); /* lo saco del archivo */ + mergefile_pop(min_mf); /* lo saco del archivo */ /* obtengo el próximo mínimo */ for (n = 0; n < i; n++) { if (mergefile_has_more(mfpool[n])) { - printf("Archivo %i: leído = %i\n", n, mergefile_peek_next(mfpool[n])); + printf("Archivo %i: leído = %i\n", n, mergefile_peek(mfpool[n])); } else { printf("Archivo %i: No hay más datos\n", n); } - if (mergefile_has_more(mfpool[n]) && (!assigned || mergefile_peek_next(mfpool[n]) < min)) { + if (mergefile_has_more(mfpool[n]) && (!assigned || mergefile_peek(mfpool[n]) < min)) { assigned = 1; - min = mergefile_peek_next(mfpool[n]); + min = mergefile_peek(mfpool[n]); min_mf = mfpool[n]; printf("min = %i\n", min); } -- 2.43.0