Statistics
| Branch: | Revision:

grapes / src / Cache / topo_proto.c @ 10ddaca7

History | View | Annotate | Download (4.82 KB)

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

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

    
12
#include "net_helper.h"
13
#include "topocache.h"
14
#include "proto.h"
15
#include "topo_proto.h"
16

    
17
struct topo_context{
18
 struct peer_cache *myEntry;
19
 uint8_t *pkt;
20
 int pkt_size;
21
};
22

    
23
static int topo_payload_fill(struct topo_context *context, uint8_t *payload, int size, const struct peer_cache *c, const struct nodeID *snot, int max_peers, int include_me)
24
{
25
  int i;
26
  uint8_t *p = payload;
27

    
28
  if (!max_peers) max_peers = 1000; // FIXME: just to be sure to dump the whole cache...
29
  p += cache_header_dump(p, c, include_me);
30
  if (include_me) {
31
    p += entry_dump(p, context->myEntry, 0, size - (p - payload));
32
    max_peers--;
33
  }
34
  for (i = 0; nodeid(c, i) && max_peers; i++) {
35
    if (!nodeid_equal(nodeid(c, i), snot)) {
36
      int res;
37
      res = entry_dump(p, c, i, size - (p - payload));
38
      if (res < 0) {
39
        fprintf(stderr, "too many entries!\n");
40
        return -1;
41
      }
42
      p += res;
43
      --max_peers;
44
    }
45
  }
46

    
47
  return p - payload;
48
}
49

    
50
int topo_reply_header(struct topo_context *context, const struct peer_cache *c, const struct peer_cache *local_cache, int protocol,
51
                      int type, uint8_t *header, int header_len, int max_peers, int include_me)
52
{
53
  struct topo_header *h = (struct topo_header *)context->pkt;
54
  int len, res, shift;
55
  struct nodeID *dst;
56

    
57
  shift = sizeof(struct topo_header);
58
  if (header_len > 0) {
59
    if (header_len > context->pkt_size - shift) return -1;
60

    
61
    memcpy(context->pkt + shift, header, header_len);
62
    shift += sizeof(uint8_t) * header_len;
63
  }
64

    
65
#if 0
66
  n = psize / sizeof(struct cache_entry);
67
  if (n * sizeof(struct cache_entry) != psize) {
68
    fprintf(stderr, "Wrong number of elems %d (%d / %d)!!!\n", n, psize, sizeof(struct cache_entry));
69
    return -1;
70
  }
71
#endif
72
  dst = nodeid(c, 0);
73
  h->protocol = protocol;
74
  h->type = type;
75
  len = topo_payload_fill(context, context->pkt + shift, context->pkt_size - shift, local_cache, dst, max_peers, include_me);
76

    
77
  res = len > 0 ? send_to_peer(nodeid(context->myEntry, 0), dst, context->pkt, shift + len) : len;
78

    
79
  return res;
80
}
81

    
82
int topo_reply(struct topo_context *context, const struct peer_cache *c, const struct peer_cache *local_cache, int protocol, int type, int max_peers, int include_me)
83
{
84
  return topo_reply_header(context, c, local_cache, protocol, type, NULL, 0, max_peers, include_me);
85
}
86

    
87
int topo_query_peer_header(struct topo_context *context, const struct peer_cache *local_cache, struct nodeID *dst, int protocol, int type,
88
                           uint8_t *header, int header_len, int max_peers)
89
{
90
  struct topo_header *h = (struct topo_header *)context->pkt;
91
  int len, shift;
92

    
93
  shift = sizeof(struct topo_header);
94
  if (header_len > 0) {
95
    if (header_len > context->pkt_size - shift) return -1;
96

    
97
    memcpy(context->pkt + shift, header, header_len);
98
    shift += sizeof(uint8_t) * header_len;
99
  }
100

    
101
  h->protocol = protocol;
102
  h->type = type;
103
  len = topo_payload_fill(context, context->pkt + shift, context->pkt_size - shift, local_cache, dst, max_peers, 1);
104
  //fprintf(stderr,"[DEBUG] sending TOPO to peer \n");
105
  return len > 0  ? send_to_peer(nodeid(context->myEntry, 0), dst, context->pkt, shift + len) : len;
106
}
107

    
108
int topo_query_peer(struct topo_context *context, const struct peer_cache *local_cache, struct nodeID *dst, int protocol, int type, int max_peers)
109
{
110
  return topo_query_peer_header(context, local_cache, dst, protocol, type, NULL, 0, max_peers);
111
}
112

    
113
int topo_proto_myentry_update(struct topo_context *context, struct nodeID *s, int dts, const void *meta, int meta_size)
114
{
115
  int ret = 1;
116

    
117
  if (s && !nodeid_equal(nodeid(context->myEntry, 0), s)) {
118
    fprintf(stderr, "ERROR: myEntry change not implemented!\n");        //TODO
119
    exit(1);
120
  }
121

    
122
  if (dts) {
123
    cache_delay(context->myEntry, dts);
124
  }
125

    
126
  if (meta) {
127
    if (cache_metadata_update(context->myEntry, nodeid(context->myEntry, 0), meta, meta_size) <= 0) {
128
      ret = -1;
129
    }
130
  }
131

    
132
  return ret;
133
}
134

    
135
int topo_proto_metadata_update(struct topo_context *context, const void *meta, int meta_size)
136
{
137
  return topo_proto_myentry_update(context, nodeid(context->myEntry, 0), 0 , meta, meta_size);
138
}
139

    
140
struct topo_context* topo_proto_init(struct nodeID *s, const void *meta, int meta_size)
141
{
142
  struct topo_context* con;
143

    
144
  con = malloc(sizeof(struct topo_context));
145
  if (!con) return NULL;
146
  con->pkt_size = 60 * 1024;   // FIXME: Do something smarter, here!
147
  con->pkt = malloc(con->pkt_size);
148
  if (!con->pkt) {
149
    free(con);
150

    
151
    return NULL;
152
  }
153

    
154
  con->myEntry = cache_init(1, meta_size, 0);
155
  cache_add(con->myEntry, s, meta, meta_size);
156

    
157
  return con;
158
}
159

    
160
void topo_proto_destroy(struct topo_context ** t)
161
{
162
        if (t && *t)
163
        {
164
                if ((*t)->pkt)
165
                        free((*t)->pkt);
166
                if ((*t)->myEntry)
167
                        cache_free((*t)->myEntry);
168
                free(*t);
169
                *t = NULL;
170
        }
171
}