chunk.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:15k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * chunk.c
  4.  *
  5.  * Copyright (c) 1994, Regents of the University of California
  6.  *
  7.  *
  8.  * IDENTIFICATION
  9.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/utils/adt/chunk.c,v 1.20.2.1 1999/08/02 05:24:50 scrappy Exp $
  10.  *
  11.  *-------------------------------------------------------------------------
  12.  */
  13. #include <ctype.h>
  14. #include <sys/types.h>
  15. #include <fcntl.h>
  16. #include "postgres.h"
  17. #include "catalog/pg_type.h"
  18. #include "fmgr.h"
  19. #include "libpq/be-fsstubs.h"
  20. #include "libpq/libpq-fs.h"
  21. #include "optimizer/internal.h"
  22. #include "utils/array.h"
  23. #include "utils/memutils.h"
  24. #define INFTY 500000000
  25. #define MANY  10000
  26. #define MAXPAT 20
  27. #define quot_ceil(x,y) (((x)+(y)-1)/(y))
  28. #define min(x,y) (((x) < (y))? (x) : (y))
  29. #define max(x,y) (((x) > (y))? (x) : (y))
  30. static CHUNK_INFO cInfo;
  31. /* non-export function prototypes */
  32. static int _FindBestChunk(int size, int *dmax, int *dbest, int dim,
  33.    int A[MAXPAT][MAXDIM + 1], int N);
  34. static int get_next(int *d, int k, int C, int *dmax);
  35. static void initialize_info(CHUNK_INFO *A, int ndim, int *dim, int *chunk);
  36. #ifdef LOARRAY
  37. static void _ConvertToChunkFile(int n, int baseSize, int *dim, int *C,
  38. int srcfd, int destfd);
  39. static void read_chunk(int *chunk_no, int *C, char *a_chunk, int srcfd,
  40.    int n, int baseSize, int *PX, int *dist);
  41. static int write_chunk(struct varlena * a_chunk, int ofile);
  42. static int seek_and_read(int pos, int size, char *buff, int fp, int from);
  43. #endif
  44. static int GetChunkSize(FILE *fd, int ndim, int dim[MAXDIM], int baseSize,
  45.  int d[MAXDIM]);
  46. /*------------------------------------------------------------------------
  47.  * _ChunkArray ---
  48.  *    converts an input array to chunked format using the information
  49.  *    provided by the access pattern.
  50.  * Results:
  51.  *    creates a new file that stores the chunked array and returns
  52.  *    information about the chunked file
  53.  *-----------------------------------------------------------------------
  54.  */
  55. char *
  56. _ChunkArray(int fd,
  57. FILE *afd,
  58. int ndim,
  59. int *dim,
  60. int baseSize,
  61. int *nbytes,
  62. char *chunkfile)
  63. {
  64. #ifdef LOARRAY
  65. int cfd = 0;
  66. #endif
  67. int chunk[MAXDIM],
  68. csize;
  69. bool reorgFlag;
  70. if (chunkfile == NULL)
  71. reorgFlag = true;
  72. else
  73. reorgFlag = false;
  74. #ifdef LOARRAY
  75. if (reorgFlag)
  76. /* create new LO for chunked file */
  77. chunkfile = _array_newLO(&cfd, fileFlag);
  78. else
  79. cfd = LOopen(chunkfile, O_RDONLY);
  80. if (cfd < 0)
  81. elog(ERROR, "Unable to open chunk file");
  82. #endif
  83. strcpy(cInfo.lo_name, chunkfile);
  84. /* find chunk size */
  85. csize = GetChunkSize(afd, ndim, dim, baseSize, chunk);
  86. #ifdef LOARRAY
  87. if (reorgFlag)
  88. /* copy data from input file to chunked file */
  89. _ConvertToChunkFile(ndim, baseSize, dim, chunk, fd, cfd);
  90. #endif
  91. initialize_info(&cInfo, ndim, dim, chunk);
  92. *nbytes = sizeof(CHUNK_INFO);
  93. return (char *) &cInfo;
  94. }
  95. /*--------------------------------------------------------------------------
  96.  * GetChunkSize
  97.  *   given an access pattern and array dimensionality etc, this program
  98.  * returns the dimensions of the chunk in "d"
  99.  *-----------------------------------------------------------------------
  100.  */
  101. static int
  102. GetChunkSize(FILE *fd,
  103.  int ndim,
  104.  int dim[MAXDIM],
  105.  int baseSize,
  106.  int d[MAXDIM])
  107. {
  108. int N,
  109. i,
  110. j,
  111. csize;
  112. int A[MAXPAT][MAXDIM + 1],
  113. dmax[MAXDIM];
  114. /*
  115.  * ----------- read input ------------
  116.  */
  117. fscanf(fd, "%d", &N);
  118. if (N > MAXPAT)
  119. elog(ERROR, "array_in: too many access pattern elements");
  120. for (i = 0; i < N; i++)
  121. for (j = 0; j < ndim + 1; j++)
  122. if (fscanf(fd, "%d ", &(A[i][j])) == EOF)
  123. elog(ERROR, "array_in: bad access pattern input");
  124. /*
  125.  * estimate chunk size
  126.  */
  127. for (i = 0; i < ndim; i++)
  128. for (j = 0, dmax[i] = 1; j < N; j++)
  129. if (dmax[i] < A[j][i])
  130. dmax[i] = A[j][i];
  131. csize = BLCKSZ / baseSize;
  132. _FindBestChunk(csize, dmax, d, ndim, A, N);
  133. return csize;
  134. }
  135. /*-------------------------------------------------------------------------
  136.  * _FindBestChunk
  137.  *   This routine does most of the number crunching to compute the
  138.  *   optimal chunk shape.
  139.  * Called by GetChunkSize
  140.  *------------------------------------------------------------------------
  141.  */
  142. static int
  143. _FindBestChunk(int size,
  144.    int *dmax,
  145.    int *dbest,
  146.    int dim,
  147.    int A[MAXPAT][MAXDIM + 1],
  148.    int N)
  149. {
  150. int d[MAXDIM];
  151. int tc,
  152. mintc = INFTY;
  153. d[0] = 0;
  154. mintc = INFTY;
  155. while (get_next(d, dim, size, dmax))
  156. {
  157. /*
  158.  * compute the number of page fetches for a given chunk size (*d)
  159.  * and access pattern (**A)
  160.  */
  161. int i,
  162. j,
  163. nc;
  164. for (i = 0, tc = 0; i < N; i++)
  165. {
  166. for (j = 0, nc = 1; j < dim; j++)
  167. nc *= quot_ceil(A[i][j], d[j]);
  168. nc *= A[i][dim];
  169. tc += nc;
  170. }
  171. /*
  172.  * tc holds the total number of page fetches
  173.  */
  174. if (mintc >= tc)
  175. {
  176. mintc = tc;
  177. for (j = 0; j < dim; dbest[j] = d[j], j++)
  178. ;
  179. }
  180. }
  181. return mintc;
  182. }
  183. /*----------------------------------------------------------------------
  184.  * get_next
  185.  *  Called by _GetBestChunk to get the next tuple in the lexicographic order
  186.  *---------------------------------------------------------------------
  187.  */
  188. static int
  189. get_next(int *d, int k, int C, int *dmax)
  190. {
  191. int i,
  192. j,
  193. temp;
  194. if (!d[0])
  195. {
  196. temp = C;
  197. for (j = k - 1; j >= 0; j--)
  198. {
  199. d[j] = min(temp, dmax[j]);
  200. temp = max(1, temp / d[j]);
  201. }
  202. return 1;
  203. }
  204. for (j = 0, temp = 1; j < k; j++)
  205. temp *= d[j];
  206. for (i = k - 1; i >= 0; i--)
  207. {
  208. temp = temp / d[i];
  209. if (((temp * (d[i] + 1)) < C) && (d[i] + 1 <= dmax[i]))
  210. break;
  211. }
  212. if (i < 0)
  213. return 0;
  214. d[i]++;
  215. j = C / temp;
  216. d[i] = min(dmax[i], j / (j / d[i]));
  217. temp = temp * d[i];
  218. temp = C / temp;
  219. for (j = k - 1; j > i; j--)
  220. {
  221. d[j] = min(temp, dmax[j]);
  222. temp = max(1, temp / d[j]);
  223. }
  224. return 1;
  225. }
  226. #ifdef LOARRAY
  227. static char a_chunk[BLCKSZ + VARHDRSZ]; /* VARHDRSZ since a_chunk is in
  228.  * varlena format */
  229. #endif
  230. static void
  231. initialize_info(CHUNK_INFO *A, int ndim, int *dim, int *chunk)
  232. {
  233. int i;
  234. for (i = 0; i < ndim; i++)
  235. A->C[i] = chunk[i];
  236. }
  237. /*--------------------------------------------------------------------------
  238.  * Procedure reorganize_data():
  239.  *   This procedure reads the input multidimensional array that is organised
  240.  *   in the order specified by array "X" and breaks it up into chunks of
  241.  *   dimensions specified in "C".
  242.  *
  243.  *   This is a very slow process, since reading and writing of LARGE files
  244.  *   may be involved.
  245.  *
  246.  *-------------------------------------------------------------------------
  247.  */
  248. #ifdef LOARRAY
  249. static void
  250. _ConvertToChunkFile(int n,
  251. int baseSize,
  252. int *dim,
  253. int *C,
  254. int srcfd,
  255. int destfd)
  256. {
  257. int max_chunks[MAXDIM],
  258. chunk_no[MAXDIM];
  259. int PX[MAXDIM],
  260. dist[MAXDIM];
  261. int csize = 1,
  262. i,
  263. temp;
  264. for (i = 0; i < n; chunk_no[i++] = 0)
  265. {
  266. max_chunks[i] = dim[i] / C[i];
  267. csize *= C[i];
  268. }
  269. csize *= baseSize;
  270. temp = csize + VARHDRSZ;
  271. memmove(a_chunk, &temp, VARHDRSZ);
  272. mda_get_prod(n, dim, PX);
  273. mda_get_offset_values(n, dist, PX, C);
  274. for (i = 0; i < n; dist[i] *= baseSize, i++)
  275. ;
  276. do
  277. {
  278. read_chunk(chunk_no, C, &(a_chunk[VARHDRSZ]), srcfd, n, baseSize, PX, dist);
  279. write_chunk((struct varlena *) a_chunk, destfd);
  280. } while (next_tuple(n, chunk_no, max_chunks) != -1);
  281. }
  282. /*--------------------------------------------------------------------------
  283.  * read_chunk
  284.  *   reads a chunk from the input files into a_chunk, the position of the
  285.  *   chunk is specified by chunk_no
  286.  *--------------------------------------------------------------------------
  287.  */
  288. static void
  289. read_chunk(int *chunk_no,
  290.    int *C,
  291.    char *a_chunk,
  292.    int srcfd,
  293.    int n,
  294.    int baseSize,
  295.    int *PX,
  296.    int *dist)
  297. {
  298. int i,
  299. j,
  300. cp,
  301. unit_transfer;
  302. int start_pos,
  303. pos[MAXDIM];
  304. int indx[MAXDIM];
  305. int fpOff;
  306. for (i = start_pos = 0; i < n; i++)
  307. {
  308. pos[i] = chunk_no[i] * C[i];
  309. start_pos += pos[i] * PX[i];
  310. }
  311. start_pos *= baseSize;
  312. /* Read a block of dimesion C starting at co-ordinates pos */
  313. unit_transfer = C[n - 1] * baseSize;
  314. for (i = 0; i < n; indx[i++] = 0)
  315. ;
  316. fpOff = start_pos;
  317. seek_and_read(fpOff, unit_transfer, a_chunk, srcfd, SEEK_SET);
  318. fpOff += unit_transfer;
  319. cp = unit_transfer;
  320. while ((j = next_tuple(n - 1, indx, C)) != -1)
  321. {
  322. fpOff += dist[j];
  323. seek_and_read(fpOff, unit_transfer, &(a_chunk[cp]), srcfd, SEEK_SET);
  324. cp += unit_transfer;
  325. fpOff += unit_transfer;
  326. }
  327. }
  328. /*--------------------------------------------------------------------------
  329.  * write_chunk()
  330.  *   writes a chunk of size csize into the output file
  331.  *--------------------------------------------------------------------------
  332.  */
  333. static int
  334. write_chunk(struct varlena * a_chunk, int ofile)
  335. {
  336. int got_n = 0;
  337. #ifdef LOARRAY
  338. got_n = LOwrite(ofile, a_chunk);
  339. #endif
  340. return got_n;
  341. }
  342. /*--------------------------------------------------------------------------
  343.  * seek_and_read()
  344.  *   seeks to the asked location in the input file and reads the
  345.  *   appropriate number of blocks
  346.  *  Called By: read_chunk()
  347.  *--------------------------------------------------------------------------
  348.  */
  349. static int
  350. seek_and_read(int pos, int size, char *buff, int fp, int from)
  351. {
  352. struct varlena *v = NULL;
  353. /* Assuming only one file */
  354. if (lo_lseek(fp, pos, from) < 0)
  355. elog(ERROR, "File seek error");
  356. #ifdef LOARRAY
  357. v = (struct varlena *) LOread(fp, size);
  358. #endif
  359. if (VARSIZE(v) - VARHDRSZ < size)
  360. elog(ERROR, "File read error");
  361. memmove(buff, VARDATA(v), size);
  362. pfree(v);
  363. return 1;
  364. }
  365. #endif  /* LOARRAY */
  366. /*----------------------------------------------------------------------------
  367.  * _ReadChunkArray
  368.  *   returns the subarray specified bu the range indices "st" and "endp"
  369.  *   from the chunked array stored in file "fp"
  370.  *---------------------------------------------------------------------------
  371.  */
  372. int
  373. _ReadChunkArray(int *st,
  374. int *endp,
  375. int bsize,
  376. int fp,
  377. char *destfp,
  378. ArrayType *array,
  379. int isDestLO,
  380. bool *isNull)
  381. {
  382. int i,
  383. j,
  384. jj;
  385. int n,
  386. temp,
  387. words_read;
  388. int chunk_span[MAXDIM],
  389. chunk_off[MAXDIM];
  390. int chunk_st[MAXDIM],
  391. chunk_end[MAXDIM];
  392. int block_seek;
  393. int bptr,
  394.    *C,
  395. csize,
  396.    *dim,
  397.    *lb;
  398. int range_st[MAXDIM],
  399. range_end[MAXDIM],
  400. range[MAXDIM],
  401. array_span[MAXDIM];
  402. int PA[MAXDIM],
  403. PCHUNK[MAXDIM],
  404. PC[MAXDIM];
  405. int to_read;
  406. int cdist[MAXDIM],
  407. adist[MAXDIM];
  408. int dist[MAXDIM],
  409. temp_seek;
  410. int srcOff; /* Needed since LO don't understand
  411.  * SEEK_CUR */
  412. char    *baseDestFp = (char *) destfp;
  413. CHUNK_INFO *A = (CHUNK_INFO *) ARR_DATA_PTR(array);
  414. n = ARR_NDIM(array);
  415. dim = ARR_DIMS(array);
  416. lb = ARR_LBOUND(array);
  417. C = A->C;
  418. csize = C[n - 1];
  419. PC[n - 1] = 1;
  420. temp = dim[n - 1] / C[n - 1];
  421. for (i = n - 2; i >= 0; i--)
  422. {
  423. PC[i] = PC[i + 1] * temp;
  424. temp = dim[i] / C[i];
  425. csize *= C[i];
  426. }
  427. for (i = 0; i < n; st[i] -= lb[i], endp[i] -= lb[i], i++)
  428. ;
  429. mda_get_prod(n, C, PCHUNK);
  430. mda_get_range(n, array_span, st, endp);
  431. mda_get_prod(n, array_span, PA);
  432. array2chunk_coord(n, C, st, chunk_st);
  433. array2chunk_coord(n, C, endp, chunk_end);
  434. mda_get_range(n, chunk_span, chunk_st, chunk_end);
  435. mda_get_offset_values(n, dist, PC, chunk_span);
  436. for (i = 0; i < n; i++)
  437. {
  438. range_st[i] = st[i];
  439. range_end[i] = min(chunk_st[i] * C[i] + C[i] - 1, endp[i]);
  440. }
  441. for (i = j = 0; i < n; i++)
  442. j += chunk_st[i] * PC[i];
  443. temp_seek = srcOff = j * csize * bsize;
  444. if (lo_lseek(fp, srcOff, SEEK_SET) < 0)
  445. RETURN_NULL;
  446. jj = n - 1;
  447. for (i = 0; i < n; chunk_off[i++] = 0)
  448. ;
  449. words_read = 0;
  450. temp_seek = 0;
  451. do
  452. {
  453. /* Write chunk (chunk_st) to output buffer */
  454. mda_get_range(n, array_span, range_st, range_end);
  455. mda_get_offset_values(n, adist, PA, array_span);
  456. mda_get_offset_values(n, cdist, PCHUNK, array_span);
  457. for (i = 0; i < n; range[i] = range_st[i] - st[i], i++);
  458. bptr = tuple2linear(n, range, PA);
  459. for (i = 0; i < n; range[i++] = 0);
  460. j = n - 1;
  461. bptr *= bsize;
  462. if (isDestLO)
  463. {
  464. if (lo_lseek((int) destfp, bptr, SEEK_SET) < 0)
  465. RETURN_NULL;
  466. }
  467. else
  468. destfp = baseDestFp + bptr;
  469. for (i = 0, block_seek = 0; i < n; i++)
  470. block_seek += (range_st[i] - (chunk_st[i] + chunk_off[i])
  471.    * C[i]) * PCHUNK[i];
  472. if (dist[jj] + block_seek + temp_seek)
  473. {
  474. temp = (dist[jj] * csize + block_seek + temp_seek) * bsize;
  475. srcOff += temp;
  476. if (lo_lseek(fp, srcOff, SEEK_SET) < 0)
  477. RETURN_NULL;
  478. }
  479. for (i = n - 1, to_read = bsize; i >= 0;
  480.  to_read *= min(C[i], array_span[i]), i--)
  481. if (cdist[i] || adist[i])
  482. break;
  483. do
  484. {
  485. if (cdist[j])
  486. {
  487. srcOff += (cdist[j] * bsize);
  488. if (lo_lseek(fp, srcOff, SEEK_SET) < 0)
  489. RETURN_NULL;
  490. }
  491. block_seek += cdist[j];
  492. bptr += adist[j] * bsize;
  493. if (isDestLO)
  494. {
  495. if (lo_lseek((int) destfp, bptr, SEEK_SET) < 0)
  496. RETURN_NULL;
  497. }
  498. else
  499. destfp = baseDestFp + bptr;
  500. temp = _LOtransfer((char **) &destfp, to_read, 1, (char **) &fp, 1, isDestLO);
  501. if (temp < to_read)
  502. RETURN_NULL;
  503. srcOff += to_read;
  504. words_read += to_read;
  505. bptr += to_read;
  506. block_seek += (to_read / bsize);
  507. /*
  508.  * compute next tuple in *range
  509.  */
  510. {
  511. int x;
  512. if (!(i + 1))
  513. j = -1;
  514. else
  515. {
  516. range[i] = (range[i] + 1) % array_span[i];
  517. for (x = i; x * (!range[x]); x--)
  518. range[x - 1] = (range[x - 1] + 1) % array_span[x - 1];
  519. if (x)
  520. j = x;
  521. else
  522. {
  523. if (range[0])
  524. j = 0;
  525. else
  526. j = -1;
  527. }
  528. }
  529. }
  530. /*
  531.  * end of compute next tuple -- j is set to -1 if tuple
  532.  * generation is over
  533.  */
  534. } while (j != -1);
  535. block_seek = csize - block_seek;
  536. temp_seek = block_seek;
  537. jj = next_tuple(n, chunk_off, chunk_span);
  538. if (jj == -1)
  539. break;
  540. range_st[jj] = (chunk_st[jj] + chunk_off[jj]) * C[jj];
  541. range_end[jj] = min(range_st[jj] + C[jj] - 1, endp[jj]);
  542. for (i = jj + 1; i < n; i++)
  543. {
  544. range_st[i] = st[i];
  545. range_end[i] = min((chunk_st[i] + chunk_off[i]) * C[i] + C[i] - 1, endp[i]);
  546. }
  547. } while (jj != -1);
  548. return words_read;
  549. }
  550. /*------------------------------------------------------------------------
  551.  * _ReadChunkArray1El
  552.  *  returns one element of the chunked array as specified by the index "st"
  553.  *  the chunked file descriptor is "fp"
  554.  *-------------------------------------------------------------------------
  555.  */
  556. struct varlena *
  557. _ReadChunkArray1El(int *st,
  558.    int bsize,
  559.    int fp,
  560.    ArrayType *array,
  561.    bool *isNull)
  562. {
  563. int i,
  564. j,
  565. n,
  566. temp,
  567. srcOff;
  568. int chunk_st[MAXDIM];
  569. int    *C,
  570. csize,
  571.    *dim,
  572.    *lb;
  573. int PCHUNK[MAXDIM],
  574. PC[MAXDIM];
  575. CHUNK_INFO *A = (CHUNK_INFO *) ARR_DATA_PTR(array);
  576. n = ARR_NDIM(array);
  577. lb = ARR_LBOUND(array);
  578. C = A->C;
  579. dim = ARR_DIMS(array);
  580. csize = C[n - 1];
  581. PC[n - 1] = 1;
  582. temp = dim[n - 1] / C[n - 1];
  583. for (i = n - 2; i >= 0; i--)
  584. {
  585. PC[i] = PC[i + 1] * temp;
  586. temp = dim[i] / C[i];
  587. csize *= C[i];
  588. }
  589. for (i = 0; i < n; st[i] -= lb[i], i++);
  590. mda_get_prod(n, C, PCHUNK);
  591. array2chunk_coord(n, C, st, chunk_st);
  592. for (i = j = 0; i < n; i++)
  593. j += chunk_st[i] * PC[i];
  594. srcOff = j * csize;
  595. for (i = 0; i < n; i++)
  596. srcOff += (st[i] - chunk_st[i] * C[i]) * PCHUNK[i];
  597. srcOff *= bsize;
  598. if (lo_lseek(fp, srcOff, SEEK_SET) < 0)
  599. RETURN_NULL;
  600. #ifdef LOARRAY
  601. return (struct varlena *) LOread(fp, bsize);
  602. #endif
  603. return (struct varlena *) 0;
  604. }