home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / lib / libpq / be-fsstubs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  11.8 KB  |  473 lines

  1. /*#define FSDB 1*/
  2. /* ----------------------------------------------------------------
  3.  *   FILE
  4.  *    be-fsstubs.c
  5.  *    
  6.  *   DESCRIPTION
  7.  *    support for filesystem operations on large objects
  8.  *
  9.  *   SUPPORT ROUTINES
  10.  *
  11.  *   INTERFACE ROUTINES
  12.  * int LOopen(char *fname, int mode);
  13.  * int LOclose(int fd);
  14.  * bytea LOread(int fd, int len);
  15.  * int LOwrite(int fd, char *buf);
  16.  * int LOlseek(int fd,int offset,int whence);
  17.  * int LOcreat(char *path, int mode,int objtype);
  18.  * int LOtell(int fd);
  19.  * int LOftruncate(int fd);
  20.  * bytea LOstat(int fd);
  21.  * int LOmkdir(char *path, int mode);
  22.  * int LOrmdir(char *path);
  23.  * int LOunlink(char *path);
  24.  *    
  25.  *   NOTES
  26.  *      This should be moved to a more appropriate place.  It is here
  27.  *      for lack of a better place.
  28.  *
  29.  *   IDENTIFICATION
  30.  *    $Header: /private/postgres/src/lib/libpq/RCS/be-fsstubs.c,v 1.14 1992/06/15 08:23:27 dpassage Exp $
  31.  * ----------------------------------------------------------------
  32.  */
  33.  
  34. /*
  35.  * Builtin functions for open/close/read/write operations on large objects.
  36.  *
  37.  * The functions of the same name in the ADT implementations of large objects
  38.  * should be made less general, e.g. GregLOOpen, etc.  These stubs are meant 
  39.  * to handle any large object.
  40.  *
  41.  * These functions operate in the current portal variable context, which 
  42.  * means the large object descriptors hang around between transactions and 
  43.  * are not deallocated until explicitly closed, or until the portal is 
  44.  * closed.
  45.  *
  46.  *
  47.  * int LOopen(char *fname, int mode);
  48.  *     return file descriptor that can subsequently be used in LOread/write/
  49.  *     close.
  50.  * int LOclose(int fd);
  51.  * bytea LOread(int fd, int len);
  52.  * int LOwrite(int fd, char *buf);
  53.  * int LOlseek(int fd,int offset,int whence);
  54.  * int LOcreat(char *path, int mode, int objtype);
  55.  * int LOtell(int fd);
  56.  * int LOftruncate(int fd);
  57.  * bytea LOstat(int fd);
  58.  * int LOmkdir(char *path, int mode);
  59.  * int LOrmdir(char *path);
  60.  * int LOunlink(char *path);
  61.  *
  62.  * Implementation:
  63.  *    LOopen given filename and mode (ignored):
  64.  *       map filename to OID of large object (FilenameToOID).
  65.  *       map OID to large object cookie (LOassocOIDandLargeObjDesc).
  66.  *       call LO dependent open on cookie.
  67.  *       allocate a file descriptor in table corresponding to result of open.
  68.  *       return file descriptor.
  69.  *      (if at any step, there is an error, e.g. OID not found, table full,
  70.  *       return an error.)
  71.  *    LOclose given file descriptor
  72.  *       call LO dependent close on cookie.
  73.  *       deallocate file descriptor in table.
  74.  *    LOread given file descriptor, length
  75.  *       map length to object dependent addressing, e.g. bytes to blocks.
  76.  *       call LO dependent read on cookie.
  77.  *       return variable length byte array.
  78.  *    LOwrite given file descriptor, byte array
  79.  *       map length of array to object dependent addressing
  80.  *       call LO dependent write on cookie (possibly reading and re-writing
  81.  *       partial blocks).
  82.  */
  83.  
  84. #include "tmp/c.h"
  85. #include "tmp/postgres.h"
  86. #include "tmp/simplelists.h"
  87. #include "tmp/libpq.h"
  88. #include "tmp/libpq-fs.h"
  89. /*#include "utils/large_object.h"*/
  90. #include "utils/mcxt.h"
  91. #include "catalog/pg_lobj.h"
  92. #include "catalog/pg_naming.h"
  93.  
  94. #include "utils/log.h"
  95.  
  96. static GlobalMemory fscxt = NULL;
  97.  
  98. /* HAck protos.  move to .h later */
  99. /* lo_api.c */
  100. void *LOCreate ARGS((char *path , int open_mode ));
  101. void *LOOpen ARGS((struct varlena *object , int open_mode ));
  102. void LOClose ARGS((void *obj_desc ));
  103. int LOUnixStat ARGS((void *obj_desc , struct pgstat *stbuf ));
  104. int LOSeek ARGS((void *obj_desc , int offset , int whence ));
  105. int LOTell ARGS((void *obj_desc ));
  106. int LORead ARGS((void *obj_desc , char *buf , int n ));
  107. int LOWrite ARGS((void *obj_desc , char *buf , int n ));
  108.  
  109. /* inv_api.c */
  110. void *inv_create ARGS((char *name, int mode ));
  111. void  *inv_open ARGS((struct varlena *object, int flags ));
  112. int inv_read ARGS((void *f , char *dbuf , int nbytes ));
  113. int inv_write ARGS((void *f , char *dbuf , int nbytes ));
  114. void inv_close ARGS((void *f ));
  115. int inv_seek ARGS((void *f , int loc ));
  116. int inv_tell ARGS((void *obj_desc ));
  117. int inv_stat ARGS((void *obj_desc , struct pgstat *stbuf ));
  118.  
  119. static int noaction() { return  -1; } /* error */
  120. static void *noactionnull() { return (void *) NULL; } /* error */
  121. /* These should be easy to code */
  122.  
  123. /* This is ordered upon objtype values.  Make sure that entries are sorted
  124.    properly. */
  125.  
  126. static struct {
  127.     int bigcookie; 
  128. #define SMALL_INT 0     /* is integer wrapped in a varlena */
  129. #define BIG 1  /* must be passed as varlena*/
  130.     void *(*LOcreate) ARGS((char *,int)); /* name,mode -> runtime-cookie */
  131.     void *(*LOopen) ARGS((void *,int)); /* persistant-cookie,mode -> runtime-cookie */
  132.     void (*LOclose) ARGS((void *)); /* runtime-cookie */
  133.     int (*LOread) ARGS((void *,char *,int)); /* rt-cookie,buf,length -> bytecount*/
  134.     int (*LOwrite) ARGS((void *,char *,int)); /*rt-cookie,buf,length -> bytecount*/
  135.     int (*LOseek) ARGS((void *,int,int)); /*rt-cookie,offset,whence -> bytecount */
  136.     int (*LOtell) ARGS((void *)); /*rt-cookie ->bytecount*/
  137.     int (*LOunixstat) ARGS((void *,struct pgstat *)); /* rt-cookie,stat ->errorcode*/
  138. } LOprocs[] = {
  139.     /* Inversion */
  140.     { BIG, inv_create, inv_open, inv_close, inv_read, inv_write,
  141.     inv_seek, inv_tell, inv_stat},
  142.     /* Unix */
  143.     { BIG, LOCreate, LOOpen, LOClose, LORead, LOWrite,
  144.     LOSeek, LOTell, LOUnixStat}
  145. };
  146.  
  147.  
  148. int LOopen(fname,mode)
  149.      char *fname;
  150.      int mode;
  151. {
  152.     oid loOID;
  153.     struct varlena *lobjCookie;
  154.     char *lobjDesc;
  155.     int fd;
  156.     int objtype;
  157.     MemoryContext currentContext;
  158.  
  159. #if FSDB
  160.     elog(NOTICE,"LOopen(%s,%d)",fname,mode);
  161. #endif
  162.     loOID = FilenameToOID(fname);
  163.  
  164.     if (loOID == InvalidObjectId) { /* lookup failed */
  165.     if ((mode  & O_CREAT) != O_CREAT) {
  166. #if FSDB
  167.     elog(NOTICE,"LOopen lookup failed");
  168. #endif
  169.         return -1;
  170.     } else {
  171.         /* Have to choose a particular type */
  172.         objtype = Unix;
  173.         return LOcreat(fname,mode,objtype);
  174.     }
  175.     }
  176.     
  177.     lobjCookie = LOassocOIDandLargeObjDesc(&objtype,loOID);
  178.     
  179.     if (lobjCookie == NULL) { /* lookup failed, perhaps a dir? */
  180. #if FSDB
  181.     elog(NOTICE,"LOopen assoc failed");
  182. #endif
  183.     return -1;
  184.     } else {
  185. #if FSDB
  186.     elog(NOTICE,"LOopen assoc succeeded");
  187. #endif
  188.     }
  189.   
  190.     /* temp debug testing */
  191.     {
  192.     if (fscxt == NULL) {
  193.         fscxt = CreateGlobalMemory("Filesystem");
  194.     }
  195.     currentContext = MemoryContextSwitchTo((MemoryContext)fscxt);
  196. #if 0
  197.     /* switch context to portal cxt */
  198.     {
  199.         PortalEntry * curPort;
  200.         curPort = be_currentportal();
  201.         currentContext = MemoryContextSwitchTo(curPort->portalcxt);
  202.     }
  203. #endif
  204.     switch (LOprocs[objtype].bigcookie) {
  205.       case SMALL_INT:
  206.         lobjDesc = (char *)
  207.           LOprocs[objtype].LOopen((void *) *((int *)VARDATA(lobjCookie)),mode);
  208.         break;
  209.       case BIG: 
  210.         lobjDesc = (char *) LOprocs[objtype].LOopen(lobjCookie,mode);
  211.         break;
  212.     }
  213.         
  214.     if (lobjDesc == NULL) {
  215.         MemoryContextSwitchTo(currentContext);
  216. #if FSDB
  217.         elog(NOTICE,"LOopen objtype specific open failed");
  218. #endif
  219.         return -1;
  220.     }
  221.     fd = NewLOfd(lobjDesc,objtype);
  222.     /* switch context back to orig. */
  223.     MemoryContextSwitchTo(currentContext);
  224.     }
  225.     return fd;
  226. }
  227.  
  228. #define MAX_LOBJ_FDS 256
  229. char  *cookies[MAX_LOBJ_FDS];
  230. int lotype[MAX_LOBJ_FDS];
  231.  
  232. #if deadcode
  233. static int current_objaddr[MAX_LOBJ_FDS]; /* current address in LO's terms */
  234. static int current_objoffset[MAX_LOBJ_FDS]; /* offset in LO's terms */
  235. #endif
  236.  
  237. int LOclose(fd)
  238.      int fd;
  239. {
  240.     void DeleteLOfd();
  241.  
  242.     if (fd >= MAX_LOBJ_FDS) {
  243.     elog(WARN,"LOclose(%d) out of range",fd);
  244.     return -2;
  245.     }
  246.     if (cookies[fd] == NULL) {
  247.     elog(WARN,"LOclose(%d) invalid file descriptor",fd);
  248.     return -3;
  249.     }
  250. #if FSDB
  251.     elog(NOTICE,"LOclose(%d)",fd);
  252. #endif
  253.     /* Kemnitz large objects */
  254.     {
  255.     MemoryContext currentContext;
  256.     Assert(fscxt != NULL);
  257.     currentContext = MemoryContextSwitchTo((MemoryContext)fscxt);
  258.     
  259.     LOprocs[lotype[fd]].LOclose(cookies[fd]);
  260.  
  261.     MemoryContextSwitchTo(currentContext);
  262.     }
  263.     DeleteLOfd(fd);
  264.     return 0;
  265. }
  266.  
  267. /*
  268.  *  We assume the large object supports byte oriented reads and seeks so
  269.  *  that our work is easier.
  270.  */
  271. struct varlena *
  272. LOread(fd,len)
  273.      int fd;
  274.      int len;
  275. {
  276.     struct varlena *retval;
  277.     int bytestoread;
  278.     int totalread = 0;
  279.  
  280.     retval = (struct varlena *)palloc(sizeof(int32) + len);
  281.     totalread = LOprocs[lotype[fd]].LOread(cookies[fd],VARDATA(retval),len);
  282.     VARSIZE(retval) = totalread + sizeof(int32);
  283.  
  284.     return retval;
  285. }
  286.  
  287. int LOwrite(fd,wbuf)
  288.      int fd;
  289.      struct varlena *wbuf;
  290. {
  291.     int totalwritten;
  292.     int bytestowrite;
  293.  
  294.     bytestowrite = VARSIZE(wbuf) - sizeof(int32);
  295.     totalwritten = LOprocs[lotype[fd]].LOwrite(cookies[fd],VARDATA(wbuf),
  296.                            bytestowrite);
  297.     return totalwritten;
  298. }
  299.  
  300. int
  301. LOlseek(fd,offset,whence)
  302.      int fd,offset,whence;
  303. {
  304.     int pos;
  305.  
  306.     if (fd >= MAX_LOBJ_FDS) {
  307.     elog(WARN,"LOSeek(%d) out of range",fd);
  308.     return -2;
  309.     }
  310.     return LOprocs[lotype[fd]].LOseek(cookies[fd],offset,whence);
  311. }
  312.  
  313. int
  314. LOcreat(path,mode,objtype)
  315.      char *path;
  316.      int mode;
  317.      int objtype;
  318. {
  319.     char *lobjDesc;
  320.     int fd;
  321.     MemoryContext currentContext;
  322.  
  323.     /* prevent garbage code */
  324.     if (objtype != Inversion && objtype != Unix)
  325.     objtype = Unix;
  326.  
  327.     if (fscxt == NULL) {
  328.     fscxt = CreateGlobalMemory("Filesystem");
  329.     }
  330.  
  331.     currentContext = MemoryContextSwitchTo((MemoryContext)fscxt);
  332.  
  333.     lobjDesc = (char *) LOprocs[objtype].LOcreate(path,mode);
  334.  
  335.     if (lobjDesc == NULL) {
  336.     MemoryContextSwitchTo(currentContext);
  337.     return -1;
  338.     }
  339.  
  340.     fd = NewLOfd(lobjDesc,objtype);
  341.  
  342.     /* switch context back to original memory context */
  343.     MemoryContextSwitchTo(currentContext);
  344.  
  345.     return fd;
  346. }
  347.  
  348. int LOtell(fd)
  349.      int fd;
  350. {
  351.     if (fd >= MAX_LOBJ_FDS) {
  352.     elog(WARN,"LOtell(%d) out of range",fd);
  353.     return -2;
  354.     }
  355.     if (cookies[fd] == NULL) {
  356.     elog(WARN,"LOtell(%d) cookie is NULL",fd);
  357.     return -3;
  358.     }
  359.     return LOprocs[lotype[fd]].LOtell(cookies[fd]);
  360. }
  361.  
  362. int LOftruncate()
  363. {
  364. }
  365.  
  366. struct varlena *
  367. LOstat(path)
  368.      char *path;
  369. {
  370.     struct varlena *ret;
  371.     struct pgstat *st;
  372.     unsigned int nblocks, byte_offset;
  373.     int len;
  374.     int pathOID;
  375.     len = sizeof(struct pgstat);
  376.     ret = (struct varlena *) palloc(len+sizeof(int32));
  377.     VARSIZE(ret) = len + sizeof(int32);
  378.     st = (struct pgstat *)VARDATA(ret);
  379.     bzero(st,len);    /* default values of 0 */
  380.  
  381.     pathOID =  FilenameToOID(path);
  382.     st->st_ino = pathOID;
  383.  
  384.     if (!LOisdir(path) && pathOID != InvalidObjectId) {
  385.     int fd = LOopen(path,O_RDONLY);
  386.     LOprocs[lotype[fd]].LOunixstat(cookies[fd],st);
  387.     LOclose(fd);
  388.     } else if (pathOID != InvalidObjectId) { /* isdir */
  389.     st->st_mode = S_IFDIR;
  390.     /* our directoiries don't exist in the filesystem, so give them
  391.        artificial permissions */
  392.     st->st_uid = getuid(); /* fake uid */
  393.     st->st_mode |= S_IRUSR|S_IWUSR|S_IXUSR;
  394.     } else {
  395.     VARSIZE(ret) = 9; /* 4 + 5 */
  396.     }
  397.  
  398.     return ret;
  399. }
  400.  
  401. /*
  402.  * LOrename can be found in naming.c
  403.  */
  404.  
  405. int LOmkdir(path,mode)
  406.      char *path;
  407.      int mode;
  408. {
  409.     oid oidf;
  410.     /* enter new pathname */
  411.     oidf = LOcreatOID(path,mode);
  412.     if (oidf == InvalidObjectId) {
  413.     return -1;
  414.     } else {
  415.     return 0;
  416.     }
  417. }
  418.  
  419. int LOrmdir(path)
  420.      char *path;
  421. {
  422.     if (!LOisdir(path))
  423.       return -1;
  424.     else if (!LOisemptydir(path))
  425.       return -1;
  426.     else {
  427.       LOunlink(path);
  428.       return 0;
  429.     }
  430. }
  431.  
  432. int LOunlink(path)
  433.      char *path;
  434. {
  435.     /* remove large object descriptor */
  436.     /* remove naming entry */
  437.     oid deloid;
  438.     
  439.     deloid = LOunlinkOID(path);
  440.     if (deloid != InvalidObjectId) { /* remove associated file if any */
  441.     LOunassocOID(deloid);
  442.     }
  443. }
  444.  
  445. /*
  446.  * ------------------------------------
  447.  * Support routines for this file
  448.  * ------------------------------------
  449.  */
  450. int NewLOfd(lobjCookie,objtype)
  451.      char *lobjCookie;
  452.      int objtype;
  453. {
  454.     int i;
  455.  
  456.     for (i = 0; i < MAX_LOBJ_FDS; i++) {
  457.  
  458.     if (cookies[i] == NULL) {
  459.         cookies[i] = lobjCookie;
  460.         lotype[i] =  objtype;
  461.  
  462.         return i;
  463.     }
  464.     }
  465.     return -1;
  466. }
  467.  
  468. void DeleteLOfd(fd)
  469.      int fd;
  470. {
  471.     cookies[fd] = NULL;
  472. }
  473.