Advertisement
Guest User

table.c

a guest
Dec 18th, 2015
304
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.00 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdint.h>
  4. #include <stdbool.h>
  5. #include <string.h>
  6. #include <sys/time.h>
  7.  
  8. static inline uint32_t
  9. read_ip(FILE *in)
  10. {
  11.     unsigned ip[4];
  12.     if (fscanf(in, " %u.%u.%u.%u", ip, ip + 1, ip + 2, ip + 3) == 4)
  13.         return (ip[0] << 24) | (ip[1] << 16) | (ip[2] << 8) | ip[3];
  14.     return 0;
  15. }
  16.  
  17. static struct {
  18.     uint32_t count;
  19.     uint32_t max;
  20.     char **s;
  21. } intern_table;
  22.  
  23. static uint32_t
  24. intern(const char *s)
  25. {
  26.     for (uint32_t i = 0; i < intern_table.count; i++)
  27.         if (strcmp(intern_table.s[i], s) == 0)
  28.             return i;
  29.     if (intern_table.count == intern_table.max) {
  30.         intern_table.max = intern_table.max == 0 ? 4096 : intern_table.max * 2;
  31.         intern_table.s = realloc(intern_table.s,
  32.                                  intern_table.max * sizeof(*intern_table.s));
  33.     }
  34.     char *copy = malloc(strlen(s) + 1);
  35.     strcpy(copy, s);
  36.     intern_table.s[intern_table.count] = copy;
  37.     return intern_table.count++;
  38. }
  39.  
  40. static const char *
  41. lookup(uint32_t n)
  42. {
  43.     return intern_table.s[n];
  44. }
  45.  
  46. struct source {
  47.     uint32_t min;
  48.     uint32_t max;
  49.     uint32_t name;
  50. };
  51.  
  52. static inline bool
  53. scanline(struct source *e, FILE *in)
  54. {
  55.     e->min = read_ip(in);
  56.     e->max = read_ip(in);
  57.     char name[256];
  58.     if (e->min && e->max && fscanf(in, " %[^\n]", name) == 1) {
  59.         e->name = intern(name);
  60.         return true;
  61.     }
  62.     return false;
  63. }
  64.  
  65. struct slot {
  66.     uint32_t start;
  67.     uint32_t stop;
  68.     uint32_t source;
  69. };
  70.  
  71. struct table {
  72.     uint32_t count;
  73.     struct slot slot[];
  74. };
  75.  
  76. struct event {
  77.     uint32_t when;
  78.     struct source *who;
  79.     enum { E_ADD, E_DEL } type;
  80. };
  81.  
  82. static int
  83. uint32_cmp(const void *va, const void *vb)
  84. {
  85.     uint32_t a = *(uint32_t *)va;
  86.     uint32_t b = *(uint32_t *)vb;
  87.     if (a < b)
  88.         return -1;
  89.     else if (b < a)
  90.         return 1;
  91.     else
  92.         return 0;
  93. }
  94.  
  95. static struct table *
  96. table_create(struct source *source, uint32_t count)
  97. {
  98.     struct event *event = malloc(sizeof(*event) * count * 2);
  99.     for (uint32_t i = 0; i < count; i++) {
  100.         event[i * 2 + 0] = (struct event){
  101.             source[i].min + 0, &source[i], E_ADD
  102.         };
  103.         event[i * 2 + 1] = (struct event){
  104.             source[i].max + 1, &source[i], E_DEL
  105.         };
  106.     }
  107.     qsort(event, count * 2, sizeof(*event), uint32_cmp);
  108.  
  109.     struct table *table;
  110.     size_t size = sizeof(*table) + sizeof(*table->slot) * count * 2;
  111.     table = malloc(size);
  112.     table->count = 0;
  113.  
  114.     struct source **member = malloc(sizeof(*member) * count);
  115.     uint32_t member_count = 0;
  116.     uint32_t start;
  117.     for (uint32_t i = 0; i < count * 2; i++) {
  118.         if (member_count > 0) {
  119.             struct slot *s = &table->slot[table->count++];
  120.             s->start = start;
  121.             s->stop = event[i].when;
  122.             s->source = member[0]->name;
  123.             uint32_t smallest = member[0]->max - member[0]->min;
  124.             for (uint32_t m = 1; m < member_count; m++) {
  125.                 uint32_t range = member[m]->max - member[m]->min;
  126.                 if (range < smallest) {
  127.                     s->source = member[m]->name;
  128.                     smallest = range;
  129.                 }
  130.             }
  131.         }
  132.         start = event[i].when;
  133.         switch (event[i].type) {
  134.             case E_DEL:
  135.                 for (uint32_t m = member_count - 1; m < member_count; m--)
  136.                     if (member[m] == event[i].who) {
  137.                         member[m] = member[--member_count];
  138.                         break;
  139.                     }
  140.                 break;
  141.             case E_ADD:
  142.                 member[member_count++] = event[i].who;
  143.                 break;
  144.         }
  145.     }
  146.     free(member);
  147.     free(event);
  148.     return table;
  149. }
  150.  
  151. static int
  152. search(const void *k, const void *m)
  153. {
  154.     uint32_t ip = *(uint32_t *)k;
  155.     struct slot *slot = (struct slot *)m;
  156.     if (ip < slot->start)
  157.         return -1;
  158.     else if (ip >= slot->stop)
  159.         return 1;
  160.     else
  161.         return 0;
  162. }
  163.  
  164. static struct slot *
  165. table_search(struct table *t, uint32_t ip)
  166. {
  167.     return bsearch(&ip, t->slot, t->count, sizeof(*t->slot), search);
  168. }
  169.  
  170. static uint64_t
  171. uepoch(void)
  172. {
  173.     struct timeval tv;
  174.     gettimeofday(&tv, NULL);
  175.     return 1000000LL * tv.tv_sec + tv.tv_usec;
  176. }
  177.  
  178. int
  179. main(int argc, char **argv)
  180. {
  181.     fprintf(stderr, "Reading entries ...\n");
  182.     (void)argc;
  183.     FILE *range = fopen(argv[1], "r");
  184.     uint32_t source_max = 64 * 1024;
  185.     uint32_t source_count = 0;
  186.     struct source *source = malloc(sizeof(*source) * source_max);
  187.     while (scanline(&source[source_count], range)) {
  188.         if (++source_count == source_max) {
  189.             source_max *= 2;
  190.             source = realloc(source, sizeof(*source) * source_max);
  191.         }
  192.     }
  193.     fclose(range);
  194.     source[source_count++] = (struct source){
  195.         0, UINT32_MAX - 1, intern("<unknown>")
  196.     };
  197.  
  198.     fprintf(stderr, "Constructing table ...\n");
  199.     struct table *table = table_create(source, source_count);
  200.     free(source);
  201.     struct {
  202.         uint32_t count;
  203.         uint32_t name;
  204.     } *counts = malloc(sizeof(*counts) * intern_table.count);
  205.     for (uint32_t i = 0; i < intern_table.count; i++) {
  206.         counts[i].count = 0;
  207.         counts[i].name = i;
  208.     }
  209.  
  210.     fprintf(stderr, "Sorting IPs ...\n");
  211.     uint64_t start = uepoch();
  212.     uint32_t ip;
  213.     uint64_t total = 0;
  214.     while ((ip = read_ip(stdin))) {
  215.         struct slot *s = table_search(table, ip);
  216.         counts[s->source].count++;
  217.         total++;
  218.     }
  219.  
  220.     /* Print results */
  221.     qsort(counts, intern_table.count, sizeof(*counts), uint32_cmp);
  222.     for (uint32_t i = intern_table.count - 1; i < intern_table.count; i--)
  223.         if (counts[i].count)
  224.             printf("%u - %s\n",
  225.                    (unsigned)counts[i].count, lookup(counts[i].name));
  226.  
  227.     double delta = (uepoch() - start) / 1000000.0;
  228.     fprintf(stderr, "Elapsed: %f sec (%f ip/sec)\n", delta, total / delta);
  229.     return 0;
  230. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement