Statistics
| Branch: | Revision:

grapes / src / ChunkBuffer / buffer.c @ 10ddaca7

History | View | Annotate | Download (2.99 KB)

1
/*
2
 *  Copyright (c) 2010 Luca Abeni
3
 *  Copyright (c) 2010 Csaba Kiraly
4
 *
5
 *  This is free software; see lgpl-2.1.txt
6
 */
7

    
8
#include <stdlib.h>
9
#include <stdint.h>
10
#include <string.h>
11

    
12
#include "chunk.h"
13
#include "chunkbuffer.h"
14
#include "grapes_config.h"
15

    
16
struct chunk_buffer {
17
  int size;
18
  int num_chunks;
19
  struct chunk *buffer;
20
};
21

    
22
static void insert_sort(struct chunk *b, int size)
23
{
24
  int i, j;
25
  struct chunk tmp;
26

    
27
  for(i = 1; i < size; i++) {
28
    tmp = b[i];
29
    j = i - 1;
30
    while(j >= 0 && tmp.id < b[j].id) {
31
      b[j + 1] = b[j];
32
      j = j - 1;
33
    }
34
    b[j + 1] = tmp;
35
  }
36
}
37

    
38
static void chunk_free(struct chunk *c)
39
{
40
    free(c->data);
41
    c->data = NULL;
42
    free(c->attributes);
43
    c->attributes = NULL;
44
    c->id = -1;
45
}
46

    
47
static int remove_oldest_chunk(struct chunk_buffer *cb, int id, uint64_t ts)
48
{
49
  int i, min, pos_min;
50

    
51
  if (cb->buffer[0].id == id) {
52
    return E_CB_DUPLICATE;
53
  }
54
  min = cb->buffer[0].id; pos_min = 0;
55
  for (i = 1; i < cb->num_chunks; i++) {
56
    if (cb->buffer[i].id == id) {
57
      return E_CB_DUPLICATE;
58
    }
59
    if (cb->buffer[i].id < min) {
60
      min = cb->buffer[i].id;
61
      pos_min = i;
62
    }
63
  }
64
  if (min < id) {
65
    chunk_free(&cb->buffer[pos_min]);
66
    cb->num_chunks--;
67

    
68
    return pos_min;
69
  }
70
  // check for ID looparound and other anomalies
71
  if (cb->buffer[pos_min].timestamp < ts) {
72
    cb_clear(cb);
73
    return 0;
74
  }
75
  return E_CB_OLD;
76
}
77

    
78
struct chunk_buffer *cb_init(const char *config)
79
{
80
  struct tag *cfg_tags;
81
  struct chunk_buffer *cb;
82
  int res, i;
83

    
84
  cb = malloc(sizeof(struct chunk_buffer));
85
  if (cb == NULL) {
86
    return cb;
87
  }
88
  memset(cb, 0, sizeof(struct chunk_buffer));
89

    
90
  cfg_tags = grapes_config_parse(config);
91
  if (!cfg_tags) {
92
    free(cb);
93
    return NULL;
94
  }
95
  res = grapes_config_value_int(cfg_tags, "size", &cb->size);
96
  if (!res) {
97
    free(cb);
98
    free(cfg_tags);
99

    
100
    return NULL;
101
  }
102
  free(cfg_tags);
103

    
104
  cb->buffer = malloc(sizeof(struct chunk) * cb->size);
105
  if (cb->buffer == NULL) {
106
    free(cb);
107
    return NULL;
108
  }
109
  memset(cb->buffer, 0, sizeof(struct chunk) * cb->size);
110
  for (i = 0; i < cb->size; i++) {
111
    cb->buffer[i].id = -1;
112
  }
113

    
114
  return cb;
115
}
116

    
117
int cb_add_chunk(struct chunk_buffer *cb, const struct chunk *c)
118
{
119
  int i;
120

    
121
  if (cb->num_chunks == cb->size) {
122
    i = remove_oldest_chunk(cb, c->id, c->timestamp);
123
  } else {
124
    i = 0;
125
  }
126

    
127
  if (i < 0) {
128
    return i;
129
  }
130
  
131
  while(1) {
132
    if (cb->buffer[i].id == c->id) {
133
      return E_CB_DUPLICATE;
134
    }
135
    if (cb->buffer[i].id < 0) {
136
      cb->buffer[i] = *c;
137
      cb->num_chunks++;
138

    
139
      return 0; 
140
    }
141
    i++;
142
  }
143
}
144

    
145
struct chunk *cb_get_chunks(const struct chunk_buffer *cb, int *n)
146
{
147
  *n = cb->num_chunks;
148
  if (*n == 0) {
149
    return NULL;
150
  }
151

    
152
  insert_sort(cb->buffer, cb->num_chunks);
153

    
154
  return cb->buffer;
155
}
156

    
157
int cb_clear(struct chunk_buffer *cb)
158
{
159
  int i;
160

    
161
  for (i = 0; i < cb->num_chunks; i++) {
162
    chunk_free(&cb->buffer[i]);
163
  }
164
  cb->num_chunks = 0;
165

    
166
  return 0;
167
}
168

    
169
void cb_destroy(struct chunk_buffer *cb)
170
{
171
  cb_clear(cb);
172
  free(cb->buffer);
173
  free(cb);
174
}