2 * Copyright (c) 1998,1999,2000
3 * Traakan, Inc., Los Altos, CA
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice unmodified, this list of conditions, and the following
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 #include "ndmagents.h"
43 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
46 ndma_client_session (struct ndm_session *sess)
48 struct ndm_job_param * job = &sess->control_acb.job;
51 rc = ndma_job_audit (job, 0, 0);
55 rc = ndma_session_initialize (sess);
58 rc = ndma_session_commission (sess);
61 rc = ndmca_connect_control_agent (sess);
62 if (rc) return rc; /* already tattled */
65 sess->conn_authorized = 1;
67 rc = ndmca_control_agent (sess);
69 ndma_session_decommission (sess);
74 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
77 #ifndef NDMOS_EFFECT_NO_SERVER_AGENTS
80 ndma_server_session (struct ndm_session *sess, int control_sock)
82 struct ndmconn * conn;
87 rc = ndma_session_initialize (sess);
90 rc = ndma_session_commission (sess);
94 rc = getpeername (control_sock, &sa, &len);
96 perror ("getpeername");
98 ndmalogf (sess, 0, 2, "Connection accepted from %s",
99 inet_ntoa ( ((struct sockaddr_in *)&sa)->sin_addr));
103 rc = getsockname (control_sock, &sa, &len);
105 perror ("getsockname");
107 ndmalogf (sess, 0, 2, "Connection accepted to %s",
108 inet_ntoa ( ((struct sockaddr_in *)&sa)->sin_addr));
111 conn = ndmconn_initialize (0, "#C");
113 ndmalogf (sess, 0, 0, "can't init connection");
114 close (control_sock);
118 ndmos_condition_control_socket (sess, control_sock);
120 ndmconn_set_snoop (conn, &sess->param.log, sess->param.log_level);
121 ndmconn_accept (conn, control_sock);
123 conn->call = ndma_call;
124 conn->context = sess;
126 sess->plumb.control = conn;
128 while (!conn->chan.eof) {
129 ndma_session_quantum (sess, 1000);
133 ndmalogf (sess, 0, 2, "Connection close %s",
134 inet_ntoa ( ((struct sockaddr_in *)sa)->sin_addr));
137 ndmconn_destruct (conn);
139 ndma_session_decommission (sess);
145 exit_on_stdin_eof_thread(gpointer data G_GNUC_UNUSED)
150 if (read(0, buf, sizeof(buf)) <= 0) {
159 ndma_daemon_session (struct ndm_session *sess, int port, int is_test_daemon)
166 listen_sock = socket (AF_INET, SOCK_STREAM, 0);
167 if (listen_sock < 0) {
172 ndmos_condition_listen_socket (sess, listen_sock);
174 NDMOS_MACRO_SET_SOCKADDR(&sa, 0, port);
176 if (bind (listen_sock, &sa, sizeof sa) < 0) {
181 if (listen (listen_sock, 1) < 0) {
186 if (is_test_daemon) {
187 /* the listen socket is running, so tell our invoker */
191 /* and exit when our stdin goes away */
192 g_debug("will exit on EOF from stdin");
194 g_thread_create(exit_on_stdin_eof_thread, NULL, FALSE, NULL);
199 conn_sock = accept (listen_sock, &sa, &len);
213 ndma_server_session (sess, conn_sock);
222 #endif /* !NDMOS_EFFECT_NO_SERVER_AGENTS */
226 ndma_session_distribute_quantum (struct ndm_session *sess)
228 int total_did_something = 0;
234 did_something |= ndmis_quantum (sess);
236 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
237 if (sess->tape_acb.mover_state.state != NDMP9_MOVER_STATE_IDLE)
238 did_something |= ndmta_quantum (sess);
239 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
241 #ifndef NDMOS_OPTION_NO_DATA_AGENT
242 if (sess->data_acb.data_state.state != NDMP9_DATA_STATE_IDLE)
243 did_something |= ndmda_quantum (sess);
244 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
246 total_did_something |= did_something;
248 } while (did_something);
250 return total_did_something;
255 ndma_session_quantum (struct ndm_session *sess, int max_delay_secs)
257 struct ndm_image_stream *is = &sess->plumb.image_stream;
258 struct ndmconn * conn;
259 struct ndmconn * conntab[5];
261 struct ndmchan * chtab[16];
264 int max_delay_usec = max_delay_secs * 1000;
267 * Gather distinct connections
270 if ((conn = sess->plumb.control))
271 conntab[n_conntab++] = conn;
272 if ( (conn = sess->plumb.data)
273 && conn != sess->plumb.control)
274 conntab[n_conntab++] = conn;
275 if ( (conn = sess->plumb.tape)
276 && conn != sess->plumb.data
277 && conn != sess->plumb.control)
278 conntab[n_conntab++] = conn;
279 if ( (conn = sess->plumb.robot)
280 && conn != sess->plumb.tape
281 && conn != sess->plumb.data
282 && conn != sess->plumb.control)
283 conntab[n_conntab++] = conn;
286 * Add connections to channel table
289 for (i = 0; i < n_conntab; i++) {
291 chtab[n_chtab++] = &conn->chan;
294 #ifndef NDMOS_OPTION_NO_DATA_AGENT
296 * Add DATA AGENT channels to table if active (!IDLE)
298 if (sess->data_acb.data_state.state != NDMP9_DATA_STATE_IDLE) {
299 chtab[n_chtab++] = &sess->data_acb.formatter_image;
300 chtab[n_chtab++] = &sess->data_acb.formatter_error;
301 chtab[n_chtab++] = &sess->data_acb.formatter_wrap;
303 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
306 * Add image stream to channel table
308 if (is->remote.connect_status == NDMIS_CONN_LISTEN)
309 chtab[n_chtab++] = &is->remote.listen_chan;
311 chtab[n_chtab++] = &is->chan;
314 * Let TAPE and DATA AGENTS get a bit of work done.
315 * This fills channel buffers as much as possible prior to blocking.
317 if (ndma_session_distribute_quantum (sess))
321 #ifndef NDMOS_OPTION_NO_DATA_AGENT
323 if (sess->data_acb.data_state.state == NDMP9_DATA_STATE_ACTIVE
324 && sess->data_acb.data_state.data_connection_addr.addr_type
325 == NDMP9_ADDR_LOCAL) {
327 * There is no remote connection to cue forward
328 * progress between local DATA/MOVER.
329 * So, sniff all the connections, and immediately
330 * attempt the next tape record.
334 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
338 * Block awaiting ready I/O. Many channel buffers
339 * will have actual I/O (read/write) performed.
341 ndmchan_quantum (chtab, n_chtab, max_delay_usec);
346 if (sess->param.log_level > 7) {
347 for (i = 0; i < n_chtab; i++) {
348 struct ndmchan * ch = chtab[i];
351 ndmchan_pp (ch, buf);
352 ndmalogf (sess, 0, 7, "ch %s", buf);
357 * Let TAPE and DATA AGENTS get a bit more work done.
358 * This will mostly digest whatever data just arrived.
360 ndma_session_distribute_quantum (sess);
363 * Dispatch any pending activity on the control connections
365 for (i = 0; i < n_conntab; i++) {
367 if (conn->chan.ready) {
368 conn->chan.ready = 0;
369 ndma_dispatch_conn (sess, conn);
380 ndma_session_initialize (struct ndm_session *sess)
382 ndmis_initialize (sess);
384 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
385 /* ndmca_initialize (sess); */
386 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
388 #ifndef NDMOS_OPTION_NO_DATA_AGENT
389 ndmda_initialize (sess);
390 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
392 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
393 ndmta_initialize (sess);
394 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
396 #ifndef NDMOS_OPTION_NO_ROBOT_AGENT
397 ndmra_initialize (sess);
398 #endif /* !NDMOS_OPTION_NO_ROBOT_AGENT */
404 ndma_session_commission (struct ndm_session *sess)
406 ndmis_commission (sess);
408 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
409 /* ndmca_commission (sess); */
410 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
412 #ifndef NDMOS_OPTION_NO_DATA_AGENT
413 ndmda_commission (sess);
414 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
416 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
417 ndmta_commission (sess);
418 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
420 #ifndef NDMOS_OPTION_NO_ROBOT_AGENT
421 ndmra_commission (sess);
422 #endif /* !NDMOS_OPTION_NO_ROBOT_AGENT */
428 ndma_session_decommission (struct ndm_session *sess)
430 ndmis_decommission (sess);
432 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
433 /* ndmca_decommission (sess); */
434 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
436 #ifndef NDMOS_OPTION_NO_DATA_AGENT
437 ndmda_decommission (sess);
438 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
440 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
441 ndmta_decommission (sess);
442 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
444 #ifndef NDMOS_OPTION_NO_ROBOT_AGENT
445 ndmra_decommission (sess);
446 #endif /* !NDMOS_OPTION_NO_ROBOT_AGENT */