Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 18 additions & 19 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,30 +27,29 @@ find_package( Threads )

message( STATUS "CMAKE_BINARY_DIR" ${CMAKE_BINARY_DIR} )

# Define the output file for the git commit hash, and
# touch it in case we're starting from scratch.
# version.h carries the git provenance compiled into every daemon. It is
# generated into utils/ which is already on every include path.
#
set(GIT_COMMIT_FILE "${CMAKE_BINARY_DIR}/git_commit.txt")
file( TOUCH ${GIT_COMMIT_FILE} )
set( GEN_VERSION_ARGS
-DSRC_DIR=${CMAKE_SOURCE_DIR}
-DIN_FILE=${PROJECT_BASE_DIR}/utils/version.h.in
-DTMP_FILE=${CMAKE_BINARY_DIR}/version.h.tmp
-DOUT_FILE=${PROJECT_BASE_DIR}/utils/version.h
-P ${PROJECT_BASE_DIR}/utils/gen_version.cmake )

# Create a custom target with a command that runs every time make is invoked.
# This creates the file which contains SET commands to set cmake variables.
# Generate it now so that version.h exists for the first build.
#
add_custom_target(update_git_commit
COMMAND ${CMAKE_COMMAND} -E remove ${GIT_COMMIT_FILE}
COMMAND bash -c "echo -n set '\\( GIT_COMMIT_HASH ' " > ${GIT_COMMIT_FILE} &&
bash -c "git rev-parse HEAD " | awk '{print $0}' | xargs echo -n >> ${GIT_COMMIT_FILE} &&
bash -c "echo ' \\)'" >> ${GIT_COMMIT_FILE}
COMMAND bash -c "echo -n set '\\( PROJECT_BUILD_DATE ' " >> ${GIT_COMMIT_FILE} &&
bash -c "date +%Y-%m-%dT%H:%M:%S_%Z" | awk '{print $0}' | xargs echo -n >> ${GIT_COMMIT_FILE} &&
bash -c "echo ' \\)'" >> ${GIT_COMMIT_FILE}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Updating git commit hash file"
)
execute_process( COMMAND ${CMAKE_COMMAND} ${GEN_VERSION_ARGS} )

# include the git commit hash output file so that config files can use it
# and again on every build. Editing a file moves neither HEAD nor any
# CMakeLists, so nothing would re-run configure and a configure-time check
# would report a stale clean/dirty state. The script leaves version.h alone
# when nothing changed, so this does not force a rebuild every time.
#
INCLUDE( ${GIT_COMMIT_FILE} )
add_custom_target( update_version ALL
COMMAND ${CMAKE_COMMAND} ${GEN_VERSION_ARGS}
COMMENT "Checking git provenance"
)

# Here is everything to build
#
Expand Down
3 changes: 0 additions & 3 deletions Config/camerad.cfg.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@
# configuration file for camerad
# @CAMERAD_CFG_COMMENT@
# -----------------------------------------------------------------------------
GIT_HASH=@GIT_COMMIT_HASH@ # git commit hash
PROJ_BUILD_DATE=@PROJECT_BUILD_DATE@ # the last time make was run
# -----------------------------------------------------------------------------
IMDIR=/data # default root directory for images
BASENAME=ngps # default basename for images
BLKPORT=@CAMERAD_BLK_PORT@ # server blocking port
Expand Down
2 changes: 1 addition & 1 deletion acamd/acamd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ int main(int argc, char **argv) {
message.str(""); message << "[NOTICE] user id = " << uid << " group id = " << gid;
logwrite( function, message.str() );

message.str(""); message << "this version built " << BUILD_DATE << " " << BUILD_TIME;
message.str(""); message << "this version built " << get_build_time() << " from " << GIT_HASH_STR;
logwrite(function, message.str());

message.str(""); message << acamd.config.n_entries << " lines read from " << acamd.config.filename;
Expand Down
2 changes: 1 addition & 1 deletion calibd/calibd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ int main(int argc, char **argv) {
calibd.exit_cleanly();
}

message << "this version built " << BUILD_DATE << " " << BUILD_TIME;
message << "this version built " << get_build_time() << " from " << GIT_HASH_STR;
logwrite(function, message.str());

message.str(""); message << calibd.config.n_entries << " lines read from " << calibd.config.filename;
Expand Down
53 changes: 53 additions & 0 deletions camerad/astrocam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ namespace AstroCam {
// provider, keyed by topic. The JSON->FITS-keyword conversion is deferred
// to exposure lock-in (see do_expose / add_cached_telem).
//
void Interface::handletopic_acam( const nlohmann::json &jmessage ) {
std::unique_lock<std::mutex> lock(live_telemetry_mtx);
this->live_telemetry[Topic::ACAMD] = jmessage;
}
void Interface::handletopic_calib( const nlohmann::json &jmessage ) {
std::unique_lock<std::mutex> lock(live_telemetry_mtx);
this->live_telemetry[Topic::CALIBD] = jmessage;
Expand All @@ -87,6 +91,10 @@ namespace AstroCam {
std::unique_lock<std::mutex> lock(live_telemetry_mtx);
this->live_telemetry[Topic::POWERD] = jmessage;
}
void Interface::handletopic_slicecam( const nlohmann::json &jmessage ) {
std::unique_lock<std::mutex> lock(live_telemetry_mtx);
this->live_telemetry[Topic::SLICECAMD] = jmessage;
}
void Interface::handletopic_slit( const nlohmann::json &jmessage ) {
std::unique_lock<std::mutex> lock(live_telemetry_mtx);
this->live_telemetry[Topic::SLITD] = jmessage;
Expand Down Expand Up @@ -129,6 +137,38 @@ namespace AstroCam {
/***** AstroCam::Interface::get_live_airmass ********************************/


/***** AstroCam::Interface::get_live_provenance *****************************/
/**
* @brief return the build provenance of all running daemons
* @details Every publisher stamps its git hash and build time into every
* message (see Common::PubSub::publish), so the cached snapshots
* describe the software that was actually running. A daemon that
* was rebuilt but not restarted still reports its old build,
* which is correct because the old binary produced the data.
* @param[out] githash common commit, or "MIXED" if running daemons differ
* @param[out] buildtime newest build time among running daemons
*
*/
void Interface::get_live_provenance( std::string &githash, std::string &buildtime ) {
githash = GIT_HASH_STR;
buildtime = get_build_time();

std::unique_lock<std::mutex> lock(live_telemetry_mtx);

for ( const auto &[topic, jmsg] : this->live_telemetry ) {
if ( jmsg.contains( Key::GITHASH ) && jmsg.at( Key::GITHASH ).is_string() ) {
const std::string hash = jmsg.at( Key::GITHASH ).get<std::string>();
if ( !hash.empty() && hash != githash ) githash = "MIXED";
}
if ( jmsg.contains( Key::BUILDTIME ) && jmsg.at( Key::BUILDTIME ).is_string() ) {
const std::string btime = jmsg.at( Key::BUILDTIME ).get<std::string>();
if ( btime > buildtime ) buildtime = btime;
}
}
}
/***** AstroCam::Interface::get_live_provenance *****************************/


long NewAstroCam::new_expose( std::string nseq_in ) {
logwrite( "NewAstroCam::new_expose", nseq_in );
return( NO_ERROR );
Expand Down Expand Up @@ -2826,6 +2866,19 @@ namespace AstroCam {
this->camera_info.telemkeys = telem;
}

// Record what software was running for this exposure. Done outside the
// block above because get_live_provenance() takes live_telemetry_mtx
// itself.
//
std::string githash, buildtime;
this->get_live_provenance( githash, buildtime );
this->camera_info.telemkeys.primary().addkey( FitsHeaderKeys::Provenance::GITHASH_KEY,
githash,
FitsHeaderKeys::Provenance::GITHASH_COMMENT );
this->camera_info.telemkeys.primary().addkey( FitsHeaderKeys::Provenance::BUILDTIME_KEY,
buildtime,
FitsHeaderKeys::Provenance::BUILDTIME_COMMENT );

// Make a copy of this->camera_info for this particular exposure buffer number.
// This expinfo will be used for this particular exposure.
// Any changes to camera_info hereafter will not be used for this exposure.
Expand Down
7 changes: 7 additions & 0 deletions camerad/astrocam.h
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,8 @@ namespace AstroCam {
topic_handlers = {
{ Topic::SNAPSHOT, std::function<void(const nlohmann::json&)>(
[this](const nlohmann::json &msg) { handletopic_snapshot(msg); } ) },
{ Topic::ACAMD, std::function<void(const nlohmann::json&)>(
[this](const nlohmann::json &msg) { handletopic_acam(msg); } ) },
{ Topic::CALIBD, std::function<void(const nlohmann::json&)>(
[this](const nlohmann::json &msg) { handletopic_calib(msg); } ) },
{ Topic::FLEXURED, std::function<void(const nlohmann::json&)>(
Expand All @@ -647,6 +649,8 @@ namespace AstroCam {
[this](const nlohmann::json &msg) { handletopic_focus(msg); } ) },
{ Topic::POWERD, std::function<void(const nlohmann::json&)>(
[this](const nlohmann::json &msg) { handletopic_power(msg); } ) },
{ Topic::SLICECAMD, std::function<void(const nlohmann::json&)>(
[this](const nlohmann::json &msg) { handletopic_slicecam(msg); } ) },
{ Topic::SLITD, std::function<void(const nlohmann::json&)>(
[this](const nlohmann::json &msg) { handletopic_slit(msg); } ) },
{ Topic::TARGETINFO, std::function<void(const nlohmann::json&)>(
Expand Down Expand Up @@ -713,10 +717,12 @@ namespace AstroCam {
void publish_status(bool force=false);
void request_snapshot();
void handletopic_snapshot(const nlohmann::json &jmessage_in);
void handletopic_acam(const nlohmann::json &jmessage_in);
void handletopic_calib(const nlohmann::json &jmessage_in);
void handletopic_flexure(const nlohmann::json &jmessage_in);
void handletopic_focus(const nlohmann::json &jmessage_in);
void handletopic_power(const nlohmann::json &jmessage_in);
void handletopic_slicecam(const nlohmann::json &jmessage_in);
void handletopic_slit(const nlohmann::json &jmessage_in);
void handletopic_targetinfo(const nlohmann::json &jmessage_in);
void handletopic_tcs(const nlohmann::json &jmessage_in);
Expand Down Expand Up @@ -1236,6 +1242,7 @@ std::vector<std::shared_ptr<Camera::Information>> fitsinfo;
long expose(std::string nexp_in);
long do_expose(int nexp_in);
double get_live_airmass(); ///< latest airmass from cached tcsd telemetry, or NAN
void get_live_provenance( std::string &githash, std::string &buildtime ); ///< build provenance of all running daemons
long native(std::string cmdstr);
long native(std::string cmdstr, std::string &retstring);

Expand Down
6 changes: 4 additions & 2 deletions camerad/camerad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ int main(int argc, char **argv) {

// log build date and hash
//
message.str(""); message << "this version built " << BUILD_DATE << " " << BUILD_TIME;
message.str(""); message << "this version built " << get_build_time() << " from " << GIT_HASH_STR;
logwrite( function, message.str() );

message.str(""); message << server.config.n_entries << " lines read from " << server.config.filename;
Expand All @@ -180,10 +180,12 @@ int main(int argc, char **argv) {

// initialize the pub-sub handler with my subscriber topics
//
if ( server.init_pubsub( { Topic::CALIBD,
if ( server.init_pubsub( { Topic::ACAMD,
Topic::CALIBD,
Topic::FLEXURED,
Topic::FOCUSD,
Topic::POWERD,
Topic::SLICECAMD,
Topic::SLITD,
Topic::TARGETINFO,
Topic::TCSD,
Expand Down
18 changes: 0 additions & 18 deletions camerad/camerad.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,24 +239,6 @@ namespace Camera {
applied++;
}

// GIT_HASH
if (config.param[entry].compare(0, 8, "GIT_HASH")==0) {
this->camera_info.systemkeys.primary().addkey( "GIT_HASH", config.arg[entry], "software git hash" );
message.str(""); message << "CAMERAD:config:" << config.param[entry] << "=" << config.arg[entry];
logwrite( function, message.str() );
this->camera.async.enqueue( message.str() );
applied++;
}

// PROJ_BUILD_DATE
if (config.param[entry].compare(0, 15, "PROJ_BUILD_DATE")==0) {
this->camera_info.systemkeys.primary().addkey( "SW_BUILD", config.arg[entry], "software build date" );
message.str(""); message << "CAMERAD:config:" << config.param[entry] << "=" << config.arg[entry];
logwrite( function, message.str() );
this->camera.async.enqueue( message.str() );
applied++;
}

} // end loop through the entries in the configuration file

message.str("");
Expand Down
12 changes: 11 additions & 1 deletion common/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "logentry.h"
#include "network.h"
#include "message_keys.h"
#include "build_date.h" // declares GIT_HASH_STR and get_build_time()

const long NOTHING = -1;
const long NO_ERROR = 0;
Expand Down Expand Up @@ -192,12 +193,21 @@ namespace Common {
if ( _mode != Mode::PUB ) {
throw std::runtime_error( "(Common::PubSub::publish) not a publisher" );
}
// Every message carries the build provenance of the publishing binary
// so that a consumer can tell which software produced it. This is done
// here rather than at each call site so that no publisher can omit it.
//
static const std::string build_time = get_build_time();
json message = message_out;
message[Key::GITHASH] = GIT_HASH_STR;
message[Key::BUILDTIME] = build_time;

std::lock_guard<std::mutex> lock( _publish_mtx ); // serialize the non-thread-safe socket
zmqpp::message message_zmq;
// Publish to either class default _topic or topic specified as
// optional arg.
message_zmq.add( topic.empty() ? _topic : topic );
message_zmq.add( message_out.dump() );
message_zmq.add( message.dump() );
_socket.send( message_zmq );
}
/***** Common::PubSub::publish ******************************************/
Expand Down
14 changes: 14 additions & 0 deletions common/fits_header_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,18 @@ namespace FitsHeaderKeys {
{ Key::Slitd::SLITW.c_str(), "SLITW", "slit width in arcsec", "FLOAT" }
};

/**
* @namespace Provenance
* @brief build provenance keywords
* @details These are aggregated across every running daemon rather than
* extracted from one JSON message, so they are not part of a
* Primary[] table. They answer "was there a software change?".
*/
namespace Provenance {
inline constexpr const char* GITHASH_KEY = "GIT_HASH";
inline constexpr const char* GITHASH_COMMENT = "git commit of running software";
inline constexpr const char* BUILDTIME_KEY = "SW_BUILD";
inline constexpr const char* BUILDTIME_COMMENT = "newest build of running software";
}

}
6 changes: 6 additions & 0 deletions common/message_keys.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ namespace Key {
inline const std::string SOURCE = "source";
inline const std::string PUBTIME = "pubtime";

// Build provenance. Every publisher includes these so that a consumer can
// tell which software was running when a message was produced.
//
inline const std::string GITHASH = "githash"; ///< commit the publisher was built from
inline const std::string BUILDTIME = "buildtime"; ///< when the publisher was built, YYYY-MM-DDThh:mm:ss UTC

namespace Broadcast {
inline const std::string SEVERITY = "severity";
inline const std::string MESSAGE = "message";
Expand Down
2 changes: 1 addition & 1 deletion flexured/flexured.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ int main(int argc, char **argv) {
}
logwrite(function, "world");

message << "this version built " << BUILD_DATE << " " << BUILD_TIME;
message << "this version built " << get_build_time() << " from " << GIT_HASH_STR;
logwrite(function, message.str());

message.str(""); message << flexured.config.n_entries << " lines read from " << flexured.config.filename;
Expand Down
2 changes: 1 addition & 1 deletion focusd/focusd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ int main(int argc, char **argv) {
focusd.exit_cleanly();
}

message << "this version built " << BUILD_DATE << " " << BUILD_TIME;
message << "this version built " << get_build_time() << " from " << GIT_HASH_STR;
logwrite(function, message.str());

message.str(""); message << focusd.config.n_entries << " lines read from " << focusd.config.filename;
Expand Down
2 changes: 1 addition & 1 deletion powerd/powerd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ int main(int argc, char **argv) {
powerd.exit_cleanly();
}

message << "this version built " << BUILD_DATE << " " << BUILD_TIME;
message << "this version built " << get_build_time() << " from " << GIT_HASH_STR;
logwrite(function, message.str());

message.str(""); message << powerd.config.n_entries << " lines read from " << powerd.config.filename;
Expand Down
2 changes: 1 addition & 1 deletion sequencerd/sequencerd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ int main(int argc, char **argv) {
sequencerd.exit_cleanly();
}

message << "this version built " << BUILD_DATE << " " << BUILD_TIME;
message << "this version built " << get_build_time() << " from " << GIT_HASH_STR;
logwrite(function, message.str());

message.str(""); message << sequencerd.config.n_entries << " lines read from " << sequencerd.config.filename;
Expand Down
2 changes: 1 addition & 1 deletion slicecamd/slicecamd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ int main(int argc, char **argv) {
slicecamd.exit_cleanly();
}

message.str(""); message << "this version built " << BUILD_DATE << " " << BUILD_TIME;
message.str(""); message << "this version built " << get_build_time() << " from " << GIT_HASH_STR;
logwrite(function, message.str());

message.str(""); message << slicecamd.config.n_entries << " lines read from " << slicecamd.config.filename;
Expand Down
2 changes: 1 addition & 1 deletion slitd/slitd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ int main(int argc, char **argv) {
slitd.exit_cleanly();
}

message << "this version built " << BUILD_DATE << " " << BUILD_TIME;
message << "this version built " << get_build_time() << " from " << GIT_HASH_STR;
logwrite(function, message.str());

message.str(""); message << slitd.config.n_entries << " lines read from " << slitd.config.filename;
Expand Down
2 changes: 1 addition & 1 deletion tcsd/tcsd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ int main(int argc, char **argv) {
tcsd.exit_cleanly();
}

message << "this version built " << BUILD_DATE << " " << BUILD_TIME;
message << "this version built " << get_build_time() << " from " << GIT_HASH_STR;
logwrite(function, message.str());

message.str(""); message << tcsd.config.n_entries << " lines read from " << tcsd.config.filename;
Expand Down
2 changes: 1 addition & 1 deletion telemd/telemd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ int main(int argc, char **argv) {
telemd.exit_cleanly();
}

message << "this version built " << BUILD_DATE << " " << BUILD_TIME;
message << "this version built " << get_build_time() << " from " << GIT_HASH_STR;
logwrite(function, message.str());

message.str(""); message << telemd.config.n_entries << " lines read from " << telemd.config.filename;
Expand Down
2 changes: 1 addition & 1 deletion thermald/thermald.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ int main(int argc, char **argv) {
thermald.exit_cleanly();
}

message << "this version built " << BUILD_DATE << " " << BUILD_TIME;
message << "this version built " << get_build_time() << " from " << GIT_HASH_STR;
logwrite(function, message.str());

message.str(""); message << thermald.config.n_entries << " lines read from " << thermald.config.filename;
Expand Down
2 changes: 2 additions & 0 deletions utils/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# generated by CMake from version.h.in
version.h
Loading
Loading