kinetic-c  v0.12.0
Seagate Kinetic Protocol Client Library for C
kinetic_session.c
Go to the documentation of this file.
1 /*
2 * kinetic-c
3 * Copyright (C) 2015 Seagate Technology.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 *
19 */
20 
21 #include "kinetic_session.h"
22 #include "kinetic_types_internal.h"
23 #include "kinetic_controller.h"
24 #include "kinetic_socket.h"
25 #include "kinetic_response.h"
26 #include "kinetic_operation.h"
27 #include "kinetic_controller.h"
28 #include "kinetic_allocator.h"
29 #include "kinetic_resourcewaiter.h"
30 #include "kinetic_logger.h"
31 #include <stdlib.h>
32 #include <string.h>
33 #include <pthread.h>
34 #include <errno.h>
35 #include <sys/time.h>
36 
37 KineticStatus KineticSession_Create(KineticSession * const session, KineticClient * const client)
38 {
39  if (session == NULL) {
40  LOG0("Session is NULL");
42  }
43 
44  if (client == NULL) {
45  LOG0("Client is NULL");
47  }
48 
49  session->connected = false;
50  session->socket = KINETIC_SOCKET_INVALID;
51 
52  // initialize session send mutex
53  if (pthread_mutex_init(&session->sendMutex, NULL) != 0) {
54  LOG0("Failed initializing session send mutex!");
56  }
57 
58  session->outstandingOperations =
60  if (session->outstandingOperations == NULL) {
61  LOG0("Failed creating session counting semaphore!");
63  }
64 
66 }
67 
68 KineticStatus KineticSession_Destroy(KineticSession * const session)
69 {
70  if (session == NULL) {
72  }
73  KineticCountingSemaphore_Destroy(session->outstandingOperations);
75 
77 }
78 
79 KineticStatus KineticSession_Connect(KineticSession * const session)
80 {
81  if (session == NULL) {
83  }
84 
85  // Establish the connection
86  KINETIC_ASSERT(strlen(session->config.host) > 0);
87  session->socket = KineticSocket_Connect(
88  session->config.host, session->config.port);
89  if (session->socket == KINETIC_SOCKET_DESCRIPTOR_INVALID) {
90  LOG0("Session connection failed!");
91  session->socket = KINETIC_SOCKET_DESCRIPTOR_INVALID;
92  session->connected = false;
94  }
95  session->connected = true;
96 
97  bus_socket_t socket_type = session->config.useSsl ? BUS_SOCKET_SSL : BUS_SOCKET_PLAIN;
98  session->si = calloc(1, sizeof(socket_info) + 2 * PDU_PROTO_MAX_LEN);
99  if (session->si == NULL) { return KINETIC_STATUS_MEMORY_ERROR; }
100  bool success = Bus_RegisterSocket(session->messageBus, socket_type, session->socket, session);
101  if (!success) {
102  LOG0("Failed registering connection with client!");
103  goto connection_error_cleanup;
104  }
105 
106  // Wait for initial unsolicited status to be received in order to obtain connection ID
107  success = KineticResourceWaiter_WaitTilAvailable(&session->connectionReady, KINETIC_CONNECTION_TIMEOUT_SECS);
108  if (!success) {
109  LOG0("Timed out waiting for connection ID from device!");
110  goto connection_error_cleanup;
111  }
112  LOGF1("Received connection ID %lld for session %p",
113  (long long)KineticSession_GetConnectionID(session), (void*)session);
114 
115  return KINETIC_STATUS_SUCCESS;
116 
117 connection_error_cleanup:
118 
119  if (session->si != NULL) {
120  free(session->si);
121  session->si = NULL;
122  }
123  if (session->socket != KINETIC_SOCKET_DESCRIPTOR_INVALID) {
124  KineticSocket_Close(session->socket);
125  session->socket = KINETIC_SOCKET_DESCRIPTOR_INVALID;
126  }
127  session->connected = false;
129 }
130 
131 KineticStatus KineticSession_Disconnect(KineticSession * const session)
132 {
133  if (session == NULL) {
135  }
136  if (!session->connected || session->socket < 0) {
138  }
139 
140  // Close the connection
141  Bus_ReleaseSocket(session->messageBus, session->socket, NULL);
142  free(session->si);
143  session->si = NULL;
144  session->socket = KINETIC_SOCKET_INVALID;
145  session->connected = false;
146  pthread_mutex_destroy(&session->sendMutex);
147 
148  return KINETIC_STATUS_SUCCESS;
149 }
150 
151 KineticStatus KineticSession_GetTerminationStatus(KineticSession const * const session)
152 {
153  if (session == NULL) {
155  }
156  return session->terminationStatus;
157 }
158 
159 void KineticSession_SetTerminationStatus(KineticSession * const session, KineticStatus status)
160 {
161  KINETIC_ASSERT(session);
162  session->terminationStatus = status;
163 }
164 
165 #define ATOMIC_FETCH_AND_INCREMENT(P) __sync_fetch_and_add(P, 1)
166 
167 int64_t KineticSession_GetNextSequenceCount(KineticSession * const session)
168 {
169  KINETIC_ASSERT(session);
170  int64_t seq_cnt = ATOMIC_FETCH_AND_INCREMENT(&session->sequence);
171  return seq_cnt;
172 }
173 
174 int64_t KineticSession_GetClusterVersion(KineticSession const * const session)
175 {
176  KINETIC_ASSERT(session);
177  return session->config.clusterVersion;
178 }
179 
180 void KineticSession_SetClusterVersion(KineticSession * const session, int64_t cluster_version)
181 {
182  KINETIC_ASSERT(session);
183  session->config.clusterVersion = cluster_version;
184 }
185 
186 int64_t KineticSession_GetConnectionID(KineticSession const * const session)
187 {
188  KINETIC_ASSERT(session);
189  return session->connectionID;
190 }
191 
192 void KineticSession_SetConnectionID(KineticSession * const session, int64_t id)
193 {
194  KINETIC_ASSERT(session);
195  session->connectionID = id;
196 }
int64_t KineticSession_GetConnectionID(KineticSession const *const session)
Operation successful.
#define LOGF1(message,...)
#define KINETIC_SOCKET_INVALID
Invalid socket file descriptor value.
Definition: kinetic_types.h:39
bool Bus_ReleaseSocket(struct bus *b, int fd, void **socket_udata_out)
Free metadata about a socket that has been disconnected.
Definition: bus.c:420
KineticStatus KineticSession_Connect(KineticSession *const session)
void KineticCountingSemaphore_Destroy(KineticCountingSemaphore *const sem)
KineticStatus KineticSession_Create(KineticSession *const session, KineticClient *const client)
void KineticSession_SetClusterVersion(KineticSession *const session, int64_t cluster_version)
#define ATOMIC_FETCH_AND_INCREMENT(P)
#define KINETIC_MAX_OUTSTANDING_OPERATIONS_PER_SESSION
void KineticSession_SetTerminationStatus(KineticSession *const session, KineticStatus status)
void KineticAllocator_FreeSession(KineticSession *session)
int KineticSocket_Connect(const char *host, int port)
Failed allocating/deallocating memory.
#define KINETIC_SOCKET_DESCRIPTOR_INVALID
#define KINETIC_ASSERT(cond)
No connection/disconnected.
bus_socket_t
Definition: bus_types.h:231
#define LOG0(message)
bool KineticResourceWaiter_WaitTilAvailable(KineticResourceWaiter *const waiter, uint32_t max_wait_sec)
Session was NULL in request.
int64_t KineticSession_GetNextSequenceCount(KineticSession *const session)
int64_t KineticSession_GetClusterVersion(KineticSession const *const session)
void KineticSocket_Close(int socket)
KineticStatus KineticSession_Disconnect(KineticSession *const session)
KineticStatus KineticSession_GetTerminationStatus(KineticSession const *const session)
bool Bus_RegisterSocket(struct bus *b, bus_socket_t type, int fd, void *udata)
Register a socket connected to an endpoint, and data that will be passed to all interactions on that ...
Definition: bus.c:350
KineticStatus
Kinetic status codes.
#define KINETIC_CONNECTION_TIMEOUT_SECS
#define PDU_PROTO_MAX_LEN
KineticCountingSemaphore * KineticCountingSemaphore_Create(uint32_t counts)
void KineticSession_SetConnectionID(KineticSession *const session, int64_t id)
KineticStatus KineticSession_Destroy(KineticSession *const session)
Session configuration was invalid or NULL.