[ruby-oci8-commit] [394] trunk/ruby-oci8: * dist-files, ext/oci8/.document, ext/oci8/apiwrap. yml,

nobody at rubyforge.org nobody at rubyforge.org
Fri May 7 10:20:35 EDT 2010


Revision: 394
Author:   kubo
Date:     2010-05-07 10:20:35 -0400 (Fri, 07 May 2010)

Log Message:
-----------
* dist-files, ext/oci8/.document, ext/oci8/apiwrap.yml,
  ext/oci8/connection_pool.c, ext/oci8/extconf.rb,ext/oci8/oci8.c,
  ext/oci8/oci8.h, ext/oci8/oci8lib.c, lib/oci8.rb.in,
  lib/oci8/.document, lib/oci8/connection_pool.rb, lib/oci8/oci8.rb,
  lib/oci8/ocihandle.rb: add a new feature OCI8::ConnectionPool.

Modified Paths:
--------------
    trunk/ruby-oci8/ChangeLog
    trunk/ruby-oci8/dist-files
    trunk/ruby-oci8/ext/oci8/.document
    trunk/ruby-oci8/ext/oci8/apiwrap.yml
    trunk/ruby-oci8/ext/oci8/extconf.rb
    trunk/ruby-oci8/ext/oci8/oci8.c
    trunk/ruby-oci8/ext/oci8/oci8.h
    trunk/ruby-oci8/ext/oci8/oci8lib.c
    trunk/ruby-oci8/lib/oci8/.document
    trunk/ruby-oci8/lib/oci8/oci8.rb
    trunk/ruby-oci8/lib/oci8/ocihandle.rb
    trunk/ruby-oci8/lib/oci8.rb.in

Added Paths:
-----------
    trunk/ruby-oci8/ext/oci8/connection_pool.c
    trunk/ruby-oci8/lib/oci8/connection_pool.rb

Modified: trunk/ruby-oci8/ChangeLog
===================================================================
--- trunk/ruby-oci8/ChangeLog	2010-05-04 12:59:37 UTC (rev 393)
+++ trunk/ruby-oci8/ChangeLog	2010-05-07 14:20:35 UTC (rev 394)
@@ -1,3 +1,10 @@
+2010-05-07  KUBO Takehiro  <kubo at jiubao.org>
+	* dist-files, ext/oci8/.document, ext/oci8/apiwrap.yml,
+	  ext/oci8/connection_pool.c, ext/oci8/extconf.rb,ext/oci8/oci8.c,
+	  ext/oci8/oci8.h, ext/oci8/oci8lib.c, lib/oci8.rb.in,
+	  lib/oci8/.document, lib/oci8/connection_pool.rb, lib/oci8/oci8.rb,
+	  lib/oci8/ocihandle.rb: add a new feature OCI8::ConnectionPool.
+
 2010-05-04  KUBO Takehiro  <kubo at jiubao.org>
 	* ext/oci8/bind.c: fix a bug that a string is bound to RAW,
 	    its encoding was convertd to OCI.encoding.

Modified: trunk/ruby-oci8/dist-files
===================================================================
--- trunk/ruby-oci8/dist-files	2010-05-04 12:59:37 UTC (rev 393)
+++ trunk/ruby-oci8/dist-files	2010-05-07 14:20:35 UTC (rev 394)
@@ -21,6 +21,7 @@
 ext/oci8/apiwrap.yml
 ext/oci8/attr.c
 ext/oci8/bind.c
+ext/oci8/connection_pool.c
 ext/oci8/encoding.c
 ext/oci8/env.c
 ext/oci8/error.c
@@ -48,12 +49,14 @@
 lib/oci8/.document
 lib/oci8/bindtype.rb
 lib/oci8/compat.rb
+lib/oci8/connection_pool.rb
 lib/oci8/datetime.rb
 lib/oci8/encoding-init.rb
 lib/oci8/encoding.yml
 lib/oci8/metadata.rb
 lib/oci8/object.rb
 lib/oci8/oci8.rb
+lib/oci8/ocihandle.rb
 lib/oci8/oracle_version.rb
 test/README
 test/config.rb

Modified: trunk/ruby-oci8/ext/oci8/.document
===================================================================
--- trunk/ruby-oci8/ext/oci8/.document	2010-05-04 12:59:37 UTC (rev 393)
+++ trunk/ruby-oci8/ext/oci8/.document	2010-05-07 14:20:35 UTC (rev 394)
@@ -15,3 +15,4 @@
 ocidatetime.c
 oradate.c
 object.c
+connection_pool.c

Modified: trunk/ruby-oci8/ext/oci8/apiwrap.yml
===================================================================
--- trunk/ruby-oci8/ext/oci8/apiwrap.yml	2010-05-04 12:59:37 UTC (rev 393)
+++ trunk/ruby-oci8/ext/oci8/apiwrap.yml	2010-05-07 14:20:35 UTC (rev 394)
@@ -1056,6 +1056,30 @@
 # Oracle 9.0
 #
 
+OCIConnectionPoolCreate:
+  :version: 900
+  :args:    - OCIEnv *envhp
+            - OCIError *errhp
+            - OCICPool *poolhp
+            - OraText **poolName
+            - sb4 *poolNameLen
+            - const OraText *dblink
+            - sb4 dblinkLen
+            - ub4 connMin
+            - ub4 connMax
+            - ub4 connIncr
+            - const OraText *poolUserName
+            - sb4 poolUserLen
+            - const OraText *poolPassword
+            - sb4 poolPassLen
+            - ub4 mode
+
+OCIConnectionPoolDestroy:
+  :version: 900
+  :args:    - OCICPool *poolhp
+            - OCIError *errhp
+            - ub4 mode
+
 # round trip: 0 (not docmented. I guess.)
 OCIDateTimeConstruct:
   :version: 900

Added: trunk/ruby-oci8/ext/oci8/connection_pool.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/connection_pool.c	                        (rev 0)
+++ trunk/ruby-oci8/ext/oci8/connection_pool.c	2010-05-07 14:20:35 UTC (rev 394)
@@ -0,0 +1,188 @@
+/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
+/*
+ * connection_pool.c - part of ruby-oci8
+ *
+ * Copyright (C) 2010 KUBO Takehiro <kubo at jiubao.org>
+ *
+ */
+#include "oci8.h"
+
+static VALUE cOCIConnectionPool;
+
+typedef struct {
+    oci8_base_t base;
+    VALUE pool_name;
+} oci8_cpool_t;
+
+static void oci8_cpool_mark(oci8_base_t *base)
+{
+    oci8_cpool_t *cpool = (oci8_cpool_t *)base;
+
+    rb_gc_mark(cpool->pool_name);
+}
+
+static void oci8_cpool_free(oci8_base_t *base)
+{
+    OCIConnectionPoolDestroy(base->hp.poolhp, oci8_errhp, OCI_DEFAULT);
+}
+
+static void oci8_cpool_init(oci8_base_t *base)
+{
+    oci8_cpool_t *cpool = (oci8_cpool_t *)base;
+
+    cpool->pool_name = Qnil;
+}
+
+static oci8_base_class_t oci8_cpool_class = {
+    oci8_cpool_mark,
+    oci8_cpool_free,
+    sizeof(oci8_base_t),
+    oci8_cpool_init,
+};
+
+/*
+ * call-seq:
+ *   OCI8::ConnectionPool.new(conn_min, conn_max, conn_incr, username = nil, password = nil, dbname = nil) -> connection pool
+ *   OCI8::ConnectionPool.new(conn_min, conn_max, conn_incr, connect_string) -> connection pool
+ *
+ * Creates a connection pool.
+ *
+ * <i>conn_min</i> specifies the minimum number of connections in the
+ * connection pool. Valid values are 0 and higher.
+ *
+ * <i>conn_max</i> specifies the maximum number of connections that
+ * can be opened to the database. Once this value is reached, no more
+ * connections are opened. Valid values are 1 and higher.
+ *
+ * <i>conn_incr</i> allows the application to set the next increment
+ * for connections to be opened to the database if the current number
+ * of connections are less than <i>conn_max</i>. Valid values are 0
+ * and higher.
+ *
+ * <i>username</i> and <i>password</i> are required to establish an
+ * implicit primary session. When both are nil, external
+ * authentication is used.
+ *
+ * <i>dbname</i> specifies the database server to connect to.
+ *
+ * If the number of arguments is four, <i>username</i>,
+ * <i>password</i> and <i>dbname</i> are extracted from the fourth
+ * argument <i>connect_string</i>. The syntax is "username/password" or
+ * "username/password at dbname".
+ */
+static VALUE oci8_cpool_initialize(int argc, VALUE *argv, VALUE self)
+{
+    VALUE conn_min;
+    VALUE conn_max;
+    VALUE conn_incr;
+    VALUE username;
+    VALUE password;
+    VALUE dbname;
+    oci8_cpool_t *cpool = DATA_PTR(self);
+    OraText *pool_name;
+    sb4 pool_name_len;
+    sword rv;
+
+    /* check arguments */
+    rb_scan_args(argc, argv, "42", &conn_min, &conn_max, &conn_incr,
+                 &username, &password, &dbname);
+    Check_Type(conn_min, T_FIXNUM);
+    Check_Type(conn_max, T_FIXNUM);
+    Check_Type(conn_incr, T_FIXNUM);
+    if (argc == 4) {
+        VALUE mode;
+        VALUE conn_str = username;
+
+        OCI8SafeStringValue(conn_str);
+        oci8_do_parse_connect_string(conn_str, &username, &password, &dbname, &mode);
+        if (!NIL_P(mode)) {
+            rb_raise(rb_eArgError, "invalid connect string \"%s\": Connection pooling doesn't support sysdba and sysoper privileges.", RSTRING_PTR(conn_str));
+        }
+    } else {
+        if (!NIL_P(username)) {
+            OCI8SafeStringValue(username);
+        }
+        if (!NIL_P(password)) {
+            OCI8SafeStringValue(password);
+        }
+        if (!NIL_P(dbname)) {
+            OCI8SafeStringValue(dbname);
+        }
+    }
+
+    rv = OCIHandleAlloc(oci8_envhp, &cpool->base.hp.ptr, OCI_HTYPE_CPOOL, 0, NULL);
+    if (rv != OCI_SUCCESS)
+        oci8_env_raise(oci8_envhp, rv);
+    cpool->base.type = OCI_HTYPE_CPOOL;
+
+    oci_lc(OCIConnectionPoolCreate(oci8_envhp, oci8_errhp, cpool->base.hp.poolhp,
+                                   &pool_name, &pool_name_len,
+                                   NIL_P(dbname) ? NULL : RSTRING_ORATEXT(dbname),
+                                   NIL_P(dbname) ? 0 : RSTRING_LEN(dbname),
+                                   FIX2UINT(conn_min), FIX2UINT(conn_max),
+                                   FIX2UINT(conn_incr),
+                                   NIL_P(username) ? NULL : RSTRING_ORATEXT(username),
+                                   NIL_P(username) ? 0 : RSTRING_LEN(username),
+                                   NIL_P(password) ? NULL : RSTRING_ORATEXT(password),
+                                   NIL_P(password) ? 0 : RSTRING_LEN(password),
+                                   OCI_DEFAULT));
+    cpool->pool_name = rb_str_new(TO_CHARPTR(pool_name), pool_name_len);
+    rb_str_freeze(cpool->pool_name);
+    return Qnil;
+}
+
+/*
+ * call-seq:
+ *   reinitialize(min, max, incr)
+ *
+ * Changes the the number of minimum connections, the number of
+ * maximum connections and the connection increment parameter.
+ */
+static VALUE oci8_cpool_reinitialize(VALUE self, VALUE conn_min, VALUE conn_max, VALUE conn_incr)
+{
+    oci8_cpool_t *cpool = DATA_PTR(self);
+    OraText *pool_name;
+    sb4 pool_name_len;
+
+    /* check arguments */
+    Check_Type(conn_min, T_FIXNUM);
+    Check_Type(conn_max, T_FIXNUM);
+    Check_Type(conn_incr, T_FIXNUM);
+
+    oci_lc(OCIConnectionPoolCreate(oci8_envhp, oci8_errhp, cpool->base.hp.poolhp,
+                                   &pool_name, &pool_name_len, NULL, 0, 
+                                   FIX2UINT(conn_min), FIX2UINT(conn_max),
+                                   FIX2UINT(conn_incr),
+                                   NULL, 0, NULL, 0, OCI_CPOOL_REINITIALIZE));
+    return self;
+}
+
+/*
+ * call-seq:
+ *   pool_name -> string
+ *
+ * <b>internal use only</b>
+ *
+ * Retruns the pool name.
+ */
+static VALUE oci8_cpool_pool_name(VALUE self)
+{
+    oci8_cpool_t *cpool = DATA_PTR(self);
+
+    return cpool->pool_name;
+}
+
+void Init_oci8_connection_pool(VALUE cOCI8)
+{
+#if 0
+    cOCIHandle = rb_define_class("OCIHandle", rb_cObject);
+    cOCI8 = rb_define_class("OCI8", cOCIHandle);
+    cOCIConnectionPool = rb_define_class_under(cOCI8, "ConnectionPool", cOCIHandle);
+#endif
+
+    cOCIConnectionPool = oci8_define_class_under(cOCI8, "ConnectionPool", &oci8_cpool_class);
+
+    rb_define_private_method(cOCIConnectionPool, "initialize", oci8_cpool_initialize, -1);
+    rb_define_method(cOCIConnectionPool, "reinitialize", oci8_cpool_reinitialize, 3);
+    rb_define_private_method(cOCIConnectionPool, "pool_name", oci8_cpool_pool_name, 0);
+}

Modified: trunk/ruby-oci8/ext/oci8/extconf.rb
===================================================================
--- trunk/ruby-oci8/ext/oci8/extconf.rb	2010-05-04 12:59:37 UTC (rev 393)
+++ trunk/ruby-oci8/ext/oci8/extconf.rb	2010-05-07 14:20:35 UTC (rev 394)
@@ -70,6 +70,7 @@
 have_type('OCICallbackLobWrite2', 'ociap.h')
 have_type('OCIAdmin*', 'ociap.h')
 have_type('OCIMsg*', 'ociap.h')
+have_type('OCICPool*', 'ociap.h')
 
 if with_config('oracle-version')
   oci_client_version = OCI8::OracleVersion.new(with_config('oracle-version')).to_i
@@ -84,6 +85,7 @@
 end
 
 $objs = ["oci8lib.o", "env.o", "error.o", "oci8.o", "ocihandle.o",
+         "connection_pool.o",
          "stmt.o", "bind.o", "metadata.o", "attr.o",
          "lob.o", "oradate.o",
          "ocinumber.o", "ocidatetime.o", "object.o", "apiwrap.o",

Modified: trunk/ruby-oci8/ext/oci8/oci8.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/oci8.c	2010-05-04 12:59:37 UTC (rev 393)
+++ trunk/ruby-oci8/ext/oci8/oci8.c	2010-05-07 14:20:35 UTC (rev 394)
@@ -117,7 +117,7 @@
 }
 
 #define CONN_STR_REGEX "/^([^(\\s|\\@)]*)\\/([^(\\s|\\@)]*)(?:\\@(\\S+))?(?:\\s+as\\s+(\\S*)\\s*)?$/i"
-static void oci8_do_parse_connect_string(VALUE conn_str, VALUE *user, VALUE *pass, VALUE *dbname, VALUE *mode)
+void oci8_do_parse_connect_string(VALUE conn_str, VALUE *user, VALUE *pass, VALUE *dbname, VALUE *mode)
 {
     static VALUE re = Qnil;
     if (NIL_P(re)) {

Modified: trunk/ruby-oci8/ext/oci8/oci8.h
===================================================================
--- trunk/ruby-oci8/ext/oci8/oci8.h	2010-05-04 12:59:37 UTC (rev 393)
+++ trunk/ruby-oci8/ext/oci8/oci8.h	2010-05-07 14:20:35 UTC (rev 394)
@@ -96,6 +96,9 @@
 #ifndef HAVE_TYPE_OCIMSG_
 typedef struct OCIMsg  OCIMsg;
 #endif
+#ifndef HAVE_TYPE_OCICPOOL_
+typedef struct OCICPool OCICPool;
+#endif
 
 /* new macros in ruby 1.8.6.
  * define compatible macros for ruby 1.8.5 or lower.
@@ -270,6 +273,7 @@
     union {
         dvoid *ptr;
         OCISvcCtx *svc;
+        OCICPool *poolhp;
         OCIServer *srvhp;
         OCISession *authhp;
         OCIStmt *stmt;
@@ -429,6 +433,7 @@
 
 /* oci8.c */
 VALUE Init_oci8(void);
+void oci8_do_parse_connect_string(VALUE conn_str, VALUE *user, VALUE *pass, VALUE *dbname, VALUE *mode);
 oci8_svcctx_t *oci8_get_svcctx(VALUE obj);
 OCISvcCtx *oci8_get_oci_svcctx(VALUE obj);
 OCISession *oci8_get_oci_session(VALUE obj);
@@ -436,6 +441,9 @@
 #define TO_SVCCTX oci8_get_oci_svcctx
 #define TO_SESSION oci8_get_oci_session
 
+/* connection_pool.c */
+void Init_oci8_connection_pool(VALUE cOCI8);
+
 /* stmt.c */
 extern VALUE cOCIStmt;
 void Init_oci8_stmt(VALUE cOCI8);

Modified: trunk/ruby-oci8/ext/oci8/oci8lib.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/oci8lib.c	2010-05-04 12:59:37 UTC (rev 393)
+++ trunk/ruby-oci8/ext/oci8/oci8lib.c	2010-05-07 14:20:35 UTC (rev 394)
@@ -75,6 +75,10 @@
 
     /* OCI8 class */
     cOCI8 = Init_oci8();
+
+    /* OCI8::ConnectionPool class */
+    Init_oci8_connection_pool(cOCI8);
+
     /* OCI8::BindType module */
     mOCI8BindType = rb_define_module_under(cOCI8, "BindType");
     /* OCI8::BindType::Base class */

Modified: trunk/ruby-oci8/lib/oci8/.document
===================================================================
--- trunk/ruby-oci8/lib/oci8/.document	2010-05-04 12:59:37 UTC (rev 393)
+++ trunk/ruby-oci8/lib/oci8/.document	2010-05-07 14:20:35 UTC (rev 394)
@@ -3,3 +3,5 @@
 metadata.rb
 oracle_version.rb
 oci8.rb
+ocihandle.rb
+connection_pool.rb

Added: trunk/ruby-oci8/lib/oci8/connection_pool.rb
===================================================================
--- trunk/ruby-oci8/lib/oci8/connection_pool.rb	                        (rev 0)
+++ trunk/ruby-oci8/lib/oci8/connection_pool.rb	2010-05-07 14:20:35 UTC (rev 394)
@@ -0,0 +1,99 @@
+#--
+# connection_pool.rb -- OCI8::ConnectionPool
+#
+# Copyright (C) 2010 KUBO Takehiro <kubo at jiubao.org>
+#++
+
+class OCI8
+  class ConnectionPool
+
+    # call-seq:
+    #   timeout -> integer
+    #
+    # Connections idle for more than this time value (in seconds) are
+    # terminated, to maintain an optimum number of open
+    # connections. If it is zero, the connections are never timed out.
+    # The default value is zero.
+    #
+    # <b>Note:</b> Shrinkage of the pool only occurs when there is a network
+    # round trip. If there are no operations, then the connections
+    # stay alive.
+    def timeout
+      attr_get_ub4(OCI_ATTR_CONN_TIMEOUT)
+    end
+
+    # call-seq:
+    #   timeout = integer
+    #
+    # Changes the timeout in seconds to terminate idle connections.
+    def timeout=(val)
+      attr_set_ub4(OCI_ATTR_CONN_TIMEOUT, val)
+    end
+
+    # call-seq:
+    #   nowait? -> true or false
+    #
+    # If true, an error is thrown when all the connections in the pool
+    # are busy and the number of connections has already reached the
+    # maximum. Otherwise the call waits till it gets a connection.
+    # The default value is false.
+    def nowait?
+      attr_get_ub1(OCI_ATTR_CONN_NOWAIT) != 0
+    end
+
+    # call-seq:
+    #   nowait = true or false
+    #
+    # Changes the behavior when all the connections in the pool
+    # are busy and the number of connections has already reached the
+    # maximum.
+    def nowait=(val)
+      attr_set_ub1(OCI_ATTR_CONN_NOWAIT, val ? 1 : 0)
+    end
+
+    # call-seq:
+    #   busy_count -> integer
+    #
+    # Returns the number of busy connections.
+    def busy_count
+      attr_get_ub4(OCI_ATTR_CONN_BUSY_COUNT)
+    end
+
+    # call-seq:
+    #   open_count -> integer
+    #
+    # Returns the number of open connections.
+    def open_count
+      attr_get_ub4(OCI_ATTR_CONN_OPEN_COUNT)
+    end
+
+    # call-seq:
+    #   min -> integer
+    #
+    # Returns the number of minimum connections.
+    def min
+      attr_get_ub4(OCI_ATTR_CONN_MIN)
+    end
+
+    # call-seq:
+    #   max -> integer
+    #
+    # Returns the number of maximum connections.
+    def max
+      attr_get_ub4(OCI_ATTR_CONN_MAX)
+    end
+
+    # call-seq:
+    #   incr -> integer
+    #
+    # Returns the connection increment parameter.
+    def incr
+      attr_get_ub4(OCI_ATTR_CONN_INCR)
+    end
+
+    # 
+    def destroy
+      free
+    end
+  end
+end

Modified: trunk/ruby-oci8/lib/oci8/oci8.rb
===================================================================
--- trunk/ruby-oci8/lib/oci8/oci8.rb	2010-05-04 12:59:37 UTC (rev 393)
+++ trunk/ruby-oci8/lib/oci8/oci8.rb	2010-05-07 14:20:35 UTC (rev 394)
@@ -112,15 +112,23 @@
       raise "unknown privilege type #{mode}"
     end
 
-    if mode.nil? and cred.nil?
+    if mode.nil? and cred.nil? and (not dbname.is_a? OCI8::ConnectionPool)
       # logon by the OCI function OCILogon().
       logon(username, password, dbname)
     else
       # logon by the OCI function OCISessionBegin().
+      if dbname.is_a? OCI8::ConnectionPool
+        @pool = dbname # to prevent GC from freeing the connection pool.
+        attach_mode = OCI_CPOOL
+        dbname = dbname.send(:pool_name)
+      else
+        attach_mode = OCI_DEFAULT
+      end
+
       allocate_handles()
       session_handle.send(:attr_set_string, OCI_ATTR_USERNAME, username) if username
       session_handle.send(:attr_set_string, OCI_ATTR_PASSWORD, password) if password
-      server_attach(dbname, OCI_DEFAULT);
+      server_attach(dbname, attach_mode)
       session_begin(cred ? cred : OCI_CRED_RDBMS, mode ? mode : OCI_DEFAULT)
     end
 

Modified: trunk/ruby-oci8/lib/oci8/ocihandle.rb
===================================================================
--- trunk/ruby-oci8/lib/oci8/ocihandle.rb	2010-05-04 12:59:37 UTC (rev 393)
+++ trunk/ruby-oci8/lib/oci8/ocihandle.rb	2010-05-07 14:20:35 UTC (rev 394)
@@ -303,6 +303,15 @@
 
   #################################
   #
+  # Attach Modes
+  #
+  #################################
+
+  # Attach using server handle from pool
+  OCI_CPOOL                   = 0x0200
+
+  #################################
+  #
   # OCI Parameter Types
   #
   #################################

Modified: trunk/ruby-oci8/lib/oci8.rb.in
===================================================================
--- trunk/ruby-oci8/lib/oci8.rb.in	2010-05-04 12:59:37 UTC (rev 393)
+++ trunk/ruby-oci8/lib/oci8.rb.in	2010-05-07 14:20:35 UTC (rev 394)
@@ -69,6 +69,7 @@
 require 'oci8/metadata.rb'
 require 'oci8/compat.rb'
 require 'oci8/object.rb'
+require 'oci8/connection_pool.rb'
 
 class OCI8
   VERSION = '@@OCI8_MODULE_VERSION@@'




More information about the ruby-oci8-commit mailing list