Statistics
| Branch: | Revision:

grapes / src / Cache / topo_proto.c @ 6c4b3276

History | View | Annotate | Download (4.58 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
  return len > 0  ? send_to_peer(nodeid(context->myEntry, 0), dst, context->pkt, shift + len) : len;
105
}
106

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

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

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

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

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

    
131
  return ret;
132
}
133

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

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

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

    
150
    return NULL;
151
  }
152

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

    
156
  return con;
157
}