You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

bmap.c 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. /* This file is part of Netsukuku
  2. * (c) Copyright 2005 Andrea Lo Pumo aka AlpT <alpt@freaknet.org>
  3. *
  4. * This source code is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as published
  6. * by the Free Software Foundation; either version 2 of the License,
  7. * or (at your option) any later version.
  8. *
  9. * This source code is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. * Please refer to the GNU Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Public License along with
  15. * this source code; if not, write to:
  16. * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. *
  18. * --
  19. * bmap.c:
  20. * Border node map code.
  21. */
  22. #include "includes.h"
  23. #include "common.h"
  24. #include "inet.h"
  25. #include "endianness.h"
  26. #include "map.h"
  27. #include "gmap.h"
  28. #include "bmap.h"
  29. void
  30. bmap_levels_init(u_char levels, map_bnode *** bmap, u_int ** bmap_nodes)
  31. {
  32. *bmap = xmalloc(sizeof(map_bnode *) * levels);
  33. *bmap_nodes = (u_int *) xmalloc(sizeof(u_int) * levels);
  34. setzero(*bmap, sizeof(map_bnode *) * levels);
  35. bmap_counter_reset(levels, *bmap_nodes);
  36. }
  37. void
  38. bmap_levels_free(map_bnode ** bmap, u_int * bmap_nodes)
  39. {
  40. xfree(bmap);
  41. xfree(bmap_nodes);
  42. }
  43. void
  44. bmap_counter_init(u_char levels, u_int ** bnodes_closed,
  45. u_int ** bnodes_opened)
  46. {
  47. *bnodes_closed = (u_int *) xmalloc(sizeof(u_int) * levels);
  48. *bnodes_opened = (u_int *) xmalloc(sizeof(u_int) * levels);
  49. bmap_counter_reset(levels, *bnodes_closed);
  50. bmap_counter_reset(levels, *bnodes_opened);
  51. }
  52. void
  53. bmap_counter_free(u_int * bnodes_closed, u_int * bnodes_opened)
  54. {
  55. xfree(bnodes_closed);
  56. xfree(bnodes_opened);
  57. }
  58. void
  59. bmap_counter_reset(u_char levels, u_int * counter)
  60. {
  61. setzero(counter, sizeof(u_int) * levels);
  62. }
  63. /*
  64. * map_add_bnode: It adds a new bnode in the `bmap' and then returns its position
  65. * in the bmap. It also increments the `*bmap_nodes' counter. The bnode_ptr is set
  66. * to `bnode' and the links to `links'.
  67. * Note that the `bmap' argument must be an adress of a pointer.
  68. */
  69. int
  70. map_add_bnode(map_bnode ** bmap, u_int * bmap_nodes, u_int bnode,
  71. u_int links)
  72. {
  73. map_bnode *bnode_map;
  74. u_int bm;
  75. bm = *bmap_nodes;
  76. (*bmap_nodes)++;
  77. if (!bm)
  78. *bmap = xmalloc(sizeof(map_bnode));
  79. else
  80. *bmap = xrealloc(*bmap, sizeof(map_bnode) * *bmap_nodes);
  81. bnode_map = *bmap;
  82. setzero(bnode_map, sizeof(map_bnode));
  83. bnode_map[bm].bnode_ptr = bnode;
  84. bnode_map[bm].links = links;
  85. return bm;
  86. }
  87. /*
  88. * map_bnode_del: It deletes the `bnode' in the `bmap' which has `bmap_nodes'.
  89. * It returns the newly rescaled `bmap'.
  90. * It returns 0 if the `bmap' doesn't exist anymore.*/
  91. map_bnode *
  92. map_bnode_del(map_bnode * bmap, u_int * bmap_nodes, map_bnode * bnode)
  93. {
  94. map_node_del((map_node *) bnode);
  95. if (((char *) bnode - (char *) bmap) / sizeof(map_bnode) !=
  96. (*bmap_nodes) - 1)
  97. memcpy(bnode, &bmap[*bmap_nodes - 1], sizeof(map_bnode));
  98. (*bmap_nodes)--;
  99. if (*bmap_nodes)
  100. return xrealloc(bmap, (*bmap_nodes) * sizeof(map_bnode));
  101. else {
  102. *bmap_nodes = 0;
  103. xfree(bmap);
  104. return 0;
  105. }
  106. }
  107. /*
  108. * bmap_del_rnode_by_level: it is pretty specific, it deletes all the rnodes
  109. * of `bnode' which point to a gnode located in a level not equal to `level'.
  110. * The number of rnode deleted is returned.
  111. * `total_levels' must be equal to the maximum levels
  112. * available (use FAMILY_LVLS).
  113. */
  114. int
  115. bmap_del_rnode_by_level(map_bnode * bnode, int level, map_gnode ** ext_map,
  116. int total_levels)
  117. {
  118. map_gnode *gn;
  119. int i, ret = 0, lvl;
  120. for (i = 0; i < bnode->links; i++) {
  121. gn = (map_gnode *) bnode->r_node[i].r_node;
  122. lvl = extmap_find_level(ext_map, gn, total_levels);
  123. if (lvl != level) {
  124. rnode_del(bnode, i);
  125. ret++;
  126. }
  127. }
  128. return ret;
  129. }
  130. /*
  131. * map_find_bnode: Find the given `node' (in the pos_from_node() format) in the
  132. * given map_bnode `bmap'.
  133. */
  134. int
  135. map_find_bnode(map_bnode * bmap, int bmap_nodes, int node)
  136. {
  137. int e;
  138. for (e = 0; e < bmap_nodes; e++)
  139. if (bmap[e].bnode_ptr == node)
  140. return e;
  141. return -1;
  142. }
  143. /*
  144. * map_find_bnode_rnode: Find the first bnode in the `bmap' which has a rnode
  145. * which points to `n'. If it is found the pos of the bnode in the `bmap' is
  146. * returned, otherwise -1 is the return value.
  147. */
  148. int
  149. map_find_bnode_rnode(map_bnode * bmap, int bmap_nodes, void *n)
  150. {
  151. int e;
  152. for (e = 0; e < bmap_nodes; e++)
  153. if (rnode_find((map_node *) & bmap[e], (map_node *) n) != -1)
  154. return e;
  155. return -1;
  156. }
  157. /*
  158. * map_count_bnode_rnode: counts how many bnode which have a rnode which
  159. * points to `n' there are in `bmap'.
  160. */
  161. int
  162. map_count_bnode_rnode(map_bnode * bmap, int bmap_nodes, void *n)
  163. {
  164. int e, i;
  165. for (i = 0, e = 0; i < bmap_nodes; i++)
  166. if (rnode_find((map_node *) & bmap[i], (map_node *) n) != -1)
  167. e++;
  168. return e;
  169. }
  170. /*
  171. * bmaps_count_bnode_rnode: applies map_count_bnode_rnode() to each level of
  172. * `bmap' and returns the sum of the results.
  173. * `levels' are the total levels of `bmap'.
  174. */
  175. int
  176. bmaps_count_bnode_rnode(map_bnode ** bmap, int *bmap_nodes, int levels,
  177. void *n)
  178. {
  179. int i, e;
  180. for (i = 0, e = 0; i < levels; i++)
  181. e += map_count_bnode_rnode(bmap[i], bmap_nodes[i], n);
  182. return e;
  183. }
  184. /*
  185. * map_del_bnode_rnode: deletes all the rnodes of the bnode, present in `bmap',
  186. * which points to `n' and deletes the bnodes remained empty.
  187. * `bmap' is the address of the pointer to the bmap.
  188. * It returns the number of rnodes deleted.
  189. */
  190. int
  191. map_del_bnode_rnode(map_bnode ** bmap, int *bmap_nodes, void *n)
  192. {
  193. map_bnode *bm;
  194. int e, p, ret = 0;
  195. bm = *bmap;
  196. for (e = 0; e < *bmap_nodes; e++) {
  197. if ((p = rnode_find((map_node *) & bm[e], (map_node *) n)) != -1) {
  198. rnode_del(&bm[e], p);
  199. if (!bm[e].links) {
  200. *bmap = map_bnode_del(*bmap, (u_int *) bmap_nodes, &bm[e]);
  201. bm = *bmap;
  202. }
  203. ret++;
  204. }
  205. }
  206. return ret;
  207. }
  208. /*
  209. * bmaps_del_bnode_rnode: applies map_del_bnode_rnode() to each level of
  210. * `bmap'.
  211. * `levels' are the total levels of `bmap'.
  212. * It returns the total number of rnodes deleted
  213. */
  214. int
  215. bmaps_del_bnode_rnode(map_bnode ** bmap, int *bmap_nodes, int levels,
  216. void *n)
  217. {
  218. int i, e;
  219. for (i = 0, e = 0; i < levels; i++)
  220. e += map_del_bnode_rnode(&bmap[i], &bmap_nodes[i], n);
  221. return e;
  222. }
  223. /*
  224. * map_set_bnode_flag: sets the `flags' to all the `bmap_nodes'# present in
  225. * `bmap'.
  226. */
  227. void
  228. map_set_bnode_flag(map_bnode * bmap, int bmap_nodes, int flags)
  229. {
  230. int e;
  231. for (e = 0; e < bmap_nodes; e++)
  232. bmap[e].flags |= flags;
  233. }
  234. /*
  235. * bmaps_set_bnode_flag: sets the `flags' to all the bnodes present in the
  236. * `levels'# `bmap'.
  237. */
  238. void
  239. bmaps_set_bnode_flag(map_bnode ** bmap, int *bmap_nodes, int levels,
  240. int flags)
  241. {
  242. int i;
  243. for (i = 0; i < levels; i++)
  244. map_set_bnode_flag(bmap[i], bmap_nodes[i], flags);
  245. }
  246. /*
  247. * pack_all_bmaps: It creates the block of all the `bmaps' which have
  248. * `bmap_nodes' nodes. `ext_map' and `quadg' are the structs referring
  249. * to the external map. In `pack_sz' is stored the size of the block.
  250. * The address pointing to the block is returned otherwise 0 is given.
  251. * The package will be in network order.
  252. */
  253. char *
  254. pack_all_bmaps(map_bnode ** bmaps, u_int * bmap_nodes,
  255. map_gnode ** ext_map, quadro_group quadg, size_t * pack_sz)
  256. {
  257. struct bnode_maps_hdr bmaps_hdr;
  258. size_t sz, tmp_sz[BMAP_LEVELS(quadg.levels)];
  259. char *pack[BMAP_LEVELS(quadg.levels)], *final_pack, *buf;
  260. u_char level;
  261. *pack_sz = 0;
  262. for (level = 0; level < BMAP_LEVELS(quadg.levels); level++) {
  263. pack[level] =
  264. pack_map((map_node *) bmaps[level],
  265. (int *) ext_map[_EL(level + 1)], bmap_nodes[level], 0,
  266. &sz);
  267. tmp_sz[level] = sz;
  268. (*pack_sz) += sz;
  269. }
  270. bmaps_hdr.levels = BMAP_LEVELS(quadg.levels);
  271. bmaps_hdr.bmaps_block_sz = *pack_sz;
  272. (*pack_sz) += sizeof(struct bnode_maps_hdr);
  273. final_pack = xmalloc((*pack_sz));
  274. memcpy(final_pack, &bmaps_hdr, sizeof(struct bnode_maps_hdr));
  275. ints_host_to_network(final_pack, bnode_maps_hdr_iinfo);
  276. buf = final_pack + sizeof(struct bnode_maps_hdr);
  277. for (level = 0; level < BMAP_LEVELS(quadg.levels); level++) {
  278. memcpy(buf, pack[level], tmp_sz[level]);
  279. buf += tmp_sz[level];
  280. xfree(pack[level]);
  281. }
  282. return final_pack;
  283. }
  284. /*
  285. * unpack_all_bmaps: Given a block `pack' of size `pack_sz' containing `levels'
  286. * it unpacks each bnode map it finds in it.
  287. * `ext_map' is the external map used by the new bmaps.
  288. * In `bmap_nodes' unpack_all_bmaps stores the address of the newly xmallocated
  289. * array of u_int. Each bmap_nodes[x] contains the number of nodes of the bmap
  290. * of level x.
  291. * `maxbnodes' is the maximum number of nodes each bmap can contain,
  292. * while `maxbnode_rnodeblock' is the maximum number of rnodes each node can
  293. * contain.
  294. * On error 0 is returned.
  295. * Note: `pack' will be modified during the unpacking.
  296. */
  297. map_bnode **
  298. unpack_all_bmaps(char *pack, u_char max_levels, map_gnode ** ext_map,
  299. u_int ** bmap_nodes, int maxbnodes,
  300. int maxbnode_rnodeblock)
  301. {
  302. struct bnode_maps_hdr *bmaps_hdr;
  303. struct bnode_map_hdr *bmap_hdr;
  304. map_bnode **bmap, *unpacked_bmap;
  305. size_t bblock_sz, pack_sz;
  306. int i, e = 0;
  307. char *bblock, *buf;
  308. u_char levels;
  309. bmaps_hdr = (struct bnode_maps_hdr *) pack;
  310. ints_network_to_host(bmaps_hdr, bnode_maps_hdr_iinfo);
  311. levels = bmaps_hdr->levels;
  312. pack_sz = bmaps_hdr->bmaps_block_sz;
  313. if (levels > max_levels || pack_sz < sizeof(struct bnode_maps_hdr))
  314. return 0;
  315. bmap_levels_init(levels, &bmap, bmap_nodes);
  316. buf = pack + sizeof(struct bnode_maps_hdr);
  317. for (i = 0; i < levels; i++) {
  318. bmap_hdr = (struct bnode_map_hdr *) buf;
  319. if (!bmap_hdr->bnode_map_sz) {
  320. buf += sizeof(struct bnode_map_hdr);
  321. continue;
  322. }
  323. /*Extracting the map... */
  324. bblock = (char *) bmap_hdr;
  325. unpacked_bmap = unpack_map(bblock, (int *) ext_map[_EL(i + 1)], 0,
  326. maxbnodes, maxbnode_rnodeblock);
  327. if (!unpacked_bmap) {
  328. error("Cannot unpack the bnode_map at level %d ! Skipping...",
  329. i);
  330. e++;
  331. continue;
  332. }
  333. (*bmap_nodes)[i] = bmap_hdr->bnode_map_sz / MAP_BNODE_PACK_SZ;
  334. bblock_sz =
  335. INT_MAP_BLOCK_SZ(bmap_hdr->bnode_map_sz, bmap_hdr->rblock_sz);
  336. bmap[i] = unpacked_bmap;
  337. buf += bblock_sz;
  338. }
  339. if (e == levels)
  340. /* Not a single map was restored */
  341. return 0;
  342. return bmap;
  343. }
  344. /* * * save/load bnode_map * * */
  345. /*
  346. * save_bmap: It saves the bnode maps `bmaps' in `file'. The each `bmaps[x]' has
  347. * `bmap_nodes[x]' nodes. `ext_map' is the pointer to the external map the bmap is
  348. * referring to.
  349. */
  350. int
  351. save_bmap(map_bnode ** bmaps, u_int * bmap_nodes, map_gnode ** ext_map,
  352. quadro_group quadg, char *file)
  353. {
  354. FILE *fd;
  355. char *pack;
  356. size_t pack_sz;
  357. pack = pack_all_bmaps(bmaps, bmap_nodes, ext_map, quadg, &pack_sz);
  358. if (!pack_sz || !pack)
  359. return 0;
  360. if ((fd = fopen(file, "w")) == NULL) {
  361. error("Cannot save the bnode_map in %s: %s", file,
  362. strerror(errno));
  363. return -1;
  364. }
  365. fwrite(pack, pack_sz, 1, fd);
  366. xfree(pack);
  367. fclose(fd);
  368. return 0;
  369. }
  370. /*
  371. * load_bmap: It loads all the bnode maps from `file' and returns the address
  372. * of the array of pointer to the loaded bmaps. `ext_map' is the external maps
  373. * the bmap shall refer to. In `bmap_nodes' the address of the u_int array, used
  374. * to count the nodes in each bmaps, is stored. On error 0 is returned.
  375. */
  376. map_bnode **
  377. load_bmap(char *file, map_gnode ** ext_map, u_char max_levels,
  378. u_int ** bmap_nodes)
  379. {
  380. map_bnode **bmap = 0;
  381. FILE *fd;
  382. struct bnode_maps_hdr bmaps_hdr;
  383. size_t pack_sz;
  384. u_char levels;
  385. char *pack = 0;
  386. if ((fd = fopen(file, "r")) == NULL) {
  387. error("Cannot load the bmap from %s: %s", file, strerror(errno));
  388. return 0;
  389. }
  390. if (!fread(&bmaps_hdr, sizeof(struct bnode_maps_hdr), 1, fd))
  391. goto finish;
  392. ints_network_to_host(&bmaps_hdr, bnode_maps_hdr_iinfo);
  393. levels = bmaps_hdr.levels;
  394. pack_sz = bmaps_hdr.bmaps_block_sz;
  395. if (levels > max_levels || pack_sz < sizeof(struct bnode_maps_hdr))
  396. goto finish;
  397. /* Extracting the map... */
  398. rewind(fd);
  399. pack = xmalloc(pack_sz);
  400. if (!fread(pack, pack_sz, 1, fd))
  401. goto finish;
  402. bmap = unpack_all_bmaps(pack, max_levels, ext_map, bmap_nodes,
  403. MAXGROUPNODE, MAXBNODE_RNODEBLOCK);
  404. finish:
  405. fclose(fd);
  406. if (pack)
  407. xfree(pack);
  408. if (!bmap)
  409. error("Malformed bmap file. Cannot load the bnode maps.");
  410. return bmap;
  411. }