Fix: Connect timeout arithmetic in inet/inet6 (v4)
[lttng-tools.git] / src / common / utils.c
index aa11551c30635fd4e423382092fd1871a2534b17..e682183931d7ad7536bede5c62a938db8d48eb0d 100644 (file)
@@ -41,6 +41,7 @@
 
 #include "utils.h"
 #include "defaults.h"
+#include "time.h"
 
 /*
  * Return a partial realpath(3) of the path even if the full path does not
@@ -712,7 +713,8 @@ int utils_mkdir_recursive(const char *path, mode_t mode, int uid, int gid)
  *
  * 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)
@@ -831,6 +833,36 @@ error:
        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.
@@ -846,9 +878,13 @@ int utils_rotate_stream_file(char *path_name, char *file_name, uint64_t size,
                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");
@@ -856,32 +892,12 @@ int utils_rotate_stream_file(char *path_name, char *file_name, uint64_t size,
        }
        *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,
@@ -1017,6 +1033,59 @@ static inline unsigned int fls_u32(uint32_t x)
 #define HAS_FLS_U32
 #endif
 
+#if defined(__x86_64)
+static inline
+unsigned int fls_u64(uint64_t x)
+{
+       long r;
+
+       asm("bsrq %1,%0\n\t"
+           "jnz 1f\n\t"
+           "movq $-1,%0\n\t"
+           "1:\n\t"
+           : "=r" (r) : "rm" (x));
+       return r + 1;
+}
+#define HAS_FLS_U64
+#endif
+
+#ifndef HAS_FLS_U64
+static __attribute__((unused))
+unsigned int fls_u64(uint64_t x)
+{
+       unsigned int r = 64;
+
+       if (!x)
+               return 0;
+
+       if (!(x & 0xFFFFFFFF00000000ULL)) {
+               x <<= 32;
+               r -= 32;
+       }
+       if (!(x & 0xFFFF000000000000ULL)) {
+               x <<= 16;
+               r -= 16;
+       }
+       if (!(x & 0xFF00000000000000ULL)) {
+               x <<= 8;
+               r -= 8;
+       }
+       if (!(x & 0xF000000000000000ULL)) {
+               x <<= 4;
+               r -= 4;
+       }
+       if (!(x & 0xC000000000000000ULL)) {
+               x <<= 2;
+               r -= 2;
+       }
+       if (!(x & 0x8000000000000000ULL)) {
+               x <<= 1;
+               r -= 1;
+       }
+       return r;
+}
+#endif
+
 #ifndef HAS_FLS_U32
 static __attribute__((unused)) unsigned int fls_u32(uint32_t x)
 {
@@ -1063,6 +1132,20 @@ int utils_get_count_order_u32(uint32_t x)
        return fls_u32(x - 1);
 }
 
+/*
+ * Return the minimum order for which x <= (1UL << order).
+ * Return -1 if x is 0.
+ */
+LTTNG_HIDDEN
+int utils_get_count_order_u64(uint64_t x)
+{
+       if (!x) {
+               return -1;
+       }
+
+       return fls_u64(x - 1);
+}
+
 /**
  * Obtain the value of LTTNG_HOME environment variable, if exists.
  * Otherwise returns the value of HOME.
@@ -1335,15 +1418,17 @@ LTTNG_HIDDEN
 int utils_truncate_stream_file(int fd, off_t length)
 {
        int ret;
+       off_t lseek_ret;
 
        ret = ftruncate(fd, length);
        if (ret < 0) {
                PERROR("ftruncate");
                goto end;
        }
-       ret = lseek(fd, length, SEEK_SET);
-       if (ret < 0) {
+       lseek_ret = lseek(fd, length, SEEK_SET);
+       if (lseek_ret < 0) {
                PERROR("lseek");
+               ret = -1;
                goto end;
        }
 end:
@@ -1383,3 +1468,68 @@ int utils_show_man_page(int section, const char *page_name)
                section_string, page_name, NULL);
        return ret;
 }
+
+LTTNG_HIDDEN
+int utils_change_working_dir(const char *path)
+{
+       int ret;
+
+       assert(path);
+
+       ret = chdir(path);
+       if (ret) {
+               PERROR("Failed to change working directory: %s", path);
+               goto end;
+       }
+
+       /* Check for write access */
+       if (access(path, W_OK)) {
+               if (errno == EACCES) {
+                       /*
+                        * Do not treat this as an error since the permission
+                        * might change in the lifetime of the process
+                        */
+                       DBG("Working directory is not writable: %s", path);
+               } else {
+                       PERROR("access");
+               }
+       }
+
+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;
+}
This page took 0.027272 seconds and 5 git commands to generate.