<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[15190] CalendarServer/trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.calendarserver.org//changeset/15190">15190</a></dd>
<dt>Author</dt> <dd>cdaboo@apple.com</dd>
<dt>Date</dt> <dd>2015-10-14 11:28:42 -0700 (Wed, 14 Oct 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Make sure we patch cx_Oracle before building it.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#CalendarServertrunkbin_buildsh">CalendarServer/trunk/bin/_build.sh</a></li>
<li><a href="#CalendarServertrunkbinpackage">CalendarServer/trunk/bin/package</a></li>
<li><a href="#CalendarServertrunkrequirementsstabletxt">CalendarServer/trunk/requirements-stable.txt</a></li>
<li><a href="#CalendarServertrunksetuppy">CalendarServer/trunk/setup.py</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li>CalendarServer/trunk/lib-patches/</li>
<li>CalendarServer/trunk/lib-patches/cx_Oracle/</li>
<li><a href="#CalendarServertrunklibpatchescx_Oraclenclobfixesandprefetchpatch">CalendarServer/trunk/lib-patches/cx_Oracle/nclob-fixes-and-prefetch.patch</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServertrunkbin_buildsh"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/bin/_build.sh (15189 => 15190)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/bin/_build.sh        2015-10-14 17:41:35 UTC (rev 15189)
+++ CalendarServer/trunk/bin/_build.sh        2015-10-14 18:28:42 UTC (rev 15190)
</span><span class="lines">@@ -93,6 +93,7 @@
</span><span class="cx">   conditional_set do_setup &quot;true&quot;;
</span><span class="cx">   conditional_set force_setup &quot;false&quot;;
</span><span class="cx">   conditional_set requirements &quot;${wd}/requirements-dev.txt&quot;
</span><ins>+  conditional_set virtualenv_opts &quot;&quot;;
</ins><span class="cx"> 
</span><span class="cx">       dev_home=&quot;${wd}/.develop&quot;;
</span><span class="cx">      dev_roots=&quot;${dev_home}/roots&quot;;
</span><span class="lines">@@ -113,6 +114,9 @@
</span><span class="cx"> 
</span><span class="cx">   project=&quot;$(setup_print name)&quot; || project=&quot;&lt;unknown&gt;&quot;;
</span><span class="cx"> 
</span><ins>+  dev_patches=&quot;${dev_home}/patches&quot;;
+  patches=&quot;${wd}/lib-patches&quot;;
+
</ins><span class="cx">   # Find some hashing commands
</span><span class="cx">   # sha1() = sha1 hash, if available
</span><span class="cx">   # md5()  = md5 hash, if available
</span><span class="lines">@@ -169,6 +173,34 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+# Apply patches from lib-patches to the given dependency codebase.
+apply_patches () {
+  local name=&quot;$1&quot;; shift;
+  local path=&quot;$1&quot;; shift;
+
+  if [ -d &quot;${patches}/${name}&quot; ]; then
+    echo &quot;&quot;;
+    echo &quot;Applying patches to ${name} in ${path}...&quot;;
+
+    cd &quot;${path}&quot;;
+    find &quot;${patches}/${name}&quot;                  \
+        -type f                                \
+        -name '*.patch'                        \
+        -print                                 \
+        -exec patch -p0 --forward -i '{}' ';';
+    cd /;
+
+  fi;
+
+  echo &quot;&quot;;
+  if [ -e &quot;${path}/setup.py&quot; ]; then
+    echo &quot;Removing build directory ${path}/build...&quot;;
+    rm -rf &quot;${path}/build&quot;;
+    echo &quot;Removing pyc files from ${path}...&quot;;
+    find &quot;${path}&quot; -type f -name '*.pyc' -print0 | xargs -0 rm -f;
+  fi;
+}
+
</ins><span class="cx"> # If do_get is turned on, get an archive file containing a dependency via HTTP.
</span><span class="cx"> www_get () {
</span><span class="cx">   if ! &quot;${do_get}&quot;; then return 0; fi;
</span><span class="lines">@@ -315,6 +347,7 @@
</span><span class="cx">     rm -rf &quot;${path}&quot;;
</span><span class="cx">     cd &quot;$(dirname &quot;${path}&quot;)&quot;;
</span><span class="cx">     get | ${decompress} | ${unpack};
</span><ins>+    apply_patches &quot;${name}&quot; &quot;${path}&quot;;
</ins><span class="cx">     cd &quot;${wd}&quot;;
</span><span class="cx">   fi;
</span><span class="cx"> }
</span><span class="lines">@@ -566,7 +599,27 @@
</span><span class="cx"> 
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#
+# Special cx_Oracle patch handling
+#
+cx_Oracle_patch() {
</ins><span class="cx"> 
</span><ins>+  local f_hash=&quot;-m 6a49e1aa0e5b48589f8edfe5884ff5a5&quot;;
+  local v=&quot;5.2&quot;;
+  local n=&quot;cx_Oracle&quot;;
+  local p=&quot;${n}-${v}&quot;;
+
+  mkdir -p &quot;${dev_patches}&quot;;
+
+  local srcdir=&quot;${dev_patches}/${p}&quot;;
+
+  www_get ${f_hash} &quot;${n}&quot; &quot;${srcdir}&quot; &quot;https://pypi.python.org/packages/source/c/${n}/${p}.tar.gz&quot;;
+  cd &quot;${dev_patches}&quot;;
+  tar zcf &quot;${p}.tar.gz&quot; &quot;${p}&quot;;
+  cd &quot;${wd}&quot;;
+  rm -rf &quot;${srcdir}&quot;;
+}
+
</ins><span class="cx"> #
</span><span class="cx"> # Build Python dependencies
</span><span class="cx"> #
</span><span class="lines">@@ -603,6 +656,7 @@
</span><span class="cx">     &quot;${bootstrap_python}&quot; -m virtualenv  \
</span><span class="cx">       --system-site-packages             \
</span><span class="cx">       --no-setuptools                    \
</span><ins>+      ${virtualenv_opts}                 \
</ins><span class="cx">       &quot;${py_virtualenv}&quot;;
</span><span class="cx">   fi;
</span><span class="cx"> 
</span><span class="lines">@@ -622,12 +676,17 @@
</span><span class="cx">   echo &quot;&quot;;
</span><span class="cx">   &quot;${pip_install}&quot; --requirement=&quot;${requirements}&quot;;
</span><span class="cx"> 
</span><del>-  for option in $(&quot;${bootstrap_python}&quot; -c 'import setup; print &quot;\n&quot;.join(setup.extras_requirements.keys())'); do
-    ruler &quot;Preparing Python requirements for optional feature: ${option}&quot;;
</del><ins>+  for extra in $(&quot;${bootstrap_python}&quot; -c 'import setup; print &quot;\n&quot;.join(setup.extras_requirements.keys())'); do
+    ruler &quot;Preparing Python requirements for optional feature: ${extra}&quot;;
</ins><span class="cx">     echo &quot;&quot;;
</span><del>-    if ! &quot;${pip_install}&quot; --editable=&quot;${wd}[${option}]&quot;; then
-      echo &quot;Feature ${option} is optional; continuing.&quot;;
</del><ins>+
+    if [ &quot;${extra}&quot; = &quot;Oracle&quot; ]; then
+      cx_Oracle_patch;
</ins><span class="cx">     fi;
</span><ins>+
+    if ! &quot;${pip_install}&quot; --editable=&quot;${wd}[${extra}]&quot;; then
+      echo &quot;Feature ${extra} is optional; continuing.&quot;;
+    fi;
</ins><span class="cx">   done;
</span><span class="cx"> 
</span><span class="cx">   echo &quot;&quot;;
</span><span class="lines">@@ -690,6 +749,7 @@
</span><span class="cx">     --pre --allow-all-external               \
</span><span class="cx">     --no-index                               \
</span><span class="cx">     --no-cache-dir                           \
</span><ins>+    --find-links=&quot;${dev_patches}&quot;            \
</ins><span class="cx">     --find-links=&quot;${dev_home}/pip_downloads&quot; \
</span><span class="cx">     --log-file=&quot;${dev_home}/pip.log&quot;         \
</span><span class="cx">     &quot;$@&quot;;
</span><span class="lines">@@ -701,6 +761,7 @@
</span><span class="cx">     --disable-pip-version-check              \
</span><span class="cx">     --pre --allow-all-external               \
</span><span class="cx">     --no-cache-dir                           \
</span><ins>+    --find-links=&quot;${dev_patches}&quot;            \
</ins><span class="cx">     --log-file=&quot;${dev_home}/pip.log&quot;         \
</span><span class="cx">     &quot;$@&quot;;
</span><span class="cx"> }
</span></span></pre></div>
<a id="CalendarServertrunkbinpackage"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/bin/package (15189 => 15190)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/bin/package        2015-10-14 17:41:35 UTC (rev 15189)
+++ CalendarServer/trunk/bin/package        2015-10-14 18:28:42 UTC (rev 15190)
</span><span class="lines">@@ -110,16 +110,9 @@
</span><span class="cx">   py_virtualenv=&quot;${destination}/virtualenv&quot;;
</span><span class="cx">       py_bindir=&quot;${py_virtualenv}/bin&quot;;
</span><span class="cx">     py_ve_tools=&quot;${dev_home}/ve_tools&quot;;
</span><ins>+  virtualenv_opts=&quot;--always-copy&quot;;
+    
</ins><span class="cx"> 
</span><del>-  if [ ! -d &quot;${py_virtualenv}&quot; ]; then
-    bootstrap_virtualenv;
-    &quot;${bootstrap_python}&quot; -m virtualenv  \
-      --always-copy                      \
-      --system-site-packages             \
-      --no-setuptools                    \
-      &quot;${py_virtualenv}&quot;;
-  fi;
-
</del><span class="cx">   c_dependencies;
</span><span class="cx">   py_dependencies;
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunklibpatchescx_Oraclenclobfixesandprefetchpatch"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/lib-patches/cx_Oracle/nclob-fixes-and-prefetch.patch (0 => 15190)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/lib-patches/cx_Oracle/nclob-fixes-and-prefetch.patch                                (rev 0)
+++ CalendarServer/trunk/lib-patches/cx_Oracle/nclob-fixes-and-prefetch.patch        2015-10-14 18:28:42 UTC (rev 15190)
</span><span class="lines">@@ -0,0 +1,52 @@
</span><ins>+diff -ur ./Connection.c ../cx_Oracle-5.2-patched/Connection.c
+--- ./Connection.c        2015-06-06 23:31:08.000000000 -0400
++++ ../cx_Oracle-5.2-patched/Connection.c        2015-10-14 11:43:01.000000000 -0400
+@@ -747,6 +747,18 @@
+     if (newPasswordObj)
+         return Connection_ChangePassword(self, self-&gt;password, newPasswordObj);
+
++    // set lob prefetch attribute to session
++    ub4 default_lobprefetch_size = 4096;                  // Set default size to 4K
++    status = OCIAttrSet (self-&gt;sessionHandle, OCI_HTYPE_SESSION,
++                (void *)&amp;default_lobprefetch_size, 0,
++                OCI_ATTR_DEFAULT_LOBPREFETCH_SIZE,
++                self-&gt;environment-&gt;errorHandle);
++    if (Environment_CheckForError(self-&gt;environment, status,
++            &quot;Connection_Connect(): OCI_ATTR_DEFAULT_LOBPREFETCH_SIZE&quot;) &lt; 0) {
++        self-&gt;sessionHandle = NULL;
++        return -1;
++    }
++
+     // begin the session
+     Py_BEGIN_ALLOW_THREADS
+     status = OCISessionBegin(self-&gt;handle, self-&gt;environment-&gt;errorHandle,
+diff -ur ./Cursor.c ../cx_Oracle-5.2-patched/Cursor.c
+--- ./Cursor.c        2015-06-06 18:51:44.000000000 -0400
++++ ../cx_Oracle-5.2-patched/Cursor.c        2015-10-14 11:57:02.000000000 -0400
+@@ -1841,8 +1841,8 @@
+         }
+     }
+     Py_BEGIN_ALLOW_THREADS
+-    status = OCIStmtFetch(self-&gt;handle, self-&gt;environment-&gt;errorHandle,
+-            numRows, OCI_FETCH_NEXT, OCI_DEFAULT);
++    status = OCIStmtFetch2(self-&gt;handle, self-&gt;environment-&gt;errorHandle,
++            numRows, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
+     Py_END_ALLOW_THREADS
+     if (status != OCI_NO_DATA) {
+         if (Environment_CheckForError(self-&gt;environment, status,
+diff -ur ./ExternalLobVar.c ../cx_Oracle-5.2-patched/ExternalLobVar.c
+--- ./ExternalLobVar.c        2015-06-15 20:16:14.000000000 -0400
++++ ../cx_Oracle-5.2-patched/ExternalLobVar.c        2015-10-14 12:05:01.000000000 -0400
+@@ -275,10 +275,9 @@
+         else amount = 1;
+     }
+     length = amount;
+-    if (var-&gt;lobVar-&gt;type == &amp;vt_CLOB)
++    if ((var-&gt;lobVar-&gt;type == &amp;vt_CLOB) || (var-&gt;lobVar-&gt;type == &amp;vt_NCLOB))
++        // Always use environment setting for character LOBs
+         bufferSize = amount * var-&gt;lobVar-&gt;environment-&gt;maxBytesPerCharacter;
+-    else if (var-&gt;lobVar-&gt;type == &amp;vt_NCLOB)
+-        bufferSize = amount * 2;
+     else bufferSize = amount;
+
+     // create a string for retrieving the value
</ins></span></pre></div>
<a id="CalendarServertrunkrequirementsstabletxt"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/requirements-stable.txt (15189 => 15190)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/requirements-stable.txt        2015-10-14 17:41:35 UTC (rev 15189)
+++ CalendarServer/trunk/requirements-stable.txt        2015-10-14 18:28:42 UTC (rev 15190)
</span><span class="lines">@@ -55,7 +55,7 @@
</span><span class="cx">             pg8000==1.10.2
</span><span class="cx"> 
</span><span class="cx">         # [Oracle] extra
</span><del>-            #cx_Oracle==5.1.3  # Not in PyPI
</del><ins>+            #cx_Oracle==5.2  # Needs manual patch
</ins><span class="cx"> 
</span><span class="cx">     pyOpenSSL==0.14
</span><span class="cx">         cryptography==0.9
</span></span></pre></div>
<a id="CalendarServertrunksetuppy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/setup.py (15189 => 15190)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/setup.py        2015-10-14 17:41:35 UTC (rev 15189)
+++ CalendarServer/trunk/setup.py        2015-10-14 18:28:42 UTC (rev 15190)
</span><span class="lines">@@ -349,7 +349,7 @@
</span><span class="cx"> extras_requirements = {
</span><span class="cx">     &quot;LDAP&quot;: [&quot;twextpy[LDAP]&quot;],
</span><span class="cx">     &quot;OpenDirectory&quot;: [&quot;twextpy[OpenDirectory]&quot;],
</span><del>-    &quot;Oracle&quot;: [&quot;twextpy[Oracle]&quot;, &quot;cx_Oracle&quot;],
</del><ins>+    &quot;Oracle&quot;: [&quot;twextpy[Oracle]&quot;, &quot;cx_Oracle=5.2&quot;],
</ins><span class="cx">     &quot;Postgres&quot;: [&quot;twextpy[Postgres]&quot;, &quot;pg8000&quot;],
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>