From 9a4d09f87882039b63baf8b3f049154a3847ec7e Mon Sep 17 00:00:00 2001 From: jonzarling Date: Tue, 15 Apr 2025 17:30:00 -0500 Subject: [PATCH 01/56] New test branch --- LICENSE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.txt b/LICENSE.txt index 532710ce4..2b502ba70 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (c) 2020, Jefferson Science Associates, LLC. All Rights Reserved. Redistribution +Copyright (c) 2025, Jefferson Science Associates, LLC. All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted as a licensed user provided that the following conditions are met: From 01f793b9a19222c49f23545e510c740ed04e1701 Mon Sep 17 00:00:00 2001 From: jonzarling Date: Wed, 16 Apr 2025 15:56:01 -0500 Subject: [PATCH 02/56] Attempting to resurrect the maven build --- pom.xml | 304 +++++++++++++++++--------------------------------------- 1 file changed, 92 insertions(+), 212 deletions(-) diff --git a/pom.xml b/pom.xml index e8aa0494a..8e5ac1414 100644 --- a/pom.xml +++ b/pom.xml @@ -1,215 +1,95 @@ - + + 4.0.0 + org.jlab.coda + jevio + 6.0-SNAPSHOT + Jefferson Lab EVIO Java Library (JEVIO) + Java library for EVIO (Event Input/Output) + jar + + + + UTF-8 + 1.8 + 1.8 + 1.8.0 + 3.4.3 + 1.0 + ${project.basedir}/java/jars + + + + + + org.lz4 + lz4-java + ${lz4.version} + + + + com.lmax + disruptor + ${disruptor.version} + + + + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + ${maven.compiler.source} + ${maven.compiler.target} + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.3.0 + + + make-assembly + package + single + + + + org.jlab.coda.hipo.Evio6Converter + + + + jar-with-dependencies + + false + + + + + + + + + - - - 4.0.0 - - - jevio - - - Java EVIO Library - - - Java EVIO Library (JEVIO) - - - org.jlab.coda - - - 6.0-SNAPSHOT - - - - - 1.8 - 1.8 - - - - 1.8.0 - 3.4.3 - 1.0 - - - - - jar - - - - net.jpountz.lz4 - lz4-java - ${lz4.version} - - - com.lmax - disruptor - ${disruptor.version} - - - com.aha.compression - AHACompressionAPI - ${aha.version} - - - org.junit.jupiter - junit-jupiter - RELEASE - test - - - org.junit.jupiter - junit-jupiter - RELEASE - test - - - - - - - ./java/ - - - - - - - org.apache.maven.wagon - wagon-ssh-external - 2.8 - - - - - - - - - org.apache.maven.plugins - maven-install-plugin - 2.5.2 - - - aha - clean - install-file - - java/jars/AHACompressionAPI.jar - com.aha.compression - AHACompressionAPI - ${aha.version} - jar - - - - disruptor - clean - install-file - - java/jars/disruptor-${disruptor.version}.jar - com.lmax - disruptor - ${disruptor.version} - jar - - - - lz4 - clean - install-file - - java/jars/lz4-java-${lz4.version}.jar - net.jpountz.lz4 - lz4-java - ${lz4.version} - jar - - - - - - - maven-assembly-plugin - 2.6 - - - - org.jlab.coda.hipo.Evio6Converter - - - - jar-with-dependencies - - - - - make-assembly - package - - single - - - - - - - org.apache.maven.plugins - maven-dependency-plugin - 2.10 - - - copy-installed - install - - copy - - - - - ${project.groupId} - ${project.artifactId} - ${project.version} - ${project.packaging} - - - - - - - - - - - - - - - - ssh-clasweb - scpexe://clas12@jlabl5/group/clas/www/clasweb/html/clas12maven - - From 5ca866311b7d65d0ff43594a5d99e14ea283809b Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Thu, 17 Apr 2025 12:17:38 -0500 Subject: [PATCH 03/56] Trying out new pom.xml. Seems to work (on my machine...) --- pom.xml | 131 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 75 insertions(+), 56 deletions(-) diff --git a/pom.xml b/pom.xml index 8e5ac1414..020366eac 100644 --- a/pom.xml +++ b/pom.xml @@ -12,12 +12,16 @@ + + + + 15 + ${java.version} + ${java.version} + UTF-8 - 1.8 - 1.8 1.8.0 - 3.4.3 - 1.0 + 4.0.0 ${project.basedir}/java/jars @@ -33,63 +37,78 @@ com.lmax disruptor ${disruptor.version} - - - - - - + ${project.basedir}/java/jars/java15/disruptor-${disruptor.version}.jar + - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - ${maven.compiler.source} - ${maven.compiler.target} - - + + ${project.basedir}/java + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.6.0 + + + add-jevio-tests + generate-test-sources + + add-test-source + + + + java/org/jlab/coda/jevio/test + + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M7 + + + + **/**.java + + + true + + + + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + + run-FileWriteTest + test + + java + + + test + org.jlab.coda.jevio.test.FileWriteTest + + + + + - - - org.apache.maven.plugins - maven-assembly-plugin - 3.3.0 - - - make-assembly - package - single - - - - org.jlab.coda.hipo.Evio6Converter - - - - jar-with-dependencies - - false - - - - - - - - - + + + From 01c332ca535167050dcae26abb99fcfc9ddd0d43 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Thu, 17 Apr 2025 15:16:20 -0500 Subject: [PATCH 04/56] Change jar dir, fix maven warning --- pom.xml | 52 +++++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/pom.xml b/pom.xml index 020366eac..27a99c0fb 100644 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,7 @@ UTF-8 1.8.0 4.0.0 - ${project.basedir}/java/jars + ${pom.basedir}/java/jars @@ -38,7 +38,7 @@ disruptor ${disruptor.version} system - ${project.basedir}/java/jars/java15/disruptor-${disruptor.version}.jar + ${pom.basedir}/java/jars/java15/disruptor-${disruptor.version}.jar @@ -67,6 +67,31 @@ + + maven-assembly-plugin + 2.6 + + + + org.jlab.coda.hipo.Evio6Converter + org.jlab.coda.jevio.test.RecordSupplyTest + + + + jar-with-dependencies + + + + + make-assembly + package + + single + + + + + org.apache.maven.plugins @@ -82,29 +107,6 @@ - - - org.codehaus.mojo - exec-maven-plugin - 3.1.0 - - - run-FileWriteTest - test - - java - - - test - org.jlab.coda.jevio.test.FileWriteTest - - - - - From 8821c67df3c35eb916ab1713d69d4a9e58ca9d1a Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Mon, 21 Apr 2025 13:17:19 -0500 Subject: [PATCH 05/56] Build tweaks, add test programs --- CMakeLists.txt | 5 + pom.xml | 69 ++++++----- src/test/ReadWriteTest.cpp | 4 +- tutorials/EVIO_v4_to_v6.cpp | 59 +++++++++ tutorials/PrintXMLDict.cpp | 40 +++++++ tutorials/WriteFilePseudoPhysicsEvent.cpp | 112 ++++++++++++++++++ .../WriteFilePseudoPhysicsEventExtended.cpp | 92 ++++++++++++++ 7 files changed, 352 insertions(+), 29 deletions(-) create mode 100644 tutorials/EVIO_v4_to_v6.cpp create mode 100644 tutorials/PrintXMLDict.cpp create mode 100644 tutorials/WriteFilePseudoPhysicsEvent.cpp create mode 100644 tutorials/WriteFilePseudoPhysicsEventExtended.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ecc01d68e..b1879bb20 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -222,6 +222,10 @@ set(TEST src/test/ReadSequenceTest.cpp src/test/SequentialReaderTest.cpp src/test/SplitTest2.cpp + tutorials/WriteFilePseudoPhysicsEvent.cpp + tutorials/WriteFilePseudoPhysicsEventExtended.cpp + tutorials/PrintXMLDict.cpp + tutorials/EVIO_v4_to_v6.cpp ) set(TESTC @@ -240,6 +244,7 @@ set(TESTC src/testC/evWritePipe.c src/testC/splitTest.c src/testC/splitNameTest.c + src/libsrc/eviocopy.c ) include(FindPackageHandleStandardArgs) diff --git a/pom.xml b/pom.xml index 27a99c0fb..2a236246f 100644 --- a/pom.xml +++ b/pom.xml @@ -28,17 +28,18 @@ - org.lz4 + org.lz4 lz4-java ${lz4.version} - com.lmax + com.lmax disruptor ${disruptor.version} system - ${pom.basedir}/java/jars/java15/disruptor-${disruptor.version}.jar + /home/jzarling/super_evio_dev/disruptor/disruptor/disruptor-4.0.0.jar + @@ -46,7 +47,8 @@ ${project.basedir}/java - + + org.codehaus.mojo build-helper-maven-plugin @@ -67,29 +69,43 @@ + - maven-assembly-plugin - 2.6 - - - - org.jlab.coda.hipo.Evio6Converter - org.jlab.coda.jevio.test.RecordSupplyTest - - - - jar-with-dependencies - - - - - make-assembly - package - - single - - - + maven-assembly-plugin + 3.6.0 + + + + + jar-with-dependencies + + + jar-with-dependencies + jar + false + + + runtime + true + + + system + true + false + / + + + + + + + make-assembly + package + + single + + + @@ -108,7 +124,6 @@ - diff --git a/src/test/ReadWriteTest.cpp b/src/test/ReadWriteTest.cpp index 767d0868b..a96017eaf 100644 --- a/src/test/ReadWriteTest.cpp +++ b/src/test/ReadWriteTest.cpp @@ -194,7 +194,7 @@ namespace evio { // Do a parsing listener test here auto parser = reader3.getParser(); - // Define a listener to be used with an event parser
IEvioListener listener = new IEvioListener() {
 + // Define a listener to be used with an event parserIEvioListener listener = new IEvioListener() { class myListener : public IEvioListener { public: void gotStructure(std::shared_ptr topStructure, @@ -213,7 +213,7 @@ namespace evio { auto listener = std::make_shared(); - // Define a listener to be used with an event parser
IEvioListener listener = new IEvioListener() {
 + // Define a listener to be used with an event parserIEvioListener listener = new IEvioListener() { class myListener2 : public IEvioListener { public: void gotStructure(std::shared_ptr topStructure, diff --git a/tutorials/EVIO_v4_to_v6.cpp b/tutorials/EVIO_v4_to_v6.cpp new file mode 100644 index 000000000..c8103f291 --- /dev/null +++ b/tutorials/EVIO_v4_to_v6.cpp @@ -0,0 +1,59 @@ +#include +#include + +// Include EVIO6 C++ headers (adjust the include paths as needed for your installation) +#include "eviocc.h" // EVIO C++ API (EVIO 6 main branch) + +// Use the EVIO namespace for convenience +using namespace evio; + +int main(int argc, char* argv[]) { + if (argc < 2) { + std::cerr << "Usage: " << argv[0] << " " << std::endl; + return 1; + } + std::string f_in = argv[1]; + std::string f_out = argv[2]; + + // Read / write parameters + uint32_t maxRecordBytes = 1000000; + uint32_t maxEventsPerRecord = 1000; + uint32_t bufferBytes = 1000000; + + + try { + // Open the EVIO6 file using EvioReader + EvioReader reader(f_in); + // EvioCompactReader reader(f_in); + + EventWriter writerV6(f_out, "", "", 1, 0, + maxRecordBytes, maxEventsPerRecord, + ByteOrder::ENDIAN_LOCAL, "", true, false, + nullptr, 1, 0, 1, 1, + Compressor::CompressionType::UNCOMPRESSED, + 0, 0, bufferBytes); + + for(int32_t i = 0; i < reader.getEventCount(); ++i) { + + // **Create a top-level event (bank of banks)** with tag=1, num=1 + EventBuilder builder(1, DataType::BANK, 1); + std::shared_ptr event = builder.getEvent(); + + auto ev = reader.parseEvent(i + 1); + auto & dataVec = ev->getRawBytes(); + Util::printBytes(dataVec.data(), dataVec.size()," Event #" + std::to_string(i)); + + } + + } + + + + + catch (const std::exception& e) { + std::cerr << "Error: could not open and convert " << e.what() << std::endl; + return 1; + } + + return 0; +} diff --git a/tutorials/PrintXMLDict.cpp b/tutorials/PrintXMLDict.cpp new file mode 100644 index 000000000..61fe44f63 --- /dev/null +++ b/tutorials/PrintXMLDict.cpp @@ -0,0 +1,40 @@ +#include +#include + +// Include EVIO6 C++ headers (adjust the include paths as needed for your installation) +#include "eviocc.h" // EVIO C++ API (EVIO 6 main branch) + +// Use the EVIO namespace for convenience +using namespace evio; + +int main(int argc, char* argv[]) { + if (argc < 2) { + std::cerr << "Usage: " << argv[0] << " " << std::endl; + return 1; + } + std::string filename = argv[1]; + + try { + // Open the EVIO6 file using EvioReader + EvioReader reader(filename); + + // Check for an embedded XML dictionary + if (reader.hasDictionaryXML()) { + // Retrieve the raw XML dictionary text + std::string xmlDict = reader.getDictionaryXML(); + // Print the XML dictionary to standard output + std::cout << xmlDict; + if (!xmlDict.empty() && xmlDict.back() != '\n') { + std::cout << std::endl; // ensure a newline at end, if not already present + } + } else { + // No dictionary present in the file + std::cout << "No XML dictionary found." << std::endl; + } + } catch (const std::exception& e) { + std::cerr << "Error: Unable to read EVIO file. " << e.what() << std::endl; + return 1; + } + + return 0; +} diff --git a/tutorials/WriteFilePseudoPhysicsEvent.cpp b/tutorials/WriteFilePseudoPhysicsEvent.cpp new file mode 100644 index 000000000..4f3f47664 --- /dev/null +++ b/tutorials/WriteFilePseudoPhysicsEvent.cpp @@ -0,0 +1,112 @@ +#include +#include +#include + +#include "eviocc.h" // EVIO C++ API (EVIO 6 main branch) + +using namespace evio; + +int main(int argc, char** argv) { + if (argc < 2) { + std::cerr << "Usage: " << argv[0] << " \n"; + return 1; + } + int nEvents = std::stoi(argv[1]); + + // XML dictionary defining labels for the event structure + std::string xmlDictionary = R"( + + + + + + + + + + + + )"; + + + // Output file names for each format + std::string fileNameEvio4 = "events_v4.ev"; // EVIO version 4 file + std::string fileNameEvio6 = "events_v6.ev"; // EVIO version 6 file + std::string fileNameHipo = "events.hipo"; // HIPO format file + + // Parameters for file writing (file split thresholds, etc.) + uint32_t maxRecordBytes = 1000000; // max bytes per record (e.g., ~1 MB) + uint32_t maxEventsPerRecord = 1000; // max number of events per record + uint32_t bufferBytes = 1000000; // internal buffer size in bytes + + // **1. Create writers for each format.** + // EVIO version 4 writer (using EventWriterV4) + EventWriterV4 writerV4(fileNameEvio4, // file path + "", "", // (directory, runType not used here) + 1, 0, // runNumber=1, splitNumber=0 (no file splitting) + maxRecordBytes, maxEventsPerRecord, + ByteOrder::ENDIAN_LOCAL, // use local endian byte order + xmlDictionary, true, false, // give dictionary, overwrite existing, no append + nullptr, 0, 0, // no “first event” provided + 1, 1, // stream id=1, starting block number=1 + bufferBytes); + + // EVIO version 6 writer (EventWriter) – outputs EVIO format by default​:contentReference[oaicite:0]{index=0} + EventWriter writerV6(fileNameEvio6, // file path + "", "", // (directory, runType) + 1, 0, // runNumber=1, no file splitting + maxRecordBytes, maxEventsPerRecord, + ByteOrder::ENDIAN_LOCAL, + xmlDictionary, true, false, // dictionary, overwrite, no append + nullptr, 1, 0, 1, 1, // no first event, stream id=1, block=1 + Compressor::CompressionType::UNCOMPRESSED, + 0, 0, // no compression, so 0 threads and default level + bufferBytes); + + // HIPO format writer (also uses EventWriter, but with HIPO file header)​:contentReference[oaicite:1]{index=1} + // We enable HIPO by specifying a compression type (e.g., LZ4) – the EVIO library will + // then produce a HIPO file header (ID = 0x43455248 for "HIPO") instead of "EVIO"​:contentReference[oaicite:2]{index=2}. + EventWriter writerHipo(fileNameHipo, + "", "", + 1, 0, + maxRecordBytes, maxEventsPerRecord, + ByteOrder::ENDIAN_LOCAL, + xmlDictionary, true, false, + nullptr, 1, 0, 1, 1, + Compressor::CompressionType::UNCOMPRESSED, // use LZ4 compression to trigger HIPO format + 0, 0, + bufferBytes); + + // Random number generator for Gaussian (mean=0, sigma=0.1) + std::random_device rd; + std::mt19937 gen(rd()); + std::normal_distribution gauss(0.0, 0.1); + + + // **2. Loop over events and write each one.** + for (int i = 0; i < nEvents; ++i) { + // Create an event as a bank containing four 32-bit floats + std::shared_ptr event = EvioBank::getInstance(1, DataType::FLOAT32, 1); + // Fill the bank's float data (x, y, z, time) with 0.0 + auto &floatData = event->getFloatData(); + floatData.assign(5, 0.0f); + floatData[0] = gauss(gen); + floatData[1] = gauss(gen); + floatData[2] = 0.; + floatData[3] = i*2.008f; // to mock up rf time + event->updateFloatData(); // update internal length counters​:contentReference[oaicite:3]{index=3} + + // Write the event to each file format + writerV4.writeEvent(event); + writerV6.writeEvent(event); + writerHipo.writeEvent(event); + } + + // **3. Close all files to flush buffers.** + writerV4.close(); + writerV6.close(); + writerHipo.close(); + + std::cout << "Wrote " << nEvents << " events to EVIO4, EVIO6, and HIPO format files." << std::endl; + return 0; +} diff --git a/tutorials/WriteFilePseudoPhysicsEventExtended.cpp b/tutorials/WriteFilePseudoPhysicsEventExtended.cpp new file mode 100644 index 000000000..2e6b8399a --- /dev/null +++ b/tutorials/WriteFilePseudoPhysicsEventExtended.cpp @@ -0,0 +1,92 @@ +#include +#include +#include +#include +#include "eviocc.h" + +using namespace evio; + +int main(int argc, char** argv) { + if (argc < 2) { + std::cerr << "Usage: " << argv[0] << " \n"; + return 1; + } + int nEvents = std::stoi(argv[1]); + + // Output file names for EVIO4, EVIO6, and HIPO + std::string fileNameEvio4 = "events_v4.ev"; + std::string fileNameEvio6 = "events_v6.ev"; + std::string fileNameHipo = "events.hipo"; + + // Writing parameters (similar to minimal version) + uint32_t maxRecordBytes = 1000000; + uint32_t maxEventsPerRecord = 1000; + uint32_t bufferBytes = 1000000; + + // Create writers for EVIO4, EVIO6, and HIPO formats (same setup as minimal example) + EventWriterV4 writerV4(fileNameEvio4, "", "", 1, 0, // string baseName, string &directory, string &runType, uint32_t runNumber, uint64_t split + maxRecordBytes, maxEventsPerRecord, + ByteOrder::ENDIAN_LOCAL, "", true, false, //const ByteOrder &byteOrder, string &xmlDictionary, bool overWriteOK, bool append + nullptr, 0, 0, 1, 1, bufferBytes); // shared_ptr< EvioBank > firstEvent, uint32_t streamId, uint32_t splitNumber, uint32_t splitIncrement, uint32_t streamCount, Compressor::CompressionType compressionType, uint32_t compressionThreads, uint32_t ringSize, uint32_t bufferSize + + EventWriter writerV6(fileNameEvio6, "", "", 1, 0, + maxRecordBytes, maxEventsPerRecord, + ByteOrder::ENDIAN_LOCAL, "", true, false, + nullptr, 1, 0, 1, 1, + Compressor::CompressionType::UNCOMPRESSED, + 0, 0, bufferBytes); + + EventWriter writerHipo(fileNameHipo, "", "", 1, 0, + maxRecordBytes, maxEventsPerRecord, + ByteOrder::ENDIAN_LOCAL, "", true, false, + nullptr, 1, 0, 1, 1, + Compressor::CompressionType::UNCOMPRESSED, + 0, 0, bufferBytes); + + // Loop to build and write events + for (int i = 0; i < nEvents; ++i) { + // **Create a top-level event (bank of banks)** with tag=1, num=1 + EventBuilder builder(1, DataType::BANK, 1); + std::shared_ptr event = builder.getEvent(); + + // Valid data types: int32, unint32, long64, ulong64, short16, ushort16, char8, uchar8, charstar8, float32, double64, bank, segment, tagsegment, composite, unknown32 + + // **Bank 1: Floats** – create a bank holding 4 float32 values + auto bankFloats = EvioBank::getInstance(10, DataType::FLOAT32, 1); + auto &fData = bankFloats->getFloatData(); + fData.assign(4, 0.0f); // four floats initialized to 0.0 + bankFloats->updateFloatData(); // update length for float data​:contentReference[oaicite:8]{index=8} + builder.addChild(event, bankFloats); // add this bank to the event​:contentReference[oaicite:9]{index=9} + + // **Bank 2: Integers** – create a bank holding some int32 values + auto bankInts = EvioBank::getInstance(11, DataType::INT32, 2); + auto &iData = bankInts->getIntData(); + iData.push_back(42); // add an integer value 42 + iData.push_back(42); // (for example, add twice to illustrate multiple entries) + bankInts->updateIntData(); // update length for int data + builder.addChild(event, bankInts); // add this bank to the event​:contentReference[oaicite:10]{index=10} + + // **Bank 3: Strings** – create a bank holding one or more strings + auto bankStrings = EvioBank::getInstance(12, DataType::CHARSTAR8, 3); + auto &sData = bankStrings->getStringData(); + sData.emplace_back("example"); // add a string value "example" + // (multiple strings can be added to this vector as needed) + bankStrings->updateStringData(); // update length for string data + builder.addChild(event, bankStrings); // add this bank to the event + + // At this point, `event` contains three child banks (float, int, string). + // **Write the constructed event to all three output files:** + writerV4.writeEvent(event); + writerV6.writeEvent(event); + writerHipo.writeEvent(event); + } + + // Close writers to flush and finalize files + writerV4.close(); + writerV6.close(); + writerHipo.close(); + + std::cout << "Wrote " << nEvents + << " composite events (floats+ints+strings) to EVIO4, EVIO6, and HIPO files.\n"; + return 0; +} From 18446e306bbda805c4bd154aaecaf51d6f849e2a Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Wed, 23 Apr 2025 09:46:03 -0500 Subject: [PATCH 06/56] More work on tutorials --- .gitignore | 9 +++++++++ tutorials/EVIO_v4_to_v6.cpp | 20 +++++++++---------- .../WriteFilePseudoPhysicsEventExtended.cpp | 3 +++ 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 2e3796a9e..6d2fba405 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,12 @@ .* # ignore all files/dirs beginning with _ _* +# ignore any .evio, .ev, or .hipo extension files +*.evio +*.ev +*.hipo +# EventViewer Jar +JEventViewer*.jar # except these two !.gitignore @@ -13,6 +19,8 @@ cmake_install.cmake coda.pyc build/ jbuild/ +lib/ +bin/ doxyerrors.log /target/ doc/javadoc @@ -20,3 +28,4 @@ doc/doxygen/CC doc/doxygen/C doc/source/ config.log + diff --git a/tutorials/EVIO_v4_to_v6.cpp b/tutorials/EVIO_v4_to_v6.cpp index c8103f291..e6e7d597f 100644 --- a/tutorials/EVIO_v4_to_v6.cpp +++ b/tutorials/EVIO_v4_to_v6.cpp @@ -26,25 +26,23 @@ int main(int argc, char* argv[]) { EvioReader reader(f_in); // EvioCompactReader reader(f_in); - EventWriter writerV6(f_out, "", "", 1, 0, + EventWriter writer(f_out, "", "", 1, 0, maxRecordBytes, maxEventsPerRecord, ByteOrder::ENDIAN_LOCAL, "", true, false, nullptr, 1, 0, 1, 1, Compressor::CompressionType::UNCOMPRESSED, 0, 0, bufferBytes); - for(int32_t i = 0; i < reader.getEventCount(); ++i) { - - // **Create a top-level event (bank of banks)** with tag=1, num=1 - EventBuilder builder(1, DataType::BANK, 1); - std::shared_ptr event = builder.getEvent(); - - auto ev = reader.parseEvent(i + 1); - auto & dataVec = ev->getRawBytes(); - Util::printBytes(dataVec.data(), dataVec.size()," Event #" + std::to_string(i)); - + // 5. Loop over all regular events and write them out + std::shared_ptr event; + while ((event = reader.parseNextEvent()) != nullptr) { + writer.writeEvent(event); } + // 6. Close writer to flush data and finalize file + writer.close(); + std::cout << "Conversion complete. Output file contains " + << reader.getEventCount() << " events (plus any first event/dictionary)." << std::endl; } diff --git a/tutorials/WriteFilePseudoPhysicsEventExtended.cpp b/tutorials/WriteFilePseudoPhysicsEventExtended.cpp index 2e6b8399a..75bd59f5a 100644 --- a/tutorials/WriteFilePseudoPhysicsEventExtended.cpp +++ b/tutorials/WriteFilePseudoPhysicsEventExtended.cpp @@ -47,6 +47,9 @@ int main(int argc, char** argv) { for (int i = 0; i < nEvents; ++i) { // **Create a top-level event (bank of banks)** with tag=1, num=1 EventBuilder builder(1, DataType::BANK, 1); + // Create the buffer to hold everything + // auto buffer = std::make_shared(8192); + // CompactEventBuilder builder(buffer); std::shared_ptr event = builder.getEvent(); // Valid data types: int32, unint32, long64, ulong64, short16, ushort16, char8, uchar8, charstar8, float32, double64, bank, segment, tagsegment, composite, unknown32 From 92d11f07c531bcf36691c38c4c94d2e52c1e22bf Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Thu, 24 Apr 2025 18:36:42 -0500 Subject: [PATCH 07/56] More progress on tests --- .gitignore | 2 + CMakeLists.txt | 8 +- src/test/BigFileWrite.cpp | 107 ++++++++++++++++ src/test/BigFileWritePrimitive.cpp | 145 ++++++++++++++++++++++ src/test/ReadWriteV4Test.cpp | 7 +- tutorials/ConvertFormats.cpp | 121 ++++++++++++++++++ tutorials/EvioTestHelper.h | 97 +++++++++++++++ tutorials/WriteFilePseudoPhysicsEvent.cpp | 15 ++- 8 files changed, 493 insertions(+), 9 deletions(-) create mode 100644 src/test/BigFileWrite.cpp create mode 100644 src/test/BigFileWritePrimitive.cpp create mode 100644 tutorials/ConvertFormats.cpp create mode 100644 tutorials/EvioTestHelper.h diff --git a/.gitignore b/.gitignore index 6d2fba405..bba402351 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ _* *.evio *.ev *.hipo +*.dat +*.txt # EventViewer Jar JEventViewer*.jar diff --git a/CMakeLists.txt b/CMakeLists.txt index b1879bb20..cfde4d981 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,9 +30,9 @@ project(evio VERSION 6.0) include(GNUInstallDirs) # Allow users to set C++ standard via -DCMAKE_CXX_STANDARD -# Only default to C++11 if not already set +# Only default to C++14 if not already set if(NOT CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 11) + set(CMAKE_CXX_STANDARD 14) endif() set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_DEBUG_POSTFIX -dbg) @@ -222,10 +222,14 @@ set(TEST src/test/ReadSequenceTest.cpp src/test/SequentialReaderTest.cpp src/test/SplitTest2.cpp + # Jon added programs below + src/test/BigFileWrite.cpp + src/test/BigFileWritePrimitive.cpp tutorials/WriteFilePseudoPhysicsEvent.cpp tutorials/WriteFilePseudoPhysicsEventExtended.cpp tutorials/PrintXMLDict.cpp tutorials/EVIO_v4_to_v6.cpp + tutorials/ConvertFormats.cpp ) set(TESTC diff --git a/src/test/BigFileWrite.cpp b/src/test/BigFileWrite.cpp new file mode 100644 index 000000000..220b9a8ec --- /dev/null +++ b/src/test/BigFileWrite.cpp @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include +#include +#include // open() +#include // close(), fsync() + +#include "eviocc.h" + +int main(int argc, char *argv[]) { + // Default parameters + std::string outFile = "output.evio"; + unsigned long long fileSize = 100 * 1024 * 1024; // 100 MB default + size_t bufferSize = 1024; // event payload size in bytes + int repeatCount = 1; + bool doSync = false; + bool debug = false; + + // Parse simple command-line flags + for (int i = 1; i < argc; ++i) { + std::string arg = argv[i]; + if ((arg == "-o" || arg == "--output") && i+1 < argc) { // i+1 logic ensures argument provided + outFile = argv[++i]; + } else if ((arg == "-s" || arg == "--size") && i+1 < argc) { + fileSize = std::stoull(argv[++i]); + } else if ((arg == "-b" || arg == "--bufsize") && i+1 < argc) { + bufferSize = std::stoul(argv[++i]); + } else if ((arg == "-n" || arg == "--repeat") && i+1 < argc) { + repeatCount = std::stoi(argv[++i]); + } else if (arg == "--sync") { + doSync = true; + } else if (arg == "--debug") { + debug = true; + } else { + std::cerr << "Usage: " << argv[0] + << " -o -s -b " + << " -n [--sync] [--debug]\n"; + return 1; + } + } + + // Create dummy data buffer to fill each event + std::vector data(bufferSize); + // Fill with non-zero pattern (optional) + for (size_t i = 0; i < bufferSize; ++i) { + data[i] = static_cast(i & 0xFF); + } + + // Prepare EVIO event builder for an event with UCHAR8 (8-bit) data + evio::EventBuilder builder(1, evio::DataType::UCHAR8, 1); + auto event = builder.getEvent(); + // Attach the dummy data to the event + builder.setUCharData(event, data.data(), data.size()); + builder.setAllHeaderLengths(); // ensure EVIO length fields are up-to-date + + // Calculate how many events to write to reach at least fileSize bytes + // (We ignore EVIO file header overhead for simplicity) + uint32_t eventBytes = event->getTotalBytes(); + unsigned long long eventsPerRun = + static_cast(std::ceil(double(fileSize) / eventBytes)); + + // Loop for the specified repeat count + double totalThroughput = 0.0; + for (int r = 0; r < repeatCount; ++r) { + // Open an EventWriter to write events to the file + evio::EventWriter writer(outFile, evio::ByteOrder::ENDIAN_LOCAL, false); + // Start timing + auto start = std::chrono::high_resolution_clock::now(); + // Write events repeatedly + for (unsigned long long i = 0; i < eventsPerRun; ++i) { + writer.writeEvent(event); // write the dummy event​:contentReference[oaicite:1]{index=1} + if (debug) { + static auto lastTime = start; + auto now = std::chrono::high_resolution_clock::now(); + auto us = std::chrono::duration_cast(now - lastTime).count(); + std::cout << "Event " << i+1 << " written in " << us << " us\n"; + lastTime = now; + } + } + writer.close(); // finish writing, flush any buffered records​:contentReference[oaicite:2]{index=2} + // Optionally force sync data to disk + if (doSync) { + int fd = ::open(outFile.c_str(), O_RDONLY); + if (fd != -1) { + ::fsync(fd); + ::close(fd); + } + } + auto end = std::chrono::high_resolution_clock::now(); + // Calculate throughput (MB/s). 1 MB = 10^6 bytes for this calculation. + std::chrono::duration secs = end - start; + unsigned long long bytesWritten = eventsPerRun * eventBytes; + double MBperSec = (bytesWritten / 1.0e6) / secs.count(); + totalThroughput += MBperSec; + std::cout.setf(std::ios::fixed); + std::cout.precision(2); + std::cout << "Run " << r+1 << ": Wrote " << bytesWritten + << " bytes in " << secs.count() << " s (throughput = " + << MBperSec << " MB/s)\n"; + } + if (repeatCount > 1) { + std::cout << "Average throughput over " << repeatCount + << " runs = " << (totalThroughput / repeatCount) << " MB/s\n"; + } +} diff --git a/src/test/BigFileWritePrimitive.cpp b/src/test/BigFileWritePrimitive.cpp new file mode 100644 index 000000000..fdbca2d75 --- /dev/null +++ b/src/test/BigFileWritePrimitive.cpp @@ -0,0 +1,145 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "eviocc.h" + +int main(int argc, char *argv[]) { + // Default parameters + std::string outFile = "output.evio"; + unsigned long long fileSize = 100 * 1024 * 1024; // 100 MB default + size_t bufferSize = 1024; // event payload size in bytes + int repeatCount = 1; + bool doSync = false; + bool debug = false; + + // Parse simple command-line flags + for (int i = 1; i < argc; ++i) { + std::string arg = argv[i]; + if ((arg == "-o" || arg == "--output") && i+1 < argc) { // i+1 logic ensures argument provided + outFile = argv[++i]; + } else if ((arg == "-s" || arg == "--size") && i+1 < argc) { + fileSize = std::stoull(argv[++i]); + } else if ((arg == "-b" || arg == "--bufsize") && i+1 < argc) { + bufferSize = std::stoul(argv[++i]); + } else if ((arg == "-n" || arg == "--repeat") && i+1 < argc) { + repeatCount = std::stoi(argv[++i]); + } else if (arg == "--sync") { + doSync = true; + } else if (arg == "--debug") { + debug = true; + } else { + std::cerr << "Usage: " << argv[0] + << " -o -s -b " + << " -n [--sync] [--debug]\n"; + return 1; + } + } + + // Prepare dummy data + std::vector data(bufferSize); + for (size_t i = 0; i < bufferSize; ++i) { + data[i] = static_cast(i & 0xFF); + } + + // Build one dummy event using EventBuilder + evio::EventBuilder builder(1, evio::DataType::UCHAR8, 1); + auto event = builder.getEvent(); + builder.setUCharData(event, data.data(), data.size()); + builder.setAllHeaderLengths(); + uint32_t eventBytes = event->getTotalBytes(); // size of one event (bytes) + + // Compute number of events to write to reach fileSize + unsigned long long eventsPerRun = + static_cast(std::ceil(double(fileSize) / eventBytes)); + + // Retrieve binary representation of the event + std::vector eventBuffer(eventBytes); + event->write(eventBuffer.data(), evio::ByteOrder::ENDIAN_LOCAL); // serialize event to bytes​:contentReference[oaicite:9]{index=9} + + // EVIO file and record header construction (for one record containing all events) + const uint32_t FILE_HEADER_WORDS = 14; + const uint32_t RECORD_HEADER_WORDS = 14; + // Prepare file header (14 words) as per EVIO format version 6 + uint32_t fileHeader[FILE_HEADER_WORDS]; + uint32_t recordHeader[RECORD_HEADER_WORDS]; + // File Header fields (EVIO 6): + fileHeader[0] = 0x4556494F; // "EVIO" file type ID + fileHeader[1] = 1; // File number (for split files; 1 for single file) + fileHeader[2] = FILE_HEADER_WORDS; // Header length (words) + fileHeader[3] = 1; // Record count in file (we will use one record) + fileHeader[4] = 0; // Index array length (unused, 0) + fileHeader[5] = 6; // Bit info & Version: version=6, no extra flags + fileHeader[6] = 0; // User header length (no user header) + fileHeader[7] = 0xC0DA0100; // Magic number (endianness check) + // The remaining 6 words (user register 64-bit, trailer position 64-bit, user ints) set to 0: + fileHeader[8] = fileHeader[9] = 0; + fileHeader[10] = fileHeader[11] = 0; + fileHeader[12] = fileHeader[13] = 0; + // Record Header fields (EVIO 6): + uint32_t recordLenWords = RECORD_HEADER_WORDS + eventsPerRun * (eventBytes / 4); + recordHeader[0] = recordLenWords; // Record length in words (including this header) + recordHeader[1] = 1; // Record (block) number + recordHeader[2] = RECORD_HEADER_WORDS; // Header length in words + recordHeader[3] = (uint32_t) eventsPerRun;// Event count in this record + recordHeader[4] = 0; // Index array length (no event index) + recordHeader[5] = 0x206; // Bit info & Version: 0x200 (last record flag) | 0x6 (version 6) + recordHeader[6] = 0; // Reserved / user header length (unused here) + recordHeader[7] = 0xC0DA0100; // Magic number + // Remaining 6 words of record header: + recordHeader[8] = recordHeader[9] = 0; // (possibly uncompressed length or user info, not used) + recordHeader[10] = recordHeader[11] = 0; // (reserved/trailer info, not used) + recordHeader[12] = recordHeader[13] = 0; // User integers (unused) + + double totalThroughput = 0.0; + for (int r = 0; r < repeatCount; ++r) { + // Open output file with low-level POSIX API + int fd = ::open(outFile.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644); + if (fd < 0) { + std::cerr << "Cannot open output file " << outFile << "\n"; + return 1; + } + // Start timing + auto start = std::chrono::high_resolution_clock::now(); + // Write file header (uncompressed, 56 bytes for 14 words) + ::write(fd, fileHeader, FILE_HEADER_WORDS * sizeof(uint32_t)); + // Write record header (56 bytes) + ::write(fd, recordHeader, RECORD_HEADER_WORDS * sizeof(uint32_t)); + // Write events in a loop + for (unsigned long long i = 0; i < eventsPerRun; ++i) { + ::write(fd, eventBuffer.data(), eventBytes); + if (debug) { + static auto lastTime = start; + auto now = std::chrono::high_resolution_clock::now(); + auto us = std::chrono::duration_cast(now - lastTime).count(); + std::cout << "Event " << i+1 << " written in " << us << " us\n"; + lastTime = now; + } + } + // Optional sync to disk + if (doSync) { + ::fsync(fd); + } + ::close(fd); + auto end = std::chrono::high_resolution_clock::now(); + // Calculate throughput + std::chrono::duration secs = end - start; + unsigned long long bytesWritten = (FILE_HEADER_WORDS + RECORD_HEADER_WORDS) * 4 + + eventsPerRun * eventBytes; + double MBperSec = (bytesWritten / 1.0e6) / secs.count(); + totalThroughput += MBperSec; + std::cout.setf(std::ios::fixed); + std::cout.precision(2); + std::cout << "Run " << r+1 << ": Wrote " << bytesWritten + << " bytes in " << secs.count() << " s (throughput = " + << MBperSec << " MB/s)\n"; + } + if (repeatCount > 1) { + std::cout << "Average throughput over " << repeatCount + << " runs = " << (totalThroughput / repeatCount) << " MB/s\n"; + } +} diff --git a/src/test/ReadWriteV4Test.cpp b/src/test/ReadWriteV4Test.cpp index ce1a5a83e..42bdd6924 100644 --- a/src/test/ReadWriteV4Test.cpp +++ b/src/test/ReadWriteV4Test.cpp @@ -253,14 +253,17 @@ namespace evio { std::cout << "\n Print out events (includes first event if evio version 4) :" << std::endl; - for (uint32_t i = 0; i < evCount2; i++) { +/* for (uint32_t i = 0; i < evCount2; i++) { // The "first event" is just the first event in the list (not treated specially) std::cout << " scanned event #" << (i+1) << " :" << std::endl; std::shared_ptr compactNode = reader1.getScannedEvent(i + 1); std::cout << " node ->\n " << compactNode->toString() << std::endl; std::shared_ptr dataBuf = std::make_shared(compactNode->getTotalBytes()); + std::cout << "GOT THIS FAR 1" << std::endl; + compactNode->getStructureBuffer(dataBuf, true); + std::cout << "GOT THIS FAR 2" << std::endl; if (i == 0) { dataBuf0 = dataBuf; @@ -268,7 +271,7 @@ namespace evio { " Event #" + std::to_string(i+1)); } } - } + */ } catch (EvioException &e) { std::cout << "PROBLEM: " << e.what(); } diff --git a/tutorials/ConvertFormats.cpp b/tutorials/ConvertFormats.cpp new file mode 100644 index 000000000..bbedbe541 --- /dev/null +++ b/tutorials/ConvertFormats.cpp @@ -0,0 +1,121 @@ +#include +#include +#include +#include + +#include "eviocc.h" // EVIO-6 C++ API +using namespace evio; + +enum class Fmt { EVIO4, EVIO6, HIPO }; + +void usage(const char* prog) { + std::cerr << + "Usage: " << prog << " " + " \n"; + std::exit(1); +} + +Fmt parseFmt(const std::string& s) { + auto lo = s; std::transform(lo.begin(), lo.end(), lo.begin(), ::tolower); + if (lo=="evio4") return Fmt::EVIO4; + else if(lo=="evio6") return Fmt::EVIO6; + else if(lo=="hipo") return Fmt::HIPO; + usage("convert"); + return Fmt::EVIO6; // never reached +} + +int main(int argc, char* argv[]) { + if (argc!=5) usage(argv[0]); + std::string inFile = argv[1]; + Fmt inFmt = parseFmt(argv[2]); + std::string outFile = argv[3]; + Fmt outFmt = parseFmt(argv[4]); + + // Common EVIO parameters (tweak as desired) + uint32_t maxRecordBytes = 1000000; + uint32_t maxEventsPerRecord = 1000; + uint32_t bufferBytes = 1000000; + size_t bufferBytesSize = bufferBytes; + + // --- Set up reader --- + std::unique_ptr evioReader; + if (inFmt==Fmt::EVIO4 || inFmt==Fmt::EVIO6) evioReader = std::make_unique(inFile); + + // Pull dictionary XML (if present) + std::string dictXml = ""; + if (evioReader->hasDictionaryXML()) { + dictXml = evioReader->getDictionaryXML(); // preserves dictionary in user‐header :contentReference[oaicite:0]{index=0} + std::cerr << "Dictionary XML: " << dictXml << "\n"; + } + else std::cerr << "No dictionary XML found in input file.\n"; + + + // --- Set up writer --- + std::unique_ptr evioWriter; + std::unique_ptr evioWriterV4; + + if (outFmt==Fmt::EVIO6) { + evioWriter = std::make_unique( + outFile, + "", "", + 1, 0, + maxRecordBytes, maxEventsPerRecord, + ByteOrder::ENDIAN_LOCAL, + dictXml, // xml dictionary + true, false, // overwrite existing, no append + nullptr, 1, 0, 1, 1, + Compressor::CompressionType::UNCOMPRESSED, // use LZ4 compression to trigger HIPO format + 0, 0, + bufferBytes); + } + else if (outFmt==Fmt::EVIO4) { + evioWriterV4 = std::make_unique( + outFile, + "", "", + 1, 0, + maxRecordBytes, maxEventsPerRecord, + ByteOrder::ENDIAN_LOCAL, + dictXml, // xml dictionary + true, false, // overwrite existing, no append + nullptr, 1, 0, 1, 1, + bufferBytesSize); + } + else { + evioWriter = std::make_unique( + outFile, + "", "", + 1, 0, + maxRecordBytes, maxEventsPerRecord, + ByteOrder::ENDIAN_LOCAL, + dictXml, // xml dictionary + true, false, // overwrite existing, no append + nullptr, 1, 0, 1, 1, + Compressor::CompressionType::LZ4, // use LZ4 compression to trigger HIPO format + 0, 0, + bufferBytes); + } + + + // --- Conversion loop --- + try { + // EVIO → ... + if (evioReader) { + std::shared_ptr ev; + while ((ev = evioReader->parseNextEvent())) { + if (evioWriter) { + evioWriter->writeEvent(ev); + } + } + } + + // flush/close + if (evioWriter) evioWriter->close(); + + std::cout<<"Conversion complete.\n"; + } + catch (const std::exception &e) { + std::cerr<<"Error during conversion: "< +#include +#include +#include +#include +#include +#include +#include + +#include "eviocc.h" + + +namespace evio { + + + class EvioTestHelper { + + protected: + + + public: + + explicit EvioTestHelper(); + + + EventWriterV4 defaultEventWriterV4(); + + EventWriter defaultEventWriter() { + return EventWriter( + baseName, + directory, + runType, + runNumber, + split, + maxRecordSize, + maxEventCount, + byteOrder, + xmlDictionary, + overWriteOK, + append, + firstEvent, + streamId, + splitNumber, + splitIncrement, + streamCount, + compressionType, + compressionThreads, + ringSize, + bufferSize + ); + } + + EventWriter makeEventWriterHIPO(); + + float* genXYZT(); + + + private: + std::string dictionary; + std::string baseName; + const std::string & directory; + const std::string & runType; + uint32_t runNumber = 1; + uint64_t split = 0; + uint32_t maxRecordSize = 4194304; + uint32_t maxEventCount = 10000; + const ByteOrder & byteOrder = ByteOrder::nativeOrder(); + const std::string & xmlDictionary = ""; + bool overWriteOK = true; + bool append = false; + std::shared_ptr< EvioBank >firstEvent = nullptr; + uint32_t streamId = 1; + uint32_t splitNumber = 0; + uint32_t splitIncrement = 1; + uint32_t streamCount = 1; + Compressor::CompressionType compressionType = Compressor::UNCOMPRESSED; + uint32_t compressionThreads = 1; + uint32_t ringSize = 0; + size_t bufferSize = 32100000; + }; + +} + + +#endif //EVIO_TEST_HELPER_H diff --git a/tutorials/WriteFilePseudoPhysicsEvent.cpp b/tutorials/WriteFilePseudoPhysicsEvent.cpp index 4f3f47664..b130fb16b 100644 --- a/tutorials/WriteFilePseudoPhysicsEvent.cpp +++ b/tutorials/WriteFilePseudoPhysicsEvent.cpp @@ -13,6 +13,8 @@ int main(int argc, char** argv) { } int nEvents = std::stoi(argv[1]); + + // XML dictionary defining labels for the event structure std::string xmlDictionary = R"( @@ -46,7 +48,8 @@ int main(int argc, char** argv) { 1, 0, // runNumber=1, splitNumber=0 (no file splitting) maxRecordBytes, maxEventsPerRecord, ByteOrder::ENDIAN_LOCAL, // use local endian byte order - xmlDictionary, true, false, // give dictionary, overwrite existing, no append + xmlDictionary, // xml dictionary + true, false, // overwrite existing, no append nullptr, 0, 0, // no “first event” provided 1, 1, // stream id=1, starting block number=1 bufferBytes); @@ -57,8 +60,9 @@ int main(int argc, char** argv) { 1, 0, // runNumber=1, no file splitting maxRecordBytes, maxEventsPerRecord, ByteOrder::ENDIAN_LOCAL, - xmlDictionary, true, false, // dictionary, overwrite, no append - nullptr, 1, 0, 1, 1, // no first event, stream id=1, block=1 + xmlDictionary, // xml dictionary + true, false, // overwrite existing, no append + nullptr, 1, 0, 1, 1, // no first event, stream id=1, block=1 Compressor::CompressionType::UNCOMPRESSED, 0, 0, // no compression, so 0 threads and default level bufferBytes); @@ -71,9 +75,10 @@ int main(int argc, char** argv) { 1, 0, maxRecordBytes, maxEventsPerRecord, ByteOrder::ENDIAN_LOCAL, - xmlDictionary, true, false, + xmlDictionary, // xml dictionary + true, false, // overwrite existing, no append nullptr, 1, 0, 1, 1, - Compressor::CompressionType::UNCOMPRESSED, // use LZ4 compression to trigger HIPO format + Compressor::CompressionType::LZ4, // use LZ4 compression to trigger HIPO format 0, 0, bufferBytes); From 563cd4b1db2b2a623ef981461affa555cf7dbd52 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Fri, 25 Apr 2025 10:08:20 -0500 Subject: [PATCH 08/56] More additions to helper class --- CMakeLists.txt | 4 +- tutorials/EvioTestHelper.h | 128 +++++++++++++++++----- tutorials/WriteFilePseudoPhysicsEvent.cpp | 93 +++------------- 3 files changed, 115 insertions(+), 110 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cfde4d981..dc34ebee8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,9 +30,9 @@ project(evio VERSION 6.0) include(GNUInstallDirs) # Allow users to set C++ standard via -DCMAKE_CXX_STANDARD -# Only default to C++14 if not already set +# Only default to C++17 if not already set if(NOT CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 14) + set(CMAKE_CXX_STANDARD 17) endif() set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_DEBUG_POSTFIX -dbg) diff --git a/tutorials/EvioTestHelper.h b/tutorials/EvioTestHelper.h index fc150adc3..514eeaa3c 100644 --- a/tutorials/EvioTestHelper.h +++ b/tutorials/EvioTestHelper.h @@ -18,11 +18,13 @@ #include #include #include +#include +#include #include "eviocc.h" -namespace evio { +using namespace evio; class EvioTestHelper { @@ -34,12 +36,35 @@ namespace evio { explicit EvioTestHelper(); + std::shared_ptr defaultEventWriterV4() { + return std::make_shared( + std::string(baseName+"_V4.evio"), + directory, + runType, + runNumber, + split, + maxRecordSize, + maxEventCount, + byteOrder, + xmlDictionary, + overWriteOK, + append, + firstEvent, + streamId, + splitNumber, + splitIncrement, + streamCount, + bufferSize, + bitInfo + ); + } + + std::shared_ptr defaultEventWriter() { - EventWriterV4 defaultEventWriterV4(); + EventWriter myWriter(); - EventWriter defaultEventWriter() { - return EventWriter( - baseName, + return std::make_shared( + std::string(baseName+"_V6.ev"), directory, runType, runNumber, @@ -61,37 +86,82 @@ namespace evio { bufferSize ); } - - EventWriter makeEventWriterHIPO(); + std::shared_ptr defaultEventWriterHIPO() { + return std::make_shared( + std::string(baseName+"_HIPO_LZ4.ev"), + directory, + runType, + runNumber, + split, + maxRecordSize, + maxEventCount, + byteOrder, + xmlDictionary, + overWriteOK, + append, + firstEvent, + streamId, + splitNumber, + splitIncrement, + streamCount, + compressionTypeHIPO, + compressionThreads, + ringSize, + bufferSize + ); + } - float* genXYZT(); - + std::vector genXYZT(int i) { + std::vector x4(4); + x4[0] = gauss(gen); + x4[1] = gauss(gen); + x4[2] = 0.0f; + x4[3] = i*2.008f; + return x4; + } private: - std::string dictionary; - std::string baseName; - const std::string & directory; - const std::string & runType; + + // Random number generator for Gaussian (mean=0, sigma=0.1) + std::random_device my_rd; + std::mt19937 gen{ my_rd() }; + std::normal_distribution gauss{0.0f, 0.1f}; + + std::string dictionary = R"( + + + + + + + + + + + + )"; + const std::string baseName = "testEvents"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + const std::string directory = ""; // directory in which file is to be placed + const std::string runType = ""; // name of run type configuration to be used in naming files uint32_t runNumber = 1; - uint64_t split = 0; - uint32_t maxRecordSize = 4194304; - uint32_t maxEventCount = 10000; - const ByteOrder & byteOrder = ByteOrder::nativeOrder(); - const std::string & xmlDictionary = ""; + uint64_t split = 0; // if < 1, do not split file, write to only one file of unlimited size. Else this is max size in bytes to make a file before closing it and starting writing another. + uint32_t maxRecordSize = 33554432; // (32 MiB) max number of uncompressed data bytes each record can hold. Value of < 8MB results in default of 8MB. The size of the record will not be larger than this size unless a single event itself is larger + uint32_t maxEventCount = 10000; // max number of events each record can hold. Value <= O means use default (1M). + const ByteOrder & byteOrder = ByteOrder::nativeOrder(); + const std::string & xmlDictionary = ""; bool overWriteOK = true; bool append = false; - std::shared_ptr< EvioBank >firstEvent = nullptr; - uint32_t streamId = 1; - uint32_t splitNumber = 0; - uint32_t splitIncrement = 1; - uint32_t streamCount = 1; + std::shared_ptr< EvioBank >firstEvent = nullptr; // The first event written into each file (after any dictionary) including all split files; may be null. Useful for adding common, static info into each split file + uint32_t streamId = 1; // streamId number (100 > id > -1) for file name + uint32_t splitNumber = 0; // number at which to start the split numbers + uint32_t splitIncrement = 1; // amount to increment split number each time another file is created + uint32_t streamCount = 1; // total number of streams in DAQ Compressor::CompressionType compressionType = Compressor::UNCOMPRESSED; - uint32_t compressionThreads = 1; - uint32_t ringSize = 0; - size_t bufferSize = 32100000; + Compressor::CompressionType compressionTypeHIPO = Compressor::LZ4; + uint32_t compressionThreads = 1; // number of threads doing compression simultaneously + uint32_t ringSize = 0; // number of records in supply ring. If set to < compressionThreads, it is forced to equal that value and is also forced to be a multiple of 2, rounded up. + size_t bufferSize = 33554432; // (32 MiB) number of bytes to make each internal buffer which will be storing events before writing them to a file. 9MB = default if bufferSize = 0. + std::bitset<24>* bitInfo = nullptr; // EventWriterV4 only, set of bits to include in first block header }; -} - - #endif //EVIO_TEST_HELPER_H diff --git a/tutorials/WriteFilePseudoPhysicsEvent.cpp b/tutorials/WriteFilePseudoPhysicsEvent.cpp index b130fb16b..517705f65 100644 --- a/tutorials/WriteFilePseudoPhysicsEvent.cpp +++ b/tutorials/WriteFilePseudoPhysicsEvent.cpp @@ -2,7 +2,8 @@ #include #include -#include "eviocc.h" // EVIO C++ API (EVIO 6 main branch) +#include "eviocc.h" +#include "EvioTestHelper.h" // EVIO C++ API (EVIO 6 main branch) using namespace evio; @@ -13,79 +14,16 @@ int main(int argc, char** argv) { } int nEvents = std::stoi(argv[1]); - - - // XML dictionary defining labels for the event structure - std::string xmlDictionary = R"( - - - - - - - - - - - - )"; - + EvioTestHelper evioHelperObj(); // Output file names for each format std::string fileNameEvio4 = "events_v4.ev"; // EVIO version 4 file std::string fileNameEvio6 = "events_v6.ev"; // EVIO version 6 file std::string fileNameHipo = "events.hipo"; // HIPO format file - // Parameters for file writing (file split thresholds, etc.) - uint32_t maxRecordBytes = 1000000; // max bytes per record (e.g., ~1 MB) - uint32_t maxEventsPerRecord = 1000; // max number of events per record - uint32_t bufferBytes = 1000000; // internal buffer size in bytes - - // **1. Create writers for each format.** - // EVIO version 4 writer (using EventWriterV4) - EventWriterV4 writerV4(fileNameEvio4, // file path - "", "", // (directory, runType not used here) - 1, 0, // runNumber=1, splitNumber=0 (no file splitting) - maxRecordBytes, maxEventsPerRecord, - ByteOrder::ENDIAN_LOCAL, // use local endian byte order - xmlDictionary, // xml dictionary - true, false, // overwrite existing, no append - nullptr, 0, 0, // no “first event” provided - 1, 1, // stream id=1, starting block number=1 - bufferBytes); - - // EVIO version 6 writer (EventWriter) – outputs EVIO format by default​:contentReference[oaicite:0]{index=0} - EventWriter writerV6(fileNameEvio6, // file path - "", "", // (directory, runType) - 1, 0, // runNumber=1, no file splitting - maxRecordBytes, maxEventsPerRecord, - ByteOrder::ENDIAN_LOCAL, - xmlDictionary, // xml dictionary - true, false, // overwrite existing, no append - nullptr, 1, 0, 1, 1, // no first event, stream id=1, block=1 - Compressor::CompressionType::UNCOMPRESSED, - 0, 0, // no compression, so 0 threads and default level - bufferBytes); - - // HIPO format writer (also uses EventWriter, but with HIPO file header)​:contentReference[oaicite:1]{index=1} - // We enable HIPO by specifying a compression type (e.g., LZ4) – the EVIO library will - // then produce a HIPO file header (ID = 0x43455248 for "HIPO") instead of "EVIO"​:contentReference[oaicite:2]{index=2}. - EventWriter writerHipo(fileNameHipo, - "", "", - 1, 0, - maxRecordBytes, maxEventsPerRecord, - ByteOrder::ENDIAN_LOCAL, - xmlDictionary, // xml dictionary - true, false, // overwrite existing, no append - nullptr, 1, 0, 1, 1, - Compressor::CompressionType::LZ4, // use LZ4 compression to trigger HIPO format - 0, 0, - bufferBytes); - - // Random number generator for Gaussian (mean=0, sigma=0.1) - std::random_device rd; - std::mt19937 gen(rd()); - std::normal_distribution gauss(0.0, 0.1); + std::shared_ptr writerV4 = evioHelperObj().defaultEventWriterV4(); + std::shared_ptr writerV6 = evioHelperObj().defaultEventWriter(); + std::shared_ptr writerHipo = evioHelperObj().defaultEventWriterHIPO(); // **2. Loop over events and write each one.** @@ -94,23 +32,20 @@ int main(int argc, char** argv) { std::shared_ptr event = EvioBank::getInstance(1, DataType::FLOAT32, 1); // Fill the bank's float data (x, y, z, time) with 0.0 auto &floatData = event->getFloatData(); - floatData.assign(5, 0.0f); - floatData[0] = gauss(gen); - floatData[1] = gauss(gen); - floatData[2] = 0.; - floatData[3] = i*2.008f; // to mock up rf time + floatData.assign(4, 0.0f); + floatData = evioHelperObj().genXYZT(i); // generate pseudo x, y, z, time values event->updateFloatData(); // update internal length counters​:contentReference[oaicite:3]{index=3} // Write the event to each file format - writerV4.writeEvent(event); - writerV6.writeEvent(event); - writerHipo.writeEvent(event); + writerV4->writeEvent(event); + writerV6->writeEvent(event); + writerHipo->writeEvent(event); } // **3. Close all files to flush buffers.** - writerV4.close(); - writerV6.close(); - writerHipo.close(); + writerV4->close(); + writerV6->close(); + writerHipo->close(); std::cout << "Wrote " << nEvents << " events to EVIO4, EVIO6, and HIPO format files." << std::endl; return 0; From 9f2fe1882db7ac7e860e180e9745a0ecd8f27a8f Mon Sep 17 00:00:00 2001 From: jonzarling Date: Fri, 25 Apr 2025 11:58:56 -0500 Subject: [PATCH 09/56] now helper class works --- CMakeLists.txt | 2 ++ tutorials/EvioTestHelper.h | 42 +++++++++++------------ tutorials/WriteFilePseudoPhysicsEvent.cpp | 23 +++++-------- 3 files changed, 31 insertions(+), 36 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dc34ebee8..4b988071a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -159,6 +159,7 @@ set(CPP_HEADER_FILES src/libsrc++/StructureFinder.h src/libsrc++/eviocc.h src/test/TestBase.h + tutorials/EvioTestHelper.h ) set(CPP_LIB_FILES @@ -200,6 +201,7 @@ set(CPP_LIB_FILES src/libsrc++/EventBuilder.cpp src/libsrc++/CompactEventBuilder.cpp src/test/TestBase.cpp + tutorials/EvioTestHelper.h ) set(TEST diff --git a/tutorials/EvioTestHelper.h b/tutorials/EvioTestHelper.h index 514eeaa3c..26de0941d 100644 --- a/tutorials/EvioTestHelper.h +++ b/tutorials/EvioTestHelper.h @@ -34,11 +34,12 @@ using namespace evio; public: - explicit EvioTestHelper(); + // Constructor + explicit EvioTestHelper() {} std::shared_ptr defaultEventWriterV4() { return std::make_shared( - std::string(baseName+"_V4.evio"), + baseNameV4, directory, runType, runNumber, @@ -46,7 +47,7 @@ using namespace evio; maxRecordSize, maxEventCount, byteOrder, - xmlDictionary, + XMLdictionary, overWriteOK, append, firstEvent, @@ -60,11 +61,8 @@ using namespace evio; } std::shared_ptr defaultEventWriter() { - - EventWriter myWriter(); - return std::make_shared( - std::string(baseName+"_V6.ev"), + baseNameV6, directory, runType, runNumber, @@ -72,7 +70,7 @@ using namespace evio; maxRecordSize, maxEventCount, byteOrder, - xmlDictionary, + XMLdictionary, overWriteOK, append, firstEvent, @@ -88,7 +86,7 @@ using namespace evio; } std::shared_ptr defaultEventWriterHIPO() { return std::make_shared( - std::string(baseName+"_HIPO_LZ4.ev"), + baseNameHIPO, directory, runType, runNumber, @@ -96,7 +94,7 @@ using namespace evio; maxRecordSize, maxEventCount, byteOrder, - xmlDictionary, + XMLdictionary, overWriteOK, append, firstEvent, @@ -112,7 +110,7 @@ using namespace evio; } std::vector genXYZT(int i) { - std::vector x4(4); + std::vector x4(5); // 5th entry for pyevio debugging x4[0] = gauss(gen); x4[1] = gauss(gen); x4[2] = 0.0f; @@ -127,7 +125,18 @@ using namespace evio; std::mt19937 gen{ my_rd() }; std::normal_distribution gauss{0.0f, 0.1f}; - std::string dictionary = R"( + + std::string baseNameV4 = "testEventsV4.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + std::string baseNameV6 = "testEventsV6.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + std::string baseNameHIPO = "testEventsHIPO.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + const std::string directory = ""; // directory in which file is to be placed + const std::string runType = ""; // name of run type configuration to be used in naming files + uint32_t runNumber = 1; + uint64_t split = 0; // if < 1, do not split file, write to only one file of unlimited size. Else this is max size in bytes to make a file before closing it and starting writing another. + uint32_t maxRecordSize = 33554432; // (32 MiB) max number of uncompressed data bytes each record can hold. Value of < 8MB results in default of 8MB. The size of the record will not be larger than this size unless a single event itself is larger + uint32_t maxEventCount = 10000; // max number of events each record can hold. Value <= O means use default (1M). + const ByteOrder & byteOrder = ByteOrder::nativeOrder(); + const std::string XMLdictionary = R"( @@ -140,15 +149,6 @@ using namespace evio; )"; - const std::string baseName = "testEvents"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. - const std::string directory = ""; // directory in which file is to be placed - const std::string runType = ""; // name of run type configuration to be used in naming files - uint32_t runNumber = 1; - uint64_t split = 0; // if < 1, do not split file, write to only one file of unlimited size. Else this is max size in bytes to make a file before closing it and starting writing another. - uint32_t maxRecordSize = 33554432; // (32 MiB) max number of uncompressed data bytes each record can hold. Value of < 8MB results in default of 8MB. The size of the record will not be larger than this size unless a single event itself is larger - uint32_t maxEventCount = 10000; // max number of events each record can hold. Value <= O means use default (1M). - const ByteOrder & byteOrder = ByteOrder::nativeOrder(); - const std::string & xmlDictionary = ""; bool overWriteOK = true; bool append = false; std::shared_ptr< EvioBank >firstEvent = nullptr; // The first event written into each file (after any dictionary) including all split files; may be null. Useful for adding common, static info into each split file diff --git a/tutorials/WriteFilePseudoPhysicsEvent.cpp b/tutorials/WriteFilePseudoPhysicsEvent.cpp index 517705f65..82a705428 100644 --- a/tutorials/WriteFilePseudoPhysicsEvent.cpp +++ b/tutorials/WriteFilePseudoPhysicsEvent.cpp @@ -2,7 +2,6 @@ #include #include -#include "eviocc.h" #include "EvioTestHelper.h" // EVIO C++ API (EVIO 6 main branch) using namespace evio; @@ -13,27 +12,20 @@ int main(int argc, char** argv) { return 1; } int nEvents = std::stoi(argv[1]); + std::cout << "Writing " << nEvents << " events to files..." << std::endl; + EvioTestHelper* evioHelperObj = new EvioTestHelper(); - EvioTestHelper evioHelperObj(); + std::shared_ptr writerV4 = evioHelperObj->defaultEventWriterV4(); + std::shared_ptr writerV6 = evioHelperObj->defaultEventWriter(); + std::shared_ptr writerHipo = evioHelperObj->defaultEventWriterHIPO(); - // Output file names for each format - std::string fileNameEvio4 = "events_v4.ev"; // EVIO version 4 file - std::string fileNameEvio6 = "events_v6.ev"; // EVIO version 6 file - std::string fileNameHipo = "events.hipo"; // HIPO format file - std::shared_ptr writerV4 = evioHelperObj().defaultEventWriterV4(); - std::shared_ptr writerV6 = evioHelperObj().defaultEventWriter(); - std::shared_ptr writerHipo = evioHelperObj().defaultEventWriterHIPO(); - - - // **2. Loop over events and write each one.** for (int i = 0; i < nEvents; ++i) { // Create an event as a bank containing four 32-bit floats std::shared_ptr event = EvioBank::getInstance(1, DataType::FLOAT32, 1); // Fill the bank's float data (x, y, z, time) with 0.0 auto &floatData = event->getFloatData(); - floatData.assign(4, 0.0f); - floatData = evioHelperObj().genXYZT(i); // generate pseudo x, y, z, time values + floatData = evioHelperObj->genXYZT(i); // generate pseudo x, y, z, time values event->updateFloatData(); // update internal length counters​:contentReference[oaicite:3]{index=3} // Write the event to each file format @@ -42,11 +34,12 @@ int main(int argc, char** argv) { writerHipo->writeEvent(event); } - // **3. Close all files to flush buffers.** + // Close the writers, flush buffers writerV4->close(); writerV6->close(); writerHipo->close(); std::cout << "Wrote " << nEvents << " events to EVIO4, EVIO6, and HIPO format files." << std::endl; + delete evioHelperObj; return 0; } From 4aad9fba8f8f12b4d61061dfe0c6a9bb509a8495 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Mon, 28 Apr 2025 12:16:42 -0500 Subject: [PATCH 10/56] Add EventBuilder and CompactEventBuilder tests --- CMakeLists.txt | 4 +- tutorials/EvioTestHelper.h | 2 +- tutorials/WritePseudoPhys_builder.cpp | 52 +++++++++++++++++++ ...sEvent.cpp => WritePseudoPhys_compact.cpp} | 9 ++-- tutorials/WritePseudoPhys_simple.cpp | 42 +++++++++++++++ 5 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 tutorials/WritePseudoPhys_builder.cpp rename tutorials/{WriteFilePseudoPhysicsEvent.cpp => WritePseudoPhys_compact.cpp} (95%) create mode 100644 tutorials/WritePseudoPhys_simple.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b988071a..e1821e197 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -227,7 +227,9 @@ set(TEST # Jon added programs below src/test/BigFileWrite.cpp src/test/BigFileWritePrimitive.cpp - tutorials/WriteFilePseudoPhysicsEvent.cpp + tutorials/WritePseudoPhys_simple.cpp + tutorials/WritePseudoPhys_builder.cpp + tutorials/WritePseudoPhys_compact.cpp tutorials/WriteFilePseudoPhysicsEventExtended.cpp tutorials/PrintXMLDict.cpp tutorials/EVIO_v4_to_v6.cpp diff --git a/tutorials/EvioTestHelper.h b/tutorials/EvioTestHelper.h index 26de0941d..766dd006f 100644 --- a/tutorials/EvioTestHelper.h +++ b/tutorials/EvioTestHelper.h @@ -110,7 +110,7 @@ using namespace evio; } std::vector genXYZT(int i) { - std::vector x4(5); // 5th entry for pyevio debugging + std::vector x4(5); // 5th entry for pyevio bugfix x4[0] = gauss(gen); x4[1] = gauss(gen); x4[2] = 0.0f; diff --git a/tutorials/WritePseudoPhys_builder.cpp b/tutorials/WritePseudoPhys_builder.cpp new file mode 100644 index 000000000..90dd3371b --- /dev/null +++ b/tutorials/WritePseudoPhys_builder.cpp @@ -0,0 +1,52 @@ +#include "EvioTestHelper.h" // EVIO C++ API (EVIO 6 main branch) + +using namespace evio; + +int main(int argc, char* argv[]) { + + // Boilerplate + if (argc != 2) { + std::cerr << "Usage: " << argv[0] << " \n"; + return 1; + } + int nEvents = std::stoi(argv[1]); + std::cout << "Writing " << nEvents << " events to files..." << std::endl; + EvioTestHelper* evioHelperObj = new EvioTestHelper(); + + std::shared_ptr writerV4 = evioHelperObj->defaultEventWriterV4(); + std::shared_ptr writerV6 = evioHelperObj->defaultEventWriter(); + std::shared_ptr writerHipo = evioHelperObj->defaultEventWriterHIPO(); + + for (int i = 0; i < nEvents; ++i) { + + // Build a new event (top-level bank) with tag=1, type=BANK, num=1 + //------------------------------------- + uint16_t tag = 1; + uint8_t num = 1; + EventBuilder builder(tag, DataType::BANK, num); + auto floatVec = evioHelperObj->genXYZT(i); // generate pseudo x, y, z, time values + + // Now to start defining event + std::shared_ptr event = builder.getEvent(); + + // THE OVERBANK + // First child of event = bank of banks + auto bankBanks = EvioBank::getInstance(tag+1, DataType::BANK, num+1); + builder.addChild(event, bankBanks); + + // (SUB)BANK 1 OF 1 + // Create first (& only) child of bank of banks = bank of floats + auto bankFloats = EvioBank::getInstance(tag+11, DataType::FLOAT32, num+11); + // Write our data into bank + builder.setFloatData(bankFloats, floatVec.data(), floatVec.size()); + builder.addChild(bankBanks, bankFloats); + + // Write the completed event to file + writerV6->writeEvent(event); + } + + writerV6->close(); // close file writer (flush remaining data)​:contentReference[oaicite:6]{index=6} + std::cout << "Wrote " << nEvents << " events to file." << std::endl; + return 0; + +} diff --git a/tutorials/WriteFilePseudoPhysicsEvent.cpp b/tutorials/WritePseudoPhys_compact.cpp similarity index 95% rename from tutorials/WriteFilePseudoPhysicsEvent.cpp rename to tutorials/WritePseudoPhys_compact.cpp index 82a705428..61f0ac05e 100644 --- a/tutorials/WriteFilePseudoPhysicsEvent.cpp +++ b/tutorials/WritePseudoPhys_compact.cpp @@ -1,13 +1,11 @@ -#include -#include -#include - #include "EvioTestHelper.h" // EVIO C++ API (EVIO 6 main branch) using namespace evio; int main(int argc, char** argv) { - if (argc < 2) { + + // Boilerplate + if (argc != 2) { std::cerr << "Usage: " << argv[0] << " \n"; return 1; } @@ -19,7 +17,6 @@ int main(int argc, char** argv) { std::shared_ptr writerV6 = evioHelperObj->defaultEventWriter(); std::shared_ptr writerHipo = evioHelperObj->defaultEventWriterHIPO(); - for (int i = 0; i < nEvents; ++i) { // Create an event as a bank containing four 32-bit floats std::shared_ptr event = EvioBank::getInstance(1, DataType::FLOAT32, 1); diff --git a/tutorials/WritePseudoPhys_simple.cpp b/tutorials/WritePseudoPhys_simple.cpp new file mode 100644 index 000000000..61f0ac05e --- /dev/null +++ b/tutorials/WritePseudoPhys_simple.cpp @@ -0,0 +1,42 @@ +#include "EvioTestHelper.h" // EVIO C++ API (EVIO 6 main branch) + +using namespace evio; + +int main(int argc, char** argv) { + + // Boilerplate + if (argc != 2) { + std::cerr << "Usage: " << argv[0] << " \n"; + return 1; + } + int nEvents = std::stoi(argv[1]); + std::cout << "Writing " << nEvents << " events to files..." << std::endl; + EvioTestHelper* evioHelperObj = new EvioTestHelper(); + + std::shared_ptr writerV4 = evioHelperObj->defaultEventWriterV4(); + std::shared_ptr writerV6 = evioHelperObj->defaultEventWriter(); + std::shared_ptr writerHipo = evioHelperObj->defaultEventWriterHIPO(); + + for (int i = 0; i < nEvents; ++i) { + // Create an event as a bank containing four 32-bit floats + std::shared_ptr event = EvioBank::getInstance(1, DataType::FLOAT32, 1); + // Fill the bank's float data (x, y, z, time) with 0.0 + auto &floatData = event->getFloatData(); + floatData = evioHelperObj->genXYZT(i); // generate pseudo x, y, z, time values + event->updateFloatData(); // update internal length counters​:contentReference[oaicite:3]{index=3} + + // Write the event to each file format + writerV4->writeEvent(event); + writerV6->writeEvent(event); + writerHipo->writeEvent(event); + } + + // Close the writers, flush buffers + writerV4->close(); + writerV6->close(); + writerHipo->close(); + + std::cout << "Wrote " << nEvents << " events to EVIO4, EVIO6, and HIPO format files." << std::endl; + delete evioHelperObj; + return 0; +} From a6bc26140944a982ec1c1a89dcf05a275b4490e6 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Tue, 29 Apr 2025 10:23:50 -0500 Subject: [PATCH 11/56] Update compact writer test --- tutorials/WritePseudoPhys_compact.cpp | 39 +++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tutorials/WritePseudoPhys_compact.cpp b/tutorials/WritePseudoPhys_compact.cpp index 61f0ac05e..3dfb1b40c 100644 --- a/tutorials/WritePseudoPhys_compact.cpp +++ b/tutorials/WritePseudoPhys_compact.cpp @@ -18,6 +18,45 @@ int main(int argc, char** argv) { std::shared_ptr writerHipo = evioHelperObj->defaultEventWriterHIPO(); for (int i = 0; i < nEvents; ++i) { + + + // Data to write stored in these arrays + // int8_t byteArray[8] = {0, 1, 2, 3, 4, 5, 6, 7}; + std::vector floatArr = evioHelperObj->genXYZT(i); // generate pseudo x, y, z, time values; + // Create the buffer to hold everything + ByteBuffer buffer = ByteBuffer(8192); + // Build event (bank of banks) with CompactEventBuilder object + int tag = 1, num = 1; + CompactEventBuilder* builder = new CompactEventBuilder(8192,ByteOrder::nativeOrder()); + //------------------------------------- + // add top/event level bank of banks + builder->openBank(tag, DataType::BANK, num); + // add bank of banks to event + builder->openBank(tag+1, DataType::BANK, num+1); + // add bank of ints to bank of banks + builder->openBank(tag+11, DataType::FLOAT32, num+11); + // done with bank of ints, go to enclosing structure + builder->addFloatData(floatArr.data(),floatArr.size()); + + builder->closeStructure(); + // done with bank of banks + builder->closeStructure(); + builder->closeAll(); + // There is no way to remove any structures + // Get ready-to-read buffer from builder + // (this sets the proper pos and lim in buffer) + std::shared_ptr& bytebbuffer = builder->getBuffer(); + + + + + + + + + + + // Create an event as a bank containing four 32-bit floats std::shared_ptr event = EvioBank::getInstance(1, DataType::FLOAT32, 1); // Fill the bank's float data (x, y, z, time) with 0.0 From 3ac628d38b1952f11c81e281da94b143e8137146 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Tue, 29 Apr 2025 10:49:02 -0500 Subject: [PATCH 12/56] working on fix --- src/test/ReadWriteV4Test.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/test/ReadWriteV4Test.cpp b/src/test/ReadWriteV4Test.cpp index 42bdd6924..f11ff91d2 100644 --- a/src/test/ReadWriteV4Test.cpp +++ b/src/test/ReadWriteV4Test.cpp @@ -253,7 +253,7 @@ namespace evio { std::cout << "\n Print out events (includes first event if evio version 4) :" << std::endl; -/* for (uint32_t i = 0; i < evCount2; i++) { + for (uint32_t i = 0; i < evCount2; i++) { // The "first event" is just the first event in the list (not treated specially) std::cout << " scanned event #" << (i+1) << " :" << std::endl; std::shared_ptr compactNode = reader1.getScannedEvent(i + 1); @@ -271,7 +271,7 @@ namespace evio { " Event #" + std::to_string(i+1)); } } - */ } + } catch (EvioException &e) { std::cout << "PROBLEM: " << e.what(); } @@ -288,6 +288,7 @@ namespace evio { std::vector dataVec; std::vector dataVec0; + try { // TODO: Something WRONG with the parsing!!! @@ -303,6 +304,8 @@ namespace evio { std::cout << "\n Print out events (includes first event if evio version 4) :" << std::endl; + std::cout << "Starting reader for " << reader1.getEventCount() << " events..." << std::endl; + for (uint32_t i = 0; i < evCount2; i++) { std::shared_ptr ev = reader1.parseEvent(i + 1); std::cout << " got & parsed ev " << (i+1) << std::endl; @@ -311,7 +314,12 @@ namespace evio { dataVec0 = ev->getRawBytes(); } //std::shared_ptr evt = reader1.parseNextEvent(); + + std::cout << "GOT THIS FAR 1" << std::endl; } + std::cout << "GOT THIS FAR 2" << std::endl; + + // This has the same output as above // int j=0; // std::shared_ptr evt; From 637e27f1cbabd011b9b47a8da0642332abb77cbd Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Thu, 1 May 2025 12:04:24 -0500 Subject: [PATCH 13/56] First-pass skeleton of CLAS file reader --- .gitignore | 3 +- CMakeLists.txt | 1 + src/test/ReadWriteV4Test.cpp | 740 +++++++++++++++++------------------ tutorials/ReadCLASFile.cpp | 87 ++++ 4 files changed, 455 insertions(+), 376 deletions(-) create mode 100644 tutorials/ReadCLASFile.cpp diff --git a/.gitignore b/.gitignore index bba402351..99172ea67 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ # ignore all files/dirs beginning with _ _* # ignore any .evio, .ev, or .hipo extension files -*.evio +*.evio* *.ev *.hipo *.dat @@ -20,6 +20,7 @@ cmake-* cmake_install.cmake coda.pyc build/ +build_old/ jbuild/ lib/ bin/ diff --git a/CMakeLists.txt b/CMakeLists.txt index e1821e197..32adbe6cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -234,6 +234,7 @@ set(TEST tutorials/PrintXMLDict.cpp tutorials/EVIO_v4_to_v6.cpp tutorials/ConvertFormats.cpp + tutorials/ReadCLASFile.cpp ) set(TESTC diff --git a/src/test/ReadWriteV4Test.cpp b/src/test/ReadWriteV4Test.cpp index f11ff91d2..993c3cee3 100644 --- a/src/test/ReadWriteV4Test.cpp +++ b/src/test/ReadWriteV4Test.cpp @@ -13,380 +13,370 @@ -#include -#include -#include -#include - - -#include "TestBase.h" - - -using namespace std; - - -namespace evio { - - - class ReadWriteTest : public TestBase { - - - public: - - - - std::shared_ptr generateEvioBank(ByteOrder & order, uint16_t tag, uint8_t num) { - // Event, traditional bank of banks - EventBuilder builder(tag, DataType::BANK, num); - auto ev = builder.getEvent(); - - // add a bank of doubles - auto bank1 = EvioBank::getInstance(22, DataType::DOUBLE64, 0); - double dData[1000]; - for (int i = 0; i < 1000; i++) { - dData[i] = i + 1.; - } - builder.appendDoubleData(bank1, dData, 1000); - cout << " generate Evio Bank, bank1 len = " << bank1->getTotalBytes() << endl; - builder.addChild(ev, bank1); - cout << " generate Evio Bank, ev len = " << ev->getTotalBytes() << endl; - - return static_cast>(ev); - } - - - - void writeFile(string finalFilename, uint16_t tag, uint8_t num) { - - std::cout << std::endl; - std::cout << "--------------------------------------------" << std::endl; - std::cout << "---------- Write to file --------------" << std::endl; - std::cout << "--------------------------------------------" << std::endl; - - ByteOrder outputOrder = ByteOrder::ENDIAN_LITTLE; - - // Create a "first event" - uint32_t firstEventData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - uint32_t firstEventDataLen = 10; - EventBuilder builder(1, DataType::UINT32, 2); - std::shared_ptr firstEvent = builder.getEvent(); - builder.appendUIntData(firstEvent, firstEventData, firstEventDataLen); - //auto firstBank = static_cast>(firstEvent); - - std::string directory; - std::string runType; - - // Create files - EventWriterV4 writer(finalFilename, directory, runType, 1, 0, - EventWriterV4::DEFAULT_BLOCK_SIZE, - EventWriterV4::DEFAULT_BLOCK_COUNT, - outputOrder, dictionary, - true, false, - firstEvent); - - -// EventWriterV4(std::string & baseName, -// const std::string & directory, const std::string & runType, -// uint32_t runNumber = 1, uint64_t split = 0, -// uint32_t maxBlockSize = DEFAULT_BLOCK_SIZE, -// uint32_t maxEventCount = DEFAULT_BLOCK_COUNT, -// const ByteOrder & byteOrder = ByteOrder::nativeOrder(), -// const std::string & xmlDictionary = "", -// bool overWriteOK = true, bool append = false, -// std::shared_ptr firstEvent = nullptr, -// uint32_t streamId = 0, uint32_t splitNumber = 0, -// uint32_t splitIncrement = 1, uint32_t streamCount = 1, -// uint32_t bufferSize = DEFAULT_BUFFER_SIZE, -// std::bitset<24> *bitInfo = nullptr); - - - // Create an event with lots of stuff in it - auto evioDataBuf = createCompactEventBuffer(tag, num, outputOrder); - - // Create node from this buffer - std::shared_ptr node = EvioNode::extractEventNode(evioDataBuf,0,0,0); - - // Create EvioBank - std::shared_ptr bank = generateEvioBank(outputOrder, tag, num); - - // write as buffer - writer.writeEvent(evioDataBuf, false); - cout << " Wrote evio buffer, len = " << evioDataBuf->limit() << endl; - - // write as node - writer.writeEvent(node, false); - cout << " Wrote evio node, total bytes = " << node->getTotalBytes() << endl; - - // write as EvioBank - writer.writeEvent(bank); - cout << " Wrote evio bank, total bytes = " << bank->getTotalBytes() << endl; - cout << " Wrote evio bank, header len in bytes = " << 4*(bank->getHeader()->getLength() + 1) << endl; - - writer.close(); - cout << "Finished writing file " << finalFilename << " now read it" << endl; - - //Util::printBytes(finalFilename, 0, 2000, "File bytes"); - } - - - void readFile(string finalFilename) { - - std::cout << std::endl; - std::cout << "--------------------------------------------" << std::endl; - std::cout << "---------- Read from file --------------" << std::endl; - std::cout << "--------------------------------------------" << std::endl; - - EvioReader reader(finalFilename); - ByteOrder & order = reader.getByteOrder(); - - cout << "Read in file " << finalFilename << " of byte order " << order.getName() << endl; - int32_t evCount = reader.getEventCount(); - cout << "Got " << evCount << " events" << endl; - - string dict = reader.getDictionaryXML(); - if (dict.empty()) { - cout << "\nNo dictionary" << endl; - } - else { - cout << "\nGot dictionary:\n" << dict << endl; - } - - auto pFE = reader.getFirstEvent(); - if (pFE != nullptr) { - cout << "\nGot first Event:\n" << pFE->toString() << endl << endl; - } - else { - cout << "\nNo first event" << endl; - } - - cout << "Print out regular events:" << endl; - - for (int i=0; i < evCount; i++) { - auto ev = reader.getEvent(i+1); - cout << "\nEvent" << (i+1) << ":\n" << ev->toString() << endl; - } - } - - - - void writeAndReadBuffer(uint16_t tag, uint8_t num) { - - std::cout << std::endl; - std::cout << "--------------------------------------------" << std::endl; - std::cout << "---------- Write to buf --------------" << std::endl; - std::cout << "--------------------------------------------" << std::endl; - - ByteOrder order = ByteOrder::ENDIAN_LITTLE; - std::shared_ptr buffer = std::make_shared(200000); - buffer->order(order); - - // Create a "first event" - int firstEventData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - EventBuilder builder(1, DataType::INT32, 2); - std::shared_ptr firstEv = builder.getEvent(); - try { - builder.setIntData(firstEv, firstEventData, 10); - } - catch (EvioException &e) {/* never happen */} - - bool append = false; - // Allow only 2 events per block to test using multiple blocks - int blockCount = 20000; - - try { - EventWriterV4 writer( - buffer, - EventWriterV4::DEFAULT_BLOCK_SIZE, - blockCount, - dictionary, nullptr, 0, - 1, append, firstEv); - - // Create an event in buffer form with lots of stuff in it - std::shared_ptr evioDataBuf = createCompactEventBuffer(tag, num, order); - // Create same event as EvioEvent object - std::shared_ptr evioEv = createEventBuilderEvent(tag, num); - // Create node from this buffer - std::shared_ptr node = EvioNode::extractEventNode(evioDataBuf, 0, 0, 0); - - - // write as buffer - writer.writeEvent(evioDataBuf, false); - // write as EvioEvent - writer.writeEvent(evioEv, false); - // write as node - writer.writeEvent(node, false); - - writer.close(); - // Get ready-to-read buffer - buffer = writer.getByteBuffer(); - - } - catch (EvioException &e) { - std::cout << "PROBLEM: " << e.what(); - } - - std::shared_ptr copy = ByteBuffer::copyBuffer(buffer); - std::shared_ptr copy2 = ByteBuffer::copyBuffer(buffer); - - - // Reader cannot be used, it only works on evio version 6 files and buffers. - // Reader reader(buffer); - - - - std::cout << "--------------------------------------------" << std::endl; - std::cout << "---------- EvioCompactReader -----------" << std::endl; - std::cout << "--------------------------------------------" << std::endl; - - std::shared_ptr dataBuf0 = nullptr; - - try { - EvioCompactReader reader1(copy); - - uint32_t evCount2 = reader1.getEventCount(); - std::cout << " Got " << evCount2 << " events" << std::endl; - - std::string dict2 = reader1.getDictionaryXML(); - std::cout << " Got dictionary = \n" << dict2 << std::endl; - - // Compact reader does not deal with first events, so skip over it - - std::cout << "\n Print out events (includes first event if evio version 4) :" << std::endl; - + #include + #include + #include + #include + + + #include "TestBase.h" + + + using namespace std; + + + namespace evio { + + + class ReadWriteTest : public TestBase { + + + public: + + + + std::shared_ptr generateEvioBank(ByteOrder & order, uint16_t tag, uint8_t num) { + // Event, traditional bank of banks + EventBuilder builder(tag, DataType::BANK, num); + auto ev = builder.getEvent(); + + // add a bank of doubles + auto bank1 = EvioBank::getInstance(22, DataType::DOUBLE64, 0); + double dData[1000]; + for (int i = 0; i < 1000; i++) { + dData[i] = i + 1.; + } + builder.appendDoubleData(bank1, dData, 1000); + cout << " generate Evio Bank, bank1 len = " << bank1->getTotalBytes() << endl; + builder.addChild(ev, bank1); + cout << " generate Evio Bank, ev len = " << ev->getTotalBytes() << endl; + + return static_cast>(ev); + } + + + + void writeFile(string finalFilename, uint16_t tag, uint8_t num) { + + std::cout << std::endl; + std::cout << "--------------------------------------------" << std::endl; + std::cout << "---------- Write to file --------------" << std::endl; + std::cout << "--------------------------------------------" << std::endl; + + ByteOrder outputOrder = ByteOrder::ENDIAN_LITTLE; + + // Create a "first event" + uint32_t firstEventData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + uint32_t firstEventDataLen = 10; + EventBuilder builder(1, DataType::UINT32, 2); + std::shared_ptr firstEvent = builder.getEvent(); + builder.appendUIntData(firstEvent, firstEventData, firstEventDataLen); + //auto firstBank = static_cast>(firstEvent); + + std::string directory; + std::string runType; + + // Create files + EventWriterV4 writer(finalFilename, directory, runType, 1, 0, + EventWriterV4::DEFAULT_BLOCK_SIZE, + EventWriterV4::DEFAULT_BLOCK_COUNT, + outputOrder, dictionary, + true, false, + firstEvent); + + + // EventWriterV4(std::string & baseName, + // const std::string & directory, const std::string & runType, + // uint32_t runNumber = 1, uint64_t split = 0, + // uint32_t maxBlockSize = DEFAULT_BLOCK_SIZE, + // uint32_t maxEventCount = DEFAULT_BLOCK_COUNT, + // const ByteOrder & byteOrder = ByteOrder::nativeOrder(), + // const std::string & xmlDictionary = "", + // bool overWriteOK = true, bool append = false, + // std::shared_ptr firstEvent = nullptr, + // uint32_t streamId = 0, uint32_t splitNumber = 0, + // uint32_t splitIncrement = 1, uint32_t streamCount = 1, + // uint32_t bufferSize = DEFAULT_BUFFER_SIZE, + // std::bitset<24> *bitInfo = nullptr); + + + // Create an event with lots of stuff in it + auto evioDataBuf = createCompactEventBuffer(tag, num, outputOrder); + + // Create node from this buffer + std::shared_ptr node = EvioNode::extractEventNode(evioDataBuf,0,0,0); + + // Create EvioBank + std::shared_ptr bank = generateEvioBank(outputOrder, tag, num); + + // write as buffer + writer.writeEvent(evioDataBuf, false); + cout << " Wrote evio buffer, len = " << evioDataBuf->limit() << endl; + + // write as node + writer.writeEvent(node, false); + cout << " Wrote evio node, total bytes = " << node->getTotalBytes() << endl; + + // write as EvioBank + writer.writeEvent(bank); + cout << " Wrote evio bank, total bytes = " << bank->getTotalBytes() << endl; + cout << " Wrote evio bank, header len in bytes = " << 4*(bank->getHeader()->getLength() + 1) << endl; + + writer.close(); + cout << "Finished writing file " << finalFilename << " now read it" << endl; + + //Util::printBytes(finalFilename, 0, 2000, "File bytes"); + } + + + void readFile(string finalFilename) { + + std::cout << std::endl; + std::cout << "--------------------------------------------" << std::endl; + std::cout << "---------- Read from file --------------" << std::endl; + std::cout << "--------------------------------------------" << std::endl; + + EvioReader reader(finalFilename); + ByteOrder & order = reader.getByteOrder(); + + cout << "Read in file " << finalFilename << " of byte order " << order.getName() << endl; + int32_t evCount = reader.getEventCount(); + cout << "Got " << evCount << " events" << endl; + + string dict = reader.getDictionaryXML(); + if (dict.empty()) { + cout << "\nNo dictionary" << endl; + } + else { + cout << "\nGot dictionary:\n" << dict << endl; + } + + auto pFE = reader.getFirstEvent(); + if (pFE != nullptr) { + cout << "\nGot first Event:\n" << pFE->toString() << endl << endl; + } + else { + cout << "\nNo first event" << endl; + } + + cout << "Print out regular events:" << endl; + + for (int i=0; i < evCount; i++) { + auto ev = reader.getEvent(i+1); + cout << "\nEvent" << (i+1) << ":\n" << ev->toString() << endl; + } + } + + + + void writeAndReadBuffer(uint16_t tag, uint8_t num) { + + std::cout << std::endl; + std::cout << "--------------------------------------------" << std::endl; + std::cout << "---------- Write to buf --------------" << std::endl; + std::cout << "--------------------------------------------" << std::endl; + + ByteOrder order = ByteOrder::ENDIAN_LITTLE; + std::shared_ptr buffer = std::make_shared(200000); + buffer->order(order); + + // Create a "first event" + int firstEventData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + EventBuilder builder(1, DataType::INT32, 2); + std::shared_ptr firstEv = builder.getEvent(); + try { + builder.setIntData(firstEv, firstEventData, 10); + } + catch (EvioException &e) {/* never happen */} + + bool append = false; + // Allow only 2 events per block to test using multiple blocks + int blockCount = 20000; + + try { + EventWriterV4 writer( + buffer, + EventWriterV4::DEFAULT_BLOCK_SIZE, + blockCount, + dictionary, nullptr, 0, + 1, append, firstEv); + + // Create an event in buffer form with lots of stuff in it + std::shared_ptr evioDataBuf = createCompactEventBuffer(tag, num, order); + // Create same event as EvioEvent object + std::shared_ptr evioEv = createEventBuilderEvent(tag, num); + // Create node from this buffer + std::shared_ptr node = EvioNode::extractEventNode(evioDataBuf, 0, 0, 0); + + + // write as buffer + writer.writeEvent(evioDataBuf, false); + // write as EvioEvent + writer.writeEvent(evioEv, false); + // write as node + writer.writeEvent(node, false); + + writer.close(); + // Get ready-to-read buffer + buffer = writer.getByteBuffer(); + + } + catch (EvioException &e) { + std::cout << "PROBLEM: " << e.what(); + } + + std::shared_ptr copy = ByteBuffer::copyBuffer(buffer); + std::shared_ptr copy2 = ByteBuffer::copyBuffer(buffer); + + + // Reader cannot be used, it only works on evio version 6 files and buffers. + // Reader reader(buffer); + + + + std::cout << "--------------------------------------------" << std::endl; + std::cout << "---------- EvioCompactReader -----------" << std::endl; + std::cout << "--------------------------------------------" << std::endl; + + std::shared_ptr dataBuf0 = nullptr; + + try { + EvioCompactReader reader1(copy); + + uint32_t evCount2 = reader1.getEventCount(); + std::cout << " Got " << evCount2 << " events" << std::endl; + + std::string dict2 = reader1.getDictionaryXML(); + std::cout << " Got dictionary = \n" << dict2 << std::endl; + + // Compact reader does not deal with first events, so skip over it + + std::cout << "\n Print out events (includes first event if evio version 4) :" << std::endl; + for (uint32_t i = 0; i < evCount2; i++) { - // The "first event" is just the first event in the list (not treated specially) - std::cout << " scanned event #" << (i+1) << " :" << std::endl; - std::shared_ptr compactNode = reader1.getScannedEvent(i + 1); - std::cout << " node ->\n " << compactNode->toString() << std::endl; - - std::shared_ptr dataBuf = std::make_shared(compactNode->getTotalBytes()); - std::cout << "GOT THIS FAR 1" << std::endl; - - compactNode->getStructureBuffer(dataBuf, true); - std::cout << "GOT THIS FAR 2" << std::endl; - - if (i == 0) { - dataBuf0 = dataBuf; - Util::printBytes(dataBuf, dataBuf->position(), dataBuf->remaining(), - " Event #" + std::to_string(i+1)); - } - } + // The "first event" is just the first event in the list (not treated specially) + std::cout << " scanned event #" << (i+1) << " :" << std::endl; + std::shared_ptr compactNode = reader1.getScannedEvent(i + 1); + std::cout << " node ->\n " << compactNode->toString() << std::endl; + + std::shared_ptr dataBuf = std::make_shared(compactNode->getTotalBytes()); + compactNode->getStructureBuffer(dataBuf, true); + + if (i == 0) { + dataBuf0 = dataBuf; + Util::printBytes(dataBuf, dataBuf->position(), dataBuf->remaining(), + " Event #" + std::to_string(i+1)); + } + } } - catch (EvioException &e) { - std::cout << "PROBLEM: " << e.what(); - } - - - std::cout << std::endl; - std::cout << "--------------------------------------------" << std::endl; - std::cout << "---------- EvioReader --------------" << std::endl; - std::cout << "--------------------------------------------" << std::endl; - - - bool unchanged = true; - size_t index = 0; - std::vector dataVec; - std::vector dataVec0; - - - try { - - // TODO: Something WRONG with the parsing!!! - EvioReader reader1(copy2); - - uint32_t evCount2 = reader1.getEventCount(); - std::cout << " Got " << evCount2 << " events" << std::endl; - - std::string dict2 = reader1.getDictionaryXML(); - std::cout << " Got dictionary = \n" << dict2 << std::endl; - - std::cout << "\n Got first event = " << reader1.hasFirstEvent() << std::endl; - - std::cout << "\n Print out events (includes first event if evio version 4) :" << std::endl; - - std::cout << "Starting reader for " << reader1.getEventCount() << " events..." << std::endl; - - for (uint32_t i = 0; i < evCount2; i++) { - std::shared_ptr ev = reader1.parseEvent(i + 1); - std::cout << " got & parsed ev " << (i+1) << std::endl; - std::cout << " event ->\n" << ev->toString() << std::endl; - if (i == 0) { - dataVec0 = ev->getRawBytes(); - } - //std::shared_ptr evt = reader1.parseNextEvent(); - - std::cout << "GOT THIS FAR 1" << std::endl; - } - std::cout << "GOT THIS FAR 2" << std::endl; - - -// This has the same output as above -// int j=0; -// std::shared_ptr evt; -// while ((evt = reader1.parseNextEvent()) != nullptr) { -// std::cout << " got & parsed ev " << (j+1) << std::endl; -// std::cout << " event ->\n" << evt->toString() << std::endl; -// if (j == 0) { -// dataVec0 = evt->getRawBytes(); -// } -// j++; -// } - - std::cout << " Comparing buffer data (lim = " << dataBuf0->limit() << ") with vector data (len = " << dataVec0.size() - << ")" << std::endl; - for (size_t i = 0; i < dataVec0.size(); i++) { - if ((/*data[i+8]*/ dataBuf0->array()[i + 8] != dataVec0[i]) && (i > 3)) { - unchanged = false; - index = i; - std::cout << " Compact reader different than EvioReader at byte #" << index << std::endl; - std::cout << showbase << hex << dataBuf0->array()[i + 8] << " changed to " << - dataVec0[i] << dec << std::endl; - break; - } - } - if (unchanged) { - std::cout << "First data EVENT same whether using EvioCompactReader or EvioReader!" << std::endl; - } - - } - catch (EvioException &e) { - std::cout << "PROBLEM: " << e.what(); - } - - - - } - - - }; - - -} - - - - -int main(int argc, char **argv) { - - - string filename_c = "./evioTest.c.evio"; - string filename_j = "./evioTest.java.evio"; - - evio::ReadWriteTest tester; - - tester.writeFile(filename_c, 1,1); - tester.readFile(filename_c); - -// std::ifstream file(filename_j); -// if (file) { -// tester.readFile(filename_j); -// } - - tester.writeAndReadBuffer(1,1); - - // Buffers ... - cout << endl << endl << "----------------------------------------" << endl << endl; - - return 0; -} - + catch (EvioException &e) { + std::cout << "PROBLEM: " << e.what(); + } + + + std::cout << std::endl; + std::cout << "--------------------------------------------" << std::endl; + std::cout << "---------- EvioReader --------------" << std::endl; + std::cout << "--------------------------------------------" << std::endl; + + + bool unchanged = true; + size_t index = 0; + std::vector dataVec; + std::vector dataVec0; + + try { + + // TODO: Something WRONG with the parsing!!! + EvioReader reader1(copy2); + + uint32_t evCount2 = reader1.getEventCount(); + std::cout << " Got " << evCount2 << " events" << std::endl; + + std::string dict2 = reader1.getDictionaryXML(); + std::cout << " Got dictionary = \n" << dict2 << std::endl; + + std::cout << "\n Got first event = " << reader1.hasFirstEvent() << std::endl; + + std::cout << "\n Print out events (includes first event if evio version 4) :" << std::endl; + + for (uint32_t i = 0; i < evCount2; i++) { + std::shared_ptr ev = reader1.parseEvent(i + 1); + std::cout << " got & parsed ev " << (i+1) << std::endl; + std::cout << " event ->\n" << ev->toString() << std::endl; + if (i == 0) { + dataVec0 = ev->getRawBytes(); + } + //std::shared_ptr evt = reader1.parseNextEvent(); + } + // This has the same output as above + // int j=0; + // std::shared_ptr evt; + // while ((evt = reader1.parseNextEvent()) != nullptr) { + // std::cout << " got & parsed ev " << (j+1) << std::endl; + // std::cout << " event ->\n" << evt->toString() << std::endl; + // if (j == 0) { + // dataVec0 = evt->getRawBytes(); + // } + // j++; + // } + + std::cout << " Comparing buffer data (lim = " << dataBuf0->limit() << ") with vector data (len = " << dataVec0.size() + << ")" << std::endl; + for (size_t i = 0; i < dataVec0.size(); i++) { + if ((/*data[i+8]*/ dataBuf0->array()[i + 8] != dataVec0[i]) && (i > 3)) { + unchanged = false; + index = i; + std::cout << " Compact reader different than EvioReader at byte #" << index << std::endl; + std::cout << showbase << hex << dataBuf0->array()[i + 8] << " changed to " << + dataVec0[i] << dec << std::endl; + break; + } + } + if (unchanged) { + std::cout << "First data EVENT same whether using EvioCompactReader or EvioReader!" << std::endl; + } + + } + catch (EvioException &e) { + std::cout << "PROBLEM: " << e.what(); + } + + + + } + + + }; + + + } + + + + + int main(int argc, char **argv) { + + + string filename_c = "./evioTest.c.evio"; + string filename_j = "./evioTest.java.evio"; + + evio::ReadWriteTest tester; + + tester.writeFile(filename_c, 1,1); + tester.readFile(filename_c); + + // std::ifstream file(filename_j); + // if (file) { + // tester.readFile(filename_j); + // } + + tester.writeAndReadBuffer(1,1); + + // Buffers ... + cout << endl << endl << "----------------------------------------" << endl << endl; + + return 0; + } + + \ No newline at end of file diff --git a/tutorials/ReadCLASFile.cpp b/tutorials/ReadCLASFile.cpp new file mode 100644 index 000000000..74e9932d1 --- /dev/null +++ b/tutorials/ReadCLASFile.cpp @@ -0,0 +1,87 @@ +#include +#include + +// Include EVIO6 C++ headers (adjust the include paths as needed for your installation) +#include "eviocc.h" // EVIO C++ API (EVIO 6 main branch) + +// Use the EVIO namespace for convenience +using namespace evio; + +int main(int argc, char* argv[]) { + if (argc < 2) { + std::cerr << "Usage: " << argv[0] << " " << std::endl; + return 1; + } + std::string filename = argv[1]; + + int maxEvents = 10; // Maximum number of events to read + + try { + // Open the EVIO6 file using EvioReader + EvioReaderV4 reader(filename); + + // Check for an embedded XML dictionary + if (reader.hasDictionaryXML()) { + // Retrieve the raw XML dictionary text + std::string xmlDict = reader.getDictionaryXML(); + // Print the XML dictionary to standard output + std::cout << xmlDict; + if (!xmlDict.empty() && xmlDict.back() != '\n') std::cout << std::endl; // ensure a newline at end, if not already present + } else { + // No dictionary present in the file + std::cout << "No XML dictionary found." << std::endl; + } + + std::cout << "EVIO Ver: " << reader.getEvioVersion() << std::endl; + std::cout << "File Size: " << reader.fileSize() << std::endl; + std::cout << "Event count: " << reader.getEventCount() << std::endl; + std::cout << "Has first event?: " << reader.hasFirstEvent() << std::endl; + + for (uint32_t i = 0; i < reader.getEventCount(); i++) { + if(i+1 >= maxEvents) { + std::cout << "Reached maximum number of events to read: " << maxEvents << std::endl; + break; + } + std::shared_ptr ev = reader.parseEvent(i+1); + std::cout << " got & parsed ev " << (i+1) << std::endl; + std::cout << " event ->\n" << ev->toString() << std::endl; + auto& dataVec = ev->getRawBytes(); + std::cout << "Event has tag = " << ev->getHeader()->getTag() << std::endl; + std::cout << "Event structure type = " << ev->getStructureType().toString() << std::endl; + std::vector< std::shared_ptr< BaseStructure > > & children = ev->getChildren(); + std::cout << "Event has " << children.size() << " children" << std::endl; + std::shared_ptr< BaseStructure > child1 = children[0]; + for (size_t j = 0; j < children.size(); j++) { + std::cout << "Child " << j << " tag = " << children[j]->getStructureType().toString() << std::endl; + std::cout << "NChildren: " << children[j]->getChildCount() << std::endl; + + for (size_t k = 0; k < children[j]->getChildCount(); k++) { + std::cout << "Child " << j << ", subchild " << k << " " << children[j]->getChildAt(k)->getStructureType().toString() << std::endl; + std::cout << "Subchild " << k << " datatype: " << children[j]->getChildAt(k)->getHeader()->getDataType().toString() << std::endl; + std::cout << "nsubchildren: " << children[j]->getChildAt(k)->getChildCount() << std::endl; + std::cout << "num items stored: " << children[j]->getChildAt(k)->getNumberDataItems() << std::endl; + if(children[j]->getChildAt(k)->getHeader()->getDataType() == DataType::UINT32) { + std::cout << "Data: "; + std::vector< uint32_t > data_uint_vec = children[j]->getChildAt(k)->getUIntData(); + for (size_t l = 0; l < data_uint_vec.size(); l++) { + std::cout << data_uint_vec[l] << " "; + } + std::cout << std::endl; + } + } + std::cout << std::endl; + } + + + // Util::printBytes(dataVec.data(), dataVec.size()," Event #" + std::to_string(i+1)); + } + + + + } catch (const std::exception& e) { + std::cerr << "Error: Unable to read EVIO file. " << e.what() << std::endl; + return 1; + } + + return 0; +} From 9701401e455268b5317fe66b4887fa4f350ecb08 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Thu, 15 May 2025 10:26:17 -0500 Subject: [PATCH 14/56] Some cleanup to CMakeLists.txt, shouldn't change any default behavior --- CMakeLists.txt | 267 +++--------------------- src/test/{TestBase.cpp => TestBase.cxx} | 0 tutorials/ReadCLASFile.cpp | 3 +- tutorials/ReadHIPO_clas_file.cpp | 48 +++++ 4 files changed, 82 insertions(+), 236 deletions(-) rename src/test/{TestBase.cpp => TestBase.cxx} (100%) create mode 100644 tutorials/ReadHIPO_clas_file.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 32adbe6cd..163ee49d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,54 +1,24 @@ -# To use this, do the following the first time: -# % mkdir build -# % cd build -# % cmake .. -DCMAKE_BUILD_TYPE=release -DMAKE_EXAMPLES=1 -# % make (install) -# -# To only build C libraries and executables, replace the 3rd command above with -# % cmake .. -DCMAKE_BUILD_TYPE=release -DC_ONLY=1 -# -# After doing this once can do the following to recompile -# % cd -# % cmake --build build (--target install) -# -# The installation will default to the CODA env variable if it's defined -# This can be overridden on command line (in build dir) with: -# % cmake -DCODA_INSTALL= .. -# % make install - -# This call must be placed BEFORE "project" command cmake_minimum_required(VERSION 3.22) - -# in cmake v 3.30 and later, new way to look for boost -if(POLICY CMP0167) - cmake_policy(SET CMP0167 NEW) -endif() - -project(evio VERSION 6.0) - -# This is better to be on the top of CMake! -include(GNUInstallDirs) - -# Allow users to set C++ standard via -DCMAKE_CXX_STANDARD -# Only default to C++17 if not already set -if(NOT CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 17) -endif() -set(CMAKE_CXX_STANDARD_REQUIRED True) +project(evio VERSION 6.0 LANGUAGES C CXX) + +# Build options (and defaults) +option(C_ONLY "SKIP building C++ library, build C only" OFF) +option(MAKE_EXAMPLES "Build example/test programs" OFF) +option(USE_FILESYSTEMLIB "Use C++17 instead of Boost" OFF) +option(DISRUPTOR_FETCH "Allow CMake to download Disruptor if not found" ON) +# C/C++ standard and build options +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_DEBUG_POSTFIX -dbg) add_compile_options(-Wall) +include(GNUInstallDirs) +include(FindPackageHandleStandardArgs) # find_package_handle_standard_args() + # Add custom find_package for Disruptor list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") -# Build examples by default, but allow disabling -option(MAKE_EXAMPLES "Build examples and tests" ON) -option(C_ONLY "Build only C library (no C++)" OFF) - -# Option to enable/disable usage of -option(USE_FILESYSTEMLIB "Use C++17 instead of Boost" OFF) - -# Later, when creating your library or executable, add a compile definition if it's ON +# Add a compile definition if USE_FILESYSTEMLIB set, for when creating your library or executable if(USE_FILESYSTEMLIB) add_compile_definitions(USE_FILESYSTEMLIB=1) endif() @@ -57,7 +27,7 @@ endif() set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib) set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin) -# Set architecture-related string for installation consistent with scons file +# Set architecture-related string for installation (consistent with scons) set(ARCH ${CMAKE_HOST_SYSTEM_NAME}-${CMAKE_HOST_SYSTEM_PROCESSOR}) message(STATUS "ARCH = " ${ARCH}) @@ -76,191 +46,14 @@ elseif (DEFINED ENV{CODA}) set(CMAKE_INSTALL_INCLUDEDIR $ENV{CODA}/common/include) message(STATUS "CMAKE_INSTALL_PREFIX reset to " ${CMAKE_INSTALL_PREFIX}) else() - # Always define installation, even without CODA, using the default CMAKE_INSTALL_PREFIX + # Use default CMAKE_INSTALL_PREFIX set(INSTALL_DIR_DEFINED 1) - message(STATUS "No CODA environment - will install to default location: ${CMAKE_INSTALL_PREFIX}") + message(STATUS "Installing to default location: ${CMAKE_INSTALL_PREFIX}") # Don't set CMAKE_INSTALL_PREFIX here - use the CMake default endif() -set(C_HEADER_FILES - src/libsrc/evio.h - src/libsrc/msinttypes.h -) - -set(C_LIB_FILES - src/libsrc/evio.c - src/libsrc/evioswap.c - src/libsrc/eviofmt.c - src/libsrc/eviofmtdump.c - src/libsrc/eviofmtswap.c - src/libsrc/eviocopy.c -) - -set(CPP_HEADER_FILES - src/libsrc++/FileWritingSupport.h - src/libsrc++/FileEventIndex.h - src/libsrc++/EvioException.h - src/libsrc++/ByteOrder.h - src/libsrc++/ByteBuffer.h - src/libsrc++/HeaderType.h - src/libsrc++/Compressor.h - src/libsrc++/FileHeader.h - src/libsrc++/RecordHeader.h - src/libsrc++/RecordInput.h - src/libsrc++/RecordOutput.h - src/libsrc++/Writer.h - src/libsrc++/WriterMT.h - src/libsrc++/EvioNode.h - src/libsrc++/DataType.h - src/libsrc++/StructureType.h - src/libsrc++/RecordNode.h - src/libsrc++/Reader.h - src/libsrc++/RecordSupply.h - src/libsrc++/RecordRingItem.h - src/libsrc++/Util.h - src/libsrc++/EventWriter.h - src/libsrc++/EventWriterV4.h - src/libsrc++/RecordCompressor.h - src/libsrc++/BaseStructure.h - src/libsrc++/BaseStructureHeader.h - src/libsrc++/CompositeData.h - src/libsrc++/BankHeader.h - src/libsrc++/SegmentHeader.h - src/libsrc++/TagSegmentHeader.h - src/libsrc++/EvioBank.h - src/libsrc++/EvioSegment.h - src/libsrc++/EvioTagSegment.h - src/libsrc++/EvioEvent.h - src/libsrc++/EventParser.h - src/libsrc++/IEvioFilter.h - src/libsrc++/IEvioListener.h - src/libsrc++/EventParser.h - src/libsrc++/EventHeaderParser.h - src/libsrc++/StructureTransformer.h - src/libsrc++/IBlockHeader.h - src/libsrc++/IEvioReader.h - src/libsrc++/EvioReader.h - src/libsrc++/EvioReaderV4.h - src/libsrc++/BlockHeaderV2.h - src/libsrc++/BlockHeaderV4.h - src/libsrc++/EvioReaderV6.h - src/libsrc++/EvioCompactReader.h - src/libsrc++/IEvioCompactReader.h - src/libsrc++/EvioXMLDictionary.h - src/libsrc++/EvioDictionaryEntry.h - src/libsrc++/pugixml.hpp - src/libsrc++/pugiconfig.hpp - src/libsrc++/EvioCompactReaderV4.h - src/libsrc++/EvioCompactReaderV6.h - src/libsrc++/EvioCompactStructureHandler.h - src/libsrc++/EventBuilder.h - src/libsrc++/CompactEventBuilder.h - src/libsrc++/EvioSwap.h - src/libsrc++/StructureFinder.h - src/libsrc++/eviocc.h - src/test/TestBase.h - tutorials/EvioTestHelper.h -) - -set(CPP_LIB_FILES - src/libsrc++/FileEventIndex.cpp - src/libsrc++/ByteOrder.cpp - src/libsrc++/ByteBuffer.cpp - src/libsrc++/HeaderType.cpp - src/libsrc++/Compressor.cpp - src/libsrc++/FileHeader.cpp - src/libsrc++/RecordHeader.cpp - src/libsrc++/RecordInput.cpp - src/libsrc++/RecordOutput.cpp - src/libsrc++/Writer.cpp - src/libsrc++/WriterMT.cpp - src/libsrc++/EvioNode.cpp - src/libsrc++/DataType.cpp - src/libsrc++/StructureType.cpp - src/libsrc++/Reader.cpp - src/libsrc++/RecordSupply.cpp - src/libsrc++/RecordRingItem.cpp - src/libsrc++/EventWriter.cpp - src/libsrc++/EventWriterV4.cpp - src/libsrc++/BaseStructure.cpp - src/libsrc++/BaseStructureHeader.cpp - src/libsrc++/CompositeData.cpp - src/libsrc++/BankHeader.cpp - src/libsrc++/SegmentHeader.cpp - src/libsrc++/TagSegmentHeader.cpp - src/libsrc++/EventParser.cpp - src/libsrc++/EvioReader.cpp - src/libsrc++/EvioReaderV4.cpp - src/libsrc++/EvioReaderV6.cpp - src/libsrc++/EvioCompactReader.cpp - src/libsrc++/EvioXMLDictionary.cpp - src/libsrc++/pugixml.cpp - src/libsrc++/EvioCompactReaderV4.cpp - src/libsrc++/EvioCompactReaderV6.cpp - src/libsrc++/EvioCompactStructureHandler.cpp - src/libsrc++/EventBuilder.cpp - src/libsrc++/CompactEventBuilder.cpp - src/test/TestBase.cpp - tutorials/EvioTestHelper.h -) - -set(TEST - src/test/CompactBuilder_Test.cpp - src/test/CompactReaderAddSubtractTest.cpp - src/test/CompactReaderBugTest.cpp - src/test/CompositeTester.cpp - src/test/EvioCompStructHandlerTest.cpp - src/test/DictTest.cpp - src/test/Hipo_Test.cpp - src/test/IndexArrayLenTest.cpp - src/test/ReadWriteTest.cpp - src/test/ReadWriteV4Test.cpp - src/test/RecordSupplyTest.cpp - src/test/RingBufferTest.cpp - src/test/Tree_Buf_Composite_Builder_Test.cpp - src/test/hallDEventFiles.cpp - src/test/FileWriteTest.cpp - src/test/SwapTest.cpp - src/test/ReadSequenceTest.cpp - src/test/SequentialReaderTest.cpp - src/test/SplitTest2.cpp - # Jon added programs below - src/test/BigFileWrite.cpp - src/test/BigFileWritePrimitive.cpp - tutorials/WritePseudoPhys_simple.cpp - tutorials/WritePseudoPhys_builder.cpp - tutorials/WritePseudoPhys_compact.cpp - tutorials/WriteFilePseudoPhysicsEventExtended.cpp - tutorials/PrintXMLDict.cpp - tutorials/EVIO_v4_to_v6.cpp - tutorials/ConvertFormats.cpp - tutorials/ReadCLASFile.cpp - ) - -set(TESTC - src/testC/evReadPipe.c - src/testC/evtest.c - src/testC/evtest2.c - src/testC/evtest3.c - src/testC/evtestAppend.c - src/testC/evtestBuf.c - src/testC/evtestBuf2.c - src/testC/evTestFile.c - src/testC/evtestWriteFile.c - src/testC/evtestRead.c - src/testC/evtestRio.c - src/testC/evtestSock.c - src/testC/evWritePipe.c - src/testC/splitTest.c - src/testC/splitNameTest.c - src/libsrc/eviocopy.c -) - -include(FindPackageHandleStandardArgs) - -# search for boost libs +# Boost libs find_package(Boost REQUIRED COMPONENTS system thread chrono filesystem) - if (Boost_FOUND) message(STATUS "Boost Found: libs = " ${Boost_LIBRARIES} ", include dirs = " ${Boost_INCLUDE_DIRS}) link_directories(${Boost_LIBRARY_DIRS}) @@ -269,14 +62,11 @@ elseif(NOT C_ONLY) message(FATAL_ERROR "Boost cannot be found, cmake will exit." ) endif() -# -------------------------------------------------- -# LZ4 detection -# -------------------------------------------------- +# LZ4 library find_path(LZ4_INCLUDE_DIR NAMES lz4.h PATHS /usr/local/include /usr/include /usr/include/linux ) - find_library(LZ4_LIBRARY NAMES lz4 liblz4 PATHS @@ -287,16 +77,12 @@ find_library(LZ4_LIBRARY /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu/mesa ) - -include(FindPackageHandleStandardArgs) find_package_handle_standard_args(LZ4 REQUIRED_VARS LZ4_LIBRARY LZ4_INCLUDE_DIR HANDLE_COMPONENTS ) - if(NOT LZ4_FOUND) message(STATUS "LZ4 NOT found with the initial search; trying alternative approach ...") - # Fallback or manual search logic if you have other unique paths or want # to do something different. Or just fail here if that's your preference. # e.g. message(FATAL_ERROR "No LZ4 found!") @@ -304,8 +90,21 @@ else() message(STATUS "LZ4 Found: library = ${LZ4_LIBRARY}, include = ${LZ4_INCLUDE_DIR}") endif() +# C source files +file(GLOB C_HEADER_FILES "src/libsrc/*.h") +file(GLOB C_LIB_FILES "src/libsrc/*.c") +# C++ source files +file(GLOB CPP_LIB_FILES "src/libsrc++/*.cpp") +file(GLOB CPP_HEADER_FILES "src/libsrc++/*.h") +file(GLOB TEST "src/test/*.cpp") +file(GLOB TESTC "src/testC/*.c") +# A few extras required +if(MAKE_EXAMPLES) + list(APPEND CPP_HEADER_FILES src/test/TestBase.h tutorials/EvioTestHelper.h) + list(APPEND CPP_LIB_FILES src/test/TestBase.cxx tutorials/EvioTestHelper.h) +endif() -# If building C++ version, handle Disruptor dependency +# BUILD C++ LIBRARY (unless otherwise specified) if(NOT C_ONLY) find_package(Disruptor REQUIRED) # or find_package(Disruptor) diff --git a/src/test/TestBase.cpp b/src/test/TestBase.cxx similarity index 100% rename from src/test/TestBase.cpp rename to src/test/TestBase.cxx diff --git a/tutorials/ReadCLASFile.cpp b/tutorials/ReadCLASFile.cpp index 74e9932d1..8871d2329 100644 --- a/tutorials/ReadCLASFile.cpp +++ b/tutorials/ReadCLASFile.cpp @@ -1,8 +1,7 @@ #include #include -// Include EVIO6 C++ headers (adjust the include paths as needed for your installation) -#include "eviocc.h" // EVIO C++ API (EVIO 6 main branch) +#include "eviocc.h" // EVIO C++ API all inside // Use the EVIO namespace for convenience using namespace evio; diff --git a/tutorials/ReadHIPO_clas_file.cpp b/tutorials/ReadHIPO_clas_file.cpp new file mode 100644 index 000000000..f5bf835cd --- /dev/null +++ b/tutorials/ReadHIPO_clas_file.cpp @@ -0,0 +1,48 @@ +#include +#include + +#include "eviocc.h" // EVIO C++ API all inside + +// Use the EVIO namespace for convenience +using namespace evio; + +int main(int argc, char* argv[]) { + if (argc < 2) { + std::cerr << "Usage: " << argv[0] << " " << std::endl; + return 1; + } + std::string filename = argv[1]; + + int maxEvents = 10; // Maximum number of events to read + + try { + // Open the HIPO file using EvioReader + EvioReader reader(filename); + + // Check for an embedded XML dictionary + if (reader.hasDictionaryXML()) { + // Retrieve the raw XML dictionary text + std::string xmlDict = reader.getDictionaryXML(); + // Print the XML dictionary to standard output + std::cout << xmlDict; + if (!xmlDict.empty() && xmlDict.back() != '\n') std::cout << std::endl; // ensure a newline at end, if not already present + } else { + // No dictionary present in the file + std::cout << "No XML dictionary found." << std::endl; + } + + std::cout << "EVIO Ver: " << reader.getEvioVersion() << std::endl; + std::cout << "File Size: " << reader.fileSize() << std::endl; + std::cout << "Event count: " << reader.getEventCount() << std::endl; + std::cout << "Has first event?: " << reader.hasFirstEvent() << std::endl; + std::cout << "Byte order: " << reader.getByteOrder().getName() << std::endl; + std::cout << "Num blocks (aka records): " << reader.getBlockCount() << std::endl; + + + } catch (const std::exception& e) { + std::cerr << "Error: Unable to read HIPO file. " << e.what() << std::endl; + return 1; + } + + return 0; +} From 7253b5f7942b62df04f80462476254396620b8cf Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Thu, 15 May 2025 15:14:50 -0500 Subject: [PATCH 15/56] When reading evio6 data, add check to file header to skip HIPO format (reading not supported). --- CMakeLists.txt | 4 ++-- src/libsrc++/EvioReaderV6.cpp | 6 +++++- src/libsrc++/FileHeader.h | 4 ++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 163ee49d4..a6db34591 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,10 +96,10 @@ file(GLOB C_LIB_FILES "src/libsrc/*.c") # C++ source files file(GLOB CPP_LIB_FILES "src/libsrc++/*.cpp") file(GLOB CPP_HEADER_FILES "src/libsrc++/*.h") -file(GLOB TEST "src/test/*.cpp") -file(GLOB TESTC "src/testC/*.c") # A few extras required if(MAKE_EXAMPLES) + file(GLOB TEST "src/test/*.cpp" "tutorials/*.cpp") + file(GLOB TESTC "src/testC/*.c") list(APPEND CPP_HEADER_FILES src/test/TestBase.h tutorials/EvioTestHelper.h) list(APPEND CPP_LIB_FILES src/test/TestBase.cxx tutorials/EvioTestHelper.h) endif() diff --git a/src/libsrc++/EvioReaderV6.cpp b/src/libsrc++/EvioReaderV6.cpp index 429802486..f608729c0 100644 --- a/src/libsrc++/EvioReaderV6.cpp +++ b/src/libsrc++/EvioReaderV6.cpp @@ -37,7 +37,11 @@ namespace evio { synchronized = synced; reader = std::make_shared(path, checkSeq, forceScan); parser = std::make_shared(); - } + + if (reader->getFileHeader().getFileId() == reader->getFileHeader().HIPO_FILE_UNIQUE_WORD) { + throw EvioException("\n File is in HIPO format, not evio. Use HIPO reader instead (https://github.com/gavalian/hipo)"); + } + } /** diff --git a/src/libsrc++/FileHeader.h b/src/libsrc++/FileHeader.h index 52630e5ee..9602fc933 100644 --- a/src/libsrc++/FileHeader.h +++ b/src/libsrc++/FileHeader.h @@ -96,9 +96,9 @@ namespace evio { public: /** First word in every HIPO file for identification purposes. */ - static const uint32_t HIPO_FILE_UNIQUE_WORD = 0x4F504948; // 0x4849504F = HIPO + static const uint32_t HIPO_FILE_UNIQUE_WORD = 0x4F504948; // 0x4849504F for HIPO (= "OPIH" in ascii) /** First word in every Evio file for identification purposes. */ - static const uint32_t EVIO_FILE_UNIQUE_WORD = 0x4556494F; // = EVIO + static const uint32_t EVIO_FILE_UNIQUE_WORD = 0x4556494F; // = "EVIO" in ascii /** Number of 32-bit words in a normal sized header. */ static const uint32_t HEADER_SIZE_WORDS = 14; /** Number of bytes in a normal sized header. */ From 5f9401cee79ff7f53b98d567a28321d8425a89ba Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Fri, 16 May 2025 12:19:24 -0500 Subject: [PATCH 16/56] Add check to reject HIPO files from evio6 Reader/CompactReader, for C++ and java both. --- java/org/jlab/coda/jevio/EvioCompactReaderUnsyncV6.java | 5 +++++ java/org/jlab/coda/jevio/EvioReaderUnsyncV6.java | 8 ++++++++ src/libsrc++/EvioCompactReaderV6.cpp | 9 ++++++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/java/org/jlab/coda/jevio/EvioCompactReaderUnsyncV6.java b/java/org/jlab/coda/jevio/EvioCompactReaderUnsyncV6.java index 4ad548dcf..8c24193d6 100644 --- a/java/org/jlab/coda/jevio/EvioCompactReaderUnsyncV6.java +++ b/java/org/jlab/coda/jevio/EvioCompactReaderUnsyncV6.java @@ -10,6 +10,7 @@ package org.jlab.coda.jevio; +import org.jlab.coda.hipo.HeaderType; import org.jlab.coda.hipo.HipoException; import org.jlab.coda.hipo.Reader; @@ -85,6 +86,10 @@ public EvioCompactReaderUnsyncV6(ByteBuffer byteBuffer, EvioNodeSource pool) if (!reader.isEvioFormat()) { throw new EvioException("buffer not in evio format"); } + if (reader.getFileHeader().getHeaderType() == HeaderType.HIPO_FILE) { + throw new EvioException("file not in evio format"); + } + } catch (HipoException e) { throw new EvioException(e); diff --git a/java/org/jlab/coda/jevio/EvioReaderUnsyncV6.java b/java/org/jlab/coda/jevio/EvioReaderUnsyncV6.java index 3b20f2e20..e17b47e48 100644 --- a/java/org/jlab/coda/jevio/EvioReaderUnsyncV6.java +++ b/java/org/jlab/coda/jevio/EvioReaderUnsyncV6.java @@ -10,6 +10,7 @@ package org.jlab.coda.jevio; +import org.jlab.coda.hipo.HeaderType; import org.jlab.coda.hipo.HipoException; import org.jlab.coda.hipo.Reader; @@ -127,6 +128,10 @@ public EvioReaderUnsyncV6(File file) throws EvioException, IOException { try { reader = new Reader(file.getPath(), checkRecNumSeq, true); parser = new EventParser(); + + if (reader.getFileHeader().getHeaderType() == HeaderType.HIPO_FILE) { + throw new EvioException("file not in evio format"); + } } catch (HipoException e) { throw new EvioException(e); @@ -164,6 +169,9 @@ public EvioReaderUnsyncV6(ByteBuffer byteBuffer, boolean checkRecNumSeq) throws if (!reader.isEvioFormat()) { throw new EvioException("buffer not in evio format"); } + if (reader.getFileHeader().getHeaderType() == HeaderType.HIPO_FILE) { + throw new EvioException("file not in evio format"); + } parser = new EventParser(); } catch (HipoException e) { diff --git a/src/libsrc++/EvioCompactReaderV6.cpp b/src/libsrc++/EvioCompactReaderV6.cpp index 96d56aada..3af33dec3 100644 --- a/src/libsrc++/EvioCompactReaderV6.cpp +++ b/src/libsrc++/EvioCompactReaderV6.cpp @@ -22,10 +22,17 @@ namespace evio { */ EvioCompactReaderV6::EvioCompactReaderV6(std::string const & fileName) { if (fileName.empty()) { - throw EvioException("Buffer arg is emptyl"); + throw EvioException("Buffer arg is empty"); } path = fileName; reader.open(fileName); + + if(reader.getFileHeader().getFileId() == reader.getFileHeader().HIPO_FILE_UNIQUE_WORD) { + throw EvioException("\n File is in HIPO format, not evio. Use HIPO reader instead (https://github.com/gavalian/hipo)"); + } + + + } } From f10f84582b4a9a32c7c867c67c703ec74499bec2 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Mon, 19 May 2025 09:27:09 -0500 Subject: [PATCH 17/56] add colz defs --- SConstruct | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/SConstruct b/SConstruct index 241ab6021..a52212927 100644 --- a/SConstruct +++ b/SConstruct @@ -21,6 +21,18 @@ from subprocess import Popen, PIPE # Get useful python functions we wrote import coda +class color: + PURPLE = '\033[95m' + CYAN = '\033[96m' + DARKCYAN = '\033[36m' + BLUE = '\033[94m' + GREEN = '\033[92m' + YELLOW = '\033[93m' + RED = '\033[91m' + BOLD = '\033[1m' + UNDERLINE = '\033[4m' + END = '\033[0m' + # Created files & dirs will have this permission os.umask(0o2) From 6951312ec35814b2b0023c69b0c1b1d9fd7d89ae Mon Sep 17 00:00:00 2001 From: jonzarling Date: Mon, 19 May 2025 11:13:44 -0500 Subject: [PATCH 18/56] Adding warning that scons support will be removed. For now scons will work again (but only if DISRUPTOR_CPP built externally). --- SConstruct | 19 ++++++++++++------- src/libsrc++/EvioCompactReaderV6.cpp | 1 - src/test/SConscript | 6 +++--- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/SConstruct b/SConstruct index a52212927..5fc141037 100644 --- a/SConstruct +++ b/SConstruct @@ -51,13 +51,13 @@ osname = os.getenv('CODA_OSNAME', platform + '-' + machine) path = os.getenv('PATH', '') ldLibPath = os.getenv('LD_LIBRARY_PATH', '') -if path == '': +if path == '' or path == None: print print ("Error: set PATH environmental variable") print raise SystemExit -if ldLibPath == '': +if ldLibPath == '' or ldLibPath == None: print print ("Warning: LD_LIBRARY_PATH environmental variable not defined") print @@ -143,9 +143,9 @@ env = conf.Finish() # location of C++ version of disruptor disruptorHome = os.getenv('DISRUPTOR_CPP_HOME') -if disruptorHome == "": +if disruptorHome == "" or not os.path.exists(str(disruptorHome)): if not onlyC: - print('Disruptor-cpp must be installed by defining DISRUPTOR_CPP_HOME') + print ("Error: set DISRUPTOR_CPP_HOME environmental variable") Exit(1) else: print('Disruptor-cpp = ' + str(disruptorHome)) @@ -163,8 +163,8 @@ if debug: # Compile with -g and add debugSuffix to all executable names env.Append(CCFLAGS = ['-g'], PROGSUFFIX = debugSuffix) -# code for newlib++ written in C++11 -env.Append(CXXFLAGS = ['-std=c++11']) +# code for newlib++ written in C++17 +env.Append(CXXFLAGS = ['-std=c++17']) # Take care of 64/32 bit issues if is64bits: @@ -226,7 +226,7 @@ if (incdir == None): # If we going to install ... if 'install' in COMMAND_LINE_TARGETS: # Determine installation directories - print ("\Call getInstallationDirs with prefix = ", prefix) + print ("\nCall getInstallationDirs with prefix = ", prefix) installDirs = coda.getInstallationDirs(osname, prefix, incdir, libdir, bindir) mainInstallDir = installDirs[0] @@ -305,3 +305,8 @@ if not onlyC: env.SConscript('src/test/SConscript', variant_dir='src/test/'+archDir, duplicate=0) env.SConscript('src/testC/SConscript', variant_dir='src/testC/'+archDir, duplicate=0) + +print (color.BOLD + color.RED + "WARNING: using scons for EVIO C/C++ libraries is deprecated! \n"\ + " option to build via `scons install` will be removed in future updates \n"\ + " (use cmake instead)" + color.END) + diff --git a/src/libsrc++/EvioCompactReaderV6.cpp b/src/libsrc++/EvioCompactReaderV6.cpp index 3af33dec3..129dc444c 100644 --- a/src/libsrc++/EvioCompactReaderV6.cpp +++ b/src/libsrc++/EvioCompactReaderV6.cpp @@ -33,7 +33,6 @@ namespace evio { } - } /** diff --git a/src/test/SConscript b/src/test/SConscript index 0c8aacb9e..3e3e9fd9b 100644 --- a/src/test/SConscript +++ b/src/test/SConscript @@ -2,9 +2,9 @@ Import('env', 'platform', 'archDir', 'incInstallDir', 'libInstallDir', 'binInstallDir', 'archIncInstallDir', 'execLibs', 'debugSuffix', 'disruptorHome') -ccTestBase = 'TestBase.cpp' +ccTestBase = 'TestBase.cxx' excluded_files = ccTestBase -# list of all C++ files (excluding TestBase.cpp) +# list of all C++ files (excluding TestBase.cxx) ccfileList = [f for f in Glob('*.cpp', strings=True) if f not in excluded_files] @@ -17,7 +17,7 @@ if platform == 'Darwin': for fileName in ccfileList: compiledFile = env.Program(source = [fileName, ccTestBase], LIBS = ['eviocc'+debugSuffix, 'Disruptor', - 'boost_system', boostThdLib, 'boost_chrono', execLibs], + 'boost_system', boostThdLib, 'boost_chrono', 'boost_filesystem', execLibs], LIBPATH = ['#src/libsrc++/'+archDir, '/usr/lib64', '/usr/lib', '/usr/local/lib', str(disruptorHome)+'/build/Disruptor'], CPPPATH = ['#src/libsrc++', '#src/test', disruptorHome, '/usr/local/include', '/usr/include/boost', '/usr/local/include/boost']) From fbcbe45668f81e3f776b64318f43f0e0bf48fc07 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Mon, 19 May 2025 11:36:59 -0500 Subject: [PATCH 19/56] Small clarification to change log --- CHANGES | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 330ba87a7..55cca1b1d 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +********************************************************************************* +JAVA CODE CHANGE LOG (oldest to newest) +********************************************************************************* + + jevio-4.3.1.jar differences from previous jar : -check lengths when parsing evio so bad values are caught if possible @@ -165,7 +170,7 @@ jevio-5.1.jar ********************************************************************************* -C CODE +C/C++ CODE CHANGE LOG (oldest to newest) ********************************************************************************* evio-4.3.3 From a3698b79c7d040ebc6f9c5ebe9a686ce459352be Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Tue, 20 May 2025 19:30:47 -0500 Subject: [PATCH 20/56] Add local disruptor jar (updated for evio-6) that mvn will prefer & choose --- java/jars/disruptor-4.0.0.jar | Bin 0 -> 79351 bytes pom.xml | 18 +++++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 java/jars/disruptor-4.0.0.jar diff --git a/java/jars/disruptor-4.0.0.jar b/java/jars/disruptor-4.0.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..c0fcac29a3f5adde275307687c87135503ab8e53 GIT binary patch literal 79351 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 ShK3*f+W;@mB1XY - - 15 + 15 ${java.version} ${java.version} @@ -25,6 +24,15 @@ ${pom.basedir}/java/jars + + + + local-disruptor + file://${project.basedir}/java/jars + true + + + @@ -37,8 +45,8 @@ com.lmax disruptor ${disruptor.version} - system - /home/jzarling/super_evio_dev/disruptor/disruptor/disruptor-4.0.0.jar + + @@ -108,7 +116,7 @@ - + org.apache.maven.plugins maven-surefire-plugin From 4eba858507c5ffcf7ca1984bedfa7fbeaf952d86 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Wed, 21 May 2025 12:01:59 -0500 Subject: [PATCH 21/56] Comment out hipo header check for now, cleanup pom.xml --- .../jlab/coda/jevio/EvioCompactReaderUnsyncV6.java | 6 +++--- java/org/jlab/coda/jevio/EvioReaderUnsyncV6.java | 12 ++++++------ pom.xml | 7 ++----- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/java/org/jlab/coda/jevio/EvioCompactReaderUnsyncV6.java b/java/org/jlab/coda/jevio/EvioCompactReaderUnsyncV6.java index 8c24193d6..d38d481d1 100644 --- a/java/org/jlab/coda/jevio/EvioCompactReaderUnsyncV6.java +++ b/java/org/jlab/coda/jevio/EvioCompactReaderUnsyncV6.java @@ -86,9 +86,9 @@ public EvioCompactReaderUnsyncV6(ByteBuffer byteBuffer, EvioNodeSource pool) if (!reader.isEvioFormat()) { throw new EvioException("buffer not in evio format"); } - if (reader.getFileHeader().getHeaderType() == HeaderType.HIPO_FILE) { - throw new EvioException("file not in evio format"); - } + // if (reader.getFileHeader().getHeaderType() == HeaderType.HIPO_FILE) { + // throw new EvioException("file not in evio format"); + // } } catch (HipoException e) { diff --git a/java/org/jlab/coda/jevio/EvioReaderUnsyncV6.java b/java/org/jlab/coda/jevio/EvioReaderUnsyncV6.java index e17b47e48..f93155c33 100644 --- a/java/org/jlab/coda/jevio/EvioReaderUnsyncV6.java +++ b/java/org/jlab/coda/jevio/EvioReaderUnsyncV6.java @@ -129,9 +129,9 @@ public EvioReaderUnsyncV6(File file) throws EvioException, IOException { reader = new Reader(file.getPath(), checkRecNumSeq, true); parser = new EventParser(); - if (reader.getFileHeader().getHeaderType() == HeaderType.HIPO_FILE) { - throw new EvioException("file not in evio format"); - } + // if (reader.getFileHeader().getHeaderType() == HeaderType.HIPO_FILE) { + // throw new EvioException("file not in evio format"); + // } } catch (HipoException e) { throw new EvioException(e); @@ -169,9 +169,9 @@ public EvioReaderUnsyncV6(ByteBuffer byteBuffer, boolean checkRecNumSeq) throws if (!reader.isEvioFormat()) { throw new EvioException("buffer not in evio format"); } - if (reader.getFileHeader().getHeaderType() == HeaderType.HIPO_FILE) { - throw new EvioException("file not in evio format"); - } + // if (reader.getFileHeader().getHeaderType() == HeaderType.HIPO_FILE) { + // throw new EvioException("file not in evio format"); + // } parser = new EventParser(); } catch (HipoException e) { diff --git a/pom.xml b/pom.xml index bd64c5710..a3e0132d4 100644 --- a/pom.xml +++ b/pom.xml @@ -1,11 +1,8 @@ - + 4.0.0 org.jlab.coda jevio - 6.0-SNAPSHOT + 6.0.0 Jefferson Lab EVIO Java Library (JEVIO) Java library for EVIO (Event Input/Output) jar From 6547765c1b256ed2eb4e7b104a6714387e37ed21 Mon Sep 17 00:00:00 2001 From: jonzarling Date: Wed, 21 May 2025 16:04:01 -0500 Subject: [PATCH 22/56] Now mvn installs correct jar too, previously had been getting overridden --- pom.xml | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index a3e0132d4..2d54b4623 100644 --- a/pom.xml +++ b/pom.xml @@ -21,15 +21,6 @@ ${pom.basedir}/java/jars - - - - local-disruptor - file://${project.basedir}/java/jars - true - - - @@ -53,6 +44,30 @@ ${project.basedir}/java + + + org.apache.maven.plugins + maven-install-plugin + 3.1.4 + + + install-local-disruptor + initialize + + install-file + + + ${project.basedir}/java/jars/disruptor-${disruptor.version}.jar + com.lmax + disruptor + ${disruptor.version} + jar + true + + + + + org.codehaus.mojo From 87bf27afa82c997b8df1611ed437ad53738a6ea8 Mon Sep 17 00:00:00 2001 From: jonzarling Date: Wed, 21 May 2025 17:07:54 -0500 Subject: [PATCH 23/56] cleanup: remove old file and merge helper functions into SConstruct file --- SConstruct | 433 +++++++++++++++++++++++++++++++++++++++++++++++-- coda.py | 428 ------------------------------------------------ tar/tarexclude | 16 -- 3 files changed, 423 insertions(+), 454 deletions(-) delete mode 100644 coda.py delete mode 100644 tar/tarexclude diff --git a/SConstruct b/SConstruct index 5fc141037..fd4a5b74e 100644 --- a/SConstruct +++ b/SConstruct @@ -18,8 +18,421 @@ import re, sys, os, string, subprocess, SCons.Node.FS from subprocess import Popen, PIPE -# Get useful python functions we wrote -import coda +# Useful python functions (previously in py) +def recursiveDirs(root) : + """Return a list of all subdirectories of root, top down, + including root, but without .svn and . directories""" + return filter( (lambda a : (a.rfind( ".svn")==-1) and \ + (a.rfind( ".Linux")==-1) and \ + (a.rfind( ".SunOS")==-1) and \ + (a.rfind( ".Darwin")==-1) and \ + (a.rfind( ".vxworks")==-1)), [ a[0] for a in os.walk(root)] ) + + + +def unique(list) : + """Remove duplicates from list""" + return dict.fromkeys(list).keys() + + + +def scanFiles(dir, accept=["*.cpp"], reject=[]) : + """Return a list of selected files from a directory & its subdirectories""" + sources = [] + paths = recursiveDirs(dir) + for path in paths : + for pattern in accept : + sources+=glob.glob(path+"/"+pattern) + for pattern in reject : + sources = filter( (lambda a : a.rfind(pattern)==-1 ), sources ) + return unique(sources) + + + +def subdirsContaining(root, patterns): + """Return a list of subdirectories containing files of the given pattern""" + dirs = unique(map(os.path.dirname, scanFiles(root, patterns))) + dirs.sort() + return dirs + + + +################### +# Operating System +################### + +def CheckHas64Bits(context, flags): + """Define configure-type test function to + see if operating system is 64 or 32 bits""" + + context.Message( 'Checking for 64/32 bits ...' ) + lastCCFLAGS = context.env['CCFLAGS'] + lastLFLAGS = context.env['LINKFLAGS'] + context.env.Append(CCFLAGS = flags, LINKFLAGS = flags) + # (C) program to run to check for bits + ret = context.TryRun(""" +#include +int main(int argc, char **argv) { + printf(\"%d\", 8*sizeof(0L)); + return 0; +} +""", '.c') + # Restore original flags + context.env.Replace(CCFLAGS = lastCCFLAGS, LINKFLAGS = lastLFLAGS) + # If program successfully ran ... + if ret[0]: + context.Result(ret[1]) + if ret[1] == '64': + return 64 + return 32 + # Else if program did not run ... + else: + # Don't know if it's a 32 or 64 bit operating system + context.Result('failed') + return 0 + + + +def is64BitMachine(env, platform, machine): + """Determine if machine has 64 or 32 bit architecture""" + if platform == 'Linux' and machine == 'x86_64': + return True + else: + ccflags = '' + if platform == 'SunOS': + ccflags = '-xarch=amd64' + + # Run the test + conf = Configure( env, custom_tests = { 'CheckBits' : CheckHas64Bits } ) + ret = conf.CheckBits(ccflags) + env = conf.Finish() + if ret < 1: + print ('Cannot run test, assume 64 bit system') + return True + elif ret == 64: + # Test shows 64 bit system' + return True + else: + # Test shows 32 bit system' + return False + + + +def configure32bits(env, use32bits, platform, machine): + """Setup environment on 64 bit machine to handle 32 or 64 bit libs and executables.""" + if platform == 'SunOS': + if not use32bits: + if machine == 'sun4u': + env.Append(CCFLAGS = ['-xarch=native64', '-xcode=pic32'], + LINKFLAGS = ['-xarch=native64', '-xcode=pic32']) + else: + env.Append(CCFLAGS = ['-xarch=amd64'], + LINKFLAGS = ['-xarch=amd64']) + + elif platform == 'Darwin': + if not use32bits: + env.Append(CCFLAGS = [], + LINKFLAGS = ['-Wl', '-bind_at_load']) + + elif platform == 'Linux': + if use32bits: + env.Append(CCFLAGS = ['-m32'], LINKFLAGS = ['-m32']) + + return + + + +########################### +# Installation Directories +########################### + +def getInstallationDirs(osname, prefix, incdir, libdir, bindir): + """Determine installation directories.""" + + # Get CODA env variable if any + codaHomeEnv = os.getenv('CODA','') + + # The installation directory is the user-specified "prefix" + # by first choice, "CODA" secondly. + # Any user specified command line installation path overrides default + if (prefix == None) or (prefix == ''): + # prefix not defined try CODA env var + if codaHomeEnv == "": + if (incdir == None) or (libdir == None) or (bindir == None): + print ("\nNeed to define CODA, or use the --prefix option,") + print ("or all the --incdir, --libdir, and --bindir options.\n") + raise SystemExit + else: + prefix = codaHomeEnv + + osDir = prefix + "/" + osname + + # Set our install directories + if incdir != None: + incDir = incdir + archIncDir = incdir + else: + incDir = prefix + '/common/include' + archIncDir = osDir + '/include' + + if libdir != None: + libDir = libdir + else: + libDir = osDir + '/lib' + + if bindir != None: + binDir = bindir + else: + binDir = osDir + '/bin' + + # Return absolute paths in list + return [os.path.abspath(prefix), + os.path.abspath(osDir), + os.path.abspath(incDir), + os.path.abspath(archIncDir), + os.path.abspath(libDir), + os.path.abspath(binDir)] + + + +########################### +# Include File Directories +########################### + +def makeIncludeDirs(includeDir, archIncludeDir, archDir, archIncLocalLink): + """Function to make include directories""" + # + # Create main include dir if it doesn't exist + # + if not os.path.exists(includeDir): + os.makedirs(includeDir) + # Make sure it's a directory (if we didn't create it) + elif not os.path.isdir(includeDir): + print + print ("Error:", includeDir, "is NOT a directory") + print + raise SystemExit + + if includeDir == archIncludeDir: + return + + # + # If an install has never been done, the arch dir needs + # to be made first so the symbolic link can be created. + # + if not os.path.exists(archDir): + try: + os.makedirs(archDir) + except OSError: + return + elif not os.path.isdir(archDir): + print + print ("Error:", archDir, "is NOT a directory") + print + raise SystemExit + + # + # If the architecture include dir does NOT exist, + # make link to include dir + # + if not os.path.exists(archIncludeDir): + # Create symbolic link: symlink(source, linkname) + try: + if (archIncLocalLink == None) or (archIncLocalLink == ''): + symlink(includeDir, archIncludeDir) + else: + symlink(archIncLocalLink, archIncludeDir) + except OSError: + # Failed to create symbolic link, so + # just make it a regular directory + os.makedirs(archIncludeDir) + elif not os.path.isdir(archIncludeDir): + print + print ("Error:", archIncludeDir, "is NOT a directory") + print + raise SystemExit + + return + + + +########### +# JAVA JNI +########### + +def configureJNI(env): + """Configure the given environment for compiling Java Native Interface + c or c++ language files.""" + + # first look for a shell variable called JAVA_HOME + java_base = os.environ.get('JAVA_HOME') + if not java_base: + if sys.platform == 'darwin': + # Apple's OS X has its own special java base directory + java_base = '/System/Library/Frameworks/JavaVM.framework' + else: + # Search for the java compiler + print ("JAVA_HOME environment variable not set. Searching for javac to find jni.h ...") + if not env.get('JAVAC'): + print ("The Java compiler must be installed and in the current path, exiting") + return 0 + jcdir = os.path.dirname(env.WhereIs('javac')) + if not jcdir: + print (" not found, exiting") + return 0 + # assuming the compiler found is in some directory like + # /usr/jdkX.X/bin/javac, java's home directory is /usr/jdkX.X + java_base = os.path.join(jcdir, "..") + print (" found, dir = " + java_base) + + if sys.platform == 'darwin': + # Apple does not use Sun's naming convention + java_headers = [os.path.join(java_base, 'Headers')] + java_libs = [os.path.join(java_base, 'Libraries')] + else: + # linux + java_headers = [os.path.join(java_base, 'include')] + java_libs = [os.path.join(java_base, 'lib')] + # Sun's windows and linux JDKs keep system-specific header + # files in a sub-directory of include + if java_base == '/usr' or java_base == '/usr/local': + # too many possible subdirectories. Just use defaults + java_headers.append(os.path.join(java_headers[0], 'linux')) + java_headers.append(os.path.join(java_headers[0], 'solaris')) + else: + # add all subdirs of 'include'. The system specific headers + # should be in there somewhere + java_headers = recursiveDirs(java_headers[0]) + + # add Java's include and lib directory to the environment + env.Append(CPPPATH = java_headers) + # (only need the headers right now so comment out next line) + #env.Append(LIBPATH = java_libs) + + # add any special platform-specific compilation or linking flags + # (only need the headers right now so comment out next lines) + #if sys.platform == 'darwin': + # env.Append(SHLINKFLAGS = '-dynamiclib -framework JavaVM') + # env['SHLIBSUFFIX'] = '.jnilib' + + # Add extra potentially useful environment variables + #env['JAVA_HOME'] = java_base + #env['JNI_CPPPATH'] = java_headers + #env['JNI_LIBPATH'] = java_libs + + return 1 + + + + +################### +# Documentation +################### + +def generateDocs(env, doCPP=False, doC=False, doJava=False): + """Generate and install generated documentation (doxygen & javadoc).""" + + if doCPP: + print ('Call generateDocs() for C++') + # remove target files so documentation always gets rebuilt + rmcmd = 'rm -fr doc/doxygen/CC' + os.popen(rmcmd).read() + + def docGeneratorCC(target, source, env): + cmd = 'doxygen doc/doxygen/DoxyfileCC' + Popen(cmd, shell=True, env={"TOPLEVEL": "./"}, stdout=None) + return + + docBuildCC = Builder(action = docGeneratorCC) + env.Append(BUILDERS = {'DocGenCC' : docBuildCC}) + + env.Alias('doc', env.DocGenCC(target = ['#/doc/doxygen/CC/html/index.html'], + source = scanFiles("src/libsrc++", accept=["*.cpp", "*.h"]))) + + + if doC: + rmcmd = 'rm -fr doc/doxygen/C' + os.popen(rmcmd).read() + + def docGeneratorC(target, source, env): + cmd = 'doxygen doc/doxygen/DoxyfileC' + Popen(cmd, shell=True, env={"TOPLEVEL": "./"}, stdout=None) + return + + docBuildC = Builder(action = docGeneratorC) + env.Append(BUILDERS = {'DocGenC' : docBuildC}) + + env.Alias('doc', env.DocGenC(target = ['#/doc/doxygen/C/html/index.html'], + source = scanFiles("src/libsrc", accept=["*.c", "*.h"]))) + + + if doJava: + rmcmd = 'rm -fr doc/javadoc' + os.popen(rmcmd).read() + + def docGeneratorJava(target, source, env): + cmd = 'ant javadoc' + os.popen(cmd).read() + return + + docBuildJava = Builder(action = docGeneratorJava) + env.Append(BUILDERS = {'DocGenJava' : docBuildJava}) + + env.Alias('doc', env.DocGenJava(target = ['#/doc/javadoc/index.html'], + source = scanFiles("java/org/jlab/coda", accept=["*.java"]) )) + + return 1 + + + + +def removeDocs(env): + """Remove all generated documentation (doxygen & javadoc).""" + + def docRemover(target, source, env): + cmd = 'rm -fr doc/javadoc doc/doxygen/CC doc/doxygen/C' + output = os.popen(cmd).read() + return + + docRemoveAll = Builder(action = docRemover) + env.Append(BUILDERS = {'DocRemove' : docRemoveAll}) + + # remove documentation + env.Alias('undoc', env.DocRemove(target = ['#/.undoc'], source = None)) + + return 1 + + + +################### +# Tar file +################### + +def generateTarFile(env, baseName, majorVersion, minorVersion): + """Generate a gzipped tar file of the current directory.""" + + # Function that does the tar. Note that tar on Solaris is different + # (more primitive) than tar on Linux and MacOS. Solaris tar has no -z option + # and the exclude file does not allow wildcards. Thus, stick to Linux for + # creating the tar file. + def tarballer(target, source, env): + dirname = os.path.basename(os.path.abspath('.')) + cmd = 'tar -X tar/tarexclude -C .. -c -z -f ' + str(target[0]) + ' ./' + dirname + pipe = Popen(cmd, shell=True, stdin=PIPE).stdout + return pipe + + # name of tarfile (software package dependent) + tarfile = 'tar/' + baseName + '-' + majorVersion + '.' + minorVersion + '.tgz' + + # Use a Builder instead of env.Tar() since I can't make that work. + # It runs into circular dependencies since we copy tar file to local + # ./tar directory + tarBuild = Builder(action = tarballer) + env.Append(BUILDERS = {'Tarball' : tarBuild}) + env.Alias('tar', env.Tarball(target = tarfile, source = None)) + + return 1 + class color: PURPLE = '\033[95m' @@ -74,7 +487,7 @@ else: # For Linux 64 bit x86 machines, the "machine' variable is x86_64, # but for Darwin or Solaris there is no obvious check so run # a configure-type test. -is64bits = coda.is64BitMachine(env, platform, machine) +is64bits = is64BitMachine(env, platform, machine) if is64bits: print ("We're on a 64-bit machine") else: @@ -169,7 +582,7 @@ env.Append(CXXFLAGS = ['-std=c++17']) # Take care of 64/32 bit issues if is64bits: # Setup 64 bit machine to compile either 32 or 64 bit libs & executables - coda.configure32bits(env, use32bits, platform, machine) + configure32bits(env, use32bits, platform, machine) elif not use32bits: use32bits = True @@ -227,7 +640,7 @@ if (incdir == None): if 'install' in COMMAND_LINE_TARGETS: # Determine installation directories print ("\nCall getInstallationDirs with prefix = ", prefix) - installDirs = coda.getInstallationDirs(osname, prefix, incdir, libdir, bindir) + installDirs = getInstallationDirs(osname, prefix, incdir, libdir, bindir) mainInstallDir = installDirs[0] osDir = installDirs[1] @@ -237,7 +650,7 @@ if 'install' in COMMAND_LINE_TARGETS: binInstallDir = installDirs[5] # Create the include directories (make symbolic link if possible) - coda.makeIncludeDirs(incInstallDir, archIncInstallDir, osDir, archIncLocalLink) + makeIncludeDirs(incInstallDir, archIncInstallDir, osDir, archIncLocalLink) print ('Main install dir = '+mainInstallDir) print ('bin install dir = '+binInstallDir) @@ -262,12 +675,12 @@ Help('install -c uninstall libs, headers, and binaries\n') if 'doc' in COMMAND_LINE_TARGETS: if onlyC: - coda.generateDocs(env, False, True) + generateDocs(env, False, True) else: - coda.generateDocs(env, True, True) + generateDocs(env, True, True) if 'undoc' in COMMAND_LINE_TARGETS: - coda.removeDocs(env) + removeDocs(env) # use "doc" on command line to create tar file @@ -282,7 +695,7 @@ Help('undoc remove doxygen and javadoc (in ./doc)\n') ######################### if 'tar' in COMMAND_LINE_TARGETS: - coda.generateTarFile(env, 'evio', versionMajor, versionMinor) + generateTarFile(env, 'evio', versionMajor, versionMinor) # use "tar" on command line to create tar file Help('tar create tar file (in ./tar)\n') diff --git a/coda.py b/coda.py deleted file mode 100644 index 78e863551..000000000 --- a/coda.py +++ /dev/null @@ -1,428 +0,0 @@ -#################################################### -# Python functions to support CODA scons build files -#################################################### - -import re, sys, glob, os, string, subprocess -from os import sep, symlink -from subprocess import Popen, PIPE - -from SCons.Script import Configure -from SCons.Builder import Builder - -################ -# File handling -################ - -def recursiveDirs(root) : - """Return a list of all subdirectories of root, top down, - including root, but without .svn and . directories""" - return filter( (lambda a : (a.rfind( ".svn")==-1) and \ - (a.rfind( ".Linux")==-1) and \ - (a.rfind( ".SunOS")==-1) and \ - (a.rfind( ".Darwin")==-1) and \ - (a.rfind( ".vxworks")==-1)), [ a[0] for a in os.walk(root)] ) - - - -def unique(list) : - """Remove duplicates from list""" - return dict.fromkeys(list).keys() - - - -def scanFiles(dir, accept=["*.cpp"], reject=[]) : - """Return a list of selected files from a directory & its subdirectories""" - sources = [] - paths = recursiveDirs(dir) - for path in paths : - for pattern in accept : - sources+=glob.glob(path+"/"+pattern) - for pattern in reject : - sources = filter( (lambda a : a.rfind(pattern)==-1 ), sources ) - return unique(sources) - - - -def subdirsContaining(root, patterns): - """Return a list of subdirectories containing files of the given pattern""" - dirs = unique(map(os.path.dirname, scanFiles(root, patterns))) - dirs.sort() - return dirs - - - -################### -# Operating System -################### - -def CheckHas64Bits(context, flags): - """Define configure-type test function to - see if operating system is 64 or 32 bits""" - - context.Message( 'Checking for 64/32 bits ...' ) - lastCCFLAGS = context.env['CCFLAGS'] - lastLFLAGS = context.env['LINKFLAGS'] - context.env.Append(CCFLAGS = flags, LINKFLAGS = flags) - # (C) program to run to check for bits - ret = context.TryRun(""" -#include -int main(int argc, char **argv) { - printf(\"%d\", 8*sizeof(0L)); - return 0; -} -""", '.c') - # Restore original flags - context.env.Replace(CCFLAGS = lastCCFLAGS, LINKFLAGS = lastLFLAGS) - # If program successfully ran ... - if ret[0]: - context.Result(ret[1]) - if ret[1] == '64': - return 64 - return 32 - # Else if program did not run ... - else: - # Don't know if it's a 32 or 64 bit operating system - context.Result('failed') - return 0 - - - -def is64BitMachine(env, platform, machine): - """Determine if machine has 64 or 32 bit architecture""" - if platform == 'Linux' and machine == 'x86_64': - return True - else: - ccflags = '' - if platform == 'SunOS': - ccflags = '-xarch=amd64' - - # Run the test - conf = Configure( env, custom_tests = { 'CheckBits' : CheckHas64Bits } ) - ret = conf.CheckBits(ccflags) - env = conf.Finish() - if ret < 1: - print ('Cannot run test, assume 64 bit system') - return True - elif ret == 64: - # Test shows 64 bit system' - return True - else: - # Test shows 32 bit system' - return False - - - -def configure32bits(env, use32bits, platform, machine): - """Setup environment on 64 bit machine to handle 32 or 64 bit libs and executables.""" - if platform == 'SunOS': - if not use32bits: - if machine == 'sun4u': - env.Append(CCFLAGS = ['-xarch=native64', '-xcode=pic32'], - LINKFLAGS = ['-xarch=native64', '-xcode=pic32']) - else: - env.Append(CCFLAGS = ['-xarch=amd64'], - LINKFLAGS = ['-xarch=amd64']) - - elif platform == 'Darwin': - if not use32bits: - env.Append(CCFLAGS = [], - LINKFLAGS = ['-Wl', '-bind_at_load']) - - elif platform == 'Linux': - if use32bits: - env.Append(CCFLAGS = ['-m32'], LINKFLAGS = ['-m32']) - - return - - - -########################### -# Installation Directories -########################### - -def getInstallationDirs(osname, prefix, incdir, libdir, bindir): - """Determine installation directories.""" - - # Get CODA env variable if any - codaHomeEnv = os.getenv('CODA','') - - # The installation directory is the user-specified "prefix" - # by first choice, "CODA" secondly. - # Any user specified command line installation path overrides default - if (prefix == None) or (prefix == ''): - # prefix not defined try CODA env var - if codaHomeEnv == "": - if (incdir == None) or (libdir == None) or (bindir == None): - print ("\nNeed to define CODA, or use the --prefix option,") - print ("or all the --incdir, --libdir, and --bindir options.\n") - raise SystemExit - else: - prefix = codaHomeEnv - - osDir = prefix + "/" + osname - - # Set our install directories - if incdir != None: - incDir = incdir - archIncDir = incdir - else: - incDir = prefix + '/common/include' - archIncDir = osDir + '/include' - - if libdir != None: - libDir = libdir - else: - libDir = osDir + '/lib' - - if bindir != None: - binDir = bindir - else: - binDir = osDir + '/bin' - - # Return absolute paths in list - return [os.path.abspath(prefix), - os.path.abspath(osDir), - os.path.abspath(incDir), - os.path.abspath(archIncDir), - os.path.abspath(libDir), - os.path.abspath(binDir)] - - - -########################### -# Include File Directories -########################### - -def makeIncludeDirs(includeDir, archIncludeDir, archDir, archIncLocalLink): - """Function to make include directories""" - # - # Create main include dir if it doesn't exist - # - if not os.path.exists(includeDir): - os.makedirs(includeDir) - # Make sure it's a directory (if we didn't create it) - elif not os.path.isdir(includeDir): - print - print ("Error:", includeDir, "is NOT a directory") - print - raise SystemExit - - if includeDir == archIncludeDir: - return - - # - # If an install has never been done, the arch dir needs - # to be made first so the symbolic link can be created. - # - if not os.path.exists(archDir): - try: - os.makedirs(archDir) - except OSError: - return - elif not os.path.isdir(archDir): - print - print ("Error:", archDir, "is NOT a directory") - print - raise SystemExit - - # - # If the architecture include dir does NOT exist, - # make link to include dir - # - if not os.path.exists(archIncludeDir): - # Create symbolic link: symlink(source, linkname) - try: - if (archIncLocalLink == None) or (archIncLocalLink == ''): - symlink(includeDir, archIncludeDir) - else: - symlink(archIncLocalLink, archIncludeDir) - except OSError: - # Failed to create symbolic link, so - # just make it a regular directory - os.makedirs(archIncludeDir) - elif not os.path.isdir(archIncludeDir): - print - print ("Error:", archIncludeDir, "is NOT a directory") - print - raise SystemExit - - return - - - -########### -# JAVA JNI -########### - -def configureJNI(env): - """Configure the given environment for compiling Java Native Interface - c or c++ language files.""" - - # first look for a shell variable called JAVA_HOME - java_base = os.environ.get('JAVA_HOME') - if not java_base: - if sys.platform == 'darwin': - # Apple's OS X has its own special java base directory - java_base = '/System/Library/Frameworks/JavaVM.framework' - else: - # Search for the java compiler - print ("JAVA_HOME environment variable not set. Searching for javac to find jni.h ...") - if not env.get('JAVAC'): - print ("The Java compiler must be installed and in the current path, exiting") - return 0 - jcdir = os.path.dirname(env.WhereIs('javac')) - if not jcdir: - print (" not found, exiting") - return 0 - # assuming the compiler found is in some directory like - # /usr/jdkX.X/bin/javac, java's home directory is /usr/jdkX.X - java_base = os.path.join(jcdir, "..") - print (" found, dir = " + java_base) - - if sys.platform == 'darwin': - # Apple does not use Sun's naming convention - java_headers = [os.path.join(java_base, 'Headers')] - java_libs = [os.path.join(java_base, 'Libraries')] - else: - # linux - java_headers = [os.path.join(java_base, 'include')] - java_libs = [os.path.join(java_base, 'lib')] - # Sun's windows and linux JDKs keep system-specific header - # files in a sub-directory of include - if java_base == '/usr' or java_base == '/usr/local': - # too many possible subdirectories. Just use defaults - java_headers.append(os.path.join(java_headers[0], 'linux')) - java_headers.append(os.path.join(java_headers[0], 'solaris')) - else: - # add all subdirs of 'include'. The system specific headers - # should be in there somewhere - java_headers = recursiveDirs(java_headers[0]) - - # add Java's include and lib directory to the environment - env.Append(CPPPATH = java_headers) - # (only need the headers right now so comment out next line) - #env.Append(LIBPATH = java_libs) - - # add any special platform-specific compilation or linking flags - # (only need the headers right now so comment out next lines) - #if sys.platform == 'darwin': - # env.Append(SHLINKFLAGS = '-dynamiclib -framework JavaVM') - # env['SHLIBSUFFIX'] = '.jnilib' - - # Add extra potentially useful environment variables - #env['JAVA_HOME'] = java_base - #env['JNI_CPPPATH'] = java_headers - #env['JNI_LIBPATH'] = java_libs - - return 1 - - - - -################### -# Documentation -################### - -def generateDocs(env, doCPP=False, doC=False, doJava=False): - """Generate and install generated documentation (doxygen & javadoc).""" - - if doCPP: - print ('Call generateDocs() for C++') - # remove target files so documentation always gets rebuilt - rmcmd = 'rm -fr doc/doxygen/CC' - os.popen(rmcmd).read() - - def docGeneratorCC(target, source, env): - cmd = 'doxygen doc/doxygen/DoxyfileCC' - Popen(cmd, shell=True, env={"TOPLEVEL": "./"}, stdout=None) - return - - docBuildCC = Builder(action = docGeneratorCC) - env.Append(BUILDERS = {'DocGenCC' : docBuildCC}) - - env.Alias('doc', env.DocGenCC(target = ['#/doc/doxygen/CC/html/index.html'], - source = scanFiles("src/libsrc++", accept=["*.cpp", "*.h"]))) - - - if doC: - rmcmd = 'rm -fr doc/doxygen/C' - os.popen(rmcmd).read() - - def docGeneratorC(target, source, env): - cmd = 'doxygen doc/doxygen/DoxyfileC' - Popen(cmd, shell=True, env={"TOPLEVEL": "./"}, stdout=None) - return - - docBuildC = Builder(action = docGeneratorC) - env.Append(BUILDERS = {'DocGenC' : docBuildC}) - - env.Alias('doc', env.DocGenC(target = ['#/doc/doxygen/C/html/index.html'], - source = scanFiles("src/libsrc", accept=["*.c", "*.h"]))) - - - if doJava: - rmcmd = 'rm -fr doc/javadoc' - os.popen(rmcmd).read() - - def docGeneratorJava(target, source, env): - cmd = 'ant javadoc' - os.popen(cmd).read() - return - - docBuildJava = Builder(action = docGeneratorJava) - env.Append(BUILDERS = {'DocGenJava' : docBuildJava}) - - env.Alias('doc', env.DocGenJava(target = ['#/doc/javadoc/index.html'], - source = scanFiles("java/org/jlab/coda", accept=["*.java"]) )) - - return 1 - - - - -def removeDocs(env): - """Remove all generated documentation (doxygen & javadoc).""" - - def docRemover(target, source, env): - cmd = 'rm -fr doc/javadoc doc/doxygen/CC doc/doxygen/C' - output = os.popen(cmd).read() - return - - docRemoveAll = Builder(action = docRemover) - env.Append(BUILDERS = {'DocRemove' : docRemoveAll}) - - # remove documentation - env.Alias('undoc', env.DocRemove(target = ['#/.undoc'], source = None)) - - return 1 - - - -################### -# Tar file -################### - -def generateTarFile(env, baseName, majorVersion, minorVersion): - """Generate a gzipped tar file of the current directory.""" - - # Function that does the tar. Note that tar on Solaris is different - # (more primitive) than tar on Linux and MacOS. Solaris tar has no -z option - # and the exclude file does not allow wildcards. Thus, stick to Linux for - # creating the tar file. - def tarballer(target, source, env): - dirname = os.path.basename(os.path.abspath('.')) - cmd = 'tar -X tar/tarexclude -C .. -c -z -f ' + str(target[0]) + ' ./' + dirname - pipe = Popen(cmd, shell=True, stdin=PIPE).stdout - return pipe - - # name of tarfile (software package dependent) - tarfile = 'tar/' + baseName + '-' + majorVersion + '.' + minorVersion + '.tgz' - - # Use a Builder instead of env.Tar() since I can't make that work. - # It runs into circular dependencies since we copy tar file to local - # ./tar directory - tarBuild = Builder(action = tarballer) - env.Append(BUILDERS = {'Tarball' : tarBuild}) - env.Alias('tar', env.Tarball(target = tarfile, source = None)) - - return 1 diff --git a/tar/tarexclude b/tar/tarexclude deleted file mode 100644 index 138c1844e..000000000 --- a/tar/tarexclude +++ /dev/null @@ -1,16 +0,0 @@ -.git -.svn -.scon* -*~ -coda.pyc -*.iml -config.log -doxyerrors.log -doc/doxygen/* -tar/evio* -src/libsrc/.* -src/libsrc++/.* -src/execsrc/.* -src/examples/.* -src/test/.* -build From f883dbbe3a3c024616e079926a050021b22eb55a Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Thu, 22 May 2025 14:35:45 -0500 Subject: [PATCH 24/56] cosmetic tweaks to pom file --- pom.xml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index a3e0132d4..99630d820 100644 --- a/pom.xml +++ b/pom.xml @@ -7,21 +7,22 @@ Java library for EVIO (Event Input/Output) jar - + - 15 ${java.version} ${java.version} - - UTF-8 + 1.8.0 - 4.0.0 + 4.0.0 + + UTF-8 ${pom.basedir}/java/jars + local-disruptor @@ -42,9 +43,6 @@ com.lmax disruptor ${disruptor.version} - - - From 2888413c2bf30d3a3ac9da8300be89fe681ebec3 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Fri, 23 May 2025 12:12:33 -0500 Subject: [PATCH 25/56] addd missing import to scons --- .gitignore | 3 +-- SConstruct | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 99172ea67..2ad1d034e 100644 --- a/.gitignore +++ b/.gitignore @@ -20,12 +20,11 @@ cmake-* cmake_install.cmake coda.pyc build/ -build_old/ jbuild/ lib/ bin/ doxyerrors.log -/target/ +target/ doc/javadoc doc/doxygen/CC doc/doxygen/C diff --git a/SConstruct b/SConstruct index fd4a5b74e..d7ec55aff 100644 --- a/SConstruct +++ b/SConstruct @@ -17,6 +17,7 @@ # Get various python modules import re, sys, os, string, subprocess, SCons.Node.FS from subprocess import Popen, PIPE +from os import sep, symlink # Useful python functions (previously in py) def recursiveDirs(root) : From 7f73d2d9060de55a1cb997660353ae0ff69cf65b Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Fri, 23 May 2025 15:24:02 -0500 Subject: [PATCH 26/56] More cleanup: move unused files to new etc/ directory --- CMakeLists.txt | 1 - CHANGES => etc/CHANGES | 0 etc/README.md | 10 ++++++++++ .../cmake_uninstall.cmake.in | 0 setup_java => etc/setup_java | 0 5 files changed, 10 insertions(+), 1 deletion(-) rename CHANGES => etc/CHANGES (100%) create mode 100644 etc/README.md rename cmake_uninstall.cmake.in => etc/cmake_uninstall.cmake.in (100%) rename setup_java => etc/setup_java (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index a6db34591..18d23cf09 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,7 +49,6 @@ else() # Use default CMAKE_INSTALL_PREFIX set(INSTALL_DIR_DEFINED 1) message(STATUS "Installing to default location: ${CMAKE_INSTALL_PREFIX}") - # Don't set CMAKE_INSTALL_PREFIX here - use the CMake default endif() # Boost libs diff --git a/CHANGES b/etc/CHANGES similarity index 100% rename from CHANGES rename to etc/CHANGES diff --git a/etc/README.md b/etc/README.md new file mode 100644 index 000000000..061a9708b --- /dev/null +++ b/etc/README.md @@ -0,0 +1,10 @@ +# **Miscellaneous folder** + +This folder collects old scripts, documentation, and files from evio versions 1-5. + +| File | Description +|------------|---------------------------------------------------------------------- +| [CHANGES](CHANGES) | Change log for evio versions 4-5 | +| [setup_java](setup_java) | Setup script for choosing java version (either Java 8 or 15). | +| [cmake_uninstall.cmake.in](cmake_uninstall.cmake.in) | Uninstallation script for evio-5 | + diff --git a/cmake_uninstall.cmake.in b/etc/cmake_uninstall.cmake.in similarity index 100% rename from cmake_uninstall.cmake.in rename to etc/cmake_uninstall.cmake.in diff --git a/setup_java b/etc/setup_java similarity index 100% rename from setup_java rename to etc/setup_java From cab5c82f6a13b2f6dfe0b7f2b42a8a1a2b53494b Mon Sep 17 00:00:00 2001 From: jonzarling Date: Sun, 25 May 2025 13:46:50 -0500 Subject: [PATCH 27/56] Change directory structure of c/c++ test programs (likely will move once more) --- CMakeLists.txt | 31 ++++++++++--------- SConstruct | 6 ++-- {src => etc/src}/execsrc/README | 0 {src => etc/src}/execsrc/SConscript | 0 pom.xml | 3 ++ src/{testC => test/c}/SConscript | 0 src/{testC => test/c}/evReadPipe.c | 0 src/{testC => test/c}/evTestFile.c | 0 src/{testC => test/c}/evWritePipe.c | 0 src/{testC => test/c}/evtest.c | 0 src/{testC => test/c}/evtest2.c | 0 src/{testC => test/c}/evtest3.c | 0 src/{testC => test/c}/evtestAppend.c | 0 src/{testC => test/c}/evtestBuf.c | 0 src/{testC => test/c}/evtestBuf2.c | 0 src/{testC => test/c}/evtestRead.c | 0 src/{testC => test/c}/evtestRio.c | 0 src/{testC => test/c}/evtestSock.c | 0 src/{testC => test/c}/evtestWriteFile.c | 0 src/{testC => test/c}/splitNameTest.c | 0 src/{testC => test/c}/splitTest.c | 0 src/test/{ => cpp}/BigFileWrite.cpp | 0 src/test/{ => cpp}/BigFileWritePrimitive.cpp | 0 src/test/{ => cpp}/CompactBuilder_Test.cpp | 0 .../CompactReaderAddSubtractTest.cpp | 0 src/test/{ => cpp}/CompactReaderBugTest.cpp | 0 src/test/{ => cpp}/CompositeTester.cpp | 0 src/test/{ => cpp}/DictTest.cpp | 0 .../{ => cpp}/EvioCompStructHandlerTest.cpp | 0 src/test/{ => cpp}/FileWriteTest.cpp | 0 src/test/{ => cpp}/Hipo_Test.cpp | 0 src/test/{ => cpp}/IndexArrayLenTest.cpp | 0 src/test/{ => cpp}/README.md | 0 src/test/{ => cpp}/ReadSequenceTest.cpp | 0 src/test/{ => cpp}/ReadWriteTest.cpp | 0 src/test/{ => cpp}/ReadWriteV4Test.cpp | 0 src/test/{ => cpp}/RecordSupplyTest.cpp | 0 src/test/{ => cpp}/RingBufferTest.cpp | 0 src/test/{ => cpp}/SConscript | 0 src/test/{ => cpp}/SequentialReaderTest.cpp | 0 src/test/{ => cpp}/SplitTest2.cpp | 0 src/test/{ => cpp}/SwapTest.cpp | 0 src/test/{ => cpp}/TestBase.cxx | 0 src/test/{ => cpp}/TestBase.h | 0 .../Tree_Buf_Composite_Builder_Test.cpp | 0 src/test/{ => cpp}/fileTest.cpp | 0 src/test/{ => cpp}/hallDEventFiles.cpp | 0 47 files changed, 21 insertions(+), 19 deletions(-) rename {src => etc/src}/execsrc/README (100%) rename {src => etc/src}/execsrc/SConscript (100%) rename src/{testC => test/c}/SConscript (100%) rename src/{testC => test/c}/evReadPipe.c (100%) rename src/{testC => test/c}/evTestFile.c (100%) rename src/{testC => test/c}/evWritePipe.c (100%) rename src/{testC => test/c}/evtest.c (100%) rename src/{testC => test/c}/evtest2.c (100%) rename src/{testC => test/c}/evtest3.c (100%) rename src/{testC => test/c}/evtestAppend.c (100%) rename src/{testC => test/c}/evtestBuf.c (100%) rename src/{testC => test/c}/evtestBuf2.c (100%) rename src/{testC => test/c}/evtestRead.c (100%) rename src/{testC => test/c}/evtestRio.c (100%) rename src/{testC => test/c}/evtestSock.c (100%) rename src/{testC => test/c}/evtestWriteFile.c (100%) rename src/{testC => test/c}/splitNameTest.c (100%) rename src/{testC => test/c}/splitTest.c (100%) rename src/test/{ => cpp}/BigFileWrite.cpp (100%) rename src/test/{ => cpp}/BigFileWritePrimitive.cpp (100%) rename src/test/{ => cpp}/CompactBuilder_Test.cpp (100%) rename src/test/{ => cpp}/CompactReaderAddSubtractTest.cpp (100%) rename src/test/{ => cpp}/CompactReaderBugTest.cpp (100%) rename src/test/{ => cpp}/CompositeTester.cpp (100%) rename src/test/{ => cpp}/DictTest.cpp (100%) rename src/test/{ => cpp}/EvioCompStructHandlerTest.cpp (100%) rename src/test/{ => cpp}/FileWriteTest.cpp (100%) rename src/test/{ => cpp}/Hipo_Test.cpp (100%) rename src/test/{ => cpp}/IndexArrayLenTest.cpp (100%) rename src/test/{ => cpp}/README.md (100%) rename src/test/{ => cpp}/ReadSequenceTest.cpp (100%) rename src/test/{ => cpp}/ReadWriteTest.cpp (100%) rename src/test/{ => cpp}/ReadWriteV4Test.cpp (100%) rename src/test/{ => cpp}/RecordSupplyTest.cpp (100%) rename src/test/{ => cpp}/RingBufferTest.cpp (100%) rename src/test/{ => cpp}/SConscript (100%) rename src/test/{ => cpp}/SequentialReaderTest.cpp (100%) rename src/test/{ => cpp}/SplitTest2.cpp (100%) rename src/test/{ => cpp}/SwapTest.cpp (100%) rename src/test/{ => cpp}/TestBase.cxx (100%) rename src/test/{ => cpp}/TestBase.h (100%) rename src/test/{ => cpp}/Tree_Buf_Composite_Builder_Test.cpp (100%) rename src/test/{ => cpp}/fileTest.cpp (100%) rename src/test/{ => cpp}/hallDEventFiles.cpp (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 18d23cf09..a725b40a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,10 +97,10 @@ file(GLOB CPP_LIB_FILES "src/libsrc++/*.cpp") file(GLOB CPP_HEADER_FILES "src/libsrc++/*.h") # A few extras required if(MAKE_EXAMPLES) - file(GLOB TEST "src/test/*.cpp" "tutorials/*.cpp") - file(GLOB TESTC "src/testC/*.c") - list(APPEND CPP_HEADER_FILES src/test/TestBase.h tutorials/EvioTestHelper.h) - list(APPEND CPP_LIB_FILES src/test/TestBase.cxx tutorials/EvioTestHelper.h) + file(GLOB TEST "src/test/cpp/*.cpp" "tutorials/*.cpp") + file(GLOB TESTC "src/test/c/*.c") + list(APPEND CPP_HEADER_FILES src/test/cpp/TestBase.h tutorials/EvioTestHelper.h) + list(APPEND CPP_LIB_FILES src/test/cpp/TestBase.cxx tutorials/EvioTestHelper.h) endif() # BUILD C++ LIBRARY (unless otherwise specified) @@ -253,17 +253,18 @@ endif() # Uninstall target -if(NOT TARGET uninstall) - configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" - IMMEDIATE @ONLY - ) - - add_custom_target(uninstall - COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake - ) -endif() +# Removed for now, not yet compatible with building disruptor-cpp internally +# if(NOT TARGET uninstall) +# configure_file( +# "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" +# "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" +# IMMEDIATE @ONLY +# ) + +# add_custom_target(uninstall +# COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake +# ) +# endif() # Options printout message(STATUS "Options table: ") diff --git a/SConstruct b/SConstruct index d7ec55aff..1fc5bb7bf 100644 --- a/SConstruct +++ b/SConstruct @@ -714,11 +714,9 @@ env.SConscript('src/libsrc/SConscript', variant_dir='src/libsrc/'+archDir, dup if not onlyC: env.SConscript('src/libsrc++/SConscript', variant_dir='src/libsrc++/'+archDir, duplicate=0) - #env.SConscript('src/execsrc/SConscript', variant_dir='src/execsrc/'+archDir, duplicate=0) - #env.SConscript('src/examples/SConscript', variant_dir='src/examples/'+archDir, duplicate=0) - env.SConscript('src/test/SConscript', variant_dir='src/test/'+archDir, duplicate=0) + env.SConscript('src/test/cpp/SConscript', variant_dir='src/test/'+archDir, duplicate=0) -env.SConscript('src/testC/SConscript', variant_dir='src/testC/'+archDir, duplicate=0) +env.SConscript('src/test/c/SConscript', variant_dir='src/testC/'+archDir, duplicate=0) print (color.BOLD + color.RED + "WARNING: using scons for EVIO C/C++ libraries is deprecated! \n"\ " option to build via `scons install` will be removed in future updates \n"\ diff --git a/src/execsrc/README b/etc/src/execsrc/README similarity index 100% rename from src/execsrc/README rename to etc/src/execsrc/README diff --git a/src/execsrc/SConscript b/etc/src/execsrc/SConscript similarity index 100% rename from src/execsrc/SConscript rename to etc/src/execsrc/SConscript diff --git a/pom.xml b/pom.xml index 9d7265a6d..687c5b7f5 100644 --- a/pom.xml +++ b/pom.xml @@ -7,6 +7,9 @@ Java library for EVIO (Event Input/Output) jar + + + diff --git a/src/testC/SConscript b/src/test/c/SConscript similarity index 100% rename from src/testC/SConscript rename to src/test/c/SConscript diff --git a/src/testC/evReadPipe.c b/src/test/c/evReadPipe.c similarity index 100% rename from src/testC/evReadPipe.c rename to src/test/c/evReadPipe.c diff --git a/src/testC/evTestFile.c b/src/test/c/evTestFile.c similarity index 100% rename from src/testC/evTestFile.c rename to src/test/c/evTestFile.c diff --git a/src/testC/evWritePipe.c b/src/test/c/evWritePipe.c similarity index 100% rename from src/testC/evWritePipe.c rename to src/test/c/evWritePipe.c diff --git a/src/testC/evtest.c b/src/test/c/evtest.c similarity index 100% rename from src/testC/evtest.c rename to src/test/c/evtest.c diff --git a/src/testC/evtest2.c b/src/test/c/evtest2.c similarity index 100% rename from src/testC/evtest2.c rename to src/test/c/evtest2.c diff --git a/src/testC/evtest3.c b/src/test/c/evtest3.c similarity index 100% rename from src/testC/evtest3.c rename to src/test/c/evtest3.c diff --git a/src/testC/evtestAppend.c b/src/test/c/evtestAppend.c similarity index 100% rename from src/testC/evtestAppend.c rename to src/test/c/evtestAppend.c diff --git a/src/testC/evtestBuf.c b/src/test/c/evtestBuf.c similarity index 100% rename from src/testC/evtestBuf.c rename to src/test/c/evtestBuf.c diff --git a/src/testC/evtestBuf2.c b/src/test/c/evtestBuf2.c similarity index 100% rename from src/testC/evtestBuf2.c rename to src/test/c/evtestBuf2.c diff --git a/src/testC/evtestRead.c b/src/test/c/evtestRead.c similarity index 100% rename from src/testC/evtestRead.c rename to src/test/c/evtestRead.c diff --git a/src/testC/evtestRio.c b/src/test/c/evtestRio.c similarity index 100% rename from src/testC/evtestRio.c rename to src/test/c/evtestRio.c diff --git a/src/testC/evtestSock.c b/src/test/c/evtestSock.c similarity index 100% rename from src/testC/evtestSock.c rename to src/test/c/evtestSock.c diff --git a/src/testC/evtestWriteFile.c b/src/test/c/evtestWriteFile.c similarity index 100% rename from src/testC/evtestWriteFile.c rename to src/test/c/evtestWriteFile.c diff --git a/src/testC/splitNameTest.c b/src/test/c/splitNameTest.c similarity index 100% rename from src/testC/splitNameTest.c rename to src/test/c/splitNameTest.c diff --git a/src/testC/splitTest.c b/src/test/c/splitTest.c similarity index 100% rename from src/testC/splitTest.c rename to src/test/c/splitTest.c diff --git a/src/test/BigFileWrite.cpp b/src/test/cpp/BigFileWrite.cpp similarity index 100% rename from src/test/BigFileWrite.cpp rename to src/test/cpp/BigFileWrite.cpp diff --git a/src/test/BigFileWritePrimitive.cpp b/src/test/cpp/BigFileWritePrimitive.cpp similarity index 100% rename from src/test/BigFileWritePrimitive.cpp rename to src/test/cpp/BigFileWritePrimitive.cpp diff --git a/src/test/CompactBuilder_Test.cpp b/src/test/cpp/CompactBuilder_Test.cpp similarity index 100% rename from src/test/CompactBuilder_Test.cpp rename to src/test/cpp/CompactBuilder_Test.cpp diff --git a/src/test/CompactReaderAddSubtractTest.cpp b/src/test/cpp/CompactReaderAddSubtractTest.cpp similarity index 100% rename from src/test/CompactReaderAddSubtractTest.cpp rename to src/test/cpp/CompactReaderAddSubtractTest.cpp diff --git a/src/test/CompactReaderBugTest.cpp b/src/test/cpp/CompactReaderBugTest.cpp similarity index 100% rename from src/test/CompactReaderBugTest.cpp rename to src/test/cpp/CompactReaderBugTest.cpp diff --git a/src/test/CompositeTester.cpp b/src/test/cpp/CompositeTester.cpp similarity index 100% rename from src/test/CompositeTester.cpp rename to src/test/cpp/CompositeTester.cpp diff --git a/src/test/DictTest.cpp b/src/test/cpp/DictTest.cpp similarity index 100% rename from src/test/DictTest.cpp rename to src/test/cpp/DictTest.cpp diff --git a/src/test/EvioCompStructHandlerTest.cpp b/src/test/cpp/EvioCompStructHandlerTest.cpp similarity index 100% rename from src/test/EvioCompStructHandlerTest.cpp rename to src/test/cpp/EvioCompStructHandlerTest.cpp diff --git a/src/test/FileWriteTest.cpp b/src/test/cpp/FileWriteTest.cpp similarity index 100% rename from src/test/FileWriteTest.cpp rename to src/test/cpp/FileWriteTest.cpp diff --git a/src/test/Hipo_Test.cpp b/src/test/cpp/Hipo_Test.cpp similarity index 100% rename from src/test/Hipo_Test.cpp rename to src/test/cpp/Hipo_Test.cpp diff --git a/src/test/IndexArrayLenTest.cpp b/src/test/cpp/IndexArrayLenTest.cpp similarity index 100% rename from src/test/IndexArrayLenTest.cpp rename to src/test/cpp/IndexArrayLenTest.cpp diff --git a/src/test/README.md b/src/test/cpp/README.md similarity index 100% rename from src/test/README.md rename to src/test/cpp/README.md diff --git a/src/test/ReadSequenceTest.cpp b/src/test/cpp/ReadSequenceTest.cpp similarity index 100% rename from src/test/ReadSequenceTest.cpp rename to src/test/cpp/ReadSequenceTest.cpp diff --git a/src/test/ReadWriteTest.cpp b/src/test/cpp/ReadWriteTest.cpp similarity index 100% rename from src/test/ReadWriteTest.cpp rename to src/test/cpp/ReadWriteTest.cpp diff --git a/src/test/ReadWriteV4Test.cpp b/src/test/cpp/ReadWriteV4Test.cpp similarity index 100% rename from src/test/ReadWriteV4Test.cpp rename to src/test/cpp/ReadWriteV4Test.cpp diff --git a/src/test/RecordSupplyTest.cpp b/src/test/cpp/RecordSupplyTest.cpp similarity index 100% rename from src/test/RecordSupplyTest.cpp rename to src/test/cpp/RecordSupplyTest.cpp diff --git a/src/test/RingBufferTest.cpp b/src/test/cpp/RingBufferTest.cpp similarity index 100% rename from src/test/RingBufferTest.cpp rename to src/test/cpp/RingBufferTest.cpp diff --git a/src/test/SConscript b/src/test/cpp/SConscript similarity index 100% rename from src/test/SConscript rename to src/test/cpp/SConscript diff --git a/src/test/SequentialReaderTest.cpp b/src/test/cpp/SequentialReaderTest.cpp similarity index 100% rename from src/test/SequentialReaderTest.cpp rename to src/test/cpp/SequentialReaderTest.cpp diff --git a/src/test/SplitTest2.cpp b/src/test/cpp/SplitTest2.cpp similarity index 100% rename from src/test/SplitTest2.cpp rename to src/test/cpp/SplitTest2.cpp diff --git a/src/test/SwapTest.cpp b/src/test/cpp/SwapTest.cpp similarity index 100% rename from src/test/SwapTest.cpp rename to src/test/cpp/SwapTest.cpp diff --git a/src/test/TestBase.cxx b/src/test/cpp/TestBase.cxx similarity index 100% rename from src/test/TestBase.cxx rename to src/test/cpp/TestBase.cxx diff --git a/src/test/TestBase.h b/src/test/cpp/TestBase.h similarity index 100% rename from src/test/TestBase.h rename to src/test/cpp/TestBase.h diff --git a/src/test/Tree_Buf_Composite_Builder_Test.cpp b/src/test/cpp/Tree_Buf_Composite_Builder_Test.cpp similarity index 100% rename from src/test/Tree_Buf_Composite_Builder_Test.cpp rename to src/test/cpp/Tree_Buf_Composite_Builder_Test.cpp diff --git a/src/test/fileTest.cpp b/src/test/cpp/fileTest.cpp similarity index 100% rename from src/test/fileTest.cpp rename to src/test/cpp/fileTest.cpp diff --git a/src/test/hallDEventFiles.cpp b/src/test/cpp/hallDEventFiles.cpp similarity index 100% rename from src/test/hallDEventFiles.cpp rename to src/test/cpp/hallDEventFiles.cpp From 155b61dac14aaaecc8c370fa18ab05d9cec8992b Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Fri, 30 May 2025 16:35:09 -0500 Subject: [PATCH 28/56] Move java tests to historical `etc/` folder --- {java/org/jlab/coda => etc/java}/hipo/test/README.md | 0 {java/org/jlab/coda => etc/java}/hipo/test/ReadWriteTest.java | 0 .../org/jlab/coda => etc/java}/hipo/test/RecordSupplyTester.java | 0 {java/org/jlab/coda => etc/java}/hipo/test/TestBuilding.java | 0 {java/org/jlab/coda => etc/java}/hipo/test/TestWriter.java | 0 {java/org/jlab/coda => etc/java}/jevio/test/BigFileWrite.java | 0 .../java}/jevio/test/CompactReaderAddSubtractTest.java | 0 .../jlab/coda => etc/java}/jevio/test/CompactReaderBugTest.java | 0 .../coda => etc/java}/jevio/test/CompactStructureHandlerTest.java | 0 {java/org/jlab/coda => etc/java}/jevio/test/CompositeTester.java | 0 {java/org/jlab/coda => etc/java}/jevio/test/CompressionTest.java | 0 {java/org/jlab/coda => etc/java}/jevio/test/DictTest.java | 0 {java/org/jlab/coda => etc/java}/jevio/test/ExtractHallDdata.java | 0 {java/org/jlab/coda => etc/java}/jevio/test/FileTest.java | 0 {java/org/jlab/coda => etc/java}/jevio/test/FileTestVer6.java | 0 {java/org/jlab/coda => etc/java}/jevio/test/FileWriteTest.java | 0 .../jlab/coda => etc/java}/jevio/test/FileWritingSpeedTest.java | 0 {java/org/jlab/coda => etc/java}/jevio/test/FirstEventTest.java | 0 {java/org/jlab/coda => etc/java}/jevio/test/HipoTest.java | 0 {java/org/jlab/coda => etc/java}/jevio/test/README.md | 0 {java/org/jlab/coda => etc/java}/jevio/test/ReadAggOutput.java | 0 {java/org/jlab/coda => etc/java}/jevio/test/ReadSequenceTest.java | 0 {java/org/jlab/coda => etc/java}/jevio/test/ReadWriteTest.java | 0 {java/org/jlab/coda => etc/java}/jevio/test/ReadWriteV4Test.java | 0 {java/org/jlab/coda => etc/java}/jevio/test/RecordSupplyTest.java | 0 .../jlab/coda => etc/java}/jevio/test/SequentialReaderTest.java | 0 {java/org/jlab/coda => etc/java}/jevio/test/SplitTest.java | 0 {java/org/jlab/coda => etc/java}/jevio/test/SwapTest.java | 0 {java/org/jlab/coda => etc/java}/jevio/test/TestBase.java | 0 {java/org/jlab/coda => etc/java}/jevio/test/TreeBufTest.java | 0 {java/org/jlab/coda => etc/java}/jevio/test/XmlTest.java | 0 31 files changed, 0 insertions(+), 0 deletions(-) rename {java/org/jlab/coda => etc/java}/hipo/test/README.md (100%) rename {java/org/jlab/coda => etc/java}/hipo/test/ReadWriteTest.java (100%) rename {java/org/jlab/coda => etc/java}/hipo/test/RecordSupplyTester.java (100%) rename {java/org/jlab/coda => etc/java}/hipo/test/TestBuilding.java (100%) rename {java/org/jlab/coda => etc/java}/hipo/test/TestWriter.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/BigFileWrite.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/CompactReaderAddSubtractTest.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/CompactReaderBugTest.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/CompactStructureHandlerTest.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/CompositeTester.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/CompressionTest.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/DictTest.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/ExtractHallDdata.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/FileTest.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/FileTestVer6.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/FileWriteTest.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/FileWritingSpeedTest.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/FirstEventTest.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/HipoTest.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/README.md (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/ReadAggOutput.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/ReadSequenceTest.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/ReadWriteTest.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/ReadWriteV4Test.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/RecordSupplyTest.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/SequentialReaderTest.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/SplitTest.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/SwapTest.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/TestBase.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/TreeBufTest.java (100%) rename {java/org/jlab/coda => etc/java}/jevio/test/XmlTest.java (100%) diff --git a/java/org/jlab/coda/hipo/test/README.md b/etc/java/hipo/test/README.md similarity index 100% rename from java/org/jlab/coda/hipo/test/README.md rename to etc/java/hipo/test/README.md diff --git a/java/org/jlab/coda/hipo/test/ReadWriteTest.java b/etc/java/hipo/test/ReadWriteTest.java similarity index 100% rename from java/org/jlab/coda/hipo/test/ReadWriteTest.java rename to etc/java/hipo/test/ReadWriteTest.java diff --git a/java/org/jlab/coda/hipo/test/RecordSupplyTester.java b/etc/java/hipo/test/RecordSupplyTester.java similarity index 100% rename from java/org/jlab/coda/hipo/test/RecordSupplyTester.java rename to etc/java/hipo/test/RecordSupplyTester.java diff --git a/java/org/jlab/coda/hipo/test/TestBuilding.java b/etc/java/hipo/test/TestBuilding.java similarity index 100% rename from java/org/jlab/coda/hipo/test/TestBuilding.java rename to etc/java/hipo/test/TestBuilding.java diff --git a/java/org/jlab/coda/hipo/test/TestWriter.java b/etc/java/hipo/test/TestWriter.java similarity index 100% rename from java/org/jlab/coda/hipo/test/TestWriter.java rename to etc/java/hipo/test/TestWriter.java diff --git a/java/org/jlab/coda/jevio/test/BigFileWrite.java b/etc/java/jevio/test/BigFileWrite.java similarity index 100% rename from java/org/jlab/coda/jevio/test/BigFileWrite.java rename to etc/java/jevio/test/BigFileWrite.java diff --git a/java/org/jlab/coda/jevio/test/CompactReaderAddSubtractTest.java b/etc/java/jevio/test/CompactReaderAddSubtractTest.java similarity index 100% rename from java/org/jlab/coda/jevio/test/CompactReaderAddSubtractTest.java rename to etc/java/jevio/test/CompactReaderAddSubtractTest.java diff --git a/java/org/jlab/coda/jevio/test/CompactReaderBugTest.java b/etc/java/jevio/test/CompactReaderBugTest.java similarity index 100% rename from java/org/jlab/coda/jevio/test/CompactReaderBugTest.java rename to etc/java/jevio/test/CompactReaderBugTest.java diff --git a/java/org/jlab/coda/jevio/test/CompactStructureHandlerTest.java b/etc/java/jevio/test/CompactStructureHandlerTest.java similarity index 100% rename from java/org/jlab/coda/jevio/test/CompactStructureHandlerTest.java rename to etc/java/jevio/test/CompactStructureHandlerTest.java diff --git a/java/org/jlab/coda/jevio/test/CompositeTester.java b/etc/java/jevio/test/CompositeTester.java similarity index 100% rename from java/org/jlab/coda/jevio/test/CompositeTester.java rename to etc/java/jevio/test/CompositeTester.java diff --git a/java/org/jlab/coda/jevio/test/CompressionTest.java b/etc/java/jevio/test/CompressionTest.java similarity index 100% rename from java/org/jlab/coda/jevio/test/CompressionTest.java rename to etc/java/jevio/test/CompressionTest.java diff --git a/java/org/jlab/coda/jevio/test/DictTest.java b/etc/java/jevio/test/DictTest.java similarity index 100% rename from java/org/jlab/coda/jevio/test/DictTest.java rename to etc/java/jevio/test/DictTest.java diff --git a/java/org/jlab/coda/jevio/test/ExtractHallDdata.java b/etc/java/jevio/test/ExtractHallDdata.java similarity index 100% rename from java/org/jlab/coda/jevio/test/ExtractHallDdata.java rename to etc/java/jevio/test/ExtractHallDdata.java diff --git a/java/org/jlab/coda/jevio/test/FileTest.java b/etc/java/jevio/test/FileTest.java similarity index 100% rename from java/org/jlab/coda/jevio/test/FileTest.java rename to etc/java/jevio/test/FileTest.java diff --git a/java/org/jlab/coda/jevio/test/FileTestVer6.java b/etc/java/jevio/test/FileTestVer6.java similarity index 100% rename from java/org/jlab/coda/jevio/test/FileTestVer6.java rename to etc/java/jevio/test/FileTestVer6.java diff --git a/java/org/jlab/coda/jevio/test/FileWriteTest.java b/etc/java/jevio/test/FileWriteTest.java similarity index 100% rename from java/org/jlab/coda/jevio/test/FileWriteTest.java rename to etc/java/jevio/test/FileWriteTest.java diff --git a/java/org/jlab/coda/jevio/test/FileWritingSpeedTest.java b/etc/java/jevio/test/FileWritingSpeedTest.java similarity index 100% rename from java/org/jlab/coda/jevio/test/FileWritingSpeedTest.java rename to etc/java/jevio/test/FileWritingSpeedTest.java diff --git a/java/org/jlab/coda/jevio/test/FirstEventTest.java b/etc/java/jevio/test/FirstEventTest.java similarity index 100% rename from java/org/jlab/coda/jevio/test/FirstEventTest.java rename to etc/java/jevio/test/FirstEventTest.java diff --git a/java/org/jlab/coda/jevio/test/HipoTest.java b/etc/java/jevio/test/HipoTest.java similarity index 100% rename from java/org/jlab/coda/jevio/test/HipoTest.java rename to etc/java/jevio/test/HipoTest.java diff --git a/java/org/jlab/coda/jevio/test/README.md b/etc/java/jevio/test/README.md similarity index 100% rename from java/org/jlab/coda/jevio/test/README.md rename to etc/java/jevio/test/README.md diff --git a/java/org/jlab/coda/jevio/test/ReadAggOutput.java b/etc/java/jevio/test/ReadAggOutput.java similarity index 100% rename from java/org/jlab/coda/jevio/test/ReadAggOutput.java rename to etc/java/jevio/test/ReadAggOutput.java diff --git a/java/org/jlab/coda/jevio/test/ReadSequenceTest.java b/etc/java/jevio/test/ReadSequenceTest.java similarity index 100% rename from java/org/jlab/coda/jevio/test/ReadSequenceTest.java rename to etc/java/jevio/test/ReadSequenceTest.java diff --git a/java/org/jlab/coda/jevio/test/ReadWriteTest.java b/etc/java/jevio/test/ReadWriteTest.java similarity index 100% rename from java/org/jlab/coda/jevio/test/ReadWriteTest.java rename to etc/java/jevio/test/ReadWriteTest.java diff --git a/java/org/jlab/coda/jevio/test/ReadWriteV4Test.java b/etc/java/jevio/test/ReadWriteV4Test.java similarity index 100% rename from java/org/jlab/coda/jevio/test/ReadWriteV4Test.java rename to etc/java/jevio/test/ReadWriteV4Test.java diff --git a/java/org/jlab/coda/jevio/test/RecordSupplyTest.java b/etc/java/jevio/test/RecordSupplyTest.java similarity index 100% rename from java/org/jlab/coda/jevio/test/RecordSupplyTest.java rename to etc/java/jevio/test/RecordSupplyTest.java diff --git a/java/org/jlab/coda/jevio/test/SequentialReaderTest.java b/etc/java/jevio/test/SequentialReaderTest.java similarity index 100% rename from java/org/jlab/coda/jevio/test/SequentialReaderTest.java rename to etc/java/jevio/test/SequentialReaderTest.java diff --git a/java/org/jlab/coda/jevio/test/SplitTest.java b/etc/java/jevio/test/SplitTest.java similarity index 100% rename from java/org/jlab/coda/jevio/test/SplitTest.java rename to etc/java/jevio/test/SplitTest.java diff --git a/java/org/jlab/coda/jevio/test/SwapTest.java b/etc/java/jevio/test/SwapTest.java similarity index 100% rename from java/org/jlab/coda/jevio/test/SwapTest.java rename to etc/java/jevio/test/SwapTest.java diff --git a/java/org/jlab/coda/jevio/test/TestBase.java b/etc/java/jevio/test/TestBase.java similarity index 100% rename from java/org/jlab/coda/jevio/test/TestBase.java rename to etc/java/jevio/test/TestBase.java diff --git a/java/org/jlab/coda/jevio/test/TreeBufTest.java b/etc/java/jevio/test/TreeBufTest.java similarity index 100% rename from java/org/jlab/coda/jevio/test/TreeBufTest.java rename to etc/java/jevio/test/TreeBufTest.java diff --git a/java/org/jlab/coda/jevio/test/XmlTest.java b/etc/java/jevio/test/XmlTest.java similarity index 100% rename from java/org/jlab/coda/jevio/test/XmlTest.java rename to etc/java/jevio/test/XmlTest.java From a6a6125d42f25bea7b52139a0272e0cbec1cfd72 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Fri, 30 May 2025 16:52:37 -0500 Subject: [PATCH 29/56] Add JUnit dependency and a first dummy example (borrowed from junit5-samples) --- pom.xml | 7 +++++++ src/test/java/FirstTest.java | 25 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 src/test/java/FirstTest.java diff --git a/pom.xml b/pom.xml index 687c5b7f5..18da432cf 100644 --- a/pom.xml +++ b/pom.xml @@ -47,6 +47,13 @@ disruptor ${disruptor.version} + + + org.junit.jupiter + junit-jupiter + 5.9.3 + test + diff --git a/src/test/java/FirstTest.java b/src/test/java/FirstTest.java new file mode 100644 index 000000000..4f073bead --- /dev/null +++ b/src/test/java/FirstTest.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025. Jefferson Lab (JLab). All rights reserved. Permission + * to use, copy, modify, and distribute this software and its documentation for + * educational, research, and not-for-profit purposes, without fee and without a + * signed licensing agreement. + */ + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInfo; + +@Tag("fast") +class FirstTest { + + @Test + @DisplayName("My 1st JUnit 5 test! 😎") + void myFirstTest(TestInfo testInfo) { + assertEquals(2, 1+1, "1 + 1 should equal 2"); + assertEquals("My 1st JUnit 5 test! 😎", testInfo.getDisplayName(), () -> "TestInfo is injected correctly"); + } + +} \ No newline at end of file From 03bf0bbfdd488fd854a5cf71ce3ffebe1c015bf6 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Mon, 2 Jun 2025 09:28:06 -0500 Subject: [PATCH 30/56] Add workflow action for testing java components --- .github/workflows/java_tests.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/java_tests.yml diff --git a/.github/workflows/java_tests.yml b/.github/workflows/java_tests.yml new file mode 100644 index 000000000..58e3fd3f0 --- /dev/null +++ b/.github/workflows/java_tests.yml @@ -0,0 +1,30 @@ +name: Java Tests (EVIO-6) + +on: + pull_request: + branches: [ main ] + +jobs: + java_test: + name: Run JUnit Tests + runs-on: ubuntu-latest + container: + image: maven:3.9-eclipse-temurin-17-alpine + + steps: + - name: Check out code + uses: actions/checkout@v3 + + # Uncomment to set up Java and Maven manually, if desired + # # (and probably comment out the container image above) + # - name: Set up JDK 17 + # uses: actions/setup-java@v3 + # with: + # distribution: temurin + # java-version: 17 + # Install maven by hand (if not in container image) + # - name: Maven Setup + # run: sudo apt-get update && apt-get install -y maven + + - name: Build and run tests + run: mvn --batch-mode test From 667858027c10ca6b98ff080f64d5b8c8cac52d21 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Mon, 2 Jun 2025 09:37:32 -0500 Subject: [PATCH 31/56] Hopefully this helps it trigger --- .github/workflows/java_tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/java_tests.yml b/.github/workflows/java_tests.yml index 58e3fd3f0..15e3f7b93 100644 --- a/.github/workflows/java_tests.yml +++ b/.github/workflows/java_tests.yml @@ -3,6 +3,7 @@ name: Java Tests (EVIO-6) on: pull_request: branches: [ main ] + workflow_dispatch: jobs: java_test: From df1ad439f020a29ae2d0ad367c9f97e49457adc5 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Mon, 2 Jun 2025 10:42:22 -0500 Subject: [PATCH 32/56] Add init c/c++ testing workflow (and little fix on java one) --- .github/workflows/c_tests.yml | 24 ++++++++++++++++++++++++ .github/workflows/java_tests.yml | 1 - CMakeLists.txt | 4 ++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/c_tests.yml diff --git a/.github/workflows/c_tests.yml b/.github/workflows/c_tests.yml new file mode 100644 index 000000000..0aa39e785 --- /dev/null +++ b/.github/workflows/c_tests.yml @@ -0,0 +1,24 @@ +name: "C/C++ Tests" +on: + pull_request: + branches: [ main ] + +jobs: + cpp_test: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Install dependencies + run: sudo apt-get update && sudo apt-get install -y cmake build-essential libboost-filesystem-dev libboost-thread-dev libboost-chrono-dev liblz4-dev doxygen + + - name: Configure CMake + run: cmake -S . -B build -DMAKE_EXAMPLES=1 + + - name: Build + run: cmake --build build -- -j$(nproc) + + - name: Run tests + working-directory: build + run: ctest --output-on-failure diff --git a/.github/workflows/java_tests.yml b/.github/workflows/java_tests.yml index 15e3f7b93..58e3fd3f0 100644 --- a/.github/workflows/java_tests.yml +++ b/.github/workflows/java_tests.yml @@ -3,7 +3,6 @@ name: Java Tests (EVIO-6) on: pull_request: branches: [ main ] - workflow_dispatch: jobs: java_test: diff --git a/CMakeLists.txt b/CMakeLists.txt index a725b40a3..0856e261f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,7 @@ add_compile_options(-Wall) include(GNUInstallDirs) include(FindPackageHandleStandardArgs) # find_package_handle_standard_args() +include(CTest) # Add custom find_package for Disruptor list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") @@ -251,6 +252,9 @@ if(NOT C_ONLY) ) endif() +# Unit testing setup +# add_executable(test_basic src/test/cpp/test_basic.cpp) # Already done above +# add_test(NAME ctest_test COMMAND bin/ctest_test) # Uninstall target # Removed for now, not yet compatible with building disruptor-cpp internally From 57f28ef4800bb239d94afc2bc13b84c4cebb56ee Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Mon, 2 Jun 2025 11:22:15 -0500 Subject: [PATCH 33/56] Move java lib to standard maven-style directory src/main/java --- build.xml => etc/java/build.xml | 0 .../jlab/coda => etc/java}/jevio/apps/Xml2evio.java | 0 pom.xml | 2 +- .../java}/org/jlab/coda/hipo/CompressionType.java | 0 .../main/java}/org/jlab/coda/hipo/Compressor.java | 0 .../main/java}/org/jlab/coda/hipo/DataUtils.java | 0 .../java}/org/jlab/coda/hipo/Evio6Converter.java | 0 .../java}/org/jlab/coda/hipo/FileEventIndex.java | 0 .../main/java}/org/jlab/coda/hipo/FileHeader.java | 0 .../main/java}/org/jlab/coda/hipo/HeaderType.java | 0 .../main/java}/org/jlab/coda/hipo/HipoException.java | 0 .../main/java}/org/jlab/coda/hipo/Reader.java | 0 .../main/java}/org/jlab/coda/hipo/RecordHeader.java | 0 .../java}/org/jlab/coda/hipo/RecordInputStream.java | 0 .../java}/org/jlab/coda/hipo/RecordOutputStream.java | 0 .../java}/org/jlab/coda/hipo/RecordRingItem.java | 0 .../main/java}/org/jlab/coda/hipo/RecordSupply.java | 0 .../main/java}/org/jlab/coda/hipo/Writer.java | 0 .../main/java}/org/jlab/coda/hipo/WriterMT.java | 0 .../main/java}/org/jlab/coda/jevio/BankHeader.java | 0 .../java}/org/jlab/coda/jevio/BaseStructure.java | 0 .../org/jlab/coda/jevio/BaseStructureHeader.java | 0 .../java}/org/jlab/coda/jevio/BlockHeaderV2.java | 0 .../java}/org/jlab/coda/jevio/BlockHeaderV4.java | 0 .../main/java}/org/jlab/coda/jevio/BlockNode.java | 0 .../org/jlab/coda/jevio/ByteDataTransformer.java | 0 .../org/jlab/coda/jevio/CompactEventBuilder.java | 0 .../java}/org/jlab/coda/jevio/CompositeData.java | 0 .../main/java}/org/jlab/coda/jevio/DataType.java | 0 .../main/java}/org/jlab/coda/jevio/Environment.java | 0 .../main/java}/org/jlab/coda/jevio/EventBuilder.java | 0 .../main/java}/org/jlab/coda/jevio/EventParser.java | 0 .../main/java}/org/jlab/coda/jevio/EventWriter.java | 0 .../java}/org/jlab/coda/jevio/EventWriterUnsync.java | 0 .../org/jlab/coda/jevio/EventWriterUnsyncV4.java | 0 .../java}/org/jlab/coda/jevio/EventWriterV4.java | 0 .../main/java}/org/jlab/coda/jevio/EvioBank.java | 0 .../jlab/coda/jevio/EvioByteArrayOutputStream.java | 0 .../java}/org/jlab/coda/jevio/EvioCompactReader.java | 0 .../jlab/coda/jevio/EvioCompactReaderUnsyncV4.java | 0 .../jlab/coda/jevio/EvioCompactReaderUnsyncV6.java | 0 .../org/jlab/coda/jevio/EvioCompactReaderV4.java | 0 .../org/jlab/coda/jevio/EvioCompactReaderV6.java | 0 .../jlab/coda/jevio/EvioCompactStructureHandler.java | 0 .../org/jlab/coda/jevio/EvioDictionaryEntry.java | 0 .../org/jlab/coda/jevio/EvioDictionaryEntryType.java | 0 .../main/java}/org/jlab/coda/jevio/EvioEvent.java | 0 .../java}/org/jlab/coda/jevio/EvioException.java | 0 .../main/java}/org/jlab/coda/jevio/EvioNode.java | 0 .../main/java}/org/jlab/coda/jevio/EvioNodePool.java | 0 .../java}/org/jlab/coda/jevio/EvioNodeSource.java | 0 .../main/java}/org/jlab/coda/jevio/EvioReader.java | 0 .../org/jlab/coda/jevio/EvioReaderUnsyncV4.java | 0 .../org/jlab/coda/jevio/EvioReaderUnsyncV6.java | 0 .../main/java}/org/jlab/coda/jevio/EvioReaderV4.java | 0 .../main/java}/org/jlab/coda/jevio/EvioReaderV6.java | 0 .../main/java}/org/jlab/coda/jevio/EvioSegment.java | 0 .../java}/org/jlab/coda/jevio/EvioTagSegment.java | 0 .../java}/org/jlab/coda/jevio/EvioXMLDictionary.java | 0 .../main/java}/org/jlab/coda/jevio/IBlockHeader.java | 0 .../org/jlab/coda/jevio/IEvioCompactReader.java | 0 .../main/java}/org/jlab/coda/jevio/IEvioFilter.java | 0 .../java}/org/jlab/coda/jevio/IEvioListener.java | 0 .../org/jlab/coda/jevio/IEvioProgressListener.java | 0 .../main/java}/org/jlab/coda/jevio/IEvioReader.java | 0 .../java}/org/jlab/coda/jevio/IEvioStructure.java | 0 .../main/java}/org/jlab/coda/jevio/IEvioWriter.java | 0 .../java}/org/jlab/coda/jevio/INameProvider.java | 0 .../org/jlab/coda/jevio/MappedMemoryHandler.java | 0 .../main/java}/org/jlab/coda/jevio/NameProvider.java | 0 .../org/jlab/coda/jevio/NameProviderFactory.java | 0 .../main/java}/org/jlab/coda/jevio/ReadStatus.java | 0 .../java}/org/jlab/coda/jevio/SegmentHeader.java | 0 .../java}/org/jlab/coda/jevio/StructureFinder.java | 0 .../org/jlab/coda/jevio/StructureTransformer.java | 0 .../java}/org/jlab/coda/jevio/StructureType.java | 0 .../java}/org/jlab/coda/jevio/TagSegmentHeader.java | 0 .../main/java}/org/jlab/coda/jevio/Utilities.java | 0 .../main/java}/org/jlab/coda/jevio/WriteStatus.java | 0 .../main/java}/org/jlab/coda/jevio/manifest.mf | 0 src/test/cpp/ctest_test.cpp | 12 ++++++++++++ src/test/java/FirstTest.java | 3 ++- 82 files changed, 15 insertions(+), 2 deletions(-) rename build.xml => etc/java/build.xml (100%) rename {java/org/jlab/coda => etc/java}/jevio/apps/Xml2evio.java (100%) rename {java => src/main/java}/org/jlab/coda/hipo/CompressionType.java (100%) rename {java => src/main/java}/org/jlab/coda/hipo/Compressor.java (100%) rename {java => src/main/java}/org/jlab/coda/hipo/DataUtils.java (100%) rename {java => src/main/java}/org/jlab/coda/hipo/Evio6Converter.java (100%) rename {java => src/main/java}/org/jlab/coda/hipo/FileEventIndex.java (100%) rename {java => src/main/java}/org/jlab/coda/hipo/FileHeader.java (100%) rename {java => src/main/java}/org/jlab/coda/hipo/HeaderType.java (100%) rename {java => src/main/java}/org/jlab/coda/hipo/HipoException.java (100%) rename {java => src/main/java}/org/jlab/coda/hipo/Reader.java (100%) rename {java => src/main/java}/org/jlab/coda/hipo/RecordHeader.java (100%) rename {java => src/main/java}/org/jlab/coda/hipo/RecordInputStream.java (100%) rename {java => src/main/java}/org/jlab/coda/hipo/RecordOutputStream.java (100%) rename {java => src/main/java}/org/jlab/coda/hipo/RecordRingItem.java (100%) rename {java => src/main/java}/org/jlab/coda/hipo/RecordSupply.java (100%) rename {java => src/main/java}/org/jlab/coda/hipo/Writer.java (100%) rename {java => src/main/java}/org/jlab/coda/hipo/WriterMT.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/BankHeader.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/BaseStructure.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/BaseStructureHeader.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/BlockHeaderV2.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/BlockHeaderV4.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/BlockNode.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/ByteDataTransformer.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/CompactEventBuilder.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/CompositeData.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/DataType.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/Environment.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EventBuilder.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EventParser.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EventWriter.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EventWriterUnsync.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EventWriterUnsyncV4.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EventWriterV4.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EvioBank.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EvioByteArrayOutputStream.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EvioCompactReader.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EvioCompactReaderUnsyncV4.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EvioCompactReaderUnsyncV6.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EvioCompactReaderV4.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EvioCompactReaderV6.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EvioCompactStructureHandler.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EvioDictionaryEntry.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EvioDictionaryEntryType.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EvioEvent.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EvioException.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EvioNode.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EvioNodePool.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EvioNodeSource.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EvioReader.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EvioReaderUnsyncV4.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EvioReaderUnsyncV6.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EvioReaderV4.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EvioReaderV6.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EvioSegment.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EvioTagSegment.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/EvioXMLDictionary.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/IBlockHeader.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/IEvioCompactReader.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/IEvioFilter.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/IEvioListener.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/IEvioProgressListener.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/IEvioReader.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/IEvioStructure.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/IEvioWriter.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/INameProvider.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/MappedMemoryHandler.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/NameProvider.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/NameProviderFactory.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/ReadStatus.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/SegmentHeader.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/StructureFinder.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/StructureTransformer.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/StructureType.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/TagSegmentHeader.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/Utilities.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/WriteStatus.java (100%) rename {java => src/main/java}/org/jlab/coda/jevio/manifest.mf (100%) create mode 100644 src/test/cpp/ctest_test.cpp diff --git a/build.xml b/etc/java/build.xml similarity index 100% rename from build.xml rename to etc/java/build.xml diff --git a/java/org/jlab/coda/jevio/apps/Xml2evio.java b/etc/java/jevio/apps/Xml2evio.java similarity index 100% rename from java/org/jlab/coda/jevio/apps/Xml2evio.java rename to etc/java/jevio/apps/Xml2evio.java diff --git a/pom.xml b/pom.xml index 18da432cf..dd5105c14 100644 --- a/pom.xml +++ b/pom.xml @@ -58,7 +58,7 @@ - ${project.basedir}/java + diff --git a/java/org/jlab/coda/hipo/CompressionType.java b/src/main/java/org/jlab/coda/hipo/CompressionType.java similarity index 100% rename from java/org/jlab/coda/hipo/CompressionType.java rename to src/main/java/org/jlab/coda/hipo/CompressionType.java diff --git a/java/org/jlab/coda/hipo/Compressor.java b/src/main/java/org/jlab/coda/hipo/Compressor.java similarity index 100% rename from java/org/jlab/coda/hipo/Compressor.java rename to src/main/java/org/jlab/coda/hipo/Compressor.java diff --git a/java/org/jlab/coda/hipo/DataUtils.java b/src/main/java/org/jlab/coda/hipo/DataUtils.java similarity index 100% rename from java/org/jlab/coda/hipo/DataUtils.java rename to src/main/java/org/jlab/coda/hipo/DataUtils.java diff --git a/java/org/jlab/coda/hipo/Evio6Converter.java b/src/main/java/org/jlab/coda/hipo/Evio6Converter.java similarity index 100% rename from java/org/jlab/coda/hipo/Evio6Converter.java rename to src/main/java/org/jlab/coda/hipo/Evio6Converter.java diff --git a/java/org/jlab/coda/hipo/FileEventIndex.java b/src/main/java/org/jlab/coda/hipo/FileEventIndex.java similarity index 100% rename from java/org/jlab/coda/hipo/FileEventIndex.java rename to src/main/java/org/jlab/coda/hipo/FileEventIndex.java diff --git a/java/org/jlab/coda/hipo/FileHeader.java b/src/main/java/org/jlab/coda/hipo/FileHeader.java similarity index 100% rename from java/org/jlab/coda/hipo/FileHeader.java rename to src/main/java/org/jlab/coda/hipo/FileHeader.java diff --git a/java/org/jlab/coda/hipo/HeaderType.java b/src/main/java/org/jlab/coda/hipo/HeaderType.java similarity index 100% rename from java/org/jlab/coda/hipo/HeaderType.java rename to src/main/java/org/jlab/coda/hipo/HeaderType.java diff --git a/java/org/jlab/coda/hipo/HipoException.java b/src/main/java/org/jlab/coda/hipo/HipoException.java similarity index 100% rename from java/org/jlab/coda/hipo/HipoException.java rename to src/main/java/org/jlab/coda/hipo/HipoException.java diff --git a/java/org/jlab/coda/hipo/Reader.java b/src/main/java/org/jlab/coda/hipo/Reader.java similarity index 100% rename from java/org/jlab/coda/hipo/Reader.java rename to src/main/java/org/jlab/coda/hipo/Reader.java diff --git a/java/org/jlab/coda/hipo/RecordHeader.java b/src/main/java/org/jlab/coda/hipo/RecordHeader.java similarity index 100% rename from java/org/jlab/coda/hipo/RecordHeader.java rename to src/main/java/org/jlab/coda/hipo/RecordHeader.java diff --git a/java/org/jlab/coda/hipo/RecordInputStream.java b/src/main/java/org/jlab/coda/hipo/RecordInputStream.java similarity index 100% rename from java/org/jlab/coda/hipo/RecordInputStream.java rename to src/main/java/org/jlab/coda/hipo/RecordInputStream.java diff --git a/java/org/jlab/coda/hipo/RecordOutputStream.java b/src/main/java/org/jlab/coda/hipo/RecordOutputStream.java similarity index 100% rename from java/org/jlab/coda/hipo/RecordOutputStream.java rename to src/main/java/org/jlab/coda/hipo/RecordOutputStream.java diff --git a/java/org/jlab/coda/hipo/RecordRingItem.java b/src/main/java/org/jlab/coda/hipo/RecordRingItem.java similarity index 100% rename from java/org/jlab/coda/hipo/RecordRingItem.java rename to src/main/java/org/jlab/coda/hipo/RecordRingItem.java diff --git a/java/org/jlab/coda/hipo/RecordSupply.java b/src/main/java/org/jlab/coda/hipo/RecordSupply.java similarity index 100% rename from java/org/jlab/coda/hipo/RecordSupply.java rename to src/main/java/org/jlab/coda/hipo/RecordSupply.java diff --git a/java/org/jlab/coda/hipo/Writer.java b/src/main/java/org/jlab/coda/hipo/Writer.java similarity index 100% rename from java/org/jlab/coda/hipo/Writer.java rename to src/main/java/org/jlab/coda/hipo/Writer.java diff --git a/java/org/jlab/coda/hipo/WriterMT.java b/src/main/java/org/jlab/coda/hipo/WriterMT.java similarity index 100% rename from java/org/jlab/coda/hipo/WriterMT.java rename to src/main/java/org/jlab/coda/hipo/WriterMT.java diff --git a/java/org/jlab/coda/jevio/BankHeader.java b/src/main/java/org/jlab/coda/jevio/BankHeader.java similarity index 100% rename from java/org/jlab/coda/jevio/BankHeader.java rename to src/main/java/org/jlab/coda/jevio/BankHeader.java diff --git a/java/org/jlab/coda/jevio/BaseStructure.java b/src/main/java/org/jlab/coda/jevio/BaseStructure.java similarity index 100% rename from java/org/jlab/coda/jevio/BaseStructure.java rename to src/main/java/org/jlab/coda/jevio/BaseStructure.java diff --git a/java/org/jlab/coda/jevio/BaseStructureHeader.java b/src/main/java/org/jlab/coda/jevio/BaseStructureHeader.java similarity index 100% rename from java/org/jlab/coda/jevio/BaseStructureHeader.java rename to src/main/java/org/jlab/coda/jevio/BaseStructureHeader.java diff --git a/java/org/jlab/coda/jevio/BlockHeaderV2.java b/src/main/java/org/jlab/coda/jevio/BlockHeaderV2.java similarity index 100% rename from java/org/jlab/coda/jevio/BlockHeaderV2.java rename to src/main/java/org/jlab/coda/jevio/BlockHeaderV2.java diff --git a/java/org/jlab/coda/jevio/BlockHeaderV4.java b/src/main/java/org/jlab/coda/jevio/BlockHeaderV4.java similarity index 100% rename from java/org/jlab/coda/jevio/BlockHeaderV4.java rename to src/main/java/org/jlab/coda/jevio/BlockHeaderV4.java diff --git a/java/org/jlab/coda/jevio/BlockNode.java b/src/main/java/org/jlab/coda/jevio/BlockNode.java similarity index 100% rename from java/org/jlab/coda/jevio/BlockNode.java rename to src/main/java/org/jlab/coda/jevio/BlockNode.java diff --git a/java/org/jlab/coda/jevio/ByteDataTransformer.java b/src/main/java/org/jlab/coda/jevio/ByteDataTransformer.java similarity index 100% rename from java/org/jlab/coda/jevio/ByteDataTransformer.java rename to src/main/java/org/jlab/coda/jevio/ByteDataTransformer.java diff --git a/java/org/jlab/coda/jevio/CompactEventBuilder.java b/src/main/java/org/jlab/coda/jevio/CompactEventBuilder.java similarity index 100% rename from java/org/jlab/coda/jevio/CompactEventBuilder.java rename to src/main/java/org/jlab/coda/jevio/CompactEventBuilder.java diff --git a/java/org/jlab/coda/jevio/CompositeData.java b/src/main/java/org/jlab/coda/jevio/CompositeData.java similarity index 100% rename from java/org/jlab/coda/jevio/CompositeData.java rename to src/main/java/org/jlab/coda/jevio/CompositeData.java diff --git a/java/org/jlab/coda/jevio/DataType.java b/src/main/java/org/jlab/coda/jevio/DataType.java similarity index 100% rename from java/org/jlab/coda/jevio/DataType.java rename to src/main/java/org/jlab/coda/jevio/DataType.java diff --git a/java/org/jlab/coda/jevio/Environment.java b/src/main/java/org/jlab/coda/jevio/Environment.java similarity index 100% rename from java/org/jlab/coda/jevio/Environment.java rename to src/main/java/org/jlab/coda/jevio/Environment.java diff --git a/java/org/jlab/coda/jevio/EventBuilder.java b/src/main/java/org/jlab/coda/jevio/EventBuilder.java similarity index 100% rename from java/org/jlab/coda/jevio/EventBuilder.java rename to src/main/java/org/jlab/coda/jevio/EventBuilder.java diff --git a/java/org/jlab/coda/jevio/EventParser.java b/src/main/java/org/jlab/coda/jevio/EventParser.java similarity index 100% rename from java/org/jlab/coda/jevio/EventParser.java rename to src/main/java/org/jlab/coda/jevio/EventParser.java diff --git a/java/org/jlab/coda/jevio/EventWriter.java b/src/main/java/org/jlab/coda/jevio/EventWriter.java similarity index 100% rename from java/org/jlab/coda/jevio/EventWriter.java rename to src/main/java/org/jlab/coda/jevio/EventWriter.java diff --git a/java/org/jlab/coda/jevio/EventWriterUnsync.java b/src/main/java/org/jlab/coda/jevio/EventWriterUnsync.java similarity index 100% rename from java/org/jlab/coda/jevio/EventWriterUnsync.java rename to src/main/java/org/jlab/coda/jevio/EventWriterUnsync.java diff --git a/java/org/jlab/coda/jevio/EventWriterUnsyncV4.java b/src/main/java/org/jlab/coda/jevio/EventWriterUnsyncV4.java similarity index 100% rename from java/org/jlab/coda/jevio/EventWriterUnsyncV4.java rename to src/main/java/org/jlab/coda/jevio/EventWriterUnsyncV4.java diff --git a/java/org/jlab/coda/jevio/EventWriterV4.java b/src/main/java/org/jlab/coda/jevio/EventWriterV4.java similarity index 100% rename from java/org/jlab/coda/jevio/EventWriterV4.java rename to src/main/java/org/jlab/coda/jevio/EventWriterV4.java diff --git a/java/org/jlab/coda/jevio/EvioBank.java b/src/main/java/org/jlab/coda/jevio/EvioBank.java similarity index 100% rename from java/org/jlab/coda/jevio/EvioBank.java rename to src/main/java/org/jlab/coda/jevio/EvioBank.java diff --git a/java/org/jlab/coda/jevio/EvioByteArrayOutputStream.java b/src/main/java/org/jlab/coda/jevio/EvioByteArrayOutputStream.java similarity index 100% rename from java/org/jlab/coda/jevio/EvioByteArrayOutputStream.java rename to src/main/java/org/jlab/coda/jevio/EvioByteArrayOutputStream.java diff --git a/java/org/jlab/coda/jevio/EvioCompactReader.java b/src/main/java/org/jlab/coda/jevio/EvioCompactReader.java similarity index 100% rename from java/org/jlab/coda/jevio/EvioCompactReader.java rename to src/main/java/org/jlab/coda/jevio/EvioCompactReader.java diff --git a/java/org/jlab/coda/jevio/EvioCompactReaderUnsyncV4.java b/src/main/java/org/jlab/coda/jevio/EvioCompactReaderUnsyncV4.java similarity index 100% rename from java/org/jlab/coda/jevio/EvioCompactReaderUnsyncV4.java rename to src/main/java/org/jlab/coda/jevio/EvioCompactReaderUnsyncV4.java diff --git a/java/org/jlab/coda/jevio/EvioCompactReaderUnsyncV6.java b/src/main/java/org/jlab/coda/jevio/EvioCompactReaderUnsyncV6.java similarity index 100% rename from java/org/jlab/coda/jevio/EvioCompactReaderUnsyncV6.java rename to src/main/java/org/jlab/coda/jevio/EvioCompactReaderUnsyncV6.java diff --git a/java/org/jlab/coda/jevio/EvioCompactReaderV4.java b/src/main/java/org/jlab/coda/jevio/EvioCompactReaderV4.java similarity index 100% rename from java/org/jlab/coda/jevio/EvioCompactReaderV4.java rename to src/main/java/org/jlab/coda/jevio/EvioCompactReaderV4.java diff --git a/java/org/jlab/coda/jevio/EvioCompactReaderV6.java b/src/main/java/org/jlab/coda/jevio/EvioCompactReaderV6.java similarity index 100% rename from java/org/jlab/coda/jevio/EvioCompactReaderV6.java rename to src/main/java/org/jlab/coda/jevio/EvioCompactReaderV6.java diff --git a/java/org/jlab/coda/jevio/EvioCompactStructureHandler.java b/src/main/java/org/jlab/coda/jevio/EvioCompactStructureHandler.java similarity index 100% rename from java/org/jlab/coda/jevio/EvioCompactStructureHandler.java rename to src/main/java/org/jlab/coda/jevio/EvioCompactStructureHandler.java diff --git a/java/org/jlab/coda/jevio/EvioDictionaryEntry.java b/src/main/java/org/jlab/coda/jevio/EvioDictionaryEntry.java similarity index 100% rename from java/org/jlab/coda/jevio/EvioDictionaryEntry.java rename to src/main/java/org/jlab/coda/jevio/EvioDictionaryEntry.java diff --git a/java/org/jlab/coda/jevio/EvioDictionaryEntryType.java b/src/main/java/org/jlab/coda/jevio/EvioDictionaryEntryType.java similarity index 100% rename from java/org/jlab/coda/jevio/EvioDictionaryEntryType.java rename to src/main/java/org/jlab/coda/jevio/EvioDictionaryEntryType.java diff --git a/java/org/jlab/coda/jevio/EvioEvent.java b/src/main/java/org/jlab/coda/jevio/EvioEvent.java similarity index 100% rename from java/org/jlab/coda/jevio/EvioEvent.java rename to src/main/java/org/jlab/coda/jevio/EvioEvent.java diff --git a/java/org/jlab/coda/jevio/EvioException.java b/src/main/java/org/jlab/coda/jevio/EvioException.java similarity index 100% rename from java/org/jlab/coda/jevio/EvioException.java rename to src/main/java/org/jlab/coda/jevio/EvioException.java diff --git a/java/org/jlab/coda/jevio/EvioNode.java b/src/main/java/org/jlab/coda/jevio/EvioNode.java similarity index 100% rename from java/org/jlab/coda/jevio/EvioNode.java rename to src/main/java/org/jlab/coda/jevio/EvioNode.java diff --git a/java/org/jlab/coda/jevio/EvioNodePool.java b/src/main/java/org/jlab/coda/jevio/EvioNodePool.java similarity index 100% rename from java/org/jlab/coda/jevio/EvioNodePool.java rename to src/main/java/org/jlab/coda/jevio/EvioNodePool.java diff --git a/java/org/jlab/coda/jevio/EvioNodeSource.java b/src/main/java/org/jlab/coda/jevio/EvioNodeSource.java similarity index 100% rename from java/org/jlab/coda/jevio/EvioNodeSource.java rename to src/main/java/org/jlab/coda/jevio/EvioNodeSource.java diff --git a/java/org/jlab/coda/jevio/EvioReader.java b/src/main/java/org/jlab/coda/jevio/EvioReader.java similarity index 100% rename from java/org/jlab/coda/jevio/EvioReader.java rename to src/main/java/org/jlab/coda/jevio/EvioReader.java diff --git a/java/org/jlab/coda/jevio/EvioReaderUnsyncV4.java b/src/main/java/org/jlab/coda/jevio/EvioReaderUnsyncV4.java similarity index 100% rename from java/org/jlab/coda/jevio/EvioReaderUnsyncV4.java rename to src/main/java/org/jlab/coda/jevio/EvioReaderUnsyncV4.java diff --git a/java/org/jlab/coda/jevio/EvioReaderUnsyncV6.java b/src/main/java/org/jlab/coda/jevio/EvioReaderUnsyncV6.java similarity index 100% rename from java/org/jlab/coda/jevio/EvioReaderUnsyncV6.java rename to src/main/java/org/jlab/coda/jevio/EvioReaderUnsyncV6.java diff --git a/java/org/jlab/coda/jevio/EvioReaderV4.java b/src/main/java/org/jlab/coda/jevio/EvioReaderV4.java similarity index 100% rename from java/org/jlab/coda/jevio/EvioReaderV4.java rename to src/main/java/org/jlab/coda/jevio/EvioReaderV4.java diff --git a/java/org/jlab/coda/jevio/EvioReaderV6.java b/src/main/java/org/jlab/coda/jevio/EvioReaderV6.java similarity index 100% rename from java/org/jlab/coda/jevio/EvioReaderV6.java rename to src/main/java/org/jlab/coda/jevio/EvioReaderV6.java diff --git a/java/org/jlab/coda/jevio/EvioSegment.java b/src/main/java/org/jlab/coda/jevio/EvioSegment.java similarity index 100% rename from java/org/jlab/coda/jevio/EvioSegment.java rename to src/main/java/org/jlab/coda/jevio/EvioSegment.java diff --git a/java/org/jlab/coda/jevio/EvioTagSegment.java b/src/main/java/org/jlab/coda/jevio/EvioTagSegment.java similarity index 100% rename from java/org/jlab/coda/jevio/EvioTagSegment.java rename to src/main/java/org/jlab/coda/jevio/EvioTagSegment.java diff --git a/java/org/jlab/coda/jevio/EvioXMLDictionary.java b/src/main/java/org/jlab/coda/jevio/EvioXMLDictionary.java similarity index 100% rename from java/org/jlab/coda/jevio/EvioXMLDictionary.java rename to src/main/java/org/jlab/coda/jevio/EvioXMLDictionary.java diff --git a/java/org/jlab/coda/jevio/IBlockHeader.java b/src/main/java/org/jlab/coda/jevio/IBlockHeader.java similarity index 100% rename from java/org/jlab/coda/jevio/IBlockHeader.java rename to src/main/java/org/jlab/coda/jevio/IBlockHeader.java diff --git a/java/org/jlab/coda/jevio/IEvioCompactReader.java b/src/main/java/org/jlab/coda/jevio/IEvioCompactReader.java similarity index 100% rename from java/org/jlab/coda/jevio/IEvioCompactReader.java rename to src/main/java/org/jlab/coda/jevio/IEvioCompactReader.java diff --git a/java/org/jlab/coda/jevio/IEvioFilter.java b/src/main/java/org/jlab/coda/jevio/IEvioFilter.java similarity index 100% rename from java/org/jlab/coda/jevio/IEvioFilter.java rename to src/main/java/org/jlab/coda/jevio/IEvioFilter.java diff --git a/java/org/jlab/coda/jevio/IEvioListener.java b/src/main/java/org/jlab/coda/jevio/IEvioListener.java similarity index 100% rename from java/org/jlab/coda/jevio/IEvioListener.java rename to src/main/java/org/jlab/coda/jevio/IEvioListener.java diff --git a/java/org/jlab/coda/jevio/IEvioProgressListener.java b/src/main/java/org/jlab/coda/jevio/IEvioProgressListener.java similarity index 100% rename from java/org/jlab/coda/jevio/IEvioProgressListener.java rename to src/main/java/org/jlab/coda/jevio/IEvioProgressListener.java diff --git a/java/org/jlab/coda/jevio/IEvioReader.java b/src/main/java/org/jlab/coda/jevio/IEvioReader.java similarity index 100% rename from java/org/jlab/coda/jevio/IEvioReader.java rename to src/main/java/org/jlab/coda/jevio/IEvioReader.java diff --git a/java/org/jlab/coda/jevio/IEvioStructure.java b/src/main/java/org/jlab/coda/jevio/IEvioStructure.java similarity index 100% rename from java/org/jlab/coda/jevio/IEvioStructure.java rename to src/main/java/org/jlab/coda/jevio/IEvioStructure.java diff --git a/java/org/jlab/coda/jevio/IEvioWriter.java b/src/main/java/org/jlab/coda/jevio/IEvioWriter.java similarity index 100% rename from java/org/jlab/coda/jevio/IEvioWriter.java rename to src/main/java/org/jlab/coda/jevio/IEvioWriter.java diff --git a/java/org/jlab/coda/jevio/INameProvider.java b/src/main/java/org/jlab/coda/jevio/INameProvider.java similarity index 100% rename from java/org/jlab/coda/jevio/INameProvider.java rename to src/main/java/org/jlab/coda/jevio/INameProvider.java diff --git a/java/org/jlab/coda/jevio/MappedMemoryHandler.java b/src/main/java/org/jlab/coda/jevio/MappedMemoryHandler.java similarity index 100% rename from java/org/jlab/coda/jevio/MappedMemoryHandler.java rename to src/main/java/org/jlab/coda/jevio/MappedMemoryHandler.java diff --git a/java/org/jlab/coda/jevio/NameProvider.java b/src/main/java/org/jlab/coda/jevio/NameProvider.java similarity index 100% rename from java/org/jlab/coda/jevio/NameProvider.java rename to src/main/java/org/jlab/coda/jevio/NameProvider.java diff --git a/java/org/jlab/coda/jevio/NameProviderFactory.java b/src/main/java/org/jlab/coda/jevio/NameProviderFactory.java similarity index 100% rename from java/org/jlab/coda/jevio/NameProviderFactory.java rename to src/main/java/org/jlab/coda/jevio/NameProviderFactory.java diff --git a/java/org/jlab/coda/jevio/ReadStatus.java b/src/main/java/org/jlab/coda/jevio/ReadStatus.java similarity index 100% rename from java/org/jlab/coda/jevio/ReadStatus.java rename to src/main/java/org/jlab/coda/jevio/ReadStatus.java diff --git a/java/org/jlab/coda/jevio/SegmentHeader.java b/src/main/java/org/jlab/coda/jevio/SegmentHeader.java similarity index 100% rename from java/org/jlab/coda/jevio/SegmentHeader.java rename to src/main/java/org/jlab/coda/jevio/SegmentHeader.java diff --git a/java/org/jlab/coda/jevio/StructureFinder.java b/src/main/java/org/jlab/coda/jevio/StructureFinder.java similarity index 100% rename from java/org/jlab/coda/jevio/StructureFinder.java rename to src/main/java/org/jlab/coda/jevio/StructureFinder.java diff --git a/java/org/jlab/coda/jevio/StructureTransformer.java b/src/main/java/org/jlab/coda/jevio/StructureTransformer.java similarity index 100% rename from java/org/jlab/coda/jevio/StructureTransformer.java rename to src/main/java/org/jlab/coda/jevio/StructureTransformer.java diff --git a/java/org/jlab/coda/jevio/StructureType.java b/src/main/java/org/jlab/coda/jevio/StructureType.java similarity index 100% rename from java/org/jlab/coda/jevio/StructureType.java rename to src/main/java/org/jlab/coda/jevio/StructureType.java diff --git a/java/org/jlab/coda/jevio/TagSegmentHeader.java b/src/main/java/org/jlab/coda/jevio/TagSegmentHeader.java similarity index 100% rename from java/org/jlab/coda/jevio/TagSegmentHeader.java rename to src/main/java/org/jlab/coda/jevio/TagSegmentHeader.java diff --git a/java/org/jlab/coda/jevio/Utilities.java b/src/main/java/org/jlab/coda/jevio/Utilities.java similarity index 100% rename from java/org/jlab/coda/jevio/Utilities.java rename to src/main/java/org/jlab/coda/jevio/Utilities.java diff --git a/java/org/jlab/coda/jevio/WriteStatus.java b/src/main/java/org/jlab/coda/jevio/WriteStatus.java similarity index 100% rename from java/org/jlab/coda/jevio/WriteStatus.java rename to src/main/java/org/jlab/coda/jevio/WriteStatus.java diff --git a/java/org/jlab/coda/jevio/manifest.mf b/src/main/java/org/jlab/coda/jevio/manifest.mf similarity index 100% rename from java/org/jlab/coda/jevio/manifest.mf rename to src/main/java/org/jlab/coda/jevio/manifest.mf diff --git a/src/test/cpp/ctest_test.cpp b/src/test/cpp/ctest_test.cpp new file mode 100644 index 000000000..3bde2d69d --- /dev/null +++ b/src/test/cpp/ctest_test.cpp @@ -0,0 +1,12 @@ +#include +#include +#include "eviocc.h" + +int main() { + // Example test: simple arithmetic + assert(1 + 1 == 2); + std::cout << "Basic arithmetic test passed.\n"; + + std::cout << "All tests passed.\n"; + return 0; +} diff --git a/src/test/java/FirstTest.java b/src/test/java/FirstTest.java index 4f073bead..0a3c32f40 100644 --- a/src/test/java/FirstTest.java +++ b/src/test/java/FirstTest.java @@ -12,7 +12,8 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; -@Tag("fast") +@Tag("fast") // Run when selecting "fast" category of tests + class FirstTest { @Test From 55ee186aef04caa69c3b2f3794880ccaa52f9975 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Mon, 2 Jun 2025 12:07:21 -0500 Subject: [PATCH 34/56] More cleanup: move jars, add additional READMEs --- etc/README.md | 7 ++++--- {java => etc/java}/jars/disruptor-3.4.3.jar | Bin {java => etc/java}/jars/java15/disruptor-4.0.0.jar | Bin {java => etc/java}/jars/java15/jevio-6.0.jar | Bin {java => etc/java}/jars/java15/lz4-java.1.8.0.jar | Bin {java => etc/java}/jars/java8/disruptor-3.4.3.jar | Bin {java => etc/java}/jars/java8/jevio-6.0.jar | Bin {java => etc/java}/jars/java8/lz4-java.1.8.0.jar | Bin {java => etc/java}/jars/lz4-java.1.8.0.jar | Bin java/jars/README.md | 5 +++++ src/README.md | 9 +++++++++ src/test/cpp/DictTest.cpp | 4 ++-- 12 files changed, 20 insertions(+), 5 deletions(-) rename {java => etc/java}/jars/disruptor-3.4.3.jar (100%) rename {java => etc/java}/jars/java15/disruptor-4.0.0.jar (100%) rename {java => etc/java}/jars/java15/jevio-6.0.jar (100%) rename {java => etc/java}/jars/java15/lz4-java.1.8.0.jar (100%) rename {java => etc/java}/jars/java8/disruptor-3.4.3.jar (100%) rename {java => etc/java}/jars/java8/jevio-6.0.jar (100%) rename {java => etc/java}/jars/java8/lz4-java.1.8.0.jar (100%) rename {java => etc/java}/jars/lz4-java.1.8.0.jar (100%) create mode 100644 java/jars/README.md create mode 100644 src/README.md diff --git a/etc/README.md b/etc/README.md index 061a9708b..29f496203 100644 --- a/etc/README.md +++ b/etc/README.md @@ -2,9 +2,10 @@ This folder collects old scripts, documentation, and files from evio versions 1-5. -| File | Description +| File/Folder | Description |------------|---------------------------------------------------------------------- +| [java](java) | Collection of Java test programs, Xml2evio program, old jar dependency files, and ant build xml. | +| [src](src) | Collection of C/C++ programs from previous evio versions | | [CHANGES](CHANGES) | Change log for evio versions 4-5 | -| [setup_java](setup_java) | Setup script for choosing java version (either Java 8 or 15). | | [cmake_uninstall.cmake.in](cmake_uninstall.cmake.in) | Uninstallation script for evio-5 | - +| [setup_java](setup_java) | Setup script for choosing java version (either Java 8 or 15). | diff --git a/java/jars/disruptor-3.4.3.jar b/etc/java/jars/disruptor-3.4.3.jar similarity index 100% rename from java/jars/disruptor-3.4.3.jar rename to etc/java/jars/disruptor-3.4.3.jar diff --git a/java/jars/java15/disruptor-4.0.0.jar b/etc/java/jars/java15/disruptor-4.0.0.jar similarity index 100% rename from java/jars/java15/disruptor-4.0.0.jar rename to etc/java/jars/java15/disruptor-4.0.0.jar diff --git a/java/jars/java15/jevio-6.0.jar b/etc/java/jars/java15/jevio-6.0.jar similarity index 100% rename from java/jars/java15/jevio-6.0.jar rename to etc/java/jars/java15/jevio-6.0.jar diff --git a/java/jars/java15/lz4-java.1.8.0.jar b/etc/java/jars/java15/lz4-java.1.8.0.jar similarity index 100% rename from java/jars/java15/lz4-java.1.8.0.jar rename to etc/java/jars/java15/lz4-java.1.8.0.jar diff --git a/java/jars/java8/disruptor-3.4.3.jar b/etc/java/jars/java8/disruptor-3.4.3.jar similarity index 100% rename from java/jars/java8/disruptor-3.4.3.jar rename to etc/java/jars/java8/disruptor-3.4.3.jar diff --git a/java/jars/java8/jevio-6.0.jar b/etc/java/jars/java8/jevio-6.0.jar similarity index 100% rename from java/jars/java8/jevio-6.0.jar rename to etc/java/jars/java8/jevio-6.0.jar diff --git a/java/jars/java8/lz4-java.1.8.0.jar b/etc/java/jars/java8/lz4-java.1.8.0.jar similarity index 100% rename from java/jars/java8/lz4-java.1.8.0.jar rename to etc/java/jars/java8/lz4-java.1.8.0.jar diff --git a/java/jars/lz4-java.1.8.0.jar b/etc/java/jars/lz4-java.1.8.0.jar similarity index 100% rename from java/jars/lz4-java.1.8.0.jar rename to etc/java/jars/lz4-java.1.8.0.jar diff --git a/java/jars/README.md b/java/jars/README.md new file mode 100644 index 000000000..b45124075 --- /dev/null +++ b/java/jars/README.md @@ -0,0 +1,5 @@ +# **Java JARs Folder** + +This folder contains any jar file dependencies required by the EVIO Java library that are not retrieved directly from the Maven repository. At present, only the disruptor library needs to be added from here. + +Note that the disruptor 4.0.0 jar file included comes from a [JeffersonLab fork](https://github.com/JeffersonLab/disruptor) of the original lmax Java library. This forked repository adds an additional function (SpinCountBackoffWaitStrategy) that is required in the evio Java Library. \ No newline at end of file diff --git a/src/README.md b/src/README.md new file mode 100644 index 000000000..88750f06a --- /dev/null +++ b/src/README.md @@ -0,0 +1,9 @@ +# **Source Code fo EVIO** + +| Folder | Contents +|------------|---------------------------------------------------------------------- +| [libsrc](libsrc) | EVIO C library | +| [libsrc++](libsrc++) | EVIO C++ library | +| [main/java](main/java) | EVIO Java Library | +| [test](test) | For internal testing of Java, C, C libraries. | + diff --git a/src/test/cpp/DictTest.cpp b/src/test/cpp/DictTest.cpp index eae1c7e59..78223ead3 100644 --- a/src/test/cpp/DictTest.cpp +++ b/src/test/cpp/DictTest.cpp @@ -272,8 +272,8 @@ namespace evio { uint16_t tag = 0; uint8_t num = 0; - bool gotTag = dict.getTag("second(1)", &tag); - bool gotNum = dict.getNum("second(1)", &num); + // bool gotTag = dict.getTag("second(1)", &tag); + // bool gotNum = dict.getNum("second(1)", &num); bool exists = dict.exists("second(1)"); From 072df688d3b3d27fc225c5fd6d56ee5f666c00ea Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Mon, 2 Jun 2025 12:17:09 -0500 Subject: [PATCH 35/56] Move c++ tutorials to subfolder --- CMakeLists.txt | 6 +++--- src/README.md | 2 +- tutorials/README.md | 3 +++ tutorials/{ => cpp}/ConvertFormats.cpp | 0 tutorials/{ => cpp}/EVIO_v4_to_v6.cpp | 0 tutorials/{ => cpp}/EvioTestHelper.h | 0 tutorials/{ => cpp}/PrintXMLDict.cpp | 0 tutorials/{ => cpp}/ReadCLASFile.cpp | 0 tutorials/{ => cpp}/ReadHIPO_clas_file.cpp | 0 tutorials/{ => cpp}/WriteFilePseudoPhysicsEventExtended.cpp | 0 tutorials/{ => cpp}/WritePseudoPhys_builder.cpp | 0 tutorials/{ => cpp}/WritePseudoPhys_compact.cpp | 0 tutorials/{ => cpp}/WritePseudoPhys_simple.cpp | 0 13 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 tutorials/README.md rename tutorials/{ => cpp}/ConvertFormats.cpp (100%) rename tutorials/{ => cpp}/EVIO_v4_to_v6.cpp (100%) rename tutorials/{ => cpp}/EvioTestHelper.h (100%) rename tutorials/{ => cpp}/PrintXMLDict.cpp (100%) rename tutorials/{ => cpp}/ReadCLASFile.cpp (100%) rename tutorials/{ => cpp}/ReadHIPO_clas_file.cpp (100%) rename tutorials/{ => cpp}/WriteFilePseudoPhysicsEventExtended.cpp (100%) rename tutorials/{ => cpp}/WritePseudoPhys_builder.cpp (100%) rename tutorials/{ => cpp}/WritePseudoPhys_compact.cpp (100%) rename tutorials/{ => cpp}/WritePseudoPhys_simple.cpp (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0856e261f..9ae64ff91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,10 +98,10 @@ file(GLOB CPP_LIB_FILES "src/libsrc++/*.cpp") file(GLOB CPP_HEADER_FILES "src/libsrc++/*.h") # A few extras required if(MAKE_EXAMPLES) - file(GLOB TEST "src/test/cpp/*.cpp" "tutorials/*.cpp") + file(GLOB TEST "src/test/cpp/*.cpp" "tutorials/cpp/*.cpp") file(GLOB TESTC "src/test/c/*.c") - list(APPEND CPP_HEADER_FILES src/test/cpp/TestBase.h tutorials/EvioTestHelper.h) - list(APPEND CPP_LIB_FILES src/test/cpp/TestBase.cxx tutorials/EvioTestHelper.h) + list(APPEND CPP_HEADER_FILES src/test/cpp/TestBase.h tutorials/cpp/EvioTestHelper.h) + list(APPEND CPP_LIB_FILES src/test/cpp/TestBase.cxx tutorials/cpp/EvioTestHelper.h) endif() # BUILD C++ LIBRARY (unless otherwise specified) diff --git a/src/README.md b/src/README.md index 88750f06a..298a3ff5e 100644 --- a/src/README.md +++ b/src/README.md @@ -1,4 +1,4 @@ -# **Source Code fo EVIO** +# **Source Code for EVIO** | Folder | Contents |------------|---------------------------------------------------------------------- diff --git a/tutorials/README.md b/tutorials/README.md new file mode 100644 index 000000000..8308c36e5 --- /dev/null +++ b/tutorials/README.md @@ -0,0 +1,3 @@ +# ** Code Tutorials ** + +Examples for using the evio C/C++/Java libraries. These are intended as examples for developers using EVIO as just one package in a larger software suite. See contents within each folder for more information. \ No newline at end of file diff --git a/tutorials/ConvertFormats.cpp b/tutorials/cpp/ConvertFormats.cpp similarity index 100% rename from tutorials/ConvertFormats.cpp rename to tutorials/cpp/ConvertFormats.cpp diff --git a/tutorials/EVIO_v4_to_v6.cpp b/tutorials/cpp/EVIO_v4_to_v6.cpp similarity index 100% rename from tutorials/EVIO_v4_to_v6.cpp rename to tutorials/cpp/EVIO_v4_to_v6.cpp diff --git a/tutorials/EvioTestHelper.h b/tutorials/cpp/EvioTestHelper.h similarity index 100% rename from tutorials/EvioTestHelper.h rename to tutorials/cpp/EvioTestHelper.h diff --git a/tutorials/PrintXMLDict.cpp b/tutorials/cpp/PrintXMLDict.cpp similarity index 100% rename from tutorials/PrintXMLDict.cpp rename to tutorials/cpp/PrintXMLDict.cpp diff --git a/tutorials/ReadCLASFile.cpp b/tutorials/cpp/ReadCLASFile.cpp similarity index 100% rename from tutorials/ReadCLASFile.cpp rename to tutorials/cpp/ReadCLASFile.cpp diff --git a/tutorials/ReadHIPO_clas_file.cpp b/tutorials/cpp/ReadHIPO_clas_file.cpp similarity index 100% rename from tutorials/ReadHIPO_clas_file.cpp rename to tutorials/cpp/ReadHIPO_clas_file.cpp diff --git a/tutorials/WriteFilePseudoPhysicsEventExtended.cpp b/tutorials/cpp/WriteFilePseudoPhysicsEventExtended.cpp similarity index 100% rename from tutorials/WriteFilePseudoPhysicsEventExtended.cpp rename to tutorials/cpp/WriteFilePseudoPhysicsEventExtended.cpp diff --git a/tutorials/WritePseudoPhys_builder.cpp b/tutorials/cpp/WritePseudoPhys_builder.cpp similarity index 100% rename from tutorials/WritePseudoPhys_builder.cpp rename to tutorials/cpp/WritePseudoPhys_builder.cpp diff --git a/tutorials/WritePseudoPhys_compact.cpp b/tutorials/cpp/WritePseudoPhys_compact.cpp similarity index 100% rename from tutorials/WritePseudoPhys_compact.cpp rename to tutorials/cpp/WritePseudoPhys_compact.cpp diff --git a/tutorials/WritePseudoPhys_simple.cpp b/tutorials/cpp/WritePseudoPhys_simple.cpp similarity index 100% rename from tutorials/WritePseudoPhys_simple.cpp rename to tutorials/cpp/WritePseudoPhys_simple.cpp From d85d588950f1567ba13001d189244c68db99a9a8 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Fri, 6 Jun 2025 10:56:48 -0500 Subject: [PATCH 36/56] Move Carl's tests to `etc/` folder, add init tests that will supercede --- CMakeLists.txt | 4 +- {src => etc/src}/test/c/SConscript | 0 {src => etc/src}/test/c/evReadPipe.c | 0 {src => etc/src}/test/c/evTestFile.c | 0 {src => etc/src}/test/c/evWritePipe.c | 0 {src => etc/src}/test/c/evtest.c | 0 {src => etc/src}/test/c/evtest2.c | 0 {src => etc/src}/test/c/evtest3.c | 0 {src => etc/src}/test/c/evtestAppend.c | 0 {src => etc/src}/test/c/evtestBuf.c | 0 {src => etc/src}/test/c/evtestBuf2.c | 0 {src => etc/src}/test/c/evtestRead.c | 0 {src => etc/src}/test/c/evtestRio.c | 0 {src => etc/src}/test/c/evtestSock.c | 0 {src => etc/src}/test/c/evtestWriteFile.c | 0 {src => etc/src}/test/c/splitNameTest.c | 0 {src => etc/src}/test/c/splitTest.c | 0 {src => etc/src}/test/cpp/BigFileWrite.cpp | 0 .../src}/test/cpp/BigFileWritePrimitive.cpp | 0 .../src}/test/cpp/CompactBuilder_Test.cpp | 0 .../test/cpp/CompactReaderAddSubtractTest.cpp | 0 .../src}/test/cpp/CompactReaderBugTest.cpp | 0 {src => etc/src}/test/cpp/CompositeTester.cpp | 0 {src => etc/src}/test/cpp/DictTest.cpp | 0 .../test/cpp/EvioCompStructHandlerTest.cpp | 0 {src => etc/src}/test/cpp/FileWriteTest.cpp | 0 {src => etc/src}/test/cpp/Hipo_Test.cpp | 0 .../src}/test/cpp/IndexArrayLenTest.cpp | 0 {src => etc/src}/test/cpp/README.md | 0 .../src}/test/cpp/ReadSequenceTest.cpp | 0 {src => etc/src}/test/cpp/ReadWriteTest.cpp | 0 {src => etc/src}/test/cpp/ReadWriteV4Test.cpp | 0 .../src}/test/cpp/RecordSupplyTest.cpp | 0 {src => etc/src}/test/cpp/RingBufferTest.cpp | 0 {src => etc/src}/test/cpp/SConscript | 4 +- .../src}/test/cpp/SequentialReaderTest.cpp | 0 {src => etc/src}/test/cpp/SplitTest2.cpp | 0 {src => etc/src}/test/cpp/SwapTest.cpp | 0 .../src/test/cpp/TestBase.cpp | 0 {src => etc/src}/test/cpp/TestBase.h | 0 .../cpp/Tree_Buf_Composite_Builder_Test.cpp | 0 {src => etc/src}/test/cpp/fileTest.cpp | 0 {src => etc/src}/test/cpp/hallDEventFiles.cpp | 0 .../java/org/jlab/coda/hipo/FileHeader.java | 695 +++++++++++------- src/main/java/org/jlab/coda/hipo/Reader.java | 6 +- {tutorials => src/test}/cpp/EvioTestHelper.h | 0 .../test}/cpp/WritePseudoPhys_builder.cpp | 0 .../test}/cpp/WritePseudoPhys_compact.cpp | 2 +- .../test}/cpp/WritePseudoPhys_simple.cpp | 0 src/test/java/FirstTest.java | 8 + tutorials/README.md | 2 +- 51 files changed, 446 insertions(+), 275 deletions(-) rename {src => etc/src}/test/c/SConscript (100%) rename {src => etc/src}/test/c/evReadPipe.c (100%) rename {src => etc/src}/test/c/evTestFile.c (100%) rename {src => etc/src}/test/c/evWritePipe.c (100%) rename {src => etc/src}/test/c/evtest.c (100%) rename {src => etc/src}/test/c/evtest2.c (100%) rename {src => etc/src}/test/c/evtest3.c (100%) rename {src => etc/src}/test/c/evtestAppend.c (100%) rename {src => etc/src}/test/c/evtestBuf.c (100%) rename {src => etc/src}/test/c/evtestBuf2.c (100%) rename {src => etc/src}/test/c/evtestRead.c (100%) rename {src => etc/src}/test/c/evtestRio.c (100%) rename {src => etc/src}/test/c/evtestSock.c (100%) rename {src => etc/src}/test/c/evtestWriteFile.c (100%) rename {src => etc/src}/test/c/splitNameTest.c (100%) rename {src => etc/src}/test/c/splitTest.c (100%) rename {src => etc/src}/test/cpp/BigFileWrite.cpp (100%) rename {src => etc/src}/test/cpp/BigFileWritePrimitive.cpp (100%) rename {src => etc/src}/test/cpp/CompactBuilder_Test.cpp (100%) rename {src => etc/src}/test/cpp/CompactReaderAddSubtractTest.cpp (100%) rename {src => etc/src}/test/cpp/CompactReaderBugTest.cpp (100%) rename {src => etc/src}/test/cpp/CompositeTester.cpp (100%) rename {src => etc/src}/test/cpp/DictTest.cpp (100%) rename {src => etc/src}/test/cpp/EvioCompStructHandlerTest.cpp (100%) rename {src => etc/src}/test/cpp/FileWriteTest.cpp (100%) rename {src => etc/src}/test/cpp/Hipo_Test.cpp (100%) rename {src => etc/src}/test/cpp/IndexArrayLenTest.cpp (100%) rename {src => etc/src}/test/cpp/README.md (100%) rename {src => etc/src}/test/cpp/ReadSequenceTest.cpp (100%) rename {src => etc/src}/test/cpp/ReadWriteTest.cpp (100%) rename {src => etc/src}/test/cpp/ReadWriteV4Test.cpp (100%) rename {src => etc/src}/test/cpp/RecordSupplyTest.cpp (100%) rename {src => etc/src}/test/cpp/RingBufferTest.cpp (100%) rename {src => etc/src}/test/cpp/SConscript (93%) rename {src => etc/src}/test/cpp/SequentialReaderTest.cpp (100%) rename {src => etc/src}/test/cpp/SplitTest2.cpp (100%) rename {src => etc/src}/test/cpp/SwapTest.cpp (100%) rename src/test/cpp/TestBase.cxx => etc/src/test/cpp/TestBase.cpp (100%) rename {src => etc/src}/test/cpp/TestBase.h (100%) rename {src => etc/src}/test/cpp/Tree_Buf_Composite_Builder_Test.cpp (100%) rename {src => etc/src}/test/cpp/fileTest.cpp (100%) rename {src => etc/src}/test/cpp/hallDEventFiles.cpp (100%) rename {tutorials => src/test}/cpp/EvioTestHelper.h (100%) rename {tutorials => src/test}/cpp/WritePseudoPhys_builder.cpp (100%) rename {tutorials => src/test}/cpp/WritePseudoPhys_compact.cpp (97%) rename {tutorials => src/test}/cpp/WritePseudoPhys_simple.cpp (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ae64ff91..fc04ce8d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -100,8 +100,8 @@ file(GLOB CPP_HEADER_FILES "src/libsrc++/*.h") if(MAKE_EXAMPLES) file(GLOB TEST "src/test/cpp/*.cpp" "tutorials/cpp/*.cpp") file(GLOB TESTC "src/test/c/*.c") - list(APPEND CPP_HEADER_FILES src/test/cpp/TestBase.h tutorials/cpp/EvioTestHelper.h) - list(APPEND CPP_LIB_FILES src/test/cpp/TestBase.cxx tutorials/cpp/EvioTestHelper.h) + list(APPEND CPP_HEADER_FILES src/test/cpp/EvioTestHelper.h) + # list(APPEND CPP_LIB_FILES src/test/cpp/EvioTestHelper.h) endif() # BUILD C++ LIBRARY (unless otherwise specified) diff --git a/src/test/c/SConscript b/etc/src/test/c/SConscript similarity index 100% rename from src/test/c/SConscript rename to etc/src/test/c/SConscript diff --git a/src/test/c/evReadPipe.c b/etc/src/test/c/evReadPipe.c similarity index 100% rename from src/test/c/evReadPipe.c rename to etc/src/test/c/evReadPipe.c diff --git a/src/test/c/evTestFile.c b/etc/src/test/c/evTestFile.c similarity index 100% rename from src/test/c/evTestFile.c rename to etc/src/test/c/evTestFile.c diff --git a/src/test/c/evWritePipe.c b/etc/src/test/c/evWritePipe.c similarity index 100% rename from src/test/c/evWritePipe.c rename to etc/src/test/c/evWritePipe.c diff --git a/src/test/c/evtest.c b/etc/src/test/c/evtest.c similarity index 100% rename from src/test/c/evtest.c rename to etc/src/test/c/evtest.c diff --git a/src/test/c/evtest2.c b/etc/src/test/c/evtest2.c similarity index 100% rename from src/test/c/evtest2.c rename to etc/src/test/c/evtest2.c diff --git a/src/test/c/evtest3.c b/etc/src/test/c/evtest3.c similarity index 100% rename from src/test/c/evtest3.c rename to etc/src/test/c/evtest3.c diff --git a/src/test/c/evtestAppend.c b/etc/src/test/c/evtestAppend.c similarity index 100% rename from src/test/c/evtestAppend.c rename to etc/src/test/c/evtestAppend.c diff --git a/src/test/c/evtestBuf.c b/etc/src/test/c/evtestBuf.c similarity index 100% rename from src/test/c/evtestBuf.c rename to etc/src/test/c/evtestBuf.c diff --git a/src/test/c/evtestBuf2.c b/etc/src/test/c/evtestBuf2.c similarity index 100% rename from src/test/c/evtestBuf2.c rename to etc/src/test/c/evtestBuf2.c diff --git a/src/test/c/evtestRead.c b/etc/src/test/c/evtestRead.c similarity index 100% rename from src/test/c/evtestRead.c rename to etc/src/test/c/evtestRead.c diff --git a/src/test/c/evtestRio.c b/etc/src/test/c/evtestRio.c similarity index 100% rename from src/test/c/evtestRio.c rename to etc/src/test/c/evtestRio.c diff --git a/src/test/c/evtestSock.c b/etc/src/test/c/evtestSock.c similarity index 100% rename from src/test/c/evtestSock.c rename to etc/src/test/c/evtestSock.c diff --git a/src/test/c/evtestWriteFile.c b/etc/src/test/c/evtestWriteFile.c similarity index 100% rename from src/test/c/evtestWriteFile.c rename to etc/src/test/c/evtestWriteFile.c diff --git a/src/test/c/splitNameTest.c b/etc/src/test/c/splitNameTest.c similarity index 100% rename from src/test/c/splitNameTest.c rename to etc/src/test/c/splitNameTest.c diff --git a/src/test/c/splitTest.c b/etc/src/test/c/splitTest.c similarity index 100% rename from src/test/c/splitTest.c rename to etc/src/test/c/splitTest.c diff --git a/src/test/cpp/BigFileWrite.cpp b/etc/src/test/cpp/BigFileWrite.cpp similarity index 100% rename from src/test/cpp/BigFileWrite.cpp rename to etc/src/test/cpp/BigFileWrite.cpp diff --git a/src/test/cpp/BigFileWritePrimitive.cpp b/etc/src/test/cpp/BigFileWritePrimitive.cpp similarity index 100% rename from src/test/cpp/BigFileWritePrimitive.cpp rename to etc/src/test/cpp/BigFileWritePrimitive.cpp diff --git a/src/test/cpp/CompactBuilder_Test.cpp b/etc/src/test/cpp/CompactBuilder_Test.cpp similarity index 100% rename from src/test/cpp/CompactBuilder_Test.cpp rename to etc/src/test/cpp/CompactBuilder_Test.cpp diff --git a/src/test/cpp/CompactReaderAddSubtractTest.cpp b/etc/src/test/cpp/CompactReaderAddSubtractTest.cpp similarity index 100% rename from src/test/cpp/CompactReaderAddSubtractTest.cpp rename to etc/src/test/cpp/CompactReaderAddSubtractTest.cpp diff --git a/src/test/cpp/CompactReaderBugTest.cpp b/etc/src/test/cpp/CompactReaderBugTest.cpp similarity index 100% rename from src/test/cpp/CompactReaderBugTest.cpp rename to etc/src/test/cpp/CompactReaderBugTest.cpp diff --git a/src/test/cpp/CompositeTester.cpp b/etc/src/test/cpp/CompositeTester.cpp similarity index 100% rename from src/test/cpp/CompositeTester.cpp rename to etc/src/test/cpp/CompositeTester.cpp diff --git a/src/test/cpp/DictTest.cpp b/etc/src/test/cpp/DictTest.cpp similarity index 100% rename from src/test/cpp/DictTest.cpp rename to etc/src/test/cpp/DictTest.cpp diff --git a/src/test/cpp/EvioCompStructHandlerTest.cpp b/etc/src/test/cpp/EvioCompStructHandlerTest.cpp similarity index 100% rename from src/test/cpp/EvioCompStructHandlerTest.cpp rename to etc/src/test/cpp/EvioCompStructHandlerTest.cpp diff --git a/src/test/cpp/FileWriteTest.cpp b/etc/src/test/cpp/FileWriteTest.cpp similarity index 100% rename from src/test/cpp/FileWriteTest.cpp rename to etc/src/test/cpp/FileWriteTest.cpp diff --git a/src/test/cpp/Hipo_Test.cpp b/etc/src/test/cpp/Hipo_Test.cpp similarity index 100% rename from src/test/cpp/Hipo_Test.cpp rename to etc/src/test/cpp/Hipo_Test.cpp diff --git a/src/test/cpp/IndexArrayLenTest.cpp b/etc/src/test/cpp/IndexArrayLenTest.cpp similarity index 100% rename from src/test/cpp/IndexArrayLenTest.cpp rename to etc/src/test/cpp/IndexArrayLenTest.cpp diff --git a/src/test/cpp/README.md b/etc/src/test/cpp/README.md similarity index 100% rename from src/test/cpp/README.md rename to etc/src/test/cpp/README.md diff --git a/src/test/cpp/ReadSequenceTest.cpp b/etc/src/test/cpp/ReadSequenceTest.cpp similarity index 100% rename from src/test/cpp/ReadSequenceTest.cpp rename to etc/src/test/cpp/ReadSequenceTest.cpp diff --git a/src/test/cpp/ReadWriteTest.cpp b/etc/src/test/cpp/ReadWriteTest.cpp similarity index 100% rename from src/test/cpp/ReadWriteTest.cpp rename to etc/src/test/cpp/ReadWriteTest.cpp diff --git a/src/test/cpp/ReadWriteV4Test.cpp b/etc/src/test/cpp/ReadWriteV4Test.cpp similarity index 100% rename from src/test/cpp/ReadWriteV4Test.cpp rename to etc/src/test/cpp/ReadWriteV4Test.cpp diff --git a/src/test/cpp/RecordSupplyTest.cpp b/etc/src/test/cpp/RecordSupplyTest.cpp similarity index 100% rename from src/test/cpp/RecordSupplyTest.cpp rename to etc/src/test/cpp/RecordSupplyTest.cpp diff --git a/src/test/cpp/RingBufferTest.cpp b/etc/src/test/cpp/RingBufferTest.cpp similarity index 100% rename from src/test/cpp/RingBufferTest.cpp rename to etc/src/test/cpp/RingBufferTest.cpp diff --git a/src/test/cpp/SConscript b/etc/src/test/cpp/SConscript similarity index 93% rename from src/test/cpp/SConscript rename to etc/src/test/cpp/SConscript index 3e3e9fd9b..27dd2cb8a 100644 --- a/src/test/cpp/SConscript +++ b/etc/src/test/cpp/SConscript @@ -2,9 +2,9 @@ Import('env', 'platform', 'archDir', 'incInstallDir', 'libInstallDir', 'binInstallDir', 'archIncInstallDir', 'execLibs', 'debugSuffix', 'disruptorHome') -ccTestBase = 'TestBase.cxx' +ccTestBase = 'TestBase.cpp' excluded_files = ccTestBase -# list of all C++ files (excluding TestBase.cxx) +# list of all C++ files (excluding TestBase.cpp) ccfileList = [f for f in Glob('*.cpp', strings=True) if f not in excluded_files] diff --git a/src/test/cpp/SequentialReaderTest.cpp b/etc/src/test/cpp/SequentialReaderTest.cpp similarity index 100% rename from src/test/cpp/SequentialReaderTest.cpp rename to etc/src/test/cpp/SequentialReaderTest.cpp diff --git a/src/test/cpp/SplitTest2.cpp b/etc/src/test/cpp/SplitTest2.cpp similarity index 100% rename from src/test/cpp/SplitTest2.cpp rename to etc/src/test/cpp/SplitTest2.cpp diff --git a/src/test/cpp/SwapTest.cpp b/etc/src/test/cpp/SwapTest.cpp similarity index 100% rename from src/test/cpp/SwapTest.cpp rename to etc/src/test/cpp/SwapTest.cpp diff --git a/src/test/cpp/TestBase.cxx b/etc/src/test/cpp/TestBase.cpp similarity index 100% rename from src/test/cpp/TestBase.cxx rename to etc/src/test/cpp/TestBase.cpp diff --git a/src/test/cpp/TestBase.h b/etc/src/test/cpp/TestBase.h similarity index 100% rename from src/test/cpp/TestBase.h rename to etc/src/test/cpp/TestBase.h diff --git a/src/test/cpp/Tree_Buf_Composite_Builder_Test.cpp b/etc/src/test/cpp/Tree_Buf_Composite_Builder_Test.cpp similarity index 100% rename from src/test/cpp/Tree_Buf_Composite_Builder_Test.cpp rename to etc/src/test/cpp/Tree_Buf_Composite_Builder_Test.cpp diff --git a/src/test/cpp/fileTest.cpp b/etc/src/test/cpp/fileTest.cpp similarity index 100% rename from src/test/cpp/fileTest.cpp rename to etc/src/test/cpp/fileTest.cpp diff --git a/src/test/cpp/hallDEventFiles.cpp b/etc/src/test/cpp/hallDEventFiles.cpp similarity index 100% rename from src/test/cpp/hallDEventFiles.cpp rename to etc/src/test/cpp/hallDEventFiles.cpp diff --git a/src/main/java/org/jlab/coda/hipo/FileHeader.java b/src/main/java/org/jlab/coda/hipo/FileHeader.java index fb1f65d2d..693cbc54a 100644 --- a/src/main/java/org/jlab/coda/hipo/FileHeader.java +++ b/src/main/java/org/jlab/coda/hipo/FileHeader.java @@ -12,7 +12,8 @@ /** * This class represents the file header of an evio or hipo format file. * - *

+ * 
+ * 
  *
  * FILE HEADER STRUCTURE ( 56 bytes, 14 integers (32 bit) )
  *
@@ -63,7 +64,8 @@
  *                                 5 = HIPO file
  *                                 6 = HIPO extended file
  *
- * 
+ *
+ *
* * @version 6.0 * @since 6.0 9/6/17 @@ -73,184 +75,195 @@ public class FileHeader implements Cloneable { /** Array to help find number of bytes to pad data. */ - private final static int[] padValue = {0,3,2,1}; + private final static int[] padValue = { 0, 3, 2, 1 }; /** First word in every HIPO file for identification purposes. */ - public final static int HIPO_FILE_UNIQUE_WORD = 0x4F504948; // 0x4849504F = HIPO + public final static int HIPO_FILE_UNIQUE_WORD = 0x4F504948; // 0x4849504F = HIPO /** First word in every Evio file for identification purposes. */ - public final static int EVIO_FILE_UNIQUE_WORD = 0x4556494F; // = EVIO + public final static int EVIO_FILE_UNIQUE_WORD = 0x4556494F; // = EVIO /** Number of 32-bit words in a normal sized header. */ - public final static int HEADER_SIZE_WORDS = 14; + public final static int HEADER_SIZE_WORDS = 14; /** Number of bytes in a normal sized header. */ - public final static int HEADER_SIZE_BYTES = 56; + public final static int HEADER_SIZE_BYTES = 56; /** Magic number used to track endianness. */ - public final static int HEADER_MAGIC = 0xc0da0100; + public final static int HEADER_MAGIC = 0xc0da0100; // Byte offset to header words /** Byte offset from beginning of header to the file id. */ - public final static int FILE_ID_OFFSET = 0; + public final static int FILE_ID_OFFSET = 0; /** Byte offset from beginning of header to the file number. */ - public final static int FILE_NUMBER_OFFSET = 4; + public final static int FILE_NUMBER_OFFSET = 4; /** Byte offset from beginning of header to the header length. */ - public final static int HEADER_LENGTH_OFFSET = 8; + public final static int HEADER_LENGTH_OFFSET = 8; /** Byte offset from beginning of header to the record count. */ - public final static int RECORD_COUNT_OFFSET = 12; + public final static int RECORD_COUNT_OFFSET = 12; /** Byte offset from beginning of header to the index array length. */ - public final static int INDEX_ARRAY_OFFSET = 16; + public final static int INDEX_ARRAY_OFFSET = 16; /** Byte offset from beginning of header to bit info word. */ - public final static int BIT_INFO_OFFSET = 20; + public final static int BIT_INFO_OFFSET = 20; /** Byte offset from beginning of header to the user header length. */ - public final static int USER_LENGTH_OFFSET = 24; + public final static int USER_LENGTH_OFFSET = 24; /** Byte offset from beginning of header to the record length. */ - public final static int MAGIC_OFFSET = 28; + public final static int MAGIC_OFFSET = 28; /** Byte offset from beginning of header to the user register #1. */ - public final static int REGISTER1_OFFSET = 32; + public final static int REGISTER1_OFFSET = 32; /** Byte offset from beginning of header to write trailer position. */ - public final static int TRAILER_POSITION_OFFSET = 40; + public final static int TRAILER_POSITION_OFFSET = 40; /** Byte offset from beginning of header to the user integer #1. */ - public final static int INT1_OFFSET = 48; + public final static int INT1_OFFSET = 48; /** Byte offset from beginning of header to the user integer #2. */ - public final static int INT2_OFFSET = 52; + public final static int INT2_OFFSET = 52; // Bits in bit info word /** 8th bit set in bitInfo word in file header means contains dictionary. */ - final static int DICTIONARY_BIT = 0x100; - /** 9th bit set in bitInfo word in file header means every split file has same first event. */ - final static int FIRST_EVENT_BIT = 0x200; - /** 10th bit set in bitInfo word in file header means file trailer with index array exists. */ - final static int TRAILER_WITH_INDEX_BIT = 0x400; - - + final static int DICTIONARY_BIT = 0x100; + /** + * 9th bit set in bitInfo word in file header means every split file has same + * first event. + */ + final static int FIRST_EVENT_BIT = 0x200; + /** + * 10th bit set in bitInfo word in file header means file trailer with index + * array exists. + */ + final static int TRAILER_WITH_INDEX_BIT = 0x400; - /** File id for file identification purposes. Defaults to HIPO file. 1st word. */ - private int fileId = HIPO_FILE_UNIQUE_WORD; + /** + * File id for file identification purposes. Defaults to HIPO file. 1st word. + */ + private int fileId = HIPO_FILE_UNIQUE_WORD; /** File number or split file number, starting at 1. 2nd word. */ - private int fileNumber = 1; + private int fileNumber = 1; /** User-defined 64-bit register. 9th and 10th words. */ private long userRegister; /** Position of trailing header from start of file in bytes. 11th word. */ private long trailerPosition; /** First user-defined integer in file header. 13th word. */ - private int userIntFirst; + private int userIntFirst; /** Second user-defined integer in file header. 14th word. */ - private int userIntSecond; + private int userIntSecond; /** Position of this header in a file. */ private long position; /** Event or record count. 4th word. */ - private int entries; + private int entries; /** BitInfo & version. 6th word. */ - private int bitInfo = -1; + private int bitInfo = -1; /** Length of this header (bytes). */ - private int headerLength = HEADER_SIZE_BYTES; + private int headerLength = HEADER_SIZE_BYTES; /** Length of this header (words). 3rd word. */ - private int headerLengthWords = HEADER_SIZE_WORDS; + private int headerLengthWords = HEADER_SIZE_WORDS; /** Length of user-defined header (bytes). 7th word. */ - private int userHeaderLength; + private int userHeaderLength; /** Length of user-defined header when padded (words). */ - private int userHeaderLengthWords; + private int userHeaderLengthWords; /** Length of index array (bytes). 5th word. */ - private int indexLength; + private int indexLength; - /** Final, total length of header + index + user header (bytes) + padding. - * Not stored in any word. */ - private int totalLength = HEADER_SIZE_BYTES; + /** + * Final, total length of header + index + user header (bytes) + padding. + * Not stored in any word. + */ + private int totalLength = HEADER_SIZE_BYTES; - /** Evio format version number. It is 6 when being written, else - * the version of file/buffer being read. Lowest byte of 6th word. */ - private int headerVersion = 6; + /** + * Evio format version number. It is 6 when being written, else + * the version of file/buffer being read. Lowest byte of 6th word. + */ + private int headerVersion = 6; /** Magic number for tracking endianness. 8th word. */ - private int headerMagicWord = HEADER_MAGIC; + private int headerMagicWord = HEADER_MAGIC; - /** Number of bytes required to bring uncompressed - * user header to 4-byte boundary. Stored in 6th word. - * Updated automatically when lengths are set. */ - private int userHeaderLengthPadding; + /** + * Number of bytes required to bring uncompressed + * user header to 4-byte boundary. Stored in 6th word. + * Updated automatically when lengths are set. + */ + private int userHeaderLengthPadding; /** Byte order of file. */ - private ByteOrder byteOrder = ByteOrder.LITTLE_ENDIAN; + private ByteOrder byteOrder = ByteOrder.LITTLE_ENDIAN; /** Type of header this is. Normal HIPO record by default. */ private HeaderType headerType = HeaderType.HIPO_FILE; - - /** Default, no-arg constructor. */ - public FileHeader() {bitInfoInit();} + public FileHeader() { + bitInfoInit(); + } /** * Constructor which sets the type of header this is and file id. + * * @param isEvio if true, file has EVIO file id and header type, else is HIPO. */ public FileHeader(boolean isEvio) { if (isEvio) { fileId = EVIO_FILE_UNIQUE_WORD; headerType = HeaderType.EVIO_FILE; - } - else { + } else { fileId = HIPO_FILE_UNIQUE_WORD; headerType = HeaderType.HIPO_FILE; } bitInfoInit(); } - - /*** {@inheritDoc} */ + /*** {@inheritDoc} */ public Object clone() { try { // Don't do anything special as all are primitive types or enum or ByteOrder return super.clone(); - } - catch (CloneNotSupportedException e) { + } catch (CloneNotSupportedException e) { return null; } } - /** * Copy the contents of the arg into this object. + * * @param head object to copy */ public void copy(FileHeader head) { - if (head == null) return; - - fileId = head.fileId; - fileNumber = head.fileNumber; - userRegister = head.userRegister; - trailerPosition = head.trailerPosition; - userIntFirst = head.userIntFirst; - userIntSecond = head.userIntSecond; - position = head.position; - totalLength = head.totalLength; - headerType = head.headerType; - entries = head.entries; - bitInfo = head.bitInfo; - headerLength = head.headerLength; - headerLengthWords = head.headerLengthWords; - userHeaderLength = head.userHeaderLength; - userHeaderLengthWords = head.userHeaderLengthWords; - indexLength = head.indexLength; - headerMagicWord = head.headerMagicWord; + if (head == null) + return; + + fileId = head.fileId; + fileNumber = head.fileNumber; + userRegister = head.userRegister; + trailerPosition = head.trailerPosition; + userIntFirst = head.userIntFirst; + userIntSecond = head.userIntSecond; + position = head.position; + totalLength = head.totalLength; + headerType = head.headerType; + entries = head.entries; + bitInfo = head.bitInfo; + headerLength = head.headerLength; + headerLengthWords = head.headerLengthWords; + userHeaderLength = head.userHeaderLength; + userHeaderLengthWords = head.userHeaderLengthWords; + indexLength = head.indexLength; + headerMagicWord = head.headerMagicWord; userHeaderLengthPadding = head.userHeaderLengthPadding; - headerVersion = head.headerVersion; + headerVersion = head.headerVersion; } /** Reset most internal variables (not file id and header type). */ - public void reset(){ + public void reset() { // Do NOT reset fileId which is only set in constructor. // Do NOT reset header type. fileNumber = 1; userRegister = 0L; trailerPosition = 0L; - userIntFirst = 0; + userIntFirst = 0; userIntSecond = 0; position = 0L; entries = 0; bitInfoInit(); - totalLength = HEADER_SIZE_BYTES; + totalLength = HEADER_SIZE_BYTES; headerLength = HEADER_SIZE_BYTES; headerLengthWords = HEADER_SIZE_WORDS; userHeaderLength = 0; @@ -262,133 +275,194 @@ public void reset(){ /** * Returns length padded to 4-byte boundary for given length in bytes. + * * @param length length in bytes. * @return length in bytes padded to 4-byte boundary. */ - private static int getWords(int length){ - int words = length/4; - if (getPadding(length) > 0) words++; + private static int getWords(int length) { + int words = length / 4; + if (getPadding(length) > 0) + words++; return words; } /** - * Returns number of bytes needed to pad to 4-byte boundary for the given length. + * Returns number of bytes needed to pad to 4-byte boundary for the given + * length. + * * @param length length in bytes. * @return number of bytes needed to pad to 4-byte boundary. */ - private static int getPadding(int length) {return padValue[length%4];} + private static int getPadding(int length) { + return padValue[length % 4]; + } // Getters /** * Get the byte order of the file this header was read from. * Defaults to little endian. + * * @return byte order of the file this header was read from. */ - public ByteOrder getByteOrder() {return byteOrder;} + public ByteOrder getByteOrder() { + return byteOrder; + } /** * Get the file number or split number. + * * @return file number. */ - public int getFileNumber() {return fileNumber;} + public int getFileNumber() { + return fileNumber; + } /** * Get the file id. + * * @return file id. */ - public int getFileId() {return fileId;} + public int getFileId() { + return fileId; + } /** * Get the user register value. + * * @return user register value. */ - public long getUserRegister() {return userRegister;} + public long getUserRegister() { + return userRegister; + } /** * Get the trailer's (trailing header's) file position in bytes. + * * @return trailer's (trailing header's) file position in bytes. */ - public long getTrailerPosition() {return trailerPosition;} + public long getTrailerPosition() { + return trailerPosition; + } /** * Get the first user integer value. + * * @return first user integer value. */ - public int getUserIntFirst() {return userIntFirst;} + public int getUserIntFirst() { + return userIntFirst; + } /** * Get the second user integer value. + * * @return second user integer value. */ - public int getUserIntSecond() {return userIntSecond;} + public int getUserIntSecond() { + return userIntSecond; + } /** * Get the position of this record in a file. + * * @return position of this record in a file. */ - public long getPosition() {return position;} + public long getPosition() { + return position; + } /** * Get the number of events or entries in index. + * * @return number of events or entries in index. */ - public int getEntries() {return entries;} + public int getEntries() { + return entries; + } /** * Get the length of the user-defined header in bytes. + * * @return length of the user-defined header in bytes. */ - public int getUserHeaderLength() {return userHeaderLength;} + public int getUserHeaderLength() { + return userHeaderLength; + } /** * Get the length of the user-defined header in words. + * * @return length of the user-defined header in words. */ - public int getUserHeaderLengthWords() {return userHeaderLengthWords;} + public int getUserHeaderLengthWords() { + return userHeaderLengthWords; + } /** * Get the Evio format version number. + * * @return Evio format version number. */ - public int getVersion() {return headerVersion;} + public int getVersion() { + return headerVersion; + } /** * Get the length of the index array in bytes. + * * @return length of the index array in bytes. */ - public int getIndexLength() {return indexLength;} + public int getIndexLength() { + return indexLength; + } /** * Get the length of this header data in bytes. + * * @return length of this header data in bytes. */ - public int getHeaderLength() {return headerLength;} + public int getHeaderLength() { + return headerLength; + } /** * Get the type of header this is. + * * @return type of header this is. */ - public HeaderType getHeaderType() {return headerType;} + public HeaderType getHeaderType() { + return headerType; + } /** - * Get the total length of header + index + user header (including padding) in bytes. + * Get the total length of header + index + user header (including padding) in + * bytes. * Never compressed. - * @return total length of header + index + user header (including padding) in bytes. + * + * @return total length of header + index + user header (including padding) in + * bytes. */ - public int getLength() {return totalLength;} + public int getLength() { + return totalLength; + } /** - * Get the user header's padding - the number of bytes required to bring uncompressed + * Get the user header's padding - the number of bytes required to bring + * uncompressed * user header to 4-byte boundary. - * @return user header's padding + * + * @return user header's padding */ - public int getUserHeaderLengthPadding() {return userHeaderLengthPadding;} + public int getUserHeaderLengthPadding() { + return userHeaderLengthPadding; + } // Bit info methods /** * Decodes the bit-info word into version, padding and header type. + * * @param word bit-info word. */ private void decodeBitInfoWord(int word) { @@ -399,7 +473,7 @@ private void decodeBitInfoWord(int word) { headerVersion = (word & 0xff); // Header type - headerType = HeaderType.getHeaderType(word >>> 28); + headerType = HeaderType.getHeaderType(word >>> 28); if (headerType == null) { headerType = HeaderType.EVIO_RECORD; } @@ -412,15 +486,19 @@ private void bitInfoInit() { /** * Get the bit info word. + * * @return bit info word. */ - public int getBitInfoWord() {return bitInfo;} + public int getBitInfoWord() { + return bitInfo; + } /** * Set the bit info word and related values. - * @param word bit info word. + * + * @param word bit info word. */ - void setBitInfoWord(int word) { + void setBitInfoWord(int word) { bitInfo = word; decodeBitInfoWord(word); } @@ -428,34 +506,43 @@ void setBitInfoWord(int word) { /** * Set the bit info word for a file header. * Retains current header type, user header length padding, and version. - * @param haveFirst true if file has first event. - * @param haveDictionary true if file has dictionary in user header. - * @param haveTrailerWithIndex true if file has trailer with record length index. + * + * @param haveFirst true if file has first event. + * @param haveDictionary true if file has dictionary in user header. + * @param haveTrailerWithIndex true if file has trailer with record length + * index. * @return new bit info word. */ public int setBitInfo(boolean haveFirst, - boolean haveDictionary, - boolean haveTrailerWithIndex) { + boolean haveDictionary, + boolean haveTrailerWithIndex) { bitInfo = (headerType.getValue() << 28) | - (userHeaderLengthPadding << 20) | - (headerVersion & 0xFF); + (userHeaderLengthPadding << 20) | + (headerVersion & 0xFF); - if (haveFirst) bitInfo |= FIRST_EVENT_BIT; - if (haveDictionary) bitInfo |= DICTIONARY_BIT; - if (haveTrailerWithIndex) bitInfo |= TRAILER_WITH_INDEX_BIT; + if (haveFirst) + bitInfo |= FIRST_EVENT_BIT; + if (haveDictionary) + bitInfo |= DICTIONARY_BIT; + if (haveTrailerWithIndex) + bitInfo |= TRAILER_WITH_INDEX_BIT; return bitInfo; } /** * Get the file's type. + * * @return the file's HeaderType. */ - public HeaderType getFileType() {return headerType;} + public HeaderType getFileType() { + return headerType; + } /** * Get the file's type from the bit info word. + * * @param word bit-info word. * @return the file's HeaderType. */ @@ -472,15 +559,15 @@ public static HeaderType getFileType(int word) { /** * Set the bit which says file has a first event. - * @param hasFirst true if file has a first event. + * + * @param hasFirst true if file has a first event. * @return new bitInfo word. */ public int hasFirstEvent(boolean hasFirst) { if (hasFirst) { // set bit bitInfo |= FIRST_EVENT_BIT; - } - else { + } else { // clear bit bitInfo &= ~FIRST_EVENT_BIT; } @@ -490,28 +577,35 @@ public int hasFirstEvent(boolean hasFirst) { /** * Does this header have a first event in the file header? + * * @return true if header has a first event in the file header, else false. */ - public boolean hasFirstEvent() {return ((bitInfo & FIRST_EVENT_BIT) != 0);} + public boolean hasFirstEvent() { + return ((bitInfo & FIRST_EVENT_BIT) != 0); + } /** - * Does this bitInfo arg indicate the existence of a first event in the file header? + * Does this bitInfo arg indicate the existence of a first event in the file + * header? + * * @param bitInfo bitInfo word. * @return true if header has a first event in the file header, else false. */ - static public boolean hasFirstEvent(int bitInfo) {return ((bitInfo & FIRST_EVENT_BIT) != 0);} + static public boolean hasFirstEvent(int bitInfo) { + return ((bitInfo & FIRST_EVENT_BIT) != 0); + } /** * Set the bit in the file header which says there is a dictionary. - * @param hasDictionary true if file has a dictionary. + * + * @param hasDictionary true if file has a dictionary. * @return new bitInfo word. */ public int hasDictionary(boolean hasDictionary) { if (hasDictionary) { // set bit bitInfo |= DICTIONARY_BIT; - } - else { + } else { // clear bit bitInfo &= ~DICTIONARY_BIT; } @@ -521,28 +615,37 @@ public int hasDictionary(boolean hasDictionary) { /** * Does this header have a dictionary in the file header? + * * @return true if header has a dictionary in the file header, else false. */ - public boolean hasDictionary() {return ((bitInfo & DICTIONARY_BIT) != 0);} + public boolean hasDictionary() { + return ((bitInfo & DICTIONARY_BIT) != 0); + } /** - * Does this bitInfo arg indicate the existence of a dictionary in the file header? + * Does this bitInfo arg indicate the existence of a dictionary in the file + * header? + * * @param bitInfo bitInfo word. * @return true if header has a dictionary in the file header, else false. */ - static public boolean hasDictionary(int bitInfo) {return ((bitInfo & DICTIONARY_BIT) != 0);} + static public boolean hasDictionary(int bitInfo) { + return ((bitInfo & DICTIONARY_BIT) != 0); + } /** - * Set the bit in the file header which says there is a trailer with a record length index. - * @param hasTrailerWithIndex true if file has a trailer with a record length index. + * Set the bit in the file header which says there is a trailer with a record + * length index. + * + * @param hasTrailerWithIndex true if file has a trailer with a record length + * index. * @return new bitInfo word. */ public int hasTrailerWithIndex(boolean hasTrailerWithIndex) { if (hasTrailerWithIndex) { // set bit bitInfo |= TRAILER_WITH_INDEX_BIT; - } - else { + } else { // clear bit bitInfo &= ~TRAILER_WITH_INDEX_BIT; } @@ -552,12 +655,17 @@ public int hasTrailerWithIndex(boolean hasTrailerWithIndex) { /** * Does this file have a trailer with a record length index? + * * @return true if file has a trailer with a record length index, else false. */ - public boolean hasTrailerWithIndex() {return ((bitInfo & TRAILER_WITH_INDEX_BIT) != 0);} + public boolean hasTrailerWithIndex() { + return ((bitInfo & TRAILER_WITH_INDEX_BIT) != 0); + } /** - * Does this bitInfo arg indicate the existence of a trailer with a record length index? + * Does this bitInfo arg indicate the existence of a trailer with a record + * length index? + * * @param bitInfo bitInfo word. * @return true if file has a trailer with a record length index, else false. */ @@ -565,75 +673,107 @@ static public boolean hasTrailerWithIndex(int bitInfo) { return ((bitInfo & TRAILER_WITH_INDEX_BIT) != 0); } - //-------------------------------------------------------------- + // -------------------------------------------------------------- /** * Is this header followed by a user header? + * * @return true if header followed by a user header, else false. */ - public boolean hasUserHeader() {return userHeaderLength > 0;} + public boolean hasUserHeader() { + return userHeaderLength > 0; + } /** - * Does this file have a valid index of record lengths immediately following header? + * Does this file have a valid index of record lengths immediately following + * header? * There should be at least one integer for valid index. * Must have integral number of entries. + * * @return true if file has a valid index, else false. */ - public boolean hasIndex() {return ((indexLength > 3) && (indexLength % 4 == 0));} + public boolean hasIndex() { + return ((indexLength > 3) && (indexLength % 4 == 0)); + } // Setters /** * Set the file number which is the split number starting at 1. - * @param num file number starting at 1. + * + * @param num file number starting at 1. * @return this object. */ - public FileHeader setFileNumber(int num) {fileNumber = num; return this;} + public FileHeader setFileNumber(int num) { + fileNumber = num; + return this; + } /** * Set the first user register. - * @param val first user register. + * + * @param val first user register. * @return this object. */ - public FileHeader setUserRegister(long val) {userRegister = val; return this;} + public FileHeader setUserRegister(long val) { + userRegister = val; + return this; + } /** * Set the first user integer. - * @param val first user integer. + * + * @param val first user integer. * @return this object. */ - public FileHeader setUserIntFirst(int val) {userIntFirst = val; return this;} + public FileHeader setUserIntFirst(int val) { + userIntFirst = val; + return this; + } /** * Set the second user integer. - * @param val second user integer. + * + * @param val second user integer. * @return this object. */ - public FileHeader setUserIntSecond(int val) {userIntSecond = val; return this;} + public FileHeader setUserIntSecond(int val) { + userIntSecond = val; + return this; + } /** * Set this header's type. Normally done in constructor. Limited access. + * * @param type type of header. * @return this object. */ - FileHeader setHeaderType(HeaderType type) {headerType = type; return this;} + FileHeader setHeaderType(HeaderType type) { + headerType = type; + return this; + } /** * Set the position of this record in a file. + * * @param pos position of this record in a file. * @return this object. */ - public FileHeader setPosition(long pos) {position = pos; return this;} + public FileHeader setPosition(long pos) { + position = pos; + return this; + } /** * Set the length of the index array in bytes. * Length is forced to be a multiple of 4! * Sets the total length too. - * @param length length of index array in bytes. + * + * @param length length of index array in bytes. * @return this object. */ public FileHeader setIndexLength(int length) { - indexLength = (length/4)*4; + indexLength = (length / 4) * 4; setLength(headerLength + indexLength + userHeaderLength + userHeaderLengthPadding); return this; } @@ -641,15 +781,20 @@ public FileHeader setIndexLength(int length) { /** * Set the number of record entries. * No compression for other values. + * * @param n number of record entries. * @return this object. */ - public FileHeader setEntries(int n) {entries = n; return this;} + public FileHeader setEntries(int n) { + entries = n; + return this; + } /** * Set the user-defined header's length in bytes and words and the padding. * Sets the total length too. - * @param length user-defined header's length in bytes. + * + * @param length user-defined header's length in bytes. * @return this object. */ public FileHeader setUserHeaderLength(int length) { @@ -662,32 +807,38 @@ public FileHeader setUserHeaderLength(int length) { } /** - * Set the user header's padding - the number of bytes required to bring uncompressed - * user header to 4-byte boundary. Sets the associated value in bitInfo word. - * @param padding user header's padding. - */ - private void setUserHeaderLengthPadding(int padding) { -//System.out.println("setUserHeaderLengthPadding: IN, firstEv bit = " + hasFirstEvent()); - userHeaderLengthPadding = padding; - bitInfo = bitInfo | (userHeaderLengthPadding << 20); -//System.out.println("setUserHeaderLengthPadding: END, firstEv bit = " + hasFirstEvent()); - } + * Set the user header's padding - the number of bytes required to bring + * uncompressed + * user header to 4-byte boundary. Sets the associated value in bitInfo word. + * + * @param padding user header's padding. + */ + private void setUserHeaderLengthPadding(int padding) { + // System.out.println("setUserHeaderLengthPadding: IN, firstEv bit = " + + // hasFirstEvent()); + userHeaderLengthPadding = padding; + bitInfo = bitInfo | (userHeaderLengthPadding << 20); + // System.out.println("setUserHeaderLengthPadding: END, firstEv bit = " + + // hasFirstEvent()); + } /** * Set the this header's length in bytes and words. * Minimum length of 56 (14 words) is enforced. * If length is not a multiple of 4, you're on your own! * Sets the total length too. - * @param length this header's length in bytes. + * + * @param length this header's length in bytes. * @return this object. */ public FileHeader setHeaderLength(int length) { if (length < 56) { length = 56; -//System.out.println("setHeaderLength: attempting to set header length too small (" + hasFirstEvent() + ")"); + // System.out.println("setHeaderLength: attempting to set header length too + // small (" + hasFirstEvent() + ")"); } headerLength = length; - headerLengthWords = length/4; + headerLengthWords = length / 4; setLength(headerLength + indexLength + userHeaderLength + userHeaderLengthPadding); return this; } @@ -696,47 +847,54 @@ public FileHeader setHeaderLength(int length) { * Set the total length in bytes, header + index + user header. * This includes padding and is on a 4-byte boundary. * Never compressed. - * @param length total length in bytes, header + index + user header. + * + * @param length total length in bytes, header + index + user header. * @return this object. */ - public FileHeader setLength(int length) {totalLength = length; return this;} + public FileHeader setLength(int length) { + totalLength = length; + return this; + } - //------------------------------------------------- + // ------------------------------------------------- /** * Writes the file (not record!) header into the given byte buffer. + * * @param buf byte buffer to write file header into. * @param off position in buffer to begin writing. * @throws HipoException if buffer is null or contains too little room. */ - public void writeHeader(ByteBuffer buf, int off) throws HipoException { - - if (buf == null || (buf.limit() - off) < HEADER_SIZE_BYTES) { - throw new HipoException("buf is null or too small"); - } - - buf.putInt ( off, fileId); // 0*4 - buf.putInt ( 4 + off, fileNumber); // 1*4 - buf.putInt ( 8 + off, headerLengthWords); // 2*4 - buf.putInt (12 + off, entries); // 3*4 - buf.putInt (16 + off, indexLength); // 4*4 - buf.putInt (20 + off, getBitInfoWord()); // 5*4 - buf.putInt (24 + off, userHeaderLength); // 6*4 - buf.putInt (28 + off, headerMagicWord); // 7*4 - buf.putLong(32 + off, userRegister); // 8*4 - buf.putLong(40 + off, trailerPosition); // 10*4 - buf.putInt (48 + off, userIntFirst); // 12*4 - buf.putInt (52 + off, userIntSecond); // 13*4 - } - - /** - * Writes the file (not record!) header into the given byte buffer starting at beginning. - * @param buffer byte buffer to write file header into. - * @throws HipoException if buffer is null or contains too little room. - */ - public void writeHeader(ByteBuffer buffer) throws HipoException { - writeHeader(buffer, 0); - } + public void writeHeader(ByteBuffer buf, int off) throws HipoException { + + if (buf == null || (buf.limit() - off) < HEADER_SIZE_BYTES) { + throw new HipoException("buf is null or too small"); + } + + buf.putInt(off, fileId); // 0*4 + buf.putInt(4 + off, fileNumber); // 1*4 + buf.putInt(8 + off, headerLengthWords); // 2*4 + buf.putInt(12 + off, entries); // 3*4 + buf.putInt(16 + off, indexLength); // 4*4 + buf.putInt(20 + off, getBitInfoWord()); // 5*4 + buf.putInt(24 + off, userHeaderLength); // 6*4 + buf.putInt(28 + off, headerMagicWord); // 7*4 + buf.putLong(32 + off, userRegister); // 8*4 + buf.putLong(40 + off, trailerPosition); // 10*4 + buf.putInt(48 + off, userIntFirst); // 12*4 + buf.putInt(52 + off, userIntSecond); // 13*4 + } + + /** + * Writes the file (not record!) header into the given byte buffer starting at + * beginning. + * + * @param buffer byte buffer to write file header into. + * @throws HipoException if buffer is null or contains too little room. + */ + public void writeHeader(ByteBuffer buffer) throws HipoException { + writeHeader(buffer, 0); + } /** * Reads the file header information from a byte buffer and validates @@ -748,7 +906,8 @@ public void writeHeader(ByteBuffer buffer) throws HipoException { * @param offset position of first word to be read. * @throws HipoException if buffer is null, * remaining buffer space (limit - off) is too small, - * data is not in proper format, or version earlier than 6. + * data is not in proper format, or version earlier than + * 6. */ public void readHeader(ByteBuffer buffer, int offset) throws HipoException { @@ -765,20 +924,17 @@ public void readHeader(ByteBuffer buffer, int offset) throws HipoException { if (headerMagicWord == Integer.reverseBytes(HEADER_MAGIC)) { if (buffer.order() == ByteOrder.BIG_ENDIAN) { byteOrder = ByteOrder.LITTLE_ENDIAN; - } - else { + } else { byteOrder = ByteOrder.BIG_ENDIAN; } buffer.order(byteOrder); headerMagicWord = HEADER_MAGIC; - } - else { + } else { // ERROR condition, bad magic word throw new HipoException("buffer not in evio/hipo format? magic int = 0x" + - Integer.toHexString(headerMagicWord)); + Integer.toHexString(headerMagicWord)); } - } - else { + } else { byteOrder = buffer.order(); } @@ -789,28 +945,28 @@ public void readHeader(ByteBuffer buffer, int offset) throws HipoException { throw new HipoException("evio format < 6, = " + headerVersion); } - fileId = buffer.getInt(FILE_ID_OFFSET + offset); - fileNumber = buffer.getInt(FILE_NUMBER_OFFSET + offset); + fileId = buffer.getInt(FILE_ID_OFFSET + offset); + fileNumber = buffer.getInt(FILE_NUMBER_OFFSET + offset); headerLengthWords = buffer.getInt(HEADER_LENGTH_OFFSET + offset); - setHeaderLength(4*headerLengthWords); -//System.out.println(" fileHeader: header len = " + headerLength); - entries = buffer.getInt(RECORD_COUNT_OFFSET + offset); + setHeaderLength(4 * headerLengthWords); + // System.out.println(" fileHeader: header len = " + headerLength); + entries = buffer.getInt(RECORD_COUNT_OFFSET + offset); - indexLength = buffer.getInt(INDEX_ARRAY_OFFSET + offset); -//System.out.println(" fileHeader: index len = " + indexLength); + indexLength = buffer.getInt(INDEX_ARRAY_OFFSET + offset); + // System.out.println(" fileHeader: index len = " + indexLength); setIndexLength(indexLength); - userHeaderLength = buffer.getInt(USER_LENGTH_OFFSET + offset); + userHeaderLength = buffer.getInt(USER_LENGTH_OFFSET + offset); setUserHeaderLength(userHeaderLength); -//System.out.println(" fileHeader: user header len = " + userHeaderLength + -// ", padding = " + userHeaderLengthPadding); + // System.out.println(" fileHeader: user header len = " + userHeaderLength + + // ", padding = " + userHeaderLengthPadding); -//System.out.println(" fileHeader: total len = " + totalLength); + // System.out.println(" fileHeader: total len = " + totalLength); - userRegister = buffer.getLong(REGISTER1_OFFSET + offset); - trailerPosition = buffer.getLong(TRAILER_POSITION_OFFSET + offset); - userIntFirst = buffer.getInt (INT1_OFFSET + offset); - userIntSecond = buffer.getInt (INT2_OFFSET + offset); + userRegister = buffer.getLong(REGISTER1_OFFSET + offset); + trailerPosition = buffer.getLong(TRAILER_POSITION_OFFSET + offset); + userIntFirst = buffer.getInt(INT1_OFFSET + offset); + userIntSecond = buffer.getInt(INT2_OFFSET + offset); } /** @@ -820,7 +976,8 @@ public void readHeader(ByteBuffer buffer, int offset) throws HipoException { * NOT change. * * @param buffer buffer to read from starting at the beginning. - * @throws HipoException if buffer is not in the proper format or earlier than version 6 + * @throws HipoException if buffer is not in the proper format or earlier than + * version 6 */ public void readHeader(ByteBuffer buffer) throws HipoException { readHeader(buffer, 0); @@ -828,34 +985,35 @@ public void readHeader(ByteBuffer buffer) throws HipoException { /** * Returns a string representation of the record. + * * @return a string representation of the record. */ @Override - public String toString(){ + public String toString() { StringBuilder str = new StringBuilder(); - str.append(String.format("%24s : 0x%x, %s file\n","ID",fileId, - (fileId == EVIO_FILE_UNIQUE_WORD ? "Evio" : "Hipo"))); - str.append(String.format("%24s : %d\n","version",headerVersion)); - str.append(String.format("%24s : %d bytes, words, padding\n","file #",fileNumber)); - str.append(String.format("%24s : %8d / %8d / %8d\n","user header length", - userHeaderLength, userHeaderLengthWords, userHeaderLengthPadding)); - str.append(String.format("%24s : %d\n","header length",headerLength)); - str.append(String.format("%24s : 0x%X\n","magic word",headerMagicWord)); + str.append(String.format("%24s : 0x%x, %s file\n", "ID", fileId, + (fileId == EVIO_FILE_UNIQUE_WORD ? "Evio" : "Hipo"))); + str.append(String.format("%24s : %d\n", "version", headerVersion)); + str.append(String.format("%24s : %d bytes, words, padding\n", "file #", fileNumber)); + str.append(String.format("%24s : %8d / %8d / %8d\n", "user header length", + userHeaderLength, userHeaderLengthWords, userHeaderLengthPadding)); + str.append(String.format("%24s : %d\n", "header length", headerLength)); + str.append(String.format("%24s : 0x%X\n", "magic word", headerMagicWord)); Integer bitInfo = getBitInfoWord(); - str.append(String.format("%24s : %s\n","bit info bits",Integer.toBinaryString(bitInfo))); - str.append(String.format("%24s : 0x%x\n","bit info word",bitInfo)); - str.append(String.format("%24s : %b\n","has dictionary",FileHeader.hasDictionary(bitInfo))); - str.append(String.format("%24s : %b\n","has first event",FileHeader.hasFirstEvent(bitInfo))); - str.append(String.format("%24s : %b\n","has trailer w/ index",FileHeader.hasTrailerWithIndex(bitInfo))); - str.append(String.format("%24s : %d\n","record entries",entries)); + str.append(String.format("%24s : %s\n", "bit info bits", Integer.toBinaryString(bitInfo))); + str.append(String.format("%24s : 0x%x\n", "bit info word", bitInfo)); + str.append(String.format("%24s : %b\n", "has dictionary", FileHeader.hasDictionary(bitInfo))); + str.append(String.format("%24s : %b\n", "has first event", FileHeader.hasFirstEvent(bitInfo))); + str.append(String.format("%24s : %b\n", "has trailer w/ index", FileHeader.hasTrailerWithIndex(bitInfo))); + str.append(String.format("%24s : %d\n", "record entries", entries)); - str.append(String.format("%24s : %d\n"," index length", indexLength)); + str.append(String.format("%24s : %d\n", " index length", indexLength)); - str.append(String.format("%24s : %d\n","trailer position", trailerPosition)); - str.append(String.format("%24s : 0x%X\n","user register", userRegister)); - str.append(String.format("%24s : 0x%X\n","user int #1", userIntFirst)); - str.append(String.format("%24s : 0x%X\n","user int #2", userIntSecond)); + str.append(String.format("%24s : %d\n", "trailer position", trailerPosition)); + str.append(String.format("%24s : 0x%X\n", "user register", userRegister)); + str.append(String.format("%24s : 0x%X\n", "user int #1", userIntFirst)); + str.append(String.format("%24s : 0x%X\n", "user int #2", userIntSecond)); return str.toString(); } @@ -863,39 +1021,45 @@ public String toString(){ /** * Take a string and add padding characters to its left side. * For pretty printing purposes. - * @param original string to modify - * @param pad character to pad with - * @param upTo length to make original string plus padding + * + * @param original string to modify + * @param pad character to pad with + * @param upTo length to make original string plus padding * @return pretty string. */ private static String padLeft(String original, String pad, int upTo) { int npadding = upTo - original.length(); StringBuilder str = new StringBuilder(); - if(npadding>0) for(int i = 0;i < npadding; i++) str.append(pad); + if (npadding > 0) + for (int i = 0; i < npadding; i++) + str.append(pad); str.append(original); return str.toString(); } /** * Print out each word of the given buffer as binary, hex, and decimal. + * * @param buffer buffer to print out. */ public static void byteBufferBinaryString(ByteBuffer buffer) { - int nwords = buffer.array().length/4; - for(int i = 0; i < nwords; i++){ - int value = buffer.getInt(i*4); + int nwords = buffer.array().length / 4; + for (int i = 0; i < nwords; i++) { + int value = buffer.getInt(i * 4); System.out.println(String.format(" word %4d : %36s 0x%8s : %18d", i, - padLeft(Integer.toBinaryString(value),"0",32), - padLeft(Integer.toHexString(value),"0",8), - value)); + padLeft(Integer.toBinaryString(value), "0", 32), + padLeft(Integer.toHexString(value), "0", 8), + value)); } } /** - * Run this class as an executable which tests the writing and reading of a record. + * Run this class as an executable which tests the writing and reading of a + * record. + * * @param args args */ - public static void main(String[] args){ + public static void main(String[] args) { FileHeader header = new FileHeader(); header.setUserHeaderLength(459); @@ -908,21 +1072,20 @@ public static void main(String[] args){ header.setHeaderLength(14); System.out.println(header); - byte[] array = new byte[14*4]; + byte[] array = new byte[14 * 4]; ByteBuffer buffer = ByteBuffer.wrap(array); buffer.order(ByteOrder.LITTLE_ENDIAN); try { header.writeHeader(buffer); - } - catch (HipoException e) {/* never happen */} + } catch (HipoException e) { + /* never happen */} FileHeader header2 = new FileHeader(); try { header2.readHeader(buffer); System.out.println(header2); - } - catch (HipoException e) { + } catch (HipoException e) { e.printStackTrace(); } } diff --git a/src/main/java/org/jlab/coda/hipo/Reader.java b/src/main/java/org/jlab/coda/hipo/Reader.java index 1d85f753b..a3e9a3a47 100644 --- a/src/main/java/org/jlab/coda/hipo/Reader.java +++ b/src/main/java/org/jlab/coda/hipo/Reader.java @@ -1817,9 +1817,9 @@ public void scanFile(boolean force) throws IOException, HipoException { // Index in trailer gets first priority. // Index in file header gets next priority. boolean fileHasIndex = fileHeader.hasTrailerWithIndex() || (fileHeader.hasIndex()); -//System.out.println(" file has index = " + fileHasIndex -// + ", has trailer w/ index = " + fileHeader.hasTrailerWithIndex() -// + ", file hdr has index = " + fileHeader.hasIndex()); + //System.out.println(" file has index = " + fileHasIndex + // + ", has trailer w/ index = " + fileHeader.hasTrailerWithIndex() + // + ", file hdr has index = " + fileHeader.hasIndex()); // If there is no index, scan file if (!fileHasIndex) { diff --git a/tutorials/cpp/EvioTestHelper.h b/src/test/cpp/EvioTestHelper.h similarity index 100% rename from tutorials/cpp/EvioTestHelper.h rename to src/test/cpp/EvioTestHelper.h diff --git a/tutorials/cpp/WritePseudoPhys_builder.cpp b/src/test/cpp/WritePseudoPhys_builder.cpp similarity index 100% rename from tutorials/cpp/WritePseudoPhys_builder.cpp rename to src/test/cpp/WritePseudoPhys_builder.cpp diff --git a/tutorials/cpp/WritePseudoPhys_compact.cpp b/src/test/cpp/WritePseudoPhys_compact.cpp similarity index 97% rename from tutorials/cpp/WritePseudoPhys_compact.cpp rename to src/test/cpp/WritePseudoPhys_compact.cpp index 3dfb1b40c..bba26eed1 100644 --- a/tutorials/cpp/WritePseudoPhys_compact.cpp +++ b/src/test/cpp/WritePseudoPhys_compact.cpp @@ -1,4 +1,4 @@ -#include "EvioTestHelper.h" // EVIO C++ API (EVIO 6 main branch) +#include "EvioTestHelper.h" using namespace evio; diff --git a/tutorials/cpp/WritePseudoPhys_simple.cpp b/src/test/cpp/WritePseudoPhys_simple.cpp similarity index 100% rename from tutorials/cpp/WritePseudoPhys_simple.cpp rename to src/test/cpp/WritePseudoPhys_simple.cpp diff --git a/src/test/java/FirstTest.java b/src/test/java/FirstTest.java index 0a3c32f40..d310b12ec 100644 --- a/src/test/java/FirstTest.java +++ b/src/test/java/FirstTest.java @@ -12,6 +12,8 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; +import org.jlab.coda.*; + @Tag("fast") // Run when selecting "fast" category of tests class FirstTest { @@ -19,8 +21,14 @@ class FirstTest { @Test @DisplayName("My 1st JUnit 5 test! 😎") void myFirstTest(TestInfo testInfo) { + assertEquals(2, 1+1, "1 + 1 should equal 2"); assertEquals("My 1st JUnit 5 test! 😎", testInfo.getDisplayName(), () -> "TestInfo is injected correctly"); + + + } + + } \ No newline at end of file diff --git a/tutorials/README.md b/tutorials/README.md index 8308c36e5..903fcef5a 100644 --- a/tutorials/README.md +++ b/tutorials/README.md @@ -1,3 +1,3 @@ -# ** Code Tutorials ** +# **Code Tutorials** Examples for using the evio C/C++/Java libraries. These are intended as examples for developers using EVIO as just one package in a larger software suite. See contents within each folder for more information. \ No newline at end of file From 30165a4c2dbb4614a270f19f742668675296b93d Mon Sep 17 00:00:00 2001 From: jonzarling Date: Fri, 6 Jun 2025 13:55:53 -0500 Subject: [PATCH 37/56] Fix pom file, add helper java class for unit tests --- pom.xml | 4 +- .../coda/jevio/unit_tests/EvioTestHelper.java | 97 +++++++++++++++++++ src/test/cpp/EvioTestHelper.h | 2 +- src/test/java/EvioWriteAndReadBack.java | 47 +++++++++ src/test/java/FirstTest.java | 6 +- 5 files changed, 149 insertions(+), 7 deletions(-) create mode 100644 src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java create mode 100644 src/test/java/EvioWriteAndReadBack.java diff --git a/pom.xml b/pom.xml index dd5105c14..de5fd85dc 100644 --- a/pom.xml +++ b/pom.xml @@ -86,7 +86,7 @@
- + diff --git a/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java b/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java new file mode 100644 index 000000000..f9a7878e0 --- /dev/null +++ b/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java @@ -0,0 +1,97 @@ +package org.jlab.coda.jevio.unit_tests; +import java.util.Random; +import java.nio.ByteOrder; + +import org.jlab.coda.hipo.CompressionType; +// Import evio +import org.jlab.coda.jevio.*; + +public class EvioTestHelper { + private final Random random; + + // Parameters (simplified here for brevity) + private final String baseNameV4 = "testEventsV4.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + private final String baseNameV6 = "testEventsV6.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + private final String baseNameHIPO = "testEventsHIPO.hipo"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + private final String directory = ""; // directory in which file is to be placed + private final String runType = ""; // name of run type configuration to be used in naming files + private final int runNumber = 1; // arbitrary, usually experiment-specific + private final long split = 0; // if < 1, do not split file, write to only one file of unlimited size. Else this is max size in bytes to make a file before closing it and starting writing another. + private final int maxRecordSize = 33554432; // (32 MiB) max number of uncompressed data bytes each record can hold. Value of < 8MB results in default of 8MB. The size of the record will not be larger than this size unless a single event itself is larger + private final int maxEventCount = 10000; // max number of events each RECORD can hold. Value <= O means use default (1M). + private final ByteOrder byteOrder = ByteOrder.nativeOrder(); // options: BIG_ENDIAN, LITTLE_ENDIAN, nativeOrder() + private final String XMLdictionary = + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n"; + private final boolean overWriteOK = true; + private final boolean append = false; + private final EvioBank firstEvent = null; // The first event written into each file (after any dictionary) including all split files; may be null. Useful for adding common, static info into each split file + private final int streamId = 1; // streamId number (100 > id > -1) for file name + private final int splitNumber = 0; // number at which to start the split numbers + private final int splitIncrement = 1; // amount to increment split number each time another file is created + private final int streamCount = 1; // total number of streams in DAQ + private final CompressionType compressionType = CompressionType.RECORD_UNCOMPRESSED; + private final CompressionType compressionTypeHIPO = CompressionType.RECORD_COMPRESSION_LZ4; + private final int compressionThreads = 1; // number of threads doing compression simultaneously + private final int ringSize = 0; // number of records in supply ring. If set to < compressionThreads, it is forced to equal that value and is also forced to be a multiple of 2, rounded up. + private final int bufferSize = 33554432; // (32 MiB) number of bytes to make each internal buffer which will be storing events before writing them to a file. 9MB = default if bufferSize = 0. + + // Constructor + public EvioTestHelper() { + this.random = new Random(); + } + + // Generate a float array similar to C++ vector + public float[] genXYZT(int i) { + float[] x4 = new float[5]; // matches C++ size + x4[0] = (float) random.nextGaussian() * 0.1f; + x4[1] = (float) random.nextGaussian() * 0.1f; + x4[2] = 0.0f; + x4[3] = i * 2.008f; + return x4; + } + + // Simulated writer method (stub for example purposes) + public EventWriter defaultEventWriter() { + + EventWriter w = null; + + try { + w = new EventWriter( + baseNameV6, + directory, + runType, + runNumber, + split, + maxRecordSize, + maxEventCount, + byteOrder, + XMLdictionary, + overWriteOK, + append, + firstEvent, + streamId, + splitNumber, + splitIncrement, + streamCount, + compressionType, + compressionThreads, + ringSize, + bufferSize); + } + catch (EvioException e) { + System.err.println("Error creating writer. Stack trace:\n "); + e.printStackTrace(); + } + return w; + } +} diff --git a/src/test/cpp/EvioTestHelper.h b/src/test/cpp/EvioTestHelper.h index 766dd006f..e49b1300c 100644 --- a/src/test/cpp/EvioTestHelper.h +++ b/src/test/cpp/EvioTestHelper.h @@ -128,7 +128,7 @@ using namespace evio; std::string baseNameV4 = "testEventsV4.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. std::string baseNameV6 = "testEventsV6.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. - std::string baseNameHIPO = "testEventsHIPO.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + std::string baseNameHIPO = "testEventsHIPO.hipo"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. const std::string directory = ""; // directory in which file is to be placed const std::string runType = ""; // name of run type configuration to be used in naming files uint32_t runNumber = 1; diff --git a/src/test/java/EvioWriteAndReadBack.java b/src/test/java/EvioWriteAndReadBack.java new file mode 100644 index 000000000..2d2eea1ca --- /dev/null +++ b/src/test/java/EvioWriteAndReadBack.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2025. Jefferson Lab (JLab). All rights reserved. Permission + * to use, copy, modify, and distribute this software and its documentation for + * educational, research, and not-for-profit purposes, without fee and without a + * signed licensing agreement. + */ + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInfo; + +import org.jlab.coda.jevio.*; +import org.jlab.coda.jevio.unit_tests.EvioTestHelper; + +@Tag("fast") // Run when selecting "fast" category of tests + +class EvioWriteAndReadBack { + + @Test + @DisplayName("Evio Write and Read Back Test") + void evioWriteAndReadBack(TestInfo testInfo) throws EvioException { + + + // Create a new EvioWriter + EvioWriter writer = EvioTestHelper.defaultEventWriter(); + + // // Create an event with some data + // EvioEvent event = new EvioEvent(1); + // float[] data = {1.0f, 2.0f, 3.0f, 4.0f}; + // event.addBank(new EvioBank("floatBank", 10, 1, data)); + + // // Write the event + // writer.writeEvent(event); + // writer.close(); + + // // Now read back the event + // EvioReader reader = new EvioReader("testEvents.evio"); + // EvioEvent readEvent = reader.readEvent(); + + // // Verify the data + // assertEquals(1, readEvent.getEventNumber(), "Event number should match"); + // assertEquals(4, readEvent.getBanks().get(0).getIntData().length, "Data length should match"); + } +} \ No newline at end of file diff --git a/src/test/java/FirstTest.java b/src/test/java/FirstTest.java index d310b12ec..cd8ccc033 100644 --- a/src/test/java/FirstTest.java +++ b/src/test/java/FirstTest.java @@ -12,7 +12,8 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; -import org.jlab.coda.*; +import org.jlab.coda.jevio.*; +// import EvioTestHelper; @Tag("fast") // Run when selecting "fast" category of tests @@ -24,9 +25,6 @@ void myFirstTest(TestInfo testInfo) { assertEquals(2, 1+1, "1 + 1 should equal 2"); assertEquals("My 1st JUnit 5 test! 😎", testInfo.getDisplayName(), () -> "TestInfo is injected correctly"); - - - } From a3249a97ab7dd8538b6e930ed822938b4439d797 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Fri, 6 Jun 2025 17:26:37 -0500 Subject: [PATCH 38/56] Now java test can at least write to file --- src/main/java/org/jlab/coda/jevio/manifest.mf | 5 -- .../coda/jevio/unit_tests/EvioTestHelper.java | 53 ++++++------ src/test/java/EvioWriteAndReadBack.java | 82 +++++++++++++++---- src/test/java/FirstTest.java | 1 - 4 files changed, 93 insertions(+), 48 deletions(-) delete mode 100644 src/main/java/org/jlab/coda/jevio/manifest.mf diff --git a/src/main/java/org/jlab/coda/jevio/manifest.mf b/src/main/java/org/jlab/coda/jevio/manifest.mf deleted file mode 100644 index f88bf6d05..000000000 --- a/src/main/java/org/jlab/coda/jevio/manifest.mf +++ /dev/null @@ -1,5 +0,0 @@ -Manifest-Version: 1.0 -Created-By: "Dave Heddle" -Specification-Title: jevio -Sealed: true -Main-Class: org.jlab.coda.jevio.test.HallDEventFiles diff --git a/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java b/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java index f9a7878e0..ee0980cf9 100644 --- a/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java +++ b/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java @@ -10,17 +10,18 @@ public class EvioTestHelper { private final Random random; // Parameters (simplified here for brevity) - private final String baseNameV4 = "testEventsV4.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. - private final String baseNameV6 = "testEventsV6.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. - private final String baseNameHIPO = "testEventsHIPO.hipo"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. - private final String directory = ""; // directory in which file is to be placed - private final String runType = ""; // name of run type configuration to be used in naming files - private final int runNumber = 1; // arbitrary, usually experiment-specific - private final long split = 0; // if < 1, do not split file, write to only one file of unlimited size. Else this is max size in bytes to make a file before closing it and starting writing another. - private final int maxRecordSize = 33554432; // (32 MiB) max number of uncompressed data bytes each record can hold. Value of < 8MB results in default of 8MB. The size of the record will not be larger than this size unless a single event itself is larger - private final int maxEventCount = 10000; // max number of events each RECORD can hold. Value <= O means use default (1M). - private final ByteOrder byteOrder = ByteOrder.nativeOrder(); // options: BIG_ENDIAN, LITTLE_ENDIAN, nativeOrder() - private final String XMLdictionary = + // apparently all files must have absolute paths!!!!! + private final String baseNameV4 = "/home/jzarling/super_evio_dev/evio/tmp/testEventsV4.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + private final static String baseNameV6 = "/home/jzarling/super_evio_dev/evio/tmp/testEventsV6.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + private final static String baseNameHIPO = "/home/jzarling/super_evio_dev/evio/tmp/testEventsHIPO.hipo"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + private final static String directory = ""; // directory in which file is to be placed + private final static String runType = ""; // name of run type configuration to be used in naming files + private final static int runNumber = 1; // arbitrary, usually experiment-specific + private final static long split = 0; // if < 1, do not split file, write to only one file of unlimited size. Else this is max size in bytes to make a file before closing it and starting writing another. + private final static int maxRecordSize = 33554432; // (32 MiB) max number of uncompressed data bytes each record can hold. Value of < 8MB results in default of 8MB. The size of the record will not be larger than this size unless a single event itself is larger + private final static int maxEventCount = 10000; // max number of events each RECORD can hold. Value <= O means use default (1M). + private final static ByteOrder byteOrder = ByteOrder.nativeOrder(); // options: BIG_ENDIAN, LITTLE_ENDIAN, nativeOrder() + private final static String XMLdictionary = "\n" + " \n" + " \n" + @@ -32,18 +33,18 @@ public class EvioTestHelper { " \n" + " \n" + "\n"; - private final boolean overWriteOK = true; - private final boolean append = false; - private final EvioBank firstEvent = null; // The first event written into each file (after any dictionary) including all split files; may be null. Useful for adding common, static info into each split file - private final int streamId = 1; // streamId number (100 > id > -1) for file name - private final int splitNumber = 0; // number at which to start the split numbers - private final int splitIncrement = 1; // amount to increment split number each time another file is created - private final int streamCount = 1; // total number of streams in DAQ - private final CompressionType compressionType = CompressionType.RECORD_UNCOMPRESSED; - private final CompressionType compressionTypeHIPO = CompressionType.RECORD_COMPRESSION_LZ4; - private final int compressionThreads = 1; // number of threads doing compression simultaneously - private final int ringSize = 0; // number of records in supply ring. If set to < compressionThreads, it is forced to equal that value and is also forced to be a multiple of 2, rounded up. - private final int bufferSize = 33554432; // (32 MiB) number of bytes to make each internal buffer which will be storing events before writing them to a file. 9MB = default if bufferSize = 0. + private final static boolean overWriteOK = true; + private final static boolean append = false; + private final static EvioBank firstEvent = null; // The first event written into each file (after any dictionary) including all split files; may be null. Useful for adding common, static info into each split file + private final static int streamId = 1; // streamId number (100 > id > -1) for file name + private final static int splitNumber = 0; // number at which to start the split numbers + private final static int splitIncrement = 1; // amount to increment split number each time another file is created + private final static int streamCount = 1; // total number of streams in DAQ + private final static CompressionType compressionType = CompressionType.RECORD_UNCOMPRESSED; + private final static CompressionType compressionTypeHIPO = CompressionType.RECORD_COMPRESSION_LZ4; + private final static int compressionThreads = 1; // number of threads doing compression simultaneously + private final static int ringSize = 0; // number of records in supply ring. If set to < compressionThreads, it is forced to equal that value and is also forced to be a multiple of 2, rounded up. + private final static int bufferSize = 33554432; // (32 MiB) number of bytes to make each internal buffer which will be storing events before writing them to a file. 9MB = default if bufferSize = 0. // Constructor public EvioTestHelper() { @@ -60,8 +61,8 @@ public float[] genXYZT(int i) { return x4; } - // Simulated writer method (stub for example purposes) - public EventWriter defaultEventWriter() { + // Default writer + public static EventWriter defaultEventWriter() { EventWriter w = null; @@ -94,4 +95,6 @@ public EventWriter defaultEventWriter() { } return w; } + + } diff --git a/src/test/java/EvioWriteAndReadBack.java b/src/test/java/EvioWriteAndReadBack.java index 2d2eea1ca..ec044ae13 100644 --- a/src/test/java/EvioWriteAndReadBack.java +++ b/src/test/java/EvioWriteAndReadBack.java @@ -12,36 +12,84 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; +import java.io.*; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.channels.AsynchronousFileChannel; +import java.nio.channels.FileChannel; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.Future; + +import org.jlab.coda.hipo.*; import org.jlab.coda.jevio.*; -import org.jlab.coda.jevio.unit_tests.EvioTestHelper; +import org.jlab.coda.jevio.unit_tests.EvioTestHelper; // helper class for unit tests, also contained in java src files @Tag("fast") // Run when selecting "fast" category of tests -class EvioWriteAndReadBack { +class EvioWriteAndReadBack { @Test @DisplayName("Evio Write and Read Back Test") - void evioWriteAndReadBack(TestInfo testInfo) throws EvioException { + // void evioWriteAndReadBack(TestInfo testInfo) throws IOException, EvioException { + // evioWriteAndReadBack(testInfo, 10); + // } + + void evioWriteAndReadBack(TestInfo testInfo) throws IOException, EvioException { + + int nEvents = 10; // number of events to writeint nEvents + + EvioTestHelper h = new EvioTestHelper(); // Create a new EvioWriter - EvioWriter writer = EvioTestHelper.defaultEventWriter(); + EventWriterUnsync writer = EvioTestHelper.defaultEventWriter(); + + // Generate and write events + for (int i = 0; i < nEvents; i++) { + + // Build a new event (top-level bank) with tag=1, type=BANK, num=1 + //------------------------------------- + int tag = 1; + int num = 1; + EventBuilder builder = new EventBuilder(tag, DataType.BANK, num); + float[] floatVec = h.genXYZT(i); // generate pseudo x, y, z, time values + + // Now to start defining event + EvioEvent event = builder.getEvent(); - // // Create an event with some data - // EvioEvent event = new EvioEvent(1); - // float[] data = {1.0f, 2.0f, 3.0f, 4.0f}; - // event.addBank(new EvioBank("floatBank", 10, 1, data)); + // THE OVERBANK + // First child of event = bank of banks + // EvioBank bankBanks = new EvioBank(tag+1, DataType.BANK, num+1); + // builder.addChild(event, bankBanks); - // // Write the event - // writer.writeEvent(event); - // writer.close(); + // (SUB)BANK 1 OF 1 + // Create first (& only) child of bank of banks = bank of floats + EvioBank bankFloats = new EvioBank(tag+11, DataType.FLOAT32, num+11); + bankFloats.appendFloatData(floatVec); // add float data to bank of floats + builder.addChild(event, bankFloats); - // // Now read back the event - // EvioReader reader = new EvioReader("testEvents.evio"); - // EvioEvent readEvent = reader.readEvent(); + try { + // Write the completed event to file + writer.writeEvent(event, false); + } + catch (EvioException e) { + System.out.println("EvioException: " + e.toString()); + } + } + // End of writing events + try { + writer.close(); + } + catch (Exception e) { + System.out.println("EvioException: " + e.toString()); + e.printStackTrace(); + } - // // Verify the data - // assertEquals(1, readEvent.getEventNumber(), "Event number should match"); - // assertEquals(4, readEvent.getBanks().get(0).getIntData().length, "Data length should match"); + System.out.println(" Wrote " + nEvents + " events to file. "); + } } \ No newline at end of file diff --git a/src/test/java/FirstTest.java b/src/test/java/FirstTest.java index cd8ccc033..2ac9143e6 100644 --- a/src/test/java/FirstTest.java +++ b/src/test/java/FirstTest.java @@ -13,7 +13,6 @@ import org.junit.jupiter.api.TestInfo; import org.jlab.coda.jevio.*; -// import EvioTestHelper; @Tag("fast") // Run when selecting "fast" category of tests From 7d9fb888f7597e9f2ff31dbd5e304dc700c59570 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Mon, 9 Jun 2025 10:09:16 -0500 Subject: [PATCH 39/56] Move etc/ files to proper java directory format. --- .../{ => org/jlab/coda}/hipo/test/README.md | 0 .../jlab/coda}/hipo/test/ReadWriteTest.java | 0 .../coda}/hipo/test/RecordSupplyTester.java | 0 .../jlab/coda}/hipo/test/TestBuilding.java | 0 .../jlab/coda}/hipo/test/TestWriter.java | 0 .../jlab/coda}/jevio/apps/Xml2evio.java | 0 .../jlab/coda}/jevio/test/BigFileWrite.java | 0 .../test/CompactReaderAddSubtractTest.java | 0 .../jevio/test/CompactReaderBugTest.java | 0 .../test/CompactStructureHandlerTest.java | 0 .../coda}/jevio/test/CompositeTester.java | 0 .../coda}/jevio/test/CompressionTest.java | 0 .../jlab/coda}/jevio/test/DictTest.java | 0 .../coda}/jevio/test/ExtractHallDdata.java | 0 .../jlab/coda}/jevio/test/FileTest.java | 0 .../jlab/coda}/jevio/test/FileTestVer6.java | 0 .../jlab/coda}/jevio/test/FileWriteTest.java | 0 .../jevio/test/FileWritingSpeedTest.java | 0 .../jlab/coda}/jevio/test/FirstEventTest.java | 0 .../jlab/coda}/jevio/test/HipoTest.java | 0 .../{ => org/jlab/coda}/jevio/test/README.md | 0 .../jlab/coda}/jevio/test/ReadAggOutput.java | 0 .../coda}/jevio/test/ReadSequenceTest.java | 0 .../jlab/coda}/jevio/test/ReadWriteTest.java | 0 .../coda}/jevio/test/ReadWriteV4Test.java | 0 .../coda}/jevio/test/RecordSupplyTest.java | 0 .../jevio/test/SequentialReaderTest.java | 0 .../jlab/coda}/jevio/test/SplitTest.java | 0 .../jlab/coda}/jevio/test/SwapTest.java | 0 .../jlab/coda}/jevio/test/TestBase.java | 0 .../jlab/coda}/jevio/test/TreeBufTest.java | 0 .../jlab/coda}/jevio/test/XmlTest.java | 0 .../{ => org/jlab}/jars/disruptor-3.4.3.jar | Bin .../jlab}/jars/java15/disruptor-4.0.0.jar | Bin .../{ => org/jlab}/jars/java15/jevio-6.0.jar | Bin .../jlab}/jars/java15/lz4-java.1.8.0.jar | Bin .../jlab}/jars/java8/disruptor-3.4.3.jar | Bin .../{ => org/jlab}/jars/java8/jevio-6.0.jar | Bin .../jlab}/jars/java8/lz4-java.1.8.0.jar | Bin .../{ => org/jlab}/jars/lz4-java.1.8.0.jar | Bin pom.xml | 2 +- .../coda/jevio/unit_tests/EvioTestHelper.java | 44 ++++++++++++++++-- src/test/java/EvioWriteAndReadBack.java | 2 +- 43 files changed, 42 insertions(+), 6 deletions(-) rename etc/java/{ => org/jlab/coda}/hipo/test/README.md (100%) rename etc/java/{ => org/jlab/coda}/hipo/test/ReadWriteTest.java (100%) rename etc/java/{ => org/jlab/coda}/hipo/test/RecordSupplyTester.java (100%) rename etc/java/{ => org/jlab/coda}/hipo/test/TestBuilding.java (100%) rename etc/java/{ => org/jlab/coda}/hipo/test/TestWriter.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/apps/Xml2evio.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/BigFileWrite.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/CompactReaderAddSubtractTest.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/CompactReaderBugTest.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/CompactStructureHandlerTest.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/CompositeTester.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/CompressionTest.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/DictTest.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/ExtractHallDdata.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/FileTest.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/FileTestVer6.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/FileWriteTest.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/FileWritingSpeedTest.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/FirstEventTest.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/HipoTest.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/README.md (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/ReadAggOutput.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/ReadSequenceTest.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/ReadWriteTest.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/ReadWriteV4Test.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/RecordSupplyTest.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/SequentialReaderTest.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/SplitTest.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/SwapTest.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/TestBase.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/TreeBufTest.java (100%) rename etc/java/{ => org/jlab/coda}/jevio/test/XmlTest.java (100%) rename etc/java/{ => org/jlab}/jars/disruptor-3.4.3.jar (100%) rename etc/java/{ => org/jlab}/jars/java15/disruptor-4.0.0.jar (100%) rename etc/java/{ => org/jlab}/jars/java15/jevio-6.0.jar (100%) rename etc/java/{ => org/jlab}/jars/java15/lz4-java.1.8.0.jar (100%) rename etc/java/{ => org/jlab}/jars/java8/disruptor-3.4.3.jar (100%) rename etc/java/{ => org/jlab}/jars/java8/jevio-6.0.jar (100%) rename etc/java/{ => org/jlab}/jars/java8/lz4-java.1.8.0.jar (100%) rename etc/java/{ => org/jlab}/jars/lz4-java.1.8.0.jar (100%) diff --git a/etc/java/hipo/test/README.md b/etc/java/org/jlab/coda/hipo/test/README.md similarity index 100% rename from etc/java/hipo/test/README.md rename to etc/java/org/jlab/coda/hipo/test/README.md diff --git a/etc/java/hipo/test/ReadWriteTest.java b/etc/java/org/jlab/coda/hipo/test/ReadWriteTest.java similarity index 100% rename from etc/java/hipo/test/ReadWriteTest.java rename to etc/java/org/jlab/coda/hipo/test/ReadWriteTest.java diff --git a/etc/java/hipo/test/RecordSupplyTester.java b/etc/java/org/jlab/coda/hipo/test/RecordSupplyTester.java similarity index 100% rename from etc/java/hipo/test/RecordSupplyTester.java rename to etc/java/org/jlab/coda/hipo/test/RecordSupplyTester.java diff --git a/etc/java/hipo/test/TestBuilding.java b/etc/java/org/jlab/coda/hipo/test/TestBuilding.java similarity index 100% rename from etc/java/hipo/test/TestBuilding.java rename to etc/java/org/jlab/coda/hipo/test/TestBuilding.java diff --git a/etc/java/hipo/test/TestWriter.java b/etc/java/org/jlab/coda/hipo/test/TestWriter.java similarity index 100% rename from etc/java/hipo/test/TestWriter.java rename to etc/java/org/jlab/coda/hipo/test/TestWriter.java diff --git a/etc/java/jevio/apps/Xml2evio.java b/etc/java/org/jlab/coda/jevio/apps/Xml2evio.java similarity index 100% rename from etc/java/jevio/apps/Xml2evio.java rename to etc/java/org/jlab/coda/jevio/apps/Xml2evio.java diff --git a/etc/java/jevio/test/BigFileWrite.java b/etc/java/org/jlab/coda/jevio/test/BigFileWrite.java similarity index 100% rename from etc/java/jevio/test/BigFileWrite.java rename to etc/java/org/jlab/coda/jevio/test/BigFileWrite.java diff --git a/etc/java/jevio/test/CompactReaderAddSubtractTest.java b/etc/java/org/jlab/coda/jevio/test/CompactReaderAddSubtractTest.java similarity index 100% rename from etc/java/jevio/test/CompactReaderAddSubtractTest.java rename to etc/java/org/jlab/coda/jevio/test/CompactReaderAddSubtractTest.java diff --git a/etc/java/jevio/test/CompactReaderBugTest.java b/etc/java/org/jlab/coda/jevio/test/CompactReaderBugTest.java similarity index 100% rename from etc/java/jevio/test/CompactReaderBugTest.java rename to etc/java/org/jlab/coda/jevio/test/CompactReaderBugTest.java diff --git a/etc/java/jevio/test/CompactStructureHandlerTest.java b/etc/java/org/jlab/coda/jevio/test/CompactStructureHandlerTest.java similarity index 100% rename from etc/java/jevio/test/CompactStructureHandlerTest.java rename to etc/java/org/jlab/coda/jevio/test/CompactStructureHandlerTest.java diff --git a/etc/java/jevio/test/CompositeTester.java b/etc/java/org/jlab/coda/jevio/test/CompositeTester.java similarity index 100% rename from etc/java/jevio/test/CompositeTester.java rename to etc/java/org/jlab/coda/jevio/test/CompositeTester.java diff --git a/etc/java/jevio/test/CompressionTest.java b/etc/java/org/jlab/coda/jevio/test/CompressionTest.java similarity index 100% rename from etc/java/jevio/test/CompressionTest.java rename to etc/java/org/jlab/coda/jevio/test/CompressionTest.java diff --git a/etc/java/jevio/test/DictTest.java b/etc/java/org/jlab/coda/jevio/test/DictTest.java similarity index 100% rename from etc/java/jevio/test/DictTest.java rename to etc/java/org/jlab/coda/jevio/test/DictTest.java diff --git a/etc/java/jevio/test/ExtractHallDdata.java b/etc/java/org/jlab/coda/jevio/test/ExtractHallDdata.java similarity index 100% rename from etc/java/jevio/test/ExtractHallDdata.java rename to etc/java/org/jlab/coda/jevio/test/ExtractHallDdata.java diff --git a/etc/java/jevio/test/FileTest.java b/etc/java/org/jlab/coda/jevio/test/FileTest.java similarity index 100% rename from etc/java/jevio/test/FileTest.java rename to etc/java/org/jlab/coda/jevio/test/FileTest.java diff --git a/etc/java/jevio/test/FileTestVer6.java b/etc/java/org/jlab/coda/jevio/test/FileTestVer6.java similarity index 100% rename from etc/java/jevio/test/FileTestVer6.java rename to etc/java/org/jlab/coda/jevio/test/FileTestVer6.java diff --git a/etc/java/jevio/test/FileWriteTest.java b/etc/java/org/jlab/coda/jevio/test/FileWriteTest.java similarity index 100% rename from etc/java/jevio/test/FileWriteTest.java rename to etc/java/org/jlab/coda/jevio/test/FileWriteTest.java diff --git a/etc/java/jevio/test/FileWritingSpeedTest.java b/etc/java/org/jlab/coda/jevio/test/FileWritingSpeedTest.java similarity index 100% rename from etc/java/jevio/test/FileWritingSpeedTest.java rename to etc/java/org/jlab/coda/jevio/test/FileWritingSpeedTest.java diff --git a/etc/java/jevio/test/FirstEventTest.java b/etc/java/org/jlab/coda/jevio/test/FirstEventTest.java similarity index 100% rename from etc/java/jevio/test/FirstEventTest.java rename to etc/java/org/jlab/coda/jevio/test/FirstEventTest.java diff --git a/etc/java/jevio/test/HipoTest.java b/etc/java/org/jlab/coda/jevio/test/HipoTest.java similarity index 100% rename from etc/java/jevio/test/HipoTest.java rename to etc/java/org/jlab/coda/jevio/test/HipoTest.java diff --git a/etc/java/jevio/test/README.md b/etc/java/org/jlab/coda/jevio/test/README.md similarity index 100% rename from etc/java/jevio/test/README.md rename to etc/java/org/jlab/coda/jevio/test/README.md diff --git a/etc/java/jevio/test/ReadAggOutput.java b/etc/java/org/jlab/coda/jevio/test/ReadAggOutput.java similarity index 100% rename from etc/java/jevio/test/ReadAggOutput.java rename to etc/java/org/jlab/coda/jevio/test/ReadAggOutput.java diff --git a/etc/java/jevio/test/ReadSequenceTest.java b/etc/java/org/jlab/coda/jevio/test/ReadSequenceTest.java similarity index 100% rename from etc/java/jevio/test/ReadSequenceTest.java rename to etc/java/org/jlab/coda/jevio/test/ReadSequenceTest.java diff --git a/etc/java/jevio/test/ReadWriteTest.java b/etc/java/org/jlab/coda/jevio/test/ReadWriteTest.java similarity index 100% rename from etc/java/jevio/test/ReadWriteTest.java rename to etc/java/org/jlab/coda/jevio/test/ReadWriteTest.java diff --git a/etc/java/jevio/test/ReadWriteV4Test.java b/etc/java/org/jlab/coda/jevio/test/ReadWriteV4Test.java similarity index 100% rename from etc/java/jevio/test/ReadWriteV4Test.java rename to etc/java/org/jlab/coda/jevio/test/ReadWriteV4Test.java diff --git a/etc/java/jevio/test/RecordSupplyTest.java b/etc/java/org/jlab/coda/jevio/test/RecordSupplyTest.java similarity index 100% rename from etc/java/jevio/test/RecordSupplyTest.java rename to etc/java/org/jlab/coda/jevio/test/RecordSupplyTest.java diff --git a/etc/java/jevio/test/SequentialReaderTest.java b/etc/java/org/jlab/coda/jevio/test/SequentialReaderTest.java similarity index 100% rename from etc/java/jevio/test/SequentialReaderTest.java rename to etc/java/org/jlab/coda/jevio/test/SequentialReaderTest.java diff --git a/etc/java/jevio/test/SplitTest.java b/etc/java/org/jlab/coda/jevio/test/SplitTest.java similarity index 100% rename from etc/java/jevio/test/SplitTest.java rename to etc/java/org/jlab/coda/jevio/test/SplitTest.java diff --git a/etc/java/jevio/test/SwapTest.java b/etc/java/org/jlab/coda/jevio/test/SwapTest.java similarity index 100% rename from etc/java/jevio/test/SwapTest.java rename to etc/java/org/jlab/coda/jevio/test/SwapTest.java diff --git a/etc/java/jevio/test/TestBase.java b/etc/java/org/jlab/coda/jevio/test/TestBase.java similarity index 100% rename from etc/java/jevio/test/TestBase.java rename to etc/java/org/jlab/coda/jevio/test/TestBase.java diff --git a/etc/java/jevio/test/TreeBufTest.java b/etc/java/org/jlab/coda/jevio/test/TreeBufTest.java similarity index 100% rename from etc/java/jevio/test/TreeBufTest.java rename to etc/java/org/jlab/coda/jevio/test/TreeBufTest.java diff --git a/etc/java/jevio/test/XmlTest.java b/etc/java/org/jlab/coda/jevio/test/XmlTest.java similarity index 100% rename from etc/java/jevio/test/XmlTest.java rename to etc/java/org/jlab/coda/jevio/test/XmlTest.java diff --git a/etc/java/jars/disruptor-3.4.3.jar b/etc/java/org/jlab/jars/disruptor-3.4.3.jar similarity index 100% rename from etc/java/jars/disruptor-3.4.3.jar rename to etc/java/org/jlab/jars/disruptor-3.4.3.jar diff --git a/etc/java/jars/java15/disruptor-4.0.0.jar b/etc/java/org/jlab/jars/java15/disruptor-4.0.0.jar similarity index 100% rename from etc/java/jars/java15/disruptor-4.0.0.jar rename to etc/java/org/jlab/jars/java15/disruptor-4.0.0.jar diff --git a/etc/java/jars/java15/jevio-6.0.jar b/etc/java/org/jlab/jars/java15/jevio-6.0.jar similarity index 100% rename from etc/java/jars/java15/jevio-6.0.jar rename to etc/java/org/jlab/jars/java15/jevio-6.0.jar diff --git a/etc/java/jars/java15/lz4-java.1.8.0.jar b/etc/java/org/jlab/jars/java15/lz4-java.1.8.0.jar similarity index 100% rename from etc/java/jars/java15/lz4-java.1.8.0.jar rename to etc/java/org/jlab/jars/java15/lz4-java.1.8.0.jar diff --git a/etc/java/jars/java8/disruptor-3.4.3.jar b/etc/java/org/jlab/jars/java8/disruptor-3.4.3.jar similarity index 100% rename from etc/java/jars/java8/disruptor-3.4.3.jar rename to etc/java/org/jlab/jars/java8/disruptor-3.4.3.jar diff --git a/etc/java/jars/java8/jevio-6.0.jar b/etc/java/org/jlab/jars/java8/jevio-6.0.jar similarity index 100% rename from etc/java/jars/java8/jevio-6.0.jar rename to etc/java/org/jlab/jars/java8/jevio-6.0.jar diff --git a/etc/java/jars/java8/lz4-java.1.8.0.jar b/etc/java/org/jlab/jars/java8/lz4-java.1.8.0.jar similarity index 100% rename from etc/java/jars/java8/lz4-java.1.8.0.jar rename to etc/java/org/jlab/jars/java8/lz4-java.1.8.0.jar diff --git a/etc/java/jars/lz4-java.1.8.0.jar b/etc/java/org/jlab/jars/lz4-java.1.8.0.jar similarity index 100% rename from etc/java/jars/lz4-java.1.8.0.jar rename to etc/java/org/jlab/jars/lz4-java.1.8.0.jar diff --git a/pom.xml b/pom.xml index de5fd85dc..f8956ceb2 100644 --- a/pom.xml +++ b/pom.xml @@ -99,7 +99,7 @@ - java/org/jlab/coda/jevio/test + etc/java/org/jlab/coda/jevio/test diff --git a/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java b/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java index ee0980cf9..934fe30c2 100644 --- a/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java +++ b/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java @@ -11,10 +11,10 @@ public class EvioTestHelper { // Parameters (simplified here for brevity) // apparently all files must have absolute paths!!!!! - private final String baseNameV4 = "/home/jzarling/super_evio_dev/evio/tmp/testEventsV4.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. - private final static String baseNameV6 = "/home/jzarling/super_evio_dev/evio/tmp/testEventsV6.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. - private final static String baseNameHIPO = "/home/jzarling/super_evio_dev/evio/tmp/testEventsHIPO.hipo"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. - private final static String directory = ""; // directory in which file is to be placed + private final static String baseNameV4 = "testEventsV4.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + private final static String baseNameV6 = "testEventsV6.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + private final static String baseNameHIPO = "testEventsHIPO.hipo"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + private final static String directory = "/mnt/tmpfs"; // null=relative path (or directory in which file is to be placed) private final static String runType = ""; // name of run type configuration to be used in naming files private final static int runNumber = 1; // arbitrary, usually experiment-specific private final static long split = 0; // if < 1, do not split file, write to only one file of unlimited size. Else this is max size in bytes to make a file before closing it and starting writing another. @@ -61,6 +61,42 @@ public float[] genXYZT(int i) { return x4; } + public static EventWriterV4 defaultEventWriterV4() { + + // EventWriterV4 w = null; + + EventWriterV4 w = null; + + try { + + w = new EventWriterV4( + baseNameV4, + directory, + runType, + runNumber, + split, + maxRecordSize, + maxEventCount, + 10000, + byteOrder, + XMLdictionary, + null, + overWriteOK, + append, + firstEvent, + streamId, + splitNumber, + splitIncrement, + streamCount +); + } + catch (EvioException e) { + System.err.println("Error creating writer. Stack trace:\n "); + e.printStackTrace(); + } + return w; + } + // Default writer public static EventWriter defaultEventWriter() { diff --git a/src/test/java/EvioWriteAndReadBack.java b/src/test/java/EvioWriteAndReadBack.java index ec044ae13..1637f8dad 100644 --- a/src/test/java/EvioWriteAndReadBack.java +++ b/src/test/java/EvioWriteAndReadBack.java @@ -41,7 +41,7 @@ class EvioWriteAndReadBack { void evioWriteAndReadBack(TestInfo testInfo) throws IOException, EvioException { - int nEvents = 10; // number of events to writeint nEvents + int nEvents = 100000000; // 100 M events EvioTestHelper h = new EvioTestHelper(); From 4bdfbce7462e7e8080dad171b3bac735e8e49d3c Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Mon, 9 Jun 2025 16:42:09 -0500 Subject: [PATCH 40/56] Move files, change file names --- .gitignore | 1 + .../coda/jevio/unit_tests/EvioTestHelper.java | 2 +- {etc/src => src}/test/cpp/BigFileWrite.cpp | 0 .../test/cpp/BigFileWritePrimitive.cpp | 0 src/test/cpp/EvioTestHelper.h | 2 +- src/test/cpp/EvioWriteAndReadBack_builder.cpp | 62 +++++++++++++++++++ ...t.cpp => EvioWriteAndReadBack_compact.cpp} | 22 ++----- ...le.cpp => EvioWriteAndReadBack_simple.cpp} | 12 ++-- src/test/cpp/WritePseudoPhys_builder.cpp | 52 ---------------- ...java => EvioWriteAndReadBack_builder.java} | 16 +++-- 10 files changed, 88 insertions(+), 81 deletions(-) rename {etc/src => src}/test/cpp/BigFileWrite.cpp (100%) rename {etc/src => src}/test/cpp/BigFileWritePrimitive.cpp (100%) create mode 100644 src/test/cpp/EvioWriteAndReadBack_builder.cpp rename src/test/cpp/{WritePseudoPhys_compact.cpp => EvioWriteAndReadBack_compact.cpp} (89%) rename src/test/cpp/{WritePseudoPhys_simple.cpp => EvioWriteAndReadBack_simple.cpp} (80%) delete mode 100644 src/test/cpp/WritePseudoPhys_builder.cpp rename src/test/java/{EvioWriteAndReadBack.java => EvioWriteAndReadBack_builder.java} (90%) diff --git a/.gitignore b/.gitignore index 2ad1d034e..f69be736e 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ _* *.txt # EventViewer Jar JEventViewer*.jar +perf.data* # except these two !.gitignore diff --git a/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java b/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java index 934fe30c2..726c70cbb 100644 --- a/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java +++ b/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java @@ -14,7 +14,7 @@ public class EvioTestHelper { private final static String baseNameV4 = "testEventsV4.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. private final static String baseNameV6 = "testEventsV6.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. private final static String baseNameHIPO = "testEventsHIPO.hipo"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. - private final static String directory = "/mnt/tmpfs"; // null=relative path (or directory in which file is to be placed) + private final static String directory = null; // "/mnt/tmpfs" or null=relative path (or directory in which file is to be placed) private final static String runType = ""; // name of run type configuration to be used in naming files private final static int runNumber = 1; // arbitrary, usually experiment-specific private final static long split = 0; // if < 1, do not split file, write to only one file of unlimited size. Else this is max size in bytes to make a file before closing it and starting writing another. diff --git a/etc/src/test/cpp/BigFileWrite.cpp b/src/test/cpp/BigFileWrite.cpp similarity index 100% rename from etc/src/test/cpp/BigFileWrite.cpp rename to src/test/cpp/BigFileWrite.cpp diff --git a/etc/src/test/cpp/BigFileWritePrimitive.cpp b/src/test/cpp/BigFileWritePrimitive.cpp similarity index 100% rename from etc/src/test/cpp/BigFileWritePrimitive.cpp rename to src/test/cpp/BigFileWritePrimitive.cpp diff --git a/src/test/cpp/EvioTestHelper.h b/src/test/cpp/EvioTestHelper.h index e49b1300c..83a8e9909 100644 --- a/src/test/cpp/EvioTestHelper.h +++ b/src/test/cpp/EvioTestHelper.h @@ -129,7 +129,7 @@ using namespace evio; std::string baseNameV4 = "testEventsV4.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. std::string baseNameV6 = "testEventsV6.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. std::string baseNameHIPO = "testEventsHIPO.hipo"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. - const std::string directory = ""; // directory in which file is to be placed + const std::string directory = "tmp"; // directory in which file is to be placed const std::string runType = ""; // name of run type configuration to be used in naming files uint32_t runNumber = 1; uint64_t split = 0; // if < 1, do not split file, write to only one file of unlimited size. Else this is max size in bytes to make a file before closing it and starting writing another. diff --git a/src/test/cpp/EvioWriteAndReadBack_builder.cpp b/src/test/cpp/EvioWriteAndReadBack_builder.cpp new file mode 100644 index 000000000..7687cee7c --- /dev/null +++ b/src/test/cpp/EvioWriteAndReadBack_builder.cpp @@ -0,0 +1,62 @@ +#include "EvioTestHelper.h" // EVIO C++ API (EVIO 6 main branch) + +using namespace evio; + +int main(int argc, char* argv[]) { + + // Boilerplate + if (argc != 2) { + std::cerr << "Usage: " << argv[0] << " \n"; + return 1; + } + int nEvents = std::stoi(argv[1]); + std::cout << "Writing " << nEvents << " events to files..." << std::endl; + EvioTestHelper* evioHelperObj = new EvioTestHelper(); + + // std::shared_ptr writerV4 = evioHelperObj->defaultEventWriterV4(); + std::shared_ptr writerV6 = evioHelperObj->defaultEventWriter(); + // std::shared_ptr writerHipo = evioHelperObj->defaultEventWriterHIPO(); + + std::shared_ptr builder = NULL; + std::shared_ptr event = NULL; + + for (int i = 0; i < nEvents; ++i) { + + // Build a new event (top-level bank) with tag=1, type=BANK, num=1 + //------------------------------------- + uint16_t tag = 1; + uint8_t num = 1; + // if(i == 0) { + builder = std::make_shared(tag, DataType::BANK, num); + event = builder->getEvent(); + // } + // else { + // builder = std::make_shared(event); + // } + + std::vector floatVec = evioHelperObj->genXYZT(i); // generate pseudo x, y, z, time values + // std::vector floatVec = {0.0f, 1.0f, 2.0f, 3.0f, 4.0f}; // Example data for testing + + // Now to start defining event + + // // THE OVERBANK + // // First child of event = bank of banks + // auto bankBanks = EvioBank::getInstance(tag+1, DataType::BANK, num+1); + // builder->addChild(event, bankBanks); + + // // (SUB)BANK 1 OF 1 + // // Create first (& only) child of bank of banks = bank of floats + auto bankFloats = EvioBank::getInstance(tag+11, DataType::FLOAT32, num+11); + // // Write our data into bank + builder->setFloatData(bankFloats, floatVec.data(), floatVec.size()); + builder->addChild(event, bankFloats); + + // // Write the completed event to file + // writerV6->writeEvent(event); + } + + writerV6->close(); // close file writer (flush remaining data)​:contentReference[oaicite:6]{index=6} + std::cout << "Wrote " << nEvents << " events to file." << std::endl; + return 0; + +} diff --git a/src/test/cpp/WritePseudoPhys_compact.cpp b/src/test/cpp/EvioWriteAndReadBack_compact.cpp similarity index 89% rename from src/test/cpp/WritePseudoPhys_compact.cpp rename to src/test/cpp/EvioWriteAndReadBack_compact.cpp index bba26eed1..f74ce21d5 100644 --- a/src/test/cpp/WritePseudoPhys_compact.cpp +++ b/src/test/cpp/EvioWriteAndReadBack_compact.cpp @@ -13,9 +13,9 @@ int main(int argc, char** argv) { std::cout << "Writing " << nEvents << " events to files..." << std::endl; EvioTestHelper* evioHelperObj = new EvioTestHelper(); - std::shared_ptr writerV4 = evioHelperObj->defaultEventWriterV4(); + // std::shared_ptr writerV4 = evioHelperObj->defaultEventWriterV4(); std::shared_ptr writerV6 = evioHelperObj->defaultEventWriter(); - std::shared_ptr writerHipo = evioHelperObj->defaultEventWriterHIPO(); + // std::shared_ptr writerHipo = evioHelperObj->defaultEventWriterHIPO(); for (int i = 0; i < nEvents; ++i) { @@ -47,16 +47,6 @@ int main(int argc, char** argv) { // (this sets the proper pos and lim in buffer) std::shared_ptr& bytebbuffer = builder->getBuffer(); - - - - - - - - - - // Create an event as a bank containing four 32-bit floats std::shared_ptr event = EvioBank::getInstance(1, DataType::FLOAT32, 1); // Fill the bank's float data (x, y, z, time) with 0.0 @@ -65,15 +55,15 @@ int main(int argc, char** argv) { event->updateFloatData(); // update internal length counters​:contentReference[oaicite:3]{index=3} // Write the event to each file format - writerV4->writeEvent(event); + // writerV4->writeEvent(event); writerV6->writeEvent(event); - writerHipo->writeEvent(event); + // writerHipo->writeEvent(event); } // Close the writers, flush buffers - writerV4->close(); + // writerV4->close(); writerV6->close(); - writerHipo->close(); + // writerHipo->close(); std::cout << "Wrote " << nEvents << " events to EVIO4, EVIO6, and HIPO format files." << std::endl; delete evioHelperObj; diff --git a/src/test/cpp/WritePseudoPhys_simple.cpp b/src/test/cpp/EvioWriteAndReadBack_simple.cpp similarity index 80% rename from src/test/cpp/WritePseudoPhys_simple.cpp rename to src/test/cpp/EvioWriteAndReadBack_simple.cpp index 61f0ac05e..093d765e8 100644 --- a/src/test/cpp/WritePseudoPhys_simple.cpp +++ b/src/test/cpp/EvioWriteAndReadBack_simple.cpp @@ -13,9 +13,9 @@ int main(int argc, char** argv) { std::cout << "Writing " << nEvents << " events to files..." << std::endl; EvioTestHelper* evioHelperObj = new EvioTestHelper(); - std::shared_ptr writerV4 = evioHelperObj->defaultEventWriterV4(); + // std::shared_ptr writerV4 = evioHelperObj->defaultEventWriterV4(); std::shared_ptr writerV6 = evioHelperObj->defaultEventWriter(); - std::shared_ptr writerHipo = evioHelperObj->defaultEventWriterHIPO(); + // std::shared_ptr writerHipo = evioHelperObj->defaultEventWriterHIPO(); for (int i = 0; i < nEvents; ++i) { // Create an event as a bank containing four 32-bit floats @@ -26,15 +26,15 @@ int main(int argc, char** argv) { event->updateFloatData(); // update internal length counters​:contentReference[oaicite:3]{index=3} // Write the event to each file format - writerV4->writeEvent(event); + // writerV4->writeEvent(event); writerV6->writeEvent(event); - writerHipo->writeEvent(event); + // writerHipo->writeEvent(event); } // Close the writers, flush buffers - writerV4->close(); + // writerV4->close(); writerV6->close(); - writerHipo->close(); + // writerHipo->close(); std::cout << "Wrote " << nEvents << " events to EVIO4, EVIO6, and HIPO format files." << std::endl; delete evioHelperObj; diff --git a/src/test/cpp/WritePseudoPhys_builder.cpp b/src/test/cpp/WritePseudoPhys_builder.cpp deleted file mode 100644 index 90dd3371b..000000000 --- a/src/test/cpp/WritePseudoPhys_builder.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "EvioTestHelper.h" // EVIO C++ API (EVIO 6 main branch) - -using namespace evio; - -int main(int argc, char* argv[]) { - - // Boilerplate - if (argc != 2) { - std::cerr << "Usage: " << argv[0] << " \n"; - return 1; - } - int nEvents = std::stoi(argv[1]); - std::cout << "Writing " << nEvents << " events to files..." << std::endl; - EvioTestHelper* evioHelperObj = new EvioTestHelper(); - - std::shared_ptr writerV4 = evioHelperObj->defaultEventWriterV4(); - std::shared_ptr writerV6 = evioHelperObj->defaultEventWriter(); - std::shared_ptr writerHipo = evioHelperObj->defaultEventWriterHIPO(); - - for (int i = 0; i < nEvents; ++i) { - - // Build a new event (top-level bank) with tag=1, type=BANK, num=1 - //------------------------------------- - uint16_t tag = 1; - uint8_t num = 1; - EventBuilder builder(tag, DataType::BANK, num); - auto floatVec = evioHelperObj->genXYZT(i); // generate pseudo x, y, z, time values - - // Now to start defining event - std::shared_ptr event = builder.getEvent(); - - // THE OVERBANK - // First child of event = bank of banks - auto bankBanks = EvioBank::getInstance(tag+1, DataType::BANK, num+1); - builder.addChild(event, bankBanks); - - // (SUB)BANK 1 OF 1 - // Create first (& only) child of bank of banks = bank of floats - auto bankFloats = EvioBank::getInstance(tag+11, DataType::FLOAT32, num+11); - // Write our data into bank - builder.setFloatData(bankFloats, floatVec.data(), floatVec.size()); - builder.addChild(bankBanks, bankFloats); - - // Write the completed event to file - writerV6->writeEvent(event); - } - - writerV6->close(); // close file writer (flush remaining data)​:contentReference[oaicite:6]{index=6} - std::cout << "Wrote " << nEvents << " events to file." << std::endl; - return 0; - -} diff --git a/src/test/java/EvioWriteAndReadBack.java b/src/test/java/EvioWriteAndReadBack_builder.java similarity index 90% rename from src/test/java/EvioWriteAndReadBack.java rename to src/test/java/EvioWriteAndReadBack_builder.java index 1637f8dad..bf070c6a9 100644 --- a/src/test/java/EvioWriteAndReadBack.java +++ b/src/test/java/EvioWriteAndReadBack_builder.java @@ -30,7 +30,7 @@ @Tag("fast") // Run when selecting "fast" category of tests -class EvioWriteAndReadBack { +class EvioWriteAndReadBack_builder { @Test @DisplayName("Evio Write and Read Back Test") @@ -41,13 +41,16 @@ class EvioWriteAndReadBack { void evioWriteAndReadBack(TestInfo testInfo) throws IOException, EvioException { - int nEvents = 100000000; // 100 M events + int nEvents = 100000; // 10 M events EvioTestHelper h = new EvioTestHelper(); // Create a new EvioWriter EventWriterUnsync writer = EvioTestHelper.defaultEventWriter(); + EventBuilder builder = null; + EvioEvent event = null; + // Generate and write events for (int i = 0; i < nEvents; i++) { @@ -55,12 +58,15 @@ void evioWriteAndReadBack(TestInfo testInfo) throws IOException, EvioException { //------------------------------------- int tag = 1; int num = 1; - EventBuilder builder = new EventBuilder(tag, DataType.BANK, num); + float[] floatVec = h.genXYZT(i); // generate pseudo x, y, z, time values // Now to start defining event - EvioEvent event = builder.getEvent(); - + // if(i == 0) { + builder = new EventBuilder(tag, DataType.BANK, num); + event = builder.getEvent(); + // } + // THE OVERBANK // First child of event = bank of banks // EvioBank bankBanks = new EvioBank(tag+1, DataType.BANK, num+1); From e11579337dd0cf1dca2d93f7ed2fe0288f5994b8 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Tue, 10 Jun 2025 17:25:23 -0500 Subject: [PATCH 41/56] Fix a really nasty memory leak due to shared pointers getting stuck in cyclic dependence (parent and child) --- src/libsrc++/BaseStructure.cpp | 10 +++++----- src/libsrc++/BaseStructure.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libsrc++/BaseStructure.cpp b/src/libsrc++/BaseStructure.cpp index 2cb348a58..424b1e7a7 100644 --- a/src/libsrc++/BaseStructure.cpp +++ b/src/libsrc++/BaseStructure.cpp @@ -367,8 +367,8 @@ namespace evio { * * @param newParent this node's new parent. */ - void BaseStructure::setParent(const std::shared_ptr newParent) {parent = newParent;} + void BaseStructure::setParent(std::weak_ptr newParent) {parent = std::move(newParent);} /** * Removes newChild from its present parent (if it has a @@ -435,7 +435,7 @@ namespace evio { curIndex++; } - child->setParent(nullptr); + child->setParent(std::weak_ptr()); setLengthsUpToDate(false); } @@ -445,7 +445,7 @@ namespace evio { * Originally part of java's DefaultMutableTreeNode. * @return this node's parent BaseStructure, or null if this node has no parent. */ - std::shared_ptr BaseStructure::getParent() const { return parent; } + std::shared_ptr BaseStructure::getParent() const { return parent.lock();} /** @@ -2630,8 +2630,8 @@ namespace evio { if (!lenUpToDate) { // propagate back up the tree if lengths have been changed - if (parent != nullptr) { - parent->setLengthsUpToDate(false); + if (!parent.expired()) { + parent.lock()->setLengthsUpToDate(false); } } } diff --git a/src/libsrc++/BaseStructure.h b/src/libsrc++/BaseStructure.h index 3f23a3df1..21ff38130 100644 --- a/src/libsrc++/BaseStructure.h +++ b/src/libsrc++/BaseStructure.h @@ -423,7 +423,7 @@ namespace evio { protected: /** This node's parent, or null if this node has no parent. */ - std::shared_ptr parent = nullptr; + std::weak_ptr parent; /** Array of children, may be null if this node has no children. */ std::vector> children; @@ -450,7 +450,7 @@ namespace evio { protected: - void setParent(std::shared_ptr newParent); + void setParent(std::weak_ptr newParent); public: From 6dcf5da57e2c5f17560b60a70e816db52b1adaa9 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Wed, 11 Jun 2025 13:31:20 -0500 Subject: [PATCH 42/56] Tweak tests; fix nullptr to proper value so code compiles again after weak_ptr switch --- CMakeLists.txt | 3 ++- src/libsrc++/EventBuilder.cpp | 2 +- src/test/cpp/EvioWriteAndReadBack_builder.cpp | 23 +++++++++++-------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fc04ce8d5..db134cc11 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -254,7 +254,8 @@ endif() # Unit testing setup # add_executable(test_basic src/test/cpp/test_basic.cpp) # Already done above -# add_test(NAME ctest_test COMMAND bin/ctest_test) +add_test(NAME ctest_test COMMAND bin/ctest_test) +add_test(NAME EvioWriteAndReadBack_builder COMMAND bin/EvioWriteAndReadBack_builder 10) # Uninstall target # Removed for now, not yet compatible with building disruptor-cpp internally diff --git a/src/libsrc++/EventBuilder.cpp b/src/libsrc++/EventBuilder.cpp index ad84ac45c..43e21550e 100644 --- a/src/libsrc++/EventBuilder.cpp +++ b/src/libsrc++/EventBuilder.cpp @@ -142,7 +142,7 @@ namespace evio { } child->removeFromParent(); - child->setParent(nullptr); + child->setParent(std::weak_ptr()); setAllHeaderLengths(); } diff --git a/src/test/cpp/EvioWriteAndReadBack_builder.cpp b/src/test/cpp/EvioWriteAndReadBack_builder.cpp index 7687cee7c..ea952702d 100644 --- a/src/test/cpp/EvioWriteAndReadBack_builder.cpp +++ b/src/test/cpp/EvioWriteAndReadBack_builder.cpp @@ -17,9 +17,6 @@ int main(int argc, char* argv[]) { std::shared_ptr writerV6 = evioHelperObj->defaultEventWriter(); // std::shared_ptr writerHipo = evioHelperObj->defaultEventWriterHIPO(); - std::shared_ptr builder = NULL; - std::shared_ptr event = NULL; - for (int i = 0; i < nEvents; ++i) { // Build a new event (top-level bank) with tag=1, type=BANK, num=1 @@ -27,15 +24,15 @@ int main(int argc, char* argv[]) { uint16_t tag = 1; uint8_t num = 1; // if(i == 0) { - builder = std::make_shared(tag, DataType::BANK, num); - event = builder->getEvent(); + std::shared_ptr builder = std::make_shared(tag, DataType::BANK, num); + std::shared_ptr event = builder->getEvent(); // } // else { // builder = std::make_shared(event); // } - std::vector floatVec = evioHelperObj->genXYZT(i); // generate pseudo x, y, z, time values - // std::vector floatVec = {0.0f, 1.0f, 2.0f, 3.0f, 4.0f}; // Example data for testing + // std::vector floatVec = evioHelperObj->genXYZT(i); // generate pseudo x, y, z, time values + std::vector floatVec = {0.0f, 1.0f, 2.0f, 3.0f, 4.0f}; // Example data for testing // Now to start defining event @@ -46,15 +43,21 @@ int main(int argc, char* argv[]) { // // (SUB)BANK 1 OF 1 // // Create first (& only) child of bank of banks = bank of floats - auto bankFloats = EvioBank::getInstance(tag+11, DataType::FLOAT32, num+11); + std::shared_ptr bankFloats = EvioBank::getInstance(tag+11, DataType::FLOAT32, num+11); // // Write our data into bank builder->setFloatData(bankFloats, floatVec.data(), floatVec.size()); builder->addChild(event, bankFloats); - // // Write the completed event to file - // writerV6->writeEvent(event); + // Write the completed event to file + writerV6->writeEvent(event); + + // event.reset(); + // bankFloats.reset(); + // builder.reset(); + // floatVec.clear(); } + writerV6->close(); // close file writer (flush remaining data)​:contentReference[oaicite:6]{index=6} std::cout << "Wrote " << nEvents << " events to file." << std::endl; return 0; From 5342303a7c919f75b84b14e3485a6cbd838921c9 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Wed, 11 Jun 2025 15:18:29 -0500 Subject: [PATCH 43/56] Add another test program to debug --- src/libsrc++/EvioReaderV4.cpp | 14 ++++++ src/test/cpp/evioReadTest.cpp | 62 +++++++++++++++++++++++++ tmp/README.md | 86 +++++++++++++++++++++++++++++++++++ 3 files changed, 162 insertions(+) create mode 100644 src/test/cpp/evioReadTest.cpp create mode 100644 tmp/README.md diff --git a/src/libsrc++/EvioReaderV4.cpp b/src/libsrc++/EvioReaderV4.cpp index 9a2d207fe..6d6e32e18 100644 --- a/src/libsrc++/EvioReaderV4.cpp +++ b/src/libsrc++/EvioReaderV4.cpp @@ -510,6 +510,9 @@ namespace evio { // std::cout << std::endl << dec; // Read the header data + // Here's the offending setSize() + // std::cerr << "1) EvioReaderV4: doing setSize()" << std::endl; + // std::cerr << "Size: " << headerBuf->getInt() << std::endl; blockHeader4->setSize( headerBuf->getInt()); blockHeader4->setNumber( headerBuf->getInt()); blockHeader4->setHeaderLength(headerBuf->getInt()); @@ -784,8 +787,19 @@ namespace evio { blockHeader->setBufferStartingPosition(byteBuffer->position()); } + // DEBUG: print out the buffer information + std::cout << "EvioReaderV4: buffer pos = " << byteBuffer->position() << + ", limit = " << byteBuffer->limit() << + ", remaining = " << byteBuffer->remaining() << + ", capacity = " << byteBuffer->capacity() << std::endl; + + if (evioVersion >= 4) { // Read the header data. + + // Here's the offending setSize() + std::cerr << "2) EvioReaderV4: doing setSize()" << std::endl; + std::cerr << "Size: " << byteBuffer->getInt() << std::endl; blockHeader4->setSize(byteBuffer->getInt()); blockHeader4->setNumber(byteBuffer->getInt()); blockHeader4->setHeaderLength(byteBuffer->getInt()); diff --git a/src/test/cpp/evioReadTest.cpp b/src/test/cpp/evioReadTest.cpp new file mode 100644 index 000000000..7a3cd7dd9 --- /dev/null +++ b/src/test/cpp/evioReadTest.cpp @@ -0,0 +1,62 @@ +// Description: Test program to read an evio file and print its contents. +// This taken mostly from ReadWriteV4Test.cpp +#include +#include +#include +#include + + +using namespace std; +using namespace evio; + +void readFile(string finalFilename) { + + std::cout << std::endl; + std::cout << "--------------------------------------------" << std::endl; + std::cout << "---------- Read from file --------------" << std::endl; + std::cout << "--------------------------------------------" << std::endl; + + EvioReader reader(finalFilename); + ByteOrder & order = reader.getByteOrder(); + + cout << "Read in file " << finalFilename << " of byte order " << order.getName() << endl; + cout << "Evio version: " << reader.getEvioVersion() << endl; + int32_t evCount = reader.getEventCount(); + cout << "Got " << evCount << " events" << endl; + + string dict = reader.getDictionaryXML(); + if (dict.empty()) { + cout << "\nNo dictionary" << endl; + } + else { + cout << "\nGot dictionary:\n" << dict << endl; + } + + auto pFE = reader.getFirstEvent(); + if (pFE != nullptr) { + cout << "\nGot first Event:\n" << pFE->toString() << endl << endl; + } + else { + cout << "\nNo first event" << endl; + } + + cout << "Print out regular events:" << endl; + + for (int i=0; i < evCount; i++) { + auto ev = reader.getEvent(i+1); + cout << "\nEvent" << (i+1) << ":\n" << ev->toString() << endl; + } +} + +int main(int argc, char **argv) { + + if( argc > 1 ) { + string filename = argv[1]; + readFile(filename); + }else{ + std::cout << "Usage: evioReadTest " << std::endl; + std::cout << " where is the path to an evio file" << std::endl; + } + + return 0; +} diff --git a/tmp/README.md b/tmp/README.md new file mode 100644 index 000000000..71d089bc7 --- /dev/null +++ b/tmp/README.md @@ -0,0 +1,86 @@ + +Here is how to convert the CLAS12 pcap files into evio and then into ROOT trees. + +Note that a single pcap file has packets destined for 24 different ports. Each stream maintains its own EVIO format so the streams must be split and then the payloads extracted in order to get valid EVIO. + +## Get the pcap headers and libraries + +This is a round-about way of getting these on the ifarm. If the libpcap-devel package were installed there, then this would not be needed. It is a quick and dirty recipe though for getting these by installing the package in a docker container that is using the same almalinux 9.5 OS that the ifarm is currently using. The files are just copied from there. Skip this if you already have them through other means. +~~~bash +mkdir -p opt/include opt/lib64 +podman run -it --rm -v $PWD/opt:/work docker://almalinux:9.5 bash + +dnf install -y 'dnf-command(config-manager)' +dnf config-manager --set-enabled crb +dnf install -y libpcap-devel + +cp -rp /usr/include/*pcap* /work/include +cp -rp /usr/lib64/*pcap* /work/lib64 +exit +~~~ + +## Build the first two tools. + +Clone the existing SRO-RTDP repository and build the pcapSplit and pcpa2evio tools. + +~~~bash +git clone git@github.com:JeffersonLab/SRO-RTDP + +g++ -g -std=c++2a -o pcapSplit -Iopt/include -Lopt/lib64 SRO-RTDP/src/utilities/cpp/pcapSplit/pcapSplit.cc -lpcap +g++ -g -std=c++2a -o pcap2evio -Iopt/include -Lopt/lib64 SRO-RTDP/src/utilities/cpp/pcap2evio/pcap2evio.cc -lpcap +~~~ + +## Convert into EVIO +Here are commands to split the captured *.pcap* file and then convert one of them into *evio*. You will only need to run the split command once as that should create 24 *pcap* files. One for each stream. The *pcap2evio* command will need to be run on each single split file you want to process. Thus, if you process all of them, you will end up with 24 *evio* files. +~~~bash +jcache get /mss/epsci/RTDP/2024.05.16.RTDP_CLAS12/CLAS12_ECAL_PCAL_DC_2024-05-16_09-07-18.pcap +ln -s /cache/epsci/RTDP/2024.05.16.RTDP_CLAS12/CLAS12_ECAL_PCAL_DC_2024-05-16_09-07-18.pcap +./pcapSplit CLAS12_ECAL_PCAL_DC_2024-05-16_09-07-18.pcap + +# Repeat this for each port +./pcap2evio CLAS12_ECAL_PCAL_DC_2024-05-16_09-07-18.pcap_split/port7001.pcap +~~~ + +## Convert the EVIO file(s) into *ROOT* +This is just an example of reading an *evio* created in the previous step and plotting one of the braches. + +n.b. This does minimal EVIO parsing and does *not* use the EVIO library. It should be easy to though, but it will need to use the EVIO-4 library routines. This is because the VTP puts out EVIO-4 so that is what was captured. +~~~bash +module use /cvmfs/oasis.opensciencegrid.org/jlab/scicomp/sw/el9/modulefiles +module load root/6.30.06-gcc11.4.0 +g++ -g -std=c++17 -o evio2root SRO-RTDP/src/utilities/cpp/evio2root/evio2root.cc `root-config --cflags --libs` + +# Repeat this for each port +./evio2root CLAS12_ECAL_PCAL_DC_2024-05-16_09-07-18.pcap_split/port7001.evio + +root -l CLAS12_ECAL_PCAL_DC_2024-05-16_09-07-18.pcap_split/port7001.evio.root +root [1] dcrb->Draw("t") +~~~ + +
+ +## Build EVIO + +This is an attempt to use the official EVIO library v6.0.1 to read the *evio* file(s) produced by the above. + +First, checkout and build the EVIO library +~~~bash +git clone git@github.com:JeffersonLab/evio +cd evio +git checkout v6.0.1 +cd - + +cmake -S evio -B build.evio -DCMAKE_INSTALL_PREFIX=${PWD}/opt -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_CXX_STANDARD=20 +cmake --build build.evio --target install -j 16 +~~~ + +## Build the evioReadTest program + +~~~bash +g++ -g -std=c++2a evioReadTest.cc -o evioReadTest -Iopt/include -Lopt/lib64 -Lopt/lib -levio -leviocc -Wl,-rpath,${PWD}/opt/lib64 +~~~ + + +~~~bash +./evioReadTest CLAS12_ECAL_PCAL_DC_2024-05-16_09-07-18.pcap_split/port7001.evio +~~~ \ No newline at end of file From 17555d46f70156ce4732ad639baa6ef77d2aa103 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Fri, 13 Jun 2025 11:46:26 -0500 Subject: [PATCH 44/56] Revert debugging output code, no longer needed. Add more extensions to gitignores. --- .gitignore | 15 +- src/libsrc++/EvioReaderV4.cpp | 1126 +++++++++++++++++++-------------- 2 files changed, 664 insertions(+), 477 deletions(-) diff --git a/.gitignore b/.gitignore index f69be736e..ab91451fc 100644 --- a/.gitignore +++ b/.gitignore @@ -2,19 +2,22 @@ .* # ignore all files/dirs beginning with _ _* -# ignore any .evio, .ev, or .hipo extension files +# EventViewer Jar +JEventViewer*.jar + +# except these two +!.gitignore +!.github/ + +# ignore any .evio, .ev, or .hipo extension files (+ other common file types) *.evio* *.ev *.hipo *.dat *.txt -# EventViewer Jar -JEventViewer*.jar +*.out.* perf.data* -# except these two -!.gitignore -!.github/ # ignore generated files/dirs cmake-* diff --git a/src/libsrc++/EvioReaderV4.cpp b/src/libsrc++/EvioReaderV4.cpp index 6d6e32e18..34685c5f2 100644 --- a/src/libsrc++/EvioReaderV4.cpp +++ b/src/libsrc++/EvioReaderV4.cpp @@ -7,66 +7,70 @@ // 12000, Jefferson Ave, Newport News, VA 23606 // (757)-269-7100 - - #include "EvioReaderV4.h" -namespace evio { +namespace evio +{ /** * This method saves the current state of this EvioReader object. * @return the current state of this EvioReader object. */ - EvioReaderV4::ReaderState * EvioReaderV4::getState() { - auto * currentState = new ReaderState(); - currentState->lastBlock = lastBlock; + EvioReaderV4::ReaderState *EvioReaderV4::getState() + { + auto *currentState = new ReaderState(); + currentState->lastBlock = lastBlock; currentState->eventNumber = eventNumber; currentState->blockNumberExpected = blockNumberExpected; - if (sequentialRead) { + if (sequentialRead) + { currentState->filePosition = file.tellg(); } currentState->byteBufferLimit = byteBuffer->limit(); currentState->byteBufferPosition = byteBuffer->position(); - if (evioVersion > 3) { + if (evioVersion > 3) + { currentState->blockHeader4 = blockHeader4; } - else { + else + { currentState->blockHeader2 = blockHeader2; } return currentState; } - /** * This method restores a previously saved state of this EvioReader object. * @param state a previously stored state of this EvioReader object. */ - void EvioReaderV4::restoreState(ReaderState * state) { - lastBlock = state->lastBlock; + void EvioReaderV4::restoreState(ReaderState *state) + { + lastBlock = state->lastBlock; eventNumber = state->eventNumber; blockNumberExpected = state->blockNumberExpected; - if (sequentialRead) { + if (sequentialRead) + { file.seekg(state->filePosition); } byteBuffer->limit(state->byteBufferLimit); byteBuffer->position(state->byteBufferPosition); - if (evioVersion > 3) { + if (evioVersion > 3) + { blockHeader = blockHeader4 = state->blockHeader4; } - else { + else + { blockHeader = blockHeader2 = state->blockHeader2; } } - //------------------------ - /** * Constructor for reading an event file. * Do not set sequential to false for remote files. @@ -81,9 +85,11 @@ namespace evio { * @throws EvioException if file arg is null; if read failure; * if first block number != 1 when checkBlkNumSeq arg is true */ - EvioReaderV4::EvioReaderV4(std::string const & path, bool checkBlkNumSeq, bool synced) { + EvioReaderV4::EvioReaderV4(std::string const &path, bool checkBlkNumSeq, bool synced) + { - if (path.empty()) { + if (path.empty()) + { throw EvioException("path is empty"); } @@ -94,7 +100,8 @@ namespace evio { // Go back to beginning of file file.seekg(0); - if (fileBytes < 40) { + if (fileBytes < 40) + { throw EvioException("File too small to have valid evio data"); } @@ -105,7 +112,6 @@ namespace evio { blockHeader4 = std::make_shared(); blockHeader2 = std::make_shared(); - // Look at the first block header to get various info like endianness and version. // Store it for later reference in blockHeader2,4 and in other variables. @@ -116,7 +122,8 @@ namespace evio { // Read 32 bytes of file's first block header file.read(reinterpret_cast(headerBytes), bytesToRead); - if (file.fail()) { + if (file.fail()) + { throw EvioException("I/O error reading file"); } @@ -129,17 +136,21 @@ namespace evio { // Do not use memory mapping as the Java version did. // Since evio data files tend to be large (> 2GB), memory mapping // can be slower than conventional reads. - if (evioVersion < 4) { + if (evioVersion < 4) + { // Remember, no dictionaries exist for these early versions - prepareForSequentialRead(); + prepareForSequentialRead(); } // For version 4 ... - else { + else + { prepareForSequentialRead(); - if (blockHeader4->hasDictionary()) { + if (blockHeader4->hasDictionary()) + { // Dictionary is always the first event auto dict = parseNextEvent(); - if (dict != nullptr) { + if (dict != nullptr) + { auto strs = dict->getStringData(); dictionaryXML = strs[0]; } @@ -147,7 +158,6 @@ namespace evio { } } - /** * Constructor for reading a buffer. * @@ -160,7 +170,8 @@ namespace evio { * @throws EvioException if buffer arg is null; * if first block number != 1 when checkBlkNumSeq arg is true */ - EvioReaderV4::EvioReaderV4(std::shared_ptr bb, bool checkBlkNumSeq, bool synced) { + EvioReaderV4::EvioReaderV4(std::shared_ptr bb, bool checkBlkNumSeq, bool synced) + { checkBlockNumSeq = checkBlkNumSeq; synchronized = synced; @@ -177,27 +188,29 @@ namespace evio { // For the latest evio format, generate a table // of all event positions in buffer for random access. - if (evioVersion > 3) { -//std::cout << "EvioReaderV4 const: evioVersion = " << evioVersion << ", generate event positions" << std::endl; + if (evioVersion > 3) + { + // std::cout << "EvioReaderV4 const: evioVersion = " << evioVersion << ", generate event positions" << std::endl; generateEventPositions(byteBuffer); - if (blockHeader4->hasDictionary()) { + if (blockHeader4->hasDictionary()) + { // Jump to the first event prepareForBufferRead(byteBuffer); // Dictionary is the first event readDictionary(byteBuffer); } } - else { + else + { // Setting the byte order is only necessary if someone hands // this method a buffer in which the byte order is improperly set. byteBuffer->order(byteOrder); prepareForBufferRead(byteBuffer); } - parser = std::make_shared(); + parser = std::make_shared(); } - /** * Generate a table (vector) of positions of events in file/buffer. * This method does not affect the byteBuffer position, eventNumber, @@ -209,165 +222,182 @@ namespace evio { * contained in the given byte buffer. * @throws EvioException if bad file format */ - size_t EvioReaderV4::generateEventPositions(std::shared_ptr bb) { - - uint32_t blockSize, blockHdrSize, blockEventCount, magicNum; - uint32_t byteInfo, byteLen, bytesLeft, position; - bool firstBlock=true, hasDictionary=false; -// bool curLastBlock; + size_t EvioReaderV4::generateEventPositions(std::shared_ptr bb) + { + + uint32_t blockSize, blockHdrSize, blockEventCount, magicNum; + uint32_t byteInfo, byteLen, bytesLeft, position; + bool firstBlock = true, hasDictionary = false; + // bool curLastBlock; + + // In Java evio, setting eventCount from its initial value of -1 is done in MappeMemoryHandler.java, + // but in C++ that does not exist so we set it here. + if (eventCount < 0) + { + eventCount = 0; + } + + eventPositions.reserve(20000); + + // Start at the beginning of byteBuffer + position = 0; + bytesLeft = bb->limit(); + + while (bytesLeft > 0) + { + // Check to see if enough data to read block header. + // If not return the amount of memory we've used/read. + if (bytesLeft < 32) + { + // std::cout << " genEvTablePos: return, not enough to read header, bytes left = " << bytesLeft << std::endl; + return position; + } - // In Java evio, setting eventCount from its initial value of -1 is done in MappeMemoryHandler.java, - // but in C++ that does not exist so we set it here. - if (eventCount < 0) { - eventCount = 0; + // File is now positioned before block header. + // Look at block header to get info. Swapping is taken care of + byteInfo = bb->getUInt(position + 4 * BlockHeaderV4::EV_VERSION); + blockSize = bb->getUInt(position + 4 * BlockHeaderV4::EV_BLOCKSIZE); + blockHdrSize = bb->getUInt(position + 4 * BlockHeaderV4::EV_HEADERSIZE); + blockEventCount = bb->getUInt(position + 4 * BlockHeaderV4::EV_COUNT); + magicNum = bb->getUInt(position + 4 * BlockHeaderV4::EV_MAGIC); + + // std::cout << " genEvTablePos: pos " << position << + // ", blk ev count = " << blockEventCount << + // ", blockSize = " << blockSize << + // ", blockHdrSize = " << blockHdrSize << std::showbase << + // ", byteInfo = " << std::hex << byteInfo << + // ", magic # = " << magicNum << std::dec << std::endl; + + // If magic # is not right, file is not in proper format + if (magicNum != BlockHeaderV4::MAGIC_NUMBER) + { + throw EvioException("Bad evio format: block header magic # incorrect"); } - eventPositions.reserve(20000); + // Check lengths in block header + if (blockSize < 8 || blockHdrSize < 8) + { + throw EvioException("Bad evio format: (block: total len = " + std::to_string(blockSize) + + ", header len = " + std::to_string(blockHdrSize) + ")"); + } - // Start at the beginning of byteBuffer - position = 0; - bytesLeft = bb->limit(); + // Check to see if the whole block is within the mapped memory. + // If not return the amount of memory we've used/read. + if (4 * blockSize > bytesLeft) + { + // std::cout << " 4*blockSize = " << std::to_string(4*blockSize) + " >? bytesLeft = " << + // std::to_string(bytesLeft) + ", pos = " + std::to_string(position) << std::endl; + // std::cout << " return, not enough to read all block data" << std::endl; + return position; + } - while (bytesLeft > 0) { - // Check to see if enough data to read block header. - // If not return the amount of memory we've used/read. - if (bytesLeft < 32) { -//std::cout << " genEvTablePos: return, not enough to read header, bytes left = " << bytesLeft << std::endl; - return position; - } + blockCount++; + // curLastBlock = BlockHeaderV4.isLastBlock(byteInfo); + if (firstBlock) + { + hasDictionary = BlockHeaderV4::hasDictionary(byteInfo); + } - // File is now positioned before block header. - // Look at block header to get info. Swapping is taken care of - byteInfo = bb->getUInt(position + 4*BlockHeaderV4::EV_VERSION); - blockSize = bb->getUInt(position + 4*BlockHeaderV4::EV_BLOCKSIZE); - blockHdrSize = bb->getUInt(position + 4*BlockHeaderV4::EV_HEADERSIZE); - blockEventCount = bb->getUInt(position + 4*BlockHeaderV4::EV_COUNT); - magicNum = bb->getUInt(position + 4*BlockHeaderV4::EV_MAGIC); - -// std::cout << " genEvTablePos: pos " << position << -// ", blk ev count = " << blockEventCount << -// ", blockSize = " << blockSize << -// ", blockHdrSize = " << blockHdrSize << std::showbase << -// ", byteInfo = " << std::hex << byteInfo << -// ", magic # = " << magicNum << std::dec << std::endl; - - // If magic # is not right, file is not in proper format - if (magicNum != BlockHeaderV4::MAGIC_NUMBER) { - throw EvioException("Bad evio format: block header magic # incorrect"); + // std::cout << " genEvTablePos: blk count = " << blockCount << + // ", total ev count = " << (eventCount + blockEventCount) << + // "\n firstBlock = " << firstBlock << + // /* ", isLastBlock = " + curLastBlock + */ + // ", hasDict = " << hasDictionary << + // ", pos = " << position << std::endl; + + // Hop over block header to data + position += 4 * blockHdrSize; + bytesLeft -= 4 * blockHdrSize; + + // std::cout << " hopped blk hdr, bytesLeft = " << bytesLeft << ", pos = " << position << std::endl; + + // Check for a dictionary - the first event in the first block. + // It's not included in the header block count, but we must take + // it into account by skipping over it. + if (firstBlock && hasDictionary) + { + // Get its length - bank's len does not include itself + byteLen = 4 * (bb->getUInt(position) + 1); + + if (byteLen < 4) + { + throw EvioException("Bad evio format: bad bank length"); } - // Check lengths in block header - if (blockSize < 8 || blockHdrSize < 8) { - throw EvioException("Bad evio format: (block: total len = " + std::to_string(blockSize) + - ", header len = " + std::to_string(blockHdrSize) + ")" ); - } + // Skip over dictionary + position += byteLen; + bytesLeft -= byteLen; + // std::cout << " hopped dict, dic bytes = " << byteLen << ", bytesLeft = " << + // bytesLeft << ", pos = " << position << std::endl; + } - // Check to see if the whole block is within the mapped memory. - // If not return the amount of memory we've used/read. - if (4*blockSize > bytesLeft) { -//std::cout << " 4*blockSize = " << std::to_string(4*blockSize) + " >? bytesLeft = " << -// std::to_string(bytesLeft) + ", pos = " + std::to_string(position) << std::endl; -//std::cout << " return, not enough to read all block data" << std::endl; - return position; - } + firstBlock = false; - blockCount++; -// curLastBlock = BlockHeaderV4.isLastBlock(byteInfo); - if (firstBlock) { - hasDictionary = BlockHeaderV4::hasDictionary(byteInfo); + // For each event in block, store its location + for (uint32_t i = 0; i < blockEventCount; i++) + { + // Sanity check - must have at least 1 header's amount left + if (bytesLeft < 8) + { + throw EvioException("Bad evio format: not enough data to read event (bad bank len?)"); } -//std::cout << " genEvTablePos: blk count = " << blockCount << -// ", total ev count = " << (eventCount + blockEventCount) << -// "\n firstBlock = " << firstBlock << -// /* ", isLastBlock = " + curLastBlock + */ -// ", hasDict = " << hasDictionary << -// ", pos = " << position << std::endl; - - // Hop over block header to data - position += 4*blockHdrSize; - bytesLeft -= 4*blockHdrSize; - -//std::cout << " hopped blk hdr, bytesLeft = " << bytesLeft << ", pos = " << position << std::endl; - - // Check for a dictionary - the first event in the first block. - // It's not included in the header block count, but we must take - // it into account by skipping over it. - if (firstBlock && hasDictionary) { - // Get its length - bank's len does not include itself - byteLen = 4*(bb->getUInt(position) + 1); - - if (byteLen < 4) { - throw EvioException("Bad evio format: bad bank length"); - } - - // Skip over dictionary - position += byteLen; - bytesLeft -= byteLen; -//std::cout << " hopped dict, dic bytes = " << byteLen << ", bytesLeft = " << -// bytesLeft << ", pos = " << position << std::endl; + // Get length of current event (including full header) + byteLen = 4 * (bb->getInt(position) + 1); + if (byteLen < 4 || bytesLeft < byteLen) + { + throw EvioException("Bad evio format: bad bank length"); } + bytesLeft -= byteLen; - firstBlock = false; - - // For each event in block, store its location - for (uint32_t i=0; i < blockEventCount; i++) { - // Sanity check - must have at least 1 header's amount left - if (bytesLeft < 8) { - throw EvioException("Bad evio format: not enough data to read event (bad bank len?)"); - } - - // Get length of current event (including full header) - byteLen = 4*(bb->getInt(position) + 1); - if (byteLen < 4 || bytesLeft < byteLen) { - throw EvioException("Bad evio format: bad bank length"); - } - bytesLeft -= byteLen; + // Store current position + eventPositions.push_back(position); + eventCount++; - // Store current position - eventPositions.push_back(position); - eventCount++; - - position += byteLen; -//std::cout << " hopped event " << (i+1) << ", bytesLeft = " << bytesLeft << ", pos = " << position << std::endl; - } + position += byteLen; + // std::cout << " hopped event " << (i+1) << ", bytesLeft = " << bytesLeft << ", pos = " << position << std::endl; } + } - return position; + return position; } - /** {@inheritDoc} */ - void EvioReaderV4::setBuffer(std::shared_ptr buf) { + void EvioReaderV4::setBuffer(std::shared_ptr buf) + { close(); - if (buf == nullptr) { + if (buf == nullptr) + { throw EvioException("null buf arg"); } - lastBlock = false; - eventNumber = 0; - blockCount = 0; - eventCount = -1; - blockNumberExpected = 1; - dictionaryXML = ""; - initialPosition = buf->position(); - sequentialRead = false; + lastBlock = false; + eventNumber = 0; + blockCount = 0; + eventCount = -1; + blockNumberExpected = 1; + dictionaryXML = ""; + initialPosition = buf->position(); + sequentialRead = false; byteBuffer = buf->slice(); parseFirstHeader(byteBuffer); byteBuffer->position(0); - if (evioVersion > 3) { + if (evioVersion > 3) + { generateEventPositions(byteBuffer); - if (blockHeader4->hasDictionary()) { + if (blockHeader4->hasDictionary()) + { // Jump to the first event prepareForBufferRead(byteBuffer); // Dictionary is the first event readDictionary(byteBuffer); } } - else { + else + { byteBuffer->order(byteOrder); prepareForBufferRead(byteBuffer); } @@ -375,64 +405,55 @@ namespace evio { closed = false; } - /** {@inheritDoc} */ - bool EvioReaderV4::isClosed() {return closed;} - + bool EvioReaderV4::isClosed() { return closed; } /** {@inheritDoc} */ - bool EvioReaderV4::checkBlockNumberSequence() {return checkBlockNumSeq;} - + bool EvioReaderV4::checkBlockNumberSequence() { return checkBlockNumSeq; } /** {@inheritDoc} */ - ByteOrder & EvioReaderV4::getByteOrder() {return byteOrder;} - + ByteOrder &EvioReaderV4::getByteOrder() { return byteOrder; } /** {@inheritDoc} */ - uint32_t EvioReaderV4::getEvioVersion() {return evioVersion;} - + uint32_t EvioReaderV4::getEvioVersion() { return evioVersion; } /** {@inheritDoc} */ - std::string EvioReaderV4::getPath() {return path;} - + std::string EvioReaderV4::getPath() { return path; } /** {@inheritDoc} */ - std::shared_ptr EvioReaderV4::getParser() {return parser;} - + std::shared_ptr EvioReaderV4::getParser() { return parser; } /** {@inheritDoc} */ - void EvioReaderV4::setParser(std::shared_ptr evParser) {parser = evParser;} - + void EvioReaderV4::setParser(std::shared_ptr evParser) { parser = evParser; } /** {@inheritDoc} */ - std::string EvioReaderV4::getDictionaryXML() {return dictionaryXML;} - + std::string EvioReaderV4::getDictionaryXML() { return dictionaryXML; } /** {@inheritDoc} */ - bool EvioReaderV4::hasDictionaryXML() {return !dictionaryXML.empty();} - + bool EvioReaderV4::hasDictionaryXML() { return !dictionaryXML.empty(); } /** {@inheritDoc} */ - std::shared_ptr EvioReaderV4::getFirstEvent() { - if (hasFirstEvent()) { + std::shared_ptr EvioReaderV4::getFirstEvent() + { + if (hasFirstEvent()) + { return getEvent(1); } return nullptr; } - /** {@inheritDoc} */ - bool EvioReaderV4::hasFirstEvent() { - if (evioVersion < 4) { + bool EvioReaderV4::hasFirstEvent() + { + if (evioVersion < 4) + { firstBlockHeader2->hasFirstEvent(); } return firstBlockHeader4->hasFirstEvent(); } - /** {@inheritDoc} */ - size_t EvioReaderV4::getNumEventsRemaining() {return getEventCount() - eventNumber;} - + size_t EvioReaderV4::getNumEventsRemaining() { return getEventCount() - eventNumber; } /** * {@inheritDoc}. @@ -440,16 +461,13 @@ namespace evio { * returns the internal buffer containing an evio block if using sequential access * (for example files > 2.1 GB). It returns the memory mapped buffer otherwise. */ - std::shared_ptr EvioReaderV4::getByteBuffer() {return byteBuffer;} - + std::shared_ptr EvioReaderV4::getByteBuffer() { return byteBuffer; } /** {@inheritDoc} */ - size_t EvioReaderV4::fileSize() {return fileBytes;} - + size_t EvioReaderV4::fileSize() { return fileBytes; } /** {@inheritDoc} */ - std::shared_ptr EvioReaderV4::getFirstBlockHeader() {return firstBlockHeader;} - + std::shared_ptr EvioReaderV4::getFirstBlockHeader() { return firstBlockHeader; } /** * Reads 8 words of the first block (physical record) header in order to determine @@ -461,11 +479,13 @@ namespace evio { * @throws EvioException if buffer too small, contains invalid data, * or bad block # sequence */ - void EvioReaderV4::parseFirstHeader(std::shared_ptr headerBuf) { + void EvioReaderV4::parseFirstHeader(std::shared_ptr headerBuf) + { // Check buffer length headerBuf->position(0); - if (headerBuf->remaining() < 32) { + if (headerBuf->remaining() < 32) + { throw EvioException("buffer too small"); } @@ -474,7 +494,8 @@ namespace evio { uint32_t magicNumber = headerBuf->getUInt(MAGIC_OFFSET); - if (magicNumber != IBlockHeader::MAGIC_NUMBER) { + if (magicNumber != IBlockHeader::MAGIC_NUMBER) + { swap = true; byteOrder = byteOrder.getOppositeEndian(); @@ -482,50 +503,60 @@ namespace evio { // Reread magic number to make sure things are OK magicNumber = headerBuf->getInt(MAGIC_OFFSET); - if (magicNumber != IBlockHeader::MAGIC_NUMBER) { - std::cout << "ERROR reread magic # (" << std::to_string(magicNumber) << - ") & still not right" << std::endl; + if (magicNumber != IBlockHeader::MAGIC_NUMBER) + { + std::cout << "ERROR reread magic # (" << std::to_string(magicNumber) << ") & still not right" << std::endl; throw EvioException("bad magic #"); } } // Check the version number. This requires peeking ahead 5 ints or 20 bytes. evioVersion = headerBuf->getInt(VERSION_OFFSET) & VERSION_MASK; - if (evioVersion < 1) { + if (evioVersion < 1) + { throw EvioException("bad version"); } -// std::cout << "Evio version# = " << evioVersion << std::endl; + // std::cout << "Evio version# = " << evioVersion << std::endl; - if (evioVersion >= 4) { + if (evioVersion >= 4) + { blockHeader4->setBufferStartingPosition(0); -// int pos = 0; -// std::cout << "BlockHeader v4:" << std::endl << hex << showbase; -// std::cout << " block length = " << headerBuf->getInt(pos) << std::endl; pos+=4; -// std::cout << " block number = " << headerBuf->getInt(pos) << std::endl; pos+=4; -// std::cout << " header length = " << headerBuf->getInt(pos) << std::endl; pos+=4; -// std::cout << " event count = " << headerBuf->getInt(pos) << std::endl; pos+=8; -// std::cout << " version = " << headerBuf->getInt(pos) << std::endl; pos+=8; -// std::cout << " magic number = " << headerBuf->getInt(pos) << std::endl; pos+=4; -// std::cout << std::endl << dec; + int pos = 0; + std::cout << "BlockHeader v4:" << std::endl << std::hex << std::showbase; + std::cout << " block length = " << headerBuf->getInt(pos) << std::endl; pos+=4; + std::cout << " block number = " << headerBuf->getInt(pos) << std::endl; pos+=4; + std::cout << " header length = " << headerBuf->getInt(pos) << std::endl; pos+=4; + std::cout << " reserved1 = " << headerBuf->getInt(pos) << std::endl; pos+=4; + std::cout << " event count = " << headerBuf->getInt(pos) << std::endl; pos+=4; + std::cout << " bitinfo/version = " << headerBuf->getInt(pos) << std::endl; pos+=4; + std::cout << " reserved2 = " << headerBuf->getInt(pos) << std::endl; pos+=4; + std::cout << " magic number = " << headerBuf->getInt(pos) << std::endl; pos+=4; + std::cout << std::endl << std::dec; + + // DEBUG: print out the buffer information + std::cout << "EvioReaderV4: buffer pos = " << headerBuf->position() << + ", limit = " << headerBuf->limit() << + ", remaining = " << headerBuf->remaining() << + ", capacity = " << headerBuf->capacity() << std::endl; + // Read the header data - // Here's the offending setSize() - // std::cerr << "1) EvioReaderV4: doing setSize()" << std::endl; - // std::cerr << "Size: " << headerBuf->getInt() << std::endl; - blockHeader4->setSize( headerBuf->getInt()); - blockHeader4->setNumber( headerBuf->getInt()); - blockHeader4->setHeaderLength(headerBuf->getInt()); - blockHeader4->setEventCount( headerBuf->getInt()); - blockHeader4->setReserved1( headerBuf->getInt()); + // Opposite the offending setSize() + std::cout << "1) EvioReaderV4: doing setSize()" << std::endl; + blockHeader4->setSize(headerBuf->getInt(0)); // Word 1 + blockHeader4->setNumber(headerBuf->getInt(4)); // Word 2, 4 bytes = 32 bits offset + blockHeader4->setHeaderLength(headerBuf->getInt(8)); // Word 3 + blockHeader4->setEventCount(headerBuf->getInt(12)); // Word 4 + blockHeader4->setReserved1(headerBuf->getInt(16)); // Word 5 // Use 6th word to set bit info & version - blockHeader4->parseToBitInfo(headerBuf->getInt()); + blockHeader4->parseToBitInfo(headerBuf->getInt(20)); blockHeader4->setVersion(evioVersion); lastBlock = blockHeader4->getBitInfo(1); - blockHeader4->setReserved2(headerBuf->getInt()); - blockHeader4->setMagicNumber(headerBuf->getInt()); - blockHeader4->setByteOrder(byteOrder); + blockHeader4->setReserved2(headerBuf->getInt(24)); // Word 7 + blockHeader4->setMagicNumber(headerBuf->getInt(28)); // Word 8 + blockHeader4->setByteOrder(byteOrder); blockHeader = blockHeader4; // Copy it @@ -534,36 +565,37 @@ namespace evio { // Deal with non-standard header lengths here int64_t headerLenDiff = blockHeader4->getHeaderLength() - BlockHeaderV4::HEADER_SIZE; // If too small quit with error since headers have a minimum size - if (headerLenDiff < 0) { + if (headerLenDiff < 0) + { throw EvioException("header size too small"); } -//std::cout << "BlockHeader v4:" << std::endl; -//std::cout << " block length = " << blockHeader4.getSize() << " ints" << std::endl; -//std::cout << " block number = " << blockHeader4.getNumber() << std::endl; -//std::cout << " header length = " << blockHeader4.getHeaderLength() + " ints" << std::endl; -//std::cout << " event count = " << blockHeader4.getEventCount() << std::endl; -//std::cout << " version = " << blockHeader4.getVersion() << std::endl; -//std::cout << " has Dict = " << blockHeader4.getBitInfo(0) << std::endl; -//std::cout << " is End = " << lastBlock << std::endl << hex; -//std::cout << " magic number = " << blockHeader4.getMagicNumber() << std::endl << dec; - - } - else { + // std::cout << "BlockHeader v4:" << std::endl; + // std::cout << " block length = " << blockHeader4.getSize() << " ints" << std::endl; + // std::cout << " block number = " << blockHeader4.getNumber() << std::endl; + // std::cout << " header length = " << blockHeader4.getHeaderLength() + " ints" << std::endl; + // std::cout << " event count = " << blockHeader4.getEventCount() << std::endl; + // std::cout << " version = " << blockHeader4.getVersion() << std::endl; + // std::cout << " has Dict = " << blockHeader4.getBitInfo(0) << std::endl; + // std::cout << " is End = " << lastBlock << std::endl << hex; + // std::cout << " magic number = " << blockHeader4.getMagicNumber() << std::endl << dec; + } + else + { // Cache the starting position blockHeader2->setBufferStartingPosition(0); // read the header data. - blockHeader2->setSize( headerBuf->getInt()); - blockHeader2->setNumber( headerBuf->getInt()); + blockHeader2->setSize(headerBuf->getInt()); + blockHeader2->setNumber(headerBuf->getInt()); blockHeader2->setHeaderLength(headerBuf->getInt()); - blockHeader2->setStart( headerBuf->getInt()); - blockHeader2->setEnd( headerBuf->getInt()); + blockHeader2->setStart(headerBuf->getInt()); + blockHeader2->setEnd(headerBuf->getInt()); // skip version headerBuf->getInt(); blockHeader2->setVersion(evioVersion); - blockHeader2->setReserved1( headerBuf->getInt()); - blockHeader2->setMagicNumber( headerBuf->getInt()); + blockHeader2->setReserved1(headerBuf->getInt()); + blockHeader2->setMagicNumber(headerBuf->getInt()); blockHeader2->setByteOrder(byteOrder); blockHeader = blockHeader2; @@ -571,13 +603,14 @@ namespace evio { } // Store this for later regurgitation of blockCount - firstBlockSize = 4*blockHeader->getSize(); + firstBlockSize = 4 * blockHeader->getSize(); // check block number if so configured - if (checkBlockNumSeq) { - if (blockHeader->getNumber() != blockNumberExpected) { - std::cout << "block # out of sequence, got " << blockHeader->getNumber() << - " expecting " << blockNumberExpected << std::endl; + if (checkBlockNumSeq) + { + if (blockHeader->getNumber() != blockNumberExpected) + { + std::cout << "block # out of sequence, got " << blockHeader->getNumber() << " expecting " << blockNumberExpected << std::endl; throw EvioException("bad block # sequence"); } @@ -585,35 +618,35 @@ namespace evio { } } - /** * Reads the first block header into a buffer and gets that * buffer ready for first-time read. * * @throws EvioException if file access problems */ - void EvioReaderV4::prepareForSequentialRead() { + void EvioReaderV4::prepareForSequentialRead() + { size_t bytesToRead; // Evio format version 4 or greater has a large enough default block size // so that reading a single block at a time is not inefficient. - if (evioVersion > 3) { - bytesToRead = 4*firstBlockHeader->getSize(); + if (evioVersion > 3) + { + bytesToRead = 4 * firstBlockHeader->getSize(); } // Reading data by 32768 byte blocks in older versions is inefficient, // so read in 500 block (16MB) chunks. - else { + else + { size_t bytesLeftInFile = fileBytes - file.tellg(); - bytesToRead = DEFAULT_READ_BYTES < bytesLeftInFile ? - DEFAULT_READ_BYTES : bytesLeftInFile; + bytesToRead = DEFAULT_READ_BYTES < bytesLeftInFile ? DEFAULT_READ_BYTES : bytesLeftInFile; } - -//std::cout << "prepareForSequentialRead: bytesToRead = " << bytesToRead << std::endl; - + // std::cout << "prepareForSequentialRead: bytesToRead = " << bytesToRead << std::endl; // Create/expand a buffer to hold a chunk of data - if ((byteBuffer == nullptr) || (byteBuffer->capacity() < bytesToRead)) { + if ((byteBuffer == nullptr) || (byteBuffer->capacity() < bytesToRead)) + { byteBuffer = std::make_shared(bytesToRead); byteBuffer->order(byteOrder); } @@ -621,7 +654,8 @@ namespace evio { // Read the first chunk of data from file file.read((char *)(byteBuffer->array() + byteBuffer->arrayOffset()), bytesToRead); - if (file.fail()) { + if (file.fail()) + { throw EvioException("file read failure"); } @@ -631,25 +665,28 @@ namespace evio { prepareForBufferRead(byteBuffer); } - /** * Sets the proper buffer position for first-time read AFTER the first header. * @param buffer buffer to prepare */ - void EvioReaderV4::prepareForBufferRead(std::shared_ptr buffer) const { + void EvioReaderV4::prepareForBufferRead(std::shared_ptr buffer) const + { // Position after header size_t pos = 32; buffer->position(pos); // Deal with non-standard first header length. // No non-standard header lengths in evio version 2 & 3 files. - if (evioVersion < 4) return; + if (evioVersion < 4) + return; int64_t headerLenDiff = blockHeader4->getHeaderLength() - BlockHeaderV4::HEADER_SIZE; // Hop over any extra header words - if (headerLenDiff > 0) { - for (int i=0; i < headerLenDiff; i++) { - //std::cout << "Skip extra header int"); + if (headerLenDiff > 0) + { + for (int i = 0; i < headerLenDiff; i++) + { + // std::cout << "Skip extra header int"); pos += 4; buffer->position(pos); } @@ -659,7 +696,6 @@ namespace evio { // If there's a dictionary present, skip over it now. } - /** * Reads the block (physical record) header. * Assumes mapped buffer or file is positioned at start of the next block header. @@ -684,37 +720,44 @@ namespace evio { * @return status of read attempt * @throws EvioException if file access problems, evio format problems */ - IEvioReader::ReadWriteStatus EvioReaderV4::processNextBlock() { + IEvioReader::ReadWriteStatus EvioReaderV4::processNextBlock() + { // We already read the last block header - if (lastBlock) { + if (lastBlock) + { return IEvioReader::ReadWriteStatus::END_OF_FILE; } - try { - if (sequentialRead) { - if (evioVersion < 4) { + try + { + if (sequentialRead) + { + if (evioVersion < 4) + { size_t bytesInBuf = bufferBytesRemaining(); - if (bytesInBuf == 0) { + if (bytesInBuf == 0) + { // How much of the file is left to read? size_t bytesLeftInFile = fileBytes - file.tellg(); - if (bytesLeftInFile < 32L) { + if (bytesLeftInFile < 32L) + { return IEvioReader::ReadWriteStatus::END_OF_FILE; } // The block size is 32kB which is on the small side. // We want to read in 16MB (DEFAULT_READ_BYTES) or so // at once for efficiency. - size_t bytesToRead = DEFAULT_READ_BYTES < bytesLeftInFile ? - DEFAULT_READ_BYTES : bytesLeftInFile; + size_t bytesToRead = DEFAULT_READ_BYTES < bytesLeftInFile ? DEFAULT_READ_BYTES : bytesLeftInFile; // Reset buffer byteBuffer->position(0).limit(bytesToRead); // Read the entire chunk of data file.read((char *)(byteBuffer->array() + byteBuffer->arrayOffset()), bytesToRead); - if (file.fail()) { + if (file.fail()) + { throw EvioException("file read failure"); } byteBuffer->limit(bytesToRead); @@ -722,46 +765,69 @@ namespace evio { // Now keeping track of pos in this new blockBuffer blockHeader->setBufferStartingPosition(0); } - else if (bytesInBuf % 32768 == 0) { + else if (bytesInBuf % 32768 == 0) + { // Next block header starts at this position in buffer blockHeader->setBufferStartingPosition(byteBuffer->position()); } - else { + else + { throw EvioException("file contains non-integral # of 32768 byte blocks"); } } - else { + else + { // Enough data left to read len? - if (fileBytes - file.tellg() < 4L) { + if (fileBytes - file.tellg() < 4L) + { return IEvioReader::ReadWriteStatus::END_OF_FILE; } // Read len of block in 32 bit words uint32_t blkSize; - file.read(reinterpret_cast(&blkSize), sizeof(blkSize)); - if (file.fail()) { + file.read(reinterpret_cast(&blkSize), sizeof(blkSize)); + if (file.fail()) + { throw EvioException("file read failure"); } - if (swap) blkSize = SWAP_32(blkSize); + if (swap) + blkSize = SWAP_32(blkSize); + + std::cout << "EvioReaderV4: sizeof(blkSize) = " << sizeof(blkSize) << std::endl; // Change to bytes uint32_t blkBytes = 4 * blkSize; // Enough data left to read rest of block? - if (fileBytes - file.tellg() < blkBytes-4) { + if (fileBytes - file.tellg() < blkBytes - 4) + { return IEvioReader::ReadWriteStatus::END_OF_FILE; } + std::cerr << "Reading byteBuffer from file... " << std::endl; + // DEBUG: print out the buffer information + std::cout << "EvioReaderV4 BEFORE: buffer pos = " << byteBuffer->position() << + ", fileBytes = " << fileBytes << + ", blkSize = " << blkSize << + ", blkBytes = " << blkBytes << + ", limit = " << byteBuffer->limit() << + ", remaining = " << byteBuffer->remaining() << + ", capacity = " << byteBuffer->capacity() << std::endl; + // Create a buffer to hold the entire first block of data - if (byteBuffer->capacity() >= blkBytes) { + if (byteBuffer->capacity() >= blkBytes) + { byteBuffer->clear(); byteBuffer->limit(blkBytes); + std::cerr << "1Reading byteBuffer from file... " << std::endl; } - else { + else + { // Make this bigger than necessary so we're not constantly reallocating byteBuffer = std::make_shared(blkBytes + 10000); byteBuffer->limit(blkBytes); byteBuffer->order(byteOrder); + std::cerr << "2Reading byteBuffer from file... " << std::endl; } // Read the entire block of data. @@ -769,8 +835,9 @@ namespace evio { byteBuffer->putInt(0, blkSize); // Now the rest of the block (already put int, 4 bytes, in) - file.read((char *)(byteBuffer->array() + byteBuffer->arrayOffset() + 4), blkBytes-4); - if (file.fail()) { + file.read((char *)(byteBuffer->array() + byteBuffer->arrayOffset() + 4), blkBytes - 4); + if (file.fail()) + { throw EvioException("file read failure"); } @@ -778,8 +845,10 @@ namespace evio { blockHeader->setBufferStartingPosition(0); } } - else { - if (byteBuffer->remaining() < 32) { + else + { + if (byteBuffer->remaining() < 32) + { byteBuffer->clear(); return IEvioReader::ReadWriteStatus::END_OF_FILE; } @@ -793,13 +862,23 @@ namespace evio { ", remaining = " << byteBuffer->remaining() << ", capacity = " << byteBuffer->capacity() << std::endl; - - if (evioVersion >= 4) { + if (evioVersion >= 4) + { // Read the header data. + int pos = 0; + std::cout << "BlockHeader v4:" << std::endl << std::hex << std::showbase; + std::cout << " block length = " << byteBuffer->getInt(pos) << std::endl; pos+=4; + std::cout << " block number = " << byteBuffer->getInt(pos) << std::endl; pos+=4; + std::cout << " header length = " << byteBuffer->getInt(pos) << std::endl; pos+=4; + std::cout << " reserved1 = " << byteBuffer->getInt(pos) << std::endl; pos+=4; + std::cout << " event count = " << byteBuffer->getInt(pos) << std::endl; pos+=4; + std::cout << " bitinfo/version = " << byteBuffer->getInt(pos) << std::endl; pos+=4; + std::cout << " reserved2 = " << byteBuffer->getInt(pos) << std::endl; pos+=4; + std::cout << " magic number = " << byteBuffer->getInt(pos) << std::endl; pos+=4; + std::cout << std::endl << std::dec; + // Here's the offending setSize() - std::cerr << "2) EvioReaderV4: doing setSize()" << std::endl; - std::cerr << "Size: " << byteBuffer->getInt() << std::endl; blockHeader4->setSize(byteBuffer->getInt()); blockHeader4->setNumber(byteBuffer->getInt()); blockHeader4->setHeaderLength(byteBuffer->getInt()); @@ -811,22 +890,48 @@ namespace evio { lastBlock = blockHeader4->getBitInfo(1); blockHeader4->setReserved2(byteBuffer->getInt()); blockHeader4->setMagicNumber(byteBuffer->getInt()); + blockHeader4->setByteOrder(byteOrder); blockHeader = blockHeader4; + // // Read the header data + // // Copied from above the offending setSize() + // std::cout << "1) EvioReaderV4: doing setSize()" << std::endl; + // blockHeader4->setSize(headerBuf->getInt(0)); // Word 1 + // blockHeader4->setNumber(headerBuf->getInt(4)); // Word 2, 4 bytes = 32 bits offset + // blockHeader4->setHeaderLength(headerBuf->getInt(8)); // Word 3 + // blockHeader4->setEventCount(headerBuf->getInt(12)); // Word 4 + // blockHeader4->setReserved1(headerBuf->getInt(16)); // Word 5 + + // // Use 6th word to set bit info & version + // blockHeader4->parseToBitInfo(headerBuf->getInt(20)); + // blockHeader4->setVersion(evioVersion); + // lastBlock = blockHeader4->getBitInfo(1); + // blockHeader4->setReserved2(headerBuf->getInt(24)); // Word 7 + // blockHeader4->setMagicNumber(headerBuf->getInt(28)); // Word 8 + // blockHeader4->setByteOrder(byteOrder); + // blockHeader = blockHeader4; + + // DEBUG: print out the buffer information + std::cout << "blockHeader4 header length: " << blockHeader4->getHeaderLength() << std::endl; + // Deal with non-standard header lengths here int64_t headerLenDiff = blockHeader4->getHeaderLength() - BlockHeaderV4::HEADER_SIZE; // If too small quit with error since headers have a minimum size - if (headerLenDiff < 0) { + if (headerLenDiff < 0) + { return IEvioReader::ReadWriteStatus::EVIO_EXCEPTION; } - // If bigger, read extra ints - else if (headerLenDiff > 0) { - for (int i=0; i < headerLenDiff; i++) { + // If bigger, read extra ints + else if (headerLenDiff > 0) + { + for (int i = 0; i < headerLenDiff; i++) + { byteBuffer->getInt(); } } } - else if (evioVersion < 4) { + else if (evioVersion < 4) + { // read the header data blockHeader2->setSize(byteBuffer->getInt()); blockHeader2->setNumber(byteBuffer->getInt()); @@ -840,36 +945,39 @@ namespace evio { blockHeader2->setMagicNumber(byteBuffer->getInt()); blockHeader = blockHeader2; } - else { + else + { // bad version # - should never happen return IEvioReader::ReadWriteStatus::EVIO_EXCEPTION; } // check block number if so configured - if (checkBlockNumSeq) { - if (blockHeader->getNumber() != blockNumberExpected) { + if (checkBlockNumSeq) + { + if (blockHeader->getNumber() != blockNumberExpected) + { - std::cout << "block # out of sequence, got " << std::to_string(blockHeader->getNumber()) + - " expecting " << std::to_string(blockNumberExpected) << std::endl; + std::cout << "block # out of sequence, got " << std::to_string(blockHeader->getNumber()) + " expecting " << std::to_string(blockNumberExpected) << std::endl; return IEvioReader::ReadWriteStatus::EVIO_EXCEPTION; } blockNumberExpected++; } } - catch (EvioException & e) { + catch (EvioException &e) + { + std::cout << "ERROR in processNextBlock: " << e.what() << std::endl; return IEvioReader::ReadWriteStatus::EVIO_EXCEPTION; } -// catch (BufferUnderflowException & a) { -// std::cout << "ERROR endOfBuffer " << a << std::endl; -// byteBuffer->clear(); -// return IEvioReader::ReadWriteStatus::UNKNOWN_ERROR; -// } + // catch (BufferUnderflowException & a) { + // std::cout << "ERROR endOfBuffer " << a << std::endl; + // byteBuffer->clear(); + // return IEvioReader::ReadWriteStatus::UNKNOWN_ERROR; + // } return IEvioReader::ReadWriteStatus::SUCCESS; } - /** * This method is only called once at the very beginning if buffer is known to have * a dictionary. It then reads that dictionary. Only called in format versions 4 & up. @@ -881,15 +989,18 @@ namespace evio { * @throws EvioException if failed read due to bad buffer format; * if version 3 or earlier */ - void EvioReaderV4::readDictionary(std::shared_ptr buffer) { + void EvioReaderV4::readDictionary(std::shared_ptr buffer) + { - if (evioVersion < 4) { + if (evioVersion < 4) + { throw EvioException("Unsupported version (" + std::to_string(evioVersion) + ")"); } // How many bytes remain in this buffer? size_t bytesRemaining = buffer->remaining(); - if (bytesRemaining < 12) { + if (bytesRemaining < 12) + { throw std::underflow_error("Not enough data in buffer"); } @@ -902,8 +1013,9 @@ namespace evio { bytesRemaining -= 4; // get the raw data - uint32_t eventDataSizeBytes = 4*(length - 1); - if (bytesRemaining < eventDataSizeBytes) { + uint32_t eventDataSizeBytes = 4 * (length - 1); + if (bytesRemaining < eventDataSizeBytes) + { throw EvioException("Not enough data in buffer"); } @@ -914,16 +1026,18 @@ namespace evio { // This is the very first event and must be a dictionary BaseStructure::unpackRawBytesToStrings(bytes, eventDataSizeBytes, strs); - if (strs.empty()) { + if (strs.empty()) + { throw EvioException("Data in bad format"); } dictionaryXML = strs[0]; } - /** {@inheritDoc} */ - std::shared_ptr EvioReaderV4::getEvent(size_t index) { - if (sequentialRead || evioVersion < 4) { + std::shared_ptr EvioReaderV4::getEvent(size_t index) + { + if (sequentialRead || evioVersion < 4) + { // Do not fully parse events up to index_TH event return gotoEventNumber(index, false); } @@ -932,7 +1046,6 @@ namespace evio { return getEventV4(index); } - /** * Get the event in the file/buffer at a given index (starting at 1). * It is only valid for evio versions 4+. @@ -946,17 +1059,21 @@ namespace evio { * @throws EvioException if failed read due to bad file/buffer format; * if object closed */ - std::shared_ptr EvioReaderV4::getEventV4(size_t index) { + std::shared_ptr EvioReaderV4::getEventV4(size_t index) + { // Lock this method - if (synchronized) { + if (synchronized) + { const std::lock_guard lock(mtx); } - if (index > getEventCount()) { + if (index > getEventCount()) + { return nullptr; } - if (closed) { + if (closed) + { throw EvioException("object closed"); } @@ -978,7 +1095,7 @@ namespace evio { // However, it that MAY also be the legacy tagsegment type // with no padding information. Ignore this as having tag & num // in legacy code is probably rare. - //if (dt == 0x40) { + // if (dt == 0x40) { // type = DataType.TAGSEGMENT.getValue(); // padding = 0; //} @@ -987,7 +1104,7 @@ namespace evio { header->setNumber(word & 0xff); // Read the raw data - eventDataSizeBytes = 4*(length - 1); + eventDataSizeBytes = 4 * (length - 1); event->setRawBytes((uint8_t *)(byteBuffer->array() + byteBuffer->arrayOffset() + byteBuffer->position()), (size_t)eventDataSizeBytes); byteBuffer->position(byteBuffer->position() + eventDataSizeBytes); @@ -998,33 +1115,38 @@ namespace evio { return event; } - /** {@inheritDoc} */ - std::shared_ptr EvioReaderV4::parseEvent(size_t index) { + std::shared_ptr EvioReaderV4::parseEvent(size_t index) + { // Lock this method - if (synchronized) { + if (synchronized) + { const std::lock_guard lock(mtx); } auto event = getEvent(index); - if (event != nullptr) parseEvent(event); + if (event != nullptr) + parseEvent(event); return event; } - /** {@inheritDoc} */ - std::shared_ptr EvioReaderV4::nextEvent() { + std::shared_ptr EvioReaderV4::nextEvent() + { // Lock this method - if (synchronized) { + if (synchronized) + { const std::lock_guard lock(mtx); } - if (!sequentialRead && evioVersion > 3) { - return getEvent(eventNumber+1); + if (!sequentialRead && evioVersion > 3) + { + return getEvent(eventNumber + 1); } - if (closed) { + if (closed) + { throw EvioException("object closed"); } @@ -1042,23 +1164,29 @@ namespace evio { // We now read in bigger chunks that are integral multiples of a single block // (32768 bytes). Must see if we have to deal with an event crossing physical // record boundaries. Previously, java evio only read 1 block at a time. - if (blkBytesRemaining == 0) { + if (blkBytesRemaining == 0) + { IEvioReader::ReadWriteStatus status = processNextBlock(); - if (status == IEvioReader::ReadWriteStatus::SUCCESS) { + if (status == IEvioReader::ReadWriteStatus::SUCCESS) + { return nextEvent(); } - else if (status == IEvioReader::ReadWriteStatus::END_OF_FILE) { + else if (status == IEvioReader::ReadWriteStatus::END_OF_FILE) + { return nullptr; } - else { - throw EvioException("Failed reading block header in nextEvent."); + else + { + throw EvioException("Failed reading block header in nextEvent (status=" + + std::to_string(static_cast(status)) + ")"); } } // Or have we already read in the last event? // If jevio versions 1-3, the last block may not be full. // Thus bytesRemaining may be > 0, but we may have read // in all the existing data. (This should never happen in version 4). - else if (blockHeader->getBufferEndingPosition() == currentPosition) { + else if (blockHeader->getBufferEndingPosition() == currentPosition) + { return nullptr; } @@ -1074,13 +1202,17 @@ namespace evio { // Versions 1-3: if we were unlucky, after reading the length // there are no bytes remaining in this block. // Don't really need the "if (version < 4)" here except for clarity. - if (evioVersion < 4) { - if (bufferBytesRemaining() == 0) { + if (evioVersion < 4) + { + if (bufferBytesRemaining() == 0) + { IEvioReader::ReadWriteStatus status = processNextBlock(); - if (status == IEvioReader::ReadWriteStatus::END_OF_FILE) { + if (status == IEvioReader::ReadWriteStatus::END_OF_FILE) + { return nullptr; } - else if (status != IEvioReader::ReadWriteStatus::SUCCESS) { + else if (status != IEvioReader::ReadWriteStatus::SUCCESS) + { throw EvioException("Failed reading block header in nextEvent."); } blkBytesRemaining = blockBytesRemaining(); @@ -1101,36 +1233,41 @@ namespace evio { blkBytesRemaining -= 4; // just read in 4 bytes // get the raw data - uint32_t eventDataSizeBytes = 4*(length - 1); + uint32_t eventDataSizeBytes = 4 * (length - 1); - try { + try + { auto *bytes = new uint8_t[eventDataSizeBytes]; uint32_t bytesToGo = eventDataSizeBytes; uint32_t offset = 0; // Don't really need the "if (version < 4)" here except for clarity. - if (evioVersion < 4) { + if (evioVersion < 4) + { // Be in while loop if have to cross block boundary[ies]. - while (bytesToGo > 0) { + while (bytesToGo > 0) + { // Don't read more than what is left in current block - uint32_t bytesToReadNow = bytesToGo > blkBytesRemaining ? - blkBytesRemaining : bytesToGo; + uint32_t bytesToReadNow = bytesToGo > blkBytesRemaining ? blkBytesRemaining : bytesToGo; // Read in bytes remaining in internal buffer byteBuffer->getBytes(bytes + offset, bytesToReadNow); - offset += bytesToReadNow; - bytesToGo -= bytesToReadNow; - blkBytesRemaining -= bytesToReadNow; + offset += bytesToReadNow; + bytesToGo -= bytesToReadNow; + blkBytesRemaining -= bytesToReadNow; - if (blkBytesRemaining == 0) { + if (blkBytesRemaining == 0) + { IEvioReader::ReadWriteStatus status = processNextBlock(); - if (status == IEvioReader::ReadWriteStatus::END_OF_FILE) { + if (status == IEvioReader::ReadWriteStatus::END_OF_FILE) + { return nullptr; } - else if (status != IEvioReader::ReadWriteStatus::SUCCESS) { + else if (status != IEvioReader::ReadWriteStatus::SUCCESS) + { throw EvioException("Failed reading block header after crossing boundary in nextEvent."); } @@ -1141,46 +1278,50 @@ namespace evio { // Last (perhaps only) read byteBuffer->getBytes(bytes + offset, bytesToGo); -//std::cout << "nextEvent: eventDataSizeByte = " << eventDataSizeBytes << std::endl; + // std::cout << "nextEvent: eventDataSizeByte = " << eventDataSizeBytes << std::endl; event->setRawBytes(bytes, eventDataSizeBytes); event->setByteOrder(byteOrder); // add this to track endianness, timmer // Don't worry about dictionaries here as version must be 1-3 event->setEventNumber(++eventNumber); return event; } - catch (EvioException & e) { + catch (EvioException &e) + { std::cout << e.what() << std::endl; return nullptr; } } - /** {@inheritDoc} */ - std::shared_ptr EvioReaderV4::parseNextEvent() { + std::shared_ptr EvioReaderV4::parseNextEvent() + { // Lock this method - if (synchronized) { + if (synchronized) + { const std::lock_guard lock(mtx); } auto event = nextEvent(); - if (event != nullptr) { + if (event != nullptr) + { parseEvent(event); } return event; } - /** {@inheritDoc} */ - void EvioReaderV4::parseEvent(std::shared_ptr evioEvent) { + void EvioReaderV4::parseEvent(std::shared_ptr evioEvent) + { // This method is called by locked methods parser->parseEvent(evioEvent); } - /** {@inheritDoc} */ - uint32_t EvioReaderV4::getEventArray(size_t evNumber, std::vector & vec) { + uint32_t EvioReaderV4::getEventArray(size_t evNumber, std::vector &vec) + { auto ev = gotoEventNumber(evNumber, false); - if (ev == nullptr) { + if (ev == nullptr) + { throw EvioException("event number must be > 0"); } @@ -1190,11 +1331,12 @@ namespace evio { return numBytes; } - /** {@inheritDoc} */ - uint32_t EvioReaderV4::getEventBuffer(size_t evNumber, ByteBuffer & buf) { + uint32_t EvioReaderV4::getEventBuffer(size_t evNumber, ByteBuffer &buf) + { auto ev = gotoEventNumber(evNumber, false); - if (ev == nullptr) { + if (ev == nullptr) + { throw EvioException("event number must be > 0"); } @@ -1206,14 +1348,12 @@ namespace evio { return numBytes; } - /** * Get the number of bytes remaining in the internal byte buffer. * Called only by {@link #nextEvent()}. * @return the number of bytes remaining in the current block (physical record). */ - size_t EvioReaderV4::bufferBytesRemaining() const {return byteBuffer->remaining();} - + size_t EvioReaderV4::bufferBytesRemaining() const { return byteBuffer->remaining(); } /** * Get the number of bytes remaining in the current block (physical record). @@ -1223,27 +1363,32 @@ namespace evio { * @return the number of bytes remaining in the current block (physical record). * @throws EvioException if position out of bounds */ - uint32_t EvioReaderV4::blockBytesRemaining() const { + uint32_t EvioReaderV4::blockBytesRemaining() const + { return blockHeader->bytesRemaining(byteBuffer->position()); } - /** {@inheritDoc} */ - void EvioReaderV4::rewind() { + void EvioReaderV4::rewind() + { // Lock this method - if (synchronized) { + if (synchronized) + { const std::lock_guard lock(mtx); } - if (closed) { + if (closed) + { throw EvioException("object closed"); } - if (sequentialRead) { + if (sequentialRead) + { file.seekg(initialPosition); prepareForSequentialRead(); } - else if (evioVersion < 4) { + else if (evioVersion < 4) + { byteBuffer->position(initialPosition); prepareForBufferRead(byteBuffer); } @@ -1252,16 +1397,19 @@ namespace evio { eventNumber = 0; blockNumberExpected = 1; - if (evioVersion < 4) { + if (evioVersion < 4) + { blockHeader = blockHeader2 = std::make_shared(firstBlockHeader2); } - else { + else + { blockHeader = blockHeader4 = std::make_shared(firstBlockHeader4); } blockHeader->setBufferStartingPosition(initialPosition); - if (sequentialRead && hasDictionaryXML()) { + if (sequentialRead && hasDictionaryXML()) + { // Dictionary is always the first event so skip over it. // For sequential reads, do this after each rewind. nextEvent(); @@ -1269,59 +1417,70 @@ namespace evio { } /** {@inheritDoc} */ - ssize_t EvioReaderV4::position() { + ssize_t EvioReaderV4::position() + { // Lock this method - if (synchronized) { + if (synchronized) + { const std::lock_guard lock(mtx); } - if (!sequentialRead && evioVersion > 3) return -1L; + if (!sequentialRead && evioVersion > 3) + return -1L; - if (closed) { + if (closed) + { throw EvioException("object closed"); } - if (sequentialRead) { + if (sequentialRead) + { return file.tellg(); } return byteBuffer->position(); } /** {@inheritDoc} */ - void EvioReaderV4::close() { + void EvioReaderV4::close() + { // Lock this method - if (synchronized) { + if (synchronized) + { const std::lock_guard lock(mtx); } - if (closed) { + if (closed) + { return; } - if (sequentialRead) { + if (sequentialRead) + { file.close(); } - else { - try { + else + { + try + { byteBuffer->position(initialPosition); } - catch (EvioException & e) {} + catch (EvioException &e) + { + } } closed = true; } - /** {@inheritDoc} */ - std::shared_ptr EvioReaderV4::getCurrentBlockHeader() {return blockHeader;} - + std::shared_ptr EvioReaderV4::getCurrentBlockHeader() { return blockHeader; } /** {@inheritDoc} */ - std::shared_ptr EvioReaderV4::gotoEventNumber(size_t evNumber) { + std::shared_ptr EvioReaderV4::gotoEventNumber(size_t evNumber) + { return gotoEventNumber(evNumber, true); } - /** * Go to a specific event in the file. The events are numbered 1..N. * This number is transient--it is not part of the event as stored in the evio file. @@ -1332,26 +1491,34 @@ namespace evio { * @return the specified event in file or null if there's an error or nothing at that event #. * @throws EvioException if object closed; if failed file access */ - std::shared_ptr EvioReaderV4::gotoEventNumber(size_t evNumber, bool parse) { + std::shared_ptr EvioReaderV4::gotoEventNumber(size_t evNumber, bool parse) + { // Lock this method - if (synchronized) { + if (synchronized) + { const std::lock_guard lock(mtx); } - if (closed) { + if (closed) + { throw EvioException("object closed"); } - if (!sequentialRead && evioVersion > 3) { - try { - if (parse) { + if (!sequentialRead && evioVersion > 3) + { + try + { + if (parse) + { return parseEvent(evNumber); } - else { + else + { return getEvent(evNumber); } } - catch (EvioException & e) { + catch (EvioException &e) + { return nullptr; } } @@ -1359,113 +1526,130 @@ namespace evio { rewind(); std::shared_ptr event; - try { + try + { // get the first evNumber - 1 events without parsing - for (size_t i = 1; i < evNumber; i++) { + for (size_t i = 1; i < evNumber; i++) + { event = nextEvent(); - if (event == nullptr) { + if (event == nullptr) + { throw EvioException("Asked to go to event: " + std::to_string(evNumber) + ", which is beyond the end of file"); } } // get one more event, the evNumber'th event - if (parse) { + if (parse) + { return parseNextEvent(); } - else { + else + { return nextEvent(); } } - catch (EvioException & e) { + catch (EvioException &e) + { std::cout << e.what() << std::endl; } return nullptr; } - /** {@inheritDoc} */ - size_t EvioReaderV4::getEventCount() { + size_t EvioReaderV4::getEventCount() + { // Lock this method - if (synchronized) { + if (synchronized) + { const std::lock_guard lock(mtx); } - if (closed) { - throw EvioException("object closed"); - } - - // sequentialRead is always false for reading buffer and - // always true for reading file. - if (!sequentialRead && evioVersion > 3) { - // Already calculated by calling generateEventPositions in constructor ... - //std::cout << "EvioReaderV4 getEventCount: not seq read, event count = " << eventCount << std::endl; - return eventCount; - } + if (closed) + { + throw EvioException("object closed"); + } - if (eventCount < 0) { - // The difficulty is that this method can be called at - // any time. So we need to save our state and then restore - // it when we're done. - ReaderState *state = getState(); + // sequentialRead is always false for reading buffer and + // always true for reading file. + if (!sequentialRead && evioVersion > 3) + { + // Already calculated by calling generateEventPositions in constructor ... + // std::cout << "EvioReaderV4 getEventCount: not seq read, event count = " << eventCount << std::endl; + return eventCount; + } - rewind(); - eventCount = 0; + if (eventCount < 0) + { + // The difficulty is that this method can be called at + // any time. So we need to save our state and then restore + // it when we're done. + ReaderState *state = getState(); - while (nextEvent() != nullptr) { - //std::cout << "EvioReaderV4 getEventCount: add to eventCount (" << eventCount << ")" << std::endl; - eventCount++; - } + rewind(); + eventCount = 0; - // If sequential access to v2 file, then nextEvent() places - // new data into byteBuffer. Restoring the original state - // is useless without also restoring/re-reading the data. - if (sequentialRead) { - rewind(); + while (nextEvent() != nullptr) + { + // std::cout << "EvioReaderV4 getEventCount: add to eventCount (" << eventCount << ")" << std::endl; + eventCount++; + } - // Skip dictionary - if (hasDictionaryXML()) { - nextEvent(); - } + // If sequential access to v2 file, then nextEvent() places + // new data into byteBuffer. Restoring the original state + // is useless without also restoring/re-reading the data. + if (sequentialRead) + { + rewind(); - // Go back to original event # & therefore buffer data - for (uint32_t i=1; i < state->eventNumber; i++) { - nextEvent(); - } + // Skip dictionary + if (hasDictionaryXML()) + { + nextEvent(); } - // Restore our original settings - restoreState(state); + // Go back to original event # & therefore buffer data + for (uint32_t i = 1; i < state->eventNumber; i++) + { + nextEvent(); + } } - return eventCount; - } + // Restore our original settings + restoreState(state); + } + return eventCount; + } /** {@inheritDoc} */ - size_t EvioReaderV4::getBlockCount() { + size_t EvioReaderV4::getBlockCount() + { // Lock this method - if (synchronized) { + if (synchronized) + { const std::lock_guard lock(mtx); } - if (closed) { - throw EvioException("object closed"); - } + if (closed) + { + throw EvioException("object closed"); + } - if (!sequentialRead && evioVersion > 3) { - return blockCount; - } + if (!sequentialRead && evioVersion > 3) + { + return blockCount; + } - if (blockCount < 0) { - // Although block size is theoretically adjustable, I believe - // that everyone used 8192 words for the block size in version 3. - blockCount = (uint32_t) (fileBytes/firstBlockSize); - } + if (blockCount < 0) + { + // Although block size is theoretically adjustable, I believe + // that everyone used 8192 words for the block size in version 3. + blockCount = (uint32_t)(fileBytes / firstBlockSize); + } - return blockCount; + return blockCount; } - } \ No newline at end of file From 985d3cf8c7d91d651223a5a290c88ff4d8f51d50 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Sun, 22 Jun 2025 16:51:12 -0500 Subject: [PATCH 45/56] minor tweaks to tests --- CMakeLists.txt | 4 ++-- .../coda/jevio/unit_tests/EvioTestHelper.java | 10 +++++----- src/test/cpp/EvioTestHelper.h | 17 +++++++++++------ src/test/java/EvioWriteAndReadBack_builder.java | 2 +- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index db134cc11..af387bd18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -254,8 +254,8 @@ endif() # Unit testing setup # add_executable(test_basic src/test/cpp/test_basic.cpp) # Already done above -add_test(NAME ctest_test COMMAND bin/ctest_test) -add_test(NAME EvioWriteAndReadBack_builder COMMAND bin/EvioWriteAndReadBack_builder 10) +add_test(NAME ctest_test COMMAND bin/ctest_test-dbg) +add_test(NAME EvioWriteAndReadBack_builder COMMAND bin/EvioWriteAndReadBack_builder-dbg 10) # Uninstall target # Removed for now, not yet compatible with building disruptor-cpp internally diff --git a/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java b/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java index 726c70cbb..74246a70a 100644 --- a/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java +++ b/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java @@ -11,10 +11,10 @@ public class EvioTestHelper { // Parameters (simplified here for brevity) // apparently all files must have absolute paths!!!!! - private final static String baseNameV4 = "testEventsV4.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. - private final static String baseNameV6 = "testEventsV6.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. - private final static String baseNameHIPO = "testEventsHIPO.hipo"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. - private final static String directory = null; // "/mnt/tmpfs" or null=relative path (or directory in which file is to be placed) + private final static String baseNameV4 = "testEventsV4_javaAPI.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + private final static String baseNameV6 = "testEventsV6_javaAPI.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + private final static String baseNameHIPO = "testEventsHIPO_javaAPI.hipo"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + private final static String directory = "tmp"; // "/mnt/tmpfs" or null=relative path (or directory in which file is to be placed) private final static String runType = ""; // name of run type configuration to be used in naming files private final static int runNumber = 1; // arbitrary, usually experiment-specific private final static long split = 0; // if < 1, do not split file, write to only one file of unlimited size. Else this is max size in bytes to make a file before closing it and starting writing another. @@ -53,7 +53,7 @@ public EvioTestHelper() { // Generate a float array similar to C++ vector public float[] genXYZT(int i) { - float[] x4 = new float[5]; // matches C++ size + float[] x4 = new float[4]; x4[0] = (float) random.nextGaussian() * 0.1f; x4[1] = (float) random.nextGaussian() * 0.1f; x4[2] = 0.0f; diff --git a/src/test/cpp/EvioTestHelper.h b/src/test/cpp/EvioTestHelper.h index 83a8e9909..78c767405 100644 --- a/src/test/cpp/EvioTestHelper.h +++ b/src/test/cpp/EvioTestHelper.h @@ -60,9 +60,14 @@ using namespace evio; ); } - std::shared_ptr defaultEventWriter() { + std::shared_ptr defaultEventWriter(std::string baseName = "") { + + if (baseName.empty()) { + baseName = baseNameV6; // Default to V6 if no base name is provided + } + return std::make_shared( - baseNameV6, + baseName, directory, runType, runNumber, @@ -126,10 +131,10 @@ using namespace evio; std::normal_distribution gauss{0.0f, 0.1f}; - std::string baseNameV4 = "testEventsV4.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. - std::string baseNameV6 = "testEventsV6.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. - std::string baseNameHIPO = "testEventsHIPO.hipo"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. - const std::string directory = "tmp"; // directory in which file is to be placed + std::string baseNameV4 = "testEventsV4_cppAPI.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + std::string baseNameV6 = "testEventsV6_cppAPI.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + std::string baseNameHIPO = "testEventsHIPO_cppAPI.hipo"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + const std::string directory = "/home/jzarling/super_evio_dev/evio/tmp"; // directory in which file is to be placed const std::string runType = ""; // name of run type configuration to be used in naming files uint32_t runNumber = 1; uint64_t split = 0; // if < 1, do not split file, write to only one file of unlimited size. Else this is max size in bytes to make a file before closing it and starting writing another. diff --git a/src/test/java/EvioWriteAndReadBack_builder.java b/src/test/java/EvioWriteAndReadBack_builder.java index bf070c6a9..7b936ea8e 100644 --- a/src/test/java/EvioWriteAndReadBack_builder.java +++ b/src/test/java/EvioWriteAndReadBack_builder.java @@ -39,7 +39,7 @@ class EvioWriteAndReadBack_builder { // evioWriteAndReadBack(testInfo, 10); // } - void evioWriteAndReadBack(TestInfo testInfo) throws IOException, EvioException { + void evioWriteAndReadBackBuilder(TestInfo testInfo) throws IOException, EvioException { int nEvents = 100000; // 10 M events From ba9379758d2266592c604c94783147c64027ae4d Mon Sep 17 00:00:00 2001 From: jonzarling Date: Mon, 23 Jun 2025 08:58:12 -0500 Subject: [PATCH 46/56] more small junit tweaks --- .../coda/jevio/unit_tests/EvioTestHelper.java | 10 +-- .../java/EvioWriteAndReadBack_builder.java | 85 +++++++++++++++---- 2 files changed, 75 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java b/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java index 74246a70a..0107efb64 100644 --- a/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java +++ b/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java @@ -11,11 +11,11 @@ public class EvioTestHelper { // Parameters (simplified here for brevity) // apparently all files must have absolute paths!!!!! - private final static String baseNameV4 = "testEventsV4_javaAPI.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. - private final static String baseNameV6 = "testEventsV6_javaAPI.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. - private final static String baseNameHIPO = "testEventsHIPO_javaAPI.hipo"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. - private final static String directory = "tmp"; // "/mnt/tmpfs" or null=relative path (or directory in which file is to be placed) - private final static String runType = ""; // name of run type configuration to be used in naming files + public static String baseNameV4 = "testEventsV4_javaAPI.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + public static String baseNameV6 = "testEventsV6_javaAPI.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + public static String baseNameHIPO = "testEventsHIPO_javaAPI.hipo"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + public static String directory = "tmp"; // "/mnt/tmpfs" or null=relative path (or directory in which file is to be placed) + final static String runType = ""; // name of run type configuration to be used in naming files private final static int runNumber = 1; // arbitrary, usually experiment-specific private final static long split = 0; // if < 1, do not split file, write to only one file of unlimited size. Else this is max size in bytes to make a file before closing it and starting writing another. private final static int maxRecordSize = 33554432; // (32 MiB) max number of uncompressed data bytes each record can hold. Value of < 8MB results in default of 8MB. The size of the record will not be larger than this size unless a single event itself is larger diff --git a/src/test/java/EvioWriteAndReadBack_builder.java b/src/test/java/EvioWriteAndReadBack_builder.java index 7b936ea8e..ea5ba1c5b 100644 --- a/src/test/java/EvioWriteAndReadBack_builder.java +++ b/src/test/java/EvioWriteAndReadBack_builder.java @@ -30,18 +30,20 @@ @Tag("fast") // Run when selecting "fast" category of tests -class EvioWriteAndReadBack_builder { +class EvioTestReadback_builder { @Test @DisplayName("Evio Write and Read Back Test") + void DoReadbackTest(TestInfo testInfo) throws IOException, EvioException { + + int nEvents = 100000; // Number of events to write + + evioWriteStep(nEvents); // Write events + evioReadStep(nEvents); // Readback with asserts + } - // void evioWriteAndReadBack(TestInfo testInfo) throws IOException, EvioException { - // evioWriteAndReadBack(testInfo, 10); - // } - - void evioWriteAndReadBackBuilder(TestInfo testInfo) throws IOException, EvioException { - int nEvents = 100000; // 10 M events + void evioWriteStep(int nEvents) throws IOException, EvioException { EvioTestHelper h = new EvioTestHelper(); @@ -61,17 +63,9 @@ void evioWriteAndReadBackBuilder(TestInfo testInfo) throws IOException, EvioExce float[] floatVec = h.genXYZT(i); // generate pseudo x, y, z, time values - // Now to start defining event - // if(i == 0) { builder = new EventBuilder(tag, DataType.BANK, num); event = builder.getEvent(); - // } - // THE OVERBANK - // First child of event = bank of banks - // EvioBank bankBanks = new EvioBank(tag+1, DataType.BANK, num+1); - // builder.addChild(event, bankBanks); - // (SUB)BANK 1 OF 1 // Create first (& only) child of bank of banks = bank of floats EvioBank bankFloats = new EvioBank(tag+11, DataType.FLOAT32, num+11); @@ -98,4 +92,65 @@ void evioWriteAndReadBackBuilder(TestInfo testInfo) throws IOException, EvioExce System.out.println(" Wrote " + nEvents + " events to file. "); } + + + void evioReadStep(int nEvents) throws IOException, EvioException { + + String filename = EvioTestHelper.directory + "/" + EvioTestHelper.baseNameV6; + + try { + EvioReader reader = new EvioReader(filename); + int evCount = reader.getEventCount(); + int eventsToCheck = 10; // Number of events to check with explicit output + + System.out.println("Read " + evCount + " events from file: " + filename); + assertEquals(nEvents, evCount, "Event count mismatch after reading back"); + + // Does it contain a dictionary? + if (reader.hasDictionaryXML()) { + String dict = reader.getDictionaryXML(); + System.out.println("Dictionary = \n" + dict); + } + + // Look at each event with random-access type method (starts at 1) + System.out.println("Print out regular events’ raw data:"); + for (int i = 0; i < evCount; i++) { + EvioEvent ev = reader.parseEvent(i + 1); + byte[] byteData = ev.getByteData(); + Utilities.printBytes(byteData, 0, byteData.length, " Event #" + i); + } + + reader.rewind(); // Rewind to the beginning of the file + // Look at each event with sequential type method (starts at 0) + for (int i = 0; i < evCount; i++) { + EvioEvent ev = reader.parseNextEvent(); + byte[] byteData = ev.getByteData(); + Utilities.printBytes(byteData, 0, byteData.length, " Event #" + i); + + // Check if the event is a bank + if (ev.getStructureType() == StructureType.BANK) { + List banks = ev.getChildBanks(); + assertEquals(1, banks.size(), "Expected 1 child bank in event " + i); + + EvioBank bank = banks.get(0); + assertEquals(1, bank.getNum(), "Expected num=1 for bank in event " + i); + + // Check the float data + float[] data = bank.getFloatData(); + assertEquals(4, data.length, "Expected 4 float values in bank of event " + i); + + // Validate the data + float[] expectedData = EvioTestHelper.genXYZT(i); + assertEquals(expectedData[0], data[0], 0.001, "X value mismatch in event " + i); + assertEquals(expectedData[1], data[1], 0.001, "Y value mismatch in event " + i); + assertEquals(expectedData[2], data[2], 0.001, "Z value mismatch in event " + i); + assertEquals(expectedData[3], data[3], 0.001, "T value mismatch in event " + i); + } + } + } + catch (Exception e) { + e.printStackTrace(); + } + } + } \ No newline at end of file From 3737088992cda96e10c27cdd1c6722d2821a0dfb Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Wed, 25 Jun 2025 10:17:18 -0500 Subject: [PATCH 47/56] more tweaks --- .../coda/jevio/unit_tests/EvioTestHelper.java | 4 +- src/test/cpp/EvioTestHelper.h | 18 +-- src/test/cpp/EvioWriteAndReadBack_builder.cpp | 106 +++++++++++++++++- .../java/EvioWriteAndReadBack_builder.java | 74 +++++++----- 4 files changed, 158 insertions(+), 44 deletions(-) diff --git a/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java b/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java index 0107efb64..d0371aeeb 100644 --- a/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java +++ b/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java @@ -30,8 +30,8 @@ public class EvioTestHelper { " \n" + " \n" + " \n" + - " \n" + - " \n" + + // " \n" + + // " \n" + "
\n"; private final static boolean overWriteOK = true; private final static boolean append = false; diff --git a/src/test/cpp/EvioTestHelper.h b/src/test/cpp/EvioTestHelper.h index 78c767405..e07da544c 100644 --- a/src/test/cpp/EvioTestHelper.h +++ b/src/test/cpp/EvioTestHelper.h @@ -115,13 +115,17 @@ using namespace evio; } std::vector genXYZT(int i) { - std::vector x4(5); // 5th entry for pyevio bugfix + std::vector x4(4); // 5th entry for pyevio bugfix x4[0] = gauss(gen); x4[1] = gauss(gen); x4[2] = 0.0f; x4[3] = i*2.008f; return x4; } + std::string baseNameV4 = "testEventsV4_cppAPI.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + std::string baseNameV6 = "testEventsV6_cppAPI.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + std::string baseNameHIPO = "testEventsHIPO_cppAPI.hipo"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. + std::string directory = "/home/jzarling/super_evio_dev/evio/tmp"; // directory in which file is to be placed private: @@ -131,10 +135,6 @@ using namespace evio; std::normal_distribution gauss{0.0f, 0.1f}; - std::string baseNameV4 = "testEventsV4_cppAPI.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. - std::string baseNameV6 = "testEventsV6_cppAPI.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. - std::string baseNameHIPO = "testEventsHIPO_cppAPI.hipo"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. - const std::string directory = "/home/jzarling/super_evio_dev/evio/tmp"; // directory in which file is to be placed const std::string runType = ""; // name of run type configuration to be used in naming files uint32_t runNumber = 1; uint64_t split = 0; // if < 1, do not split file, write to only one file of unlimited size. Else this is max size in bytes to make a file before closing it and starting writing another. @@ -150,10 +150,10 @@ using namespace evio; - - - - )"; + + )"; + // + // bool overWriteOK = true; bool append = false; std::shared_ptr< EvioBank >firstEvent = nullptr; // The first event written into each file (after any dictionary) including all split files; may be null. Useful for adding common, static info into each split file diff --git a/src/test/cpp/EvioWriteAndReadBack_builder.cpp b/src/test/cpp/EvioWriteAndReadBack_builder.cpp index ea952702d..ae1f34341 100644 --- a/src/test/cpp/EvioWriteAndReadBack_builder.cpp +++ b/src/test/cpp/EvioWriteAndReadBack_builder.cpp @@ -2,6 +2,9 @@ using namespace evio; +// Forward declaration for a few functions +void evioReadStep(std::string filename); + int main(int argc, char* argv[]) { // Boilerplate @@ -31,8 +34,8 @@ int main(int argc, char* argv[]) { // builder = std::make_shared(event); // } - // std::vector floatVec = evioHelperObj->genXYZT(i); // generate pseudo x, y, z, time values - std::vector floatVec = {0.0f, 1.0f, 2.0f, 3.0f, 4.0f}; // Example data for testing + std::vector floatVec = evioHelperObj->genXYZT(i); // generate pseudo x, y, z, time values + // std::vector floatVec = {0.0f, 1.0f, 2.0f, 3.0f, 4.0f}; // Example data for testing // Now to start defining event @@ -60,6 +63,105 @@ int main(int argc, char* argv[]) { writerV6->close(); // close file writer (flush remaining data)​:contentReference[oaicite:6]{index=6} std::cout << "Wrote " << nEvents << " events to file." << std::endl; + + evioReadStep(evioHelperObj->directory + "/" + evioHelperObj->baseNameV6); + return 0; +} + + +void evioReadStep(std::string filename) { + + EvioReader reader(filename); + + // Find out how many events the file contains + int32_t evCount = reader.getEventCount(); + int32_t eventsToCheck = 10; // Number of events to check with explicit output + std::cout << "File has " << evCount << " events" << std::endl; + + // Does it contain a dictionary? + if (reader.hasDictionaryXML()) { + std::string dict = reader.getDictionaryXML(); + std::cout << "Dictionary = " << dict << std::endl; + } + + // Does it contain a first event? + std::shared_ptr fe = reader.getFirstEvent(); + if (fe != nullptr) std::cout << "First event size = " << fe->getTotalBytes() << " bytes" << std::endl; + + std::cout << "EVIO Ver: " << reader.getEvioVersion() << std::endl; + std::cout << "File Size: " << reader.fileSize() << std::endl; + std::cout << "Event count: " << reader.getEventCount() << std::endl; + std::cout << "Has first event?: " << reader.hasFirstEvent() << std::endl; + + // Look at each event with random-access type method (start at 1) + std::cout << "Print out regular events raw data:" << std::endl; + for (int i = 0; i < evCount; i++) { + + if (i >= eventsToCheck) { + std::cout << "Reached maximum number of events to read: " << eventsToCheck << std::endl; + break; + } + + auto ev = reader.parseEvent(i+1); + std::cout << " got & parsed ev " << (i+1) << std::endl; + std::cout << " event ->\n" << ev->toString() << std::endl; + auto& dataVec = ev->getRawBytes(); + std::cout << "Event has tag = " << ev->getHeader()->getTag() << std::endl; + std::cout << "Event structure type = " << ev->getStructureType().toString() << std::endl; + std::vector< std::shared_ptr< BaseStructure > > & children = ev->getChildren(); + std::cout << "Event has " << children.size() << " children" << std::endl; + + // Now loop over children, if any + for (size_t j = 0; j < children.size(); j++) { + std::cout << "Child " << j << " tag = " << children[j]->getStructureType().toString() << std::endl; + + std::cout << "NChildren: " << children[j]->getChildCount() << std::endl; + std::cout << "Num items stored: " << children[j]->getNumberDataItems() << std::endl; + std::cout << "Data type: " << children[j]->getHeader()->getDataType().toString() << std::endl; + if(children[j]->getHeader()->getDataType() == DataType::FLOAT32) { + std::cout << "Data: "; + std::vector data_vec = children[j]->getFloatData(); + for (size_t l = 0; l < data_vec.size(); l++) { + std::cout << data_vec[l] << " "; + } + + // for (size_t k = 0; k < children[j]->getChildCount(); k++) { + // std::cout << "Child " << j << ", subchild " << k << " " << children[j]->getChildAt(k)->getStructureType().toString() << std::endl; + // std::cout << "Subchild " << k << " datatype: " << children[j]->getChildAt(k)->getHeader()->getDataType().toString() << std::endl; + // std::cout << "nsubchildren: " << children[j]->getChildAt(k)->getChildCount() << std::endl; + // std::cout << "num items stored: " << children[j]->getChildAt(k)->getNumberDataItems() << std::endl; + // // If data type is int, dump the data + // std::cout << "Data type: " << children[j]->getChildAt(k)->getHeader()->getDataType().toString() << std::endl; + // if(children[j]->getChildAt(k)->getHeader()->getDataType() == DataType::FLOAT32) { + // std::cout << "Data: "; + // std::vector data_uint_vec = children[j]->getChildAt(k)->getFloatData(); + // for (size_t l = 0; l < data_uint_vec.size(); l++) { + // std::cout << data_uint_vec[l] << " "; + // } + // std::cout << std::endl; + // } + // } + } + std::cout << std::endl; + + + reader.rewind(); + + } + } + return; } + + // Go back to beginning of file + + // // Use sequential access to events + // std::shared_ptr ev = nullptr; + // int counter = 0; + // while ((ev = reader.parseNextEvent()) != nullptr) { + // counter++; + // if (counter >= eventsToCheck) break; + // // do something with event + // std::cout << "Event has tag = " << ev->getHeader()->getTag() << std::endl; + // } diff --git a/src/test/java/EvioWriteAndReadBack_builder.java b/src/test/java/EvioWriteAndReadBack_builder.java index ea5ba1c5b..c2a9a791e 100644 --- a/src/test/java/EvioWriteAndReadBack_builder.java +++ b/src/test/java/EvioWriteAndReadBack_builder.java @@ -107,50 +107,62 @@ void evioReadStep(int nEvents) throws IOException, EvioException { assertEquals(nEvents, evCount, "Event count mismatch after reading back"); // Does it contain a dictionary? - if (reader.hasDictionaryXML()) { - String dict = reader.getDictionaryXML(); - System.out.println("Dictionary = \n" + dict); - } + // if (reader.hasDictionaryXML()) { + // String dict = reader.getDictionaryXML(); + // System.out.println("Dictionary = \n" + dict); + // } // Look at each event with random-access type method (starts at 1) - System.out.println("Print out regular events’ raw data:"); - for (int i = 0; i < evCount; i++) { - EvioEvent ev = reader.parseEvent(i + 1); - byte[] byteData = ev.getByteData(); - Utilities.printBytes(byteData, 0, byteData.length, " Event #" + i); - } + // System.out.println("Print out regular events’ raw data:"); + // for (int i = 0; i < eventsToCheck; i++) { + // EvioEvent ev = reader.parseEvent(i + 1); + // byte[] byteData = ev.getByteData(); + // System.out.println("First ev size = " + ev.getTotalBytes() + " bytes"); + // System.out.println(" Event # " + i + " length = " + byteData.length + " ints"); + // Utilities.printBytes(byteData, 0, byteData.length, " Event #" + i); + // } reader.rewind(); // Rewind to the beginning of the file - // Look at each event with sequential type method (starts at 0) - for (int i = 0; i < evCount; i++) { + for (int i = 0; i < eventsToCheck; i++) { EvioEvent ev = reader.parseNextEvent(); byte[] byteData = ev.getByteData(); + System.out.println("First ev size = " + ev.getTotalBytes() + " bytes"); + System.out.println(" Event # " + i + " length = " + byteData.length + " ints"); Utilities.printBytes(byteData, 0, byteData.length, " Event #" + i); + } + + + + // reader.rewind(); // Rewind to the beginning of the file + // // Look at each event with sequential type method (starts at 0) + // for (int i = 0; i < evCount; i++) { + // EvioEvent ev = reader.parseNextEvent(); + // byte[] byteData = ev.getByteData(); + // Utilities.printBytes(byteData, 0, byteData.length, " Event #" + i); - // Check if the event is a bank - if (ev.getStructureType() == StructureType.BANK) { - List banks = ev.getChildBanks(); - assertEquals(1, banks.size(), "Expected 1 child bank in event " + i); + // // Check if the event is a bank + // if (ev.getStructureType() == StructureType.BANK) { + // List banks = ev.getChildBanks(); + // assertEquals(1, banks.size(), "Expected 1 child bank in event " + i); - EvioBank bank = banks.get(0); - assertEquals(1, bank.getNum(), "Expected num=1 for bank in event " + i); + // EvioBank bank = banks.get(0); + // assertEquals(1, bank.getNum(), "Expected num=1 for bank in event " + i); - // Check the float data - float[] data = bank.getFloatData(); - assertEquals(4, data.length, "Expected 4 float values in bank of event " + i); + // // Check the float data + // float[] data = bank.getFloatData(); + // assertEquals(4, data.length, "Expected 4 float values in bank of event " + i); - // Validate the data - float[] expectedData = EvioTestHelper.genXYZT(i); - assertEquals(expectedData[0], data[0], 0.001, "X value mismatch in event " + i); - assertEquals(expectedData[1], data[1], 0.001, "Y value mismatch in event " + i); - assertEquals(expectedData[2], data[2], 0.001, "Z value mismatch in event " + i); - assertEquals(expectedData[3], data[3], 0.001, "T value mismatch in event " + i); - } - } - } + // // Validate the data + // float[] expectedData = EvioTestHelper.genXYZT(i); + // assertEquals(expectedData[0], data[0], 0.001, "X value mismatch in event " + i); + // assertEquals(expectedData[1], data[1], 0.001, "Y value mismatch in event " + i); + // assertEquals(expectedData[2], data[2], 0.001, "Z value mismatch in event " + i); + // assertEquals(expectedData[3], data[3], 0.001, "T value mismatch in event " + i); + // } + // } + } catch (Exception e) { e.printStackTrace(); } } - } \ No newline at end of file From 5957355d560a313e2ec1708ac6f0c977f7e1aee2 Mon Sep 17 00:00:00 2001 From: jonzarling Date: Wed, 25 Jun 2025 14:09:12 -0500 Subject: [PATCH 48/56] Starting work on a "recovery" feature, to look nearby for magic word when the header length is off by one or two in counting --- .../java/org/jlab/coda/jevio/EvioReader.java | 6 ++ .../jlab/coda/jevio/EvioReaderUnsyncV4.java | 72 ++++++++++++------- .../coda/jevio/dev/EvioReadFileSimple.java | 43 +++++++++++ .../java/EvioWriteAndReadBack_builder.java | 34 +++++---- 4 files changed, 118 insertions(+), 37 deletions(-) create mode 100644 src/main/java/org/jlab/coda/jevio/dev/EvioReadFileSimple.java diff --git a/src/main/java/org/jlab/coda/jevio/EvioReader.java b/src/main/java/org/jlab/coda/jevio/EvioReader.java index 83b58b266..ba034970c 100644 --- a/src/main/java/org/jlab/coda/jevio/EvioReader.java +++ b/src/main/java/org/jlab/coda/jevio/EvioReader.java @@ -53,6 +53,12 @@ public class EvioReader implements IEvioReader { */ private ByteOrder byteOrder; + /** If enabled by setting > 0, then scan +/- this many words around expected + * magic number when reading record header + */ + private int magicNumRecoverWin = -1; + + /** The buffer being read. */ private final ByteBuffer byteBuffer; diff --git a/src/main/java/org/jlab/coda/jevio/EvioReaderUnsyncV4.java b/src/main/java/org/jlab/coda/jevio/EvioReaderUnsyncV4.java index 0fc5d594a..32784170f 100644 --- a/src/main/java/org/jlab/coda/jevio/EvioReaderUnsyncV4.java +++ b/src/main/java/org/jlab/coda/jevio/EvioReaderUnsyncV4.java @@ -1072,31 +1072,54 @@ else if (bytesInBuf % 32768 == 0) { if (evioVersion >= 4) { // Read the header data. - blockHeader4.setSize(byteBuffer.getInt()); - blockHeader4.setNumber(byteBuffer.getInt()); - blockHeader4.setHeaderLength(byteBuffer.getInt()); - blockHeader4.setEventCount(byteBuffer.getInt()); - blockHeader4.setReserved1(byteBuffer.getInt()); - // Use 6th word to set bit info - blockHeader4.parseToBitInfo(byteBuffer.getInt()); - blockHeader4.setVersion(evioVersion); - lastBlock = blockHeader4.getBitInfo(1); - blockHeader4.setReserved2(byteBuffer.getInt()); - blockHeader4.setMagicNumber(byteBuffer.getInt()); - blockHeader = blockHeader4; - - // Deal with non-standard header lengths here - int headerLenDiff = blockHeader4.getHeaderLength() - BlockHeaderV4.HEADER_SIZE; - // If too small quit with error since headers have a minimum size - if (headerLenDiff < 0) { + + System.out.println("GOT THIS FAR"); + + int[] words = new int[8]; + for (int i=0; i < 8; i++) { + if (byteBuffer.remaining() < 4) { + System.out.println("Remaining: " + byteBuffer.remaining() ); + return ReadStatus.END_OF_FILE; + } + System.out.println("Filling word " + i); + words[i] = byteBuffer.getInt(); + } + if(words[7] != IBlockHeader.MAGIC_NUMBER) { + System.err.println("ERROR magic # (" + words[7] + + ") != expected value " + IBlockHeader.MAGIC_NUMBER); return ReadStatus.EVIO_EXCEPTION; } - // If bigger, read extra ints - else if (headerLenDiff > 0) { - for (int i=0; i < headerLenDiff; i++) { - byteBuffer.getInt(); - } + else { + System.out.println("Magic word is correct"); + return ReadStatus.EVIO_EXCEPTION; } + + // blockHeader4.setSize(words[0]); + // blockHeader4.setNumber(words[1]); + // blockHeader4.setHeaderLength(words[2]); + // blockHeader4.setEventCount(words[3]); + // blockHeader4.setReserved1(words[4]); + // // Use 6th word to set bit info + // blockHeader4.parseToBitInfo(words[5]); + // blockHeader4.setVersion(evioVersion); + // lastBlock = blockHeader4.getBitInfo(1); + // blockHeader4.setReserved2(words[6]); + // blockHeader4.setMagicNumber(words[7]); + // blockHeader = blockHeader4; + + + // // Deal with non-standard header lengths here + // int headerLenDiff = blockHeader4.getHeaderLength() - BlockHeaderV4.HEADER_SIZE; + // // If too small quit with error since headers have a minimum size + // if (headerLenDiff < 0) { + // return ReadStatus.EVIO_EXCEPTION; + // } + // // If bigger, read extra ints + // else if (headerLenDiff > 0) { + // for (int i=0; i < headerLenDiff; i++) { + // byteBuffer.getInt(); + // } + // } } else if (evioVersion < 4) { // read the header data @@ -1121,9 +1144,8 @@ else if (evioVersion < 4) { if (checkBlockNumberSequence) { if (blockHeader.getNumber() != blockNumberExpected) { -System.out.println("block # out of sequence, got " + blockHeader.getNumber() + - " expecting " + blockNumberExpected); - + System.out.println("block # out of sequence, got " + blockHeader.getNumber() + + " expecting " + blockNumberExpected); return ReadStatus.EVIO_EXCEPTION; } blockNumberExpected++; diff --git a/src/main/java/org/jlab/coda/jevio/dev/EvioReadFileSimple.java b/src/main/java/org/jlab/coda/jevio/dev/EvioReadFileSimple.java new file mode 100644 index 000000000..59b000816 --- /dev/null +++ b/src/main/java/org/jlab/coda/jevio/dev/EvioReadFileSimple.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014, Jefferson Science Associates + * + * Thomas Jefferson National Accelerator Facility + * Data Acquisition Group + * + * 12000, Jefferson Ave, Newport News, VA 23606 + * Phone : (757)-269-7100 + * + */ + +package org.jlab.coda.jevio.dev; + +import java.io.IOException; + +import org.jlab.coda.jevio.EvioException; +import org.jlab.coda.jevio.EvioReader; + +public class EvioReadFileSimple { + + public static void main(String[] args) { + // This is a simple example of how to read an Evio file. + // It assumes that the Evio file is already created and contains events. + + if (args.length != 1) { + System.out.println("Usage: java EvioReadFileSimple "); + return; + } + + String filename = args[0]; // Replace with your Evio file name + + try { + EvioReader reader = new EvioReader(filename); + + int evCount = reader.getEventCount(); + + reader.close(); + } catch (EvioException | IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/test/java/EvioWriteAndReadBack_builder.java b/src/test/java/EvioWriteAndReadBack_builder.java index c2a9a791e..dfd6df8ce 100644 --- a/src/test/java/EvioWriteAndReadBack_builder.java +++ b/src/test/java/EvioWriteAndReadBack_builder.java @@ -13,18 +13,6 @@ import org.junit.jupiter.api.TestInfo; import java.io.*; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.AsynchronousFileChannel; -import java.nio.channels.FileChannel; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.Future; - -import org.jlab.coda.hipo.*; import org.jlab.coda.jevio.*; import org.jlab.coda.jevio.unit_tests.EvioTestHelper; // helper class for unit tests, also contained in java src files @@ -140,6 +128,16 @@ void evioReadStep(int nEvents) throws IOException, EvioException { // byte[] byteData = ev.getByteData(); // Utilities.printBytes(byteData, 0, byteData.length, " Event #" + i); + // // Check if the event is a bank + // if (ev.getStructureType() == StructureType.BANK) { + // List banks = ev.getChildBanks(); + // assertEquals(1, banks.size(), "Expected 1 child bank in event " + i); + // // Look at each event with sequential type method (starts at 0) + // for (int i = 0; i < evCount; i++) { + // EvioEvent ev = reader.parseNextEvent(); + // byte[] byteData = ev.getByteData(); + // Utilities.printBytes(byteData, 0, byteData.length, " Event #" + i); + // // Check if the event is a bank // if (ev.getStructureType() == StructureType.BANK) { // List banks = ev.getChildBanks(); @@ -148,10 +146,22 @@ void evioReadStep(int nEvents) throws IOException, EvioException { // EvioBank bank = banks.get(0); // assertEquals(1, bank.getNum(), "Expected num=1 for bank in event " + i); + // // Check the float data + // float[] data = bank.getFloatData(); + // assertEquals(4, data.length, "Expected 4 float values in bank of event " + i); // // Check the float data // float[] data = bank.getFloatData(); // assertEquals(4, data.length, "Expected 4 float values in bank of event " + i); + // // Validate the data + // // float[] expectedData = EvioTestHelper.genXYZT(i); + // assertEquals(expectedData[0], data[0], 0.001, "X value mismatch in event " + i); + // assertEquals(expectedData[1], data[1], 0.001, "Y value mismatch in event " + i); + // assertEquals(expectedData[2], data[2], 0.001, "Z value mismatch in event " + i); + // assertEquals(expectedData[3], data[3], 0.001, "T value mismatch in event " + i); + // } + // } + } // // Validate the data // float[] expectedData = EvioTestHelper.genXYZT(i); // assertEquals(expectedData[0], data[0], 0.001, "X value mismatch in event " + i); From c54583ad16c1f42f2adb537175c35134e4005281 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Fri, 27 Jun 2025 11:31:38 -0500 Subject: [PATCH 49/56] Add addHeaderRecoveryCheck() function to Java API allowing for recovering files in some cases. Will be used by JEventViewer too. --- .gitignore | 2 + .../java/org/jlab/coda/jevio/EvioReader.java | 3 + .../jlab/coda/jevio/EvioReaderUnsyncV4.java | 151 ++++++++++++------ .../jlab/coda/jevio/EvioReaderUnsyncV6.java | 13 ++ .../java/org/jlab/coda/jevio/IEvioReader.java | 6 + .../coda/jevio/dev/EvioReadFileSimple.java | 2 + .../java/EvioWriteAndReadBack_builder.java | 16 +- 7 files changed, 137 insertions(+), 56 deletions(-) diff --git a/.gitignore b/.gitignore index ab91451fc..8457866f8 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,8 @@ JEventViewer*.jar *.out.* perf.data* +# test programs to ignore +src/main/java/org/jlab/coda/jevio/dev/* # ignore generated files/dirs cmake-* diff --git a/src/main/java/org/jlab/coda/jevio/EvioReader.java b/src/main/java/org/jlab/coda/jevio/EvioReader.java index ba034970c..4bffadde7 100644 --- a/src/main/java/org/jlab/coda/jevio/EvioReader.java +++ b/src/main/java/org/jlab/coda/jevio/EvioReader.java @@ -333,6 +333,9 @@ public void setBuffer(ByteBuffer buf) throws EvioException, IOException { /** {@inheritDoc} */ public boolean checkBlockNumberSequence() {return reader.checkBlockNumberSequence();} + /** {@inheritDoc} */ + public void addHeaderRecoveryCheck() {reader.addHeaderRecoveryCheck();} + /** {@inheritDoc} */ public ByteOrder getByteOrder() {return reader.getByteOrder();} diff --git a/src/main/java/org/jlab/coda/jevio/EvioReaderUnsyncV4.java b/src/main/java/org/jlab/coda/jevio/EvioReaderUnsyncV4.java index 32784170f..580f9c920 100644 --- a/src/main/java/org/jlab/coda/jevio/EvioReaderUnsyncV4.java +++ b/src/main/java/org/jlab/coda/jevio/EvioReaderUnsyncV4.java @@ -125,6 +125,13 @@ public class EvioReaderUnsyncV4 implements IEvioReader { /** Block number expected when reading. Used to check sequence of blocks. */ protected int blockNumberExpected = 1; + /** If true, attempt header recovery when block headers aren’t where expected + * currently, having extraneous words is supported + * it doesn't handle missing header words yet (more difficult) + * also ignores lastBlock flag + */ + protected boolean doHeaderRecoveryCheck = false; + /** If true, throw an exception if block numbers are out of sequence. */ protected boolean checkBlockNumberSequence; @@ -612,6 +619,13 @@ public void setBuffer(ByteBuffer buf) throws EvioException, IOException { @Override public boolean checkBlockNumberSequence() { return checkBlockNumberSequence; } + /** Invoke to try header recovery when block headers aren’t where expected + * currently, having extraneous words is supported + * it doesn't handle missing header words yet (more difficult) + */ + @Override + public void addHeaderRecoveryCheck() {this.doHeaderRecoveryCheck=true;} + /** * Get the byte order of the file/buffer being read. * @return byte order of the file/buffer being read. @@ -971,7 +985,7 @@ protected void prepareForBufferRead(ByteBuffer buffer) { protected ReadStatus processNextBlock() throws IOException { // We already read the last block header - if (lastBlock) { + if (lastBlock && !doHeaderRecoveryCheck) { return ReadStatus.END_OF_FILE; } @@ -1023,12 +1037,65 @@ else if (bytesInBuf % 32768 == 0) { return ReadStatus.END_OF_FILE; } + long initPos = fileChannel.position(); + // Read len of block in 32 bit words int blkSize = dataStream.readInt(); if (swap) blkSize = Integer.reverseBytes(blkSize); - // Change to bytes - int blkBytes = 4 * blkSize; + // Check block size, attempt to recover if flag set + // (otherwise return exception with a hint to set flag) + // System.out.println("blkSize BEFORE = " + blkSize); + if(doHeaderRecoveryCheck && fileSize - fileChannel.position() >= 10*4) { + + int expectedMagicPos = 27; // in words + int words_to_skip = 0; // words_to_skip = foundMagicPos - expectedMagicPos + + // peek at 40 words around current position (32-bit ints, 4 bytes) + // WITHOUT changing current position + ByteBuffer peek = ByteBuffer.allocate(40*4).order(byteOrder); + // Perform positional read (does NOT move file position) + int bytesRead = fileChannel.read(peek, initPos - 20 * 4); + peek.flip(); // prepare for reading + if (bytesRead != 40 * 4) { + throw new IOException("Failed to read sufficient data for header recovery."); + } + + int foundMagicPos = -1000; // dummy val + int[] words = new int[40]; + for (int i=0; i < 40; i++) { + words[i] = peek.getInt(); + // System.out.println(" peeked word " + i + " = 0x" + Integer.toHexString(words[i])); + if(words[i] == IBlockHeader.MAGIC_NUMBER) { + foundMagicPos = i; + // System.out.println("Found magic # at pos " + foundMagicPos); + } + } + words_to_skip = foundMagicPos-expectedMagicPos; + + // It's a little more challenging to look backwards than forwards + // (since e rely on a relative read just below) + // Not sure why, but trying to reset position doesn't work + if (words_to_skip <= -1) { + System.out.println("Error: According to magic " + + "word, block header began earlier than the current file position"); + // until implemented, return exception + return ReadStatus.EVIO_EXCEPTION; + } + if (words_to_skip > 0) { + // Skip over some this many words + for (int i=0; i < (words_to_skip); i++) { + blkSize = dataStream.readInt(); + if (swap) blkSize = Integer.reverseBytes(blkSize); + } + } + blkSize+=words_to_skip; // Previous block pointed us to wrong place, + // but this will fix for future blocks + } + + // Change to bytes + int blkBytes = 4 * (blkSize); + // Enough data left to read rest of block? if (fileSize - fileChannel.position() < blkBytes-4) { return ReadStatus.END_OF_FILE; @@ -1071,55 +1138,43 @@ else if (bytesInBuf % 32768 == 0) { } if (evioVersion >= 4) { - // Read the header data. - System.out.println("GOT THIS FAR"); - - int[] words = new int[8]; - for (int i=0; i < 8; i++) { - if (byteBuffer.remaining() < 4) { - System.out.println("Remaining: " + byteBuffer.remaining() ); - return ReadStatus.END_OF_FILE; - } - System.out.println("Filling word " + i); - words[i] = byteBuffer.getInt(); - } - if(words[7] != IBlockHeader.MAGIC_NUMBER) { - System.err.println("ERROR magic # (" + words[7] + - ") != expected value " + IBlockHeader.MAGIC_NUMBER); + // Read the header data. + blockHeader4.setSize(byteBuffer.getInt()); + blockHeader4.setNumber(byteBuffer.getInt()); + blockHeader4.setHeaderLength(byteBuffer.getInt()); + blockHeader4.setEventCount(byteBuffer.getInt()); + blockHeader4.setReserved1(byteBuffer.getInt()); + // Use 6th word to set bit info + blockHeader4.parseToBitInfo(byteBuffer.getInt()); + blockHeader4.setVersion(evioVersion); + lastBlock = blockHeader4.getBitInfo(1); + blockHeader4.setReserved2(byteBuffer.getInt()); + blockHeader4.setMagicNumber(byteBuffer.getInt()); + blockHeader = blockHeader4; + + // System.out.println("BlockHeader v4:"); + // System.out.println(" block length = " + blockHeader4.getSize()); + // System.out.println(" block number = " + blockHeader4.getNumber()); + // System.out.println(" header length = " + blockHeader4.getHeaderLength()); + // System.out.println(" event count = " + blockHeader4.getEventCount()); + // System.out.println(" version = " + blockHeader4.getVersion()); + // System.out.println(" has Dict = " + blockHeader4.getBitInfo(0)); + // System.out.println(" is End = " + lastBlock); + + // Deal with non-standard header lengths here + int headerLenDiff = blockHeader4.getHeaderLength() - BlockHeaderV4.HEADER_SIZE; + // If too small quit with error since headers have a minimum size + if (headerLenDiff < 0) { return ReadStatus.EVIO_EXCEPTION; } - else { - System.out.println("Magic word is correct"); - return ReadStatus.EVIO_EXCEPTION; + // If bigger, read extra ints + else if (headerLenDiff > 0) { + for (int i=0; i < headerLenDiff; i++) { + byteBuffer.getInt(); + } } - // blockHeader4.setSize(words[0]); - // blockHeader4.setNumber(words[1]); - // blockHeader4.setHeaderLength(words[2]); - // blockHeader4.setEventCount(words[3]); - // blockHeader4.setReserved1(words[4]); - // // Use 6th word to set bit info - // blockHeader4.parseToBitInfo(words[5]); - // blockHeader4.setVersion(evioVersion); - // lastBlock = blockHeader4.getBitInfo(1); - // blockHeader4.setReserved2(words[6]); - // blockHeader4.setMagicNumber(words[7]); - // blockHeader = blockHeader4; - - - // // Deal with non-standard header lengths here - // int headerLenDiff = blockHeader4.getHeaderLength() - BlockHeaderV4.HEADER_SIZE; - // // If too small quit with error since headers have a minimum size - // if (headerLenDiff < 0) { - // return ReadStatus.EVIO_EXCEPTION; - // } - // // If bigger, read extra ints - // else if (headerLenDiff > 0) { - // for (int i=0; i < headerLenDiff; i++) { - // byteBuffer.getInt(); - // } - // } } else if (evioVersion < 4) { // read the header data @@ -1156,7 +1211,7 @@ else if (evioVersion < 4) { return ReadStatus.EVIO_EXCEPTION; } catch (BufferUnderflowException a) { -System.err.println("ERROR endOfBuffer " + a); + System.err.println("ERROR endOfBuffer " + a); byteBuffer.clear(); return ReadStatus.UNKNOWN_ERROR; } diff --git a/src/main/java/org/jlab/coda/jevio/EvioReaderUnsyncV6.java b/src/main/java/org/jlab/coda/jevio/EvioReaderUnsyncV6.java index f93155c33..c8780e9bf 100644 --- a/src/main/java/org/jlab/coda/jevio/EvioReaderUnsyncV6.java +++ b/src/main/java/org/jlab/coda/jevio/EvioReaderUnsyncV6.java @@ -61,6 +61,12 @@ public class EvioReaderUnsyncV6 implements IEvioReader { /** Parser object for file/buffer. */ protected EventParser parser; + /** If true, attempt header recovery when block headers aren’t where expected + * currently, having extraneous words is supported + * it doesn't handle missing header words yet (more difficult) + */ + protected boolean doHeaderRecoveryCheck = false; + //------------------------ @@ -209,6 +215,13 @@ public void setBuffer(ByteBuffer buf) throws EvioException, IOException { @Override public boolean checkBlockNumberSequence() {return reader.getCheckRecordNumberSequence();} + /** Invoke to try header recovery when block headers aren’t where expected + * currently, having extraneous words is supported + * it doesn't handle missing header words yet (more difficult) + */ + @Override + public void addHeaderRecoveryCheck() {this.doHeaderRecoveryCheck=true;} + /** {@inheritDoc} */ @Override public ByteOrder getByteOrder() {return reader.getByteOrder();} diff --git a/src/main/java/org/jlab/coda/jevio/IEvioReader.java b/src/main/java/org/jlab/coda/jevio/IEvioReader.java index 93d2b2bfc..e22c0c129 100644 --- a/src/main/java/org/jlab/coda/jevio/IEvioReader.java +++ b/src/main/java/org/jlab/coda/jevio/IEvioReader.java @@ -39,6 +39,12 @@ public interface IEvioReader { */ boolean checkBlockNumberSequence(); + /** Invoke to try header recovery when block headers aren’t where expected + * currently, having extraneous words is supported + * it doesn't handle missing header words yet (more difficult) + */ + void addHeaderRecoveryCheck(); + /** * Get the byte order of the file/buffer being read. * @return byte order of the file/buffer being read. diff --git a/src/main/java/org/jlab/coda/jevio/dev/EvioReadFileSimple.java b/src/main/java/org/jlab/coda/jevio/dev/EvioReadFileSimple.java index 59b000816..87ad6b312 100644 --- a/src/main/java/org/jlab/coda/jevio/dev/EvioReadFileSimple.java +++ b/src/main/java/org/jlab/coda/jevio/dev/EvioReadFileSimple.java @@ -31,8 +31,10 @@ public static void main(String[] args) { try { EvioReader reader = new EvioReader(filename); + reader.addHeaderRecoveryCheck(); int evCount = reader.getEventCount(); + System.out.println("Number of events in file: " + evCount); reader.close(); } catch (EvioException | IOException e) { diff --git a/src/test/java/EvioWriteAndReadBack_builder.java b/src/test/java/EvioWriteAndReadBack_builder.java index dfd6df8ce..ebf1466f7 100644 --- a/src/test/java/EvioWriteAndReadBack_builder.java +++ b/src/test/java/EvioWriteAndReadBack_builder.java @@ -111,13 +111,13 @@ void evioReadStep(int nEvents) throws IOException, EvioException { // } reader.rewind(); // Rewind to the beginning of the file - for (int i = 0; i < eventsToCheck; i++) { - EvioEvent ev = reader.parseNextEvent(); - byte[] byteData = ev.getByteData(); - System.out.println("First ev size = " + ev.getTotalBytes() + " bytes"); - System.out.println(" Event # " + i + " length = " + byteData.length + " ints"); - Utilities.printBytes(byteData, 0, byteData.length, " Event #" + i); - } + // for (int i = 0; i < eventsToCheck; i++) { + // EvioEvent ev = reader.parseNextEvent(); + // byte[] byteData = ev.getByteData(); + // System.out.println("First ev size = " + ev.getTotalBytes() + " bytes"); + // // System.out.println(" Event # " + i + " length = " + byteData.length + " ints"); + // Utilities.printBytes(byteData, 0, byteData.length, " Event #" + i); + // } @@ -161,7 +161,7 @@ void evioReadStep(int nEvents) throws IOException, EvioException { // assertEquals(expectedData[3], data[3], 0.001, "T value mismatch in event " + i); // } // } - } + // } // // Validate the data // float[] expectedData = EvioTestHelper.genXYZT(i); // assertEquals(expectedData[0], data[0], 0.001, "X value mismatch in event " + i); From 943a7cb725306e5e6baebef0ac96002c3d65200f Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Mon, 7 Jul 2025 11:04:23 -0500 Subject: [PATCH 50/56] More cleanup and typos, getting ready for next version release --- etc/README.md | 6 +++--- .../jlab/coda/hipo/test => src/test/java/hipo}/README.md | 0 .../hipo/test => src/test/java/hipo}/ReadWriteTest.java | 0 .../test => src/test/java/hipo}/RecordSupplyTester.java | 0 .../coda/hipo/test => src/test/java/hipo}/TestBuilding.java | 0 .../coda/hipo/test => src/test/java/hipo}/TestWriter.java | 0 .../jevio/test => src/test/java/jevio}/BigFileWrite.java | 0 .../test/java/jevio}/CompactReaderAddSubtractTest.java | 0 .../test => src/test/java/jevio}/CompactReaderBugTest.java | 0 .../test/java/jevio}/CompactStructureHandlerTest.java | 0 .../jevio/test => src/test/java/jevio}/CompositeTester.java | 0 .../jevio/test => src/test/java/jevio}/CompressionTest.java | 0 .../coda/jevio/test => src/test/java/jevio}/DictTest.java | 0 .../test => src/test/java/jevio}/ExtractHallDdata.java | 0 .../coda/jevio/test => src/test/java/jevio}/FileTest.java | 0 .../jevio/test => src/test/java/jevio}/FileTestVer6.java | 0 .../jevio/test => src/test/java/jevio}/FileWriteTest.java | 0 .../test => src/test/java/jevio}/FileWritingSpeedTest.java | 0 .../jevio/test => src/test/java/jevio}/FirstEventTest.java | 0 .../coda/jevio/test => src/test/java/jevio}/HipoTest.java | 0 .../jlab/coda/jevio/test => src/test/java/jevio}/README.md | 0 .../jevio/test => src/test/java/jevio}/ReadAggOutput.java | 0 .../test => src/test/java/jevio}/ReadSequenceTest.java | 0 .../jevio/test => src/test/java/jevio}/ReadWriteTest.java | 0 .../jevio/test => src/test/java/jevio}/ReadWriteV4Test.java | 0 .../test => src/test/java/jevio}/RecordSupplyTest.java | 0 .../test => src/test/java/jevio}/SequentialReaderTest.java | 0 .../coda/jevio/test => src/test/java/jevio}/SplitTest.java | 0 .../coda/jevio/test => src/test/java/jevio}/SwapTest.java | 0 .../coda/jevio/test => src/test/java/jevio}/TestBase.java | 0 .../jevio/test => src/test/java/jevio}/TreeBufTest.java | 0 .../coda/jevio/test => src/test/java/jevio}/XmlTest.java | 0 src/README.md | 2 +- .../coda/jevio/unit_tests => test/java}/EvioTestHelper.java | 3 +-- src/test/java/EvioWriteAndReadBack_builder.java | 1 - 35 files changed, 5 insertions(+), 7 deletions(-) rename etc/{java/org/jlab/coda/hipo/test => src/test/java/hipo}/README.md (100%) rename etc/{java/org/jlab/coda/hipo/test => src/test/java/hipo}/ReadWriteTest.java (100%) rename etc/{java/org/jlab/coda/hipo/test => src/test/java/hipo}/RecordSupplyTester.java (100%) rename etc/{java/org/jlab/coda/hipo/test => src/test/java/hipo}/TestBuilding.java (100%) rename etc/{java/org/jlab/coda/hipo/test => src/test/java/hipo}/TestWriter.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/BigFileWrite.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/CompactReaderAddSubtractTest.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/CompactReaderBugTest.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/CompactStructureHandlerTest.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/CompositeTester.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/CompressionTest.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/DictTest.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/ExtractHallDdata.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/FileTest.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/FileTestVer6.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/FileWriteTest.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/FileWritingSpeedTest.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/FirstEventTest.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/HipoTest.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/README.md (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/ReadAggOutput.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/ReadSequenceTest.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/ReadWriteTest.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/ReadWriteV4Test.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/RecordSupplyTest.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/SequentialReaderTest.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/SplitTest.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/SwapTest.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/TestBase.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/TreeBufTest.java (100%) rename etc/{java/org/jlab/coda/jevio/test => src/test/java/jevio}/XmlTest.java (100%) rename src/{main/java/org/jlab/coda/jevio/unit_tests => test/java}/EvioTestHelper.java (98%) diff --git a/etc/README.md b/etc/README.md index 29f496203..f131cad18 100644 --- a/etc/README.md +++ b/etc/README.md @@ -1,11 +1,11 @@ # **Miscellaneous folder** -This folder collects old scripts, documentation, and files from evio versions 1-5. +This folder collects old scripts, documentation, and other misc files from evio versions 1-5. | File/Folder | Description |------------|---------------------------------------------------------------------- -| [java](java) | Collection of Java test programs, Xml2evio program, old jar dependency files, and ant build xml. | -| [src](src) | Collection of C/C++ programs from previous evio versions | +| [java](java) | Collection of Java resources, Xml2evio program, old jar dependency files, and ant build xml. | +| [src](src) | Collection of Java, C/C++ library code. Essentially, these are all old test programs. | | [CHANGES](CHANGES) | Change log for evio versions 4-5 | | [cmake_uninstall.cmake.in](cmake_uninstall.cmake.in) | Uninstallation script for evio-5 | | [setup_java](setup_java) | Setup script for choosing java version (either Java 8 or 15). | diff --git a/etc/java/org/jlab/coda/hipo/test/README.md b/etc/src/test/java/hipo/README.md similarity index 100% rename from etc/java/org/jlab/coda/hipo/test/README.md rename to etc/src/test/java/hipo/README.md diff --git a/etc/java/org/jlab/coda/hipo/test/ReadWriteTest.java b/etc/src/test/java/hipo/ReadWriteTest.java similarity index 100% rename from etc/java/org/jlab/coda/hipo/test/ReadWriteTest.java rename to etc/src/test/java/hipo/ReadWriteTest.java diff --git a/etc/java/org/jlab/coda/hipo/test/RecordSupplyTester.java b/etc/src/test/java/hipo/RecordSupplyTester.java similarity index 100% rename from etc/java/org/jlab/coda/hipo/test/RecordSupplyTester.java rename to etc/src/test/java/hipo/RecordSupplyTester.java diff --git a/etc/java/org/jlab/coda/hipo/test/TestBuilding.java b/etc/src/test/java/hipo/TestBuilding.java similarity index 100% rename from etc/java/org/jlab/coda/hipo/test/TestBuilding.java rename to etc/src/test/java/hipo/TestBuilding.java diff --git a/etc/java/org/jlab/coda/hipo/test/TestWriter.java b/etc/src/test/java/hipo/TestWriter.java similarity index 100% rename from etc/java/org/jlab/coda/hipo/test/TestWriter.java rename to etc/src/test/java/hipo/TestWriter.java diff --git a/etc/java/org/jlab/coda/jevio/test/BigFileWrite.java b/etc/src/test/java/jevio/BigFileWrite.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/BigFileWrite.java rename to etc/src/test/java/jevio/BigFileWrite.java diff --git a/etc/java/org/jlab/coda/jevio/test/CompactReaderAddSubtractTest.java b/etc/src/test/java/jevio/CompactReaderAddSubtractTest.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/CompactReaderAddSubtractTest.java rename to etc/src/test/java/jevio/CompactReaderAddSubtractTest.java diff --git a/etc/java/org/jlab/coda/jevio/test/CompactReaderBugTest.java b/etc/src/test/java/jevio/CompactReaderBugTest.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/CompactReaderBugTest.java rename to etc/src/test/java/jevio/CompactReaderBugTest.java diff --git a/etc/java/org/jlab/coda/jevio/test/CompactStructureHandlerTest.java b/etc/src/test/java/jevio/CompactStructureHandlerTest.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/CompactStructureHandlerTest.java rename to etc/src/test/java/jevio/CompactStructureHandlerTest.java diff --git a/etc/java/org/jlab/coda/jevio/test/CompositeTester.java b/etc/src/test/java/jevio/CompositeTester.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/CompositeTester.java rename to etc/src/test/java/jevio/CompositeTester.java diff --git a/etc/java/org/jlab/coda/jevio/test/CompressionTest.java b/etc/src/test/java/jevio/CompressionTest.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/CompressionTest.java rename to etc/src/test/java/jevio/CompressionTest.java diff --git a/etc/java/org/jlab/coda/jevio/test/DictTest.java b/etc/src/test/java/jevio/DictTest.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/DictTest.java rename to etc/src/test/java/jevio/DictTest.java diff --git a/etc/java/org/jlab/coda/jevio/test/ExtractHallDdata.java b/etc/src/test/java/jevio/ExtractHallDdata.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/ExtractHallDdata.java rename to etc/src/test/java/jevio/ExtractHallDdata.java diff --git a/etc/java/org/jlab/coda/jevio/test/FileTest.java b/etc/src/test/java/jevio/FileTest.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/FileTest.java rename to etc/src/test/java/jevio/FileTest.java diff --git a/etc/java/org/jlab/coda/jevio/test/FileTestVer6.java b/etc/src/test/java/jevio/FileTestVer6.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/FileTestVer6.java rename to etc/src/test/java/jevio/FileTestVer6.java diff --git a/etc/java/org/jlab/coda/jevio/test/FileWriteTest.java b/etc/src/test/java/jevio/FileWriteTest.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/FileWriteTest.java rename to etc/src/test/java/jevio/FileWriteTest.java diff --git a/etc/java/org/jlab/coda/jevio/test/FileWritingSpeedTest.java b/etc/src/test/java/jevio/FileWritingSpeedTest.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/FileWritingSpeedTest.java rename to etc/src/test/java/jevio/FileWritingSpeedTest.java diff --git a/etc/java/org/jlab/coda/jevio/test/FirstEventTest.java b/etc/src/test/java/jevio/FirstEventTest.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/FirstEventTest.java rename to etc/src/test/java/jevio/FirstEventTest.java diff --git a/etc/java/org/jlab/coda/jevio/test/HipoTest.java b/etc/src/test/java/jevio/HipoTest.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/HipoTest.java rename to etc/src/test/java/jevio/HipoTest.java diff --git a/etc/java/org/jlab/coda/jevio/test/README.md b/etc/src/test/java/jevio/README.md similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/README.md rename to etc/src/test/java/jevio/README.md diff --git a/etc/java/org/jlab/coda/jevio/test/ReadAggOutput.java b/etc/src/test/java/jevio/ReadAggOutput.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/ReadAggOutput.java rename to etc/src/test/java/jevio/ReadAggOutput.java diff --git a/etc/java/org/jlab/coda/jevio/test/ReadSequenceTest.java b/etc/src/test/java/jevio/ReadSequenceTest.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/ReadSequenceTest.java rename to etc/src/test/java/jevio/ReadSequenceTest.java diff --git a/etc/java/org/jlab/coda/jevio/test/ReadWriteTest.java b/etc/src/test/java/jevio/ReadWriteTest.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/ReadWriteTest.java rename to etc/src/test/java/jevio/ReadWriteTest.java diff --git a/etc/java/org/jlab/coda/jevio/test/ReadWriteV4Test.java b/etc/src/test/java/jevio/ReadWriteV4Test.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/ReadWriteV4Test.java rename to etc/src/test/java/jevio/ReadWriteV4Test.java diff --git a/etc/java/org/jlab/coda/jevio/test/RecordSupplyTest.java b/etc/src/test/java/jevio/RecordSupplyTest.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/RecordSupplyTest.java rename to etc/src/test/java/jevio/RecordSupplyTest.java diff --git a/etc/java/org/jlab/coda/jevio/test/SequentialReaderTest.java b/etc/src/test/java/jevio/SequentialReaderTest.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/SequentialReaderTest.java rename to etc/src/test/java/jevio/SequentialReaderTest.java diff --git a/etc/java/org/jlab/coda/jevio/test/SplitTest.java b/etc/src/test/java/jevio/SplitTest.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/SplitTest.java rename to etc/src/test/java/jevio/SplitTest.java diff --git a/etc/java/org/jlab/coda/jevio/test/SwapTest.java b/etc/src/test/java/jevio/SwapTest.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/SwapTest.java rename to etc/src/test/java/jevio/SwapTest.java diff --git a/etc/java/org/jlab/coda/jevio/test/TestBase.java b/etc/src/test/java/jevio/TestBase.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/TestBase.java rename to etc/src/test/java/jevio/TestBase.java diff --git a/etc/java/org/jlab/coda/jevio/test/TreeBufTest.java b/etc/src/test/java/jevio/TreeBufTest.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/TreeBufTest.java rename to etc/src/test/java/jevio/TreeBufTest.java diff --git a/etc/java/org/jlab/coda/jevio/test/XmlTest.java b/etc/src/test/java/jevio/XmlTest.java similarity index 100% rename from etc/java/org/jlab/coda/jevio/test/XmlTest.java rename to etc/src/test/java/jevio/XmlTest.java diff --git a/src/README.md b/src/README.md index 298a3ff5e..f99503b21 100644 --- a/src/README.md +++ b/src/README.md @@ -5,5 +5,5 @@ | [libsrc](libsrc) | EVIO C library | | [libsrc++](libsrc++) | EVIO C++ library | | [main/java](main/java) | EVIO Java Library | -| [test](test) | For internal testing of Java, C, C libraries. | +| [test](test) | For internal testing of Java, C, C++ libraries. | diff --git a/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java b/src/test/java/EvioTestHelper.java similarity index 98% rename from src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java rename to src/test/java/EvioTestHelper.java index d0371aeeb..26dde7a5b 100644 --- a/src/main/java/org/jlab/coda/jevio/unit_tests/EvioTestHelper.java +++ b/src/test/java/EvioTestHelper.java @@ -1,4 +1,4 @@ -package org.jlab.coda.jevio.unit_tests; + import java.util.Random; import java.nio.ByteOrder; @@ -10,7 +10,6 @@ public class EvioTestHelper { private final Random random; // Parameters (simplified here for brevity) - // apparently all files must have absolute paths!!!!! public static String baseNameV4 = "testEventsV4_javaAPI.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. public static String baseNameV6 = "testEventsV6_javaAPI.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. public static String baseNameHIPO = "testEventsHIPO_javaAPI.hipo"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. diff --git a/src/test/java/EvioWriteAndReadBack_builder.java b/src/test/java/EvioWriteAndReadBack_builder.java index ebf1466f7..1be3af390 100644 --- a/src/test/java/EvioWriteAndReadBack_builder.java +++ b/src/test/java/EvioWriteAndReadBack_builder.java @@ -14,7 +14,6 @@ import java.io.*; import org.jlab.coda.jevio.*; -import org.jlab.coda.jevio.unit_tests.EvioTestHelper; // helper class for unit tests, also contained in java src files @Tag("fast") // Run when selecting "fast" category of tests From fc6707765ae159d241a19de763d56865dc302a12 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Mon, 7 Jul 2025 11:41:24 -0500 Subject: [PATCH 51/56] Revert spacings back to old file; prevent (deceptively) large diff --- src/libsrc++/EvioReaderV4.cpp | 1128 ++++++++++++++------------------- 1 file changed, 465 insertions(+), 663 deletions(-) diff --git a/src/libsrc++/EvioReaderV4.cpp b/src/libsrc++/EvioReaderV4.cpp index 34685c5f2..9a2d207fe 100644 --- a/src/libsrc++/EvioReaderV4.cpp +++ b/src/libsrc++/EvioReaderV4.cpp @@ -7,70 +7,66 @@ // 12000, Jefferson Ave, Newport News, VA 23606 // (757)-269-7100 + + #include "EvioReaderV4.h" -namespace evio -{ +namespace evio { /** * This method saves the current state of this EvioReader object. * @return the current state of this EvioReader object. */ - EvioReaderV4::ReaderState *EvioReaderV4::getState() - { - auto *currentState = new ReaderState(); - currentState->lastBlock = lastBlock; + EvioReaderV4::ReaderState * EvioReaderV4::getState() { + auto * currentState = new ReaderState(); + currentState->lastBlock = lastBlock; currentState->eventNumber = eventNumber; currentState->blockNumberExpected = blockNumberExpected; - if (sequentialRead) - { + if (sequentialRead) { currentState->filePosition = file.tellg(); } currentState->byteBufferLimit = byteBuffer->limit(); currentState->byteBufferPosition = byteBuffer->position(); - if (evioVersion > 3) - { + if (evioVersion > 3) { currentState->blockHeader4 = blockHeader4; } - else - { + else { currentState->blockHeader2 = blockHeader2; } return currentState; } + /** * This method restores a previously saved state of this EvioReader object. * @param state a previously stored state of this EvioReader object. */ - void EvioReaderV4::restoreState(ReaderState *state) - { - lastBlock = state->lastBlock; + void EvioReaderV4::restoreState(ReaderState * state) { + lastBlock = state->lastBlock; eventNumber = state->eventNumber; blockNumberExpected = state->blockNumberExpected; - if (sequentialRead) - { + if (sequentialRead) { file.seekg(state->filePosition); } byteBuffer->limit(state->byteBufferLimit); byteBuffer->position(state->byteBufferPosition); - if (evioVersion > 3) - { + if (evioVersion > 3) { blockHeader = blockHeader4 = state->blockHeader4; } - else - { + else { blockHeader = blockHeader2 = state->blockHeader2; } } + //------------------------ + /** * Constructor for reading an event file. * Do not set sequential to false for remote files. @@ -85,11 +81,9 @@ namespace evio * @throws EvioException if file arg is null; if read failure; * if first block number != 1 when checkBlkNumSeq arg is true */ - EvioReaderV4::EvioReaderV4(std::string const &path, bool checkBlkNumSeq, bool synced) - { + EvioReaderV4::EvioReaderV4(std::string const & path, bool checkBlkNumSeq, bool synced) { - if (path.empty()) - { + if (path.empty()) { throw EvioException("path is empty"); } @@ -100,8 +94,7 @@ namespace evio // Go back to beginning of file file.seekg(0); - if (fileBytes < 40) - { + if (fileBytes < 40) { throw EvioException("File too small to have valid evio data"); } @@ -112,6 +105,7 @@ namespace evio blockHeader4 = std::make_shared(); blockHeader2 = std::make_shared(); + // Look at the first block header to get various info like endianness and version. // Store it for later reference in blockHeader2,4 and in other variables. @@ -122,8 +116,7 @@ namespace evio // Read 32 bytes of file's first block header file.read(reinterpret_cast(headerBytes), bytesToRead); - if (file.fail()) - { + if (file.fail()) { throw EvioException("I/O error reading file"); } @@ -136,21 +129,17 @@ namespace evio // Do not use memory mapping as the Java version did. // Since evio data files tend to be large (> 2GB), memory mapping // can be slower than conventional reads. - if (evioVersion < 4) - { + if (evioVersion < 4) { // Remember, no dictionaries exist for these early versions - prepareForSequentialRead(); + prepareForSequentialRead(); } // For version 4 ... - else - { + else { prepareForSequentialRead(); - if (blockHeader4->hasDictionary()) - { + if (blockHeader4->hasDictionary()) { // Dictionary is always the first event auto dict = parseNextEvent(); - if (dict != nullptr) - { + if (dict != nullptr) { auto strs = dict->getStringData(); dictionaryXML = strs[0]; } @@ -158,6 +147,7 @@ namespace evio } } + /** * Constructor for reading a buffer. * @@ -170,8 +160,7 @@ namespace evio * @throws EvioException if buffer arg is null; * if first block number != 1 when checkBlkNumSeq arg is true */ - EvioReaderV4::EvioReaderV4(std::shared_ptr bb, bool checkBlkNumSeq, bool synced) - { + EvioReaderV4::EvioReaderV4(std::shared_ptr bb, bool checkBlkNumSeq, bool synced) { checkBlockNumSeq = checkBlkNumSeq; synchronized = synced; @@ -188,29 +177,27 @@ namespace evio // For the latest evio format, generate a table // of all event positions in buffer for random access. - if (evioVersion > 3) - { - // std::cout << "EvioReaderV4 const: evioVersion = " << evioVersion << ", generate event positions" << std::endl; + if (evioVersion > 3) { +//std::cout << "EvioReaderV4 const: evioVersion = " << evioVersion << ", generate event positions" << std::endl; generateEventPositions(byteBuffer); - if (blockHeader4->hasDictionary()) - { + if (blockHeader4->hasDictionary()) { // Jump to the first event prepareForBufferRead(byteBuffer); // Dictionary is the first event readDictionary(byteBuffer); } } - else - { + else { // Setting the byte order is only necessary if someone hands // this method a buffer in which the byte order is improperly set. byteBuffer->order(byteOrder); prepareForBufferRead(byteBuffer); } - parser = std::make_shared(); + parser = std::make_shared(); } + /** * Generate a table (vector) of positions of events in file/buffer. * This method does not affect the byteBuffer position, eventNumber, @@ -222,182 +209,165 @@ namespace evio * contained in the given byte buffer. * @throws EvioException if bad file format */ - size_t EvioReaderV4::generateEventPositions(std::shared_ptr bb) - { - - uint32_t blockSize, blockHdrSize, blockEventCount, magicNum; - uint32_t byteInfo, byteLen, bytesLeft, position; - bool firstBlock = true, hasDictionary = false; - // bool curLastBlock; - - // In Java evio, setting eventCount from its initial value of -1 is done in MappeMemoryHandler.java, - // but in C++ that does not exist so we set it here. - if (eventCount < 0) - { - eventCount = 0; - } - - eventPositions.reserve(20000); - - // Start at the beginning of byteBuffer - position = 0; - bytesLeft = bb->limit(); - - while (bytesLeft > 0) - { - // Check to see if enough data to read block header. - // If not return the amount of memory we've used/read. - if (bytesLeft < 32) - { - // std::cout << " genEvTablePos: return, not enough to read header, bytes left = " << bytesLeft << std::endl; - return position; - } + size_t EvioReaderV4::generateEventPositions(std::shared_ptr bb) { - // File is now positioned before block header. - // Look at block header to get info. Swapping is taken care of - byteInfo = bb->getUInt(position + 4 * BlockHeaderV4::EV_VERSION); - blockSize = bb->getUInt(position + 4 * BlockHeaderV4::EV_BLOCKSIZE); - blockHdrSize = bb->getUInt(position + 4 * BlockHeaderV4::EV_HEADERSIZE); - blockEventCount = bb->getUInt(position + 4 * BlockHeaderV4::EV_COUNT); - magicNum = bb->getUInt(position + 4 * BlockHeaderV4::EV_MAGIC); - - // std::cout << " genEvTablePos: pos " << position << - // ", blk ev count = " << blockEventCount << - // ", blockSize = " << blockSize << - // ", blockHdrSize = " << blockHdrSize << std::showbase << - // ", byteInfo = " << std::hex << byteInfo << - // ", magic # = " << magicNum << std::dec << std::endl; - - // If magic # is not right, file is not in proper format - if (magicNum != BlockHeaderV4::MAGIC_NUMBER) - { - throw EvioException("Bad evio format: block header magic # incorrect"); - } + uint32_t blockSize, blockHdrSize, blockEventCount, magicNum; + uint32_t byteInfo, byteLen, bytesLeft, position; + bool firstBlock=true, hasDictionary=false; +// bool curLastBlock; - // Check lengths in block header - if (blockSize < 8 || blockHdrSize < 8) - { - throw EvioException("Bad evio format: (block: total len = " + std::to_string(blockSize) + - ", header len = " + std::to_string(blockHdrSize) + ")"); + // In Java evio, setting eventCount from its initial value of -1 is done in MappeMemoryHandler.java, + // but in C++ that does not exist so we set it here. + if (eventCount < 0) { + eventCount = 0; } - // Check to see if the whole block is within the mapped memory. - // If not return the amount of memory we've used/read. - if (4 * blockSize > bytesLeft) - { - // std::cout << " 4*blockSize = " << std::to_string(4*blockSize) + " >? bytesLeft = " << - // std::to_string(bytesLeft) + ", pos = " + std::to_string(position) << std::endl; - // std::cout << " return, not enough to read all block data" << std::endl; - return position; - } + eventPositions.reserve(20000); - blockCount++; - // curLastBlock = BlockHeaderV4.isLastBlock(byteInfo); - if (firstBlock) - { - hasDictionary = BlockHeaderV4::hasDictionary(byteInfo); - } + // Start at the beginning of byteBuffer + position = 0; + bytesLeft = bb->limit(); - // std::cout << " genEvTablePos: blk count = " << blockCount << - // ", total ev count = " << (eventCount + blockEventCount) << - // "\n firstBlock = " << firstBlock << - // /* ", isLastBlock = " + curLastBlock + */ - // ", hasDict = " << hasDictionary << - // ", pos = " << position << std::endl; - - // Hop over block header to data - position += 4 * blockHdrSize; - bytesLeft -= 4 * blockHdrSize; - - // std::cout << " hopped blk hdr, bytesLeft = " << bytesLeft << ", pos = " << position << std::endl; - - // Check for a dictionary - the first event in the first block. - // It's not included in the header block count, but we must take - // it into account by skipping over it. - if (firstBlock && hasDictionary) - { - // Get its length - bank's len does not include itself - byteLen = 4 * (bb->getUInt(position) + 1); - - if (byteLen < 4) - { - throw EvioException("Bad evio format: bad bank length"); + while (bytesLeft > 0) { + // Check to see if enough data to read block header. + // If not return the amount of memory we've used/read. + if (bytesLeft < 32) { +//std::cout << " genEvTablePos: return, not enough to read header, bytes left = " << bytesLeft << std::endl; + return position; } - // Skip over dictionary - position += byteLen; - bytesLeft -= byteLen; - // std::cout << " hopped dict, dic bytes = " << byteLen << ", bytesLeft = " << - // bytesLeft << ", pos = " << position << std::endl; - } + // File is now positioned before block header. + // Look at block header to get info. Swapping is taken care of + byteInfo = bb->getUInt(position + 4*BlockHeaderV4::EV_VERSION); + blockSize = bb->getUInt(position + 4*BlockHeaderV4::EV_BLOCKSIZE); + blockHdrSize = bb->getUInt(position + 4*BlockHeaderV4::EV_HEADERSIZE); + blockEventCount = bb->getUInt(position + 4*BlockHeaderV4::EV_COUNT); + magicNum = bb->getUInt(position + 4*BlockHeaderV4::EV_MAGIC); + +// std::cout << " genEvTablePos: pos " << position << +// ", blk ev count = " << blockEventCount << +// ", blockSize = " << blockSize << +// ", blockHdrSize = " << blockHdrSize << std::showbase << +// ", byteInfo = " << std::hex << byteInfo << +// ", magic # = " << magicNum << std::dec << std::endl; + + // If magic # is not right, file is not in proper format + if (magicNum != BlockHeaderV4::MAGIC_NUMBER) { + throw EvioException("Bad evio format: block header magic # incorrect"); + } - firstBlock = false; + // Check lengths in block header + if (blockSize < 8 || blockHdrSize < 8) { + throw EvioException("Bad evio format: (block: total len = " + std::to_string(blockSize) + + ", header len = " + std::to_string(blockHdrSize) + ")" ); + } - // For each event in block, store its location - for (uint32_t i = 0; i < blockEventCount; i++) - { - // Sanity check - must have at least 1 header's amount left - if (bytesLeft < 8) - { - throw EvioException("Bad evio format: not enough data to read event (bad bank len?)"); + // Check to see if the whole block is within the mapped memory. + // If not return the amount of memory we've used/read. + if (4*blockSize > bytesLeft) { +//std::cout << " 4*blockSize = " << std::to_string(4*blockSize) + " >? bytesLeft = " << +// std::to_string(bytesLeft) + ", pos = " + std::to_string(position) << std::endl; +//std::cout << " return, not enough to read all block data" << std::endl; + return position; } - // Get length of current event (including full header) - byteLen = 4 * (bb->getInt(position) + 1); - if (byteLen < 4 || bytesLeft < byteLen) - { - throw EvioException("Bad evio format: bad bank length"); + blockCount++; +// curLastBlock = BlockHeaderV4.isLastBlock(byteInfo); + if (firstBlock) { + hasDictionary = BlockHeaderV4::hasDictionary(byteInfo); + } + +//std::cout << " genEvTablePos: blk count = " << blockCount << +// ", total ev count = " << (eventCount + blockEventCount) << +// "\n firstBlock = " << firstBlock << +// /* ", isLastBlock = " + curLastBlock + */ +// ", hasDict = " << hasDictionary << +// ", pos = " << position << std::endl; + + // Hop over block header to data + position += 4*blockHdrSize; + bytesLeft -= 4*blockHdrSize; + +//std::cout << " hopped blk hdr, bytesLeft = " << bytesLeft << ", pos = " << position << std::endl; + + // Check for a dictionary - the first event in the first block. + // It's not included in the header block count, but we must take + // it into account by skipping over it. + if (firstBlock && hasDictionary) { + // Get its length - bank's len does not include itself + byteLen = 4*(bb->getUInt(position) + 1); + + if (byteLen < 4) { + throw EvioException("Bad evio format: bad bank length"); + } + + // Skip over dictionary + position += byteLen; + bytesLeft -= byteLen; +//std::cout << " hopped dict, dic bytes = " << byteLen << ", bytesLeft = " << +// bytesLeft << ", pos = " << position << std::endl; } - bytesLeft -= byteLen; - // Store current position - eventPositions.push_back(position); - eventCount++; + firstBlock = false; + + // For each event in block, store its location + for (uint32_t i=0; i < blockEventCount; i++) { + // Sanity check - must have at least 1 header's amount left + if (bytesLeft < 8) { + throw EvioException("Bad evio format: not enough data to read event (bad bank len?)"); + } + + // Get length of current event (including full header) + byteLen = 4*(bb->getInt(position) + 1); + if (byteLen < 4 || bytesLeft < byteLen) { + throw EvioException("Bad evio format: bad bank length"); + } + bytesLeft -= byteLen; + + // Store current position + eventPositions.push_back(position); + eventCount++; - position += byteLen; - // std::cout << " hopped event " << (i+1) << ", bytesLeft = " << bytesLeft << ", pos = " << position << std::endl; + position += byteLen; +//std::cout << " hopped event " << (i+1) << ", bytesLeft = " << bytesLeft << ", pos = " << position << std::endl; + } } - } - return position; + return position; } + /** {@inheritDoc} */ - void EvioReaderV4::setBuffer(std::shared_ptr buf) - { + void EvioReaderV4::setBuffer(std::shared_ptr buf) { close(); - if (buf == nullptr) - { + if (buf == nullptr) { throw EvioException("null buf arg"); } - lastBlock = false; - eventNumber = 0; - blockCount = 0; - eventCount = -1; - blockNumberExpected = 1; - dictionaryXML = ""; - initialPosition = buf->position(); - sequentialRead = false; + lastBlock = false; + eventNumber = 0; + blockCount = 0; + eventCount = -1; + blockNumberExpected = 1; + dictionaryXML = ""; + initialPosition = buf->position(); + sequentialRead = false; byteBuffer = buf->slice(); parseFirstHeader(byteBuffer); byteBuffer->position(0); - if (evioVersion > 3) - { + if (evioVersion > 3) { generateEventPositions(byteBuffer); - if (blockHeader4->hasDictionary()) - { + if (blockHeader4->hasDictionary()) { // Jump to the first event prepareForBufferRead(byteBuffer); // Dictionary is the first event readDictionary(byteBuffer); } } - else - { + else { byteBuffer->order(byteOrder); prepareForBufferRead(byteBuffer); } @@ -405,55 +375,64 @@ namespace evio closed = false; } + /** {@inheritDoc} */ - bool EvioReaderV4::isClosed() { return closed; } + bool EvioReaderV4::isClosed() {return closed;} + /** {@inheritDoc} */ - bool EvioReaderV4::checkBlockNumberSequence() { return checkBlockNumSeq; } + bool EvioReaderV4::checkBlockNumberSequence() {return checkBlockNumSeq;} + /** {@inheritDoc} */ - ByteOrder &EvioReaderV4::getByteOrder() { return byteOrder; } + ByteOrder & EvioReaderV4::getByteOrder() {return byteOrder;} + /** {@inheritDoc} */ - uint32_t EvioReaderV4::getEvioVersion() { return evioVersion; } + uint32_t EvioReaderV4::getEvioVersion() {return evioVersion;} + /** {@inheritDoc} */ - std::string EvioReaderV4::getPath() { return path; } + std::string EvioReaderV4::getPath() {return path;} + /** {@inheritDoc} */ - std::shared_ptr EvioReaderV4::getParser() { return parser; } + std::shared_ptr EvioReaderV4::getParser() {return parser;} + /** {@inheritDoc} */ - void EvioReaderV4::setParser(std::shared_ptr evParser) { parser = evParser; } + void EvioReaderV4::setParser(std::shared_ptr evParser) {parser = evParser;} + /** {@inheritDoc} */ - std::string EvioReaderV4::getDictionaryXML() { return dictionaryXML; } + std::string EvioReaderV4::getDictionaryXML() {return dictionaryXML;} + /** {@inheritDoc} */ - bool EvioReaderV4::hasDictionaryXML() { return !dictionaryXML.empty(); } + bool EvioReaderV4::hasDictionaryXML() {return !dictionaryXML.empty();} + /** {@inheritDoc} */ - std::shared_ptr EvioReaderV4::getFirstEvent() - { - if (hasFirstEvent()) - { + std::shared_ptr EvioReaderV4::getFirstEvent() { + if (hasFirstEvent()) { return getEvent(1); } return nullptr; } + /** {@inheritDoc} */ - bool EvioReaderV4::hasFirstEvent() - { - if (evioVersion < 4) - { + bool EvioReaderV4::hasFirstEvent() { + if (evioVersion < 4) { firstBlockHeader2->hasFirstEvent(); } return firstBlockHeader4->hasFirstEvent(); } + /** {@inheritDoc} */ - size_t EvioReaderV4::getNumEventsRemaining() { return getEventCount() - eventNumber; } + size_t EvioReaderV4::getNumEventsRemaining() {return getEventCount() - eventNumber;} + /** * {@inheritDoc}. @@ -461,13 +440,16 @@ namespace evio * returns the internal buffer containing an evio block if using sequential access * (for example files > 2.1 GB). It returns the memory mapped buffer otherwise. */ - std::shared_ptr EvioReaderV4::getByteBuffer() { return byteBuffer; } + std::shared_ptr EvioReaderV4::getByteBuffer() {return byteBuffer;} + /** {@inheritDoc} */ - size_t EvioReaderV4::fileSize() { return fileBytes; } + size_t EvioReaderV4::fileSize() {return fileBytes;} + /** {@inheritDoc} */ - std::shared_ptr EvioReaderV4::getFirstBlockHeader() { return firstBlockHeader; } + std::shared_ptr EvioReaderV4::getFirstBlockHeader() {return firstBlockHeader;} + /** * Reads 8 words of the first block (physical record) header in order to determine @@ -479,13 +461,11 @@ namespace evio * @throws EvioException if buffer too small, contains invalid data, * or bad block # sequence */ - void EvioReaderV4::parseFirstHeader(std::shared_ptr headerBuf) - { + void EvioReaderV4::parseFirstHeader(std::shared_ptr headerBuf) { // Check buffer length headerBuf->position(0); - if (headerBuf->remaining() < 32) - { + if (headerBuf->remaining() < 32) { throw EvioException("buffer too small"); } @@ -494,8 +474,7 @@ namespace evio uint32_t magicNumber = headerBuf->getUInt(MAGIC_OFFSET); - if (magicNumber != IBlockHeader::MAGIC_NUMBER) - { + if (magicNumber != IBlockHeader::MAGIC_NUMBER) { swap = true; byteOrder = byteOrder.getOppositeEndian(); @@ -503,60 +482,47 @@ namespace evio // Reread magic number to make sure things are OK magicNumber = headerBuf->getInt(MAGIC_OFFSET); - if (magicNumber != IBlockHeader::MAGIC_NUMBER) - { - std::cout << "ERROR reread magic # (" << std::to_string(magicNumber) << ") & still not right" << std::endl; + if (magicNumber != IBlockHeader::MAGIC_NUMBER) { + std::cout << "ERROR reread magic # (" << std::to_string(magicNumber) << + ") & still not right" << std::endl; throw EvioException("bad magic #"); } } // Check the version number. This requires peeking ahead 5 ints or 20 bytes. evioVersion = headerBuf->getInt(VERSION_OFFSET) & VERSION_MASK; - if (evioVersion < 1) - { + if (evioVersion < 1) { throw EvioException("bad version"); } - // std::cout << "Evio version# = " << evioVersion << std::endl; +// std::cout << "Evio version# = " << evioVersion << std::endl; - if (evioVersion >= 4) - { + if (evioVersion >= 4) { blockHeader4->setBufferStartingPosition(0); - int pos = 0; - std::cout << "BlockHeader v4:" << std::endl << std::hex << std::showbase; - std::cout << " block length = " << headerBuf->getInt(pos) << std::endl; pos+=4; - std::cout << " block number = " << headerBuf->getInt(pos) << std::endl; pos+=4; - std::cout << " header length = " << headerBuf->getInt(pos) << std::endl; pos+=4; - std::cout << " reserved1 = " << headerBuf->getInt(pos) << std::endl; pos+=4; - std::cout << " event count = " << headerBuf->getInt(pos) << std::endl; pos+=4; - std::cout << " bitinfo/version = " << headerBuf->getInt(pos) << std::endl; pos+=4; - std::cout << " reserved2 = " << headerBuf->getInt(pos) << std::endl; pos+=4; - std::cout << " magic number = " << headerBuf->getInt(pos) << std::endl; pos+=4; - std::cout << std::endl << std::dec; - - // DEBUG: print out the buffer information - std::cout << "EvioReaderV4: buffer pos = " << headerBuf->position() << - ", limit = " << headerBuf->limit() << - ", remaining = " << headerBuf->remaining() << - ", capacity = " << headerBuf->capacity() << std::endl; - +// int pos = 0; +// std::cout << "BlockHeader v4:" << std::endl << hex << showbase; +// std::cout << " block length = " << headerBuf->getInt(pos) << std::endl; pos+=4; +// std::cout << " block number = " << headerBuf->getInt(pos) << std::endl; pos+=4; +// std::cout << " header length = " << headerBuf->getInt(pos) << std::endl; pos+=4; +// std::cout << " event count = " << headerBuf->getInt(pos) << std::endl; pos+=8; +// std::cout << " version = " << headerBuf->getInt(pos) << std::endl; pos+=8; +// std::cout << " magic number = " << headerBuf->getInt(pos) << std::endl; pos+=4; +// std::cout << std::endl << dec; // Read the header data - // Opposite the offending setSize() - std::cout << "1) EvioReaderV4: doing setSize()" << std::endl; - blockHeader4->setSize(headerBuf->getInt(0)); // Word 1 - blockHeader4->setNumber(headerBuf->getInt(4)); // Word 2, 4 bytes = 32 bits offset - blockHeader4->setHeaderLength(headerBuf->getInt(8)); // Word 3 - blockHeader4->setEventCount(headerBuf->getInt(12)); // Word 4 - blockHeader4->setReserved1(headerBuf->getInt(16)); // Word 5 + blockHeader4->setSize( headerBuf->getInt()); + blockHeader4->setNumber( headerBuf->getInt()); + blockHeader4->setHeaderLength(headerBuf->getInt()); + blockHeader4->setEventCount( headerBuf->getInt()); + blockHeader4->setReserved1( headerBuf->getInt()); // Use 6th word to set bit info & version - blockHeader4->parseToBitInfo(headerBuf->getInt(20)); + blockHeader4->parseToBitInfo(headerBuf->getInt()); blockHeader4->setVersion(evioVersion); lastBlock = blockHeader4->getBitInfo(1); - blockHeader4->setReserved2(headerBuf->getInt(24)); // Word 7 - blockHeader4->setMagicNumber(headerBuf->getInt(28)); // Word 8 - blockHeader4->setByteOrder(byteOrder); + blockHeader4->setReserved2(headerBuf->getInt()); + blockHeader4->setMagicNumber(headerBuf->getInt()); + blockHeader4->setByteOrder(byteOrder); blockHeader = blockHeader4; // Copy it @@ -565,37 +531,36 @@ namespace evio // Deal with non-standard header lengths here int64_t headerLenDiff = blockHeader4->getHeaderLength() - BlockHeaderV4::HEADER_SIZE; // If too small quit with error since headers have a minimum size - if (headerLenDiff < 0) - { + if (headerLenDiff < 0) { throw EvioException("header size too small"); } - // std::cout << "BlockHeader v4:" << std::endl; - // std::cout << " block length = " << blockHeader4.getSize() << " ints" << std::endl; - // std::cout << " block number = " << blockHeader4.getNumber() << std::endl; - // std::cout << " header length = " << blockHeader4.getHeaderLength() + " ints" << std::endl; - // std::cout << " event count = " << blockHeader4.getEventCount() << std::endl; - // std::cout << " version = " << blockHeader4.getVersion() << std::endl; - // std::cout << " has Dict = " << blockHeader4.getBitInfo(0) << std::endl; - // std::cout << " is End = " << lastBlock << std::endl << hex; - // std::cout << " magic number = " << blockHeader4.getMagicNumber() << std::endl << dec; - } - else - { +//std::cout << "BlockHeader v4:" << std::endl; +//std::cout << " block length = " << blockHeader4.getSize() << " ints" << std::endl; +//std::cout << " block number = " << blockHeader4.getNumber() << std::endl; +//std::cout << " header length = " << blockHeader4.getHeaderLength() + " ints" << std::endl; +//std::cout << " event count = " << blockHeader4.getEventCount() << std::endl; +//std::cout << " version = " << blockHeader4.getVersion() << std::endl; +//std::cout << " has Dict = " << blockHeader4.getBitInfo(0) << std::endl; +//std::cout << " is End = " << lastBlock << std::endl << hex; +//std::cout << " magic number = " << blockHeader4.getMagicNumber() << std::endl << dec; + + } + else { // Cache the starting position blockHeader2->setBufferStartingPosition(0); // read the header data. - blockHeader2->setSize(headerBuf->getInt()); - blockHeader2->setNumber(headerBuf->getInt()); + blockHeader2->setSize( headerBuf->getInt()); + blockHeader2->setNumber( headerBuf->getInt()); blockHeader2->setHeaderLength(headerBuf->getInt()); - blockHeader2->setStart(headerBuf->getInt()); - blockHeader2->setEnd(headerBuf->getInt()); + blockHeader2->setStart( headerBuf->getInt()); + blockHeader2->setEnd( headerBuf->getInt()); // skip version headerBuf->getInt(); blockHeader2->setVersion(evioVersion); - blockHeader2->setReserved1(headerBuf->getInt()); - blockHeader2->setMagicNumber(headerBuf->getInt()); + blockHeader2->setReserved1( headerBuf->getInt()); + blockHeader2->setMagicNumber( headerBuf->getInt()); blockHeader2->setByteOrder(byteOrder); blockHeader = blockHeader2; @@ -603,14 +568,13 @@ namespace evio } // Store this for later regurgitation of blockCount - firstBlockSize = 4 * blockHeader->getSize(); + firstBlockSize = 4*blockHeader->getSize(); // check block number if so configured - if (checkBlockNumSeq) - { - if (blockHeader->getNumber() != blockNumberExpected) - { - std::cout << "block # out of sequence, got " << blockHeader->getNumber() << " expecting " << blockNumberExpected << std::endl; + if (checkBlockNumSeq) { + if (blockHeader->getNumber() != blockNumberExpected) { + std::cout << "block # out of sequence, got " << blockHeader->getNumber() << + " expecting " << blockNumberExpected << std::endl; throw EvioException("bad block # sequence"); } @@ -618,35 +582,35 @@ namespace evio } } + /** * Reads the first block header into a buffer and gets that * buffer ready for first-time read. * * @throws EvioException if file access problems */ - void EvioReaderV4::prepareForSequentialRead() - { + void EvioReaderV4::prepareForSequentialRead() { size_t bytesToRead; // Evio format version 4 or greater has a large enough default block size // so that reading a single block at a time is not inefficient. - if (evioVersion > 3) - { - bytesToRead = 4 * firstBlockHeader->getSize(); + if (evioVersion > 3) { + bytesToRead = 4*firstBlockHeader->getSize(); } // Reading data by 32768 byte blocks in older versions is inefficient, // so read in 500 block (16MB) chunks. - else - { + else { size_t bytesLeftInFile = fileBytes - file.tellg(); - bytesToRead = DEFAULT_READ_BYTES < bytesLeftInFile ? DEFAULT_READ_BYTES : bytesLeftInFile; + bytesToRead = DEFAULT_READ_BYTES < bytesLeftInFile ? + DEFAULT_READ_BYTES : bytesLeftInFile; } - // std::cout << "prepareForSequentialRead: bytesToRead = " << bytesToRead << std::endl; + +//std::cout << "prepareForSequentialRead: bytesToRead = " << bytesToRead << std::endl; + // Create/expand a buffer to hold a chunk of data - if ((byteBuffer == nullptr) || (byteBuffer->capacity() < bytesToRead)) - { + if ((byteBuffer == nullptr) || (byteBuffer->capacity() < bytesToRead)) { byteBuffer = std::make_shared(bytesToRead); byteBuffer->order(byteOrder); } @@ -654,8 +618,7 @@ namespace evio // Read the first chunk of data from file file.read((char *)(byteBuffer->array() + byteBuffer->arrayOffset()), bytesToRead); - if (file.fail()) - { + if (file.fail()) { throw EvioException("file read failure"); } @@ -665,28 +628,25 @@ namespace evio prepareForBufferRead(byteBuffer); } + /** * Sets the proper buffer position for first-time read AFTER the first header. * @param buffer buffer to prepare */ - void EvioReaderV4::prepareForBufferRead(std::shared_ptr buffer) const - { + void EvioReaderV4::prepareForBufferRead(std::shared_ptr buffer) const { // Position after header size_t pos = 32; buffer->position(pos); // Deal with non-standard first header length. // No non-standard header lengths in evio version 2 & 3 files. - if (evioVersion < 4) - return; + if (evioVersion < 4) return; int64_t headerLenDiff = blockHeader4->getHeaderLength() - BlockHeaderV4::HEADER_SIZE; // Hop over any extra header words - if (headerLenDiff > 0) - { - for (int i = 0; i < headerLenDiff; i++) - { - // std::cout << "Skip extra header int"); + if (headerLenDiff > 0) { + for (int i=0; i < headerLenDiff; i++) { + //std::cout << "Skip extra header int"); pos += 4; buffer->position(pos); } @@ -696,6 +656,7 @@ namespace evio // If there's a dictionary present, skip over it now. } + /** * Reads the block (physical record) header. * Assumes mapped buffer or file is positioned at start of the next block header. @@ -720,44 +681,37 @@ namespace evio * @return status of read attempt * @throws EvioException if file access problems, evio format problems */ - IEvioReader::ReadWriteStatus EvioReaderV4::processNextBlock() - { + IEvioReader::ReadWriteStatus EvioReaderV4::processNextBlock() { // We already read the last block header - if (lastBlock) - { + if (lastBlock) { return IEvioReader::ReadWriteStatus::END_OF_FILE; } - try - { - if (sequentialRead) - { - if (evioVersion < 4) - { + try { + if (sequentialRead) { + if (evioVersion < 4) { size_t bytesInBuf = bufferBytesRemaining(); - if (bytesInBuf == 0) - { + if (bytesInBuf == 0) { // How much of the file is left to read? size_t bytesLeftInFile = fileBytes - file.tellg(); - if (bytesLeftInFile < 32L) - { + if (bytesLeftInFile < 32L) { return IEvioReader::ReadWriteStatus::END_OF_FILE; } // The block size is 32kB which is on the small side. // We want to read in 16MB (DEFAULT_READ_BYTES) or so // at once for efficiency. - size_t bytesToRead = DEFAULT_READ_BYTES < bytesLeftInFile ? DEFAULT_READ_BYTES : bytesLeftInFile; + size_t bytesToRead = DEFAULT_READ_BYTES < bytesLeftInFile ? + DEFAULT_READ_BYTES : bytesLeftInFile; // Reset buffer byteBuffer->position(0).limit(bytesToRead); // Read the entire chunk of data file.read((char *)(byteBuffer->array() + byteBuffer->arrayOffset()), bytesToRead); - if (file.fail()) - { + if (file.fail()) { throw EvioException("file read failure"); } byteBuffer->limit(bytesToRead); @@ -765,69 +719,46 @@ namespace evio // Now keeping track of pos in this new blockBuffer blockHeader->setBufferStartingPosition(0); } - else if (bytesInBuf % 32768 == 0) - { + else if (bytesInBuf % 32768 == 0) { // Next block header starts at this position in buffer blockHeader->setBufferStartingPosition(byteBuffer->position()); } - else - { + else { throw EvioException("file contains non-integral # of 32768 byte blocks"); } } - else - { + else { // Enough data left to read len? - if (fileBytes - file.tellg() < 4L) - { + if (fileBytes - file.tellg() < 4L) { return IEvioReader::ReadWriteStatus::END_OF_FILE; } // Read len of block in 32 bit words uint32_t blkSize; - file.read(reinterpret_cast(&blkSize), sizeof(blkSize)); - if (file.fail()) - { + file.read(reinterpret_cast(&blkSize), sizeof(blkSize)); + if (file.fail()) { throw EvioException("file read failure"); } - if (swap) - blkSize = SWAP_32(blkSize); - - std::cout << "EvioReaderV4: sizeof(blkSize) = " << sizeof(blkSize) << std::endl; + if (swap) blkSize = SWAP_32(blkSize); // Change to bytes uint32_t blkBytes = 4 * blkSize; // Enough data left to read rest of block? - if (fileBytes - file.tellg() < blkBytes - 4) - { + if (fileBytes - file.tellg() < blkBytes-4) { return IEvioReader::ReadWriteStatus::END_OF_FILE; } - std::cerr << "Reading byteBuffer from file... " << std::endl; - // DEBUG: print out the buffer information - std::cout << "EvioReaderV4 BEFORE: buffer pos = " << byteBuffer->position() << - ", fileBytes = " << fileBytes << - ", blkSize = " << blkSize << - ", blkBytes = " << blkBytes << - ", limit = " << byteBuffer->limit() << - ", remaining = " << byteBuffer->remaining() << - ", capacity = " << byteBuffer->capacity() << std::endl; - // Create a buffer to hold the entire first block of data - if (byteBuffer->capacity() >= blkBytes) - { + if (byteBuffer->capacity() >= blkBytes) { byteBuffer->clear(); byteBuffer->limit(blkBytes); - std::cerr << "1Reading byteBuffer from file... " << std::endl; } - else - { + else { // Make this bigger than necessary so we're not constantly reallocating byteBuffer = std::make_shared(blkBytes + 10000); byteBuffer->limit(blkBytes); byteBuffer->order(byteOrder); - std::cerr << "2Reading byteBuffer from file... " << std::endl; } // Read the entire block of data. @@ -835,9 +766,8 @@ namespace evio byteBuffer->putInt(0, blkSize); // Now the rest of the block (already put int, 4 bytes, in) - file.read((char *)(byteBuffer->array() + byteBuffer->arrayOffset() + 4), blkBytes - 4); - if (file.fail()) - { + file.read((char *)(byteBuffer->array() + byteBuffer->arrayOffset() + 4), blkBytes-4); + if (file.fail()) { throw EvioException("file read failure"); } @@ -845,10 +775,8 @@ namespace evio blockHeader->setBufferStartingPosition(0); } } - else - { - if (byteBuffer->remaining() < 32) - { + else { + if (byteBuffer->remaining() < 32) { byteBuffer->clear(); return IEvioReader::ReadWriteStatus::END_OF_FILE; } @@ -856,29 +784,8 @@ namespace evio blockHeader->setBufferStartingPosition(byteBuffer->position()); } - // DEBUG: print out the buffer information - std::cout << "EvioReaderV4: buffer pos = " << byteBuffer->position() << - ", limit = " << byteBuffer->limit() << - ", remaining = " << byteBuffer->remaining() << - ", capacity = " << byteBuffer->capacity() << std::endl; - - if (evioVersion >= 4) - { + if (evioVersion >= 4) { // Read the header data. - - int pos = 0; - std::cout << "BlockHeader v4:" << std::endl << std::hex << std::showbase; - std::cout << " block length = " << byteBuffer->getInt(pos) << std::endl; pos+=4; - std::cout << " block number = " << byteBuffer->getInt(pos) << std::endl; pos+=4; - std::cout << " header length = " << byteBuffer->getInt(pos) << std::endl; pos+=4; - std::cout << " reserved1 = " << byteBuffer->getInt(pos) << std::endl; pos+=4; - std::cout << " event count = " << byteBuffer->getInt(pos) << std::endl; pos+=4; - std::cout << " bitinfo/version = " << byteBuffer->getInt(pos) << std::endl; pos+=4; - std::cout << " reserved2 = " << byteBuffer->getInt(pos) << std::endl; pos+=4; - std::cout << " magic number = " << byteBuffer->getInt(pos) << std::endl; pos+=4; - std::cout << std::endl << std::dec; - - // Here's the offending setSize() blockHeader4->setSize(byteBuffer->getInt()); blockHeader4->setNumber(byteBuffer->getInt()); blockHeader4->setHeaderLength(byteBuffer->getInt()); @@ -890,48 +797,22 @@ namespace evio lastBlock = blockHeader4->getBitInfo(1); blockHeader4->setReserved2(byteBuffer->getInt()); blockHeader4->setMagicNumber(byteBuffer->getInt()); - blockHeader4->setByteOrder(byteOrder); blockHeader = blockHeader4; - // // Read the header data - // // Copied from above the offending setSize() - // std::cout << "1) EvioReaderV4: doing setSize()" << std::endl; - // blockHeader4->setSize(headerBuf->getInt(0)); // Word 1 - // blockHeader4->setNumber(headerBuf->getInt(4)); // Word 2, 4 bytes = 32 bits offset - // blockHeader4->setHeaderLength(headerBuf->getInt(8)); // Word 3 - // blockHeader4->setEventCount(headerBuf->getInt(12)); // Word 4 - // blockHeader4->setReserved1(headerBuf->getInt(16)); // Word 5 - - // // Use 6th word to set bit info & version - // blockHeader4->parseToBitInfo(headerBuf->getInt(20)); - // blockHeader4->setVersion(evioVersion); - // lastBlock = blockHeader4->getBitInfo(1); - // blockHeader4->setReserved2(headerBuf->getInt(24)); // Word 7 - // blockHeader4->setMagicNumber(headerBuf->getInt(28)); // Word 8 - // blockHeader4->setByteOrder(byteOrder); - // blockHeader = blockHeader4; - - // DEBUG: print out the buffer information - std::cout << "blockHeader4 header length: " << blockHeader4->getHeaderLength() << std::endl; - // Deal with non-standard header lengths here int64_t headerLenDiff = blockHeader4->getHeaderLength() - BlockHeaderV4::HEADER_SIZE; // If too small quit with error since headers have a minimum size - if (headerLenDiff < 0) - { + if (headerLenDiff < 0) { return IEvioReader::ReadWriteStatus::EVIO_EXCEPTION; } - // If bigger, read extra ints - else if (headerLenDiff > 0) - { - for (int i = 0; i < headerLenDiff; i++) - { + // If bigger, read extra ints + else if (headerLenDiff > 0) { + for (int i=0; i < headerLenDiff; i++) { byteBuffer->getInt(); } } } - else if (evioVersion < 4) - { + else if (evioVersion < 4) { // read the header data blockHeader2->setSize(byteBuffer->getInt()); blockHeader2->setNumber(byteBuffer->getInt()); @@ -945,39 +826,36 @@ namespace evio blockHeader2->setMagicNumber(byteBuffer->getInt()); blockHeader = blockHeader2; } - else - { + else { // bad version # - should never happen return IEvioReader::ReadWriteStatus::EVIO_EXCEPTION; } // check block number if so configured - if (checkBlockNumSeq) - { - if (blockHeader->getNumber() != blockNumberExpected) - { + if (checkBlockNumSeq) { + if (blockHeader->getNumber() != blockNumberExpected) { - std::cout << "block # out of sequence, got " << std::to_string(blockHeader->getNumber()) + " expecting " << std::to_string(blockNumberExpected) << std::endl; + std::cout << "block # out of sequence, got " << std::to_string(blockHeader->getNumber()) + + " expecting " << std::to_string(blockNumberExpected) << std::endl; return IEvioReader::ReadWriteStatus::EVIO_EXCEPTION; } blockNumberExpected++; } } - catch (EvioException &e) - { - std::cout << "ERROR in processNextBlock: " << e.what() << std::endl; + catch (EvioException & e) { return IEvioReader::ReadWriteStatus::EVIO_EXCEPTION; } - // catch (BufferUnderflowException & a) { - // std::cout << "ERROR endOfBuffer " << a << std::endl; - // byteBuffer->clear(); - // return IEvioReader::ReadWriteStatus::UNKNOWN_ERROR; - // } +// catch (BufferUnderflowException & a) { +// std::cout << "ERROR endOfBuffer " << a << std::endl; +// byteBuffer->clear(); +// return IEvioReader::ReadWriteStatus::UNKNOWN_ERROR; +// } return IEvioReader::ReadWriteStatus::SUCCESS; } + /** * This method is only called once at the very beginning if buffer is known to have * a dictionary. It then reads that dictionary. Only called in format versions 4 & up. @@ -989,18 +867,15 @@ namespace evio * @throws EvioException if failed read due to bad buffer format; * if version 3 or earlier */ - void EvioReaderV4::readDictionary(std::shared_ptr buffer) - { + void EvioReaderV4::readDictionary(std::shared_ptr buffer) { - if (evioVersion < 4) - { + if (evioVersion < 4) { throw EvioException("Unsupported version (" + std::to_string(evioVersion) + ")"); } // How many bytes remain in this buffer? size_t bytesRemaining = buffer->remaining(); - if (bytesRemaining < 12) - { + if (bytesRemaining < 12) { throw std::underflow_error("Not enough data in buffer"); } @@ -1013,9 +888,8 @@ namespace evio bytesRemaining -= 4; // get the raw data - uint32_t eventDataSizeBytes = 4 * (length - 1); - if (bytesRemaining < eventDataSizeBytes) - { + uint32_t eventDataSizeBytes = 4*(length - 1); + if (bytesRemaining < eventDataSizeBytes) { throw EvioException("Not enough data in buffer"); } @@ -1026,18 +900,16 @@ namespace evio // This is the very first event and must be a dictionary BaseStructure::unpackRawBytesToStrings(bytes, eventDataSizeBytes, strs); - if (strs.empty()) - { + if (strs.empty()) { throw EvioException("Data in bad format"); } dictionaryXML = strs[0]; } + /** {@inheritDoc} */ - std::shared_ptr EvioReaderV4::getEvent(size_t index) - { - if (sequentialRead || evioVersion < 4) - { + std::shared_ptr EvioReaderV4::getEvent(size_t index) { + if (sequentialRead || evioVersion < 4) { // Do not fully parse events up to index_TH event return gotoEventNumber(index, false); } @@ -1046,6 +918,7 @@ namespace evio return getEventV4(index); } + /** * Get the event in the file/buffer at a given index (starting at 1). * It is only valid for evio versions 4+. @@ -1059,21 +932,17 @@ namespace evio * @throws EvioException if failed read due to bad file/buffer format; * if object closed */ - std::shared_ptr EvioReaderV4::getEventV4(size_t index) - { + std::shared_ptr EvioReaderV4::getEventV4(size_t index) { // Lock this method - if (synchronized) - { + if (synchronized) { const std::lock_guard lock(mtx); } - if (index > getEventCount()) - { + if (index > getEventCount()) { return nullptr; } - if (closed) - { + if (closed) { throw EvioException("object closed"); } @@ -1095,7 +964,7 @@ namespace evio // However, it that MAY also be the legacy tagsegment type // with no padding information. Ignore this as having tag & num // in legacy code is probably rare. - // if (dt == 0x40) { + //if (dt == 0x40) { // type = DataType.TAGSEGMENT.getValue(); // padding = 0; //} @@ -1104,7 +973,7 @@ namespace evio header->setNumber(word & 0xff); // Read the raw data - eventDataSizeBytes = 4 * (length - 1); + eventDataSizeBytes = 4*(length - 1); event->setRawBytes((uint8_t *)(byteBuffer->array() + byteBuffer->arrayOffset() + byteBuffer->position()), (size_t)eventDataSizeBytes); byteBuffer->position(byteBuffer->position() + eventDataSizeBytes); @@ -1115,38 +984,33 @@ namespace evio return event; } + /** {@inheritDoc} */ - std::shared_ptr EvioReaderV4::parseEvent(size_t index) - { + std::shared_ptr EvioReaderV4::parseEvent(size_t index) { // Lock this method - if (synchronized) - { + if (synchronized) { const std::lock_guard lock(mtx); } auto event = getEvent(index); - if (event != nullptr) - parseEvent(event); + if (event != nullptr) parseEvent(event); return event; } + /** {@inheritDoc} */ - std::shared_ptr EvioReaderV4::nextEvent() - { + std::shared_ptr EvioReaderV4::nextEvent() { // Lock this method - if (synchronized) - { + if (synchronized) { const std::lock_guard lock(mtx); } - if (!sequentialRead && evioVersion > 3) - { - return getEvent(eventNumber + 1); + if (!sequentialRead && evioVersion > 3) { + return getEvent(eventNumber+1); } - if (closed) - { + if (closed) { throw EvioException("object closed"); } @@ -1164,29 +1028,23 @@ namespace evio // We now read in bigger chunks that are integral multiples of a single block // (32768 bytes). Must see if we have to deal with an event crossing physical // record boundaries. Previously, java evio only read 1 block at a time. - if (blkBytesRemaining == 0) - { + if (blkBytesRemaining == 0) { IEvioReader::ReadWriteStatus status = processNextBlock(); - if (status == IEvioReader::ReadWriteStatus::SUCCESS) - { + if (status == IEvioReader::ReadWriteStatus::SUCCESS) { return nextEvent(); } - else if (status == IEvioReader::ReadWriteStatus::END_OF_FILE) - { + else if (status == IEvioReader::ReadWriteStatus::END_OF_FILE) { return nullptr; } - else - { - throw EvioException("Failed reading block header in nextEvent (status=" + - std::to_string(static_cast(status)) + ")"); + else { + throw EvioException("Failed reading block header in nextEvent."); } } // Or have we already read in the last event? // If jevio versions 1-3, the last block may not be full. // Thus bytesRemaining may be > 0, but we may have read // in all the existing data. (This should never happen in version 4). - else if (blockHeader->getBufferEndingPosition() == currentPosition) - { + else if (blockHeader->getBufferEndingPosition() == currentPosition) { return nullptr; } @@ -1202,17 +1060,13 @@ namespace evio // Versions 1-3: if we were unlucky, after reading the length // there are no bytes remaining in this block. // Don't really need the "if (version < 4)" here except for clarity. - if (evioVersion < 4) - { - if (bufferBytesRemaining() == 0) - { + if (evioVersion < 4) { + if (bufferBytesRemaining() == 0) { IEvioReader::ReadWriteStatus status = processNextBlock(); - if (status == IEvioReader::ReadWriteStatus::END_OF_FILE) - { + if (status == IEvioReader::ReadWriteStatus::END_OF_FILE) { return nullptr; } - else if (status != IEvioReader::ReadWriteStatus::SUCCESS) - { + else if (status != IEvioReader::ReadWriteStatus::SUCCESS) { throw EvioException("Failed reading block header in nextEvent."); } blkBytesRemaining = blockBytesRemaining(); @@ -1233,41 +1087,36 @@ namespace evio blkBytesRemaining -= 4; // just read in 4 bytes // get the raw data - uint32_t eventDataSizeBytes = 4 * (length - 1); + uint32_t eventDataSizeBytes = 4*(length - 1); - try - { + try { auto *bytes = new uint8_t[eventDataSizeBytes]; uint32_t bytesToGo = eventDataSizeBytes; uint32_t offset = 0; // Don't really need the "if (version < 4)" here except for clarity. - if (evioVersion < 4) - { + if (evioVersion < 4) { // Be in while loop if have to cross block boundary[ies]. - while (bytesToGo > 0) - { + while (bytesToGo > 0) { // Don't read more than what is left in current block - uint32_t bytesToReadNow = bytesToGo > blkBytesRemaining ? blkBytesRemaining : bytesToGo; + uint32_t bytesToReadNow = bytesToGo > blkBytesRemaining ? + blkBytesRemaining : bytesToGo; // Read in bytes remaining in internal buffer byteBuffer->getBytes(bytes + offset, bytesToReadNow); - offset += bytesToReadNow; - bytesToGo -= bytesToReadNow; - blkBytesRemaining -= bytesToReadNow; + offset += bytesToReadNow; + bytesToGo -= bytesToReadNow; + blkBytesRemaining -= bytesToReadNow; - if (blkBytesRemaining == 0) - { + if (blkBytesRemaining == 0) { IEvioReader::ReadWriteStatus status = processNextBlock(); - if (status == IEvioReader::ReadWriteStatus::END_OF_FILE) - { + if (status == IEvioReader::ReadWriteStatus::END_OF_FILE) { return nullptr; } - else if (status != IEvioReader::ReadWriteStatus::SUCCESS) - { + else if (status != IEvioReader::ReadWriteStatus::SUCCESS) { throw EvioException("Failed reading block header after crossing boundary in nextEvent."); } @@ -1278,50 +1127,46 @@ namespace evio // Last (perhaps only) read byteBuffer->getBytes(bytes + offset, bytesToGo); - // std::cout << "nextEvent: eventDataSizeByte = " << eventDataSizeBytes << std::endl; +//std::cout << "nextEvent: eventDataSizeByte = " << eventDataSizeBytes << std::endl; event->setRawBytes(bytes, eventDataSizeBytes); event->setByteOrder(byteOrder); // add this to track endianness, timmer // Don't worry about dictionaries here as version must be 1-3 event->setEventNumber(++eventNumber); return event; } - catch (EvioException &e) - { + catch (EvioException & e) { std::cout << e.what() << std::endl; return nullptr; } } + /** {@inheritDoc} */ - std::shared_ptr EvioReaderV4::parseNextEvent() - { + std::shared_ptr EvioReaderV4::parseNextEvent() { // Lock this method - if (synchronized) - { + if (synchronized) { const std::lock_guard lock(mtx); } auto event = nextEvent(); - if (event != nullptr) - { + if (event != nullptr) { parseEvent(event); } return event; } + /** {@inheritDoc} */ - void EvioReaderV4::parseEvent(std::shared_ptr evioEvent) - { + void EvioReaderV4::parseEvent(std::shared_ptr evioEvent) { // This method is called by locked methods parser->parseEvent(evioEvent); } + /** {@inheritDoc} */ - uint32_t EvioReaderV4::getEventArray(size_t evNumber, std::vector &vec) - { + uint32_t EvioReaderV4::getEventArray(size_t evNumber, std::vector & vec) { auto ev = gotoEventNumber(evNumber, false); - if (ev == nullptr) - { + if (ev == nullptr) { throw EvioException("event number must be > 0"); } @@ -1331,12 +1176,11 @@ namespace evio return numBytes; } + /** {@inheritDoc} */ - uint32_t EvioReaderV4::getEventBuffer(size_t evNumber, ByteBuffer &buf) - { + uint32_t EvioReaderV4::getEventBuffer(size_t evNumber, ByteBuffer & buf) { auto ev = gotoEventNumber(evNumber, false); - if (ev == nullptr) - { + if (ev == nullptr) { throw EvioException("event number must be > 0"); } @@ -1348,12 +1192,14 @@ namespace evio return numBytes; } + /** * Get the number of bytes remaining in the internal byte buffer. * Called only by {@link #nextEvent()}. * @return the number of bytes remaining in the current block (physical record). */ - size_t EvioReaderV4::bufferBytesRemaining() const { return byteBuffer->remaining(); } + size_t EvioReaderV4::bufferBytesRemaining() const {return byteBuffer->remaining();} + /** * Get the number of bytes remaining in the current block (physical record). @@ -1363,32 +1209,27 @@ namespace evio * @return the number of bytes remaining in the current block (physical record). * @throws EvioException if position out of bounds */ - uint32_t EvioReaderV4::blockBytesRemaining() const - { + uint32_t EvioReaderV4::blockBytesRemaining() const { return blockHeader->bytesRemaining(byteBuffer->position()); } + /** {@inheritDoc} */ - void EvioReaderV4::rewind() - { + void EvioReaderV4::rewind() { // Lock this method - if (synchronized) - { + if (synchronized) { const std::lock_guard lock(mtx); } - if (closed) - { + if (closed) { throw EvioException("object closed"); } - if (sequentialRead) - { + if (sequentialRead) { file.seekg(initialPosition); prepareForSequentialRead(); } - else if (evioVersion < 4) - { + else if (evioVersion < 4) { byteBuffer->position(initialPosition); prepareForBufferRead(byteBuffer); } @@ -1397,19 +1238,16 @@ namespace evio eventNumber = 0; blockNumberExpected = 1; - if (evioVersion < 4) - { + if (evioVersion < 4) { blockHeader = blockHeader2 = std::make_shared(firstBlockHeader2); } - else - { + else { blockHeader = blockHeader4 = std::make_shared(firstBlockHeader4); } blockHeader->setBufferStartingPosition(initialPosition); - if (sequentialRead && hasDictionaryXML()) - { + if (sequentialRead && hasDictionaryXML()) { // Dictionary is always the first event so skip over it. // For sequential reads, do this after each rewind. nextEvent(); @@ -1417,70 +1255,59 @@ namespace evio } /** {@inheritDoc} */ - ssize_t EvioReaderV4::position() - { + ssize_t EvioReaderV4::position() { // Lock this method - if (synchronized) - { + if (synchronized) { const std::lock_guard lock(mtx); } - if (!sequentialRead && evioVersion > 3) - return -1L; + if (!sequentialRead && evioVersion > 3) return -1L; - if (closed) - { + if (closed) { throw EvioException("object closed"); } - if (sequentialRead) - { + if (sequentialRead) { return file.tellg(); } return byteBuffer->position(); } /** {@inheritDoc} */ - void EvioReaderV4::close() - { + void EvioReaderV4::close() { // Lock this method - if (synchronized) - { + if (synchronized) { const std::lock_guard lock(mtx); } - if (closed) - { + if (closed) { return; } - if (sequentialRead) - { + if (sequentialRead) { file.close(); } - else - { - try - { + else { + try { byteBuffer->position(initialPosition); } - catch (EvioException &e) - { - } + catch (EvioException & e) {} } closed = true; } + /** {@inheritDoc} */ - std::shared_ptr EvioReaderV4::getCurrentBlockHeader() { return blockHeader; } + std::shared_ptr EvioReaderV4::getCurrentBlockHeader() {return blockHeader;} + /** {@inheritDoc} */ - std::shared_ptr EvioReaderV4::gotoEventNumber(size_t evNumber) - { + std::shared_ptr EvioReaderV4::gotoEventNumber(size_t evNumber) { return gotoEventNumber(evNumber, true); } + /** * Go to a specific event in the file. The events are numbered 1..N. * This number is transient--it is not part of the event as stored in the evio file. @@ -1491,34 +1318,26 @@ namespace evio * @return the specified event in file or null if there's an error or nothing at that event #. * @throws EvioException if object closed; if failed file access */ - std::shared_ptr EvioReaderV4::gotoEventNumber(size_t evNumber, bool parse) - { + std::shared_ptr EvioReaderV4::gotoEventNumber(size_t evNumber, bool parse) { // Lock this method - if (synchronized) - { + if (synchronized) { const std::lock_guard lock(mtx); } - if (closed) - { + if (closed) { throw EvioException("object closed"); } - if (!sequentialRead && evioVersion > 3) - { - try - { - if (parse) - { + if (!sequentialRead && evioVersion > 3) { + try { + if (parse) { return parseEvent(evNumber); } - else - { + else { return getEvent(evNumber); } } - catch (EvioException &e) - { + catch (EvioException & e) { return nullptr; } } @@ -1526,130 +1345,113 @@ namespace evio rewind(); std::shared_ptr event; - try - { + try { // get the first evNumber - 1 events without parsing - for (size_t i = 1; i < evNumber; i++) - { + for (size_t i = 1; i < evNumber; i++) { event = nextEvent(); - if (event == nullptr) - { + if (event == nullptr) { throw EvioException("Asked to go to event: " + std::to_string(evNumber) + ", which is beyond the end of file"); } } // get one more event, the evNumber'th event - if (parse) - { + if (parse) { return parseNextEvent(); } - else - { + else { return nextEvent(); } } - catch (EvioException &e) - { + catch (EvioException & e) { std::cout << e.what() << std::endl; } return nullptr; } + /** {@inheritDoc} */ - size_t EvioReaderV4::getEventCount() - { + size_t EvioReaderV4::getEventCount() { // Lock this method - if (synchronized) - { + if (synchronized) { const std::lock_guard lock(mtx); } - if (closed) - { - throw EvioException("object closed"); - } - - // sequentialRead is always false for reading buffer and - // always true for reading file. - if (!sequentialRead && evioVersion > 3) - { - // Already calculated by calling generateEventPositions in constructor ... - // std::cout << "EvioReaderV4 getEventCount: not seq read, event count = " << eventCount << std::endl; - return eventCount; - } - - if (eventCount < 0) - { - // The difficulty is that this method can be called at - // any time. So we need to save our state and then restore - // it when we're done. - ReaderState *state = getState(); - - rewind(); - eventCount = 0; + if (closed) { + throw EvioException("object closed"); + } - while (nextEvent() != nullptr) - { - // std::cout << "EvioReaderV4 getEventCount: add to eventCount (" << eventCount << ")" << std::endl; - eventCount++; + // sequentialRead is always false for reading buffer and + // always true for reading file. + if (!sequentialRead && evioVersion > 3) { + // Already calculated by calling generateEventPositions in constructor ... + //std::cout << "EvioReaderV4 getEventCount: not seq read, event count = " << eventCount << std::endl; + return eventCount; } - // If sequential access to v2 file, then nextEvent() places - // new data into byteBuffer. Restoring the original state - // is useless without also restoring/re-reading the data. - if (sequentialRead) - { + if (eventCount < 0) { + // The difficulty is that this method can be called at + // any time. So we need to save our state and then restore + // it when we're done. + ReaderState *state = getState(); + rewind(); + eventCount = 0; - // Skip dictionary - if (hasDictionaryXML()) - { - nextEvent(); + while (nextEvent() != nullptr) { + //std::cout << "EvioReaderV4 getEventCount: add to eventCount (" << eventCount << ")" << std::endl; + eventCount++; } - // Go back to original event # & therefore buffer data - for (uint32_t i = 1; i < state->eventNumber; i++) - { - nextEvent(); + // If sequential access to v2 file, then nextEvent() places + // new data into byteBuffer. Restoring the original state + // is useless without also restoring/re-reading the data. + if (sequentialRead) { + rewind(); + + // Skip dictionary + if (hasDictionaryXML()) { + nextEvent(); + } + + // Go back to original event # & therefore buffer data + for (uint32_t i=1; i < state->eventNumber; i++) { + nextEvent(); + } } - } - // Restore our original settings - restoreState(state); - } + // Restore our original settings + restoreState(state); + } - return eventCount; + return eventCount; } + /** {@inheritDoc} */ - size_t EvioReaderV4::getBlockCount() - { + size_t EvioReaderV4::getBlockCount() { // Lock this method - if (synchronized) - { + if (synchronized) { const std::lock_guard lock(mtx); } - if (closed) - { - throw EvioException("object closed"); - } + if (closed) { + throw EvioException("object closed"); + } - if (!sequentialRead && evioVersion > 3) - { - return blockCount; - } + if (!sequentialRead && evioVersion > 3) { + return blockCount; + } - if (blockCount < 0) - { - // Although block size is theoretically adjustable, I believe - // that everyone used 8192 words for the block size in version 3. - blockCount = (uint32_t)(fileBytes / firstBlockSize); - } + if (blockCount < 0) { + // Although block size is theoretically adjustable, I believe + // that everyone used 8192 words for the block size in version 3. + blockCount = (uint32_t) (fileBytes/firstBlockSize); + } - return blockCount; + return blockCount; } + } \ No newline at end of file From 62aea6b573097fb39323fd8ad4950ee506581b5f Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Tue, 8 Jul 2025 12:00:26 -0500 Subject: [PATCH 52/56] Update readme and CMakeLists.txt files, remove old tests and tutorials --- CMakeLists.txt | 2 +- README.md | 424 +++--------------- etc/README_v6.0.md | 412 +++++++++++++++++ src/test/cpp/BigFileWrite.cpp | 107 ----- src/test/cpp/BigFileWritePrimitive.cpp | 145 ------ src/test/cpp/ctest_test.cpp | 12 - src/test/cpp/evioReadTest.cpp | 62 --- src/test/java/FirstTest.java | 31 -- tutorials/README.md | 3 - tutorials/cpp/ConvertFormats.cpp | 121 ----- tutorials/cpp/EVIO_v4_to_v6.cpp | 57 --- tutorials/cpp/PrintXMLDict.cpp | 40 -- tutorials/cpp/ReadCLASFile.cpp | 86 ---- tutorials/cpp/ReadHIPO_clas_file.cpp | 48 -- .../WriteFilePseudoPhysicsEventExtended.cpp | 95 ---- 15 files changed, 468 insertions(+), 1177 deletions(-) create mode 100644 etc/README_v6.0.md delete mode 100644 src/test/cpp/BigFileWrite.cpp delete mode 100644 src/test/cpp/BigFileWritePrimitive.cpp delete mode 100644 src/test/cpp/ctest_test.cpp delete mode 100644 src/test/cpp/evioReadTest.cpp delete mode 100644 src/test/java/FirstTest.java delete mode 100644 tutorials/README.md delete mode 100644 tutorials/cpp/ConvertFormats.cpp delete mode 100644 tutorials/cpp/EVIO_v4_to_v6.cpp delete mode 100644 tutorials/cpp/PrintXMLDict.cpp delete mode 100644 tutorials/cpp/ReadCLASFile.cpp delete mode 100644 tutorials/cpp/ReadHIPO_clas_file.cpp delete mode 100644 tutorials/cpp/WriteFilePseudoPhysicsEventExtended.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index af387bd18..618fbb4e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,7 +98,7 @@ file(GLOB CPP_LIB_FILES "src/libsrc++/*.cpp") file(GLOB CPP_HEADER_FILES "src/libsrc++/*.h") # A few extras required if(MAKE_EXAMPLES) - file(GLOB TEST "src/test/cpp/*.cpp" "tutorials/cpp/*.cpp") + file(GLOB TEST "src/test/cpp/*.cpp") file(GLOB TESTC "src/test/c/*.c") list(APPEND CPP_HEADER_FILES src/test/cpp/EvioTestHelper.h) # list(APPEND CPP_LIB_FILES src/test/cpp/EvioTestHelper.h) diff --git a/README.md b/README.md index ac8120009..4c53bbda6 100644 --- a/README.md +++ b/README.md @@ -1,400 +1,87 @@ ----------------------------- - -# **EVIO 6.0 SOFTWARE PACKAGE** - ----------------------------- - -EVIO stands for EVent Input/Output and contains libraries which read & write -data in its own unique format. It was created by the Data Acquisition (DAQ) group -and is now maintained by the Experimental Physics Software and Computing Infrastructure -(EPSCI) group at Thomas Jefferson National Accelerator Facility (Jefferson Lab). -It was originally used in the online DAQ as part of the CODA software, -but is now being used offline and in other applications as well. - -There is a C library as well as an independent C++ library which -is a port from the Java version. There are a few utility programs included. -The Java version is a library with an extensive, user-friendly -interface. There is an additional package containing a GUI for looking at -evio format data at the byte level. - -If you only plan to run C/C++ applications you can skip the Java -installation. If you only plan to use Java applications you can -you can skip the C/C++ installation. - -### **Main evio links:** +# **EVIO 6 SOFTWARE PACKAGE** - [EVIO Home Page](https://coda.jlab.org/drupal/content/event-io-evio/) +EVIO stands for EVent Input/Output, a unique data format developed by Jefferson Lab. +It was created by the Data Acquisition (DAQ) group and is maintained by the +Experimental Physics Software and Computing Infrastructure (EPSCI) group at Thomas +Jefferson National Accelerator Facility (JLab). - [EVIO on GitHub (**evio-6.0** branch)](https://github.com/JeffersonLab/evio) +This software repository allows one to read & write evio format data, within +either a C/C++ or Java programming environment. -### **GUI for viewing data in evio format:** +# **Getting Started** - [EVIO Event Viewer Home Page](https://coda.jlab.org/drupal/content/graphical-data-viewer) - - [EVIO Event Viewer on GitHub](https://github.com/JeffersonLab/JEventViewer) - ------------------------------ - -# **Documentation** - ----------------------------- - -Documentation on GitHub: +## **C/C++ Library** -* [All Documentation](https://jeffersonlab.github.io/evio) +To build C/C++ code from this repository: -Documentation on the home page: + git clone https://github.com/JeffersonLab/evio/ + cd evio; mkdir build + cmake -S . -B build + cmake --build build --parallel -* [User's Guide PDF](https://coda.jlab.org/drupal/content/evio-60-users-guide) -* [Javadoc for Java Library](https://coda.jlab.org/drupal/content/evio-60-javadoc) -* [Doxygen for C Library](https://coda.jlab.org/drupal/content/evio-60-doxygen-c) -* [Doxygen for C++ Libary](https://coda.jlab.org/drupal/content/evio-60-doxygen-c-0) +Note that during the cmake configure step (first of two `cmake` commands above), one can +toggle the following special flags: ----------------------------- +* `C_ONLY` : build C lib only, skip C++ (default `-DC_ONLY=0`) +* `MAKE_EXAMPLES`: build example/test programs (default `-DMAKE_EXAMPLES=0`) +* `USE_FILESYSTEMLIB`: ue C++17 instead of Boost (default `-DUSE_FILESYSTEMLIB=0`) +* `DISRUPTOR_FETCH`: allow CMake to download Disruptor if not found (default `-DDISRUPTOR_FETCH=1`) -# **C Library** ----------------------------- -The C library is called libevio. -It is a library with limited capabilities. In the past, this was acceptable because the evio -format was fairly simple. However, as its complexity has greatly expanded in this version, the C library will -be of very limited usefullness unless one is knowledgeable about all the intricacies of the format. +### Prerequisites -To compile it, follow the directions below for the C++ compilation which will include the C as well. -The C++ library is much more extensive in scope. -Having said that, the C library and executables can be compiled without any C++. This can be done in 2 ways: +C++ 17 or higher, `cmake`, `lz4`, `boost_system`, `boost_thread`, and `boost_chrono`. If LZ4 is not +already configured, it can be installed from [LZ4 on github](https://github.com/lz4/lz4). The boost +libraries are typically system-specific. - scons --C -or +## **Java Library** - mkdir build - cd build - cmake .. –DC_ONLY=1 +The Java version of evio (internally `org.jlab.coda.jevio`) can also be used for reading & writing +`.evio` format files. A "fat" jar file with all dependencies is included in the `java/jars` folder, +which should be all most users need to run and execute Java code utilizing the evio library. +Java 17 is the default version used, however the Java evio library should be compatible with all +java versions 8 and higher (note this has not been rigorously tested). If one wants to create a +new jar file for any reason (e.g. to modify Java versions), do: ----------------------------- + git clone https://github.com/JeffersonLab/evio/ + cd evio + mvn clean install -# **C++ Library** +### Prerequisites ----------------------------- -The C++ library is called libeviocc. -The current C++ evio library is entirely different from the previous version (5.2) as it has been ported -from the Java code. This was done for a number of reasons. -First, a much more comprehensive C++ library was desired than was currently existing. -Second, it needed major, new capabilities such as being able to (un)compress data. -Third, it had to use a new format developed from the merging of Java evio version 4 and the Java HIPO library. -Finally, the author and maintainer of the previous code was no longer working at Jefferson Lab. -The simplest solution was to port the well-tested Java code which avoided having to redesign complex software -from scratch. C++ evio is supported on both the MacOS and Linux platforms. C++ version 11 is used, -and gcc version 5 or higher is required. +Requires Maven (`mvn`) and an installation of Java on your system. +**Running on "ifarm" at JLab will not work unless you install java yourself**. Note that the default java versions on the farm will be too old to +work. See downloads from [OpenJDK](https://openjdk.org/install/) or [Oracle](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html). ----------------------------- -## **Prerequisites** - - -### Disruptor - - -Evio depends upon the Disruptor-cpp software package available from a fork of the original package at github at - -[C++ Disruptor Fork on Github](https://github.com/JeffersonLab/Disruptor-cpp) - -In terms of functionality, it is an ingenious, ultrafast ring buffer which was initially developed in Java -and then ported to C++. It’s extremely useful when splitting work among multiple threads and then recombining it. -To build it, do this on the Mac: - - git clone https://github.com/JeffersonLab/Disruptor-cpp.git - cd Disruptor-cpp - mkdir build - cd build - cmake .. - make - setenv DISRUPTOR_CPP_HOME <../> - -If using Jefferson Lab’s Redhat Enterprise 7 do: - - git clone https://github.com/JeffersonLab/Disruptor-cpp.git - cd Disruptor-cpp - mkdir build - cd build - cmake .. -DCMAKE_C_COMPILER=/apps/gcc/5.3.0/bin/gcc -DCMAKE_CXX_COMPILER=/apps/gcc/5.3.0/bin/g++ - make - setenv DISRUPTOR_CPP_HOME <../> - -Note that it requires GCC 5.0 / Clang 3.8 / C++14 or newer and boost. -Its shared library must be installed where evio can find it. -If not compiling on Jefferson Lab’s RHEL7, either your default compilers must meet this criteria -or you must specify the proper ones on the cmake command line. - - -### Boost - - -Besides the disruptor library, evio requires the boost libraries: boost_system, boost_thread, and boost_chrono. - - -### Lz4 - - -Finally, evio depends on the lz4 library for compressing data in the lz4 and gzip formats. -If it isn’t already available on your machine, it can be obtained from the -[lz4 repository on github](https://github.com/lz4/lz4): - - git clone https://github.com/lz4/lz4.git - cd lz4 - make - make install - - ------------------------------ -## **Building** - - -There are 2 different methods to build the C++ library and executables. -The first uses scons, a Python-based build software package which is available at https://scons.org. -The second uses cmake and make. Also, be sure you’ve set the DISRUPTOR_CPP_HOME environmental variable. - - -### Scons - - -To get a listing of all the local options available to the scons command, -run _**scons -h**_ in the top-level directory to get this output: - - -D build from subdirectory of package - local scons OPTIONS: - --C compile C code only - --dbg compile with debug flag - --32bits compile 32bit libs & executables on 64bit system - --prefix= use base directory when doing install - --incdir= copy header files to directory when doing install - --libdir= copy library files to directory when doing install - --bindir= copy binary files to directory when doing install - install install libs, headers, and binaries - install -c uninstall libs, headers, and binaries - doc create doxygen and javadoc (in ./doc) - undoc remove doxygen and javadoc (in ./doc) - tar create tar file (in ./tar) - - Use scons -H for help about command-line options. - - -Although fairly self-explanatory, if on Jefferson Lab's CUE system with Redhat 7, executing: - - use gcc/5.3.0 - cd - scons install or - scons –-prefix=/my/installation/directory install - -will compile and install all the code. -Note that for C/C++, only Linux and Darwin (Mac OSX) operating systems are supported. -By default, the libraries and executables are placed into the _**$CODA/[arch]/lib**_ and _**bin**_ subdirectories -(eg. Linux-x86_64/lib). If the command line options -–prefix, --incdir, --libdir, or –bindir are used, they take priority. -Be sure to change your LD_LIBRARY_PATH environmental variable to include the correct lib directory. - - -To compile a debug version, execute: - - scons install --dbg - - -### Cmake - - -**Preferable to scons, cmake is the best way to compile evio.** Experience shows that cmake is -simpler, more powerful and more complete than scons. If the disruptor library is not -immediately accessible, cmake can automatically fetch and build it. -Cmake uses the included CMakeLists.txt file. - -To build the C and C++ libraries and executables, start with: - - cd - mkdir build - cd build - -At this point, several choices can be made. - -Evio will fetch and compile its own copy of the Disruptor if neither of the environmental variables -pointing to an existing Disruptor repository, DISRUPTOR_CPP_DIR or DISRUPTOR_CPP_HOME, is defined. -If an existing repository can be found, it will use the includes and libs found there. Simply do: - - cmake .. -To define the Disruptor location on the command line: +# **Useful Links** - cmake .. -DDISRUPTOR_CPP_HOME= or - cmake .. -DDISRUPTOR_CPP_DIR= - -To force Disruptor to be used from an existing local directory: - - cmake .. -DDISRUPTOR_ALLOW_FETCH=OFF -DDISRUPTOR_CPP_HOME= - -When using C++17 and later, #include can be used to access the routines in std::filesystem to deal with the local file system. This can be turned on by defining USE_FILESYSTEMLIB when running cmake. - - cmake .. -DUSE_FILESYSTEMLIB=ON … - -In addition, one can create evioConfig.cmake during install. This allows users to simply use find_package(evio) in their CMake setups. - -If you happen to be building on an older version of linux, such as redhat 7, you’ll need to make sure your g++ is at least version 5. This may look like: - - cmake .. -DCMAKE_C_COMPILER=/apps/gcc/5.3.0/bin/gcc - -DCMAKE_CXX_COMPILER=/apps/gcc/5.3.0/bin/g++ … - -To build only C code, place –DC_ONLY=1 on the cmake command line: - - cmake .. -DC_ONLY=1 … - -To build all the examples as well as libs and programs, place –DMAKE_EXAMPLES=1 on the cmake command line. - - cmake .. -DMAKE_EXAMPLES=1 … - -One can also define the directory in which to install the resulting libs, includes and executables upon compilation: - - cmake .. -DINSTALL= … - -So, for compiling C++ code while fetching the Disruptor and making examples, one might do something like: - - cmake .. -DMAKE_EXAMPLES=1 - -The final step is to call make: - - make -j 4 install - -To uninstall simply do: - - make uninstall - - - - ------------------------------- - -# **Java** - ------------------------------- - - -The current Java evio package, org.jlab.coda.jevio, was originally written by Dr. Dave Heddle of CNU -and was graciously given to the JLAB DAQ group for maintenance and continued development. -A large amount of additional work has been done since that time. As previously mentioned, -evio now uses a new format developed from the merging of evio version 4 and the HIPO library. -The code will compile using Java version 8 or later. - -The jar files necessary to compile an evio jar file are in the java/jars directory. -They are compiled with Java 8. In addition, there are 2 subdirectories: - - * java8, which contains all such jars compiled with Java 8, and - * java15 which contains all jars compiled with Java 15. - -If a jar file is not available in Java 15 use the Java 8 version. - -A pre-compiled _**jevio-6.0.jar**_ file is found in each of these subdirectories. -Using these allows the user to skip over all the following compilation instructions. - - ------------------------------ -## **Prerequisites** - - -### Disruptor - - -Evio depends upon the LMAX-Exchange/disruptor software package available from github whose fork is at: - -[Original Disruptor Fork on Github](https://github.com/JeffersonLab/disruptor) - -In terms of functionality, it is an ingenious, ultrafast ring buffer which was initially developed -for use the in the commodities exchange markets. It’s extremely useful when splitting work among -multiple threads and then recombining it. Although there are many branches in this git repository, -only 2 branches have had the necessary changes to be compatible with CODA. -These are the master and v3.4 branches. The v3.4 branch should be compiled with Java 8 -(it does not compile with Java 15) while the master requires at least Java 11. - -The disruptor software is provided in the _**java/jars/disruptor-3.4.3.jar**_ file (compiled with Java 8). -However, to generate this file yourself, get the disruptor software package by simply doing the following: - - git clone https://github.com/JeffersonLab/disruptor.git - cd disruptor - git checkout v3.4 - ./gradlew - -The resulting disruptor jar file, disruptor-3.4.3.jar, will be found in the disruptor package’s build/libs subdirectory. - -One can also use the master branch which needs to be compiled with Java version 11 or greater and produces disruptor-4.0.0.jar. -Currently this has been created with java15 and is in the java/jars/java15 directory. Here is how to generate it: - - git clone https://github.com/JeffersonLab/disruptor.git - cd disruptor - ./gradlew - -The resulting jar will be in build/libs as before. - - -### Lz4 - - -A lz4 data compression software is provided in the _**java/jars/lz4-java-1.8.0.jar**_ file (compiled with Java 8). -Although this is available in various versions and locations on the web, one can generate this from its source which is the -[lz4/lz4-java repository on github](https://github.com/lz4/lz4-java): - - git clone https://github.com/lz4/lz4-java.git - cd lz4-java - ant ivy-bootstrap - ant submodule init - ant submodule update - ant - -Generated jar files will be in dist subdirectory. - -Another jar file, AHACompressionAPI.jar, also in the the java/jars directory, is for use in Compressor.java -when using the AHA374 FPGA data compression board for gzip compression in hardware. -This is an effort that never took off since LZ4 compresssion was so much more efficient. -Thus, it may be safely ignored or removed. - - ------------------------------ -## **Building** - - -The java evio uses ant to compile. To get a listing of all the options available to the ant command, run +---------------------------- - ant help +Documentation on GitHub: -in the evio top level directory to get this output: +* [All Documentation](https://jeffersonlab.github.io/evio) +* [User's Guide PDF](https://jeffersonlab.github.io/evio/doc-6.0/users_guide/evio_Users_Guide.pdf) +* [EVIO Data Format Reference](https://jeffersonlab.github.io/evio/doc-6.0/format_guide/evio_Formats.pdf) - help: - [echo] Usage: ant [ant options] [target2 | target3 | ...] - - [echo] targets: - [echo] help - print out usage - [echo] env - print out build file variables' values - [echo] compile - compile java files - [echo] clean - remove class files - [echo] cleanall - remove all generated files - [echo] jar - compile and create jar file - [echo] install - create jar file and install into 'prefix' - [echo] if given on command line by -Dprefix=dir', - [echo] else install into CODA if defined - [echo] uninstall - remove jar file previously installed into 'prefix' - [echo] if given on command line by -Dprefix=dir', - [echo] else installed into CODA if defined - [echo] all - clean, compile and create jar file - [echo] javadoc - create javadoc documentation - [echo] developdoc - create javadoc documentation for developer - [echo] undoc - remove all javadoc documentation - [echo] prepare - create necessary directories +Software Library Documentation: +* [Javadoc for Java Library](https://jeffersonlab.github.io/evio/doc-6.0/javadoc/index.html) +* [Doxygen for C Library](https://jeffersonlab.github.io/evio/doc-6.0/doxygen/C/html/index.html) +* [Doxygen for C++ Libary](https://jeffersonlab.github.io/evio/doc-6.0/doxygen/CC/html/index.html) -Although this is fairly self-explanatory, executing _**ant**_ is the same as ant compile. -That will compile all the java. All compiled code is placed in the generated _**jbuild**_ directory. -If the user wants a jar file, execute +Other Links: +* [EVIO Event Viewer on GitHub](https://github.com/JeffersonLab/JEventViewer) - ant jar -to place the resulting file in the _**jbuild/lib**_ directory. -The java command in the user’s path will be the one used to do the compilation. +The EVIO-6 data format is closely related to the HIPO data format, following the same data +framework to the record level. Beyond this level, they differ in the way data is stored as +well as the software used to read and write to these respective `.evio` and `.hipo` formats. +More information on the HIPO data format can be found at https://github.com/gavalian/hipo, +or from the CLAS12 Software Project Coordinator. ---------------------------- @@ -403,4 +90,3 @@ The java command in the user’s path will be the one used to do the compilation ---------------------------- For any issues regarding use and copyright, read the [license](LICENSE.txt) file. - diff --git a/etc/README_v6.0.md b/etc/README_v6.0.md new file mode 100644 index 000000000..55cedf6d6 --- /dev/null +++ b/etc/README_v6.0.md @@ -0,0 +1,412 @@ + + +---------------------------- + +# **EVIO 6.0 SOFTWARE PACKAGE** + +This may useful for some historical reference, as it represents a record of commands and +setup used prior to the change to Alma Linux as Jefferson Lab's preferred distro for on-site +resources. + +---------------------------- + +EVIO stands for EVent Input/Output and contains libraries which read & write +data in its own unique format. It was created by the Data Acquisition (DAQ) group +and is now maintained by the Experimental Physics Software and Computing Infrastructure +(EPSCI) group at Thomas Jefferson National Accelerator Facility (Jefferson Lab). +It was originally used in the online DAQ as part of the CODA software, +but is now being used offline and in other applications as well. + +There is a C library as well as an independent C++ library which +is a port from the Java version. There are a few utility programs included. +The Java version is a library with an extensive, user-friendly +interface. There is an additional package containing a GUI for looking at +evio format data at the byte level. + +If you only plan to run C/C++ applications you can skip the Java +installation. If you only plan to use Java applications you can +you can skip the C/C++ installation. + +### **Main evio links:** + + [EVIO Home Page](https://coda.jlab.org/drupal/content/event-io-evio/) + + [EVIO on GitHub (**evio-6.0** branch)](https://github.com/JeffersonLab/evio) + +### **GUI for viewing data in evio format:** + + [EVIO Event Viewer Home Page](https://coda.jlab.org/drupal/content/graphical-data-viewer) + + [EVIO Event Viewer on GitHub](https://github.com/JeffersonLab/JEventViewer) + +----------------------------- + +# **Documentation** + +---------------------------- + +Documentation on GitHub: + +* [All Documentation](https://jeffersonlab.github.io/evio) + +Documentation on the home page: + +* [User's Guide PDF](https://coda.jlab.org/drupal/content/evio-60-users-guide) +* [Javadoc for Java Library](https://coda.jlab.org/drupal/content/evio-60-javadoc) +* [Doxygen for C Library](https://coda.jlab.org/drupal/content/evio-60-doxygen-c) +* [Doxygen for C++ Libary](https://coda.jlab.org/drupal/content/evio-60-doxygen-c-0) + +---------------------------- + +# **C Library** + +---------------------------- +The C library is called libevio. +It is a library with limited capabilities. In the past, this was acceptable because the evio +format was fairly simple. However, as its complexity has greatly expanded in this version, the C library will +be of very limited usefullness unless one is knowledgeable about all the intricacies of the format. + +To compile it, follow the directions below for the C++ compilation which will include the C as well. +The C++ library is much more extensive in scope. +Having said that, the C library and executables can be compiled without any C++. This can be done in 2 ways: + + scons --C +or + + mkdir build + cd build + cmake .. –DC_ONLY=1 + + +---------------------------- + +# **C++ Library** + +---------------------------- +The C++ library is called libeviocc. +The current C++ evio library is entirely different from the previous version (5.2) as it has been ported +from the Java code. This was done for a number of reasons. +First, a much more comprehensive C++ library was desired than was currently existing. +Second, it needed major, new capabilities such as being able to (un)compress data. +Third, it had to use a new format developed from the merging of Java evio version 4 and the Java HIPO library. +Finally, the author and maintainer of the previous code was no longer working at Jefferson Lab. +The simplest solution was to port the well-tested Java code which avoided having to redesign complex software +from scratch. C++ evio is supported on both the MacOS and Linux platforms. C++ version 11 is used, +and gcc version 5 or higher is required. + + +----------------------------- +## **Prerequisites** + + +### Disruptor + + +Evio depends upon the Disruptor-cpp software package available from a fork of the original package at github at + +[C++ Disruptor Fork on Github](https://github.com/JeffersonLab/Disruptor-cpp) + +In terms of functionality, it is an ingenious, ultrafast ring buffer which was initially developed in Java +and then ported to C++. It’s extremely useful when splitting work among multiple threads and then recombining it. +To build it, do this on the Mac: + + git clone https://github.com/JeffersonLab/Disruptor-cpp.git + cd Disruptor-cpp + mkdir build + cd build + cmake .. + make + setenv DISRUPTOR_CPP_HOME <../> + +If using Jefferson Lab’s Redhat Enterprise 7 do: + + git clone https://github.com/JeffersonLab/Disruptor-cpp.git + cd Disruptor-cpp + mkdir build + cd build + cmake .. -DCMAKE_C_COMPILER=/apps/gcc/5.3.0/bin/gcc -DCMAKE_CXX_COMPILER=/apps/gcc/5.3.0/bin/g++ + make + setenv DISRUPTOR_CPP_HOME <../> + +Note that it requires GCC 5.0 / Clang 3.8 / C++14 or newer and boost. +Its shared library must be installed where evio can find it. +If not compiling on Jefferson Lab’s RHEL7, either your default compilers must meet this criteria +or you must specify the proper ones on the cmake command line. + + +### Boost + + +Besides the disruptor library, evio requires the boost libraries: boost_system, boost_thread, and boost_chrono. + + +### Lz4 + + +Finally, evio depends on the lz4 library for compressing data in the lz4 and gzip formats. +If it isn’t already available on your machine, it can be obtained from the +[lz4 repository on github](https://github.com/lz4/lz4): + + git clone https://github.com/lz4/lz4.git + cd lz4 + make + make install + + +----------------------------- +## **Building** + + +There are 2 different methods to build the C++ library and executables. +The first uses scons, a Python-based build software package which is available at https://scons.org. +The second uses cmake and make. Also, be sure you’ve set the DISRUPTOR_CPP_HOME environmental variable. + + +### Scons + + +To get a listing of all the local options available to the scons command, +run _**scons -h**_ in the top-level directory to get this output: + + -D build from subdirectory of package + local scons OPTIONS: + --C compile C code only + --dbg compile with debug flag + --32bits compile 32bit libs & executables on 64bit system + --prefix= use base directory when doing install + --incdir= copy header files to directory when doing install + --libdir= copy library files to directory when doing install + --bindir= copy binary files to directory when doing install + install install libs, headers, and binaries + install -c uninstall libs, headers, and binaries + doc create doxygen and javadoc (in ./doc) + undoc remove doxygen and javadoc (in ./doc) + tar create tar file (in ./tar) + + Use scons -H for help about command-line options. + + +Although fairly self-explanatory, if on Jefferson Lab's CUE system with Redhat 7, executing: + + use gcc/5.3.0 + cd + scons install or + scons –-prefix=/my/installation/directory install + +will compile and install all the code. +Note that for C/C++, only Linux and Darwin (Mac OSX) operating systems are supported. +By default, the libraries and executables are placed into the _**$CODA/[arch]/lib**_ and _**bin**_ subdirectories +(eg. Linux-x86_64/lib). If the command line options +–prefix, --incdir, --libdir, or –bindir are used, they take priority. +Be sure to change your LD_LIBRARY_PATH environmental variable to include the correct lib directory. + + +To compile a debug version, execute: + + scons install --dbg + + +### Cmake + + +**Preferable to scons, cmake is the best way to compile evio.** Experience shows that cmake is +simpler, more powerful and more complete than scons. If the disruptor library is not +immediately accessible, cmake can automatically fetch and build it. +Cmake uses the included CMakeLists.txt file. + +To build the C and C++ libraries and executables, start with: + + cd + mkdir build + cd build + +At this point, several choices can be made. + +Evio will fetch and compile its own copy of the Disruptor if neither of the environmental variables +pointing to an existing Disruptor repository, DISRUPTOR_CPP_DIR or DISRUPTOR_CPP_HOME, is defined. +If an existing repository can be found, it will use the includes and libs found there. Simply do: + + cmake .. + +To define the Disruptor location on the command line: + + cmake .. -DDISRUPTOR_CPP_HOME= or + cmake .. -DDISRUPTOR_CPP_DIR= + +To force Disruptor to be used from an existing local directory: + + cmake .. -DDISRUPTOR_ALLOW_FETCH=OFF -DDISRUPTOR_CPP_HOME= + +When using C++17 and later, #include can be used to access the routines in std::filesystem to deal with the local file system. This can be turned on by defining USE_FILESYSTEMLIB when running cmake. + + cmake .. -DUSE_FILESYSTEMLIB=ON … + +In addition, one can create evioConfig.cmake during install. This allows users to simply use find_package(evio) in their CMake setups. + +If you happen to be building on an older version of linux, such as redhat 7, you’ll need to make sure your g++ is at least version 5. This may look like: + + cmake .. -DCMAKE_C_COMPILER=/apps/gcc/5.3.0/bin/gcc + -DCMAKE_CXX_COMPILER=/apps/gcc/5.3.0/bin/g++ … + +To build only C code, place –DC_ONLY=1 on the cmake command line: + + cmake .. -DC_ONLY=1 … + +To build all the examples as well as libs and programs, place –DMAKE_EXAMPLES=1 on the cmake command line. + + cmake .. -DMAKE_EXAMPLES=1 … + +One can also define the directory in which to install the resulting libs, includes and executables upon compilation: + + cmake .. -DINSTALL= … + +So, for compiling C++ code while fetching the Disruptor and making examples, one might do something like: + + cmake .. -DMAKE_EXAMPLES=1 + +The final step is to call make: + + make -j 4 install + +To uninstall simply do: + + make uninstall + + + + +------------------------------ + +# **Java** + +------------------------------ + + +The current Java evio package, org.jlab.coda.jevio, was originally written by Dr. Dave Heddle of CNU +and was graciously given to the JLAB DAQ group for maintenance and continued development. +A large amount of additional work has been done since that time. As previously mentioned, +evio now uses a new format developed from the merging of evio version 4 and the HIPO library. +The code will compile using Java version 8 or later. + +The jar files necessary to compile an evio jar file are in the java/jars directory. +They are compiled with Java 8. In addition, there are 2 subdirectories: + + * java8, which contains all such jars compiled with Java 8, and + * java15 which contains all jars compiled with Java 15. + +If a jar file is not available in Java 15 use the Java 8 version. + +A pre-compiled _**jevio-6.0.jar**_ file is found in each of these subdirectories. +Using these allows the user to skip over all the following compilation instructions. + + +----------------------------- +## **Prerequisites** + + +### Disruptor + + +Evio depends upon the LMAX-Exchange/disruptor software package available from github whose fork is at: + +[Original Disruptor Fork on Github](https://github.com/JeffersonLab/disruptor) + +In terms of functionality, it is an ingenious, ultrafast ring buffer which was initially developed +for use the in the commodities exchange markets. It’s extremely useful when splitting work among +multiple threads and then recombining it. Although there are many branches in this git repository, +only 2 branches have had the necessary changes to be compatible with CODA. +These are the master and v3.4 branches. The v3.4 branch should be compiled with Java 8 +(it does not compile with Java 15) while the master requires at least Java 11. + +The disruptor software is provided in the _**java/jars/disruptor-3.4.3.jar**_ file (compiled with Java 8). +However, to generate this file yourself, get the disruptor software package by simply doing the following: + + git clone https://github.com/JeffersonLab/disruptor.git + cd disruptor + git checkout v3.4 + ./gradlew + +The resulting disruptor jar file, disruptor-3.4.3.jar, will be found in the disruptor package’s build/libs subdirectory. + +One can also use the master branch which needs to be compiled with Java version 11 or greater and produces disruptor-4.0.0.jar. +Currently this has been created with java15 and is in the java/jars/java15 directory. Here is how to generate it: + + git clone https://github.com/JeffersonLab/disruptor.git + cd disruptor + ./gradlew + +The resulting jar will be in build/libs as before. + + +### Lz4 + + +A lz4 data compression software is provided in the _**java/jars/lz4-java-1.8.0.jar**_ file (compiled with Java 8). +Although this is available in various versions and locations on the web, one can generate this from its source which is the +[lz4/lz4-java repository on github](https://github.com/lz4/lz4-java): + + git clone https://github.com/lz4/lz4-java.git + cd lz4-java + ant ivy-bootstrap + ant submodule init + ant submodule update + ant + +Generated jar files will be in dist subdirectory. + +Another jar file, AHACompressionAPI.jar, also in the the java/jars directory, is for use in Compressor.java +when using the AHA374 FPGA data compression board for gzip compression in hardware. +This is an effort that never took off since LZ4 compresssion was so much more efficient. +Thus, it may be safely ignored or removed. + + +----------------------------- +## **Building** + + +The java evio uses ant to compile. To get a listing of all the options available to the ant command, run + + ant help + +in the evio top level directory to get this output: + + help: + [echo] Usage: ant [ant options] [target2 | target3 | ...] + + [echo] targets: + [echo] help - print out usage + [echo] env - print out build file variables' values + [echo] compile - compile java files + [echo] clean - remove class files + [echo] cleanall - remove all generated files + [echo] jar - compile and create jar file + [echo] install - create jar file and install into 'prefix' + [echo] if given on command line by -Dprefix=dir', + [echo] else install into CODA if defined + [echo] uninstall - remove jar file previously installed into 'prefix' + [echo] if given on command line by -Dprefix=dir', + [echo] else installed into CODA if defined + [echo] all - clean, compile and create jar file + [echo] javadoc - create javadoc documentation + [echo] developdoc - create javadoc documentation for developer + [echo] undoc - remove all javadoc documentation + [echo] prepare - create necessary directories + + +Although this is fairly self-explanatory, executing _**ant**_ is the same as ant compile. +That will compile all the java. All compiled code is placed in the generated _**jbuild**_ directory. +If the user wants a jar file, execute + + ant jar + +to place the resulting file in the _**jbuild/lib**_ directory. +The java command in the user’s path will be the one used to do the compilation. + +---------------------------- + +# **Copyright** + +---------------------------- + +For any issues regarding use and copyright, read the [license](LICENSE.txt) file. + diff --git a/src/test/cpp/BigFileWrite.cpp b/src/test/cpp/BigFileWrite.cpp deleted file mode 100644 index 220b9a8ec..000000000 --- a/src/test/cpp/BigFileWrite.cpp +++ /dev/null @@ -1,107 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include // open() -#include // close(), fsync() - -#include "eviocc.h" - -int main(int argc, char *argv[]) { - // Default parameters - std::string outFile = "output.evio"; - unsigned long long fileSize = 100 * 1024 * 1024; // 100 MB default - size_t bufferSize = 1024; // event payload size in bytes - int repeatCount = 1; - bool doSync = false; - bool debug = false; - - // Parse simple command-line flags - for (int i = 1; i < argc; ++i) { - std::string arg = argv[i]; - if ((arg == "-o" || arg == "--output") && i+1 < argc) { // i+1 logic ensures argument provided - outFile = argv[++i]; - } else if ((arg == "-s" || arg == "--size") && i+1 < argc) { - fileSize = std::stoull(argv[++i]); - } else if ((arg == "-b" || arg == "--bufsize") && i+1 < argc) { - bufferSize = std::stoul(argv[++i]); - } else if ((arg == "-n" || arg == "--repeat") && i+1 < argc) { - repeatCount = std::stoi(argv[++i]); - } else if (arg == "--sync") { - doSync = true; - } else if (arg == "--debug") { - debug = true; - } else { - std::cerr << "Usage: " << argv[0] - << " -o -s -b " - << " -n [--sync] [--debug]\n"; - return 1; - } - } - - // Create dummy data buffer to fill each event - std::vector data(bufferSize); - // Fill with non-zero pattern (optional) - for (size_t i = 0; i < bufferSize; ++i) { - data[i] = static_cast(i & 0xFF); - } - - // Prepare EVIO event builder for an event with UCHAR8 (8-bit) data - evio::EventBuilder builder(1, evio::DataType::UCHAR8, 1); - auto event = builder.getEvent(); - // Attach the dummy data to the event - builder.setUCharData(event, data.data(), data.size()); - builder.setAllHeaderLengths(); // ensure EVIO length fields are up-to-date - - // Calculate how many events to write to reach at least fileSize bytes - // (We ignore EVIO file header overhead for simplicity) - uint32_t eventBytes = event->getTotalBytes(); - unsigned long long eventsPerRun = - static_cast(std::ceil(double(fileSize) / eventBytes)); - - // Loop for the specified repeat count - double totalThroughput = 0.0; - for (int r = 0; r < repeatCount; ++r) { - // Open an EventWriter to write events to the file - evio::EventWriter writer(outFile, evio::ByteOrder::ENDIAN_LOCAL, false); - // Start timing - auto start = std::chrono::high_resolution_clock::now(); - // Write events repeatedly - for (unsigned long long i = 0; i < eventsPerRun; ++i) { - writer.writeEvent(event); // write the dummy event​:contentReference[oaicite:1]{index=1} - if (debug) { - static auto lastTime = start; - auto now = std::chrono::high_resolution_clock::now(); - auto us = std::chrono::duration_cast(now - lastTime).count(); - std::cout << "Event " << i+1 << " written in " << us << " us\n"; - lastTime = now; - } - } - writer.close(); // finish writing, flush any buffered records​:contentReference[oaicite:2]{index=2} - // Optionally force sync data to disk - if (doSync) { - int fd = ::open(outFile.c_str(), O_RDONLY); - if (fd != -1) { - ::fsync(fd); - ::close(fd); - } - } - auto end = std::chrono::high_resolution_clock::now(); - // Calculate throughput (MB/s). 1 MB = 10^6 bytes for this calculation. - std::chrono::duration secs = end - start; - unsigned long long bytesWritten = eventsPerRun * eventBytes; - double MBperSec = (bytesWritten / 1.0e6) / secs.count(); - totalThroughput += MBperSec; - std::cout.setf(std::ios::fixed); - std::cout.precision(2); - std::cout << "Run " << r+1 << ": Wrote " << bytesWritten - << " bytes in " << secs.count() << " s (throughput = " - << MBperSec << " MB/s)\n"; - } - if (repeatCount > 1) { - std::cout << "Average throughput over " << repeatCount - << " runs = " << (totalThroughput / repeatCount) << " MB/s\n"; - } -} diff --git a/src/test/cpp/BigFileWritePrimitive.cpp b/src/test/cpp/BigFileWritePrimitive.cpp deleted file mode 100644 index fdbca2d75..000000000 --- a/src/test/cpp/BigFileWritePrimitive.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "eviocc.h" - -int main(int argc, char *argv[]) { - // Default parameters - std::string outFile = "output.evio"; - unsigned long long fileSize = 100 * 1024 * 1024; // 100 MB default - size_t bufferSize = 1024; // event payload size in bytes - int repeatCount = 1; - bool doSync = false; - bool debug = false; - - // Parse simple command-line flags - for (int i = 1; i < argc; ++i) { - std::string arg = argv[i]; - if ((arg == "-o" || arg == "--output") && i+1 < argc) { // i+1 logic ensures argument provided - outFile = argv[++i]; - } else if ((arg == "-s" || arg == "--size") && i+1 < argc) { - fileSize = std::stoull(argv[++i]); - } else if ((arg == "-b" || arg == "--bufsize") && i+1 < argc) { - bufferSize = std::stoul(argv[++i]); - } else if ((arg == "-n" || arg == "--repeat") && i+1 < argc) { - repeatCount = std::stoi(argv[++i]); - } else if (arg == "--sync") { - doSync = true; - } else if (arg == "--debug") { - debug = true; - } else { - std::cerr << "Usage: " << argv[0] - << " -o -s -b " - << " -n [--sync] [--debug]\n"; - return 1; - } - } - - // Prepare dummy data - std::vector data(bufferSize); - for (size_t i = 0; i < bufferSize; ++i) { - data[i] = static_cast(i & 0xFF); - } - - // Build one dummy event using EventBuilder - evio::EventBuilder builder(1, evio::DataType::UCHAR8, 1); - auto event = builder.getEvent(); - builder.setUCharData(event, data.data(), data.size()); - builder.setAllHeaderLengths(); - uint32_t eventBytes = event->getTotalBytes(); // size of one event (bytes) - - // Compute number of events to write to reach fileSize - unsigned long long eventsPerRun = - static_cast(std::ceil(double(fileSize) / eventBytes)); - - // Retrieve binary representation of the event - std::vector eventBuffer(eventBytes); - event->write(eventBuffer.data(), evio::ByteOrder::ENDIAN_LOCAL); // serialize event to bytes​:contentReference[oaicite:9]{index=9} - - // EVIO file and record header construction (for one record containing all events) - const uint32_t FILE_HEADER_WORDS = 14; - const uint32_t RECORD_HEADER_WORDS = 14; - // Prepare file header (14 words) as per EVIO format version 6 - uint32_t fileHeader[FILE_HEADER_WORDS]; - uint32_t recordHeader[RECORD_HEADER_WORDS]; - // File Header fields (EVIO 6): - fileHeader[0] = 0x4556494F; // "EVIO" file type ID - fileHeader[1] = 1; // File number (for split files; 1 for single file) - fileHeader[2] = FILE_HEADER_WORDS; // Header length (words) - fileHeader[3] = 1; // Record count in file (we will use one record) - fileHeader[4] = 0; // Index array length (unused, 0) - fileHeader[5] = 6; // Bit info & Version: version=6, no extra flags - fileHeader[6] = 0; // User header length (no user header) - fileHeader[7] = 0xC0DA0100; // Magic number (endianness check) - // The remaining 6 words (user register 64-bit, trailer position 64-bit, user ints) set to 0: - fileHeader[8] = fileHeader[9] = 0; - fileHeader[10] = fileHeader[11] = 0; - fileHeader[12] = fileHeader[13] = 0; - // Record Header fields (EVIO 6): - uint32_t recordLenWords = RECORD_HEADER_WORDS + eventsPerRun * (eventBytes / 4); - recordHeader[0] = recordLenWords; // Record length in words (including this header) - recordHeader[1] = 1; // Record (block) number - recordHeader[2] = RECORD_HEADER_WORDS; // Header length in words - recordHeader[3] = (uint32_t) eventsPerRun;// Event count in this record - recordHeader[4] = 0; // Index array length (no event index) - recordHeader[5] = 0x206; // Bit info & Version: 0x200 (last record flag) | 0x6 (version 6) - recordHeader[6] = 0; // Reserved / user header length (unused here) - recordHeader[7] = 0xC0DA0100; // Magic number - // Remaining 6 words of record header: - recordHeader[8] = recordHeader[9] = 0; // (possibly uncompressed length or user info, not used) - recordHeader[10] = recordHeader[11] = 0; // (reserved/trailer info, not used) - recordHeader[12] = recordHeader[13] = 0; // User integers (unused) - - double totalThroughput = 0.0; - for (int r = 0; r < repeatCount; ++r) { - // Open output file with low-level POSIX API - int fd = ::open(outFile.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644); - if (fd < 0) { - std::cerr << "Cannot open output file " << outFile << "\n"; - return 1; - } - // Start timing - auto start = std::chrono::high_resolution_clock::now(); - // Write file header (uncompressed, 56 bytes for 14 words) - ::write(fd, fileHeader, FILE_HEADER_WORDS * sizeof(uint32_t)); - // Write record header (56 bytes) - ::write(fd, recordHeader, RECORD_HEADER_WORDS * sizeof(uint32_t)); - // Write events in a loop - for (unsigned long long i = 0; i < eventsPerRun; ++i) { - ::write(fd, eventBuffer.data(), eventBytes); - if (debug) { - static auto lastTime = start; - auto now = std::chrono::high_resolution_clock::now(); - auto us = std::chrono::duration_cast(now - lastTime).count(); - std::cout << "Event " << i+1 << " written in " << us << " us\n"; - lastTime = now; - } - } - // Optional sync to disk - if (doSync) { - ::fsync(fd); - } - ::close(fd); - auto end = std::chrono::high_resolution_clock::now(); - // Calculate throughput - std::chrono::duration secs = end - start; - unsigned long long bytesWritten = (FILE_HEADER_WORDS + RECORD_HEADER_WORDS) * 4 - + eventsPerRun * eventBytes; - double MBperSec = (bytesWritten / 1.0e6) / secs.count(); - totalThroughput += MBperSec; - std::cout.setf(std::ios::fixed); - std::cout.precision(2); - std::cout << "Run " << r+1 << ": Wrote " << bytesWritten - << " bytes in " << secs.count() << " s (throughput = " - << MBperSec << " MB/s)\n"; - } - if (repeatCount > 1) { - std::cout << "Average throughput over " << repeatCount - << " runs = " << (totalThroughput / repeatCount) << " MB/s\n"; - } -} diff --git a/src/test/cpp/ctest_test.cpp b/src/test/cpp/ctest_test.cpp deleted file mode 100644 index 3bde2d69d..000000000 --- a/src/test/cpp/ctest_test.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include -#include "eviocc.h" - -int main() { - // Example test: simple arithmetic - assert(1 + 1 == 2); - std::cout << "Basic arithmetic test passed.\n"; - - std::cout << "All tests passed.\n"; - return 0; -} diff --git a/src/test/cpp/evioReadTest.cpp b/src/test/cpp/evioReadTest.cpp deleted file mode 100644 index 7a3cd7dd9..000000000 --- a/src/test/cpp/evioReadTest.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// Description: Test program to read an evio file and print its contents. -// This taken mostly from ReadWriteV4Test.cpp -#include -#include -#include -#include - - -using namespace std; -using namespace evio; - -void readFile(string finalFilename) { - - std::cout << std::endl; - std::cout << "--------------------------------------------" << std::endl; - std::cout << "---------- Read from file --------------" << std::endl; - std::cout << "--------------------------------------------" << std::endl; - - EvioReader reader(finalFilename); - ByteOrder & order = reader.getByteOrder(); - - cout << "Read in file " << finalFilename << " of byte order " << order.getName() << endl; - cout << "Evio version: " << reader.getEvioVersion() << endl; - int32_t evCount = reader.getEventCount(); - cout << "Got " << evCount << " events" << endl; - - string dict = reader.getDictionaryXML(); - if (dict.empty()) { - cout << "\nNo dictionary" << endl; - } - else { - cout << "\nGot dictionary:\n" << dict << endl; - } - - auto pFE = reader.getFirstEvent(); - if (pFE != nullptr) { - cout << "\nGot first Event:\n" << pFE->toString() << endl << endl; - } - else { - cout << "\nNo first event" << endl; - } - - cout << "Print out regular events:" << endl; - - for (int i=0; i < evCount; i++) { - auto ev = reader.getEvent(i+1); - cout << "\nEvent" << (i+1) << ":\n" << ev->toString() << endl; - } -} - -int main(int argc, char **argv) { - - if( argc > 1 ) { - string filename = argv[1]; - readFile(filename); - }else{ - std::cout << "Usage: evioReadTest " << std::endl; - std::cout << " where is the path to an evio file" << std::endl; - } - - return 0; -} diff --git a/src/test/java/FirstTest.java b/src/test/java/FirstTest.java deleted file mode 100644 index 2ac9143e6..000000000 --- a/src/test/java/FirstTest.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2025. Jefferson Lab (JLab). All rights reserved. Permission - * to use, copy, modify, and distribute this software and its documentation for - * educational, research, and not-for-profit purposes, without fee and without a - * signed licensing agreement. - */ - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInfo; - -import org.jlab.coda.jevio.*; - -@Tag("fast") // Run when selecting "fast" category of tests - -class FirstTest { - - @Test - @DisplayName("My 1st JUnit 5 test! 😎") - void myFirstTest(TestInfo testInfo) { - - assertEquals(2, 1+1, "1 + 1 should equal 2"); - assertEquals("My 1st JUnit 5 test! 😎", testInfo.getDisplayName(), () -> "TestInfo is injected correctly"); - } - - - -} \ No newline at end of file diff --git a/tutorials/README.md b/tutorials/README.md deleted file mode 100644 index 903fcef5a..000000000 --- a/tutorials/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# **Code Tutorials** - -Examples for using the evio C/C++/Java libraries. These are intended as examples for developers using EVIO as just one package in a larger software suite. See contents within each folder for more information. \ No newline at end of file diff --git a/tutorials/cpp/ConvertFormats.cpp b/tutorials/cpp/ConvertFormats.cpp deleted file mode 100644 index bbedbe541..000000000 --- a/tutorials/cpp/ConvertFormats.cpp +++ /dev/null @@ -1,121 +0,0 @@ -#include -#include -#include -#include - -#include "eviocc.h" // EVIO-6 C++ API -using namespace evio; - -enum class Fmt { EVIO4, EVIO6, HIPO }; - -void usage(const char* prog) { - std::cerr << - "Usage: " << prog << " " - " \n"; - std::exit(1); -} - -Fmt parseFmt(const std::string& s) { - auto lo = s; std::transform(lo.begin(), lo.end(), lo.begin(), ::tolower); - if (lo=="evio4") return Fmt::EVIO4; - else if(lo=="evio6") return Fmt::EVIO6; - else if(lo=="hipo") return Fmt::HIPO; - usage("convert"); - return Fmt::EVIO6; // never reached -} - -int main(int argc, char* argv[]) { - if (argc!=5) usage(argv[0]); - std::string inFile = argv[1]; - Fmt inFmt = parseFmt(argv[2]); - std::string outFile = argv[3]; - Fmt outFmt = parseFmt(argv[4]); - - // Common EVIO parameters (tweak as desired) - uint32_t maxRecordBytes = 1000000; - uint32_t maxEventsPerRecord = 1000; - uint32_t bufferBytes = 1000000; - size_t bufferBytesSize = bufferBytes; - - // --- Set up reader --- - std::unique_ptr evioReader; - if (inFmt==Fmt::EVIO4 || inFmt==Fmt::EVIO6) evioReader = std::make_unique(inFile); - - // Pull dictionary XML (if present) - std::string dictXml = ""; - if (evioReader->hasDictionaryXML()) { - dictXml = evioReader->getDictionaryXML(); // preserves dictionary in user‐header :contentReference[oaicite:0]{index=0} - std::cerr << "Dictionary XML: " << dictXml << "\n"; - } - else std::cerr << "No dictionary XML found in input file.\n"; - - - // --- Set up writer --- - std::unique_ptr evioWriter; - std::unique_ptr evioWriterV4; - - if (outFmt==Fmt::EVIO6) { - evioWriter = std::make_unique( - outFile, - "", "", - 1, 0, - maxRecordBytes, maxEventsPerRecord, - ByteOrder::ENDIAN_LOCAL, - dictXml, // xml dictionary - true, false, // overwrite existing, no append - nullptr, 1, 0, 1, 1, - Compressor::CompressionType::UNCOMPRESSED, // use LZ4 compression to trigger HIPO format - 0, 0, - bufferBytes); - } - else if (outFmt==Fmt::EVIO4) { - evioWriterV4 = std::make_unique( - outFile, - "", "", - 1, 0, - maxRecordBytes, maxEventsPerRecord, - ByteOrder::ENDIAN_LOCAL, - dictXml, // xml dictionary - true, false, // overwrite existing, no append - nullptr, 1, 0, 1, 1, - bufferBytesSize); - } - else { - evioWriter = std::make_unique( - outFile, - "", "", - 1, 0, - maxRecordBytes, maxEventsPerRecord, - ByteOrder::ENDIAN_LOCAL, - dictXml, // xml dictionary - true, false, // overwrite existing, no append - nullptr, 1, 0, 1, 1, - Compressor::CompressionType::LZ4, // use LZ4 compression to trigger HIPO format - 0, 0, - bufferBytes); - } - - - // --- Conversion loop --- - try { - // EVIO → ... - if (evioReader) { - std::shared_ptr ev; - while ((ev = evioReader->parseNextEvent())) { - if (evioWriter) { - evioWriter->writeEvent(ev); - } - } - } - - // flush/close - if (evioWriter) evioWriter->close(); - - std::cout<<"Conversion complete.\n"; - } - catch (const std::exception &e) { - std::cerr<<"Error during conversion: "< -#include - -// Include EVIO6 C++ headers (adjust the include paths as needed for your installation) -#include "eviocc.h" // EVIO C++ API (EVIO 6 main branch) - -// Use the EVIO namespace for convenience -using namespace evio; - -int main(int argc, char* argv[]) { - if (argc < 2) { - std::cerr << "Usage: " << argv[0] << " " << std::endl; - return 1; - } - std::string f_in = argv[1]; - std::string f_out = argv[2]; - - // Read / write parameters - uint32_t maxRecordBytes = 1000000; - uint32_t maxEventsPerRecord = 1000; - uint32_t bufferBytes = 1000000; - - - try { - // Open the EVIO6 file using EvioReader - EvioReader reader(f_in); - // EvioCompactReader reader(f_in); - - EventWriter writer(f_out, "", "", 1, 0, - maxRecordBytes, maxEventsPerRecord, - ByteOrder::ENDIAN_LOCAL, "", true, false, - nullptr, 1, 0, 1, 1, - Compressor::CompressionType::UNCOMPRESSED, - 0, 0, bufferBytes); - - // 5. Loop over all regular events and write them out - std::shared_ptr event; - while ((event = reader.parseNextEvent()) != nullptr) { - writer.writeEvent(event); - } - - // 6. Close writer to flush data and finalize file - writer.close(); - std::cout << "Conversion complete. Output file contains " - << reader.getEventCount() << " events (plus any first event/dictionary)." << std::endl; - } - - - - - catch (const std::exception& e) { - std::cerr << "Error: could not open and convert " << e.what() << std::endl; - return 1; - } - - return 0; -} diff --git a/tutorials/cpp/PrintXMLDict.cpp b/tutorials/cpp/PrintXMLDict.cpp deleted file mode 100644 index 61fe44f63..000000000 --- a/tutorials/cpp/PrintXMLDict.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include - -// Include EVIO6 C++ headers (adjust the include paths as needed for your installation) -#include "eviocc.h" // EVIO C++ API (EVIO 6 main branch) - -// Use the EVIO namespace for convenience -using namespace evio; - -int main(int argc, char* argv[]) { - if (argc < 2) { - std::cerr << "Usage: " << argv[0] << " " << std::endl; - return 1; - } - std::string filename = argv[1]; - - try { - // Open the EVIO6 file using EvioReader - EvioReader reader(filename); - - // Check for an embedded XML dictionary - if (reader.hasDictionaryXML()) { - // Retrieve the raw XML dictionary text - std::string xmlDict = reader.getDictionaryXML(); - // Print the XML dictionary to standard output - std::cout << xmlDict; - if (!xmlDict.empty() && xmlDict.back() != '\n') { - std::cout << std::endl; // ensure a newline at end, if not already present - } - } else { - // No dictionary present in the file - std::cout << "No XML dictionary found." << std::endl; - } - } catch (const std::exception& e) { - std::cerr << "Error: Unable to read EVIO file. " << e.what() << std::endl; - return 1; - } - - return 0; -} diff --git a/tutorials/cpp/ReadCLASFile.cpp b/tutorials/cpp/ReadCLASFile.cpp deleted file mode 100644 index 8871d2329..000000000 --- a/tutorials/cpp/ReadCLASFile.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include - -#include "eviocc.h" // EVIO C++ API all inside - -// Use the EVIO namespace for convenience -using namespace evio; - -int main(int argc, char* argv[]) { - if (argc < 2) { - std::cerr << "Usage: " << argv[0] << " " << std::endl; - return 1; - } - std::string filename = argv[1]; - - int maxEvents = 10; // Maximum number of events to read - - try { - // Open the EVIO6 file using EvioReader - EvioReaderV4 reader(filename); - - // Check for an embedded XML dictionary - if (reader.hasDictionaryXML()) { - // Retrieve the raw XML dictionary text - std::string xmlDict = reader.getDictionaryXML(); - // Print the XML dictionary to standard output - std::cout << xmlDict; - if (!xmlDict.empty() && xmlDict.back() != '\n') std::cout << std::endl; // ensure a newline at end, if not already present - } else { - // No dictionary present in the file - std::cout << "No XML dictionary found." << std::endl; - } - - std::cout << "EVIO Ver: " << reader.getEvioVersion() << std::endl; - std::cout << "File Size: " << reader.fileSize() << std::endl; - std::cout << "Event count: " << reader.getEventCount() << std::endl; - std::cout << "Has first event?: " << reader.hasFirstEvent() << std::endl; - - for (uint32_t i = 0; i < reader.getEventCount(); i++) { - if(i+1 >= maxEvents) { - std::cout << "Reached maximum number of events to read: " << maxEvents << std::endl; - break; - } - std::shared_ptr ev = reader.parseEvent(i+1); - std::cout << " got & parsed ev " << (i+1) << std::endl; - std::cout << " event ->\n" << ev->toString() << std::endl; - auto& dataVec = ev->getRawBytes(); - std::cout << "Event has tag = " << ev->getHeader()->getTag() << std::endl; - std::cout << "Event structure type = " << ev->getStructureType().toString() << std::endl; - std::vector< std::shared_ptr< BaseStructure > > & children = ev->getChildren(); - std::cout << "Event has " << children.size() << " children" << std::endl; - std::shared_ptr< BaseStructure > child1 = children[0]; - for (size_t j = 0; j < children.size(); j++) { - std::cout << "Child " << j << " tag = " << children[j]->getStructureType().toString() << std::endl; - std::cout << "NChildren: " << children[j]->getChildCount() << std::endl; - - for (size_t k = 0; k < children[j]->getChildCount(); k++) { - std::cout << "Child " << j << ", subchild " << k << " " << children[j]->getChildAt(k)->getStructureType().toString() << std::endl; - std::cout << "Subchild " << k << " datatype: " << children[j]->getChildAt(k)->getHeader()->getDataType().toString() << std::endl; - std::cout << "nsubchildren: " << children[j]->getChildAt(k)->getChildCount() << std::endl; - std::cout << "num items stored: " << children[j]->getChildAt(k)->getNumberDataItems() << std::endl; - if(children[j]->getChildAt(k)->getHeader()->getDataType() == DataType::UINT32) { - std::cout << "Data: "; - std::vector< uint32_t > data_uint_vec = children[j]->getChildAt(k)->getUIntData(); - for (size_t l = 0; l < data_uint_vec.size(); l++) { - std::cout << data_uint_vec[l] << " "; - } - std::cout << std::endl; - } - } - std::cout << std::endl; - } - - - // Util::printBytes(dataVec.data(), dataVec.size()," Event #" + std::to_string(i+1)); - } - - - - } catch (const std::exception& e) { - std::cerr << "Error: Unable to read EVIO file. " << e.what() << std::endl; - return 1; - } - - return 0; -} diff --git a/tutorials/cpp/ReadHIPO_clas_file.cpp b/tutorials/cpp/ReadHIPO_clas_file.cpp deleted file mode 100644 index f5bf835cd..000000000 --- a/tutorials/cpp/ReadHIPO_clas_file.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include -#include - -#include "eviocc.h" // EVIO C++ API all inside - -// Use the EVIO namespace for convenience -using namespace evio; - -int main(int argc, char* argv[]) { - if (argc < 2) { - std::cerr << "Usage: " << argv[0] << " " << std::endl; - return 1; - } - std::string filename = argv[1]; - - int maxEvents = 10; // Maximum number of events to read - - try { - // Open the HIPO file using EvioReader - EvioReader reader(filename); - - // Check for an embedded XML dictionary - if (reader.hasDictionaryXML()) { - // Retrieve the raw XML dictionary text - std::string xmlDict = reader.getDictionaryXML(); - // Print the XML dictionary to standard output - std::cout << xmlDict; - if (!xmlDict.empty() && xmlDict.back() != '\n') std::cout << std::endl; // ensure a newline at end, if not already present - } else { - // No dictionary present in the file - std::cout << "No XML dictionary found." << std::endl; - } - - std::cout << "EVIO Ver: " << reader.getEvioVersion() << std::endl; - std::cout << "File Size: " << reader.fileSize() << std::endl; - std::cout << "Event count: " << reader.getEventCount() << std::endl; - std::cout << "Has first event?: " << reader.hasFirstEvent() << std::endl; - std::cout << "Byte order: " << reader.getByteOrder().getName() << std::endl; - std::cout << "Num blocks (aka records): " << reader.getBlockCount() << std::endl; - - - } catch (const std::exception& e) { - std::cerr << "Error: Unable to read HIPO file. " << e.what() << std::endl; - return 1; - } - - return 0; -} diff --git a/tutorials/cpp/WriteFilePseudoPhysicsEventExtended.cpp b/tutorials/cpp/WriteFilePseudoPhysicsEventExtended.cpp deleted file mode 100644 index 75bd59f5a..000000000 --- a/tutorials/cpp/WriteFilePseudoPhysicsEventExtended.cpp +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include -#include -#include -#include "eviocc.h" - -using namespace evio; - -int main(int argc, char** argv) { - if (argc < 2) { - std::cerr << "Usage: " << argv[0] << " \n"; - return 1; - } - int nEvents = std::stoi(argv[1]); - - // Output file names for EVIO4, EVIO6, and HIPO - std::string fileNameEvio4 = "events_v4.ev"; - std::string fileNameEvio6 = "events_v6.ev"; - std::string fileNameHipo = "events.hipo"; - - // Writing parameters (similar to minimal version) - uint32_t maxRecordBytes = 1000000; - uint32_t maxEventsPerRecord = 1000; - uint32_t bufferBytes = 1000000; - - // Create writers for EVIO4, EVIO6, and HIPO formats (same setup as minimal example) - EventWriterV4 writerV4(fileNameEvio4, "", "", 1, 0, // string baseName, string &directory, string &runType, uint32_t runNumber, uint64_t split - maxRecordBytes, maxEventsPerRecord, - ByteOrder::ENDIAN_LOCAL, "", true, false, //const ByteOrder &byteOrder, string &xmlDictionary, bool overWriteOK, bool append - nullptr, 0, 0, 1, 1, bufferBytes); // shared_ptr< EvioBank > firstEvent, uint32_t streamId, uint32_t splitNumber, uint32_t splitIncrement, uint32_t streamCount, Compressor::CompressionType compressionType, uint32_t compressionThreads, uint32_t ringSize, uint32_t bufferSize - - EventWriter writerV6(fileNameEvio6, "", "", 1, 0, - maxRecordBytes, maxEventsPerRecord, - ByteOrder::ENDIAN_LOCAL, "", true, false, - nullptr, 1, 0, 1, 1, - Compressor::CompressionType::UNCOMPRESSED, - 0, 0, bufferBytes); - - EventWriter writerHipo(fileNameHipo, "", "", 1, 0, - maxRecordBytes, maxEventsPerRecord, - ByteOrder::ENDIAN_LOCAL, "", true, false, - nullptr, 1, 0, 1, 1, - Compressor::CompressionType::UNCOMPRESSED, - 0, 0, bufferBytes); - - // Loop to build and write events - for (int i = 0; i < nEvents; ++i) { - // **Create a top-level event (bank of banks)** with tag=1, num=1 - EventBuilder builder(1, DataType::BANK, 1); - // Create the buffer to hold everything - // auto buffer = std::make_shared(8192); - // CompactEventBuilder builder(buffer); - std::shared_ptr event = builder.getEvent(); - - // Valid data types: int32, unint32, long64, ulong64, short16, ushort16, char8, uchar8, charstar8, float32, double64, bank, segment, tagsegment, composite, unknown32 - - // **Bank 1: Floats** – create a bank holding 4 float32 values - auto bankFloats = EvioBank::getInstance(10, DataType::FLOAT32, 1); - auto &fData = bankFloats->getFloatData(); - fData.assign(4, 0.0f); // four floats initialized to 0.0 - bankFloats->updateFloatData(); // update length for float data​:contentReference[oaicite:8]{index=8} - builder.addChild(event, bankFloats); // add this bank to the event​:contentReference[oaicite:9]{index=9} - - // **Bank 2: Integers** – create a bank holding some int32 values - auto bankInts = EvioBank::getInstance(11, DataType::INT32, 2); - auto &iData = bankInts->getIntData(); - iData.push_back(42); // add an integer value 42 - iData.push_back(42); // (for example, add twice to illustrate multiple entries) - bankInts->updateIntData(); // update length for int data - builder.addChild(event, bankInts); // add this bank to the event​:contentReference[oaicite:10]{index=10} - - // **Bank 3: Strings** – create a bank holding one or more strings - auto bankStrings = EvioBank::getInstance(12, DataType::CHARSTAR8, 3); - auto &sData = bankStrings->getStringData(); - sData.emplace_back("example"); // add a string value "example" - // (multiple strings can be added to this vector as needed) - bankStrings->updateStringData(); // update length for string data - builder.addChild(event, bankStrings); // add this bank to the event - - // At this point, `event` contains three child banks (float, int, string). - // **Write the constructed event to all three output files:** - writerV4.writeEvent(event); - writerV6.writeEvent(event); - writerHipo.writeEvent(event); - } - - // Close writers to flush and finalize files - writerV4.close(); - writerV6.close(); - writerHipo.close(); - - std::cout << "Wrote " << nEvents - << " composite events (floats+ints+strings) to EVIO4, EVIO6, and HIPO files.\n"; - return 0; -} From 9e36009795d11f36d726c7f69fe138777cad1a88 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Tue, 8 Jul 2025 12:03:08 -0500 Subject: [PATCH 53/56] Note about scons for the readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 4c53bbda6..c7bdb78be 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,8 @@ toggle the following special flags: * `USE_FILESYSTEMLIB`: ue C++17 instead of Boost (default `-DUSE_FILESYSTEMLIB=0`) * `DISRUPTOR_FETCH`: allow CMake to download Disruptor if not found (default `-DDISRUPTOR_FETCH=1`) +One can still also use `scons` instead of cmake to build the evio C/C++ library, though this feature +will not be supported in future releases. ### Prerequisites From 69d8a7e967f4fc315bd7d5833bcc51fde8a6a076 Mon Sep 17 00:00:00 2001 From: Jonathan Zarling Date: Tue, 8 Jul 2025 12:28:50 -0500 Subject: [PATCH 54/56] Update c_tests.yml --- .github/workflows/c_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/c_tests.yml b/.github/workflows/c_tests.yml index 0aa39e785..f1cf8a4b8 100644 --- a/.github/workflows/c_tests.yml +++ b/.github/workflows/c_tests.yml @@ -14,7 +14,7 @@ jobs: run: sudo apt-get update && sudo apt-get install -y cmake build-essential libboost-filesystem-dev libboost-thread-dev libboost-chrono-dev liblz4-dev doxygen - name: Configure CMake - run: cmake -S . -B build -DMAKE_EXAMPLES=1 + run: cmake -S . -B build -DMAKE_EXAMPLES=1 "-DCMAKE_CXX_FLAGS_DEBUG=-g -O0" - name: Build run: cmake --build build -- -j$(nproc) From c8728a5d7c4d05965f8e7ccc960cad13ad5b571a Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Tue, 8 Jul 2025 13:09:23 -0500 Subject: [PATCH 55/56] Fix debug postfix so github actions work --- .github/workflows/c_tests.yml | 2 +- CMakeLists.txt | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/c_tests.yml b/.github/workflows/c_tests.yml index f1cf8a4b8..0aa39e785 100644 --- a/.github/workflows/c_tests.yml +++ b/.github/workflows/c_tests.yml @@ -14,7 +14,7 @@ jobs: run: sudo apt-get update && sudo apt-get install -y cmake build-essential libboost-filesystem-dev libboost-thread-dev libboost-chrono-dev liblz4-dev doxygen - name: Configure CMake - run: cmake -S . -B build -DMAKE_EXAMPLES=1 "-DCMAKE_CXX_FLAGS_DEBUG=-g -O0" + run: cmake -S . -B build -DMAKE_EXAMPLES=1 - name: Build run: cmake --build build -- -j$(nproc) diff --git a/CMakeLists.txt b/CMakeLists.txt index 618fbb4e6..84f4ba016 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -253,9 +253,7 @@ if(NOT C_ONLY) endif() # Unit testing setup -# add_executable(test_basic src/test/cpp/test_basic.cpp) # Already done above -add_test(NAME ctest_test COMMAND bin/ctest_test-dbg) -add_test(NAME EvioWriteAndReadBack_builder COMMAND bin/EvioWriteAndReadBack_builder-dbg 10) +add_test(NAME EvioWriteAndReadBack_builder COMMAND bin/EvioWriteAndReadBack_builder 10) # Uninstall target # Removed for now, not yet compatible with building disruptor-cpp internally From 72bbdf430d44d6904a1ca42c7edb6ded1d6f14a0 Mon Sep 17 00:00:00 2001 From: Jon Zarling Date: Tue, 8 Jul 2025 13:18:27 -0500 Subject: [PATCH 56/56] Fix directory path for unit test output --- src/test/cpp/EvioTestHelper.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/cpp/EvioTestHelper.h b/src/test/cpp/EvioTestHelper.h index e07da544c..2c788b9dc 100644 --- a/src/test/cpp/EvioTestHelper.h +++ b/src/test/cpp/EvioTestHelper.h @@ -125,7 +125,7 @@ using namespace evio; std::string baseNameV4 = "testEventsV4_cppAPI.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. std::string baseNameV6 = "testEventsV6_cppAPI.evio"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. std::string baseNameHIPO = "testEventsHIPO_cppAPI.hipo"; // base name of file to be created. If split > 1, this is the base name of all files created. If split < 1, this is the name of the only file created. - std::string directory = "/home/jzarling/super_evio_dev/evio/tmp"; // directory in which file is to be placed + std::string directory = "./"; // directory in which file is to be placed private: