Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Unified Diff: tools/android/file_poller/file_poller.cc

Issue 1841863002: Update monet. (Closed) Base URL: https://github.com/domokit/monet.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/android/download_android_tools.py ('k') | tools/android/find_unused_resources.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/android/file_poller/file_poller.cc
diff --git a/tools/android/file_poller/file_poller.cc b/tools/android/file_poller/file_poller.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c73db8b6e6f7cd2083ff3587e1c1dc1ddd9efd56
--- /dev/null
+++ b/tools/android/file_poller/file_poller.cc
@@ -0,0 +1,207 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// When run with 2 or more arguments the file_poller tool will open a port on
+// the device, print it on its standard output and then start collect file
+// contents. The first argument is the polling rate in Hz, and the following
+// arguments are file to poll.
+// When run with the port of an already running file_poller, the tool will
+// contact the first instance, retrieve the sample and print those on its
+// standard output. This will also terminate the first instance.
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "base/logging.h"
+
+// Context containing the files to poll and the polling rate.
+struct Context {
+ size_t nb_files;
+ int* file_fds;
+ int poll_rate;
+};
+
+// Write from the buffer to the given file descriptor.
+void safe_write(int fd, const char* buffer, int size) {
+ const char* index = buffer;
+ size_t to_write = size;
+ while (to_write > 0) {
+ int written = write(fd, index, to_write);
+ if (written < 0)
+ PLOG(FATAL);
+ index += written;
+ to_write -= written;
+ }
+}
+
+// Transfer the content of a file descriptor to another.
+void transfer_to_fd(int fd_in, int fd_out) {
+ char buffer[1024];
+ int n;
+ while ((n = read(fd_in, buffer, sizeof(buffer))) > 0)
+ safe_write(fd_out, buffer, n);
+}
+
+// Transfer the content of a file descriptor to a buffer.
+int transfer_to_buffer(int fd_in, char* bufffer, size_t size) {
+ char* index = bufffer;
+ size_t to_read = size;
+ int n;
+ while (to_read > 0 && ((n = read(fd_in, index, to_read)) > 0)) {
+ index += n;
+ to_read -= n;
+ }
+ if (n < 0)
+ PLOG(FATAL);
+ return size - to_read;
+}
+
+// Try to open the file at the given path for reading. Exit in case of failure.
+int checked_open(const char* path) {
+ int fd = open(path, O_RDONLY);
+ if (fd < 0)
+ PLOG(FATAL);
+ return fd;
+}
+
+void transfer_measurement(int fd_in, int fd_out, bool last) {
+ char buffer[1024];
+ if (lseek(fd_in, 0, SEEK_SET) < 0)
+ PLOG(FATAL);
+ int n = transfer_to_buffer(fd_in, buffer, sizeof(buffer));
+ safe_write(fd_out, buffer, n - 1);
+ safe_write(fd_out, last ? "\n" : " ", 1);
+}
+
+// Acquire a sample and save it to the given file descriptor.
+void acquire_sample(int fd, const Context& context) {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ char buffer[1024];
+ int n = snprintf(buffer, sizeof(buffer), "%d.%06d ", tv.tv_sec, tv.tv_usec);
+ safe_write(fd, buffer, n);
+
+ for (int i = 0; i < context.nb_files; ++i)
+ transfer_measurement(context.file_fds[i], fd, i == (context.nb_files - 1));
+}
+
+void poll_content(const Context& context) {
+ // Create and bind the socket so that the port can be written to stdout.
+ int sockfd = socket(AF_INET, SOCK_STREAM, 0);
+ struct sockaddr_in socket_info;
+ socket_info.sin_family = AF_INET;
+ socket_info.sin_addr.s_addr = htonl(INADDR_ANY);
+ socket_info.sin_port = htons(0);
+ if (bind(sockfd, (struct sockaddr*)&socket_info, sizeof(socket_info)) < 0)
+ PLOG(FATAL);
+ socklen_t size = sizeof(socket_info);
+ getsockname(sockfd, (struct sockaddr*)&socket_info, &size);
+ printf("%d\n", ntohs(socket_info.sin_port));
+ // Using a pipe to ensure child is diconnected from the terminal before
+ // quitting.
+ int pipes[2];
+ pipe(pipes);
+ pid_t pid = fork();
+ if (pid < 0)
+ PLOG(FATAL);
+ if (pid != 0) {
+ close(pipes[1]);
+ // Not expecting any data to be received.
+ read(pipes[0], NULL, 1);
+ signal(SIGCHLD, SIG_IGN);
+ return;
+ }
+
+ // Detach from terminal.
+ setsid();
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
+ close(STDERR_FILENO);
+ close(pipes[0]);
+
+ // Start listening for incoming connection.
+ if (listen(sockfd, 1) < 0)
+ PLOG(FATAL);
+
+ // Signal the parent that it can now safely exit.
+ close(pipes[1]);
+
+ // Prepare file to store the samples.
+ int fd;
+ char filename[] = "/data/local/tmp/fileXXXXXX";
+ fd = mkstemp(filename);
+ unlink(filename);
+
+ // Collect samples until a client connect on the socket.
+ fd_set rfds;
+ struct timeval timeout;
+ do {
+ acquire_sample(fd, context);
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 1000000 / context.poll_rate;
+ FD_ZERO(&rfds);
+ FD_SET(sockfd, &rfds);
+ } while (select(sockfd + 1, &rfds, NULL, NULL, &timeout) == 0);
+
+ // Collect a final sample.
+ acquire_sample(fd, context);
+
+ // Send the result back.
+ struct sockaddr_in remote_socket_info;
+ int rfd = accept(sockfd, (struct sockaddr*)&remote_socket_info, &size);
+ if (rfd < 0)
+ PLOG(FATAL);
+ if (lseek(fd, 0, SEEK_SET) < 0)
+ PLOG(FATAL);
+ transfer_to_fd(fd, rfd);
+}
+
+void content_collection(int port) {
+ int sockfd = socket(AF_INET, SOCK_STREAM, 0);
+ // Connect to localhost.
+ struct sockaddr_in socket_info;
+ socket_info.sin_family = AF_INET;
+ socket_info.sin_addr.s_addr = htonl(0x7f000001);
+ socket_info.sin_port = htons(port);
+ if (connect(sockfd, (struct sockaddr*)&socket_info, sizeof(socket_info)) <
+ 0) {
+ PLOG(FATAL);
+ }
+ transfer_to_fd(sockfd, STDOUT_FILENO);
+}
+
+int main(int argc, char** argv) {
+ if (argc == 1) {
+ fprintf(stderr,
+ "Usage: \n"
+ " %s port\n"
+ " %s rate FILE...\n",
+ argv[0],
+ argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ if (argc == 2) {
+ // Argument is the port to connect to.
+ content_collection(atoi(argv[1]));
+ } else {
+ // First argument is the poll frequency, in Hz, following arguments are the
+ // file to poll.
+ Context context;
+ context.poll_rate = atoi(argv[1]);
+ context.nb_files = argc - 2;
+ context.file_fds = new int[context.nb_files];
+ for (int i = 2; i < argc; ++i)
+ context.file_fds[i - 2] = checked_open(argv[i]);
+ poll_content(context);
+ }
+ return EXIT_SUCCESS;
+}
« no previous file with comments | « tools/android/download_android_tools.py ('k') | tools/android/find_unused_resources.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698