]> git.proxmox.com Git - ceph.git/blob - ceph/src/common/admin_socket_client.cc
update sources to v12.1.0
[ceph.git] / ceph / src / common / admin_socket_client.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2011 New Dream Network
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15 #include "common/admin_socket.h"
16 #include "common/errno.h"
17 #include "common/safe_io.h"
18 #include "common/admin_socket_client.h"
19
20 #include <sys/un.h>
21
22 using std::ostringstream;
23
24 const char* get_rand_socket_path()
25 {
26 static char *g_socket_path = NULL;
27
28 if (g_socket_path == NULL) {
29 char buf[512];
30 const char *tdir = getenv("TMPDIR");
31 if (tdir == NULL) {
32 tdir = "/tmp";
33 }
34 snprintf(buf, sizeof(((struct sockaddr_un*)0)->sun_path),
35 "%s/perfcounters_test_socket.%ld.%ld",
36 tdir, (long int)getpid(), time(NULL));
37 g_socket_path = (char*)strdup(buf);
38 }
39 return g_socket_path;
40 }
41
42 static std::string asok_connect(const std::string &path, int *fd)
43 {
44 int socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
45 if(socket_fd < 0) {
46 int err = errno;
47 ostringstream oss;
48 oss << "socket(PF_UNIX, SOCK_STREAM, 0) failed: " << cpp_strerror(err);
49 return oss.str();
50 }
51
52 struct sockaddr_un address;
53 memset(&address, 0, sizeof(struct sockaddr_un));
54 address.sun_family = AF_UNIX;
55 snprintf(address.sun_path, sizeof(address.sun_path), "%s", path.c_str());
56
57 if (::connect(socket_fd, (struct sockaddr *) &address,
58 sizeof(struct sockaddr_un)) != 0) {
59 int err = errno;
60 ostringstream oss;
61 oss << "connect(" << socket_fd << ") failed: " << cpp_strerror(err);
62 close(socket_fd);
63 return oss.str();
64 }
65
66 struct timeval timer;
67 timer.tv_sec = 5;
68 timer.tv_usec = 0;
69 if (::setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &timer, sizeof(timer))) {
70 int err = errno;
71 ostringstream oss;
72 oss << "setsockopt(" << socket_fd << ", SO_RCVTIMEO) failed: "
73 << cpp_strerror(err);
74 close(socket_fd);
75 return oss.str();
76 }
77 timer.tv_sec = 5;
78 timer.tv_usec = 0;
79 if (::setsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, &timer, sizeof(timer))) {
80 int err = errno;
81 ostringstream oss;
82 oss << "setsockopt(" << socket_fd << ", SO_SNDTIMEO) failed: "
83 << cpp_strerror(err);
84 close(socket_fd);
85 return oss.str();
86 }
87
88 *fd = socket_fd;
89 return "";
90 }
91
92 static std::string asok_request(int socket_fd, std::string request)
93 {
94 ssize_t res = safe_write(socket_fd, request.c_str(), request.length() + 1);
95 if (res < 0) {
96 int err = res;
97 ostringstream oss;
98 oss << "safe_write(" << socket_fd << ") failed to write request code: "
99 << cpp_strerror(err);
100 return oss.str();
101 }
102 return "";
103 }
104
105 AdminSocketClient::
106 AdminSocketClient(const std::string &path)
107 : m_path(path)
108 {
109 }
110
111 std::string AdminSocketClient::ping(bool *ok)
112 {
113 std::string version;
114 std::string result = do_request("{\"prefix\":\"0\"}", &version);
115 *ok = result == "" && version.length() == 1;
116 return result;
117 }
118
119 std::string AdminSocketClient::do_request(std::string request, std::string *result)
120 {
121 int socket_fd = 0, res;
122 std::string buffer;
123 uint32_t message_size_raw, message_size;
124
125 std::string err = asok_connect(m_path, &socket_fd);
126 if (!err.empty()) {
127 goto out;
128 }
129 err = asok_request(socket_fd, request);
130 if (!err.empty()) {
131 goto done;
132 }
133 res = safe_read_exact(socket_fd, &message_size_raw,
134 sizeof(message_size_raw));
135 if (res < 0) {
136 int e = res;
137 ostringstream oss;
138 oss << "safe_read(" << socket_fd << ") failed to read message size: "
139 << cpp_strerror(e);
140 err = oss.str();
141 goto done;
142 }
143 message_size = ntohl(message_size_raw);
144 buffer.resize(message_size, 0);
145 res = safe_read_exact(socket_fd, &buffer[0], message_size);
146 if (res < 0) {
147 int e = res;
148 ostringstream oss;
149 oss << "safe_read(" << socket_fd << ") failed: " << cpp_strerror(e);
150 err = oss.str();
151 goto done;
152 }
153 //printf("MESSAGE FROM SERVER: %s\n", buffer.c_str());
154 std::swap(*result, buffer);
155 done:
156 close(socket_fd);
157 out:
158 return err;
159 }