freetds AT lists.ibiblio.org
Subject: FreeTDS Development Group
List archive
- From: Frediano Ziglio <freddy77 AT gmail.com>
- To: FreeTDS Development Group <freetds AT lists.ibiblio.org>
- Subject: Re: [freetds] [0.95rc2] Preliminary test results
- Date: Wed, 13 May 2015 04:27:02 +0100
2015-05-12 23:10 GMT+01:00 Frediano Ziglio <freddy77 AT gmail.com>:
> 2015-05-12 21:07 GMT+01:00 Sergio NNX <sfhacker AT hotmail.com>:
....
>
>>
>>>> freeclose test output
>>>>
>>>> [...]
>>>> Error finding last socket opened
>>>> FAIL freeclose.exe (exit status: 1)
>>>>
>>
>>> Can you try the attached version?
>>
>> It didn't work. Same error message as before.
>> I'd like to understand that test. What's a typical result for this
>> function: odbc_find_last_socket(void)?
>> What's a common (or default) value for ip remote addr and remote port?
>> Show me an example.
>>
>> Thanks for your time.
>>
>> Sergio.
>>
>
> This function is quite an hack function. It try to discover the last
> socket connection opened. So it try to scan a lot of possible handles
> (numerically 4096 starting from 4, so 4, 8, 12, 16 ... etc) and call
> some function to check if they are really sockets (getpeername and
> getsockname). I also recently changed to discard pair of socketpair
> (two sockets attached together).
>
> I attached a new version, should handle IPv6 addresses (unfortunately
> sizeof(struct sockaddr) < sizeof(struct sockaddr_in6) on Windows).
>
Sorry, silly mistake in attachment
Frediano
#include "common.h" #if HAVE_UNISTD_H #include <unistd.h> #endif /* HAVE_UNISTD_H */ #include <freetds/time.h> #if HAVE_ERRNO_H #include <errno.h> #endif /* HAVE_ERRNO_H */ #if HAVE_SYS_SOCKET_H #include <sys/socket.h> #endif /* HAVE_SYS_SOCKET_H */ #if HAVE_SYS_STAT_H #include <sys/stat.h> #endif /* HAVE_SYS_STAT_H */ #if HAVE_SYS_IOCTL_H #include <sys/ioctl.h> #endif /* HAVE_SYS_IOCTL_H */ #if HAVE_SYS_WAIT_H #include <sys/wait.h> #endif /* HAVE_SYS_WAIT_H */ #if HAVE_NETINET_IN_H #include <netinet/in.h> #endif /* HAVE_NETINET_IN_H */ #if (!defined(TDS_NO_THREADSAFE) && HAVE_ALARM && HAVE_FSTAT && defined(S_IFSOCK)) || defined(_WIN32) #include <ctype.h> #include <freetds/tds.h> #include <freetds/thread.h> /* this crazy test test that we do not send too much prepare ... */ static tds_mutex mtx; typedef union { struct sockaddr sa; struct sockaddr_in sin; char dummy[256]; } long_sockaddr; #ifdef _WIN32 static TDS_SYS_SOCKET odbc_find_last_socket(void) { typedef struct { TDS_SYS_SOCKET sock; int local_port; int remote_port; } sock_info; sock_info found[8]; unsigned num_found = 0, n; int i; for (i = 4; i <= (4096*4); i += 4) { long_sockaddr remote_addr, local_addr; struct sockaddr_in *in; socklen_t remote_addr_len, local_addr_len; sock_info *info; /* check if is a socket */ remote_addr_len = sizeof(remote_addr); if (tds_getpeername((TDS_SYS_SOCKET) i, &remote_addr.sa, &remote_addr_len)) continue; local_addr_len = sizeof(local_addr); if (tds_getsockname((TDS_SYS_SOCKET) i, &local_addr.sa, &local_addr_len)) continue; /* save in the array */ if (num_found >= 8) { memmove(found, found+1, sizeof(found) - sizeof(found[0])); num_found = 7; } info = &found[num_found++]; info->sock = (TDS_SYS_SOCKET) i; info->local_port = -1; info->remote_port = -1; /* now check if is a socketpair */ in = &remote_addr.sin; if (in->sin_family != AF_INET) continue; if (in->sin_addr.s_addr != htonl(INADDR_LOOPBACK)) continue; info->remote_port = ntohs(in->sin_port); in = &local_addr.sin; if (in->sin_family != AF_INET) continue; if (in->sin_addr.s_addr != htonl(INADDR_LOOPBACK)) continue; info->local_port = ntohs(in->sin_port); for (n = 0; n < num_found - 1; ++n) { if (found[n].remote_port != info->local_port || found[n].local_port != info->remote_port) continue; --num_found; memmove(found+n, found+n+1, num_found-n-1); --num_found; break; } } /* return last */ if (num_found == 0) return INVALID_SOCKET; return found[num_found-1].sock; } #endif static long_sockaddr remote_addr; static socklen_t remote_addr_len; static TDS_SYS_SOCKET fake_sock; static tds_thread fake_thread; #ifdef _WIN32 #define alarm(n) do { ; } while(0) #endif static TDS_THREAD_PROC_DECLARE(fake_thread_proc, arg); static int init_fake_server(int ip_port) { struct sockaddr_in sin; TDS_SYS_SOCKET s; memset(&sin, 0, sizeof(sin)); sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = htons((short) ip_port); sin.sin_family = AF_INET; if (TDS_IS_SOCKET_INVALID(s = socket(AF_INET, SOCK_STREAM, 0))) { perror("socket"); exit(1); } if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) { perror("bind"); CLOSESOCKET(s); return 1; } listen(s, 5); if (tds_thread_create(&fake_thread, fake_thread_proc, int2ptr(s)) != 0) { perror("tds_thread_create"); exit(1); } return 0; } static void write_all(TDS_SYS_SOCKET s, const void *buf, size_t len) { int res, l; fd_set fds_write; for (; len > 0;) { FD_ZERO(&fds_write); FD_SET(s, &fds_write); res = select(s + 1, NULL, &fds_write, NULL, NULL); if (res <= 0) { if (errno == EINTR) continue; perror("select"); exit(1); } l = WRITESOCKET(s, buf, len); if (l <= 0) { perror("write socket"); exit(1); } buf = ((const char *) buf) + l; len -= l; } } static unsigned int inserts = 0; static char insert_buf[256] = ""; static void count_insert(const char* buf, size_t len) { static const char search[] = "insert into"; static unsigned char prev = 'x'; char *p; unsigned char c; size_t insert_len; /* add to buffer */ for (p = strchr(insert_buf, 0); len > 0; --len, ++buf) { c = (unsigned char) buf[0]; if (prev == 0 || c != 0) *p++ = (c >= ' ' && c < 128) ? tolower(c) : '_'; prev = c; } *p = 0; /* check it */ while ((p=strstr(insert_buf, search)) != NULL) { tds_mutex_lock(&mtx); ++inserts; tds_mutex_unlock(&mtx); /* do not find again */ p[0] = '_'; } /* avoid buffer too long */ insert_len = strlen(insert_buf); if (insert_len > sizeof(search)) { p = insert_buf + insert_len - sizeof(search); memmove(insert_buf, p, strlen(p) + 1); } } static unsigned int round_trips = 0; static enum { sending, receiving } flow = sending; static TDS_THREAD_PROC_DECLARE(fake_thread_proc, arg) { TDS_SYS_SOCKET s = ptr2int(arg), server_sock; socklen_t sock_len; int len; char buf[128]; struct sockaddr_in sin; fd_set fds_read, fds_write, fds_error; TDS_SYS_SOCKET max_fd = 0; memset(&sin, 0, sizeof(sin)); sock_len = sizeof(sin); alarm(30); if ((fake_sock = tds_accept(s, (struct sockaddr *) &sin, &sock_len)) < 0) { perror("accept"); exit(1); } CLOSESOCKET(s); if (TDS_IS_SOCKET_INVALID(server_sock = socket(AF_INET, SOCK_STREAM, 0))) { perror("socket"); exit(1); } if (connect(server_sock, &remote_addr.sa, remote_addr_len)) { perror("connect"); exit(1); } alarm(0); if (fake_sock > max_fd) max_fd = fake_sock; if (server_sock > max_fd) max_fd = server_sock; for (;;) { int res; FD_ZERO(&fds_read); FD_SET(fake_sock, &fds_read); FD_SET(server_sock, &fds_read); FD_ZERO(&fds_write); FD_ZERO(&fds_error); FD_SET(fake_sock, &fds_error); FD_SET(server_sock, &fds_error); alarm(30); res = select(max_fd + 1, &fds_read, &fds_write, &fds_error, NULL); alarm(0); if (res < 0) { if (sock_errno == TDSSOCK_EINTR) continue; perror("select"); exit(1); } if (FD_ISSET(fake_sock, &fds_error) || FD_ISSET(server_sock, &fds_error)) { fprintf(stderr, "error in select\n"); exit(1); } /* just read and forward */ if (FD_ISSET(fake_sock, &fds_read)) { if (flow != sending) { tds_mutex_lock(&mtx); ++round_trips; tds_mutex_unlock(&mtx); } flow = sending; len = READSOCKET(fake_sock, buf, sizeof(buf)); if (len == 0) break; if (len < 0 && sock_errno != TDSSOCK_EINPROGRESS) break; count_insert(buf, len); write_all(server_sock, buf, len); } if (FD_ISSET(server_sock, &fds_read)) { if (flow != receiving) { tds_mutex_lock(&mtx); ++round_trips; tds_mutex_unlock(&mtx); } flow = receiving; len = READSOCKET(server_sock, buf, sizeof(buf)); if (len == 0) break; if (len < 0 && sock_errno != TDSSOCK_EINPROGRESS) break; write_all(fake_sock, buf, len); } } CLOSESOCKET(fake_sock); CLOSESOCKET(server_sock); return NULL; } int main(int argc, char **argv) { SQLLEN sql_nts = SQL_NTS; const char *query; SQLINTEGER id = 0; char string[64]; TDS_SYS_SOCKET last_socket; int port; const int num_inserts = 20; int is_freetds; #ifdef _WIN32 WSADATA wsaData; WSAStartup(MAKEWORD(1, 1), &wsaData); #endif if (tds_mutex_init(&mtx)) return 1; odbc_connect(); /* * this does not work if server is not connected with socket * (ie ms driver connected locally) */ last_socket = odbc_find_last_socket(); if (TDS_IS_SOCKET_INVALID(last_socket)) { fprintf(stderr, "Error finding last socket opened\n"); return 1; } remote_addr_len = sizeof(remote_addr); if (tds_getpeername(last_socket, &remote_addr.sa, &remote_addr_len)) { fprintf(stderr, "Unable to get remote address\n"); return 1; } is_freetds = odbc_driver_is_freetds(); odbc_disconnect(); /* init fake server, behave like a proxy */ for (port = 12340; port < 12350; ++port) if (!init_fake_server(port)) break; if (port == 12350) { fprintf(stderr, "Cannot bind to a port\n"); return 1; } printf("Fake server bound at port %d\n", port); /* override connections */ if (is_freetds) { setenv("TDSHOST", "127.0.0.1", 1); sprintf(string, "%d", port); setenv("TDSPORT", string, 1); odbc_connect(); } else { char tmp[2048]; SQLSMALLINT len; CHKAllocEnv(&odbc_env, "S"); CHKAllocConnect(&odbc_conn, "S"); sprintf(tmp, "DRIVER={SQL Server};SERVER=127.0.0.1,%d;UID=%s;PWD=%s;DATABASE=%s;Network=DBMSSOCN;", port, odbc_user, odbc_password, odbc_database); printf("connection string: %s\n", tmp); CHKDriverConnect(NULL, T(tmp), SQL_NTS, (SQLTCHAR *) tmp, sizeof(tmp)/sizeof(SQLTCHAR), &len, SQL_DRIVER_NOPROMPT, "SI"); CHKAllocStmt(&odbc_stmt, "S"); } /* real test */ odbc_command("CREATE TABLE #test(i int, c varchar(40))"); odbc_reset_statement(); /* do not take into account connection statistics */ tds_mutex_lock(&mtx); round_trips = 0; inserts = 0; tds_mutex_unlock(&mtx); query = "insert into #test values (?, ?)"; CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, sizeof(id), 0, &id, 0, &sql_nts, "SI"); CHKBindParameter(2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, sizeof(string), 0, string, 0, &sql_nts, "SI"); CHKPrepare(T(query), SQL_NTS, "SI"); tds_mutex_lock(&mtx); printf("%u round trips %u inserts\n", round_trips, inserts); tds_mutex_unlock(&mtx); for (id = 0; id < num_inserts; id++) { sprintf(string, "This is a test (%d)", (int) id); CHKExecute("SI"); CHKFreeStmt(SQL_CLOSE, "S"); } tds_mutex_lock(&mtx); printf("%u round trips %u inserts\n", round_trips, inserts); tds_mutex_unlock(&mtx); odbc_reset_statement(); tds_mutex_lock(&mtx); if (inserts > 1 || round_trips > (unsigned) (num_inserts * 2 + 6)) { fprintf(stderr, "Too much round trips (%u) or insert (%u) !!!\n", round_trips, inserts); tds_mutex_unlock(&mtx); return 1; } printf("%u round trips %u inserts\n", round_trips, inserts); tds_mutex_unlock(&mtx); #ifdef ENABLE_DEVELOPING /* check for SQL_RESET_PARAMS */ tds_mutex_lock(&mtx); round_trips = 0; inserts = 0; tds_mutex_unlock(&mtx); CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, sizeof(id), 0, &id, 0, &sql_nts, "SI"); CHKBindParameter(2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, sizeof(string), 0, string, 0, &sql_nts, "SI"); CHKPrepare((SQLCHAR *) query, SQL_NTS, "SI"); tds_mutex_lock(&mtx); printf("%u round trips %u inserts\n", round_trips, inserts); tds_mutex_unlock(&mtx); for (id = 0; id < num_inserts; id++) { CHKBindParameter(1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, sizeof(id), 0, &id, 0, &sql_nts, "SI"); CHKBindParameter(2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, sizeof(string), 0, string, 0, &sql_nts, "SI"); sprintf(string, "This is a test (%d)", (int) id); CHKExecute("SI"); CHKFreeStmt(SQL_RESET_PARAMS, "S"); } tds_mutex_lock(&mtx); printf("%u round trips %u inserts\n", round_trips, inserts); tds_mutex_unlock(&mtx); odbc_reset_statement(); tds_mutex_lock(&mtx); if (inserts > 1 || round_trips > num_inserts * 2 + 6) { fprintf(stderr, "Too much round trips (%u) or insert (%u) !!!\n", round_trips, inserts); tds_mutex_unlock(&mtx); return 1; } printf("%u round trips %u inserts\n", round_trips, inserts); tds_mutex_unlock(&mtx); #endif odbc_disconnect(); alarm(10); tds_thread_join(fake_thread, NULL); return 0; } #else int main(void) { printf("Not possible for this platform.\n"); return 0; } #endif
-
[freetds] [0.95rc1] Some preliminary test results,
Sergio NNX, 05/07/2015
-
Re: [freetds] [0.95rc1] Some preliminary test results,
Frediano Ziglio, 05/08/2015
- Re: [freetds] [0.95rc1] Some preliminary test results, Sergio NNX, 05/08/2015
-
Re: [freetds] [0.95rc1] Some preliminary test results,
Frediano Ziglio, 05/09/2015
-
Re: [freetds] [0.95rc1] Some preliminary test results,
Sergio NNX, 05/09/2015
-
Re: [freetds] [0.95rc1] Some preliminary test results,
Frediano Ziglio, 05/11/2015
-
[freetds] [0.95rc2] Preliminary test results,
Sergio NNX, 05/11/2015
-
Re: [freetds] [0.95rc2] Preliminary test results,
Frediano Ziglio, 05/12/2015
-
Re: [freetds] [0.95rc2] Preliminary test results,
Sergio NNX, 05/12/2015
- Re: [freetds] [0.95rc2] Preliminary test results, Frediano Ziglio, 05/12/2015
- Re: [freetds] [0.95rc2] Preliminary test results, Frediano Ziglio, 05/12/2015
- [freetds] [0.95rc2][Windows] Deployment, Sergio NNX, 05/13/2015
- Re: [freetds] [0.95rc2][Windows] Deployment, Frediano Ziglio, 05/14/2015
- [freetds] [0.95rc2][Windows] Unit Tests, Sergio NNX, 05/14/2015
- Re: [freetds] [0.95rc2][Windows] Unit Tests, Frediano Ziglio, 05/14/2015
- Re: [freetds] [0.95rc2][Windows] Unit Tests, Sergio NNX, 05/14/2015
- Re: [freetds] [0.95rc2][Windows] Unit Tests, Frediano Ziglio, 05/14/2015
- [freetds] [0.95rc2][Windows] Unit Tests / Next release, Sergio NNX, 05/15/2015
-
Re: [freetds] [0.95rc2] Preliminary test results,
Sergio NNX, 05/12/2015
-
Re: [freetds] [0.95rc2] Preliminary test results,
Frediano Ziglio, 05/12/2015
-
[freetds] [0.95rc2] Preliminary test results,
Sergio NNX, 05/11/2015
-
Re: [freetds] [0.95rc1] Some preliminary test results,
Frediano Ziglio, 05/11/2015
-
Re: [freetds] [0.95rc1] Some preliminary test results,
Sergio NNX, 05/09/2015
- [freetds] [0.95rc2] Unit Tests / Unicode, Sergio NNX, 05/15/2015
- Re: [freetds] [0.95rc2] Unit Tests / Unicode, Frediano Ziglio, 05/15/2015
- Re: [freetds] [0.95rc2] Unit Tests / Unicode, Frediano Ziglio, 05/16/2015
-
Re: [freetds] [0.95rc1] Some preliminary test results,
Frediano Ziglio, 05/08/2015
Archive powered by MHonArc 2.6.24.