1
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
3
<title>FreeTDS API: /usr/local/users/home/jklowden/projects/releases/freetds/0.82/src/dblib/buffering.h Source File</title>
4
<link href="doxygen.css" rel="stylesheet" type="text/css">
6
<!-- Generated by Doxygen 1.4.1 -->
7
<div class="qindex"><a class="qindex" href="index.html">Main Page</a> | <a class="qindex" href="modules.html">Modules</a> | <a class="qindex" href="annotated.html">Class List</a> | <a class="qindex" href="dirs.html">Directories</a> | <a class="qindex" href="files.html">File List</a> | <a class="qindex" href="functions.html">Class Members</a> | <a class="qindex" href="globals.html">File Members</a> | <a class="qindex" href="pages.html">Related Pages</a></div>
9
<a class="el" href="dir_000002.html">src</a> / <a class="el" href="dir_000006.html">dblib</a></div>
10
<h1>buffering.h</h1><div class="fragment"><pre class="fragment">00001 <span class="keyword">typedef</span> <span class="keyword">struct </span>dblib_buffer_row {
11
00003 <a class="code" href="a00143.html">TDSRESULTINFO</a> *resinfo;
12
00005 <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> *row_data;
15
00010 } DBLIB_BUFFER_ROW;
17
00012 <span class="keyword">static</span> <span class="keywordtype">void</span> buffer_struct_print(<span class="keyword">const</span> DBPROC_ROWBUF *buf);
18
00013 <span class="keyword">static</span> <span class="keywordtype">int</span> buffer_save_row(DBPROCESS *dbproc);
19
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);
21
00045 <span class="keyword">static</span> <span class="keywordtype">int</span>
22
00046 buffer_count(<span class="keyword">const</span> DBPROC_ROWBUF *buf)
24
00048 <span class="keywordflow">return</span> (buf->head > buf->tail) ?
25
00049 buf->head - buf->tail : <span class="comment">/* |...TddddH....| */</span>
26
00050 buf->capacity - (buf->tail - buf->head); <span class="comment">/* |ddddH....Tddd| */</span>
29
00056 <span class="keyword">static</span> <span class="keywordtype">int</span>
30
00057 buffer_is_full(<span class="keyword">const</span> DBPROC_ROWBUF *buf)
32
00059 <span class="keywordflow">return</span> buf->capacity == buffer_count(buf) && buf->capacity > 1;
35
00062 <span class="preprocessor">#ifndef NDEBUG</span>
36
00063 <span class="preprocessor"></span><span class="keyword">static</span> <span class="keywordtype">int</span>
37
00064 buffer_index_valid(<span class="keyword">const</span> DBPROC_ROWBUF *buf, <span class="keywordtype">int</span> idx)
39
00066 <span class="keywordflow">if</span> (buf->tail <= buf->head)
40
00067 if (buf->head <= idx && idx <= buf->tail)
43
00070 if (0 <= idx && idx <= buf->head)
46
00073 if (buf->tail <= idx && idx < buf->capacity)
49
00076 printf("buffer_index_valid: idx = %d\n", idx);
50
00077 buffer_struct_print(buf);
56
00083 static <span class="keywordtype">void</span>
57
00084 buffer_free_row(DBLIB_BUFFER_ROW *row)
59
00086 <span class="keywordflow">if</span> (row->sizes)
60
00087 TDS_ZERO_FREE(row->sizes);
61
00088 if (row->row_data) {
62
00089 tds_free_row(row->resinfo, row->row_data);
63
00090 row->row_data = NULL;
65
00092 tds_free_results(row->resinfo);
66
00093 row->resinfo = NULL;
69
00096 <span class="comment">/*</span>
70
00097 <span class="comment"> * Buffer is freed at slightly odd points, whenever</span>
71
00098 <span class="comment"> * capacity changes: </span>
72
00099 <span class="comment"> * </span>
73
00100 <span class="comment"> * 1. When setting capacity, to release prior buffer. </span>
74
00101 <span class="comment"> * 2. By dbresults. When called the second time, it has to </span>
75
00102 <span class="comment"> * release prior storage because the new resultset will have</span>
76
00103 <span class="comment"> * a different width. </span>
77
00104 <span class="comment"> * 3. By dbclose(), else open/close/open would leak. </span>
78
00105 <span class="comment"> */</span>
79
00106 <span class="keyword">static</span> <span class="keywordtype">void</span>
80
00107 buffer_free(DBPROC_ROWBUF *buf)
82
00109 <span class="keywordflow">if</span> (buf->rows != NULL) {
83
00110 <span class="keywordtype">int</span> i;
84
00111 <span class="keywordflow">for</span> (i = 0; i < buf->capacity; ++i)
85
00112 buffer_free_row(&buf->rows[i]);
86
00113 TDS_ZERO_FREE(buf->rows);
90
00117 <span class="comment">/*</span>
91
00118 <span class="comment"> * When no rows are currently buffered (and the buffer is allocated)</span>
92
00119 <span class="comment"> * set the indices to their initial postions.</span>
93
00120 <span class="comment"> */</span>
94
00121 static <span class="keywordtype">void</span>
95
00122 buffer_reset(DBPROC_ROWBUF *buf)
97
00124 buf->head = 0;
98
00125 buf->current = buf->tail = buf->capacity;
101
00128 <span class="keyword">static</span> <span class="keywordtype">int</span>
102
00129 buffer_idx_increment(<span class="keyword">const</span> DBPROC_ROWBUF *buf, <span class="keywordtype">int</span> idx)
104
00131 <span class="keywordflow">if</span> (++idx >= buf->capacity) {
107
00134 <span class="keywordflow">return</span> idx;
110
00141 <span class="keyword">static</span> DBLIB_BUFFER_ROW*
111
00142 buffer_row_address(<span class="keyword">const</span> DBPROC_ROWBUF * buf, <span class="keywordtype">int</span> idx)
113
00144 <span class="keywordflow">if</span> (!(idx >= 0 && idx < buf->capacity)) {
114
00145 printf(<span class="stringliteral">"idx is %d:\n"</span>, idx);
115
00146 buffer_struct_print(buf);
116
00147 assert(idx >= 0);
117
00148 assert(idx < buf->capacity);
120
00151 <span class="keywordflow">return</span> &(buf->rows[idx]);
123
00157 <span class="keyword">static</span> DBINT
124
00158 buffer_idx2row(<span class="keyword">const</span> DBPROC_ROWBUF *buf, <span class="keywordtype">int</span> idx)
126
00160 <span class="keywordflow">return</span> buffer_row_address(buf, idx)->row;
129
00166 <span class="keyword">static</span> <span class="keywordtype">int</span>
130
00167 buffer_row2idx(<span class="keyword">const</span> DBPROC_ROWBUF *buf, <span class="keywordtype">int</span> row_number)
132
00169 <span class="keywordtype">int</span> i, ii, idx = -1;
134
00171 <span class="keywordflow">if</span> (buf->tail == buf->capacity) {
135
00172 assert (buf->head == 0);
136
00173 <span class="keywordflow">return</span> -1; <span class="comment">/* no rows buffered */</span>
139
00176 <span class="comment">/* </span>
140
00177 <span class="comment"> * March through the buffers from tail to head, stop if we find our row. </span>
141
00178 <span class="comment"> * A full queue is indicated by tail == head (which means we can't write).</span>
142
00179 <span class="comment"> */</span>
143
00180 <span class="keywordflow">for</span> (ii=0, i = buf->tail; i != buf->head || ii == 0; i = buffer_idx_increment(buf, i)) {
144
00181 <span class="keywordflow">if</span>( buffer_idx2row(buf, i) == row_number) {
146
00183 <span class="keywordflow">break</span>;
148
00185 assert(ii++ < buf->capacity); <span class="comment">/* prevent infinite loop */</span>
151
00188 <span class="keywordflow">return</span> idx;
154
00196 <span class="keyword">static</span> <span class="keywordtype">void</span>
155
00197 buffer_delete_rows(DBPROC_ROWBUF * buf, <span class="keywordtype">int</span> count)
157
00199 <span class="keywordtype">int</span> i;
159
00201 <span class="keywordflow">if</span> (count < 0 || count > buffer_count(buf)) {
160
00202 count = buffer_count(buf);
163
00205 <span class="keywordflow">for</span> (i=0; i < count; i++) {
164
00206 <span class="keywordflow">if</span> (buf->tail < buf->capacity)
165
00207 buffer_free_row(&buf->rows[i]);
166
00208 buf->tail = buffer_idx_increment(buf, buf->tail);
167
00209 <span class="comment">/* </span>
168
00210 <span class="comment"> * If deleting rows from the buffer catches the tail to the head, </span>
169
00211 <span class="comment"> * return to the initial postion. Otherwise, it will look full.</span>
170
00212 <span class="comment"> */</span>
171
00213 if (buf->tail == buf->head) {
172
00214 buffer_reset(buf);
173
00215 <span class="keywordflow">break</span>;
176
00218 <span class="preprocessor">#if 0</span>
177
00219 <span class="preprocessor"></span> buffer_struct_print(buf);
178
00220 <span class="preprocessor">#endif</span>
179
00221 <span class="preprocessor"></span>}
181
00223 <span class="keyword">static</span> <span class="keywordtype">void</span>
182
00224 buffer_transfer_bound_data(DBPROC_ROWBUF *buf, TDS_INT res_type, TDS_INT compute_id, DBPROCESS * dbproc, <span class="keywordtype">int</span> idx)
184
00226 <span class="keywordtype">int</span> i;
185
00227 <span class="keywordtype">int</span> srctype, desttype;
187
00229 <span class="keyword">const</span> DBLIB_BUFFER_ROW *row;
189
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);
190
00232 assert(buffer_index_valid(buf, idx));
192
00234 row = buffer_row_address(buf, idx);
193
00235 assert(row->resinfo);
195
00237 <span class="keywordflow">for</span> (i = 0; i < row->resinfo->num_cols; i++) {
197
00239 <a class="code" href="a00140.html">TDSCOLUMN</a> *curcol = row->resinfo->columns[i];
199
00241 <span class="keywordflow">if</span> (row->sizes)
200
00242 curcol->column_cur_size = row->sizes[i];
202
00244 if (curcol->column_nullbind) {
203
00245 <span class="keywordflow">if</span> (curcol-><a class="code" href="a00140.html#o9">column_cur_size</a> < 0) {
204
00246 *(DBINT *)(curcol-><a class="code" href="a00140.html#o20">column_nullbind</a>) = -1;
205
00247 } <span class="keywordflow">else</span> {
206
00248 *(DBINT *)(curcol-><a class="code" href="a00140.html#o20">column_nullbind</a>) = 0;
209
00251 <span class="keywordflow">if</span> (!curcol-><a class="code" href="a00140.html#o32">column_varaddr</a>)
212
00254 if (row->row_data)
213
00255 src = &row->row_data[curcol->column_data - row->resinfo->current_row];
215
00257 src = curcol->column_data;
216
00258 srclen = curcol->column_cur_size;
217
00259 if (is_blob_type(curcol->column_type)) {
218
00260 src = (BYTE *) ((<a class="code" href="a00139.html">TDSBLOB</a> *) src)->textvalue;
220
00262 desttype = _db_get_server_type(curcol-><a class="code" href="a00140.html#o7">column_bindtype</a>);
221
00263 srctype = <a class="code" href="a00287.html#ga17">tds_get_conversion_type</a>(curcol-><a class="code" href="a00140.html#o30">column_type</a>, curcol-><a class="code" href="a00140.html#o26">column_size</a>);
223
00265 <span class="keywordflow">if</span> (srclen <= 0) {
224
00266 <span class="keywordflow">if</span> (srclen == 0 || !curcol-><a class="code" href="a00140.html#o20">column_nullbind</a>)
225
00267 dbgetnull(dbproc, curcol->column_bindtype, curcol->column_bindlen,
226
00268 (BYTE *) curcol->column_varaddr);
228
00270 copy_data_to_host_var(dbproc, srctype, src, srclen, desttype,
229
00271 (BYTE *) curcol-><a class="code" href="a00140.html#o32">column_varaddr</a>, curcol-><a class="code" href="a00140.html#o6">column_bindlen</a>,
230
00272 curcol-><a class="code" href="a00140.html#o7">column_bindtype</a>, curcol-><a class="code" href="a00140.html#o20">column_nullbind</a>);
234
00276 <span class="comment">/*</span>
235
00277 <span class="comment"> * This function always bumps current. Usually, it's called </span>
236
00278 <span class="comment"> * by dbnextrow(), so bumping current is a pretty obvious choice. </span>
237
00279 <span class="comment"> * It can also be called by dbgetrow(), but that function also </span>
238
00280 <span class="comment"> * causes the bump. If you call dbgetrow() for row N, a subsequent</span>
239
00281 <span class="comment"> * call to dbnextrow() yields N+1. </span>
240
00282 <span class="comment"> */</span>
241
00283 buf->current = buffer_idx_increment(buf, buf->current);
243
00285 } <span class="comment">/* end buffer_transfer_bound_data() */</span>
245
00287 <span class="keyword">static</span> <span class="keywordtype">void</span>
246
00288 buffer_struct_print(<span class="keyword">const</span> DBPROC_ROWBUF *buf)
250
00292 printf(<span class="stringliteral">"\t%d rows in buffer\n"</span>, buffer_count(buf));
252
00294 printf(<span class="stringliteral">"\thead = %d\t"</span>, buf->head);
253
00295 printf(<span class="stringliteral">"\ttail = %d\t"</span>, buf->tail);
254
00296 printf(<span class="stringliteral">"\tcurrent = %d\n"</span>, buf->current);
255
00297 printf(<span class="stringliteral">"\tcapacity = %d\t"</span>, buf->capacity);
256
00298 printf(<span class="stringliteral">"\thead row number = %d\n"</span>, buf->received);
259
00301 <span class="comment">/* * * Functions called only by public db-lib API take DBPROCESS* * */</span>
261
00319 <span class="keyword">static</span> <span class="keywordtype">int</span>
262
00320 buffer_current_index(<span class="keyword">const</span> DBPROCESS *dbproc)
264
00322 <span class="keyword">const</span> DBPROC_ROWBUF *buf = &dbproc->row_buf;
265
00323 <span class="preprocessor">#if 0</span>
266
00324 <span class="preprocessor"></span> buffer_struct_print(buf);
267
00325 <span class="preprocessor">#endif</span>
268
00326 <span class="preprocessor"></span> <span class="keywordflow">if</span> (buf->capacity <= 1) <span class="comment">/* no buffering */</span>
270
00328 if (buf->current == buf->head || buf->current == buf->capacity)
273
00331 assert(buf->current >= 0);
274
00332 assert(buf->current < buf->capacity);
276
00334 if( buf->tail < buf->head) {
277
00335 assert(buf->tail < buf->current);
278
00336 assert(buf->current < buf->head);
279
00337 } <span class="keywordflow">else</span> {
280
00338 <span class="keywordflow">if</span> (buf->current > buf->head)
281
00339 assert(buf->current > buf->tail);
283
00341 return buf->current;
286
00344 <span class="comment">/*</span>
287
00345 <span class="comment"> * Normally called by dbsetopt() to prepare for buffering</span>
288
00346 <span class="comment"> * Called with nrows == 0 by dbopen to safely set buf->rows to NULL. </span>
289
00347 <span class="comment"> */</span>
290
00348 static <span class="keywordtype">void</span>
291
00349 buffer_set_capacity(DBPROCESS *dbproc, <span class="keywordtype">int</span> nrows)
293
00351 DBPROC_ROWBUF *buf = &dbproc->row_buf;
295
00353 buffer_free(buf);
297
00355 memset(buf, 0, <span class="keyword">sizeof</span>(DBPROC_ROWBUF));
299
00357 <span class="keywordflow">if</span> (0 == nrows) {
300
00358 buf->capacity = 1;
301
00359 <span class="keywordflow">return</span>;
304
00362 assert(0 < nrows);
306
00364 buf->capacity = nrows;
309
00367 <span class="comment">/*</span>
310
00368 <span class="comment"> * Called only by dbresults(); capacity must be >= 1. </span>
311
00369 <span class="comment"> * Sybase's documents say dbresults() cannot return FAIL if the prior calls worked, </span>
312
00370 <span class="comment"> * which is a little strange, because (for FreeTDS, at least), dbresults</span>
313
00371 <span class="comment"> * is when we learn about the result set's width. Without that information, we</span>
314
00372 <span class="comment"> * can't allocate memory for the buffer. But if we *fail* to allocate memory, </span>
315
00373 <span class="comment"> * we're not to communicate it back to the caller? </span>
316
00374 <span class="comment"> */</span>
317
00375 <span class="keyword">static</span> <span class="keywordtype">void</span>
318
00376 buffer_alloc(DBPROCESS *dbproc)
320
00378 DBPROC_ROWBUF *buf = &dbproc->row_buf;
322
00380 <span class="comment">/* Call this function only after setting capacity. */</span>
325
00383 assert(buf->capacity > 0);
326
00384 assert(buf->rows == NULL);
328
00386 buf->rows = (DBLIB_BUFFER_ROW *) calloc(buf->capacity, <span class="keyword">sizeof</span>(DBLIB_BUFFER_ROW));
330
00388 assert(buf->rows);
332
00390 buffer_reset(buf);
334
00392 buf->received = 0;
337
00399 <span class="keyword">static</span> <span class="keywordtype">int</span>
338
00400 buffer_add_row(DBPROCESS *dbproc, <a class="code" href="a00143.html">TDSRESULTINFO</a> *resinfo)
340
00402 DBPROC_ROWBUF *buf = &dbproc->row_buf;
341
00403 DBLIB_BUFFER_ROW *row;
342
00404 <span class="keywordtype">int</span> i;
344
00406 assert(buf->capacity >= 0);
346
00408 <span class="keywordflow">if</span> (buffer_is_full(buf))
349
00411 <span class="comment">/* initial condition is head == 0 and tail == capacity */</span>
350
00412 if (buf->tail == buf->capacity) {
351
00413 <span class="comment">/* bumping this tail will set it to zero */</span>
352
00414 assert(buf->head == 0);
353
00415 buf->tail = buffer_idx_increment(buf, buf->tail);
356
00418 row = buffer_row_address(buf, buf->head);
358
00420 <span class="comment">/* bump the row number, write it, and move the data to head */</span>
359
00421 <span class="keywordflow">if</span> (row->resinfo) {
360
00422 tds_free_row(row->resinfo, row->row_data);
361
00423 tds_free_results(row->resinfo);
363
00425 row->row = ++buf->received;
364
00426 ++resinfo->ref_count;
365
00427 row->resinfo = resinfo;
366
00428 row->row_data = NULL;
367
00429 <span class="keywordflow">if</span> (row->sizes)
368
00430 free(row->sizes);
369
00431 row->sizes = (TDS_INT *) calloc(resinfo->num_cols, sizeof(TDS_INT));
370
00432 for (i = 0; i < resinfo->num_cols; ++i)
371
00433 row->sizes[i] = resinfo->columns[i]->column_cur_size;
373
00435 <span class="comment">/* update current, bump the head */</span>
374
00436 buf->current = buf->head;
375
00437 buf->head = buffer_idx_increment(buf, buf->head);
377
00439 return buf->current;
380
00442 static <span class="keywordtype">int</span>
381
00443 buffer_save_row(DBPROCESS *dbproc)
383
00445 DBPROC_ROWBUF *buf = &dbproc->row_buf;
384
00446 DBLIB_BUFFER_ROW *row;
385
00447 <span class="keywordtype">int</span> idx = buf->head - 1;
387
00449 <span class="keywordflow">if</span> (buf->capacity <= 1)
388
00450 return SUCCEED;
390
00452 if (idx < 0)
391
00453 idx = buf->capacity - 1;
392
00454 if (idx >= 0 && idx < buf->capacity) {
393
00455 row = &buf->rows[idx];
395
00457 <span class="keywordflow">if</span> (row->resinfo && !row->row_data) {
396
00458 row->row_data = row->resinfo->current_row;
397
00459 <a class="code" href="a00289.html#ga12">tds_alloc_row</a>(row->resinfo);
401
00463 <span class="keywordflow">return</span> SUCCEED;
404
</pre></div><hr size="1"><address style="align: right;"><small>Generated on Wed May 7 19:22:09 2008 for FreeTDS API by
405
<a href="http://www.doxygen.org/index.html">
406
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.4.1 </small></address>