Sophie

Sophie

distrib > Mageia > 1 > i586 > media > core-release > by-pkgid > f0bc842dcf666302badcfd2545f3387c > files > 103

libfreetds0-doc-0.82-12.mga1.i586.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>FreeTDS API: /usr/local/users/home/jklowden/projects/releases/freetds/0.82/src/dblib/buffering.h Source File</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.4.1 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="modules.html">Modules</a> | <a class="qindex" href="annotated.html">Class&nbsp;List</a> | <a class="qindex" href="dirs.html">Directories</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Class&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a> | <a class="qindex" href="pages.html">Related&nbsp;Pages</a></div>
<div class="nav">
<a class="el" href="dir_000002.html">src</a>&nbsp;/&nbsp;<a class="el" href="dir_000006.html">dblib</a></div>
<h1>buffering.h</h1><div class="fragment"><pre class="fragment">00001 <span class="keyword">typedef</span> <span class="keyword">struct </span>dblib_buffer_row {
00003         <a class="code" href="a00143.html">TDSRESULTINFO</a> *resinfo;
00005         <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> *row_data;
00007         DBINT row;
00009         TDS_INT *sizes;
00010 } DBLIB_BUFFER_ROW;
00011 
00012 <span class="keyword">static</span> <span class="keywordtype">void</span> buffer_struct_print(<span class="keyword">const</span> DBPROC_ROWBUF *buf);
00013 <span class="keyword">static</span> <span class="keywordtype">int</span> buffer_save_row(DBPROCESS *dbproc);
00014 <span class="keyword">static</span> DBLIB_BUFFER_ROW* buffer_row_address(<span class="keyword">const</span> DBPROC_ROWBUF * buf, <span class="keywordtype">int</span> idx);
00015 
00045 <span class="keyword">static</span> <span class="keywordtype">int</span>
00046 buffer_count(<span class="keyword">const</span> DBPROC_ROWBUF *buf)
00047 {
00048         <span class="keywordflow">return</span> (buf-&gt;head &gt; buf-&gt;tail) ?
00049                 buf-&gt;head - buf-&gt;tail :                         <span class="comment">/* |...TddddH....| */</span>
00050                 buf-&gt;capacity - (buf-&gt;tail - buf-&gt;head);        <span class="comment">/* |ddddH....Tddd| */</span>
00051 }
00052  
00056 <span class="keyword">static</span> <span class="keywordtype">int</span>
00057 buffer_is_full(<span class="keyword">const</span> DBPROC_ROWBUF *buf)
00058 {
00059         <span class="keywordflow">return</span> buf-&gt;capacity == buffer_count(buf) &amp;&amp; buf-&gt;capacity &gt; 1;
00060 }
00061 
00062 <span class="preprocessor">#ifndef NDEBUG</span>
00063 <span class="preprocessor"></span><span class="keyword">static</span> <span class="keywordtype">int</span>
00064 buffer_index_valid(<span class="keyword">const</span> DBPROC_ROWBUF *buf, <span class="keywordtype">int</span> idx)
00065 {
00066         <span class="keywordflow">if</span> (buf-&gt;tail &lt;= buf-&gt;head)
00067                 if (buf-&gt;head &lt;= idx &amp;&amp; idx &lt;= buf-&gt;tail)
00068                         return 1;
00069         
00070         if (0 &lt;= idx &amp;&amp; idx &lt;= buf-&gt;head)
00071                 return 1;
00072         
00073         if (buf-&gt;tail &lt;= idx &amp;&amp; idx &lt; buf-&gt;capacity)
00074                 return 1;
00075 #if 0   
00076         printf("buffer_index_valid: idx = %d\n", idx);
00077         buffer_struct_print(buf);
00078 #endif
00079         return 0;       
00080 }
00081 #endif
00082 
00083 static <span class="keywordtype">void</span>
00084 buffer_free_row(DBLIB_BUFFER_ROW *row)
00085 {
00086         <span class="keywordflow">if</span> (row-&gt;sizes)
00087                 TDS_ZERO_FREE(row-&gt;sizes);
00088         if (row-&gt;row_data) {
00089                 tds_free_row(row-&gt;resinfo, row-&gt;row_data);
00090                 row-&gt;row_data = NULL;
00091         }
00092         tds_free_results(row-&gt;resinfo);
00093         row-&gt;resinfo = NULL;
00094 }
00095  
00096 <span class="comment">/*</span>
00097 <span class="comment"> * Buffer is freed at slightly odd points, whenever</span>
00098 <span class="comment"> * capacity changes: </span>
00099 <span class="comment"> * </span>
00100 <span class="comment"> * 1. When setting capacity, to release prior buffer.  </span>
00101 <span class="comment"> * 2. By dbresults.  When called the second time, it has to </span>
00102 <span class="comment"> * release prior storage because the new resultset will have</span>
00103 <span class="comment"> * a different width.  </span>
00104 <span class="comment"> * 3. By dbclose(), else open/close/open would leak.  </span>
00105 <span class="comment"> */</span>
00106 <span class="keyword">static</span> <span class="keywordtype">void</span>
00107 buffer_free(DBPROC_ROWBUF *buf)
00108 {
00109         <span class="keywordflow">if</span> (buf-&gt;rows != NULL) {
00110                 <span class="keywordtype">int</span> i;
00111                 <span class="keywordflow">for</span> (i = 0; i &lt; buf-&gt;capacity; ++i)
00112                         buffer_free_row(&amp;buf-&gt;rows[i]);
00113                 TDS_ZERO_FREE(buf-&gt;rows);
00114         }
00115 }
00116 
00117 <span class="comment">/*</span>
00118 <span class="comment"> * When no rows are currently buffered (and the buffer is allocated)</span>
00119 <span class="comment"> * set the indices to their initial postions.</span>
00120 <span class="comment"> */</span>
00121 static <span class="keywordtype">void</span>
00122 buffer_reset(DBPROC_ROWBUF *buf)
00123 {
00124         buf-&gt;head = 0;
00125         buf-&gt;current = buf-&gt;tail = buf-&gt;capacity;
00126 }
00127 
00128 <span class="keyword">static</span> <span class="keywordtype">int</span>
00129 buffer_idx_increment(<span class="keyword">const</span> DBPROC_ROWBUF *buf, <span class="keywordtype">int</span> idx)
00130 {
00131         <span class="keywordflow">if</span> (++idx &gt;= buf-&gt;capacity) { 
00132                 idx = 0;
00133         }
00134         <span class="keywordflow">return</span> idx;
00135 }
00136 
00141 <span class="keyword">static</span> DBLIB_BUFFER_ROW*
00142 buffer_row_address(<span class="keyword">const</span> DBPROC_ROWBUF * buf, <span class="keywordtype">int</span> idx)
00143 {
00144         <span class="keywordflow">if</span> (!(idx &gt;= 0 &amp;&amp; idx &lt; buf-&gt;capacity)) {
00145                 printf(<span class="stringliteral">"idx is %d:\n"</span>, idx);
00146                 buffer_struct_print(buf);
00147                 assert(idx &gt;= 0);
00148                 assert(idx &lt; buf-&gt;capacity);
00149         }
00150         
00151         <span class="keywordflow">return</span> &amp;(buf-&gt;rows[idx]);
00152 }
00153 
00157 <span class="keyword">static</span> DBINT
00158 buffer_idx2row(<span class="keyword">const</span> DBPROC_ROWBUF *buf, <span class="keywordtype">int</span> idx)
00159 {
00160         <span class="keywordflow">return</span> buffer_row_address(buf, idx)-&gt;row;
00161 }
00162 
00166 <span class="keyword">static</span> <span class="keywordtype">int</span>
00167 buffer_row2idx(<span class="keyword">const</span> DBPROC_ROWBUF *buf, <span class="keywordtype">int</span> row_number)
00168 {
00169         <span class="keywordtype">int</span> i, ii, idx = -1;
00170         
00171         <span class="keywordflow">if</span> (buf-&gt;tail == buf-&gt;capacity) {
00172                 assert (buf-&gt;head == 0);
00173                 <span class="keywordflow">return</span> -1;      <span class="comment">/* no rows buffered */</span>
00174         }
00175         
00176         <span class="comment">/* </span>
00177 <span class="comment">         * March through the buffers from tail to head, stop if we find our row.  </span>
00178 <span class="comment">         * A full queue is indicated by tail == head (which means we can't write).</span>
00179 <span class="comment">         */</span>
00180         <span class="keywordflow">for</span> (ii=0, i = buf-&gt;tail; i != buf-&gt;head || ii == 0; i = buffer_idx_increment(buf, i)) {
00181                 <span class="keywordflow">if</span>( buffer_idx2row(buf, i) == row_number) {
00182                         idx = i;
00183                         <span class="keywordflow">break</span>;
00184                 }
00185                 assert(ii++ &lt; buf-&gt;capacity); <span class="comment">/* prevent infinite loop */</span>
00186         } 
00187         
00188         <span class="keywordflow">return</span> idx;
00189 }
00190 
00196 <span class="keyword">static</span> <span class="keywordtype">void</span>
00197 buffer_delete_rows(DBPROC_ROWBUF * buf, <span class="keywordtype">int</span> count)
00198 {
00199         <span class="keywordtype">int</span> i;
00200 
00201         <span class="keywordflow">if</span> (count &lt; 0 || count &gt; buffer_count(buf)) {
00202                 count = buffer_count(buf);
00203         }
00204 
00205         <span class="keywordflow">for</span> (i=0; i &lt; count; i++) {
00206                 <span class="keywordflow">if</span> (buf-&gt;tail &lt; buf-&gt;capacity)
00207                         buffer_free_row(&amp;buf-&gt;rows[i]);
00208                 buf-&gt;tail = buffer_idx_increment(buf, buf-&gt;tail);
00209                 <span class="comment">/* </span>
00210 <span class="comment">                 * If deleting rows from the buffer catches the tail to the head, </span>
00211 <span class="comment">                 * return to the initial postion.  Otherwise, it will look full.</span>
00212 <span class="comment">                 */</span>
00213                 if (buf-&gt;tail == buf-&gt;head) {
00214                         buffer_reset(buf);
00215                         <span class="keywordflow">break</span>;
00216                 }
00217         }
00218 <span class="preprocessor">#if 0</span>
00219 <span class="preprocessor"></span>        buffer_struct_print(buf);
00220 <span class="preprocessor">#endif</span>
00221 <span class="preprocessor"></span>}
00222 
00223 <span class="keyword">static</span> <span class="keywordtype">void</span>
00224 buffer_transfer_bound_data(DBPROC_ROWBUF *buf, TDS_INT res_type, TDS_INT compute_id, DBPROCESS * dbproc, <span class="keywordtype">int</span> idx)
00225 {
00226         <span class="keywordtype">int</span> i;
00227         <span class="keywordtype">int</span> srctype, desttype;
00228         BYTE *src;
00229         <span class="keyword">const</span> DBLIB_BUFFER_ROW *row;
00230 
00231         tdsdump_log(TDS_DBG_FUNC, <span class="stringliteral">"buffer_transfer_bound_data(%p %d %d %p %d)\n"</span>, buf, res_type, compute_id, dbproc, idx);
00232         assert(buffer_index_valid(buf, idx));
00233 
00234         row = buffer_row_address(buf, idx);
00235         assert(row-&gt;resinfo);
00236 
00237         <span class="keywordflow">for</span> (i = 0; i &lt; row-&gt;resinfo-&gt;num_cols; i++) {
00238                 DBINT srclen;
00239                 <a class="code" href="a00140.html">TDSCOLUMN</a> *curcol = row-&gt;resinfo-&gt;columns[i];
00240                 
00241                 <span class="keywordflow">if</span> (row-&gt;sizes)
00242                         curcol-&gt;column_cur_size = row-&gt;sizes[i];
00243 
00244                 if (curcol-&gt;column_nullbind) {
00245                         <span class="keywordflow">if</span> (curcol-&gt;<a class="code" href="a00140.html#o9">column_cur_size</a> &lt; 0) {
00246                                 *(DBINT *)(curcol-&gt;<a class="code" href="a00140.html#o20">column_nullbind</a>) = -1;
00247                         } <span class="keywordflow">else</span> {
00248                                 *(DBINT *)(curcol-&gt;<a class="code" href="a00140.html#o20">column_nullbind</a>) = 0;
00249                         }
00250                 }
00251                 <span class="keywordflow">if</span> (!curcol-&gt;<a class="code" href="a00140.html#o32">column_varaddr</a>)
00252                         continue;
00253 
00254                 if (row-&gt;row_data)
00255                         src = &amp;row-&gt;row_data[curcol-&gt;column_data - row-&gt;resinfo-&gt;current_row];
00256                 else
00257                         src = curcol-&gt;column_data;
00258                 srclen = curcol-&gt;column_cur_size;
00259                 if (is_blob_type(curcol-&gt;column_type)) {
00260                         src = (BYTE *) ((<a class="code" href="a00139.html">TDSBLOB</a> *) src)-&gt;textvalue;
00261                 }
00262                 desttype = _db_get_server_type(curcol-&gt;<a class="code" href="a00140.html#o7">column_bindtype</a>);
00263                 srctype = <a class="code" href="a00287.html#ga17">tds_get_conversion_type</a>(curcol-&gt;<a class="code" href="a00140.html#o30">column_type</a>, curcol-&gt;<a class="code" href="a00140.html#o26">column_size</a>);
00264 
00265                 <span class="keywordflow">if</span> (srclen &lt;= 0) {
00266                         <span class="keywordflow">if</span> (srclen == 0 || !curcol-&gt;<a class="code" href="a00140.html#o20">column_nullbind</a>)
00267                                 dbgetnull(dbproc, curcol-&gt;column_bindtype, curcol-&gt;column_bindlen,
00268                                                 (BYTE *) curcol-&gt;column_varaddr);
00269                 } else {
00270                         copy_data_to_host_var(dbproc, srctype, src, srclen, desttype, 
00271                                                 (BYTE *) curcol-&gt;<a class="code" href="a00140.html#o32">column_varaddr</a>,  curcol-&gt;<a class="code" href="a00140.html#o6">column_bindlen</a>,
00272                                                          curcol-&gt;<a class="code" href="a00140.html#o7">column_bindtype</a>, curcol-&gt;<a class="code" href="a00140.html#o20">column_nullbind</a>);
00273                 }
00274         }
00275 
00276         <span class="comment">/*</span>
00277 <span class="comment">         * This function always bumps current.  Usually, it's called </span>
00278 <span class="comment">         * by dbnextrow(), so bumping current is a pretty obvious choice.  </span>
00279 <span class="comment">         * It can also be called by dbgetrow(), but that function also </span>
00280 <span class="comment">         * causes the bump.  If you call dbgetrow() for row N, a subsequent</span>
00281 <span class="comment">         * call to dbnextrow() yields N+1.  </span>
00282 <span class="comment">         */</span>
00283         buf-&gt;current = buffer_idx_increment(buf, buf-&gt;current);
00284 
00285 }       <span class="comment">/* end buffer_transfer_bound_data()  */</span>
00286 
00287 <span class="keyword">static</span> <span class="keywordtype">void</span> 
00288 buffer_struct_print(<span class="keyword">const</span> DBPROC_ROWBUF *buf)
00289 {
00290         assert(buf);
00291 
00292         printf(<span class="stringliteral">"\t%d rows in buffer\n"</span>,         buffer_count(buf));
00293         
00294         printf(<span class="stringliteral">"\thead = %d\t"</span>,                 buf-&gt;head);
00295         printf(<span class="stringliteral">"\ttail = %d\t"</span>,                 buf-&gt;tail);
00296         printf(<span class="stringliteral">"\tcurrent = %d\n"</span>,              buf-&gt;current);
00297         printf(<span class="stringliteral">"\tcapacity = %d\t"</span>,             buf-&gt;capacity);
00298         printf(<span class="stringliteral">"\thead row number = %d\n"</span>,      buf-&gt;received);
00299 }
00300 
00301 <span class="comment">/* * * Functions called only by public db-lib API take DBPROCESS* * */</span>
00302 
00319 <span class="keyword">static</span> <span class="keywordtype">int</span>
00320 buffer_current_index(<span class="keyword">const</span> DBPROCESS *dbproc)
00321 {
00322         <span class="keyword">const</span> DBPROC_ROWBUF *buf = &amp;dbproc-&gt;row_buf;
00323 <span class="preprocessor">#if 0</span>
00324 <span class="preprocessor"></span>        buffer_struct_print(buf);
00325 <span class="preprocessor">#endif</span>
00326 <span class="preprocessor"></span>        <span class="keywordflow">if</span> (buf-&gt;capacity &lt;= 1) <span class="comment">/* no buffering */</span>
00327                 return -1;
00328         if (buf-&gt;current == buf-&gt;head || buf-&gt;current == buf-&gt;capacity)
00329                 return -1;
00330                 
00331         assert(buf-&gt;current &gt;= 0);
00332         assert(buf-&gt;current &lt; buf-&gt;capacity);
00333         
00334         if( buf-&gt;tail &lt; buf-&gt;head) {
00335                 assert(buf-&gt;tail &lt; buf-&gt;current);
00336                 assert(buf-&gt;current &lt; buf-&gt;head);
00337         } <span class="keywordflow">else</span> {
00338                 <span class="keywordflow">if</span> (buf-&gt;current &gt; buf-&gt;head)
00339                         assert(buf-&gt;current &gt; buf-&gt;tail);
00340         }
00341         return buf-&gt;current;
00342 }
00343 
00344 <span class="comment">/*</span>
00345 <span class="comment"> * Normally called by dbsetopt() to prepare for buffering</span>
00346 <span class="comment"> * Called with nrows == 0 by dbopen to safely set buf-&gt;rows to NULL.  </span>
00347 <span class="comment"> */</span>
00348 static <span class="keywordtype">void</span>
00349 buffer_set_capacity(DBPROCESS *dbproc, <span class="keywordtype">int</span> nrows)
00350 {
00351         DBPROC_ROWBUF *buf = &amp;dbproc-&gt;row_buf;
00352         
00353         buffer_free(buf);
00354 
00355         memset(buf, 0, <span class="keyword">sizeof</span>(DBPROC_ROWBUF));
00356 
00357         <span class="keywordflow">if</span> (0 == nrows) {
00358                 buf-&gt;capacity = 1;
00359                 <span class="keywordflow">return</span>;
00360         }
00361 
00362         assert(0 &lt; nrows);
00363 
00364         buf-&gt;capacity = nrows;
00365 }
00366 
00367 <span class="comment">/*</span>
00368 <span class="comment"> * Called only by dbresults(); capacity must be &gt;= 1. </span>
00369 <span class="comment"> * Sybase's documents say dbresults() cannot return FAIL if the prior calls worked, </span>
00370 <span class="comment"> * which is a little strange, because (for FreeTDS, at least), dbresults</span>
00371 <span class="comment"> * is when we learn about the result set's width.  Without that information, we</span>
00372 <span class="comment"> * can't allocate memory for the buffer.  But if we *fail* to allocate memory, </span>
00373 <span class="comment"> * we're not to communicate it back to the caller?   </span>
00374 <span class="comment"> */</span>
00375 <span class="keyword">static</span> <span class="keywordtype">void</span>
00376 buffer_alloc(DBPROCESS *dbproc)
00377 {
00378         DBPROC_ROWBUF *buf = &amp;dbproc-&gt;row_buf;
00379         
00380         <span class="comment">/* Call this function only after setting capacity. */</span>
00381 
00382         assert(buf);
00383         assert(buf-&gt;capacity &gt; 0);
00384         assert(buf-&gt;rows == NULL);
00385         
00386         buf-&gt;rows = (DBLIB_BUFFER_ROW *) calloc(buf-&gt;capacity, <span class="keyword">sizeof</span>(DBLIB_BUFFER_ROW));
00387         
00388         assert(buf-&gt;rows);
00389         
00390         buffer_reset(buf);
00391         
00392         buf-&gt;received = 0;
00393 }
00394 
00399 <span class="keyword">static</span> <span class="keywordtype">int</span>
00400 buffer_add_row(DBPROCESS *dbproc, <a class="code" href="a00143.html">TDSRESULTINFO</a> *resinfo)
00401 {
00402         DBPROC_ROWBUF *buf = &amp;dbproc-&gt;row_buf;
00403         DBLIB_BUFFER_ROW *row;
00404         <span class="keywordtype">int</span> i;
00405 
00406         assert(buf-&gt;capacity &gt;= 0);
00407 
00408         <span class="keywordflow">if</span> (buffer_is_full(buf))
00409                 return -1;
00410 
00411         <span class="comment">/* initial condition is head == 0 and tail == capacity */</span>
00412         if (buf-&gt;tail == buf-&gt;capacity) {
00413                 <span class="comment">/* bumping this tail will set it to zero */</span>
00414                 assert(buf-&gt;head == 0);
00415                 buf-&gt;tail = buffer_idx_increment(buf, buf-&gt;tail);
00416         }
00417 
00418         row = buffer_row_address(buf, buf-&gt;head);
00419 
00420         <span class="comment">/* bump the row number, write it, and move the data to head */</span>
00421         <span class="keywordflow">if</span> (row-&gt;resinfo) {
00422                 tds_free_row(row-&gt;resinfo, row-&gt;row_data);
00423                 tds_free_results(row-&gt;resinfo);
00424         }
00425         row-&gt;row = ++buf-&gt;received;
00426         ++resinfo-&gt;ref_count;
00427         row-&gt;resinfo = resinfo;
00428         row-&gt;row_data = NULL;
00429         <span class="keywordflow">if</span> (row-&gt;sizes)
00430                 free(row-&gt;sizes);
00431         row-&gt;sizes = (TDS_INT *) calloc(resinfo-&gt;num_cols, sizeof(TDS_INT));
00432         for (i = 0; i &lt; resinfo-&gt;num_cols; ++i)
00433                 row-&gt;sizes[i] = resinfo-&gt;columns[i]-&gt;column_cur_size;
00434 
00435         <span class="comment">/* update current, bump the head */</span>
00436         buf-&gt;current = buf-&gt;head;
00437         buf-&gt;head = buffer_idx_increment(buf, buf-&gt;head);
00438 
00439         return buf-&gt;current;
00440 }
00441 
00442 static <span class="keywordtype">int</span>
00443 buffer_save_row(DBPROCESS *dbproc)
00444 {
00445         DBPROC_ROWBUF *buf = &amp;dbproc-&gt;row_buf;
00446         DBLIB_BUFFER_ROW *row;
00447         <span class="keywordtype">int</span> idx = buf-&gt;head - 1;
00448 
00449         <span class="keywordflow">if</span> (buf-&gt;capacity &lt;= 1)
00450                 return SUCCEED;
00451 
00452         if (idx &lt; 0)
00453                 idx = buf-&gt;capacity - 1;
00454         if (idx &gt;= 0 &amp;&amp; idx &lt; buf-&gt;capacity) {
00455                 row = &amp;buf-&gt;rows[idx];
00456 
00457                 <span class="keywordflow">if</span> (row-&gt;resinfo &amp;&amp; !row-&gt;row_data) {
00458                         row-&gt;row_data = row-&gt;resinfo-&gt;current_row;
00459                         <a class="code" href="a00289.html#ga12">tds_alloc_row</a>(row-&gt;resinfo);
00460                 }
00461         }
00462 
00463         <span class="keywordflow">return</span> SUCCEED;
00464 }
00465 
</pre></div><hr size="1"><address style="align: right;"><small>Generated on Wed May 7 19:22:09 2008 for FreeTDS API by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.4.1 </small></address>
</body>
</html>