📄 ncbi_connection.c
字号:
CONN_NOT_NULL(Flush); if (conn->state == eCONN_Unusable) return eIO_InvalidArg; /* perform open, if not opened yet */ if (conn->state != eCONN_Open && (status = s_Open(conn)) != eIO_Success) return status; assert(conn->state == eCONN_Open && conn->meta.list != 0); /* call current connector's "FLUSH" method */ if ( !conn->meta.flush ) return eIO_Success; status = conn->meta.flush(conn->meta.c_flush, conn->w_timeout == kDefaultTimeout ? conn->meta.default_timeout : conn->w_timeout); if (status != eIO_Success) CONN_LOG(eLOG_Warning, "[CONN_Flush] Cannot flush data"); return status;}/* Read or peek data from the input queue, see CONN_Read() */static EIO_Status s_CONN_Read(CONN conn, void* buf, size_t size, size_t* n_read, int/*bool*/ peek){ EIO_Status status; assert(*n_read == 0); /* check if the read method is specified at all */ if ( !conn->meta.read ) { status = eIO_NotSupported; CONN_LOG(eLOG_Error, "[CONN_Read] Unable to read data"); return status; } /* read data from the internal peek buffer, if any */ *n_read = peek ? BUF_Peek(conn->buf, buf, size) : BUF_Read(conn->buf, buf, size); if (*n_read == size) return eIO_Success; buf = (char*) buf + *n_read; /* read data from the connection */ {{ size_t x_read = 0; /* call current connector's "READ" method */ status = conn->meta.read(conn->meta.c_read, buf, size- *n_read,&x_read, conn->r_timeout == kDefaultTimeout ? conn->meta.default_timeout : conn->r_timeout); *n_read += x_read; if (peek && x_read) /* save data in the internal peek buffer */ verify(BUF_Write(&conn->buf, buf, x_read)); }} if (status != eIO_Success) { if ( *n_read ) { CONN_LOG(eLOG_Trace, "[CONN_Read] Read error"); status = eIO_Success; } else if ( size ) { CONN_LOG(status == eIO_Closed ? eLOG_Trace : status == eIO_Timeout ? eLOG_Warning : eLOG_Error, "[CONN_Read] Cannot read data"); } } return status;}/* Persistently read data from the input queue, see CONN_Read() */static EIO_Status s_CONN_ReadPersist(CONN conn, void* buf, size_t size, size_t* n_read){ EIO_Status status; assert(*n_read == 0); for (;;) { size_t x_read = 0; status = s_CONN_Read(conn, (char*) buf + *n_read, size - *n_read, &x_read, 0/*no peek*/); *n_read += x_read; if (*n_read == size || status != eIO_Success) break; /* flush the unwritten output data (if any) */ if ( conn->meta.flush ) { conn->meta.flush(conn->meta.c_flush, conn->r_timeout == kDefaultTimeout ? conn->meta.default_timeout : conn->r_timeout); } } return status;}extern EIO_Status CONN_Read(CONN conn, void* buf, size_t size, size_t* n_read, EIO_ReadMethod how){ EIO_Status status; if (!n_read) return eIO_InvalidArg; *n_read = 0; if (size && !buf) return eIO_InvalidArg; CONN_NOT_NULL(Read); if (conn->state == eCONN_Unusable) return eIO_InvalidArg; /* perform open, if not opened yet */ if (conn->state != eCONN_Open && (status = s_Open(conn)) != eIO_Success) return status; assert(conn->state == eCONN_Open && conn->meta.list != 0); /* flush the unwritten output data (if any) */ if ( conn->meta.flush ) { conn->meta.flush(conn->meta.c_flush, conn->r_timeout == kDefaultTimeout ? conn->meta.default_timeout : conn->r_timeout); } /* now do read */ switch (how) { case eIO_ReadPlain: return s_CONN_Read(conn, buf, size, n_read, 0/*no peek*/); case eIO_ReadPeek: return s_CONN_Read(conn, buf, size, n_read, 1/*peek*/); case eIO_ReadPersist: return s_CONN_ReadPersist(conn, buf, size, n_read); default: break; } return eIO_Unknown;}extern EIO_Status CONN_ReadLine(CONN conn, char* line, size_t size, size_t* n_read ){ EIO_Status status = eIO_Success; char w[1024]; size_t len; if (!n_read) return eIO_InvalidArg; *n_read = 0; if (size && !line) return eIO_InvalidArg; CONN_NOT_NULL(ReadLine); /* perform open, if not opened yet */ if (conn->state != eCONN_Open && (status = s_Open(conn)) != eIO_Success) return status; assert(conn->state == eCONN_Open && conn->meta.list != 0); /* flush the unwritten output data (if any) */ if ( conn->meta.flush ) { conn->meta.flush(conn->meta.c_flush, conn->r_timeout == kDefaultTimeout ? conn->meta.default_timeout : conn->r_timeout); } len = 0; while (len < size) { size_t i; size_t x_read = 0; size_t x_size = BUF_Size(conn->buf); char* buf = size - len < sizeof(w) ? w : &line[len]; if (x_size == 0 || x_size > sizeof(w)) x_size = sizeof(w); status = s_CONN_Read(conn, buf, x_size, &x_read, 0); for (i = 0; i < x_read; i++) { if (buf == w) line[len] = buf[i]; if (buf[i] == '\n') { line[len] = '\0'; i++; break; } else if (++len >= size) { i++; break; } } if (i < x_read) { if (!BUF_PushBack(&conn->buf, &buf[i], x_read - i)) status = eIO_Unknown; break; } else if (status != eIO_Success) { if (len < size) line[len] = '\0'; break; } } *n_read = len; return status;}extern EIO_Status CONN_Status(CONN conn, EIO_Event dir){ CONN_NOT_NULL(Status); if (conn->state == eCONN_Unusable || !conn->meta.list) return eIO_Unknown; if (dir != eIO_Read && dir != eIO_Write) return eIO_InvalidArg; if (conn->state == eCONN_Closed) return eIO_Closed; if ( !conn->meta.status ) return eIO_NotSupported; return conn->meta.status(conn->meta.c_status, dir);}extern EIO_Status CONN_Close(CONN conn){ FConnCallback func = 0; void* data = 0; CONN_NOT_NULL(Close); if (conn->state != eCONN_Unusable) { func = conn->cbs[eCONN_OnClose].func; data = conn->cbs[eCONN_OnClose].data; } /* allow close CB only once */ memset(&conn->cbs[eCONN_OnClose], 0, sizeof(conn->cbs[eCONN_OnClose])); /* call it! */ if ( func ) (*func)(conn, eCONN_OnClose, data); /* now close the connection - this also makes it "eCONN_Unusable" */ if ( conn->meta.list ) CONN_ReInit(conn, 0); BUF_Destroy(conn->buf); conn->buf = 0; free(conn); return eIO_Success;}extern EIO_Status CONN_SetCallback(CONN conn, ECONN_Callback type, const SCONN_Callback* new_cb, SCONN_Callback* old_cb){ int i = (int) type; if (i >= CONN_N_CALLBACKS) return eIO_InvalidArg; CONN_NOT_NULL(SetCallback); if ( old_cb ) *old_cb = conn->cbs[i]; if ( new_cb ) conn->cbs[i] = *new_cb; return eIO_Success;}#ifdef IMPLEMENTED__CONN_WaitAsync/* Internal handler(wrapper for the user-provided handler) for CONN_WaitAsync() */static void s_ConnectorAsyncHandler(SConnectorAsyncHandler* data, EIO_Event event, EIO_Status status){ /* handle the async. event */ data->handler(data->conn, event, status, data->data); /* reset */ verify(CONN_WaitAsync(data->conn, eIO_ReadWrite, 0, 0, 0) == eIO_Success);}extern EIO_Status CONN_WaitAsync(CONN conn, EIO_Event event, FConnAsyncHandler handler, void* data, FConnAsyncCleanup cleanup){ EIO_Status status; CONNECTOR x_connector = conn->connector; SConnectorAsyncHandler* x_data = &conn->async_data; CONN_NOT_NULL(WaitAsync); /* perform connect, if not connected yet */ if (!conn->connected && (status = s_Connect(conn)) != eIO_Success) return status; /* reset previous handler, cleanup its data */ /* (call current connector's "WAIT_ASYNC" method with NULLs) */ status = x_connector->vtable.wait_async ? x_connector->vtable.wait_async(x_connector->handle, 0, 0) : eIO_NotSupported; if (status != eIO_Success) { CONN_LOG(eLOG_Error, "[CONN_WaitAsync] Cannot reset the handler"); return status; } if ( x_data->cleanup ) x_data->cleanup(x_data->data); memset(x_data, '\0', sizeof(*x_data)); /* set new handler, if specified */ /* (call current connector's "WAIT_ASYNC" method with new handler/data) */ if ( !handler ) return eIO_Success; x_data->conn = conn; x_data->wait_event = event; x_data->handler = handler; x_data->data = data; x_data->cleanup = cleanup; status = x_connector->vtable.wait_async(x_connector->handle, s_ConnectorAsyncHandler, x_data); if (status != eIO_Success) { CONN_LOG(eLOG_Error, "[CONN_WaitAsync] Cannot set new handler"); } return status;}#endif /* IMPLEMENTED__CONN_WaitAsync *//* * -------------------------------------------------------------------------- * $Log: ncbi_connection.c,v $ * Revision 1000.3 2004/06/01 18:44:48 gouriano * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R6.42 * * Revision 6.42 2004/05/26 16:00:06 lavr * Minor status fixes in CONN_SetTimeout() and CONN_ReadLine() * * Revision 6.41 2004/05/24 20:19:19 lavr * Fix eIO_InvalidArg conditions (size and no buffer) * * Revision 6.40 2004/05/24 19:54:59 lavr * +CONN_ReadLine() * * Revision 6.39 2004/03/23 02:27:37 lavr * Code formatting * * Revision 6.38 2004/02/23 15:23:39 lavr * New (last) parameter "how" added in CONN_Write() API call * * Revision 6.37 2003/08/25 14:40:53 lavr * Employ new k..Timeout constants * * Revision 6.36 2003/05/31 05:18:26 lavr * Optimize on calling flush; do not require to have flush method * * Revision 6.35 2003/05/21 17:53:06 lavr * Better check for {0,0} timeout in CONN_Read() * * Revision 6.34 2003/05/20 21:21:45 lavr * CONN_Write(): log with different log levels on write errors * * Revision 6.33 2003/05/19 16:43:40 lavr * Bugfix in CONN_SetTimeout(); better close callback sequence * * Revision 6.32 2003/05/14 03:51:16 lavr * +CONN_Description() * * Revision 6.31 2003/05/12 18:33:21 lavr * Names of timeout variables uniformed * * Revision 6.30 2003/01/28 15:16:37 lavr * Fix "NULL" message not to contain double quotes in call names * * Revision 6.29 2003/01/17 19:44:46 lavr * Reduce dependencies * * Revision 6.28 2003/01/15 19:51:17 lavr * +CONN_PushBack() * * Revision 6.27 2002/09/19 19:43:46 lavr * Add more assert()'s and do not rely on CONN_Flush() to open in CONN_Read() * * Revision 6.26 2002/09/06 15:43:20 lavr * Bug fixes of late assignments in Read and Write; Flush changed to open * connection if not yet open; more error logging * * Revision 6.25 2002/08/07 16:32:32 lavr * Changed EIO_ReadMethod enums accordingly; log moved to end * * Revision 6.24 2002/04/26 16:30:26 lavr * Checks for kDefaultTimeout and use of default_timeout of meta-connector * * Revision 6.23 2002/04/24 21:18:04 lavr * Beautifying: pup open check before buffer check in CONN_Wait() * * Revision 6.22 2002/04/22 19:30:01 lavr * Do not put trace message on polling wait (tmo={0,0}) * More effective CONN_Read w/o repeatitive checkings for eIO_ReadPersist * * Revision 6.21 2002/03/22 22:17:01 lavr * Better check when formally timed out but technically polled in CONN_Wait() * * Revision 6.20 2002/02/05 22:04:12 lavr * Included header files rearranged * * Revision 6.19 2002/01/30 20:10:56 lavr * Remove *n_read = 0 assignment in s_CONN_Read; replace it with assert() * * Revision 6.18 2001/08/20 20:13:15 vakatov * CONN_ReInit() -- Check connection handle for NULL (it was missed in R6.17) * * Revision 6.17 2001/08/20 20:00:43 vakatov * CONN_SetTimeout() to return "EIO_Status". * CONN_***() -- Check connection handle for NULL. * * Revision 6.16 2001/07/10 15:08:35 lavr * Edit for style * * Revision 6.15 2001/06/29 21:06:46 lavr * BUGFIX: CONN_LOG now checks for non-NULL get_type virtual function * * Revision 6.14 2001/06/28 22:00:48 lavr * Added function: CONN_SetCallback * Added callback: eCONN_OnClose * * Revision 6.13 2001/06/07 17:54:36 lavr * Modified exit branch in s_CONN_Read() * * Revision 6.12 2001/05/30 19:42:44 vakatov * s_CONN_Read() -- do not issue warning if requested zero bytes * (by A.Lavrentiev) * * Revision 6.11 2001/04/24 21:29:04 lavr * kDefaultTimeout is used everywhere when timeout is not set explicitly * * Revision 6.10 2001/02/26 22:52:44 kans * Initialize x_read in s_CONN_Read * * Revision 6.9 2001/02/26 16:32:01 kans * Including string.h instead of cstring * * Revision 6.8 2001/02/25 21:41:50 kans * Include <cstring> on Mac to get memset * * Revision 6.7 2001/02/09 17:34:18 lavr * CONN_GetType added; severities of some messages changed * * Revision 6.6 2001/01/25 16:55:48 lavr * CONN_ReInit bugs fixed * * Revision 6.5 2001/01/23 23:10:53 lavr * Typo corrected in description of connection structure * * Revision 6.4 2001/01/12 23:51:38 lavr * Message logging modified for use LOG facility only * * Revision 6.3 2001/01/03 22:29:59 lavr * CONN_Status implemented * * Revision 6.2 2000/12/29 17:52:59 lavr * Adapted to use new connector structure; modified to have * Internal tri-state {Unusable | Open | Closed }. * * Revision 6.1 2000/03/24 22:53:34 vakatov * Initial revision * * Revision 6.4 1999/11/01 16:14:23 vakatov * s_CONN_Read() -- milder error levels when hitting EOF * * Revision 6.3 1999/04/05 15:32:53 vakatov * CONN_Wait(): be more mild and discrete about the posted error severity * * Revision 6.1 1999/04/01 21:48:09 vakatov * Fixed for the change in spec: "n_written/n_read" args in * CONN_Write/Read to be non-NULL and "*n_written / *n_read" := 0 * * Revision 6.0 1999/03/25 23:04:57 vakatov * Initial revision * * ========================================================================== */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -