Statistics
| Branch: | Revision:

streamers / output.c @ 80b2d694

History | View | Annotate | Download (2.71 KB)

1
/*
2
 *  Copyright (c) 2010 Luca Abeni
3
 *  Copyright (c) 2010 Csaba Kiraly
4
 *
5
 *  This is free software; see gpl-3.0.txt
6
 */
7
#include <unistd.h>
8
#include <stdlib.h>
9
#include <string.h>
10
#include <stdint.h>
11
#include <stdio.h>
12

    
13
#include <chunk.h>
14

    
15
#include "out-stream.h"
16
#include "dbg.h"
17

    
18
static int next_chunk;
19
static int buff_size;
20

    
21
struct outbuf {
22
  void *data;
23
  int size;
24
  int id;
25
};
26
static struct outbuf *buff;
27

    
28
void output_init(int bufsize)
29
{
30
  if (!buff) {
31
    int i;
32

    
33
    buff_size = bufsize;
34
    buff = malloc(sizeof(struct outbuf) * buff_size);
35
    if (!buff) {
36
     fprintf(stderr, "Error: can't allocate output buffer\n");
37
     exit(1);
38
    }
39
    for (i = 0; i < buff_size; i++) {
40
      buff[i].data = NULL;
41
    }
42
  } else {
43
   fprintf(stderr, "Error: output buffer re-init not allowed!\n");
44
   exit(1);
45
  }
46
}
47

    
48
void buffer_free(int i)
49
{
50
  dprintf("\t\tFlush Buf %d: %s\n", i, buff[i].data);
51
  chunk_write(buff[i].id, buff[i].data, buff[i].size);
52
  free(buff[i].data);
53
  buff[i].data = NULL;
54
  dprintf("Next Chunk: %d -> %d\n", next_chunk, buff[i].id + 1);
55
  next_chunk = buff[i].id + 1;
56
}
57

    
58
void buffer_flush(int id)
59
{
60
  int i = id % buff_size;
61

    
62
  while(buff[i].data) {
63
    buffer_free(i);
64
    i = (i + 1) % buff_size;
65
    if (i == id % buff_size) {
66
      break;
67
    }
68
  }
69
}
70

    
71
void output_deliver(const struct chunk *c)
72
{
73
  if (!buff) {
74
    fprintf(stderr, "Warning: code should use output_init!!! Setting output buffer to 8\n");
75
    output_init(8);
76
  }
77

    
78
  dprintf("Chunk %d delivered\n", c->id);
79
  if (c->id < next_chunk) {
80
    return;
81
  }
82

    
83
  if (c->id >= next_chunk + buff_size) {
84
    int i;
85

    
86
    /* We might need some space for storing this chunk,
87
     * or the stored chunks are too old
88
     */
89
    for (i = next_chunk; i <= c->id - buff_size; i++) {
90
      if (buff[i % buff_size].data) {
91
        buffer_free(i % buff_size);
92
      } else {
93
        next_chunk++;
94
      }
95
    }
96
    buffer_flush(next_chunk);
97
    dprintf("Next is now %d, chunk is %d\n", next_chunk, c->id);
98
  }
99

    
100
  dprintf("%d == %d?\n", c->id, next_chunk);
101
  if (c->id == next_chunk) {
102
    dprintf("\tOut Chunk[%d] - %d: %s\n", c->id, c->id % buff_size, c->data);
103
    chunk_write(c->id, c->data, c->size);
104
    next_chunk++;
105
    buffer_flush(next_chunk);
106
  } else {
107
    dprintf("Storing %d (in %d)\n", c->id, c->id % buff_size);
108
    if (buff[c->id % buff_size].data) {
109
      if (buff[c->id % buff_size].id == c->id) {
110
        /* Duplicate of a stored chunk */
111
        return;
112
      }
113
      fprintf(stderr, "Crap!\n");
114
      exit(-1);
115
    }
116
    /* We previously flushed, so we know that c->id is free */
117
    buff[c->id % buff_size].data = malloc(c->size);
118
    memcpy(buff[c->id % buff_size].data, c->data, c->size);
119
    buff[c->id % buff_size].size = c->size;
120
    buff[c->id % buff_size].id = c->id;
121
  }
122
}