#include "utils.h"
#include "defaults.h"
+#include "time.h"
/*
* Return a partial realpath(3) of the path even if the full path does not
*
* Return 0 on success or else a negative value.
*/
-static int utils_stream_file_name(char *path,
+LTTNG_HIDDEN
+int utils_stream_file_name(char *path,
const char *path_name, const char *file_name,
uint64_t size, uint64_t count,
const char *suffix)
return ret;
}
+LTTNG_HIDDEN
+void utils_stream_file_rotation_get_new_count(uint64_t count,
+ uint64_t *new_count, bool *should_unlink)
+{
+ if (count > 0) {
+ /*
+ * In tracefile rotation, for the relay daemon we need
+ * to unlink the old file if present, because it may
+ * still be open in reading by the live thread, and we
+ * need to ensure that we do not overwrite the content
+ * between get_index and get_packet. Since we have no
+ * way to verify integrity of the data content compared
+ * to the associated index, we need to ensure the reader
+ * has exclusive access to the file content, and that
+ * the open of the data file is performed in get_index.
+ * Unlinking the old file rather than overwriting it
+ * achieves this.
+ */
+ if (new_count) {
+ *new_count = (*new_count + 1) % count;
+ }
+ *should_unlink = true;
+ } else {
+ if (new_count) {
+ (*new_count)++;
+ }
+ *should_unlink = false;
+ }
+}
+
/*
* Change the output tracefile according to the given size and count The
* new_count pointer is set during this operation.
int *stream_fd)
{
int ret;
+ bool should_unlink;
assert(stream_fd);
+ utils_stream_file_rotation_get_new_count(count, new_count,
+ &should_unlink);
+
ret = close(out_fd);
if (ret < 0) {
PERROR("Closing tracefile");
}
*stream_fd = -1;
- if (count > 0) {
- /*
- * In tracefile rotation, for the relay daemon we need
- * to unlink the old file if present, because it may
- * still be open in reading by the live thread, and we
- * need to ensure that we do not overwrite the content
- * between get_index and get_packet. Since we have no
- * way to verify integrity of the data content compared
- * to the associated index, we need to ensure the reader
- * has exclusive access to the file content, and that
- * the open of the data file is performed in get_index.
- * Unlinking the old file rather than overwriting it
- * achieves this.
- */
- if (new_count) {
- *new_count = (*new_count + 1) % count;
- }
+ if (should_unlink) {
ret = utils_unlink_stream_file(path_name, file_name, size,
new_count ? *new_count : 0, uid, gid, 0);
if (ret < 0 && errno != ENOENT) {
goto error;
}
- } else {
- if (new_count) {
- (*new_count)++;
- }
}
ret = utils_create_stream_file(path_name, file_name, size,
end:
return ret;
}
+
+LTTNG_HIDDEN
+int timespec_to_ms(struct timespec ts, unsigned long *ms)
+{
+ unsigned long res, remain_ms;
+
+ if (ts.tv_sec > ULONG_MAX / MSEC_PER_SEC) {
+ errno = EOVERFLOW;
+ return -1; /* multiplication overflow */
+ }
+ res = ts.tv_sec * MSEC_PER_SEC;
+ remain_ms = ULONG_MAX - res;
+ if (ts.tv_nsec / NSEC_PER_MSEC > remain_ms) {
+ errno = EOVERFLOW;
+ return -1; /* addition overflow */
+ }
+ res += ts.tv_nsec / NSEC_PER_MSEC;
+ *ms = res;
+ return 0;
+}
+
+LTTNG_HIDDEN
+struct timespec timespec_abs_diff(struct timespec t1, struct timespec t2)
+{
+ uint64_t ts1 = (uint64_t) t1.tv_sec * (uint64_t) NSEC_PER_SEC +
+ (uint64_t) t1.tv_nsec;
+ uint64_t ts2 = (uint64_t) t2.tv_sec * (uint64_t) NSEC_PER_SEC +
+ (uint64_t) t2.tv_nsec;
+ uint64_t diff = max(ts1, ts2) - min(ts1, ts2);
+ struct timespec res;
+
+ res.tv_sec = diff / (uint64_t) NSEC_PER_SEC;
+ res.tv_nsec = diff % (uint64_t) NSEC_PER_SEC;
+ return res;
+}