Mercurial > repos > youngkim > ezbamqc
comparison ezBAMQC/src/htslib/hfile_irods.c @ 0:dfa3745e5fd8
Uploaded
| author | youngkim |
|---|---|
| date | Thu, 24 Mar 2016 17:12:52 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:dfa3745e5fd8 |
|---|---|
| 1 /* hfile_irods.c -- iRODS backend for low-level file streams. | |
| 2 | |
| 3 Copyright (C) 2013, 2015 Genome Research Ltd. | |
| 4 | |
| 5 Author: John Marshall <jm18@sanger.ac.uk> | |
| 6 | |
| 7 Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 8 of this software and associated documentation files (the "Software"), to deal | |
| 9 in the Software without restriction, including without limitation the rights | |
| 10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 11 copies of the Software, and to permit persons to whom the Software is | |
| 12 furnished to do so, subject to the following conditions: | |
| 13 | |
| 14 The above copyright notice and this permission notice shall be included in | |
| 15 all copies or substantial portions of the Software. | |
| 16 | |
| 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| 20 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 22 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| 23 DEALINGS IN THE SOFTWARE. */ | |
| 24 | |
| 25 #include <stdlib.h> | |
| 26 #include <string.h> | |
| 27 #include <errno.h> | |
| 28 | |
| 29 #include "hfile_internal.h" | |
| 30 | |
| 31 #include <rcConnect.h> | |
| 32 #include <dataObjOpen.h> | |
| 33 #include <dataObjRead.h> | |
| 34 #include <dataObjWrite.h> | |
| 35 #include <dataObjFsync.h> | |
| 36 #include <dataObjLseek.h> | |
| 37 #include <dataObjClose.h> | |
| 38 | |
| 39 typedef struct { | |
| 40 hFILE base; | |
| 41 int descriptor; | |
| 42 } hFILE_irods; | |
| 43 | |
| 44 static int status_errno(int status) | |
| 45 { | |
| 46 switch (status) { | |
| 47 case SYS_NO_API_PRIV: return EACCES; | |
| 48 case SYS_MALLOC_ERR: return ENOMEM; | |
| 49 case SYS_OUT_OF_FILE_DESC: return ENFILE; | |
| 50 case SYS_BAD_FILE_DESCRIPTOR: return EBADF; | |
| 51 case CAT_NO_ROWS_FOUND: return ENOENT; | |
| 52 case CATALOG_ALREADY_HAS_ITEM_BY_THAT_NAME: return EEXIST; | |
| 53 default: return EIO; | |
| 54 } | |
| 55 } | |
| 56 | |
| 57 static void set_errno(int status) | |
| 58 { | |
| 59 int err = abs(status) % 1000; | |
| 60 errno = err? err : status_errno(status); | |
| 61 } | |
| 62 | |
| 63 static struct { | |
| 64 rcComm_t *conn; | |
| 65 rodsEnv env; | |
| 66 } irods = { NULL }; | |
| 67 | |
| 68 static void irods_exit() | |
| 69 { | |
| 70 (void) rcDisconnect(irods.conn); | |
| 71 irods.conn = NULL; | |
| 72 } | |
| 73 | |
| 74 static int irods_init() | |
| 75 { | |
| 76 rErrMsg_t err; | |
| 77 int ret; | |
| 78 | |
| 79 ret = getRodsEnv(&irods.env); | |
| 80 if (ret < 0) goto error; | |
| 81 | |
| 82 irods.conn = rcConnect(irods.env.rodsHost, irods.env.rodsPort, | |
| 83 irods.env.rodsUserName, irods.env.rodsZone, | |
| 84 NO_RECONN, &err); | |
| 85 if (irods.conn == NULL) { ret = err.status; goto error; } | |
| 86 | |
| 87 if (strcmp(irods.env.rodsUserName, PUBLIC_USER_NAME) != 0) { | |
| 88 ret = clientLogin(irods.conn); | |
| 89 if (ret != 0) goto error; | |
| 90 } | |
| 91 | |
| 92 // In the unlikely event atexit() fails, it's better to succeed here and | |
| 93 // carry on and do the I/O; then eventually when the program exits, we'll | |
| 94 // merely disconnect from the server uncleanly, as if we had aborted. | |
| 95 (void) atexit(irods_exit); | |
| 96 | |
| 97 return 0; | |
| 98 | |
| 99 error: | |
| 100 if (irods.conn) { (void) rcDisconnect(irods.conn); } | |
| 101 irods.conn = NULL; | |
| 102 set_errno(ret); | |
| 103 return -1; | |
| 104 } | |
| 105 | |
| 106 static ssize_t irods_read(hFILE *fpv, void *buffer, size_t nbytes) | |
| 107 { | |
| 108 hFILE_irods *fp = (hFILE_irods *) fpv; | |
| 109 openedDataObjInp_t args; | |
| 110 bytesBuf_t buf; | |
| 111 int ret; | |
| 112 | |
| 113 memset(&args, 0, sizeof args); | |
| 114 args.l1descInx = fp->descriptor; | |
| 115 args.len = nbytes; | |
| 116 | |
| 117 buf.buf = buffer; | |
| 118 buf.len = nbytes; | |
| 119 | |
| 120 ret = rcDataObjRead(irods.conn, &args, &buf); | |
| 121 if (ret < 0) set_errno(ret); | |
| 122 return ret; | |
| 123 } | |
| 124 | |
| 125 static ssize_t irods_write(hFILE *fpv, const void *buffer, size_t nbytes) | |
| 126 { | |
| 127 hFILE_irods *fp = (hFILE_irods *) fpv; | |
| 128 openedDataObjInp_t args; | |
| 129 bytesBuf_t buf; | |
| 130 int ret; | |
| 131 | |
| 132 memset(&args, 0, sizeof args); | |
| 133 args.l1descInx = fp->descriptor; | |
| 134 args.len = nbytes; | |
| 135 | |
| 136 buf.buf = (void *) buffer; // ...the iRODS API is not const-correct here | |
| 137 buf.len = nbytes; | |
| 138 | |
| 139 ret = rcDataObjWrite(irods.conn, &args, &buf); | |
| 140 if (ret < 0) set_errno(ret); | |
| 141 return ret; | |
| 142 } | |
| 143 | |
| 144 static off_t irods_seek(hFILE *fpv, off_t offset, int whence) | |
| 145 { | |
| 146 hFILE_irods *fp = (hFILE_irods *) fpv; | |
| 147 openedDataObjInp_t args; | |
| 148 fileLseekOut_t *out = NULL; | |
| 149 int ret; | |
| 150 | |
| 151 memset(&args, 0, sizeof args); | |
| 152 args.l1descInx = fp->descriptor; | |
| 153 args.offset = offset; | |
| 154 args.whence = whence; | |
| 155 | |
| 156 ret = rcDataObjLseek(irods.conn, &args, &out); | |
| 157 | |
| 158 if (out) { offset = out->offset; free(out); } | |
| 159 else offset = -1; | |
| 160 if (ret < 0) { set_errno(ret); return -1; } | |
| 161 return offset; | |
| 162 } | |
| 163 | |
| 164 static int irods_flush(hFILE *fpv) | |
| 165 { | |
| 166 // FIXME rcDataObjFsync() doesn't seem to function as expected. | |
| 167 // For now, flush is a no-op: see https://github.com/samtools/htslib/issues/168 | |
| 168 #if 0 | |
| 169 hFILE_irods *fp = (hFILE_irods *) fpv; | |
| 170 openedDataObjInp_t args; | |
| 171 int ret; | |
| 172 | |
| 173 memset(&args, 0, sizeof args); | |
| 174 args.l1descInx = fp->descriptor; | |
| 175 | |
| 176 ret = rcDataObjFsync(irods.conn, &args); | |
| 177 if (ret < 0) set_errno(ret); | |
| 178 return ret; | |
| 179 #endif | |
| 180 return 0; | |
| 181 } | |
| 182 | |
| 183 static int irods_close(hFILE *fpv) | |
| 184 { | |
| 185 hFILE_irods *fp = (hFILE_irods *) fpv; | |
| 186 openedDataObjInp_t args; | |
| 187 int ret; | |
| 188 | |
| 189 memset(&args, 0, sizeof args); | |
| 190 args.l1descInx = fp->descriptor; | |
| 191 | |
| 192 ret = rcDataObjClose(irods.conn, &args); | |
| 193 if (ret < 0) set_errno(ret); | |
| 194 return ret; | |
| 195 } | |
| 196 | |
| 197 static const struct hFILE_backend irods_backend = | |
| 198 { | |
| 199 irods_read, irods_write, irods_seek, irods_flush, irods_close | |
| 200 }; | |
| 201 | |
| 202 hFILE *hopen_irods(const char *filename, const char *mode) | |
| 203 { | |
| 204 hFILE_irods *fp; | |
| 205 rodsPath_t path; | |
| 206 dataObjInp_t args; | |
| 207 int ret; | |
| 208 | |
| 209 // Initialise the iRODS connection if this is the first use. | |
| 210 if (irods.conn == NULL) { if (irods_init() < 0) return NULL; } | |
| 211 | |
| 212 if (strncmp(filename, "irods:", 6) == 0) filename += 6; | |
| 213 else { errno = EINVAL; return NULL; } | |
| 214 | |
| 215 fp = (hFILE_irods *) hfile_init(sizeof (hFILE_irods), mode, 0); | |
| 216 if (fp == NULL) return NULL; | |
| 217 | |
| 218 strncpy(path.inPath, filename, MAX_NAME_LEN-1); | |
| 219 path.inPath[MAX_NAME_LEN-1] = '\0'; | |
| 220 | |
| 221 ret = parseRodsPath(&path, &irods.env); | |
| 222 if (ret < 0) goto error; | |
| 223 | |
| 224 memset(&args, 0, sizeof args); | |
| 225 strcpy(args.objPath, path.outPath); | |
| 226 args.openFlags = hfile_oflags(mode); | |
| 227 if (args.openFlags & O_CREAT) { | |
| 228 args.createMode = 0666; | |
| 229 addKeyVal(&args.condInput, DEST_RESC_NAME_KW,irods.env.rodsDefResource); | |
| 230 } | |
| 231 | |
| 232 ret = rcDataObjOpen(irods.conn, &args); | |
| 233 if (ret < 0) goto error; | |
| 234 fp->descriptor = ret; | |
| 235 | |
| 236 fp->base.backend = &irods_backend; | |
| 237 return &fp->base; | |
| 238 | |
| 239 error: | |
| 240 hfile_destroy((hFILE *) fp); | |
| 241 set_errno(ret); | |
| 242 return NULL; | |
| 243 } |
