int algopr_send_data(exa_nodeid_t node_id, void *buffer1, int size1, void *buffer2, int size2) { payload_t *payload; EXA_ASSERT(EXA_NODEID_VALID(node_id)); /* FIXME see comment above definition of SIZEOF_ALGOPR_MSGNETWORK_T */ EXA_ASSERT(size1 == SIZEOF_ALGOPR_MSGNETWORK_T); /* Send is local, just forwrd it */ if (node_id == this_node_id) { algopr_new_msg(buffer1, size1, buffer2, size2); return 1; } /* Note: All nbd lists send_list[] share the same root so here we don't * care in which one is picked up the buffer */ payload = nbd_list_remove(ð.send_list[0].root->free, NULL, LISTWAIT); EXA_ASSERT(payload != NULL); memcpy(payload->payload, buffer1, size1); payload->size1 = size1; payload->size2 = size2; payload->buffer = buffer2; nbd_list_post(ð.send_list[node_id], payload, -1); wq_wake(ð.wq_send); return 1; }
/** * Thread responsible for accepting connections * * It's a separate thread because we accept do some memory allocation and we * must avoid that in recv thread. * * @param unused Unused parameter */ static void accept_thread(void *unused) { exalog_as(EXAMSG_ISCSI_ID); while (algopr_run) { exa_nodeid_t node_id; const char *ip_addr; struct sockaddr_in client_address; int size = sizeof(client_address); int sock = os_accept(eth.accept_sock, (struct sockaddr *)&client_address, &size); if (sock < 0) continue; /* it's a false accept */ ip_addr = os_inet_ntoa(client_address.sin_addr); if (!suspended) { exalog_warning("Closing incoming connection from %s while not" " suspended.", ip_addr); __close_socket(sock); continue; } internal_setsock_opt(sock, SOCK_FLAGS); node_id = get_peer_id_from_ip_addr(ip_addr); if (!EXA_NODEID_VALID(node_id)) { exalog_warning("Closing incoming connection from unknown node %s.", ip_addr); __close_socket(sock); continue; } set_peer_socket(node_id, ip_addr, sock); } }
/** \brief Initialization of examsgd daemon. * * Command line must contain the node name and the interface name to use * for control messages. * * Accepts hidden option -d (debugging mode). * * \param[in] argc Argument count. * \param[in] argv Array of argument values. * * \return exit code. */ int daemon_init(int argc, char *argv[]) { int s; /* getopt variables */ static struct option long_opts[] = { { "cluster-id", required_argument, NULL, 'c' }, { "help", no_argument, NULL, 'h' }, { "hostname", required_argument, NULL, 'N' }, { "incarnation", required_argument, NULL, 'I' }, { "mcast-addr", required_argument, NULL, 'm' }, { "mcast-port", required_argument, NULL, 'p' }, { "node-id", required_argument, NULL, 'i' }, { "node-name", required_argument, NULL, 'n' }, { "stats", no_argument, NULL, 's' }, { NULL, 0, NULL, 0 } }; int long_idx, c; char *e; extern char *optarg; extern int optind; /* configurable options and default values */ const char *node_name = NULL; const char *hostname = NULL; const char *mgroup = EXAMSG_MCASTIP; unsigned short mport = EXAMSG_PORT; unsigned short inca = 0; exa_uuid_t cluster_uuid; exa_nodeid_t nodeid; bool err = false; uuid_zero(&cluster_uuid); nodeid = EXA_NODEID_NONE; /* options parsing */ while ((c = os_getopt_long(argc, argv, "c:dhi:I:m:n:N:p:s", long_opts, &long_idx)) != -1) switch (c) { case 'c': if (uuid_scan(optarg, &cluster_uuid) < 0) { fprintf(stderr, "invalid cluster id: '%s'\n", optarg); return -EINVAL; } break; case 'i': nodeid = (exa_nodeid_t)strtol(optarg, &e, 10); if (*e || !EXA_NODEID_VALID(nodeid)) { fprintf(stderr, "invalid node id: '%s'\n", optarg); return -EINVAL; } break; case 'I': inca = (unsigned short)strtol(optarg, &e, 10); if (*e || inca == 0) { fprintf(stderr, "invalid incarnation: '%s'\n", optarg); return -EINVAL; } break; /* multicast group */ case 'm': mgroup = optarg; break; case 'n': node_name = optarg; break; /* hostname */ case 'N': hostname = optarg; break; /* communication port */ case 'p': mport = strtol(optarg, &e, 0); if (*e != '\0') { fprintf(stderr, "invalid port number '%s'\n", optarg); return -EINVAL; } break; case 's': examsg_show_stats(); return 0; break; /* usage */ case 'h': case '?': default: usage(argv[0]); return -EINVAL; } if (uuid_is_zero(&cluster_uuid)) { fprintf(stderr, "missing cluster id\n"); err = true; } if (nodeid == EXA_NODEID_NONE) { fprintf(stderr, "missing node id\n"); err = true; } if (node_name == NULL) { fprintf(stderr, "missing node name\n"); err = true; } if (hostname == NULL) { fprintf(stderr, "missing hostname\n"); err = true; } if (inca == 0) { fprintf(stderr, "missing incarnation\n"); err = true; } if (err) return -EINVAL; /* Get cluster id, number of nodes, node id, node name and interface parameters */ if (argc - optind != 0) { fprintf(stderr, "stray parameters\n"); usage(argv[0]); return -EINVAL; } signal(SIGTERM, sig_term); signal(SIGINT, sig_term); s = examsg_static_init(EXAMSG_STATIC_GET); if (s) { fprintf(stderr, "Can't initialize messaging layer."); return s; } exalog_static_init(); /* Log as exa_msgd by default */ exalog_as(EXAMSG_CMSGD_ID); #ifdef USE_YAOURT if (yaourt_init()) exalog_debug("Yaourt: Examsgd init OK"); else exalog_warning("Yaourt: Examsgd init FAILED (%s)", yaourt_error); #endif /* set up network communication */ return startup(&cluster_uuid, node_name, hostname, nodeid, mgroup, mport, inca); }
/** * init_plugin initialise internal data * * if we are server, try to bind and launch a thread to accept * launch the thread of receive data * * @param net_plugin Info on the new instance that we will fill * * @return EXA_SUCCESS or error */ int algopr_init_plugin(exa_nodeid_t node_id, int max_buffer_size) { struct sockaddr_in serv_addr; int retval = -NBD_ERR_MALLOC_FAILED; int i; EXA_ASSERT(EXA_NODEID_VALID(node_id)); this_node_id = node_id; init_peers(); eth.max_buffer_size = max_buffer_size + max_buffer_size; wq_init(ð.wq_send); nbd_init_root(MAX_BIG_RECV_ELT, eth.max_buffer_size, ð.root_list_big_recv); nbd_init_root(MAX_SEND_ELT, sizeof(payload_t), ð.root_list_send); for (i = 0; i < EXA_MAX_NODES_NUMBER; i++) nbd_init_list(ð.root_list_send, ð.send_list[i]); algopr_run = true; if (!exathread_create_named(ð.receive_thread, NBD_THREAD_STACK_SIZE + MIN_THREAD_STACK_SIZE_OF_THIS_PLUGIN, algopr_receive_thread, NULL, "AlgoPrRcv")) return -NBD_ERR_THREAD_CREATION; if (!exathread_create_named(ð.send_thread, NBD_THREAD_STACK_SIZE + MIN_THREAD_STACK_SIZE_OF_THIS_PLUGIN, algopr_send_thread, NULL, "AlgoPrSnd")) return -NBD_ERR_THREAD_CREATION; eth.accept_sock = os_socket(PF_INET, SOCK_STREAM, 0); if (eth.accept_sock < 0) return -EXA_ERR_CREATE_SOCKET; /* bind a socket to SERVERD_DATA_PORT port and make it listen for incoming * connections */ serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(algopr_network_port); retval = internal_setsock_opt(eth.accept_sock, SOCK_LISTEN_FLAGS); if (retval != EXA_SUCCESS) return retval; if (os_bind(eth.accept_sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) return -EXA_ERR_CREATE_SOCKET; if (os_listen(eth.accept_sock, EXA_MAX_NODES_NUMBER) < 0) return -EXA_ERR_CREATE_SOCKET; if (!exathread_create_named(ð.accept_thread, NBD_THREAD_STACK_SIZE + MIN_THREAD_STACK_SIZE_OF_THIS_PLUGIN, accept_thread, NULL, "servEthAccPlugin")) return -NBD_ERR_THREAD_CREATION; return EXA_SUCCESS; }