xrootd
XrdClFileStateHandler.hh
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
2 // Copyright (c) 2011-2014 by European Organization for Nuclear Research (CERN)
3 // Author: Lukasz Janyst <ljanyst@cern.ch>
4 //------------------------------------------------------------------------------
5 // This file is part of the XRootD software suite.
6 //
7 // XRootD is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Lesser General Public License as published by
9 // the Free Software Foundation, either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // XRootD is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public License
18 // along with XRootD. If not, see <http://www.gnu.org/licenses/>.
19 //
20 // In applying this licence, CERN does not waive the privileges and immunities
21 // granted to it by virtue of its status as an Intergovernmental Organization
22 // or submit itself to any jurisdiction.
23 //------------------------------------------------------------------------------
24 
25 #ifndef __XRD_CL_FILE_STATE_HANDLER_HH__
26 #define __XRD_CL_FILE_STATE_HANDLER_HH__
27 
30 #include "XrdCl/XrdClFileSystem.hh"
33 #include "XrdCl/XrdClOptional.hh"
34 #include "XrdSys/XrdSysPthread.hh"
35 #include "XrdSys/XrdSysPageSize.hh"
36 
37 #include <list>
38 #include <set>
39 #include <vector>
40 
41 #include <sys/uio.h>
42 #include <stdint.h>
43 
44 namespace
45 {
46  class PgReadHandler;
47  class PgReadRetryHandler;
48  class PgReadSubstitutionHandler;
49 }
50 
51 namespace XrdCl
52 {
53  class ResponseHandlerHolder;
54  class Message;
55 
56  //----------------------------------------------------------------------------
58  //----------------------------------------------------------------------------
59  struct PgReadFlags
60  {
61  //------------------------------------------------------------------------
63  //------------------------------------------------------------------------
64  enum Flags
65  {
66  None = 0, //< Nothing
67  Retry = XrdProto::kXR_pgRetry //< Retry reading currupted page
68 
69  };
70  };
72 
73  //----------------------------------------------------------------------------
75  //----------------------------------------------------------------------------
77  {
78  friend class ::PgReadHandler;
79  friend class ::PgReadRetryHandler;
80  friend class ::PgReadSubstitutionHandler;
81 
82  public:
83  //------------------------------------------------------------------------
85  //------------------------------------------------------------------------
87  {
93  CloseInProgress
94  };
95 
96  //------------------------------------------------------------------------
98  //------------------------------------------------------------------------
100 
101  //------------------------------------------------------------------------
106  //------------------------------------------------------------------------
107  FileStateHandler( bool useVirtRedirector );
108 
109  //------------------------------------------------------------------------
111  //------------------------------------------------------------------------
113 
114  //------------------------------------------------------------------------
124  //------------------------------------------------------------------------
125  XRootDStatus Open( const std::string &url,
126  uint16_t flags,
127  uint16_t mode,
128  ResponseHandler *handler,
129  uint16_t timeout = 0 );
130 
131  //------------------------------------------------------------------------
138  //------------------------------------------------------------------------
140  uint16_t timeout = 0 );
141 
142  //------------------------------------------------------------------------
152  //------------------------------------------------------------------------
153  XRootDStatus Stat( bool force,
154  ResponseHandler *handler,
155  uint16_t timeout = 0 );
156 
157 
158  //------------------------------------------------------------------------
173  //------------------------------------------------------------------------
174  XRootDStatus Read( uint64_t offset,
175  uint32_t size,
176  void *buffer,
177  ResponseHandler *handler,
178  uint16_t timeout = 0 );
179 
180  //------------------------------------------------------------------------
193  //------------------------------------------------------------------------
194  XRootDStatus PgRead( uint64_t offset,
195  uint32_t size,
196  void *buffer,
197  ResponseHandler *handler,
198  uint16_t timeout = 0 );
199 
200  //------------------------------------------------------------------------
211  //------------------------------------------------------------------------
212  XRootDStatus PgReadRetry( uint64_t offset,
213  uint32_t size,
214  size_t pgnb,
215  void *buffer,
216  PgReadHandler *handler,
217  uint16_t timeout = 0 );
218 
219  //------------------------------------------------------------------------
233  //------------------------------------------------------------------------
234  XRootDStatus PgReadImpl( uint64_t offset,
235  uint32_t size,
236  void *buffer,
237  uint16_t flags,
238  ResponseHandler *handler,
239  uint16_t timeout = 0 );
240 
241  //------------------------------------------------------------------------
251  //------------------------------------------------------------------------
252  XRootDStatus Write( uint64_t offset,
253  uint32_t size,
254  const void *buffer,
255  ResponseHandler *handler,
256  uint16_t timeout = 0 );
257 
258  //------------------------------------------------------------------------
268  //------------------------------------------------------------------------
269  XRootDStatus Write( uint64_t offset,
270  Buffer &&buffer,
271  ResponseHandler *handler,
272  uint16_t timeout = 0 );
273 
274  //------------------------------------------------------------------------
287  //------------------------------------------------------------------------
288  XRootDStatus Write( uint64_t offset,
289  uint32_t size,
290  Optional<uint64_t> fdoff,
291  int fd,
292  ResponseHandler *handler,
293  uint16_t timeout = 0 );
294 
295 
296  //------------------------------------------------------------------------
303  //------------------------------------------------------------------------
305  uint16_t timeout = 0 );
306 
307  //------------------------------------------------------------------------
315  //------------------------------------------------------------------------
316  XRootDStatus Truncate( uint64_t size,
317  ResponseHandler *handler,
318  uint16_t timeout = 0 );
319 
320  //------------------------------------------------------------------------
329  //------------------------------------------------------------------------
331  void *buffer,
332  ResponseHandler *handler,
333  uint16_t timeout = 0 );
334 
335  //------------------------------------------------------------------------
343  //------------------------------------------------------------------------
345  ResponseHandler *handler,
346  uint16_t timeout = 0 );
347 
348  //------------------------------------------------------------------------
358  //------------------------------------------------------------------------
359  XRootDStatus WriteV( uint64_t offset,
360  const struct iovec *iov,
361  int iovcnt,
362  ResponseHandler *handler,
363  uint16_t timeout = 0 );
364 
365  //------------------------------------------------------------------------
376  //------------------------------------------------------------------------
377  XRootDStatus Fcntl( const Buffer &arg,
378  ResponseHandler *handler,
379  uint16_t timeout = 0 );
380 
381  //------------------------------------------------------------------------
390  //------------------------------------------------------------------------
392  uint16_t timeout = 0 );
393 
394  //------------------------------------------------------------------------
405  //------------------------------------------------------------------------
406  XRootDStatus SetXAttr( const std::vector<xattr_t> &attrs,
407  ResponseHandler *handler,
408  uint16_t timeout = 0 );
409 
410  //------------------------------------------------------------------------
421  //------------------------------------------------------------------------
422  XRootDStatus GetXAttr( const std::vector<std::string> &attrs,
423  ResponseHandler *handler,
424  uint16_t timeout = 0 );
425 
426  //------------------------------------------------------------------------
437  //------------------------------------------------------------------------
438  XRootDStatus DelXAttr( const std::vector<std::string> &attrs,
439  ResponseHandler *handler,
440  uint16_t timeout = 0 );
441 
442  //------------------------------------------------------------------------
452  //------------------------------------------------------------------------
454  uint16_t timeout = 0 );
455 
456  //------------------------------------------------------------------------
458  //------------------------------------------------------------------------
459  void OnOpen( const XRootDStatus *status,
460  const OpenInfo *openInfo,
461  const HostList *hostList );
462 
463  //------------------------------------------------------------------------
465  //------------------------------------------------------------------------
466  void OnClose( const XRootDStatus *status );
467 
468  //------------------------------------------------------------------------
470  //------------------------------------------------------------------------
471  void OnStateError( XRootDStatus *status,
472  Message *message,
473  ResponseHandler *userHandler,
474  MessageSendParams &sendParams );
475 
476  //------------------------------------------------------------------------
478  //------------------------------------------------------------------------
479  void OnStateRedirection( const std::string &redirectUrl,
480  Message *message,
481  ResponseHandler *userHandler,
482  MessageSendParams &sendParams );
483 
484  //------------------------------------------------------------------------
486  //------------------------------------------------------------------------
488  Message *message,
489  AnyObject *response,
490  HostList *hostList );
491 
492  //------------------------------------------------------------------------
494  //------------------------------------------------------------------------
495  bool IsOpen() const;
496 
497  //------------------------------------------------------------------------
501  //------------------------------------------------------------------------
502  bool SetProperty( const std::string &name, const std::string &value );
503 
504  //------------------------------------------------------------------------
508  //------------------------------------------------------------------------
509  bool GetProperty( const std::string &name, std::string &value ) const;
510 
511  //------------------------------------------------------------------------
513  //------------------------------------------------------------------------
514  void Lock()
515  {
516  pMutex.Lock();
517  }
518 
519  //------------------------------------------------------------------------
521  //------------------------------------------------------------------------
522  void UnLock()
523  {
524  pMutex.UnLock();
525  }
526 
527  //------------------------------------------------------------------------
529  //------------------------------------------------------------------------
530  void Tick( time_t now );
531 
532  //------------------------------------------------------------------------
534  //------------------------------------------------------------------------
535  void TimeOutRequests( time_t now );
536 
537  //------------------------------------------------------------------------
539  //------------------------------------------------------------------------
541 
542  private:
543  //------------------------------------------------------------------------
544  // Helper for queuing messages
545  //------------------------------------------------------------------------
546  struct RequestData
547  {
548  RequestData(): request(0), handler(0) {}
550  const MessageSendParams &p ):
551  request(r), handler(h), params(p) {}
555  };
556  typedef std::list<RequestData> RequestList;
557 
558  //------------------------------------------------------------------------
565  //------------------------------------------------------------------------
566  template<typename T>
568  kXR_char options,
569  const std::vector<T> &attrs,
570  ResponseHandler *handler,
571  uint16_t timeout = 0 );
572 
573  //------------------------------------------------------------------------
575  //------------------------------------------------------------------------
576  Status SendOrQueue( const URL &url,
577  Message *msg,
578  ResponseHandler *handler,
579  MessageSendParams &sendParams );
580 
581  //------------------------------------------------------------------------
583  //------------------------------------------------------------------------
584  bool IsRecoverable( const XRootDStatus &stataus ) const;
585 
586  //------------------------------------------------------------------------
592  //------------------------------------------------------------------------
593  Status RecoverMessage( RequestData rd, bool callbackOnFailure = true );
594 
595  //------------------------------------------------------------------------
597  //------------------------------------------------------------------------
599 
600  //------------------------------------------------------------------------
601  // Send a close and ignore the response
602  //------------------------------------------------------------------------
603  XRootDStatus SendClose( uint16_t timeout );
604 
605  //------------------------------------------------------------------------
607  //------------------------------------------------------------------------
608  bool IsReadOnly() const;
609 
610  //------------------------------------------------------------------------
612  //------------------------------------------------------------------------
613  XRootDStatus ReOpenFileAtServer( const URL &url, uint16_t timeout );
614 
615  //------------------------------------------------------------------------
617  //------------------------------------------------------------------------
619 
620  //------------------------------------------------------------------------
622  //------------------------------------------------------------------------
624 
625  //------------------------------------------------------------------------
627  //------------------------------------------------------------------------
629 
630  //------------------------------------------------------------------------
632  //------------------------------------------------------------------------
634 
635  //------------------------------------------------------------------------
637  //------------------------------------------------------------------------
639  {
640  pOpenTime.tv_sec = 0; pOpenTime.tv_usec = 0;
641  pRBytes = 0;
642  pVRBytes = 0;
643  pWBytes = 0;
644  pVSegs = 0;
645  pRCount = 0;
646  pVRCount = 0;
647  pWCount = 0;
648  pCloseReason = Status();
649  }
650 
651  //------------------------------------------------------------------------
653  //------------------------------------------------------------------------
654  void MonitorClose( const XRootDStatus *status );
655 
656  //------------------------------------------------------------------------
662  //------------------------------------------------------------------------
664  Message *msg,
665  ResponseHandler *handler,
666  MessageSendParams &sendParams );
667 
668  //------------------------------------------------------------------------
670  //------------------------------------------------------------------------
671  XRootDStatus WriteKernelBuffer( uint64_t offset,
672  uint32_t length,
673  std::unique_ptr<XrdSys::KernelBuffer> kbuff,
674  ResponseHandler *handler,
675  uint16_t timeout );
676 
686  uint8_t *pFileHandle;
687  uint16_t pOpenMode;
688  uint16_t pOpenFlags;
690  std::set<Message*> pInTheFly;
691  uint64_t pSessionId;
698 
699  //------------------------------------------------------------------------
700  // Monitoring variables
701  //------------------------------------------------------------------------
702  timeval pOpenTime;
703  uint64_t pRBytes;
704  uint64_t pVRBytes;
705  uint64_t pWBytes;
706  uint64_t pVWBytes;
707  uint64_t pVSegs;
708  uint64_t pRCount;
709  uint64_t pVRCount;
710  uint64_t pWCount;
711  uint64_t pVWCount;
713 
714  //------------------------------------------------------------------------
715  // Holds the OpenHanlder used to issue reopen
716  // (there is only only OpenHandler reopening a file at a time)
717  //------------------------------------------------------------------------
718  ResponseHandlerHolder *pReOpenHandler;
719 
720  //------------------------------------------------------------------------
721  // Responsible for file:// operations on the local filesystem
722  //------------------------------------------------------------------------
724  };
725 }
726 
727 #endif // __XRD_CL_FILE_STATE_HANDLER_HH__
unsigned char kXR_char
Definition: XPtypes.hh:65
#define XRDOUC_ENUM_OPERATORS(T)
Definition: XrdOucEnum.hh:22
Definition: XrdClAnyObject.hh:33
Binary blob representation.
Definition: XrdClBuffer.hh:34
Handle the stateful operations.
Definition: XrdClFileStateHandler.hh:77
uint64_t pRBytes
Definition: XrdClFileStateHandler.hh:703
void OnStateRedirection(const std::string &redirectUrl, Message *message, ResponseHandler *userHandler, MessageSendParams &sendParams)
Handle stateful redirect.
Status SendOrQueue(const URL &url, Message *msg, ResponseHandler *handler, MessageSendParams &sendParams)
Send a message to a host or put it in the recovery queue.
XRootDStatus VectorWrite(const ChunkList &chunks, ResponseHandler *handler, uint16_t timeout=0)
ResponseHandlerHolder * pReOpenHandler
Definition: XrdClFileStateHandler.hh:718
URL * pDataServer
Definition: XrdClFileStateHandler.hh:682
std::set< Message * > pInTheFly
Definition: XrdClFileStateHandler.hh:690
void AfterForkChild()
Called in the child process after the fork.
XRootDStatus SetXAttr(const std::vector< xattr_t > &attrs, ResponseHandler *handler, uint16_t timeout=0)
URL * pStateRedirect
Definition: XrdClFileStateHandler.hh:684
void TimeOutRequests(time_t now)
Declare timeout on requests being recovered.
XRootDStatus VectorRead(const ChunkList &chunks, void *buffer, ResponseHandler *handler, uint16_t timeout=0)
XRootDStatus PgRead(uint64_t offset, uint32_t size, void *buffer, ResponseHandler *handler, uint16_t timeout=0)
XRootDStatus Stat(bool force, ResponseHandler *handler, uint16_t timeout=0)
void ReWriteFileHandle(Message *msg)
Re-write file handle.
bool pDoRecoverRead
Definition: XrdClFileStateHandler.hh:692
XRootDStatus Read(uint64_t offset, uint32_t size, void *buffer, ResponseHandler *handler, uint16_t timeout=0)
void Tick(time_t now)
Tick.
bool IsReadOnly() const
Check if the file is open for read only.
Status XAttrOperationImpl(kXR_char subcode, kXR_char options, const std::vector< T > &attrs, ResponseHandler *handler, uint16_t timeout=0)
bool pFollowRedirects
Definition: XrdClFileStateHandler.hh:694
void FailQueuedMessages(XRootDStatus status)
Fail queued messages.
std::list< RequestData > RequestList
Definition: XrdClFileStateHandler.hh:556
XRootDStatus WriteV(uint64_t offset, const struct iovec *iov, int iovcnt, ResponseHandler *handler, uint16_t timeout=0)
bool pIsChannelEncrypted
Definition: XrdClFileStateHandler.hh:696
XRootDStatus Sync(ResponseHandler *handler, uint16_t timeout=0)
XRootDStatus IssueRequest(const URL &url, Message *msg, ResponseHandler *handler, MessageSendParams &sendParams)
XRootDStatus DelXAttr(const std::vector< std::string > &attrs, ResponseHandler *handler, uint16_t timeout=0)
uint64_t pVWBytes
Definition: XrdClFileStateHandler.hh:706
uint16_t pOpenFlags
Definition: XrdClFileStateHandler.hh:688
XrdSysMutex pMutex
Definition: XrdClFileStateHandler.hh:677
URL * pLoadBalancer
Definition: XrdClFileStateHandler.hh:683
XRootDStatus Write(uint64_t offset, uint32_t size, const void *buffer, ResponseHandler *handler, uint16_t timeout=0)
URL * pWrtRecoveryRedir
Definition: XrdClFileStateHandler.hh:685
FileStateHandler(bool useVirtRedirector)
uint64_t pVSegs
Definition: XrdClFileStateHandler.hh:707
StatInfo * pStatInfo
Definition: XrdClFileStateHandler.hh:680
FileStatus
State of the file.
Definition: XrdClFileStateHandler.hh:87
@ OpenInProgress
Opening is in progress.
Definition: XrdClFileStateHandler.hh:92
@ Closed
The file is closed.
Definition: XrdClFileStateHandler.hh:88
@ Opened
Opening has succeeded.
Definition: XrdClFileStateHandler.hh:89
@ Error
Opening has failed.
Definition: XrdClFileStateHandler.hh:90
@ Recovering
Recovering from an error.
Definition: XrdClFileStateHandler.hh:91
void UnLock()
Unlock the internal lock.
Definition: XrdClFileStateHandler.hh:522
XRootDStatus Write(uint64_t offset, uint32_t size, Optional< uint64_t > fdoff, int fd, ResponseHandler *handler, uint16_t timeout=0)
RequestList pToBeRecovered
Definition: XrdClFileStateHandler.hh:689
void ResetMonitoringVars()
Reset monitoring vars.
Definition: XrdClFileStateHandler.hh:638
XRootDStatus pCloseReason
Definition: XrdClFileStateHandler.hh:712
uint64_t pVWCount
Definition: XrdClFileStateHandler.hh:711
XRootDStatus Truncate(uint64_t size, ResponseHandler *handler, uint16_t timeout=0)
uint64_t pVRBytes
Definition: XrdClFileStateHandler.hh:704
uint64_t pSessionId
Definition: XrdClFileStateHandler.hh:691
bool SetProperty(const std::string &name, const std::string &value)
bool pAllowBundledClose
Definition: XrdClFileStateHandler.hh:697
XRootDStatus SendClose(uint16_t timeout)
XRootDStatus GetXAttr(const std::vector< std::string > &attrs, ResponseHandler *handler, uint16_t timeout=0)
Status RunRecovery()
Run the recovery procedure if appropriate.
void OnClose(const XRootDStatus *status)
Process the results of the closing operation.
void OnStateError(XRootDStatus *status, Message *message, ResponseHandler *userHandler, MessageSendParams &sendParams)
Handle an error while sending a stateful message.
XRootDStatus Visa(ResponseHandler *handler, uint16_t timeout=0)
void OnStateResponse(XRootDStatus *status, Message *message, AnyObject *response, HostList *hostList)
Handle stateful response.
uint16_t pOpenMode
Definition: XrdClFileStateHandler.hh:687
XRootDStatus Write(uint64_t offset, Buffer &&buffer, ResponseHandler *handler, uint16_t timeout=0)
uint8_t * pFileHandle
Definition: XrdClFileStateHandler.hh:686
XRootDStatus ListXAttr(ResponseHandler *handler, uint16_t timeout=0)
XRootDStatus Fcntl(const Buffer &arg, ResponseHandler *handler, uint16_t timeout=0)
void OnOpen(const XRootDStatus *status, const OpenInfo *openInfo, const HostList *hostList)
Process the results of the opening operation.
XRootDStatus PgReadImpl(uint64_t offset, uint32_t size, void *buffer, uint16_t flags, ResponseHandler *handler, uint16_t timeout=0)
XRootDStatus WriteKernelBuffer(uint64_t offset, uint32_t length, std::unique_ptr< XrdSys::KernelBuffer > kbuff, ResponseHandler *handler, uint16_t timeout)
Send a write request with payload being stored in a kernel buffer.
uint64_t pRCount
Definition: XrdClFileStateHandler.hh:708
void MonitorClose(const XRootDStatus *status)
Dispatch monitoring information on close.
Status RecoverMessage(RequestData rd, bool callbackOnFailure=true)
bool pDoRecoverWrite
Definition: XrdClFileStateHandler.hh:693
bool IsRecoverable(const XRootDStatus &stataus) const
Check if the stateful error is recoverable.
uint64_t pVRCount
Definition: XrdClFileStateHandler.hh:709
XRootDStatus Close(ResponseHandler *handler, uint16_t timeout=0)
uint64_t pWBytes
Definition: XrdClFileStateHandler.hh:705
XRootDStatus pStatus
Definition: XrdClFileStateHandler.hh:679
XRootDStatus Open(const std::string &url, uint16_t flags, uint16_t mode, ResponseHandler *handler, uint16_t timeout=0)
void FailMessage(RequestData rd, XRootDStatus status)
Fail a message.
~FileStateHandler()
Destructor.
bool GetProperty(const std::string &name, std::string &value) const
LocalFileHandler * pLFileHandler
Definition: XrdClFileStateHandler.hh:723
uint64_t pWCount
Definition: XrdClFileStateHandler.hh:710
XRootDStatus PgReadRetry(uint64_t offset, uint32_t size, size_t pgnb, void *buffer, PgReadHandler *handler, uint16_t timeout=0)
FileStateHandler()
Constructor.
FileStatus pFileState
Definition: XrdClFileStateHandler.hh:678
bool pUseVirtRedirector
Definition: XrdClFileStateHandler.hh:695
timeval pOpenTime
Definition: XrdClFileStateHandler.hh:702
bool IsOpen() const
Check if the file is open.
XRootDStatus ReOpenFileAtServer(const URL &url, uint16_t timeout)
Re-open the current file at a given server.
void ReSendQueuedMessages()
Re-send queued messages.
void Lock()
Lock the internal lock.
Definition: XrdClFileStateHandler.hh:514
URL * pFileUrl
Definition: XrdClFileStateHandler.hh:681
Definition: XrdClLocalFileHandler.hh:33
The message representation used throughout the system.
Definition: XrdClMessage.hh:30
Information returned by file open operation.
Definition: XrdClXRootDResponses.hh:849
Definition: XrdClOptional.hh:44
Handle an async response.
Definition: XrdClXRootDResponses.hh:1037
Object stat info.
Definition: XrdClXRootDResponses.hh:396
URL representation.
Definition: XrdClURL.hh:31
Request status.
Definition: XrdClXRootDResponses.hh:215
Definition: XrdSysPthread.hh:166
Definition: XrdClAnyObject.hh:26
std::vector< HostInfo > HostList
Definition: XrdClXRootDResponses.hh:1031
std::vector< ChunkInfo > ChunkList
List of chunks.
Definition: XrdClXRootDResponses.hh:966
static const int kXR_pgRetry
Definition: XProtocol.hh:482
Definition: XrdClFileStateHandler.hh:547
RequestData()
Definition: XrdClFileStateHandler.hh:548
Message * request
Definition: XrdClFileStateHandler.hh:552
RequestData(Message *r, ResponseHandler *h, const MessageSendParams &p)
Definition: XrdClFileStateHandler.hh:549
ResponseHandler * handler
Definition: XrdClFileStateHandler.hh:553
MessageSendParams params
Definition: XrdClFileStateHandler.hh:554
Definition: XrdClMessageUtils.hh:132
none object for initializing empty Optional
Definition: XrdClOptional.hh:35
PgRead flags.
Definition: XrdClFileStateHandler.hh:60
Flags
PgRead flags.
Definition: XrdClFileStateHandler.hh:65
@ Retry
Definition: XrdClFileStateHandler.hh:67
Procedure execution status.
Definition: XrdClStatus.hh:111
Definition: XrdOucIOVec.hh:65