From 692955e3d2c990c75d132a2e99ec57d8d3032a1e Mon Sep 17 00:00:00 2001 From: Lew Rossman Date: Tue, 5 Mar 2019 09:23:49 -0500 Subject: [PATCH 1/9] Give external apps access to binary output file (#407) --- src/epanet.c | 7 ++++++- src/project.c | 3 ++- src/report.c | 26 ++++++++++++++++---------- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/epanet.c b/src/epanet.c index 626d65b..45e6e6c 100644 --- a/src/epanet.c +++ b/src/epanet.c @@ -7,7 +7,7 @@ Authors: see AUTHORS Copyright: see AUTHORS License: see LICENSE - Last Updated: 02/08/2019 + Last Updated: 03/05/2019 ****************************************************************************** */ @@ -819,6 +819,11 @@ int DLLEXPORT EN_closeQ(EN_Project p) if (!p->Openflag) return 102; closequal(p); p->quality.OpenQflag = FALSE; + if (p->outfile.OutFile != NULL) + { + fclose(p->outfile.OutFile); + p->outfile.OutFile = NULL; + } return 0; } diff --git a/src/project.c b/src/project.c index 349fa13..b8e6119 100644 --- a/src/project.c +++ b/src/project.c @@ -7,7 +7,7 @@ Authors: see AUTHORS Copyright: see AUTHORS License: see LICENSE - Last Updated: 01/01/2019 + Last Updated: 03/05/2019 ****************************************************************************** */ @@ -95,6 +95,7 @@ int openhydfile(Project *pr) { if (pr->outfile.Hydflag == SCRATCH) return 0; fclose(pr->outfile.HydFile); + pr->outfile.HydFile = NULL; } // Use Hydflag to determine the type of hydraulics file to use. diff --git a/src/report.c b/src/report.c index 55387da..0032ee7 100644 --- a/src/report.c +++ b/src/report.c @@ -7,7 +7,7 @@ Authors: see AUTHORS Copyright: see AUTHORS License: see LICENSE - Last Updated: 11/27/2018 + Last Updated: 03/05/2019 ****************************************************************************** */ @@ -98,12 +98,7 @@ int copyreport(Project* pr, char *filename) // Copy contents of project's report file if (rpt->RptFile) { - c = fgetc(rpt->RptFile); - while (c != EOF) - { - fputc(c, tfile); - c = fgetc(rpt->RptFile); - } + while ((c = fgetc(rpt->RptFile)) != EOF) fputc(c, tfile); fclose(rpt->RptFile); } @@ -539,9 +534,6 @@ int writeresults(Project *pr) // at each reporting time. //----------------------------------------------------------- - // Return if no output file - if (outFile == NULL) return 106; - // Return if no nodes or links selected for reporting // or if no node or link report variables enabled if (!rpt->Nodeflag && !rpt->Linkflag) return errcode; @@ -552,6 +544,13 @@ int writeresults(Project *pr) for (j = LENGTH; j <= FRICTION; j++) nlv += rpt->Field[j].Enabled; if (nnv == 0 && nlv == 0) return errcode; + // Return if no output file + if (outFile == NULL) + { + outFile = fopen(pr->outfile.OutFname, "r+b"); + if (outFile == NULL) return 106; + } + // Allocate memory for output variables: // m = larger of # node variables & # link variables // n = larger of # nodes & # links @@ -592,6 +591,13 @@ int writeresults(Project *pr) } } + // Free output file + if (outFile != NULL) + { + fclose(outFile); + outFile = NULL; + } + // Free allocated memory for (j = 0; j < m; j++) free(x[j]); free(x); From 8052ed0b6f5d8a2c2073e864d0cfbada37bd2e29 Mon Sep 17 00:00:00 2001 From: Lew Rossman Date: Tue, 5 Mar 2019 15:20:37 -0500 Subject: [PATCH 2/9] Walking back closing/opening output file --- src/epanet.c | 2 ++ src/report.c | 11 ++++------- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/epanet.c b/src/epanet.c index 45e6e6c..383bd6f 100644 --- a/src/epanet.c +++ b/src/epanet.c @@ -819,11 +819,13 @@ int DLLEXPORT EN_closeQ(EN_Project p) if (!p->Openflag) return 102; closequal(p); p->quality.OpenQflag = FALSE; +/* if (p->outfile.OutFile != NULL) { fclose(p->outfile.OutFile); p->outfile.OutFile = NULL; } +*/ return 0; } diff --git a/src/report.c b/src/report.c index 0032ee7..4d0c4df 100644 --- a/src/report.c +++ b/src/report.c @@ -545,11 +545,8 @@ int writeresults(Project *pr) if (nnv == 0 && nlv == 0) return errcode; // Return if no output file - if (outFile == NULL) - { - outFile = fopen(pr->outfile.OutFname, "r+b"); - if (outFile == NULL) return 106; - } +// if (outFile == NULL) outFile = fopen(pr->outfile.OutFname, "r+b"); + if (outFile == NULL) return 106; // Allocate memory for output variables: // m = larger of # node variables & # link variables @@ -590,14 +587,14 @@ int writeresults(Project *pr) time->Htime += time->Rstep; } } - +/* // Free output file if (outFile != NULL) { fclose(outFile); outFile = NULL; } - +*/ // Free allocated memory for (j = 0; j < m; j++) free(x[j]); free(x); From f2c07188198d6883e6f14e8c9d419155192478e3 Mon Sep 17 00:00:00 2001 From: Lew Rossman Date: Tue, 5 Mar 2019 16:15:33 -0500 Subject: [PATCH 3/9] Refactored closing/opening of output file --- src/epanet.c | 4 ++-- src/project.c | 10 +++++++++- src/report.c | 6 +++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/epanet.c b/src/epanet.c index 383bd6f..57952ec 100644 --- a/src/epanet.c +++ b/src/epanet.c @@ -819,13 +819,13 @@ int DLLEXPORT EN_closeQ(EN_Project p) if (!p->Openflag) return 102; closequal(p); p->quality.OpenQflag = FALSE; -/* + if (p->outfile.OutFile != NULL) { fclose(p->outfile.OutFile); p->outfile.OutFile = NULL; } -*/ + return 0; } diff --git a/src/project.c b/src/project.c index b8e6119..0a40489 100644 --- a/src/project.c +++ b/src/project.c @@ -49,7 +49,11 @@ int openfiles(Project *pr, const char *f1, const char *f2, const char *f3) strncpy(pr->report.Rpt1Fname, f2, MAXFNAME); strncpy(pr->outfile.OutFname, f3, MAXFNAME); if (strlen(f3) > 0) pr->outfile.Outflag = SAVE; - else pr->outfile.Outflag = SCRATCH; + else + { + pr->outfile.Outflag = SCRATCH; + strcpy(pr->outfile.OutFname, pr->TmpOutFname); + } // Check that file names are not identical if (strlen(f1) > 0 && (strcomp(f1, f2) || strcomp(f1, f3))) return 301; @@ -181,6 +185,7 @@ int openoutfile(Project *pr) // If output file name was supplied, then attempt to // open it. Otherwise open a temporary output file. +/* if (pr->outfile.Outflag == SAVE) { pr->outfile.OutFile = fopen(pr->outfile.OutFname, "w+b"); @@ -192,6 +197,9 @@ int openoutfile(Project *pr) pr->outfile.OutFile = fopen(pr->outfile.OutFname, "w+b"); if (pr->outfile.OutFile == NULL) errcode = 304; } +*/ + pr->outfile.OutFile = fopen(pr->outfile.OutFname, "w+b"); + if (pr->outfile.OutFile == NULL) errcode = 304; // Save basic network data & energy usage results ERRCODE(savenetdata(pr)); diff --git a/src/report.c b/src/report.c index 4d0c4df..5605ffb 100644 --- a/src/report.c +++ b/src/report.c @@ -545,7 +545,7 @@ int writeresults(Project *pr) if (nnv == 0 && nlv == 0) return errcode; // Return if no output file -// if (outFile == NULL) outFile = fopen(pr->outfile.OutFname, "r+b"); + if (outFile == NULL) outFile = fopen(pr->outfile.OutFname, "rb"); if (outFile == NULL) return 106; // Allocate memory for output variables: @@ -587,14 +587,14 @@ int writeresults(Project *pr) time->Htime += time->Rstep; } } -/* + // Free output file if (outFile != NULL) { fclose(outFile); outFile = NULL; } -*/ + // Free allocated memory for (j = 0; j < m; j++) free(x[j]); free(x); From 09d6c7ea5d96725b201057414fcc300f0907a6a3 Mon Sep 17 00:00:00 2001 From: Lew Rossman Date: Tue, 5 Mar 2019 19:07:55 -0500 Subject: [PATCH 4/9] Reverting some previous changes --- src/epanet.c | 4 ++-- src/report.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/epanet.c b/src/epanet.c index 57952ec..383bd6f 100644 --- a/src/epanet.c +++ b/src/epanet.c @@ -819,13 +819,13 @@ int DLLEXPORT EN_closeQ(EN_Project p) if (!p->Openflag) return 102; closequal(p); p->quality.OpenQflag = FALSE; - +/* if (p->outfile.OutFile != NULL) { fclose(p->outfile.OutFile); p->outfile.OutFile = NULL; } - +*/ return 0; } diff --git a/src/report.c b/src/report.c index 5605ffb..790aac8 100644 --- a/src/report.c +++ b/src/report.c @@ -545,7 +545,7 @@ int writeresults(Project *pr) if (nnv == 0 && nlv == 0) return errcode; // Return if no output file - if (outFile == NULL) outFile = fopen(pr->outfile.OutFname, "rb"); +// if (outFile == NULL) outFile = fopen(pr->outfile.OutFname, "rb"); if (outFile == NULL) return 106; // Allocate memory for output variables: @@ -587,14 +587,14 @@ int writeresults(Project *pr) time->Htime += time->Rstep; } } - +/* // Free output file if (outFile != NULL) { fclose(outFile); outFile = NULL; } - +*/ // Free allocated memory for (j = 0; j < m; j++) free(x[j]); free(x); From 324487ba86725e0e6443b8928b6f6ed44830f00b Mon Sep 17 00:00:00 2001 From: Lew Rossman Date: Tue, 5 Mar 2019 19:40:30 -0500 Subject: [PATCH 5/9] Opening & closing output file in writeresults --- src/project.c | 13 ------------- src/report.c | 6 +++--- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/src/project.c b/src/project.c index 0a40489..b66117c 100644 --- a/src/project.c +++ b/src/project.c @@ -185,19 +185,6 @@ int openoutfile(Project *pr) // If output file name was supplied, then attempt to // open it. Otherwise open a temporary output file. -/* - if (pr->outfile.Outflag == SAVE) - { - pr->outfile.OutFile = fopen(pr->outfile.OutFname, "w+b"); - if (pr->outfile.OutFile == NULL) errcode = 304; - } - else - { - strcpy(pr->outfile.OutFname, pr->TmpOutFname); - pr->outfile.OutFile = fopen(pr->outfile.OutFname, "w+b"); - if (pr->outfile.OutFile == NULL) errcode = 304; - } -*/ pr->outfile.OutFile = fopen(pr->outfile.OutFname, "w+b"); if (pr->outfile.OutFile == NULL) errcode = 304; diff --git a/src/report.c b/src/report.c index 790aac8..5605ffb 100644 --- a/src/report.c +++ b/src/report.c @@ -545,7 +545,7 @@ int writeresults(Project *pr) if (nnv == 0 && nlv == 0) return errcode; // Return if no output file -// if (outFile == NULL) outFile = fopen(pr->outfile.OutFname, "rb"); + if (outFile == NULL) outFile = fopen(pr->outfile.OutFname, "rb"); if (outFile == NULL) return 106; // Allocate memory for output variables: @@ -587,14 +587,14 @@ int writeresults(Project *pr) time->Htime += time->Rstep; } } -/* + // Free output file if (outFile != NULL) { fclose(outFile); outFile = NULL; } -*/ + // Free allocated memory for (j = 0; j < m; j++) free(x[j]); free(x); From 8765dfa3ab0933e962164226dd6351b37c49fc20 Mon Sep 17 00:00:00 2001 From: Lew Rossman Date: Tue, 5 Mar 2019 20:50:34 -0500 Subject: [PATCH 6/9] Initialize all file pointers to NULL in initpointers --- src/epanet.c | 4 ++-- src/project.c | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/epanet.c b/src/epanet.c index 383bd6f..57952ec 100644 --- a/src/epanet.c +++ b/src/epanet.c @@ -819,13 +819,13 @@ int DLLEXPORT EN_closeQ(EN_Project p) if (!p->Openflag) return 102; closequal(p); p->quality.OpenQflag = FALSE; -/* + if (p->outfile.OutFile != NULL) { fclose(p->outfile.OutFile); p->outfile.OutFile = NULL; } -*/ + return 0; } diff --git a/src/project.c b/src/project.c index b66117c..4de0736 100644 --- a/src/project.c +++ b/src/project.c @@ -265,6 +265,12 @@ void initpointers(Project *pr) pr->hydraul.smatrix.XLNZ = NULL; pr->hydraul.smatrix.NZSUB = NULL; pr->hydraul.smatrix.LNZ = NULL; + + pr->outfile.OutFile = NULL; + pr->outfile.HydFile = NULL; + pr->outfile.TmpOutFile = NULL; + pr->parser.InFile = NULL; + pr->report.RptFile = NULL; initrules(pr); } From 3ebb1831d77fd4b5f115001ed4c4a860e7bd847b Mon Sep 17 00:00:00 2001 From: Lew Rossman Date: Wed, 6 Mar 2019 10:44:03 -0500 Subject: [PATCH 7/9] Another attempt to fix closing/opening of output project --- src/epanet.c | 1 + src/project.c | 18 +++++++----------- src/quality.c | 18 ++++++++++++------ 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/epanet.c b/src/epanet.c index 57952ec..d8ba333 100644 --- a/src/epanet.c +++ b/src/epanet.c @@ -1572,6 +1572,7 @@ int DLLEXPORT EN_setqualtype(EN_Project p, int qualType, char *chemName, double ccf = 1.0; if (!p->Openflag) return 102; + if (qual->OpenQflag) return 262; if (qualType < EN_NONE || qualType > EN_TRACE) return 251; qual->Qualflag = (char)qualType; qual->Ctol *= Ucf[QUALITY]; diff --git a/src/project.c b/src/project.c index 4de0736..4d1621f 100644 --- a/src/project.c +++ b/src/project.c @@ -43,6 +43,7 @@ int openfiles(Project *pr, const char *f1, const char *f2, const char *f3) pr->report.RptFile = NULL; pr->outfile.OutFile = NULL; pr->outfile.HydFile = NULL; + pr->outfile.TmpOutFile = NULL; // Save file names strncpy(pr->parser.InpFname, f1, MAXFNAME); @@ -172,16 +173,17 @@ int openoutfile(Project *pr) int errcode = 0; // Close output file if already opened + if (pr->outfile.TmpOutFile != pr->outfile.OutFile && + pr->outfile.TmpOutFile != NULL) + { + fclose(pr->outfile.TmpOutFile); + pr->outfile.TmpOutFile = NULL; + } if (pr->outfile.OutFile != NULL) { fclose(pr->outfile.OutFile); pr->outfile.OutFile = NULL; } - if (pr->outfile.TmpOutFile != NULL) - { - fclose(pr->outfile.TmpOutFile); - pr->outfile.TmpOutFile = NULL; - } // If output file name was supplied, then attempt to // open it. Otherwise open a temporary output file. @@ -266,12 +268,6 @@ void initpointers(Project *pr) pr->hydraul.smatrix.NZSUB = NULL; pr->hydraul.smatrix.LNZ = NULL; - pr->outfile.OutFile = NULL; - pr->outfile.HydFile = NULL; - pr->outfile.TmpOutFile = NULL; - pr->parser.InFile = NULL; - pr->report.RptFile = NULL; - initrules(pr); } diff --git a/src/quality.c b/src/quality.c index f9ede48..e46fe42 100644 --- a/src/quality.c +++ b/src/quality.c @@ -67,6 +67,9 @@ int openqual(Project *pr) int errcode = 0; int n; + + // Return if no quality analysis requested + if (qual->Qualflag == NONE) return errcode; // Build nodal adjacency lists if they don't already exist if (net->Adjlist == NULL) @@ -401,12 +404,15 @@ int closequal(Project *pr) Quality *qual = &pr->quality; int errcode = 0; - if (qual->SegPool) mempool_delete(qual->SegPool); - FREE(qual->FirstSeg); - FREE(qual->LastSeg); - FREE(qual->PipeRateCoeff); - FREE(qual->FlowDir); - FREE(qual->SortedNodes); + if (qual->Qualflag != NONE) + { + if (qual->SegPool) mempool_delete(qual->SegPool); + FREE(qual->FirstSeg); + FREE(qual->LastSeg); + FREE(qual->PipeRateCoeff); + FREE(qual->FlowDir); + FREE(qual->SortedNodes); + } return errcode; } From 6e13d7e3aa8ec200dbe5a0745fc5a8afcd1a65d7 Mon Sep 17 00:00:00 2001 From: Lew Rossman Date: Wed, 6 Mar 2019 11:14:03 -0500 Subject: [PATCH 8/9] Refactoring how the binary output is closed This change implements the fix suggested by @gonccalo. --- src/epanet.c | 8 +------- src/funcs.h | 1 + src/project.c | 41 +++++++++++++++++++++++++++++------------ 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/src/epanet.c b/src/epanet.c index d8ba333..e39c752 100644 --- a/src/epanet.c +++ b/src/epanet.c @@ -819,13 +819,7 @@ int DLLEXPORT EN_closeQ(EN_Project p) if (!p->Openflag) return 102; closequal(p); p->quality.OpenQflag = FALSE; - - if (p->outfile.OutFile != NULL) - { - fclose(p->outfile.OutFile); - p->outfile.OutFile = NULL; - } - + closeoutfile(p); return 0; } diff --git a/src/funcs.h b/src/funcs.h index dde13c4..154dcfc 100755 --- a/src/funcs.h +++ b/src/funcs.h @@ -24,6 +24,7 @@ void freedata(Project *); int openfiles(Project *, const char *, const char *,const char *); int openhydfile(Project *); int openoutfile(Project *); +void closeoutfile(Project *); int buildadjlists(Network *); void freeadjlists(Network *); diff --git a/src/project.c b/src/project.c index 4d1621f..aceffa8 100644 --- a/src/project.c +++ b/src/project.c @@ -173,18 +173,8 @@ int openoutfile(Project *pr) int errcode = 0; // Close output file if already opened - if (pr->outfile.TmpOutFile != pr->outfile.OutFile && - pr->outfile.TmpOutFile != NULL) - { - fclose(pr->outfile.TmpOutFile); - pr->outfile.TmpOutFile = NULL; - } - if (pr->outfile.OutFile != NULL) - { - fclose(pr->outfile.OutFile); - pr->outfile.OutFile = NULL; - } - + closeoutfile(pr); + // If output file name was supplied, then attempt to // open it. Otherwise open a temporary output file. pr->outfile.OutFile = fopen(pr->outfile.OutFname, "w+b"); @@ -209,6 +199,33 @@ int openoutfile(Project *pr) return errcode; } +void closeoutfile(Project *pr) +/*---------------------------------------------------------------- +** Input: none +** Output: none +** Purpose: closes binary output file. +**---------------------------------------------------------------- +*/ +{ + if (pr->outfile.TmpOutFile != pr->outfile.OutFile) + { + if (pr->outfile.TmpOutFile != NULL) + { + fclose(pr->outfile.TmpOutFile); + pr->outfile.TmpOutFile = NULL; + } + } + if (pr->outfile.OutFile != NULL) + { + if (pr->outfile.OutFile == pr->outfile.TmpOutFile) + { + pr->outfile.TmpOutFile = NULL; + } + fclose(pr->outfile.OutFile); + pr->outfile.OutFile = NULL; + } +} + void initpointers(Project *pr) /*---------------------------------------------------------------- ** Input: none From 12c64b69cdc2254202c683babcca06d9851a1d53 Mon Sep 17 00:00:00 2001 From: Lew Rossman Date: Wed, 6 Mar 2019 13:23:55 -0500 Subject: [PATCH 9/9] Refactored EN_close function to use newly added closeoutfile function --- src/epanet.c | 20 ++++---------------- src/quality.c | 9 +-------- 2 files changed, 5 insertions(+), 24 deletions(-) diff --git a/src/epanet.c b/src/epanet.c index e39c752..71c2b26 100644 --- a/src/epanet.c +++ b/src/epanet.c @@ -332,24 +332,12 @@ int DLLEXPORT EN_close(EN_Project p) **---------------------------------------------------------------- */ { - Outfile *out; - // Free all project data if (p->Openflag) writetime(p, FMT105); freedata(p); // Close output file - out = &p->outfile; - if (out->TmpOutFile != out->OutFile) - { - if (out->TmpOutFile != NULL) fclose(out->TmpOutFile); - out->TmpOutFile = NULL; - } - if (out->OutFile != NULL) - { - fclose(out->OutFile); - out->OutFile = NULL; - } + closeoutfile(p); // Close input file if (p->parser.InFile != NULL) @@ -366,10 +354,10 @@ int DLLEXPORT EN_close(EN_Project p) } // Close hydraulics file - if (out->HydFile != NULL) + if (p->outfile.HydFile != NULL) { - fclose(out->HydFile); - out->HydFile = NULL; + fclose(p->outfile.HydFile); + p->outfile.HydFile = NULL; } // Reset system flags diff --git a/src/quality.c b/src/quality.c index e46fe42..de27f63 100644 --- a/src/quality.c +++ b/src/quality.c @@ -27,14 +27,7 @@ Last Updated: 11/27/2018 // Stagnant flow tolerance const double Q_STAGNANT = 0.005 / GPMperCFS; // 0.005 gpm = 1.114e-5 cfs -// Exported functions (declared in FUNCS.H) -//int openqual(Project *); -//void initqual(Project *); -//int runqual(Project *, long *); -//int nextqual(Project *, long *); -//int stepqual(Project *, long *); -//int closequal(Project *); -//double avgqual(Project *, int); +// Exported functions double findsourcequal(Project *, int, double, long); // Imported functions