Browse Source

HPCC-24174 Reimplement noseek IFileIOStream using a helper class

Signed-off-by: Gavin Halliday <gavin.halliday@lexisnexis.com>
Gavin Halliday 5 years ago
parent
commit
dfd2e9722b

+ 4 - 1
ecl/hthor/hthor.cpp

@@ -1157,7 +1157,10 @@ void CHThorIndexWriteActivity::execute()
         if (hasTrailingFileposition(helper.queryDiskRecordSize()->queryTypeInfo()))
             keyMaxSize -= sizeof(offset_t);
 
-        Owned<IFileIOStream> out = createIOStream(io, needsSeek);
+        Owned<IFileIOStream> out = createIOStream(io);
+        if (!needsSeek)
+            out.setown(createNoSeekIOStream(out));
+
         Owned<IKeyBuilder> builder = createKeyBuilder(out, flags, keyMaxSize, nodeSize, helper.getKeyedSize(), 0, &helper, true, false);
         class BcWrapper : implements IBlobCreator
         {

+ 4 - 1
roxie/ccd/ccdserver.cpp

@@ -12367,7 +12367,10 @@ public:
             }
             if (metadata->getPropBool("_useTrailingHeader", true))
                 flags |= USE_TRAILING_HEADER;
-            Owned<IFileIOStream> out = createIOStream(io, needsSeek);
+            Owned<IFileIOStream> out = createIOStream(io);
+            if (!needsSeek)
+                out.setown(createNoSeekIOStream(out));
+
             Owned<IKeyBuilder> builder = createKeyBuilder(out, flags, maxDiskRecordSize, nodeSize, helper.getKeyedSize(), 0, &helper, true, false);
             class BcWrapper : implements IBlobCreator
             {

+ 3 - 1
system/jhtree/jhtree.cpp

@@ -3161,7 +3161,9 @@ class IKeyManagerTest : public CppUnit::TestFixture
     {
         OwnedIFile file = createIFile(filename);
         OwnedIFileIO io = file->openShared(IFOcreate, IFSHfull);
-        Owned<IFileIOStream> out = createIOStream(io, !noSeek);
+        Owned<IFileIOStream> out = createIOStream(io);
+        if (noSeek)
+            out.setown(createNoSeekIOStream(out));
         unsigned maxRecSize = variable ? 18 : 10;
         unsigned keyedSize = 10;
         Owned<IKeyBuilder> builder = createKeyBuilder(out, COL_PREFIX | HTREE_FULLSORT_KEY | HTREE_COMPRESSED_KEY |

+ 4 - 1
system/jhtree/keydiff.cpp

@@ -414,7 +414,10 @@ public:
         keyFileIO.setown(keyFile->openShared(IFOcreate, IFSHfull)); // not sure if needs shared here
         if(!keyFileIO)
             throw MakeStringException(0, "Could not write index file %s", filename);
-        keyStream.setown(createIOStream(keyFileIO, !noSeek));
+        keyStream.setown(createIOStream(keyFileIO));
+        if (noSeek)
+            keyStream.setown(createNoSeekIOStream(keyStream));
+
         unsigned flags = COL_PREFIX | HTREE_FULLSORT_KEY | HTREE_COMPRESSED_KEY | USE_TRAILING_HEADER;
         if (noSeek)
             flags |= TRAILING_HEADER_ONLY;

+ 65 - 7
system/jlib/jfile.cpp

@@ -2449,11 +2449,10 @@ IFileAsyncResult *CFileAsyncIO::writeAsync(offset_t pos, size32_t len, const voi
 
 //---------------------------------------------------------------------------
 
-CFileIOStream::CFileIOStream(IFileIO * _io, bool _allowSeek)
+CFileIOStream::CFileIOStream(IFileIO * _io)
 {
     io.set(_io);
     curOffset = 0;
-    allowSeek = _allowSeek;
 }
 
 
@@ -2471,7 +2470,6 @@ size32_t CFileIOStream::read(size32_t len, void * data)
 
 void CFileIOStream::seek(offset_t pos, IFSmode origin)
 {
-    auto oldOffset = curOffset;
     switch (origin)
     {
     case IFScurrent:
@@ -2484,8 +2482,6 @@ void CFileIOStream::seek(offset_t pos, IFSmode origin)
         curOffset = pos;
         break;
     }
-    if (!allowSeek && oldOffset != curOffset)
-        throw makeStringException(0, "Seek on non-seekable CFileIOStream");
 }
 
 offset_t CFileIOStream::size()
@@ -2509,6 +2505,63 @@ size32_t CFileIOStream::write(size32_t len, const void * data)
 
 //---------------------------------------------------------------------------
 
+CNoSeekFileIOStream::CNoSeekFileIOStream(IFileIOStream * _stream) : stream(_stream)
+{
+}
+
+
+void CNoSeekFileIOStream::flush()
+{
+    stream->flush();
+}
+
+
+size32_t CNoSeekFileIOStream::read(size32_t len, void * data)
+{
+    return stream->read(len, data);
+}
+
+void CNoSeekFileIOStream::seek(offset_t pos, IFSmode origin)
+{
+    offset_t prevOffset = stream->tell();
+    offset_t nextOffset = 0;
+    switch (origin)
+    {
+    case IFScurrent:
+        nextOffset = prevOffset + pos;
+        break;
+    case IFSend:
+        nextOffset = stream->size() + pos;
+        break;
+    case IFSbegin:
+        nextOffset = pos;
+        break;
+    }
+    if (prevOffset != nextOffset)
+        throw makeStringExceptionV(0, "Seek on non-seekable CFileIOStream (from %" I64F "u to %" I64F "u)", prevOffset, nextOffset);
+
+    //No need to call stream->seek since it will have no effect
+}
+
+offset_t CNoSeekFileIOStream::size()
+{
+    return stream->size();
+}
+
+offset_t CNoSeekFileIOStream::tell()
+{
+    return stream->tell();
+}
+
+size32_t CNoSeekFileIOStream::write(size32_t len, const void * data)
+{
+    return stream->write(len, data);
+}
+
+
+
+//---------------------------------------------------------------------------
+
 
 class CBufferedFileIOStreamBase : public CBufferedIOStreamBase, implements IFileIOStream
 {
@@ -4134,9 +4187,14 @@ IFile * createIFile(const char * filename)
 }
 
 
-IFileIOStream * createIOStream(IFileIO * file, bool allowSeek)
+IFileIOStream * createIOStream(IFileIO * file)
+{
+    return new CFileIOStream(file);
+}
+
+IFileIOStream * createNoSeekIOStream(IFileIOStream * stream)
 {
-    return new CFileIOStream(file, allowSeek);
+    return new CNoSeekFileIOStream(stream);
 }
 
 IFileIO * createIORange(IFileIO * io, offset_t header, offset_t length)

+ 2 - 1
system/jlib/jfile.hpp

@@ -267,7 +267,8 @@ extern jlib_decl IDirectoryIterator * createDirectoryIterator(const char * path
 extern jlib_decl IDirectoryIterator * createNullDirectoryIterator();
 extern jlib_decl IFileIO * createIORange(IFileIO * file, offset_t header, offset_t length);     // restricts input/output to a section of a file.
 
-extern jlib_decl IFileIOStream * createIOStream(IFileIO * file, bool allowSeek=true);        // links argument
+extern jlib_decl IFileIOStream * createIOStream(IFileIO * file);        // links argument
+extern jlib_decl IFileIOStream * createNoSeekIOStream(IFileIOStream * stream);  // links argument
 extern jlib_decl IFileIOStream * createBufferedIOStream(IFileIO * file, unsigned bufsize=(unsigned)-1);// links argument
 extern jlib_decl IFileIOStream * createBufferedAsyncIOStream(IFileAsyncIO * file, unsigned bufsize=(unsigned)-1);// links argument
 

+ 19 - 4
system/jlib/jfile.ipp

@@ -180,11 +180,10 @@ protected: friend class CFileAsyncResult;
 };
 
 
-class CFileIOStream : implements IFileIOStream, public CInterface
+class CFileIOStream : implements CInterfaceOf<IFileIOStream>
 {
 public:
-    CFileIOStream(IFileIO * _io, bool _allowSeek=true);
-    IMPLEMENT_IINTERFACE
+    CFileIOStream(IFileIO * _io);
 
     virtual void flush();
     virtual size32_t read(size32_t len, void * data);
@@ -196,11 +195,27 @@ public:
 protected:
     Linked<IFileIO>     io;
     offset_t            curOffset;
-    bool allowSeek = true;
 };
 
 
 
+class CNoSeekFileIOStream : implements CInterfaceOf<IFileIOStream>
+{
+public:
+    CNoSeekFileIOStream(IFileIOStream * _stream);
+
+    virtual void flush();
+    virtual size32_t read(size32_t len, void * data);
+    virtual void seek(offset_t pos, IFSmode origin);
+    virtual offset_t size();
+    virtual offset_t tell();
+    virtual size32_t write(size32_t len, const void * data);
+
+protected:
+    Linked<IFileIOStream>     stream;
+};
+
+
 class jlib_decl CIOStreamReadWriteSeq : public IWriteSeq, public IReadSeq, public CInterface
 {
 public: