[tools/peerindex] Improve resource management and error reporting

This commit is contained in:
Lorenzo Cogotti 2021-08-01 15:10:31 +02:00
parent 5b090d605e
commit 5e43edd273
2 changed files with 82 additions and 68 deletions

View File

@ -133,6 +133,15 @@ void Peerindex_DropFile(const char *fmt, ...)
Bgp_ClearMrt(&S.peerIndex); Bgp_ClearMrt(&S.peerIndex);
S.hasPeerIndex = FALSE; S.hasPeerIndex = FALSE;
// Drop any opened file and jump out
if (S.infOps) {
if (S.infOps->Close) S.infOps->Close(S.inf);
S.inf = NULL;
S.infOps = NULL;
}
S.filename = NULL;
longjmp(S.dropFileFrame, 1); longjmp(S.dropFileFrame, 1);
} }
@ -179,36 +188,40 @@ static void Peerindex_Init(void)
S.rec.memOps = Mem_BgpBufOps; S.rec.memOps = Mem_BgpBufOps;
} }
static const StmOps *Peerindex_OpenMrtDump(const char *filename, void **phn) static void Peerindex_OpenMrtDump(const char *filename)
{ {
S.filename = filename;
if (strcmp(S.filename, "-") == 0) {
// Direct read from stdin, assume uncompressed
S.inf = STM_FILDES(CON_FILDES(STDIN));
S.infOps = Stm_NcFildesOps;
return;
}
Fildes fh = Sys_Fopen(filename, FM_READ, FH_SEQ); Fildes fh = Sys_Fopen(filename, FM_READ, FH_SEQ);
if (fh == FILDES_BAD) if (fh == FILDES_BAD)
Peerindex_DropFile("Can't open file"); Peerindex_DropFile("Can't open file");
const char *ext = Sys_GetFileExtension(filename); const char *ext = Sys_GetFileExtension(filename);
void *hn;
const StmOps *ops;
if (Df_stricmp(ext, ".bz2") == 0) { if (Df_stricmp(ext, ".bz2") == 0) {
hn = Bzip2_OpenDecompress(STM_FILDES(fh), Stm_FildesOps, /*opts=*/NULL); S.inf = Bzip2_OpenDecompress(STM_FILDES(fh), Stm_FildesOps, /*opts=*/NULL);
ops = Bzip2_StmOps; S.infOps = Bzip2_StmOps;
Bzip2Ret err = Bzip2_GetErrStat(); Bzip2Ret err = Bzip2_GetErrStat();
if (err) if (err)
Peerindex_DropFile("Can't read Bz2 archive: %s", Bzip2_ErrorString(err)); Peerindex_DropFile("Can't read Bz2 archive: %s", Bzip2_ErrorString(err));
} else if (Df_stricmp(ext, ".gz") == 0 || Df_stricmp(ext, ".z") == 0) { } else if (Df_stricmp(ext, ".gz") == 0 || Df_stricmp(ext, ".z") == 0) {
hn = Zlib_InflateOpen(STM_FILDES(fh), Stm_FildesOps, /*opts=*/NULL); S.inf = Zlib_InflateOpen(STM_FILDES(fh), Stm_FildesOps, /*opts=*/NULL);
ops = Zlib_StmOps; S.infOps = Zlib_StmOps;
ZlibRet err = Zlib_GetErrStat(); ZlibRet err = Zlib_GetErrStat();
if (err) if (err)
Peerindex_DropFile("Can't read Zlib archive: %s", Zlib_ErrorString(err)); Peerindex_DropFile("Can't read Zlib archive: %s", Zlib_ErrorString(err));
} else if (Df_stricmp(ext, ".xz") == 0) { } else if (Df_stricmp(ext, ".xz") == 0) {
hn = Xz_OpenDecompress(STM_FILDES(fh), Stm_FildesOps, /*opts=*/NULL); S.inf = Xz_OpenDecompress(STM_FILDES(fh), Stm_FildesOps, /*opts=*/NULL);
ops = Xz_StmOps; S.infOps = Xz_StmOps;
XzRet err = Xz_GetErrStat(); XzRet err = Xz_GetErrStat();
if (err) if (err)
@ -216,12 +229,9 @@ static const StmOps *Peerindex_OpenMrtDump(const char *filename, void **phn)
} else { } else {
// Assume uncompressed file // Assume uncompressed file
hn = STM_FILDES(fh); S.inf = STM_FILDES(fh);
ops = Stm_FildesOps; S.infOps = Stm_FildesOps;
} }
*phn = hn;
return ops;
} }
static void Peerindex_MarkPeerRefs(void) static void Peerindex_MarkPeerRefs(void)
@ -242,7 +252,7 @@ static void Peerindex_MarkPeerRefs(void)
} }
} }
static void Peerindex_DumpPeerIndexTable(void) static void Peerindex_FlushPeerIndexTable(void)
{ {
char buf[IPV6_STRLEN + 1]; char buf[IPV6_STRLEN + 1];
Stmbuf sb; Stmbuf sb;
@ -278,28 +288,15 @@ static void Peerindex_DumpPeerIndexTable(void)
Bufio_Flush(&sb); Bufio_Flush(&sb);
} }
static void Peerindex_ProcessMrtDump(const char *filename) static void Peerindex_ProcessRecord(void)
{ {
void *hn;
const StmOps *ops;
S.filename = filename; // NOTE: Only function that manipulates this
if (strcmp(filename, "-") == 0) {
hn = STM_FILDES(CON_FILDES(STDIN));
ops = Stm_NcFildesOps;
} else
ops = Peerindex_OpenMrtDump(filename, &hn);
setjmp(S.dropRecordFrame); // NOTE: The ONLY place where this is set
while (Bgp_ReadMrt(&S.rec, hn, ops) == OK) {
const Mrthdr *hdr = MRT_HDR(&S.rec); const Mrthdr *hdr = MRT_HDR(&S.rec);
if (hdr->type != MRT_TABLE_DUMPV2) if (hdr->type != MRT_TABLE_DUMPV2)
continue; // don't care for anything else return; // don't care for anything else
if (hdr->subtype == TABLE_DUMPV2_PEER_INDEX_TABLE) { if (hdr->subtype == TABLE_DUMPV2_PEER_INDEX_TABLE) {
// Dump peers seen so far, if any // Dump peers seen so far, if any
Peerindex_DumpPeerIndexTable(); Peerindex_FlushPeerIndexTable();
// Clear previous PEER_INDEX_TABLE, if any // Clear previous PEER_INDEX_TABLE, if any
Bgp_ClearMrt(&S.peerIndex); Bgp_ClearMrt(&S.peerIndex);
// Clear reference table... // Clear reference table...
@ -312,24 +309,43 @@ static void Peerindex_ProcessMrtDump(const char *filename)
Bgp_GetMrtPeerIndexPeers(&S.peerIndex, &npeers, /*nbytes=*/NULL); Bgp_GetMrtPeerIndexPeers(&S.peerIndex, &npeers, /*nbytes=*/NULL);
S.npeers = npeers; S.npeers = npeers;
S.hasPeerIndex = TRUE; S.hasPeerIndex = TRUE;
continue; return;
} }
if (!TABLE_DUMPV2_ISRIB(hdr->subtype))
continue; // don't care for anything but RIBs
if (!S.hasPeerIndex) { if (!TABLE_DUMPV2_ISRIB(hdr->subtype))
Peerindex_Warning("SKIPPING"); return; // irrelevant to us
continue;
} if (!S.hasPeerIndex)
Peerindex_DropRecord("SKIPPING TABLE_DUMPV2 RECORD - No PEER_INDEX_TABLE found yet");
Peerindex_MarkPeerRefs(); Peerindex_MarkPeerRefs();
}
static void Peerindex_ProcessMrtDump(const char *filename)
{
// NOTE: This call is responsible to set and clear:
// S.filename, S.inf, S.infOps.
// These must be cleared either here or within a file drop.
Peerindex_OpenMrtDump(filename);
setjmp(S.dropRecordFrame); // NOTE: The ONLY place where this is set
while (Bgp_ReadMrt(&S.rec, S.inf, S.infOps) == OK) {
Peerindex_ProcessRecord();
Bgp_ClearMrt(&S.rec);
} }
Peerindex_DumpPeerIndexTable(); // execute the very last dump Peerindex_FlushPeerIndexTable(); // execute the very last dump
if (ops->Close) // Don't need PEER_INDEX_TABLE anymore
ops->Close(hn); Bgp_ClearMrt(&S.peerIndex);
S.hasPeerIndex = FALSE;
// Finally close file and call it a day
if (S.infOps->Close) S.infOps->Close(S.inf);
S.inf = NULL;
S.infOps = NULL;
S.filename = NULL; S.filename = NULL;
} }
@ -370,13 +386,8 @@ int main(int argc, char **argv)
volatile int i = 0; volatile int i = 0;
setjmp(S.dropFileFrame); // NOTE: The ONLY place where this is set setjmp(S.dropFileFrame); // NOTE: The ONLY place where this is set
while (i < argc) { while (i < argc)
Peerindex_ProcessMrtDump(argv[i++]); Peerindex_ProcessMrtDump(argv[i++]);
// Don't need PEER_INDEX_TABLE anymore
Bgp_ClearMrt(&S.peerIndex);
S.hasPeerIndex = FALSE;
}
return (S.nerrors > 0) ? EXIT_FAILURE : EXIT_SUCCESS; return (S.nerrors > 0) ? EXIT_FAILURE : EXIT_SUCCESS;
} }

View File

@ -31,7 +31,10 @@ FORCE_INLINE Boolean ISPEERINDEXREF(const PeerRefsTab tab, Uint16 idx)
} }
typedef struct { typedef struct {
const char *filename; // current file being processed // MRT input file stream
const char *filename;
void *inf;
const StmOps *infOps;
// Miscellaneous global flags and data // Miscellaneous global flags and data
Boolean8 hasPeerIndex; Boolean8 hasPeerIndex;