From 6c2d7f91f421e926f2588fcd24857b58265b5133 Mon Sep 17 00:00:00 2001 From: Chris Lalancette <clalance@redhat.com> Date: Tue, 7 Sep 2010 16:13:34 -0400 Subject: [PATCH] Implement trace. This is a backport of the upstream ruby-pg changesets 56, 57, and 59. Signed-off-by: Chris Lalancette <clalance@redhat.com> --- ext/postgres.c | 64 +++++++++++++++++++++++++++++++++++++++---------------- 1 files changed, 45 insertions(+), 19 deletions(-) diff --git a/ext/postgres.c b/ext/postgres.c index c6c2bb7..e9bb032 100644 --- a/ext/postgres.c +++ b/ext/postgres.c @@ -33,6 +33,7 @@ #include <libpq/libpq-fs.h> /* large-object interface */ #include <stdio.h> #include <stdlib.h> +#include <unistd.h> #include <sys/types.h> #ifndef HAVE_PQSERVERVERSION @@ -1212,26 +1213,48 @@ pgconn_error(obj) return rb_tainted_str_new2(error); } -/*TODO broken for ruby 1.9 +/* * call-seq: - * conn.trace( port ) + * conn.trace( stream ) * - * Enables tracing message passing between backend. - * The trace message will be written to the _port_ object, - * which is an instance of the class +File+. + * Enables tracing message passing between backend. The + * trace message will be written to the stream _stream_, + * which must implement a method +fileno+ that returns + * a writable file descriptor. */ static VALUE -pgconn_trace(obj, port) - VALUE obj, port; +pgconn_trace(VALUE self, VALUE stream) { - //OpenFile* fp; + VALUE fileno; + FILE *new_fp; + int old_fd, new_fd; + VALUE new_file; - Check_Type(port, T_FILE); - //GetOpenFile(port, fp); + if(rb_respond_to(stream,rb_intern("fileno")) == Qfalse) + rb_raise(rb_eArgError, "stream does not respond to method: fileno"); - //PQtrace(get_pgconn(obj), fp->f2?fp->f2:fp->f); + fileno = rb_funcall(stream, rb_intern("fileno"), 0); + if(fileno == Qnil) + rb_raise(rb_eArgError, "can't get file descriptor from stream"); - return obj; + /* Duplicate the file descriptor and re-open + * it. Then, make it into a ruby File object + * and assign it to an instance variable. + * This prevents a problem when the File + * object passed to this function is closed + * before the connection object is. */ + old_fd = NUM2INT(fileno); + new_fd = dup(old_fd); + new_fp = fdopen(new_fd, "w"); + + if(new_fp == NULL) + rb_raise(rb_eArgError, "stream is not writable"); + + new_file = rb_funcall(rb_cIO, rb_intern("new"), 1, INT2NUM(new_fd)); + rb_iv_set(self, "@trace_file", new_file); + + PQtrace(get_pgconn(self), new_fp); + return self; } /* @@ -1241,11 +1264,14 @@ pgconn_trace(obj, port) * Disables the message tracing. */ static VALUE -pgconn_untrace(obj) - VALUE obj; +pgconn_untrace(VALUE self) { - PQuntrace(get_pgconn(obj)); - return obj; + VALUE trace_stream; + PQuntrace(get_pgconn(self)); + trace_stream = rb_iv_get(self, "@trace_stream"); + rb_funcall(trace_stream, rb_intern("close"), 0); + rb_iv_set(self, "@trace_stream", Qnil); + return self; } /* -- 1.7.2.2