SPH
Platform.cpp
Go to the documentation of this file.
1 #include "system/Platform.h"
2 #include "io/FileSystem.h"
5 #include <fcntl.h>
6 
7 #include <libgen.h>
8 #include <string.h>
9 #include <sys/stat.h>
10 #include <sys/times.h>
11 #include <unistd.h>
12 
14 
16  char result[PATH_MAX];
17  ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
18  if (count != -1) {
19  Path path(std::string(result, count));
20  return path.parentPath();
21  } else {
22  return makeUnexpected<Path>("Unknown error");
23  }
24 }
25 
26 Outcome sendMail(const std::string& to,
27  const std::string& from,
28  const std::string& subject,
29  const std::string& message) {
30  NOT_IMPLEMENTED; // somehow doesn't work
31  FILE* mailpipe = popen("/usr/bin/sendmail -t", "w");
32  if (mailpipe == nullptr) {
33  return makeFailed("Cannot invoke sendmail");
34  }
35  fprintf(mailpipe, "To: %s\n", to.c_str());
36  fprintf(mailpipe, "From: %s\n", from.c_str());
37  fprintf(mailpipe, "Subject: %s\n\n", subject.c_str());
38  fwrite(message.c_str(), 1, message.size(), mailpipe);
39  fwrite(".\n", 1, 2, mailpipe);
40  pclose(mailpipe);
41  return SUCCESS;
42 }
43 
44 Outcome showNotification(const std::string& title, const std::string& message) {
45  std::string command = "notify-send \"" + title + "\" \"" + message + "\"";
46  if (system(command.c_str())) {
47  return SUCCESS;
48  } else {
49  return makeFailed("Command failed");
50  }
51 }
52 
53 Outcome sendPushNotification(const std::string& key, const std::string& title, const std::string& message) {
54  std::string command = "curl --data 'key=" + key + "&title=" + title + "&msg=" + message +
55  "' https://api.simplepush.io/send > /dev/null 2> /dev/null";
56  if (system(command.c_str())) {
57  return SUCCESS;
58  } else {
59  return makeFailed("Command failed");
60  }
61 }
62 
63 Expected<std::string> getGitCommit(const Path& pathToGitRoot, const Size prev) {
64  if (!FileSystem::pathExists(pathToGitRoot)) {
65  return makeUnexpected<std::string>("Invalid path");
66  }
68  std::string command = "cd " + pathToGitRoot.native() + " && git rev-parse HEAD~" + std::to_string(prev);
69  std::string result;
70  FILE* pipe = popen(command.c_str(), "r");
71  auto f = finally([pipe] { pclose(pipe); });
72  if (!pipe) {
73  return "";
74  }
75  while (!feof(pipe)) {
76  if (fgets(&buffer[0], 128, pipe) != NULL) {
77  result += &buffer[0];
78  }
79  }
80  // remove \n if in the string
81  std::size_t n;
82  if ((n = result.find("\n")) != std::string::npos) {
83  result = result.substr(0, n);
84  }
85  // some sanity checks so that we don't return nonsense
86  if (result.size() != 40) {
87  return makeUnexpected<std::string>(
88  "Returned git SHA has incorrent length (" + std::to_string(result.size()) + ")");
89  } else if (result.find_first_not_of("0123456789abcdef") != std::string::npos) {
90  return makeUnexpected<std::string>("Returned git SHA contains invalid characters");
91  } else {
92  return result;
93  }
94 }
95 
96 class CpuUsage {
97 private:
98  clock_t lastCpu;
99  clock_t lastSysCpu;
100  clock_t lastUserCpu;
101  Size numProcessors;
102 
103 public:
105  FILE* file;
106  struct tms timeSample;
107  char line[128];
108 
109  lastCpu = times(&timeSample);
110  lastSysCpu = timeSample.tms_stime;
111  lastUserCpu = timeSample.tms_utime;
112 
113  file = fopen("/proc/cpuinfo", "r");
114  numProcessors = 0;
115  while (fgets(line, 128, file) != NULL) {
116  if (strncmp(line, "processor", 9) == 0)
117  numProcessors++;
118  }
119  fclose(file);
120  }
121 
123  tms timeSample;
124  clock_t now;
125  Optional<Float> usage;
126 
127  now = times(&timeSample);
128  if (now <= lastCpu || timeSample.tms_stime < lastSysCpu || timeSample.tms_utime < lastUserCpu) {
129  // Overflow detection. Just skip this value.
130  usage = NOTHING;
131  } else {
132  usage = (timeSample.tms_stime - lastSysCpu) + (timeSample.tms_utime - lastUserCpu);
133  usage.value() /= (now - lastCpu);
134  usage.value() /= numProcessors;
135  }
136  lastCpu = now;
137  lastSysCpu = timeSample.tms_stime;
138  lastUserCpu = timeSample.tms_utime;
139 
140  return usage;
141  }
142 };
143 
145  static CpuUsage cpu;
146  return cpu.getUsage();
147 }
148 
150  char buf[1024];
151  bool debuggerPresent = false;
152 
153  int status_fd = open("/proc/self/status", O_RDONLY);
154  if (status_fd == -1) {
155  return false;
156  }
157 
158  std::size_t num_read = read(status_fd, buf, sizeof(buf));
159 
160  if (num_read > 0) {
161  static const char TracerPid[] = "TracerPid:";
162  char* tracer_pid;
163 
164  buf[num_read] = 0;
165  tracer_pid = strstr(buf, TracerPid);
166  if (tracer_pid) {
167  debuggerPresent = atoi(tracer_pid + sizeof(TracerPid) - 1) != 0;
168  }
169  }
170  return debuggerPresent;
171 }
172 
#define NOT_IMPLEMENTED
Helper macro marking missing implementation.
Definition: Assert.h:100
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
Wraps a functor and executes it once the wrapper goes out of scope.
uint32_t Size
Integral type used to index arrays (by default).
Definition: Globals.h:16
#define NAMESPACE_SPH_END
Definition: Object.h:12
const NothingType NOTHING
Definition: Optional.h:16
const SuccessTag SUCCESS
Global constant for successful outcome.
Definition: Outcome.h:141
INLINE Outcome makeFailed(TArgs &&... args)
Constructs failed object with error message.
Definition: Outcome.h:157
Expected< std::string > getGitCommit(const Path &pathToGitRoot, const Size prev)
Returns git commit hash of the current or older commit as string.
Definition: Platform.cpp:63
NAMESPACE_SPH_BEGIN Expected< Path > getExecutablePath()
Returns the absolute path to the currently running executable.
Definition: Platform.cpp:15
Optional< Float > getCpuUsage()
Definition: Platform.cpp:144
Outcome sendMail(const std::string &to, const std::string &from, const std::string &subject, const std::string &message)
Sends a mail with given message.
Definition: Platform.cpp:26
Outcome sendPushNotification(const std::string &key, const std::string &title, const std::string &message)
Sends a push notification to an Android device, using SimplePush API.
Definition: Platform.cpp:53
Outcome showNotification(const std::string &title, const std::string &message)
Shows a notification using 'notify-send' command.
Definition: Platform.cpp:44
bool isDebuggerPresent()
Returns true if the program is running with attached debugger.
Definition: Platform.cpp:149
System functions.
Optional< Float > getUsage()
Definition: Platform.cpp:122
Wrapper of type that either contains a value of given type, or an error message.
Definition: Expected.h:25
INLINE Type & value()
Returns the reference to the stored value.
Definition: Optional.h:172
Object representing a path on a filesystem.
Definition: Path.h:17
std::string native() const
Returns the native version of the path.
Definition: Path.cpp:71
Path parentPath() const
Returns the parent directory. If the path is empty or root, return empty path.
Definition: Path.cpp:35
Array with fixed number of allocated elements.
Definition: StaticArray.h:19
@ FILE
Print log to file.
bool pathExists(const Path &path)
Checks if a file or directory exists (or more precisely, if a file or directory is accessible).
Definition: FileSystem.cpp:21