00001
00002
00003 #ifndef MuscleFailoverDataIO_h
00004 #define MuscleFailoverDataIO_h
00005
00006 #include "dataio/DataIO.h"
00007 #include "util/Queue.h"
00008
00009 BEGIN_NAMESPACE(muscle);
00010
00011 class FailoverDataIO;
00012
00014 class IFailoverNotifyTarget
00015 {
00016 public:
00018 IFailoverNotifyTarget() {}
00019
00021 virtual ~IFailoverNotifyTarget() {}
00022
00026 virtual void DataIOFailover(const FailoverDataIO & source) = 0;
00027 };
00028
00034 class FailoverDataIO : public DataIO
00035 {
00036 public:
00042 FailoverDataIO(int logErrorLevel = MUSCLE_LOG_NONE) : _logErrorLevel(logErrorLevel), _target(NULL) {}
00043
00045 virtual ~FailoverDataIO() {}
00046
00047 virtual int32 Read(void * buffer, uint32 size)
00048 {
00049 while(HasChild())
00050 {
00051 int32 ret = GetChild()->Read(buffer, size);
00052 if (ret >= 0) return ret;
00053 else Failover();
00054 }
00055 return -1;
00056 }
00057
00058 virtual int32 Write(const void * buffer, uint32 size)
00059 {
00060 while(HasChild())
00061 {
00062 int32 ret = GetChild()->Write(buffer, size);
00063 if (ret >= 0) return ret;
00064 else Failover();
00065 }
00066 return -1;
00067 }
00068
00069 virtual status_t Seek(int64 offset, int whence)
00070 {
00071 while(HasChild())
00072 {
00073 status_t ret = GetChild()->Seek(offset, whence);
00074 if (ret == B_NO_ERROR) return ret;
00075 else Failover();
00076 }
00077 return B_ERROR;
00078 }
00079
00080 virtual int64 GetPosition() const {return HasChild() ? GetChild()->GetPosition() : -1;}
00081
00082 virtual uint64 GetOutputStallLimit() const {return HasChild() ? GetChild()->GetOutputStallLimit() : MUSCLE_TIME_NEVER;}
00083
00084 virtual void FlushOutput() {if (HasChild()) GetChild()->FlushOutput();}
00085
00086 virtual void Shutdown() {_childIOs.Clear();}
00087
00088 virtual const SocketRef & GetSelectSocket() const {return (HasChild()) ? GetChild()->GetSelectSocket() : GetNullSocket();}
00089
00090 virtual status_t GetReadByteTimeStamp(int32 whichByte, uint64 & retStamp) const {return HasChild() ? GetChild()->GetReadByteTimeStamp(whichByte, retStamp) : B_ERROR;}
00091
00092 virtual bool HasBufferedOutput() const {return HasChild() ? GetChild()->HasBufferedOutput() : false;}
00093
00094 virtual void WriteBufferedOutput() {if (HasChild()) GetChild()->WriteBufferedOutput();}
00095
00097 const Queue<DataIORef> & GetChildDataIOs() const {return _childIOs;}
00098
00100 Queue<DataIORef> & GetChildDataIOs() {return _childIOs;}
00101
00107 virtual void Failover()
00108 {
00109 (void) _childIOs.RemoveHead();
00110 if (HasChild()) LogTime(_logErrorLevel, "FailoverDataIO: Child IO errored out, failing over to next child ("UINT32_FORMAT_SPEC" children left)!\n", _childIOs.GetNumItems());
00111 else LogTime(_logErrorLevel, "FailoverDataIO: Child IO errored out, no backup children left!\n");
00112 if (_target) _target->DataIOFailover(*this);
00113 }
00114
00116 void SetFailoverNotifyTarget(IFailoverNotifyTarget * t) {_target = t;}
00117
00119 IFailoverNotifyTarget * GetFailoverNotifyTarget() const {return _target;}
00120
00121 private:
00122 bool HasChild() const {return (_childIOs.HasItems());}
00123 DataIO * GetChild() const {return (_childIOs.Head()());}
00124
00125 Queue<DataIORef> _childIOs;
00126 int _logErrorLevel;
00127 IFailoverNotifyTarget * _target;
00128 };
00129
00130 END_NAMESPACE(muscle);
00131
00132 #endif