]> code.citadel.org Git - citadel.git/blobdiff - libcitadel/lib/stringbuf.c
FileSendChunked(): add mode which operates without known transmission size
[citadel.git] / libcitadel / lib / stringbuf.c
index ab9a1814887e4204d21c98572dd5b2eb44f2e83b..ff44368f1cbf71f30312aafd0d4efdec32ce3701 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1987-2011 by the citadel.org team
+ * Copyright (c) 1987-2013 by the citadel.org team
  *
  * This program is open source software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -1173,29 +1173,22 @@ void StrBufSpaceToBlank(StrBuf *Buf)
 
 void StrBufStripAllBut(StrBuf *Buf, char leftboundary, char rightboundary)
 {
-       const char *pBuff;
        const char *pLeft;
        const char *pRight;
 
-       if ((Buf == NULL) || (Buf->buf == NULL))
+       if ((Buf == NULL) || (Buf->buf == NULL)) {
                return;
-       pLeft = pBuff = Buf->buf;
-       while (pBuff != NULL) {
-               pLeft = pBuff;
-               pBuff = strchr(pBuff, leftboundary);
-               if (pBuff != NULL)
-                       pBuff++;
        }
-               
-       if (pLeft != NULL)
-               pBuff = pLeft;
-       else
-               pBuff = Buf->buf;
-       pRight = strchr(pBuff, rightboundary);
-       if (pRight != NULL)
+
+       pRight = strchr(Buf->buf, rightboundary);
+       if (pRight != NULL) {
                StrBufCutAt(Buf, 0, pRight);
-       if (pLeft != NULL)
-               StrBufCutLeft(Buf, pLeft - Buf->buf);
+       }
+
+       pLeft = strrchr(ChrPtr(Buf), leftboundary);
+       if (pLeft != NULL) {
+               StrBufCutLeft(Buf, pLeft - Buf->buf + 1);
+       }
 }
 
 
@@ -3932,18 +3925,34 @@ long IOBufferStrLength(IOBuffer *FB)
        return StrLength(FB->Buf) - (FB->ReadWritePointer - FB->Buf->buf);
 }
 
-void FDIOBufferInit(FDIOBuffer *FDB, IOBuffer *IO, int FD, long TotalSendSize)
+inline static void FDIOBufferFlush(FDIOBuffer *FDB)
 {
        memset(FDB, 0, sizeof(FDIOBuffer));
-       FDB->ChunkSize = 
-               FDB->TotalSendSize = TotalSendSize;
+       FDB->OtherFD = -1;
+       FDB->SplicePipe[0] = -1;
+       FDB->SplicePipe[1] = -1;
+}
+
+void FDIOBufferInit(FDIOBuffer *FDB, IOBuffer *IO, int FD, long TotalSendSize)
+{
+       FDIOBufferFlush(FDB);
+
+       FDB->TotalSendSize = TotalSendSize;
+       if (TotalSendSize > 0)
+               FDB->ChunkSize = TotalSendSize;
+       else
+       {
+               TotalSendSize = SIZ * 10;
+               FDB->ChunkSize = TotalSendSize;
+       }
        FDB->IOB = IO;
+
 #ifdef LINUX_SPLICE
        if (EnableSplice)
                pipe(FDB->SplicePipe);
        else
 #endif
-               FDB->ChunkBuffer = NewStrBufPlain(NULL, TotalSendSize + 1);
+               FDB->ChunkBuffer = NewStrBufPlain(NULL, TotalSendSize+ 1);
 
        FDB->OtherFD = FD;
 }
@@ -3953,82 +3962,176 @@ void FDIOBufferDelete(FDIOBuffer *FDB)
 #ifdef LINUX_SPLICE
        if (EnableSplice)
        {
-               close(FDB->SplicePipe[0]);
-               close(FDB->SplicePipe[1]);
+               if (FDB->SplicePipe[0] > 0)
+                       close(FDB->SplicePipe[0]);
+               if (FDB->SplicePipe[1] > 0)
+                       close(FDB->SplicePipe[1]);
        }
        else
 #endif
                FreeStrBuf(&FDB->ChunkBuffer);
        
-       close(FDB->OtherFD);
-       memset(FDB, 0, sizeof(FDIOBuffer));     
+       if (FDB->OtherFD > 0)
+               close(FDB->OtherFD);
+       FDIOBufferFlush(FDB);
 }
 
 int FileSendChunked(FDIOBuffer *FDB, const char **Err)
 {
        ssize_t sent, pipesize;
-#ifdef LINUX_SPLICE
-       if (EnableSplice)
+
+       if (FDB->TotalSendSize > 0)
        {
-               if (FDB->PipeSize == 0)
+#ifdef LINUX_SPLICE
+               if (EnableSplice)
                {
-                       pipesize = splice(FDB->OtherFD,
-                                         &FDB->TotalSentAlready, 
-                                         FDB->SplicePipe[1],
-                                         NULL, 
-                                         FDB->ChunkSendRemain, 
-                                         SPLICE_F_MOVE);
+                       if (FDB->PipeSize == 0)
+                       {
+                               pipesize = splice(FDB->OtherFD,
+                                                 &FDB->TotalSentAlready, 
+                                                 FDB->SplicePipe[1],
+                                                 NULL, 
+                                                 FDB->ChunkSendRemain, 
+                                                 SPLICE_F_MOVE);
        
-                       if (pipesize == -1)
+                               if (pipesize == -1)
+                               {
+                                       *Err = strerror(errno);
+                                       return pipesize;
+                               }
+                               FDB->PipeSize = pipesize;
+                       }
+                       sent =  splice(FDB->SplicePipe[0],
+                                      NULL, 
+                                      FDB->IOB->fd,
+                                      NULL, 
+                                      FDB->PipeSize,
+                                      SPLICE_F_MORE | SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
+                       if (sent == -1)
                        {
                                *Err = strerror(errno);
-                               return pipesize;
+                               return sent;
                        }
-                       FDB->PipeSize = pipesize;
+                       FDB->PipeSize -= sent;
+                       FDB->ChunkSendRemain -= sent;
+                       return sent;
                }
-               sent =  splice(FDB->SplicePipe[0],
-                              NULL, 
-                              FDB->IOB->fd,
-                              NULL, 
-                              FDB->PipeSize,
-                              SPLICE_F_MORE | SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
-               if (sent == -1)
+               else
+#endif
                {
-                       *Err = strerror(errno);
-                       return sent;
+                       char *pRead;
+                       long nRead = 0;
+
+                       pRead = FDB->ChunkBuffer->buf;
+                       while ((FDB->ChunkBuffer->BufUsed < FDB->TotalSendSize) && (nRead >= 0))
+                       {
+                               nRead = read(FDB->OtherFD, pRead, FDB->TotalSendSize - FDB->ChunkBuffer->BufUsed);
+                               if (nRead > 0) {
+                                       FDB->ChunkBuffer->BufUsed += nRead;
+                                       FDB->ChunkBuffer->buf[FDB->ChunkBuffer->BufUsed] = '\0';
+                               }
+                               else if (nRead == 0) {}
+                               else return nRead;
+                       }
+
+                       nRead = write(FDB->IOB->fd,
+                                     FDB->ChunkBuffer->buf     + FDB->TotalSentAlready,
+                                     FDB->ChunkBuffer->BufUsed - FDB->TotalSentAlready);
+
+                       if (nRead >= 0) {
+                               FDB->TotalSentAlready += nRead;
+                               FDB->ChunkSendRemain -= nRead;
+                               return FDB->ChunkSendRemain;
+                       }
+                       else {
+                               return nRead;
+                       }
                }
-               FDB->PipeSize -= sent;
-               FDB->ChunkSendRemain -= sent;
-               return sent;
        }
        else
-#endif
        {
-               char *pRead;
-               long nRead = 0;
-
-               pRead = FDB->ChunkBuffer->buf;
-               while ((FDB->ChunkBuffer->BufUsed < FDB->TotalSendSize) && (nRead >= 0))
+#ifdef LINUX_SPLICE
+               if (EnableSplice)
                {
-                       nRead = read(FDB->OtherFD, pRead, FDB->TotalSendSize - FDB->ChunkBuffer->BufUsed);
-                       if (nRead > 0) {
-                               FDB->ChunkBuffer->BufUsed += nRead;
-                               FDB->ChunkBuffer->buf[FDB->ChunkBuffer->BufUsed] = '\0';
+                       if (FDB->PipeSize == 0)
+                       {
+                               pipesize = splice(FDB->OtherFD,
+                                                 &FDB->TotalSentAlready, 
+                                                 FDB->SplicePipe[1],
+                                                 NULL, 
+                                                 SIZ * 10, 
+                                                 SPLICE_F_MOVE);
+       
+                               if (pipesize == -1)
+                               {
+                                       *Err = strerror(errno);
+                                       return pipesize;
+                               }
+                               FDB->PipeSize = pipesize;
+                               if (pipesize == 0)
+                                       return -1;
                        }
-                       else if (nRead == 0) {}
-                       else return nRead;
-               
+                       sent =  splice(FDB->SplicePipe[0],
+                                      NULL, 
+                                      FDB->IOB->fd,
+                                      NULL, 
+                                      FDB->PipeSize,
+                                      SPLICE_F_MORE | SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
+                       if (sent == -1)
+                       {
+                               *Err = strerror(errno);
+                               return sent;
+                       }
+                       FDB->PipeSize -= sent;
+                       FDB->ChunkSendRemain -= sent;
+                       return sent;
                }
+               else
+#endif
+               {
+                       char *pRead;
+                       long nRead = 0;
 
-               nRead = write(FDB->IOB->fd, FDB->ChunkBuffer->buf + FDB->TotalSentAlready, FDB->ChunkSendRemain);
+                       pRead = FDB->ChunkBuffer->buf;
+                       while ((FDB->ChunkSendRemain == 0) && 
+                              (FDB->ChunkBuffer->BufUsed < FDB->ChunkBuffer->BufSize) &&
+                              (nRead >= 0))
+                       {
+                               FDB->TotalSentAlready = 0;
+                               nRead = read(FDB->OtherFD, pRead, FDB->ChunkBuffer->BufSize - FDB->ChunkBuffer->BufUsed);
+                               if (nRead > 0) {
+                                       FDB->ChunkBuffer->BufUsed += nRead;
+                                       FDB->ChunkBuffer->buf[FDB->ChunkBuffer->BufUsed] = '\0';
+                                       FDB->ChunkSendRemain += nRead;
+                               }
+                               else if (nRead == 0)
+                               {
+                                       return -1;
+                               }
+                               else
+                               {
+                                       *Err = strerror(errno);
+                                       return nRead;
+                               }
+                       }
 
-               if (nRead >= 0) {
-                       FDB->TotalSentAlready += nRead;
-                       FDB->ChunkSendRemain -= nRead;
-                       return FDB->ChunkSendRemain;
-               }
-               else {
-                       return nRead;
+                       nRead = write(FDB->IOB->fd,
+                                     FDB->ChunkBuffer->buf     + FDB->TotalSentAlready,
+                                     FDB->ChunkBuffer->BufUsed - FDB->TotalSentAlready);
+
+                       if (nRead >= 0) {
+                               FDB->TotalSentAlready += nRead;
+                               FDB->ChunkSendRemain -= nRead;
+                               if (FDB->ChunkSendRemain == 0)
+                               {
+                                       FDB->ChunkBuffer->BufUsed = 0;
+                                       FDB->TotalSentAlready = 0;
+                               }
+                               return FDB->ChunkSendRemain;
+                       }
+                       else {
+                               return nRead;
+                       }
                }
        }
 }
@@ -4561,6 +4664,10 @@ int StrBufTCP_read_buffered_line_fast(StrBuf *Line,
 
                        continue;
                }
+               else
+               {
+                       nSuccessLess++;
+               }
        }
        *Pos = NULL;
        if (pLF != NULL) {