@@ -93,6 +93,16 @@ struct ConnectionImpl
9393 void prepare_auth (std::string_view user, std::string_view passwd);
9494 void commit_auth (std::string_view user, std::string_view passwd);
9595
96+ void hasSentBytes (size_t bytes);
97+ void hasNotRecvBytes (size_t bytes);
98+ bool hasDataToSend ();
99+ bool hasDataToDecode ();
100+
101+ DecodeStatus processResponse (int req_sync, Response<BUFFER> *result);
102+ int decodeGreeting ();
103+
104+ void inputBufGC ();
105+
96106 Connector<BUFFER, NetProvider> &connector;
97107 BUFFER inBuf;
98108 static constexpr size_t GC_STEP_CNT = 100 ;
@@ -199,6 +209,123 @@ ConnectionImpl<BUFFER, NetProvider>::commit_auth(std::string_view user, std::str
199209 connector.readyToSend (this );
200210}
201211
212+ template <class BUFFER , class NetProvider >
213+ void
214+ ConnectionImpl<BUFFER, NetProvider>::hasSentBytes(size_t bytes)
215+ {
216+ // dropBack()/dropFront() interfaces require number of bytes be greater
217+ // than zero so let's check it first.
218+ if (bytes > 0 )
219+ getOutBuf ().dropFront (bytes);
220+ }
221+
222+ template <class BUFFER , class NetProvider >
223+ void
224+ ConnectionImpl<BUFFER, NetProvider>::hasNotRecvBytes(size_t bytes)
225+ {
226+ if (bytes > 0 )
227+ getInBuf ().dropBack (bytes);
228+ }
229+
230+ template <class BUFFER , class NetProvider >
231+ bool
232+ ConnectionImpl<BUFFER, NetProvider>::hasDataToSend()
233+ {
234+ // We drop content of input buffer once it has been sent. So to detect
235+ // if there's any data to send it's enough to check buffer's emptiness.
236+ return !getOutBuf ().empty ();
237+ }
238+
239+ template <class BUFFER , class NetProvider >
240+ bool
241+ ConnectionImpl<BUFFER, NetProvider>::hasDataToDecode()
242+ {
243+ assert (endDecoded < getInBuf ().end () || endDecoded == getInBuf ().end ());
244+ return endDecoded != getInBuf ().end ();
245+ }
246+
247+ template <class BUFFER , class NetProvider >
248+ void
249+ ConnectionImpl<BUFFER, NetProvider>::inputBufGC()
250+ {
251+ if (gc_step++ % ConnectionImpl<BUFFER, NetProvider>::GC_STEP_CNT == 0 ) {
252+ LOG_DEBUG (" Flushed input buffer of the connection %p" , this );
253+ getInBuf ().flush ();
254+ }
255+ }
256+
257+ template <class BUFFER , class NetProvider >
258+ DecodeStatus
259+ ConnectionImpl<BUFFER, NetProvider>::processResponse(int req_sync, Response<BUFFER> *result)
260+ {
261+ // Decode response. In case of success - fill in feature map
262+ // and adjust end-of-decoded data pointer. Call GC if needed.
263+ if (!getInBuf ().has (endDecoded, MP_RESPONSE_SIZE))
264+ return DECODE_NEEDMORE;
265+
266+ Response<BUFFER> response;
267+ response.size = dec.decodeResponseSize ();
268+ if (response.size < 0 ) {
269+ LOG_ERROR (" Failed to decode response size" );
270+ // In case of corrupted response size all other data in the buffer
271+ // is likely to be decoded in the wrong way (since we don't
272+ // know how much bytes should be skipped). So let's simply
273+ // terminate here.
274+ std::abort ();
275+ }
276+ response.size += MP_RESPONSE_SIZE;
277+ if (!getInBuf ().has (endDecoded, response.size )) {
278+ // Response was received only partially. Reset decoder position
279+ // to the start of response to make this function re-entered.
280+ dec.reset (endDecoded);
281+ return DECODE_NEEDMORE;
282+ }
283+ if (dec.decodeResponse (response) != 0 ) {
284+ setError (" Failed to decode response, skipping bytes.." );
285+ endDecoded += response.size ;
286+ return DECODE_ERR;
287+ }
288+ LOG_DEBUG (" Header: sync=" , response.header .sync , " , code=" , response.header .code ,
289+ " , schema=" , response.header .schema_id );
290+ if (result != nullptr && response.header .sync == req_sync) {
291+ *result = std::move (response);
292+ } else {
293+ futures.insert ({response.header .sync , std::move (response)});
294+ }
295+ endDecoded += response.size ;
296+ inputBufGC ();
297+ return DECODE_SUCC;
298+ }
299+
300+ template <class BUFFER , class NetProvider >
301+ int
302+ ConnectionImpl<BUFFER, NetProvider>::decodeGreeting()
303+ {
304+ // TODO: that's not zero-copy, should be rewritten in that pattern.
305+ assert (getInBuf ().has (endDecoded, Iproto::GREETING_SIZE));
306+ char greeting_buf[Iproto::GREETING_SIZE];
307+ endDecoded.read ({greeting_buf, sizeof (greeting_buf)});
308+ dec.reset (endDecoded);
309+ if (parseGreeting (std::string_view {greeting_buf, Iproto::GREETING_SIZE}, greeting) != 0 )
310+ return -1 ;
311+ is_greeting_received = true ;
312+ LOG_DEBUG (" Version: " , greeting.version_id );
313+
314+ #ifndef NDEBUG
315+ // print salt in hex format.
316+ char hex_salt[Iproto::MAX_SALT_SIZE * 2 + 1 ];
317+ const char *hex = " 0123456789abcdef" ;
318+ for (size_t i = 0 ; i < greeting.salt_size ; i++) {
319+ uint8_t u = greeting.salt [i];
320+ hex_salt[i * 2 ] = hex[u / 16 ];
321+ hex_salt[i * 2 + 1 ] = hex[u % 16 ];
322+ }
323+ hex_salt[greeting.salt_size * 2 ] = 0 ;
324+ LOG_DEBUG (" Salt: " , hex_salt);
325+ #endif
326+ return 0 ;
327+ }
328+
202329/* * Each connection is supposed to be bound to a single socket. */
203330template <class BUFFER , class NetProvider >
204331class Connection
@@ -240,6 +367,8 @@ class Connection
240367 void flush ();
241368 size_t getFutureCount () const ;
242369
370+ bool hasDataToDecode ();
371+
243372 template <class T >
244373 rid_t call (const std::string &func, const T &args);
245374 rid_t ping ();
@@ -514,129 +643,11 @@ Connection<BUFFER, NetProvider>::getOutBuf()
514643 return impl->getOutBuf ();
515644}
516645
517- template <class BUFFER , class NetProvider >
518- void
519- hasSentBytes (ConnectionImpl<BUFFER, NetProvider> *conn, size_t bytes)
520- {
521- // dropBack()/dropFront() interfaces require number of bytes be greater
522- // than zero so let's check it first.
523- if (bytes > 0 )
524- conn->getOutBuf ().dropFront (bytes);
525- }
526-
527- template <class BUFFER , class NetProvider >
528- void
529- hasNotRecvBytes (ConnectionImpl<BUFFER, NetProvider> *conn, size_t bytes)
530- {
531- if (bytes > 0 )
532- conn->getInBuf ().dropBack (bytes);
533- }
534-
535646template <class BUFFER , class NetProvider >
536647bool
537- hasDataToSend (ConnectionImpl <BUFFER, NetProvider> *conn )
648+ Connection <BUFFER, NetProvider>::hasDataToDecode( )
538649{
539- // We drop content of input buffer once it has been sent. So to detect
540- // if there's any data to send it's enough to check buffer's emptiness.
541- return !conn->getOutBuf ().empty ();
542- }
543-
544- template <class BUFFER , class NetProvider >
545- bool
546- hasDataToDecode (Connection<BUFFER, NetProvider> &conn)
547- {
548- return hasDataToDecode (conn.getImpl ());
549- }
550-
551- template <class BUFFER , class NetProvider >
552- bool
553- hasDataToDecode (ConnectionImpl<BUFFER, NetProvider> *conn)
554- {
555- assert (conn->endDecoded < conn->getInBuf ().end () || conn->endDecoded == conn->getInBuf ().end ());
556- return conn->endDecoded != conn->getInBuf ().end ();
557- }
558-
559- template <class BUFFER , class NetProvider >
560- static void
561- inputBufGC (ConnectionImpl<BUFFER, NetProvider> *conn)
562- {
563- if (conn->gc_step ++ % ConnectionImpl<BUFFER, NetProvider>::GC_STEP_CNT == 0 ) {
564- LOG_DEBUG (" Flushed input buffer of the connection %p" , conn);
565- conn->getInBuf ().flush ();
566- }
567- }
568-
569- template <class BUFFER , class NetProvider >
570- DecodeStatus
571- processResponse (ConnectionImpl<BUFFER, NetProvider> *conn, int req_sync, Response<BUFFER> *result)
572- {
573- // Decode response. In case of success - fill in feature map
574- // and adjust end-of-decoded data pointer. Call GC if needed.
575- if (!conn->getInBuf ().has (conn->endDecoded , MP_RESPONSE_SIZE))
576- return DECODE_NEEDMORE;
577-
578- Response<BUFFER> response;
579- response.size = conn->dec .decodeResponseSize ();
580- if (response.size < 0 ) {
581- LOG_ERROR (" Failed to decode response size" );
582- // In case of corrupted response size all other data in the buffer
583- // is likely to be decoded in the wrong way (since we don't
584- // know how much bytes should be skipped). So let's simply
585- // terminate here.
586- std::abort ();
587-
588- }
589- response.size += MP_RESPONSE_SIZE;
590- if (!conn->getInBuf ().has (conn->endDecoded , response.size )) {
591- // Response was received only partially. Reset decoder position
592- // to the start of response to make this function re-entered.
593- conn->dec .reset (conn->endDecoded );
594- return DECODE_NEEDMORE;
595- }
596- if (conn->dec .decodeResponse (response) != 0 ) {
597- conn->setError (" Failed to decode response, skipping bytes.." );
598- conn->endDecoded += response.size ;
599- return DECODE_ERR;
600- }
601- LOG_DEBUG (" Header: sync=" , response.header .sync , " , code=" ,
602- response.header .code , " , schema=" , response.header .schema_id );
603- if (result != nullptr && response.header .sync == req_sync) {
604- *result = std::move (response);
605- } else {
606- conn->futures .insert ({response.header .sync , std::move (response)});
607- }
608- conn->endDecoded += response.size ;
609- inputBufGC (conn);
610- return DECODE_SUCC;
611- }
612-
613- template <class BUFFER , class NetProvider >
614- int
615- decodeGreeting (ConnectionImpl<BUFFER, NetProvider> *conn)
616- {
617- // TODO: that's not zero-copy, should be rewritten in that pattern.
618- assert (conn->getInBuf ().has (conn->endDecoded , Iproto::GREETING_SIZE));
619- char greeting_buf[Iproto::GREETING_SIZE];
620- conn->endDecoded .read ({greeting_buf, sizeof (greeting_buf)});
621- conn->dec .reset (conn->endDecoded );
622- if (parseGreeting (std::string_view {greeting_buf, Iproto::GREETING_SIZE}, conn->greeting ) != 0 )
623- return -1 ;
624- conn->is_greeting_received = true ;
625- LOG_DEBUG (" Version: " , conn->greeting .version_id );
626-
627- #ifndef NDEBUG
628- // print salt in hex format.
629- char hex_salt[Iproto::MAX_SALT_SIZE * 2 + 1 ];
630- const char *hex = " 0123456789abcdef" ;
631- for (size_t i = 0 ; i < conn->greeting .salt_size ; i++) {
632- uint8_t u = conn->greeting .salt [i];
633- hex_salt[i * 2 ] = hex[u / 16 ];
634- hex_salt[i * 2 + 1 ] = hex[u % 16 ];
635- }
636- hex_salt[conn->greeting .salt_size * 2 ] = 0 ;
637- LOG_DEBUG (" Salt: " , hex_salt);
638- #endif
639- return 0 ;
650+ return hasDataToDecode (getImpl ());
640651}
641652
642653// //////////////////////////BOX-like interface functions////////////////////////
0 commit comments