Statistics
| Branch: | Revision:

grapes / src / ChunkBuffer / buffer.c @ 176b8de8

History | View | Annotate | Download (2.81 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)
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

    
71
  return E_CB_OLD;
72
}
73

    
74
struct chunk_buffer *cb_init(const char *config)
75
{
76
  struct tag *cfg_tags;
77
  struct chunk_buffer *cb;
78
  int res, i;
79

    
80
  cb = malloc(sizeof(struct chunk_buffer));
81
  if (cb == NULL) {
82
    return cb;
83
  }
84
  memset(cb, 0, sizeof(struct chunk_buffer));
85

    
86
  cfg_tags = grapes_config_parse(config);
87
  if (!cfg_tags) {
88
    free(cb);
89
    return NULL;
90
  }
91
  res = grapes_config_value_int(cfg_tags, "size", &cb->size);
92
  if (!res) {
93
    free(cb);
94
    free(cfg_tags);
95

    
96
    return NULL;
97
  }
98
  free(cfg_tags);
99

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

    
110
  return cb;
111
}
112

    
113
int cb_add_chunk(struct chunk_buffer *cb, const struct chunk *c)
114
{
115
  int i;
116

    
117
  if (cb->num_chunks == cb->size) {
118
    i = remove_oldest_chunk(cb, c->id);
119
  } else {
120
    i = 0;
121
  }
122

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

    
135
      return 0; 
136
    }
137
    i++;
138
  }
139
}
140

    
141
struct chunk *cb_get_chunks(const struct chunk_buffer *cb, int *n)
142
{
143
  *n = cb->num_chunks;
144
  if (*n == 0) {
145
    return NULL;
146
  }
147

    
148
  insert_sort(cb->buffer, cb->num_chunks);
149

    
150
  return cb->buffer;
151
}
152

    
153
int cb_clear(struct chunk_buffer *cb)
154
{
155
  int i;
156

    
157
  for (i = 0; i < cb->num_chunks; i++) {
158
    chunk_free(&cb->buffer[i]);
159
  }
160
  cb->num_chunks = 0;
161

    
162
  return 0;
163
}
164

    
165
void cb_destroy(struct chunk_buffer *cb)
166
{
167
  cb_clear(cb);
168
  free(cb->buffer);
169
  free(cb);
170
}