OSSP CVS Repository

ossp - ossp-pkg/sio/BRAINSTORM.txt
Not logged in
[Honeypot]  [Browse]  [Directory]  [Home]  [Login
[Reports]  [Search]  [Ticket]  [Timeline
  [Raw

ossp-pkg/sio/BRAINSTORM.txt

Names:
o SIO = simple/streams/stacked I/O
o FIO = fast I/O
o IOL = IO Lite (achtung)
o LIO = Lite/Layered IO
o AIO = Abstracted I/O

Connectors/Plugs:
o Memory
  SIO_PLUG *sio_plug_mem(uchar *buf, ulong len, uchar *(cb)(ulong));
  - connect to preallocated buffer + callback function for more buffer allocs
  - connect internally to auto-growing buffer(s)
o File
  constructors:
  - from fd
  - from FILE
  - from pathname
o Socket
  - UDP
  - TCP
o FILE*-2-SIO
o fd-2-SIO
o file-2-SIO
o TCP/socket-2-SIO
o UDP/socket-2-SIO
o Pipe/FIFO-2-SIO
o Null
  Discard Plug
  SIO *sio_plug_null(void)

Filters:
o Transparent; sio_pipe_trans
o Regex-Matching-Filter
o Regex-Subst-Filter
o MD5/SHA1/DES/IDEA
o Zlib/LZO
o SSL

IO Models (according to Stevens: Unix Network programming I, p. 144)
o blocking I/O
o nonblocking I/O (NO_HANG, NONBLK)
o I/O multiplexing (select and poll)
o signal driven I/O (SIGIO)
o asynchronous I/O (POSIX aio_xxx)

Data Structures
o Rings internal
o malloc(3) and mm_malloc(3) aware

Buffering-Modes:
o flush after timeout, close and exit() + explicit via flush()
o no buffering at all
o Chunking for HTTP Support!
o only read is buffered
o only write is buffered
o read & write is buffered

Buffering:
o filter koennen window/buffer size einstellen
o filter geben an ob sie shrinken/expandieren/gleichlassen oder random sind
o source connector kann eventuell Buffer vom User direkt nutzen
o umgekehrt kann auch user buffer wird von target connector genutzt werden
o application koennte auch bei write angeben, dasz buffer destroyed
  werden darf und dasz er eventuell groesser ist als die daten,
  die aus ihm geschrieben werden -> nuetzlich fuer expanding filters
  bei der Ausgabe.

Optimierungen:
o mmap muss moeglich sein
o if target connector = socket & source connector = file => try to use sendfile(2)
o if target connector = file   & source connector = file => try to use mmap(2)
o wenn I/O ohne filters dann no buffering oder nur wenn chunks zu klein
o wann es geht writev() und readv() nutzen, um Buffers zu koppeln beim I/O
o sockets haben fuer read/write() einen low water mark (siehe setsockopt)
o FreeBSD 4.0's accept_filter(9) mechanism to check for HTTP request

NOTES:
o Timeouts muessen generell unterstuetzt werden
o Error handling optional mit callbackfunction+void
o Callback functions for exceptional things
o Socket-Connector muss z.B. shutdown() erlauben
o man sollte meta-data (mtime, inode, etc.) von SIO connector rausfinden
  koennen und setzen koennen
o Chunking muss moeglich sein (HTTP?)
o Read sollte lesen bis:
  - number of bytes read
  - found a char of class [a-z]
  - found a string "foo"
  - found a regex "..."
o man sollte auf jedem SIO seek()en koennen
o man sollte SIOs in FILEs umwandeln koennen???
o bei Socket Plugs muss shutdown() also eine Seite moeglich sein

Architecture:
o three types of objects (siehe SIO.fig):
  - plugs (Stecker/Anschluesse) for socket, file, mem, etc.
  - pipes (Rohre/Verbindungen)
  - pipelines (the Kombination von plugs und pipes zu einer Einheit)
o buffered I/O: es gibt eine buffer-pipe, das ist alles
  unbuffered I/O ist also eine Pipleline wo kein buffer-pipe dabei ist

Conversions:
- ASCII2EBCDIC and vice versa conversions

o SIO Disciplines for Virtual Filesystem Stuff
  URLs as pathname open various network things, tarballs, etc.
  file, http, ftp, extfs
  ?? vfs, libfetch, libcurl ??

Performance Gains:
- use sendfile()
- use TCP_CORK
- use ...

Filter classes (from Apache discussions):
 1) content-generator                (files, CGI, database, etc)
 2) content-filter/munger/processor  (SSI, PHP, etc)
 3) content-encoding                 (gzip?)
 4) digest/message processor?        (mod_auth_digest)
 5) transport-encoding               (HTTP chunking)
 6) socket-encoding                  (SSL)

Fuer Zero-Copy:
The data the user program writes must be page sized and start on a page
boundary in order for it to be run through the zero copy send code.

Ideas:
http://sourceforge.net/projects/paip

-----------------

API Functions:
sio_rc_t sio_attach    (sio_t **sio, int fd);
sio_rc_t sio_deattach  (sio_t *sio, int *fd);
sio_rc_t sio_setbuffer (sio_t *sio, size_t newsize, size_t *oldsize);
sio_rc_t sio_readvec   (sio_t *sio, void **vec, size_t *veclen);
sio_rc_t sio_read      (sio_t *sio, void *buf, size_t *buflen);
sio_rc_t sio_readline  (sio_t *sio, void *buf, size_t *buflen);
sio_rc_t sio_readchar  (sio_t *sio, char *c);
sio_rc_t sio_putback   (sio_t *sio, void *buf, size_t buflen);
sio_rc_t sio_undo      (sio_t *sio);
sio_rc_t sio_writevec  (sio_t *sio, void **vec, size_t veclen);
sio_rc_t sio_write     (sio_t *sio, void *buf, size_t buflen);
sio_rc_t sio_writestr  (sio_t *sio, char *str);
sio_rc_t sio_writeline (sio_t *sio, void *buf, size_t buflen);
sio_rc_t sio_writechar (sio_t *sio, char c);
sio_rc_t sio_print     (sio_t *sio, char *fmt, ...);
sio_rc_t sio_printv    (sio_t *sio, char *fmt, va_list ap);
sio_rc_t sio_flush     (sio_t *sio);
sio_rc_t sio_error     (sio_t *sio, char **error);

sio_rc_t sio_read (sio_t *sio, sio_ioflags_t flags, ...);
sio_rc_t sio_write(sio_t *sio, sio_ioflags_t flags, ...);

  SIO_CHR | SIO_STR | SIO_BUF | SIO_FMT | SIO_STRVEC | SIO_BUFVEC
     type of objects: character, nul-terminated string or buffer+size or
     format string based
  SIO_MULT
     multiple objects are passed in call
  SIO_NULLEND
     whether size of vector is indicated by NULL or given

  SIO_COPY
     objects are copied to library
     (internal its SIO_GIFT after copy!)
  SIO_GIFT
     objects are gifted to library
  SIO_LOAN
     objects are just loaned to library

sio_read(sio, SIO_BUF, buf, buflen, &readlen);
sio_read(sio, SIO_LINE, buf, buflen, &readlen);

sio_write(sio, SIO_STR, "foo");
sio_write(sio, SIO_STR|SIO_MULT, "foo", "bar", NULL);
sio_write(sio, SIO_VEC|SIO_STR, vec, veclen);
sio_write(sio, SIO_VEC|SIO_STR|SIO_NULLEND, vec);
sio_write(sio, SIO_BUF, buf, buflen);
sio_write(sio, SIO_BUF|SIO_MULT, buf, buflen, buf2, buflen2, NULL);
sio_write(sio, SIO_VEC|SIO_BUF, vec, veclen);
sio_write(sio, SIO_VEC|SIO_BUF|SIO_NULLEND, vec);
sio_write(sio, SIO_STR|SIO_MULT, line, "\r\n", NULL);
sio_write(sio, SIO_CHR, c);
sio_write(sio, SIO_BUF, &c, 1);
sio_write(sio, SIO_FMT, "%c%s%S%b%B", c, cp, cpvec, cpvecsize, buf, bufsize, bufvec, bufvecsize);

API Comfort:
   sio_writestr("..") -> sio_write(SIO_STR, "..");
API Standard:
   sio_write(SIO_STR, char *x) -> sio_output(x, strlen(x));
   sio_write(SIO_VEC, char *x) -> for... sio_output(x.ptr, x.len); done
API Basic:
   sio_output

1. Was ist mit seekable fds (files!)?
   seek, tell,
2. Top-level filtering and chaining?
   tie, untie

-----------------
IDEA:
  - SIO (Socket IO)
  - BIO (Buffered/Filtered I/O)
  - BA/BB (Buffer Aggregates, Bucket Brigades -- ACT)

-----------------

brigate ::= bucket *
bucket  ::= <buf,len,type>

-----------------

/* SFIO: sfreserve?
 *       sfpool ?
 */

/*
 * Data structures
 */

/* the general SIO API */
typedef struct sio_st sio_t;

/* I/O vector entry (similar to POSIX struct iovec) for sio_{read,write}v() */
typdef struct sio_iovec_st
    char   *iov_base;   /* Base address. */
    size_t  iov_len;    /* Length. */
} sio_iovec_t;

typedef long sio_off_t;

typedef sio_uint8_t;
typedef sio_uint16_t;
typedef sio_uint32_t;

#define SIO_SEEK_SET
#define SIO_SEEK_CUR
#define SIO_SEEK_END

/*
 * Values
 */
#define SIO_EOF (-1)

/*
 * Stream Disciplines
 */
sio_disc_t *sio_disc_null   (void);
sio_disc_t *sio_disc_anon   (void);
sio_disc_t *sio_disc_fd     (int fd, ...);
sio_disc_t *sio_disc_socket (int fd, int type /*tcp,udp*/, ...);
sio_disc_t *sio_disc_pipe   (int fd, ...);
sio_disc_t *sio_disc_file   (FILE *fp, ...);
sio_disc_t *sio_disc_url    (const char *url, ...);

/*
 * Stream Handling
 */
sio_t      *sio_new      (sio_disc_t *disc);
sio_t      *sio_dup      (sio_t *sio);
int         sio_free     (sio_t *sio);

/*
 * I/O Operations
 */
sio_size_t  sio_read     (sio_t *sio, void *buf, size_t bytes);
sio_size_t  sio_write    (sio_t *sio, void *buf, size_t bytes);
sio_size_t  sio_writev   (sio_t *sio, const sio_iovec_t *iov, int iovcnt);
sio_size_t  sio_writev   (sio_t *sio, const sio_iovec_t *iov, int iovcnt);
sio_off_t   sio_seek     (sio_t *sio, sio_off_t offset, int type);
sio_size_t  sio_move     (sio_t *siow, sio_t *sior, int n, int rsc);
int         sio_getc     (sio_t *sio);
int         sio_putc     (sio_t *sio, int c);
int         sio_nputc    (sio_t *sio, int c, sio_size_t n);
int         sio_ungetc   (sio_t *sio, int c);
char       *sio_getr     (sio_t *sio, int rsc, int type);
sio_size_t *sio_putr     (sio_t *sio, const char *str, int rsc);

/*
 * Data Formatting
 */
sio_site_t  sio_printf   (sio_t *sio, const char *fmt, ...);
sio_site_t  sio_vprintf  (sio_t *sio, const char *fmt, va_list ap);
sio_site_t  sio_scanf    (sio_t *sio, const char *fmt, ...);
sio_site_t  sio_vscanf   (sio_t *sio, const char *fmt, va_list ap);

/*
 * Buffering & Synchronization
 */
int         sio_sync     (sio_t *sio);
int         sio_purge    (sio_t *sio);
int         sio_poll     (sio_poll_t *pl, sio_size_t pn, sio_time_t timeout);
int         sio_eof      (sio_t *sio);

/*
 * Stream Control
 */
long        sio_ctrl     (sio_t *sio, int cmd, ...);
int         sio_top      (sio_t *sio);
int         sio_push     (sio_t *sio, sio_t *top);
int         sio_pop      (sio_t *sio);
int         sio_swap     (sio_t *sio1, sio_t *sio2);

###########################################################################

mlelstv sez:

sio pipe:
- two chains of handlers for reading and writing
- "bucket brigade"-buffers, degenerates to static buffer(ptr,len)
- handler degenerates to (handle,read(2),write(2)) ?

dispatching:
- sio_strategy(chain)
  h = chain;
  while (h) {
      if h->call(sio) // reader or writer
        h = h->next;
      else
        h = h->prev;
  }

? eof/error propagation -> global flags, (byte offset ?)

- sio_write(buf)
  push sio->writebuffer, buf;
  sio_strategy(sio->writers);
  buf = pop sio->writebuffer;

- sio_read(bound)
  sio->readbuffer->append(buf);
  sio_strategy(sio->readers);
  pop sio->readbuffer;


buffer:
- bytestream(policy for chunks ?)
- drop bytestream
- append bytes to bytestream (ptr, len) == copy
- prepend bytes to bytestream (ptr, len) == copy
- append static buffer to bytestream
- splice bytestream into new bytestream (offset, length, dest)
- truncate bytestream (offset, length) == splice but drop data
- traverse chunks of bytestream forward (offset, length)
- traverse chunks of bytestream reverse (offset, length)
- splice last chunk from bytestream (convenience function)
- splice first chunk from bytestream (convenience function)
- flatten chunks of bytestream into target buffer (convenience function)
- garbage collection ? pullup ? seek cache ?
- read consistency while traversing ?

bytestream, chunks, buffer

chunk memory allocator needed
buffer memory allocator ?

---

stdio "emulation"

fixed buffer <-> bytestream
EOF handling


###########################################################################

mlelstv sez:

ideas for error/eof/urgent-data handling

-> multiple assembly lines per stream
   - too big ?
   - synchronization between "bands" required

-> "urgent" pointer similar to TCP ?
   + trivial implementation
   - only single condition for multiple causes

-> in-band multiplexing of labeled streams
   + synchonization is implicit
   + any number of conditions
   - needs support in AL (coalescing/merging)


CVSTrac 2.0.1