SqlLob::~SqlLob() { // According to the Oracle 10g documentation we should try to free // implicit created temporary LOBs as soon as possible. if (isTemporary()) { sword res = OCICALL(OCILobFreeTemporary(_conn._svc_ctx, _conn._env._errh, _loc)); oci_check_error(__TROTL_HERE__, _conn._env._errh, res); } sword res = OCICALL(OCIDescriptorFree(_loc, OCI_DTYPE_LOB)); oci_check_error(__TROTL_HERE__, _conn._env, res); };
static void oci8_lob_free(oci8_base_t *base) { oci8_lob_t *lob = (oci8_lob_t *)base; boolean is_temporary; if (have_OCILobIsTemporary && lob->svchp != NULL && OCILobIsTemporary(oci8_envhp, oci8_errhp, lob->base.hp.lob, &is_temporary) == OCI_SUCCESS && is_temporary) { /* FIXME: This may stall the GC. */ OCILobFreeTemporary(lob->svchp, oci8_errhp, lob->base.hp.lob); } lob->svc = Qnil; lob->svchp = NULL; }
void DownloadFileWithCompression(struct ORACLEALLINONE *oraAllInOne, char* pDirectory, int compressionLevel, char* pRemoteFile, char* pLocalFile, int isKeepPartial, int isResume) { FILE *fp; sword ociResult; ub4 vCompressionLevel; ub8 vSkipBytes; char blobBuffer[ORA_BLOB_BUFFER_SIZE]; oraub8 vSize; int zRet; z_stream zStrm; unsigned char zOut[ORA_BLOB_BUFFER_SIZE]; #ifndef _WIN32 int showProgress; char progressLine[MAX_FMT_SIZE]; #endif int isStdUsed; off_t cnt; off_t sourceSize; struct stat fileStat; struct BINDVARIABLE oraBindsDownload[] = { { 0, SQLT_STR, ":directory", pDirectory, ORA_IDENTIFIER_SIZE + 1 }, { 0, SQLT_INT, ":compression_level", &vCompressionLevel, sizeof(vCompressionLevel) }, { 0, SQLT_STR, ":filename", pRemoteFile, MAX_FMT_SIZE }, { 0, SQLT_BLOB, ":blob", &oraAllInOne->blob, sizeof(oraAllInOne->blob) }, { 0, SQLT_INT, ":skipbytes", &vSkipBytes, sizeof(vSkipBytes) }, { 0 } }; struct ORACLESTATEMENT oraStmtDownload = { #include "downloadcompr.text" , 0, oraBindsDownload, NO_ORACLE_DEFINES }; vCompressionLevel = compressionLevel; isStdUsed = !strcmp(pLocalFile, "-"); if (isStdUsed) { isResume = 0; isKeepPartial = 1; } SetSessionAction(oraAllInOne, "GZIP_AND_DOWNLOAD: GZIP"); if (OCIDescriptorAlloc(oraAllInOne->envhp, (void**)&oraAllInOne->blob, OCI_DTYPE_LOB, 0, 0)) { ExitWithError(oraAllInOne, RET_OCIINIT, ERROR_NONE, "Failed to allocate BLOB\n"); } cnt = 0; vSkipBytes = 0; if (isResume) { if (!stat(pLocalFile, &fileStat)) vSkipBytes = cnt = fileStat.st_size; if (!cnt) isResume = 0; } #ifndef _WIN32 showProgress = 1; if (!isatty(STDOUT_FILENO) || isStdUsed) showProgress = 0; if (showProgress) start_longops_meter(oraAllInOne, 0, 1); #endif PrepareStmtAndBind(oraAllInOne, &oraStmtDownload); ociResult = ExecuteStmt(oraAllInOne); #ifndef _WIN32 if (showProgress) stop_longops_meter(); #endif if (ociResult) ExitWithError(oraAllInOne, RET_ORA, ERROR_OCI, "Failed to compress file in oracle directory\n"); #ifndef _WIN32 if (showProgress) { if (OCILobGetLength2(oraAllInOne->svchp[0], oraAllInOne->errhp, oraAllInOne->blob, (oraub8*)&sourceSize)) ExitWithError(oraAllInOne, RET_ORA, ERROR_OCI, "Error getting BLOB length\n"); strcpy(progressLine, "TRANSFER & GUNZIP: "); strncat(progressLine, basename(pLocalFile), MAX_FMT_SIZE - 1 - strlen(progressLine)); start_progress_meter(progressLine, sourceSize, &cnt); } #endif SetSessionAction(oraAllInOne, "GZIP_AND_DOWNLOAD: DOWNLOAD"); if (!isStdUsed && (fp = fopen(pLocalFile, isResume ? "ab" : "wb")) == NULL) { ExitWithError(oraAllInOne, RET_FS, ERROR_OS, "Error opening a local file for writing\n"); } if (isStdUsed) fp = stdout; zStrm.zalloc = Z_NULL; zStrm.zfree = Z_NULL; zStrm.opaque = Z_NULL; zStrm.avail_in = 0; zStrm.next_in = Z_NULL; zRet = inflateInit2(&zStrm, 16+MAX_WBITS); if (zRet != Z_OK) { if (!isStdUsed) fclose(fp); ExitWithError(oraAllInOne, RET_ZLIB, ERROR_NONE, "ZLIB initialization failed\n"); } vSize = 0; ociResult = OCILobRead2(oraAllInOne->svchp[0], oraAllInOne->errhp, oraAllInOne->blob, &vSize, 0, 1, blobBuffer, ORA_BLOB_BUFFER_SIZE, OCI_FIRST_PIECE, 0, 0, 0, 0); while (ociResult == OCI_NEED_DATA || ociResult == OCI_SUCCESS) { cnt += vSize; zStrm.avail_in = vSize; zStrm.next_in = blobBuffer; do { zStrm.avail_out = ORA_BLOB_BUFFER_SIZE; zStrm.next_out = zOut; zRet = inflate(&zStrm, Z_NO_FLUSH); switch (zRet) { case Z_STREAM_ERROR: case Z_NEED_DICT: case Z_DATA_ERROR: case Z_MEM_ERROR: (void)inflateEnd(&zStrm); if (!isStdUsed) fclose(fp); ExitWithError(oraAllInOne, RET_ZLIB, ERROR_NONE, "ZLIB inflate failed: %d, size %d\n", zRet, vSize); } fwrite(zOut, sizeof(unsigned char), ORA_BLOB_BUFFER_SIZE - zStrm.avail_out, fp); if (ferror(fp)) { (void)inflateEnd(&zStrm); if (!isStdUsed) fclose(fp); ExitWithError(oraAllInOne, RET_DONOTEXIT, ERROR_OS, "Error writing to a local file\n"); if (!isKeepPartial) { if (unlink(pLocalFile)) ExitWithError(oraAllInOne, RET_FS, ERROR_OS, "Could not remove partial file %s\n", pLocalFile); } ExitWithError(oraAllInOne, RET_FS, ERROR_NONE, 0); } } while (zStrm.avail_out == 0); if (ociResult == OCI_SUCCESS) break; ociResult = OCILobRead2(oraAllInOne->svchp[0], oraAllInOne->errhp, oraAllInOne->blob, &vSize, 0, 1, blobBuffer, ORA_BLOB_BUFFER_SIZE, OCI_NEXT_PIECE, 0, 0, 0, 0); } #ifndef _WIN32 if (showProgress) stop_progress_meter(); #endif inflateEnd(&zStrm); if (!isStdUsed) fclose(fp); if (ociResult != OCI_SUCCESS) { ExitWithError(oraAllInOne, RET_ORA, ERROR_OCI, "Error reading BLOB\n"); } ReleaseStmt(oraAllInOne); SetSessionAction(oraAllInOne, 0); OCILobFreeTemporary(oraAllInOne->svchp[0], oraAllInOne->errhp, oraAllInOne->blob); if (OCIDescriptorFree(oraAllInOne->blob, OCI_DTYPE_LOB)) { ExitWithError(oraAllInOne, RET_OCIINIT, ERROR_NONE, "Failed to free BLOB\n"); } oraAllInOne->blob = 0; } void UploadFileWithCompression(struct ORACLEALLINONE *oraAllInOne, char* pDirectory, int compressionLevel, char* pRemoteFile, char* pLocalFile, int isKeepPartial, int isResume) { FILE *fp; sword ociResult; char blobBuffer[ORA_BLOB_BUFFER_SIZE]; oraub8 vSize; ub8 vSkippedBytes; char vOpenMode[3]; ub1 piece; int zRet, zFlush; z_stream zStrm; unsigned char zIn[ORA_BLOB_BUFFER_SIZE]; #ifndef _WIN32 int showProgress; char progressLine[MAX_FMT_SIZE]; #endif int isStdUsed; off_t cnt; off_t sourceSize; struct stat fileStat; int isError; struct ORACLEFILEATTR oracleFileAttr; struct BINDVARIABLE oraBindsUpload[] = { { 0, SQLT_STR, ":directory", pDirectory, ORA_IDENTIFIER_SIZE + 1 }, { 0, SQLT_STR, ":filename", pRemoteFile, MAX_FMT_SIZE }, { 0, SQLT_STR, ":openmode", vOpenMode, sizeof(vOpenMode) }, { 0, SQLT_INT, ":file_size", &sourceSize, sizeof(sourceSize) }, { 0, SQLT_INT, ":skipped", &vSkippedBytes, sizeof(vSkippedBytes) }, { 0, SQLT_BLOB, ":blob", &oraAllInOne->blob, sizeof(oraAllInOne->blob) }, { 0 } }; struct ORACLESTATEMENT oraStmtUpload = { #include "uploadcompr.text" , 0, oraBindsUpload, NO_ORACLE_DEFINES }; isStdUsed = !strcmp(pLocalFile, "-"); if (isStdUsed) isResume = 0; SetSessionAction(oraAllInOne, "UPLOAD_AND_GUNZIP: UPLOAD"); if (OCIDescriptorAlloc(oraAllInOne->envhp, (void**)&oraAllInOne->blob, OCI_DTYPE_LOB, 0, 0)) { ExitWithError(oraAllInOne, RET_OCIINIT, ERROR_NONE, "Failed to allocate BLOB\n"); } if (OCILobCreateTemporary(oraAllInOne->svchp[0], oraAllInOne->errhp, oraAllInOne->blob, OCI_DEFAULT, 0, OCI_TEMP_BLOB, TRUE/*cache*/, OCI_DURATION_SESSION)) { ExitWithError(oraAllInOne, RET_ORA, ERROR_OCI, "Failed to create temporary BLOB\n"); } piece = OCI_FIRST_PIECE; #ifndef _WIN32 showProgress = 1; if (!isatty(STDOUT_FILENO) || isStdUsed) showProgress = 0; #endif cnt = vSkippedBytes = 0; if (isResume) { GetOracleFileAttr(oraAllInOne, pDirectory, pRemoteFile, &oracleFileAttr); if (oracleFileAttr.bExists) cnt = vSkippedBytes = oracleFileAttr.length; if (!cnt) isResume = 0; } #ifndef _WIN32 if (showProgress) { stat(pLocalFile, &fileStat); sourceSize = fileStat.st_size; strcpy(progressLine, "GZIP & TRANSFER: "); strncat(progressLine, basename(pLocalFile), MAX_FMT_SIZE - 1 - strlen(progressLine)); start_progress_meter(progressLine, sourceSize, &cnt); } #endif if (!isStdUsed && (fp = fopen(pLocalFile, "rb")) == NULL) { ExitWithError(oraAllInOne, RET_FS, ERROR_OS, "Error opening a local file for reading\n"); } if (isStdUsed) fp = stdin; if (cnt > 0) { if (fseek(fp, cnt, SEEK_SET)) { fclose(fp); ExitWithError(oraAllInOne, RET_FS, ERROR_OS, "Error setting reading position in a local file\n"); } } zStrm.zalloc = Z_NULL; zStrm.zfree = Z_NULL; zStrm.opaque = Z_NULL; zRet = deflateInit2(&zStrm, compressionLevel ? compressionLevel : Z_DEFAULT_COMPRESSION, Z_DEFLATED, 16+MAX_WBITS, 8, Z_DEFAULT_STRATEGY); if (zRet != Z_OK) { if (!isStdUsed) fclose(fp); ExitWithError(oraAllInOne, RET_ZLIB, ERROR_NONE, "ZLIB initialization failed\n"); } while (!feof(fp)) { zStrm.avail_in = fread(zIn, sizeof(unsigned char), sizeof(zIn), fp); cnt += zStrm.avail_in; if (ferror(fp)) { (void)deflateEnd(&zStrm); if (!isStdUsed) fclose(fp); ExitWithError(oraAllInOne, RET_FS, ERROR_OS, "Error reading from a local file\n"); } zFlush = feof(fp) ? Z_FINISH : Z_NO_FLUSH; zStrm.next_in = zIn; do { zStrm.avail_out = ORA_BLOB_BUFFER_SIZE; zStrm.next_out = blobBuffer; zRet = deflate(&zStrm, zFlush); if (zRet != Z_OK && zRet != Z_STREAM_END && zRet != Z_BUF_ERROR) { (void)deflateEnd(&zStrm); if (!isStdUsed) fclose(fp); ExitWithError(oraAllInOne, RET_ZLIB, ERROR_NONE, "ZLIB deflate failed: %d, size %d\n", zRet, zStrm.avail_in); } if (zRet == Z_STREAM_END) piece = (piece == OCI_FIRST_PIECE) ? OCI_ONE_PIECE : OCI_LAST_PIECE; vSize = (piece == OCI_ONE_PIECE) ? ORA_BLOB_BUFFER_SIZE - zStrm.avail_out : 0; if (zStrm.avail_out == ORA_BLOB_BUFFER_SIZE) continue; ociResult = OCILobWrite2(oraAllInOne->svchp[0], oraAllInOne->errhp, oraAllInOne->blob, &vSize, 0, 1, blobBuffer, ORA_BLOB_BUFFER_SIZE - zStrm.avail_out, piece, 0, 0, 0, 0); if (ociResult != OCI_NEED_DATA && ociResult) { (void)deflateEnd(&zStrm); if (!isStdUsed) fclose(fp); ExitWithError(oraAllInOne, RET_ORA, ERROR_OCI, "Error writing to BLOB\n"); } if (piece == OCI_FIRST_PIECE) piece = OCI_NEXT_PIECE; } while (zStrm.avail_out == 0); } #ifndef _WIN32 if (showProgress) stop_progress_meter(); #endif deflateEnd(&zStrm); if (!isStdUsed) fclose(fp); isError = 0; strcpy(vOpenMode, isResume ? "ab" : "wb"); SetSessionAction(oraAllInOne, "UPLOAD_AND_GUNZIP: GUNZIP"); #ifndef _WIN32 if (showProgress) start_longops_meter(oraAllInOne, 0, 1); #endif PrepareStmtAndBind(oraAllInOne, &oraStmtUpload); ociResult = ExecuteStmt(oraAllInOne); #ifndef _WIN32 if (showProgress) stop_longops_meter(); #endif if (ociResult) { ExitWithError(oraAllInOne, RET_DONOTEXIT, ERROR_OCI, "Failed to decompress file in oracle directory\n"); isError = 1; } else ReleaseStmt(oraAllInOne); SetSessionAction(oraAllInOne, 0); OCILobFreeTemporary(oraAllInOne->svchp[0], oraAllInOne->errhp, oraAllInOne->blob); if (OCIDescriptorFree(oraAllInOne->blob, OCI_DTYPE_LOB)) { if (!isError) ExitWithError(oraAllInOne, RET_DONOTEXIT, ERROR_NONE, "Failed to free BLOB\n"); isError = 1; } oraAllInOne->blob = 0; if (isError) { if (!isKeepPartial) Rm(oraAllInOne, pDirectory, pRemoteFile); ExitWithError(oraAllInOne, RET_ORA, ERROR_NONE, 0); } }
/* ruby 1.9 */ sword oci8_call_without_gvl(oci8_svcctx_t *svcctx, void *(*func)(void *), void *data) { OCIError *errhp = oci8_errhp; if (!NIL_P(svcctx->executing_thread)) { rb_raise(rb_eRuntimeError /* FIXME */, "executing in another thread"); } if (!svcctx->suppress_free_temp_lobs) { oci8_temp_lob_t *lob = svcctx->temp_lobs; while (lob != NULL) { oci8_temp_lob_t *lob_next = lob->next; if (svcctx->non_blocking) { free_temp_lob_arg_t arg; sword rv; arg.svcctx = svcctx; arg.svchp = svcctx->base.hp.svc; arg.errhp = errhp; arg.lob = lob->lob; svcctx->executing_thread = rb_thread_current(); #ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL rv = (sword)(VALUE)rb_thread_call_without_gvl(free_temp_lob, &arg, oci8_unblock_func, svcctx); #else rv = (sword)rb_thread_blocking_region((VALUE(*)(void*))free_temp_lob, &arg, oci8_unblock_func, svcctx); #endif if (rv == OCI_ERROR) { if (oci8_get_error_code(errhp) == 1013) { rb_raise(eOCIBreak, "Canceled by user request."); } } } else { OCILobFreeTemporary(svcctx->base.hp.svc, errhp, lob->lob); } OCIDescriptorFree(lob->lob, OCI_DTYPE_LOB); xfree(lob); svcctx->temp_lobs = lob = lob_next; } } if (svcctx->non_blocking) { sword rv; svcctx->executing_thread = rb_thread_current(); /* Note: executing_thread is cleard at the end of the blocking function. */ #ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL rv = (sword)(VALUE)rb_thread_call_without_gvl(func, data, oci8_unblock_func, svcctx); #else rv = (sword)rb_thread_blocking_region((VALUE(*)(void*))func, data, oci8_unblock_func, svcctx); #endif if (rv == OCI_ERROR) { if (oci8_get_error_code(errhp) == 1013) { rb_raise(eOCIBreak, "Canceled by user request."); } } return rv; } else { return (sword)(VALUE)func(data); } }