⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bfile.cpp

📁 在动态库中实现异步导出大数据量的oracle数据
💻 CPP
字号:
#include "stdafx.h"

#define __OCICPP_INTERNAL_USE_

#include "BFile.h"
#include "OraError.h"

/*!
  \class OCICPP::BFile
  \brief Binary external Files within the Oracle Server's filesystem

  BFiles are a mean of representing large objects within the Oracle Server.
  Alternatives are Lob and TLob. The main difference between BFiles od the one
  side and Lobs and TLobs on the other is, that the BFile does not reside 
  within the database's tablespaces (whereas Lobs and TLobs do). A BFile is
  located  within the server's filesystem and thus has to be accessed there.

  Storing data externally has some consequences:
  \arg The operating system is responsible for storing these files
  \arg The is no way the Oracle Server can preserve these files
  \arg Since there is a maximum number of open file handles, one can never be
       sure to have access to a BFile, even if it exists
  \arg BFiles are (currently?) read-only

  On the other hand, there are some advantages:
  \arg The BFile does not populate the database tables (which may resolve in
       smaller databases)
  \arg BFiles are a mean of separating classical database content (in terms of
       entities that have a relation) from multimedia data (which typically is
       a rather large amount of data)

  Oracle states, that there is hardly any measurable performace difference
  between the large-object datatypes Lob, TLob and BFile, which leaves the
  decission of the type to be used to the user again. However, current policy
  seems to discourage the usage of BFiles.

  However, they can be very useful (according to the documentation writters
  humble opinion) if used carefully (and even reduce work). Imagine a database
  storing mainly textual data, where additionally some images or even audio-
  or video-sequences are incorporated. Lets again assume that the whole 
  application is designed in client-server architecture, so that there is a
  big database which may be accessed from (many, perhaps browser) clients.
  BFiles then offer the capability to map data not stored within the database
  throught the Oracle-Layer to the client, so that there is no need to code a
  broker of any kind - this leaves one backend less.

  Let's look, if there's a Video-Archive identified by \c ZUSE and retreive
  the length of the BFILE-column called \b DATA (Error-Handling within this
  example is admittedly a little too rought...)
  \code
  using namespace OCICPP;

  int len = 0;
  try {
    Cursor cur;
    con->execQuery( "select * from MM_ARCHIVE WHERE TYPE='V' and ID='ZUSE'",
                    cur );
    if ( cur.fetch() ) {
      BFile bfile;
      cur.getFILE( "DATA", bfile );
      bfile.open();
      len = bfile.getLen();
      bfile.close();
      bfile.drop();
    }
    cur.drop();
  } catch ( OraError ) {
  }
  \endcode

  For additional information on how to create BFILE entities within the
  database, please refer to the Oracle Server Documentation (\b BFILENAME and
  \b CREATE \b DIRECTORY ).
 */

/*!
  Construct an unbound bfile entity.
 */
OCICPP::BFile::BFile():type(OCICPP::BFILE) {
	init(0,0,0);
}

OCICPP::BFile::BFile(OCISvcCtx *svcctx,OCILobLocator *lob_desc,OCIError *err): type(OCICPP::BFILE) {
	init(svcctx,lob_desc,err);
}

void OCICPP::BFile::init(OCISvcCtx *svcctx,OCILobLocator *lob_desc,OCIError *err) {
	boolean flg;
	svchp=svcctx;
	lob=lob_desc;
	errhp=err;
	offset=1;
	needLobFree=false;
	if(svchp && errhp) {
		DEBUG(DLEV_DEBUG,"Obtaining BFile len\n");
		CHECKERR(errhp,OCILobFileExists(svchp,errhp,lob,&flg));
		if(flg==FALSE) {
			throw OraError("OCICCPLIB: File not exist on server",OCICPPERROR);
		}
		CHECKERR(errhp,OCILobGetLength(svchp,errhp,lob,(ub4 *)&len));
		
		DEBUG(DLEV_DEBUG,"BFile len is %d\n",len);
	} else {
		len=0;
	}
}

void OCICPP::BFile::init(OCIEnv *envhp,OCISvcCtx *svcctx,OCIError *err,
						const string &dir,const string &fname) {
	boolean flg;
	svchp=svcctx;
	errhp=err;
	offset=1;
	needLobFree=true;
	if(envhp && svchp && errhp) {
		DEBUG(DLEV_DEBUG,"Creating BFILE\n");
		if(OCIDescriptorAlloc(envhp,(void **)&lob,OCI_DTYPE_FILE,0,0)!=OCI_SUCCESS) {
			throw OraError("OCICPPLIB: Cannot make new BFILE: Handle Allocation failed",OCICPPERROR);
		}			
		CHECKERR(errhp,
			OCILobFileSetName(envhp,errhp,&lob,
							(OraText*)const_cast<char *>(dir.c_str()),
							dir.size(),
							(OraText *)const_cast<char *>(fname.c_str()),
							fname.size()));
										
		CHECKERR(errhp,OCILobFileExists(svchp,errhp,lob,&flg));
		if(flg==FALSE) {
			throw OraError("OCICCPLIB: File not exist on server",OCICPPERROR);
		}
		CHECKERR(errhp,OCILobGetLength(svchp,errhp,lob,(ub4 *)&len));
		
		DEBUG(DLEV_DEBUG,"BFile len is %d\n",len);
	} else {
		len=0;
	}
}

/*!
  Destruct a bfile entity.
 */
OCICPP::BFile::~BFile() {
	/* nothing to be done yet 
	   all real work is in ~Cursor
	   See TODO about how it should work ..
	*/
	drop();
}

/*!
  Drop a BFile entity. The Oracle Descriptior is freed on demand leaving the
  BFile instance ready for being reused.
 */
void OCICPP::BFile::drop() {
	if(needLobFree) {
		OCIDescriptorFree(lob,OCI_DTYPE_FILE);
	}
}

/*!
  Set the position for reading/writing within a bfile.

  \param dir may be \b OCICPP::LOB_SET, \b OCICPP::LOB_CUR or \b OCICPP::LOB_END . 
  \arg LOB_SET \a new_offset from begining of the BFile. \a offset may not be
           greater than Bfile's length ( getLen() ).
  \arg LOB_CUR modifies the access point within the BFile relative to the current
           position. \a current position \a + \a offset may not exceed the
           BFile's length
  \arg LOB_END sets the position from the end of the BFile.
  \param new_offset is the new distance relative to the given direction \a dir
*/
void OCICPP::BFile::seek(unsigned new_offset,OCICPP::LobDirection dir) {
	if((!len && new_offset>0) ||
	   ((dir==OCICPP::LOB_END ||dir==OCICPP::LOB_SET) && new_offset>len) ||
	   (dir==OCICPP::LOB_CUR && (new_offset+offset-1)>len)) {
		throw OraError("OCICPPLIB: Cannot seek: offset out of range",OCICPPERROR);
	}
	if(dir==OCICPP::LOB_SET) offset=new_offset+1;
	else if(dir==OCICPP::LOB_END) offset=len-new_offset+1;
	else if(dir==OCICPP::LOB_CUR) offset=offset+new_offset;
	else throw OraError("OCICPPLIB: Cannot seek: Unknown direction",OCICPPERROR);
}

/*!
  Retuns the current position from the start of the BFile. For this position,
  the inequation 0 <= tell() < getLen() holds.
 */
unsigned OCICPP::BFile::tell() {
	return offset-1;
}

/*!
  Open a BFile. Before accessing, such a BFile has to be opened. Please keep
  in mind, that there is maximum number of simultaneously opened file handles
  withing the Oracle Server process.
 */
void OCICPP::BFile::open() {
	CHECKERR(errhp,OCILobFileOpen(svchp,errhp,lob,OCI_FILE_READONLY));
}

/*!
  Close a previously opened BFile. This operation sets one file handle free
  again on the Oracle Server again.
 */
void OCICPP::BFile::close() {
	CHECKERR(errhp,OCILobFileClose(svchp,errhp,lob));
}

/*!
  Read a sequence of \a buf_len bytes from the BFile into the buffer \a buf.
  The amount of bytes actually transfered is being returned.
 */
unsigned OCICPP::BFile::read(void * buf,int buf_len) {
	unsigned off;
	unsigned actread=buf_len;
	off=offset;
	CHECKERR(errhp,OCILobRead(svchp,errhp,lob,(ub4 *)&actread,(ub4)off,buf,(ub4)buf_len,0,
			   (sb4 (*)(void *,const void *, ub4, ub1)) 0,(ub2) 0, (ub1) SQLCS_IMPLICIT));
	offset+=actread;
	return actread;
}

/*!
  Retreive the total amount of data stored within this BFile.
 */
unsigned OCICPP::BFile::getLen() const {
	return len;
}


	
		

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -