static void recover2PC(PGconn *conn, txn_info *txn) { TXN_STATUS txn_stat; txn_stat = check_txn_global_status(txn); if (verbose_opt) { fprintf(outf, " Recovering TXN: gxid: %d, xid: \"%s\", owner: \"%s\", global status: %s\n", txn->gxid, txn->xid, txn->owner, str_txn_stat(txn_stat)); } switch (txn_stat) { case TXN_STATUS_FAILED: if (verbose_opt) fprintf(outf, " Recovery not needed.\n"); return; case TXN_STATUS_PREPARED: if (verbose_opt) fprintf(outf, " Recovery not needed.\n"); return; case TXN_STATUS_COMMITTED: do_commit(conn, txn); return; case TXN_STATUS_ABORTED: do_abort(conn, txn); return; default: fprintf(stderr, " Unknown TXN status, pgxc_clean error.\n"); exit(1); } return; }
/** * run_bg_commit - run background commit if it is needed. * @c: UBIFS file-system description object * * This function runs background commit if it is needed. Returns zero in case * of success and a negative error code in case of failure. */ static int run_bg_commit(struct ubifs_info *c) { spin_lock(&c->cs_lock); /* * Run background commit only if background commit was requested or if * commit is required. */ if (c->cmt_state != COMMIT_BACKGROUND && c->cmt_state != COMMIT_REQUIRED) goto out; spin_unlock(&c->cs_lock); down_write(&c->commit_sem); spin_lock(&c->cs_lock); if (c->cmt_state == COMMIT_REQUIRED) c->cmt_state = COMMIT_RUNNING_REQUIRED; else if (c->cmt_state == COMMIT_BACKGROUND) c->cmt_state = COMMIT_RUNNING_BACKGROUND; else goto out_cmt_unlock; spin_unlock(&c->cs_lock); return do_commit(c); out_cmt_unlock: up_write(&c->commit_sem); out: spin_unlock(&c->cs_lock); return 0; }
/** * ubifs_run_commit - run or wait for commit. * @c: UBIFS file-system description object * * This function runs commit and returns zero in case of success and a negative * error code in case of failure. */ int ubifs_run_commit(struct ubifs_info *c) { int err = 0; spin_lock(&c->cs_lock); if (c->cmt_state == COMMIT_BROKEN) { err = -EINVAL; goto out; } if (c->cmt_state == COMMIT_RUNNING_BACKGROUND) /* * We set the commit state to 'running required' to indicate * that we want it to complete as quickly as possible. */ c->cmt_state = COMMIT_RUNNING_REQUIRED; if (c->cmt_state == COMMIT_RUNNING_REQUIRED) { spin_unlock(&c->cs_lock); return wait_for_commit(c); } spin_unlock(&c->cs_lock); /* Ok, the commit is indeed needed */ down_write(&c->commit_sem); spin_lock(&c->cs_lock); /* * Since we unlocked 'c->cs_lock', the state may have changed, so * re-check it. */ if (c->cmt_state == COMMIT_BROKEN) { err = -EINVAL; goto out_cmt_unlock; } if (c->cmt_state == COMMIT_RUNNING_BACKGROUND) c->cmt_state = COMMIT_RUNNING_REQUIRED; if (c->cmt_state == COMMIT_RUNNING_REQUIRED) { up_write(&c->commit_sem); spin_unlock(&c->cs_lock); return wait_for_commit(c); } c->cmt_state = COMMIT_RUNNING_REQUIRED; spin_unlock(&c->cs_lock); err = do_commit(c); return err; out_cmt_unlock: up_write(&c->commit_sem); out: spin_unlock(&c->cs_lock); return err; }
void end_session(struct session *s) { int err; logmsg(LOG_INFO, "#%d ending session", s->id); /* Flush output buffers. */ if (s->client_bufev && s->client_fd != -1) evbuffer_write(s->client_bufev->output, s->client_fd); if (s->server_bufev && s->server_fd != -1) evbuffer_write(s->server_bufev->output, s->server_fd); if (s->client_fd != -1) close(s->client_fd); if (s->server_fd != -1) close(s->server_fd); if (s->client_bufev) bufferevent_free(s->client_bufev); if (s->server_bufev) bufferevent_free(s->server_bufev); /* Remove rulesets by commiting empty ones. */ err = 0; if (prepare_commit(s->id) == -1) err = errno; else if (do_commit() == -1) { err = errno; do_rollback(); } if (err) logmsg(LOG_ERR, "#%d pf rule removal failed: %s", s->id, strerror(err)); LIST_REMOVE(s, entry); free(s); session_count--; }
int main (int argc, char **argv) { std::string brokers = "localhost"; std::string errstr; std::vector<std::string> topics; std::string conf_file; std::string mode = "P"; int throughput = 0; int32_t partition = RdKafka::Topic::PARTITION_UA; bool do_conf_dump = false; MyHashPartitionerCb hash_partitioner; /* * Create configuration objects */ RdKafka::Conf *conf = RdKafka::Conf::create(RdKafka::Conf::CONF_GLOBAL); RdKafka::Conf *tconf = RdKafka::Conf::create(RdKafka::Conf::CONF_TOPIC); { char hostname[128]; gethostname(hostname, sizeof(hostname)-1); conf->set("client.id", std::string("rdkafka@") + hostname, errstr); } conf->set("debug", "cgrp,topic", errstr); for (int i = 1 ; i < argc ; i++) { const char *name = argv[i]; const char *val = i+1 < argc ? argv[i+1] : NULL; if (val && !strncmp(val, "--", 2)) val = NULL; std::cout << now() << ": argument: " << name << " " << (val?val:"") << std::endl; if (val) { if (!strcmp(name, "--topic")) topics.push_back(val); else if (!strcmp(name, "--broker-list")) brokers = val; else if (!strcmp(name, "--max-messages")) state.maxMessages = atoi(val); else if (!strcmp(name, "--throughput")) throughput = atoi(val); else if (!strcmp(name, "--producer.config") || !strcmp(name, "--consumer.config")) read_conf_file(val); else if (!strcmp(name, "--group-id")) conf->set("group.id", val, errstr); else if (!strcmp(name, "--session-timeout")) conf->set("session.timeout.ms", val, errstr); else if (!strcmp(name, "--reset-policy")) { if (tconf->set("auto.offset.reset", val, errstr)) { std::cerr << now() << ": " << errstr << std::endl; exit(1); } } else if (!strcmp(name, "--debug")) { conf->set("debug", val, errstr); } else { std::cerr << now() << ": Unknown option " << name << std::endl; exit(1); } i++; } else { if (!strcmp(name, "--consumer")) mode = "C"; else if (!strcmp(name, "--producer")) mode = "P"; else if (!strcmp(name, "--enable-autocommit")) { state.consumer.useAutoCommit = true; conf->set("enable.auto.commit", "true", errstr); } else { std::cerr << now() << ": Unknown option or missing argument to " << name << std::endl; exit(1); } } } if (topics.empty() || brokers.empty()) { std::cerr << now() << ": Missing --topic and --broker-list" << std::endl; exit(1); } /* * Set configuration properties */ conf->set("metadata.broker.list", brokers, errstr); ExampleEventCb ex_event_cb; conf->set("event_cb", &ex_event_cb, errstr); if (do_conf_dump) { int pass; for (pass = 0 ; pass < 2 ; pass++) { std::list<std::string> *dump; if (pass == 0) { dump = conf->dump(); std::cerr << now() << ": # Global config" << std::endl; } else { dump = tconf->dump(); std::cerr << now() << ": # Topic config" << std::endl; } for (std::list<std::string>::iterator it = dump->begin(); it != dump->end(); ) { std::cerr << *it << " = "; it++; std::cerr << *it << std::endl; it++; } std::cerr << std::endl; } exit(0); } signal(SIGINT, sigterm); signal(SIGTERM, sigterm); signal(SIGALRM, sigwatchdog); if (mode == "P") { /* * Producer mode */ ExampleDeliveryReportCb ex_dr_cb; /* Set delivery report callback */ conf->set("dr_cb", &ex_dr_cb, errstr); /* * Create producer using accumulated global configuration. */ RdKafka::Producer *producer = RdKafka::Producer::create(conf, errstr); if (!producer) { std::cerr << now() << ": Failed to create producer: " << errstr << std::endl; exit(1); } std::cerr << now() << ": % Created producer " << producer->name() << std::endl; /* * Create topic handle. */ RdKafka::Topic *topic = RdKafka::Topic::create(producer, topics[0], tconf, errstr); if (!topic) { std::cerr << now() << ": Failed to create topic: " << errstr << std::endl; exit(1); } static const int delay_us = throughput ? 1000000/throughput : 0; if (state.maxMessages == -1) state.maxMessages = 1000000; /* Avoid infinite produce */ for (int i = 0 ; run && i < state.maxMessages ; i++) { /* * Produce message */ std::ostringstream msg; msg << i; RdKafka::ErrorCode resp = producer->produce(topic, partition, RdKafka::Producer::RK_MSG_COPY /* Copy payload */, const_cast<char *>(msg.str().c_str()), msg.str().size(), NULL, NULL); if (resp != RdKafka::ERR_NO_ERROR) { errorString("producer_send_error", RdKafka::err2str(resp), topic->name(), NULL, msg.str()); state.producer.numErr++; } else { std::cerr << now() << ": % Produced message (" << msg.str().size() << " bytes)" << std::endl; state.producer.numSent++; } producer->poll(delay_us / 1000); watchdog_kick(); } run = true; while (run && producer->outq_len() > 0) { std::cerr << now() << ": Waiting for " << producer->outq_len() << std::endl; producer->poll(50); watchdog_kick(); } std::cerr << now() << ": " << state.producer.numAcked << "/" << state.producer.numSent << "/" << state.maxMessages << " msgs acked/sent/max, " << state.producer.numErr << " errored" << std::endl; delete topic; delete producer; } else if (mode == "C") { /* * Consumer mode */ tconf->set("auto.offset.reset", "smallest", errstr); /* Set default topic config */ conf->set("default_topic_conf", tconf, errstr); ExampleRebalanceCb ex_rebalance_cb; conf->set("rebalance_cb", &ex_rebalance_cb, errstr); ExampleOffsetCommitCb ex_offset_commit_cb; conf->set("offset_commit_cb", &ex_offset_commit_cb, errstr); /* * Create consumer using accumulated global configuration. */ consumer = RdKafka::KafkaConsumer::create(conf, errstr); if (!consumer) { std::cerr << now() << ": Failed to create consumer: " << errstr << std::endl; exit(1); } std::cerr << now() << ": % Created consumer " << consumer->name() << std::endl; /* * Subscribe to topic(s) */ RdKafka::ErrorCode resp = consumer->subscribe(topics); if (resp != RdKafka::ERR_NO_ERROR) { std::cerr << now() << ": Failed to subscribe to " << topics.size() << " topics: " << RdKafka::err2str(resp) << std::endl; exit(1); } /* * Consume messages */ while (run) { RdKafka::Message *msg = consumer->consume(500); msg_consume(consumer, msg, NULL); delete msg; watchdog_kick(); } /* Final commit */ do_commit(consumer, 1); /* * Stop consumer */ consumer->close(); delete consumer; } /* * Wait for RdKafka to decommission. * This is not strictly needed (when check outq_len() above), but * allows RdKafka to clean up all its resources before the application * exits so that memory profilers such as valgrind wont complain about * memory leaks. */ RdKafka::wait_destroyed(5000); std::cerr << now() << ": EXITING WITH RETURN VALUE 0" << std::endl; return 0; }
void msg_consume(RdKafka::KafkaConsumer *consumer, RdKafka::Message* msg, void* opaque) { switch (msg->err()) { case RdKafka::ERR__TIMED_OUT: /* Try reporting consumed messages */ report_records_consumed(1); /* Commit one every consume() timeout instead of on every message. * Also commit on every 1000 messages, whichever comes first. */ do_commit(consumer, 1); break; case RdKafka::ERR_NO_ERROR: { /* Real message */ std::cerr << now() << ": Read msg from " << msg->topic_name() << " [" << (int)msg->partition() << "] at offset " << msg->offset() << std::endl; if (state.maxMessages >= 0 && state.consumer.consumedMessages >= state.maxMessages) return; Assignment *a = &state.consumer.assignments[Assignment::name(msg->topic_name(), msg->partition())]; a->setup(msg->topic_name(), msg->partition()); a->consumedMessages++; if (a->minOffset == -1) a->minOffset = msg->offset(); if (a->maxOffset < msg->offset()) a->maxOffset = msg->offset(); if (msg->key()) { std::cerr << now() << ": Key: " << *msg->key() << std::endl; } fprintf(stderr, "%.*s\n", static_cast<int>(msg->len()), static_cast<const char *>(msg->payload())); state.consumer.consumedMessages++; report_records_consumed(0); do_commit(consumer, 0); } break; case RdKafka::ERR__PARTITION_EOF: /* Last message */ if (exit_eof) { run = false; } break; case RdKafka::ERR__UNKNOWN_TOPIC: case RdKafka::ERR__UNKNOWN_PARTITION: std::cerr << now() << ": Consume failed: " << msg->errstr() << std::endl; run = false; break; case RdKafka::ERR_GROUP_COORDINATOR_NOT_AVAILABLE: std::cerr << now() << ": Warning: " << msg->errstr() << std::endl; break; default: /* Errors */ std::cerr << now() << ": Consume failed: " << msg->errstr() << std::endl; run = false; } }
int main(int argc, char *argv[]) { int c, fd = 0, on = 1, out_fd = 0, peer, reqsize = 0; int transwait = DEFTRANSWAIT; char *p; struct tftphdr *tp; struct passwd *pw; size_t cbuflen; char *cbuf; char req[PKTSIZE]; struct cmsghdr *cmsg; struct msghdr msg; struct iovec iov; struct sockaddr_storage from, proxy, server, proxy_to_server, s_in; struct sockaddr_in sock_out; socklen_t j; in_port_t bindport; openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON); while ((c = getopt(argc, argv, "vw:")) != -1) switch (c) { case 'v': verbose++; break; case 'w': transwait = strtoll(optarg, &p, 10); if (transwait < 1) { syslog(LOG_ERR, "invalid -w value"); exit(1); } break; default: usage(); break; } /* open /dev/pf */ init_filter(NULL, verbose); tzset(); pw = getpwnam(NOPRIV_USER); if (!pw) { syslog(LOG_ERR, "no such user %s: %m", NOPRIV_USER); exit(1); } if (chroot(CHROOT_DIR) || chdir("/")) { syslog(LOG_ERR, "chroot %s: %m", CHROOT_DIR); exit(1); } #ifdef __NetBSD__ if (setgroups(1, &pw->pw_gid) || setgid(pw->pw_gid) || setuid(pw->pw_uid)) { syslog(LOG_ERR, "can't revoke privs: %m"); exit(1); } #else if (setgroups(1, &pw->pw_gid) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) { syslog(LOG_ERR, "can't revoke privs: %m"); exit(1); } #endif /* !__NetBSD__ */ /* non-blocking io */ if (ioctl(fd, FIONBIO, &on) < 0) { syslog(LOG_ERR, "ioctl(FIONBIO): %m"); exit(1); } if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on)) == -1) { syslog(LOG_ERR, "setsockopt(IP_RECVDSTADDR): %m"); exit(1); } j = sizeof(s_in); if (getsockname(fd, (struct sockaddr *)&s_in, &j) == -1) { syslog(LOG_ERR, "getsockname: %m"); exit(1); } bindport = ((struct sockaddr_in *)&s_in)->sin_port; /* req will be pushed back out at the end, unchanged */ j = sizeof(from); if ((reqsize = recvfrom(fd, req, sizeof(req), MSG_PEEK, (struct sockaddr *)&from, &j)) < 0) { syslog(LOG_ERR, "recvfrom: %m"); exit(1); } bzero(&msg, sizeof(msg)); iov.iov_base = req; iov.iov_len = sizeof(req); msg.msg_name = &from; msg.msg_namelen = sizeof(from); msg.msg_iov = &iov; msg.msg_iovlen = 1; cbuflen = CMSG_SPACE(sizeof(struct sockaddr_storage)); if ((cbuf = malloc(cbuflen)) == NULL) { syslog(LOG_ERR, "malloc: %m"); exit(1); } msg.msg_control = cbuf; msg.msg_controllen = cbuflen; if (recvmsg(fd, &msg, 0) < 0) { syslog(LOG_ERR, "recvmsg: %m"); exit(1); } close(fd); close(1); peer = socket(from.ss_family, SOCK_DGRAM, 0); if (peer < 0) { syslog(LOG_ERR, "socket: %m"); exit(1); } memset(&s_in, 0, sizeof(s_in)); s_in.ss_family = from.ss_family; s_in.ss_len = from.ss_len; /* get local address if possible */ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) { if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR) { memcpy(&((struct sockaddr_in *)&s_in)->sin_addr, CMSG_DATA(cmsg), sizeof(struct in_addr)); break; } } if (bind(peer, (struct sockaddr *)&s_in, s_in.ss_len) < 0) { syslog(LOG_ERR, "bind: %m"); exit(1); } if (connect(peer, (struct sockaddr *)&from, from.ss_len) < 0) { syslog(LOG_ERR, "connect: %m"); exit(1); } tp = (struct tftphdr *)req; if (!(ntohs(tp->th_opcode) == RRQ || ntohs(tp->th_opcode) == WRQ)) { /* not a tftp request, bail */ if (verbose) { syslog(LOG_WARNING, "not a valid tftp request"); exit(1); } else /* exit 0 so inetd doesn't log anything */ exit(0); } j = sizeof(struct sockaddr_storage); if (getsockname(fd, (struct sockaddr *)&proxy, &j) == -1) { syslog(LOG_ERR, "getsockname: %m"); exit(1); } ((struct sockaddr_in *)&proxy)->sin_port = bindport; /* find the un-rdr'd server and port the client wanted */ if (server_lookup((struct sockaddr *)&from, (struct sockaddr *)&proxy, (struct sockaddr *)&server, IPPROTO_UDP) != 0) { syslog(LOG_ERR, "pf connection lookup failed (no rdr?)"); exit(1); } /* establish a new outbound connection to the remote server */ if ((out_fd = socket(((struct sockaddr *)&from)->sa_family, SOCK_DGRAM, IPPROTO_UDP)) < 0) { syslog(LOG_ERR, "couldn't create new socket"); exit(1); } bzero((char *)&sock_out, sizeof(sock_out)); sock_out.sin_family = from.ss_family; sock_out.sin_port = htons(pick_proxy_port()); if (bind(out_fd, (struct sockaddr *)&sock_out, sizeof(sock_out)) < 0) { syslog(LOG_ERR, "couldn't bind to new socket: %m"); exit(1); } if (connect(out_fd, (struct sockaddr *)&server, ((struct sockaddr *)&server)->sa_len) < 0 && errno != EINPROGRESS) { syslog(LOG_ERR, "couldn't connect to remote server: %m"); exit(1); } j = sizeof(struct sockaddr_storage); if ((getsockname(out_fd, (struct sockaddr *)&proxy_to_server, &j)) < 0) { syslog(LOG_ERR, "getsockname: %m"); exit(1); } if (verbose) syslog(LOG_INFO, "%s:%d -> %s:%d/%s:%d -> %s:%d \"%s %s\"", sock_ntop((struct sockaddr *)&from), ntohs(((struct sockaddr_in *)&from)->sin_port), sock_ntop((struct sockaddr *)&proxy), ntohs(((struct sockaddr_in *)&proxy)->sin_port), sock_ntop((struct sockaddr *)&proxy_to_server), ntohs(((struct sockaddr_in *)&proxy_to_server)->sin_port), sock_ntop((struct sockaddr *)&server), ntohs(((struct sockaddr_in *)&server)->sin_port), opcode(ntohs(tp->th_opcode)), tp->th_stuff); /* get ready to add rdr and pass rules */ if (prepare_commit(1) == -1) { syslog(LOG_ERR, "couldn't prepare pf commit"); exit(1); } /* rdr from server to us on our random port -> client on its port */ if (add_rdr(1, (struct sockaddr *)&server, (struct sockaddr *)&proxy_to_server, ntohs(sock_out.sin_port), (struct sockaddr *)&from, ntohs(((struct sockaddr_in *)&from)->sin_port), IPPROTO_UDP) == -1) { syslog(LOG_ERR, "couldn't add rdr"); exit(1); } /* explicitly allow the packets to return back to the client (which pf * will see post-rdr) */ if (add_filter(1, PF_IN, (struct sockaddr *)&server, (struct sockaddr *)&from, ntohs(((struct sockaddr_in *)&from)->sin_port), IPPROTO_UDP) == -1) { syslog(LOG_ERR, "couldn't add pass in"); exit(1); } if (add_filter(1, PF_OUT, (struct sockaddr *)&server, (struct sockaddr *)&from, ntohs(((struct sockaddr_in *)&from)->sin_port), IPPROTO_UDP) == -1) { syslog(LOG_ERR, "couldn't add pass out"); exit(1); } /* and just in case, to pass out from us to the server */ if (add_filter(1, PF_OUT, (struct sockaddr *)&proxy_to_server, (struct sockaddr *)&server, ntohs(((struct sockaddr_in *)&server)->sin_port), IPPROTO_UDP) == -1) { syslog(LOG_ERR, "couldn't add pass out"); exit(1); } if (do_commit() == -1) { syslog(LOG_ERR, "couldn't commit pf rules"); exit(1); } /* forward the initial tftp request and start the insanity */ if (send(out_fd, tp, reqsize, 0) < 0) { syslog(LOG_ERR, "couldn't forward tftp packet: %m"); exit(1); } /* allow the transfer to start to establish a state */ sleep(transwait); /* delete our rdr rule and clean up */ prepare_commit(1); do_commit(); return(0); }
int allow_data_connection(struct session *s) { struct sockaddr *client_sa, *orig_sa, *proxy_sa, *server_sa; int prepared = 0; /* * The pf rules below do quite some NAT rewriting, to keep up * appearances. Points to keep in mind: * 1) The client must think it's talking to the real server, * for both control and data connections. Transparently. * 2) The server must think that the proxy is the client. * 3) Source and destination ports are rewritten to minimize * port collisions, to aid security (some systems pick weak * ports) or to satisfy RFC requirements (source port 20). */ /* Cast this once, to make code below it more readable. */ client_sa = sstosa(&s->client_ss); server_sa = sstosa(&s->server_ss); proxy_sa = sstosa(&s->proxy_ss); if (fixed_server) /* Fixed server: data connections must appear to come from / go to the original server, not the fixed one. */ orig_sa = sstosa(&s->orig_server_ss); else /* Server not fixed: orig_server == server. */ orig_sa = sstosa(&s->server_ss); /* Passive modes. */ if (s->cmd == CMD_PASV || s->cmd == CMD_EPSV) { s->port = parse_port(s->cmd); if (s->port < MIN_PORT) { logmsg(LOG_CRIT, "#%d bad port in '%s'", s->id, linebuf); return (0); } s->proxy_port = pick_proxy_port(); logmsg(LOG_INFO, "#%d passive: client to server port %d" " via port %d", s->id, s->port, s->proxy_port); if (prepare_commit(s->id) == -1) goto fail; prepared = 1; proxy_reply(s->cmd, orig_sa, s->proxy_port); logmsg(LOG_DEBUG, "#%d proxy: %s", s->id, linebuf); /* pass in from $client to $orig_server port $proxy_port rdr-to $server port $port */ if (add_rdr(s->id, client_sa, s->client_rd, orig_sa, s->proxy_port, server_sa, s->port, getrtable()) == -1) goto fail; /* pass out from $client to $server port $port nat-to $proxy */ if (add_nat(s->id, client_sa, getrtable(), server_sa, s->port, proxy_sa, PF_NAT_PROXY_PORT_LOW, PF_NAT_PROXY_PORT_HIGH) == -1) goto fail; } /* Active modes. */ if (s->cmd == CMD_PORT || s->cmd == CMD_EPRT) { logmsg(LOG_INFO, "#%d active: server to client port %d" " via port %d", s->id, s->port, s->proxy_port); if (prepare_commit(s->id) == -1) goto fail; prepared = 1; /* pass in from $server to $proxy port $proxy_port rdr-to $client port $port */ if (add_rdr(s->id, server_sa, getrtable(), proxy_sa, s->proxy_port, client_sa, s->port, s->client_rd) == -1) goto fail; /* pass out from $server to $client port $port nat-to $orig_server port $natport */ if (rfc_mode && s->cmd == CMD_PORT) { /* Rewrite sourceport to RFC mandated 20. */ if (add_nat(s->id, server_sa, s->client_rd, client_sa, s->port, orig_sa, 20, 20) == -1) goto fail; } else { /* Let pf pick a source port from the standard range. */ if (add_nat(s->id, server_sa, s->client_rd, client_sa, s->port, orig_sa, PF_NAT_PROXY_PORT_LOW, PF_NAT_PROXY_PORT_HIGH) == -1) goto fail; } } /* Commit rules if they were prepared. */ if (prepared && (do_commit() == -1)) { if (errno != EBUSY) goto fail; /* One more try if busy. */ usleep(5000); if (do_commit() == -1) goto fail; } s->cmd = CMD_NONE; s->port = 0; return (1); fail: logmsg(LOG_CRIT, "#%d pf operation failed: %s", s->id, strerror(errno)); if (prepared) do_rollback(); return (0); }
int main(int argc, const char** argv) { ndb_init(); const char* usage = "Usage: ndbsql [-h] [-d dsn] [-f file] [stmt]\n-h help\n-d <database name or connect string>\n-f <file name> batch mode\nstmt single SQL statement\n"; const char* dsn = "TEST_DB"; bool helpFlg = false, batchMode = false; const char* fileName = 0; FILE* inputFile = stdin; const char* singleStmt = 0; s_readBuf = (char*)malloc(s_bufSize); while (++argv, --argc > 0) { const char* arg = argv[0]; if (arg[0] != '-') break; if (strcmp(arg, "-d") == 0) { if (++argv, --argc > 0) { dsn = argv[0]; continue; } } if (strcmp(arg, "-h") == 0) { helpFlg = true; continue; } if (strcmp(arg, "-f") == 0) { if (++argv, --argc > 0) { fileName = argv[0]; continue; } } ndbout << usage; return 1; } if (helpFlg) { ndbout << usage << "\n"; print_help(); return 0; } if (fileName != 0) { if (argc > 0) { ndbout << usage; return 1; } if ((inputFile = fopen(fileName, "r")) == 0) { ndbout << "Could not read file " << fileName << ": " << strerror(errno) << endl; return 1; } batchMode = true; } if (argc > 0) { singleStmt = argv[0]; batchMode = true; } if (! batchMode) ndbout << "NDB Cluster NDB SQL -- A simple SQL Command-line Interface\n\n"; Con con(dsn); if (do_connect(con) < 0) return 1; if (! batchMode) ndbout << "Terminate SQL statements with a semi-colon ';'\n"; char* line = 0; char* line2 = 0; char* line3 = 0; unsigned lineno = 0; bool has_semi; bool exit_on_error = false; int exit_code = 0; while (1) { free(line); line = 0; lineno = 0; more_lines: free(line2); free(line3); line2 = line3 = 0; lineno++; has_semi = false; char prompt[20]; if (lineno == 1) strcpy(prompt, "SQL> "); else sprintf(prompt, "%4d ", lineno); if (singleStmt != 0) { line = strdup(singleStmt); int n = strlen(line); while (n > 0 && isspace(line[n - 1])) { line[--n] = 0; } if (n > 0 && line[n - 1] == ';') line[n - 1] = 0; has_semi = true; // regardless } else { const char *line1 = readline_gets(prompt, batchMode, inputFile); if (line1 != 0) { if (line == 0) line = strdup(line1); else { line = (char*)realloc(line, strlen(line) + 1 + strlen(line1) + 1); strcat(line, "\n"); strcat(line, line1); } if (batchMode) ndbout << prompt << line1 << endl; } else { if (! batchMode) ndbout << endl; if (line != 0) ndbout << "Ignored unterminated SQL statement" << endl; break; } } line2 = (char*)malloc(strlen(line) + 1); { char* p = line2; char* q = line; bool str = false; while (*q != 0) { if (*q == '\'') { str = !str; *p++ = *q++; } else if (!str && *q == '-' && *(q + 1) == '-') { while (*q != 0 && *q != '\n') q++; } else *p++ = *q++; } *p = 0; int n = strlen(line2); while (n > 0 && isspace(line2[n - 1])) line2[--n] = 0; if (n > 0 && line2[n - 1] == ';') { line2[--n] = 0; has_semi = true; } } line3 = strdup(line2); char* tok[10]; int ntok = 0; tok[ntok] = strtok(line3, " "); while (tok[ntok] != 0) { ntok++; if (ntok == 10) break; tok[ntok] = strtok(0, " "); } if (ntok == 0) continue; if (!strcasecmp(tok[0], "help") || !strcmp(tok[0], "?")) { if (ntok != 2) print_help(); else if (!strcasecmp(tok[1], "create")) print_help_create(); else if (!strcasecmp(tok[1], "insert")) print_help_insert(); else if (strcasecmp(tok[1], "select")) print_help_select(); else if (!strcasecmp(tok[1], "delete")) print_help_update(); else if (!strcasecmp(tok[1], "update")) print_help_update(); else if (!strcasecmp(tok[1], "virtual")) print_help_virtual(); else print_help(); continue; } if (!strcasecmp(tok[0], "list")) { if (ntok == 2 && !strcasecmp(tok[1], "tables")) { free(line2); line2 = strdup("SELECT TABLE_NAME FROM ODBC$TABLES"); has_semi = true; } else { ndbout << "Invalid list option - try help" << endl; continue; } } if (ntok == 1 && !strcasecmp(tok[0], "quit")) break; if (ntok == 1 && !strcasecmp(tok[0], "exit")) break; if (ntok == 1 && !strcasecmp(tok[0], "bye")) break; if (!strcasecmp(tok[0], "set")) { if (ntok == 1) { char* p; p = getenv("NDB_ODBC_TRACE"); ndbout << "Trace level is " << (p ? atoi(p) : 0) << endl; int ret = get_autocommit(con); if (ret != -1) ndbout << "Autocommit is " << (ret == SQL_AUTOCOMMIT_ON ? "on" : "off") << endl; } else if (ntok == 3 && !strcasecmp(tok[1], "trace")) { static char env[40]; int n = tok[2] ? atoi(tok[2]) : 0; sprintf(env, "NDB_ODBC_TRACE=%d", n); putenv(env); ndbout << "Trace level set to " << n << endl; } else if (ntok == 3 && !strcasecmp(tok[1], "autocommit")) { if (tok[2] && !strcasecmp(tok[2], "on")) { int ret = set_autocommit(con, SQL_AUTOCOMMIT_ON); if (ret != -1) ndbout << "Autocommit set to ON" << endl; } else if (tok[2] && !strcasecmp(tok[2], "off")) { int ret = set_autocommit(con, SQL_AUTOCOMMIT_OFF); if (ret != -1) ndbout << "Autocommit set to OFF - transaction may time out" << endl; } else { ndbout << "Invalid autocommit option - try help" << endl; } } else { ndbout << "Invalid set command - try help" << endl; } continue; } if (ntok >= 2 && !strcasecmp(tok[0], "whenever") && !strcasecmp(tok[1], "sqlerror")) { if (ntok == 3 && !strcasecmp(tok[2], "exit")) exit_on_error = true; else if (ntok == 3 && !strcasecmp(tok[2], "continue")) exit_on_error = false; else { ndbout << "Invalid whenever clause - try help" << endl; } continue; } if (!strcasecmp(tok[0], "commit")) { if (ntok == 1) { if (do_commit(con) != -1) ndbout << "Commit done" << endl; else { exit_code = 1; if (exit_on_error) { ndbout << "Exit on error" << endl; break; } } } else { ndbout << "Invalid commit command - try help" << endl; } continue; } if (!strcasecmp(tok[0], "rollback")) { if (ntok == 1) { if (do_rollback(con) != -1) ndbout << "Rollback done" << endl; else { exit_code = 1; if (exit_on_error) { ndbout << "Exit on error" << endl; break; } } } else { ndbout << "Invalid commit command - try help" << endl; } continue; } if (! has_semi) goto more_lines; if (do_stmt(con, line2) != 0) { exit_code = 1; if (exit_on_error) { ndbout << "Exit on error" << endl; break; } } if (singleStmt) break; } do_disconnect(con); return exit_code; }
int main(int argc, const char** argv){ ndb_init(); int _help = 0; const char* db = 0; const char* connectstring1 = 0; const char* connectstring2 = 0; struct getargs args[] = { { "connectstring1", 'c', arg_string, &connectstring1, "connectstring1", "" }, { "connectstring2", 'C', arg_string, &connectstring2, "connectstring2", "" }, { "database", 'd', arg_string, &db, "Database", "" }, { "usage", '?', arg_flag, &_help, "Print help", "" } }; int num_args = sizeof(args) / sizeof(args[0]); int optind = 0, i; char desc[] = "<tabname>+ \nThis program listen to events on specified tables\n"; if(getarg(args, num_args, argc, argv, &optind) || argv[optind] == NULL || _help) { arg_printusage(args, num_args, argv[0], desc); return NDBT_ProgramExit(NDBT_WRONGARGS); } // Connect to Ndb Ndb_cluster_connection con(connectstring1); if(con.connect(12, 5, 1) != 0) { return NDBT_ProgramExit(NDBT_FAILED); } Ndb MyNdb( &con, db ? db : "TEST_DB" ); if(MyNdb.init() != 0){ ERR(MyNdb.getNdbError()); return NDBT_ProgramExit(NDBT_FAILED); } // Connect to Ndb and wait for it to become ready while(MyNdb.waitUntilReady() != 0) ndbout << "Waiting for ndb to become ready..." << endl; Ndb_cluster_connection *con2 = NULL; Ndb *ndb2 = NULL; if (connectstring2) { con2 = new Ndb_cluster_connection(connectstring2); if(con2->connect(12, 5, 1) != 0) { return NDBT_ProgramExit(NDBT_FAILED); } ndb2 = new Ndb( con2, db ? db : "TEST_DB" ); if(ndb2->init() != 0){ ERR(ndb2->getNdbError()); return NDBT_ProgramExit(NDBT_FAILED); } // Connect to Ndb and wait for it to become ready while(ndb2->waitUntilReady() != 0) ndbout << "Waiting for ndb to become ready..." << endl; } int result = 0; NdbDictionary::Dictionary *myDict = MyNdb.getDictionary(); Vector<NdbDictionary::Event*> events; Vector<NdbEventOperation*> event_ops; int sz = 0; for(i= optind; i<argc; i++) { const NdbDictionary::Table* table= myDict->getTable(argv[i]); if(!table) { ndbout_c("Could not find table: %s, skipping", argv[i]); continue; } BaseString name; name.appfmt("EV-%s", argv[i]); NdbDictionary::Event *myEvent= new NdbDictionary::Event(name.c_str()); myEvent->setTable(table->getName()); myEvent->addTableEvent(NdbDictionary::Event::TE_ALL); for(int a = 0; a < table->getNoOfColumns(); a++){ myEvent->addEventColumn(a); } if (myDict->createEvent(* myEvent)) { if(myDict->getNdbError().classification == NdbError::SchemaObjectExists) { g_info << "Event creation failed event exists. Removing...\n"; if (myDict->dropEvent(name.c_str())) { g_err << "Failed to drop event: " << myDict->getNdbError() << endl; result = 1; goto end; } // try again if (myDict->createEvent(* myEvent)) { g_err << "Failed to create event: " << myDict->getNdbError() << endl; result = 1; goto end; } } else { g_err << "Failed to create event: " << myDict->getNdbError() << endl; result = 1; goto end; } } events.push_back(myEvent); NdbEventOperation* pOp = MyNdb.createEventOperation(name.c_str()); if ( pOp == NULL ) { g_err << "Event operation creation failed" << endl; result = 1; goto end; } event_values.push_back(Vector<NdbRecAttr *>()); event_pre_values.push_back(Vector<NdbRecAttr *>()); for (int a = 0; a < table->getNoOfColumns(); a++) { event_values[sz]. push_back(pOp->getValue(table->getColumn(a)->getName())); event_pre_values[sz]. push_back(pOp->getPreValue(table->getColumn(a)->getName())); } event_ops.push_back(pOp); { struct Table_info ti; ti.id = sz; table_infos.push_back(ti); } pOp->setCustomData((void *)&table_infos[sz]); sz++; } for(i= 0; i<(int)event_ops.size(); i++) { if (event_ops[i]->execute()) { g_err << "operation execution failed: " << event_ops[i]->getNdbError() << endl; result = 1; goto end; } } struct Trans_arg trans_arg; while(true) { while(MyNdb.pollEvents(100) == 0); NdbEventOperation* pOp= MyNdb.nextEvent(); while(pOp) { Uint64 gci= pOp->getGCI(); Uint64 cnt_i= 0, cnt_u= 0, cnt_d= 0; if (ndb2) do_begin(ndb2, trans_arg); do { switch(pOp->getEventType()) { case NdbDictionary::Event::TE_INSERT: cnt_i++; if (ndb2) do_insert(trans_arg, pOp); break; case NdbDictionary::Event::TE_DELETE: cnt_d++; if (ndb2) do_delete(trans_arg, pOp); break; case NdbDictionary::Event::TE_UPDATE: cnt_u++; if (ndb2) do_update(trans_arg, pOp); break; case NdbDictionary::Event::TE_CLUSTER_FAILURE: break; case NdbDictionary::Event::TE_ALTER: break; case NdbDictionary::Event::TE_DROP: break; case NdbDictionary::Event::TE_NODE_FAILURE: break; case NdbDictionary::Event::TE_SUBSCRIBE: case NdbDictionary::Event::TE_UNSUBSCRIBE: break; default: /* We should REALLY never get here. */ ndbout_c("Error: unknown event type: %u", (Uint32)pOp->getEventType()); abort(); } } while ((pOp= MyNdb.nextEvent()) && gci == pOp->getGCI()); if (ndb2) do_commit(trans_arg); ndbout_c("GCI: %lld events: %lld(I) %lld(U) %lld(D)", gci, cnt_i, cnt_u, cnt_d); } } end: for(i= 0; i<(int)event_ops.size(); i++) MyNdb.dropEventOperation(event_ops[i]); if (ndb2) delete ndb2; if (con2) delete con2; return NDBT_ProgramExit(NDBT_OK); }