1#!/usr/bin/env python
2
3import memcache
4import struct
5import sys
6import os
7import binascii
8
9"""
10/* blob format for storing:
11
12    char magic[4]; # 'CCH1', might change for other version of ccache
13                   # ccache will erase the blob in memcached if wrong magic
14    uint32_t obj_len; # network endian
15    char *obj[obj_len];
16    uint32_t stderr_len; # network endian
17    char *stderr[stderr_len];
18    uint32_t dia_len; # network endian
19    char *dia[dia_len];
20    uint32_t dep_len; # network endian
21    char *dep[dep_len];
22
23*/
24"""
25MEMCCACHE_MAGIC = 'CCH1'
26
27def get_blob(token):
28    return token[4:4+struct.unpack('!I', val[0:4])[0]]
29MEMCCACHE_BIG = 'CCBM'
30
31"""
32/* blob format for big values:
33
34    char magic[4]; # 'CCBM'
35    uint32_t numkeys; # network endian
36    uint32_t hash_size; # network endian
37    uint32_t reserved; # network endian
38    uint32_t value_length; # network endian
39
40    <hash[0]>       hash of include file                (<hash_size> bytes)
41    <size[0]>       size of include file                (4 bytes unsigned int)
42    ...
43    <hash[n-1]>
44    <size[n-1]>
45
46*/
47"""
48MEMCCACHE_BIG = 'CCBM'
49
50server = os.getenv("MEMCACHED_SERVERS", "localhost")
51mc = memcache.Client(server.split(','), debug=1)
52
53key = sys.argv[1]
54val = mc.get(key)
55if val[0:4] == MEMCCACHE_BIG:
56    numkeys = struct.unpack('!I', val[4:8])[0]
57    assert struct.unpack('!I', val[8:12])[0] == 16
58    assert struct.unpack('!I', val[12:16])[0] == 0
59    size = struct.unpack('!I', val[16:20])[0]
60    val = val[20:]
61    buf = ""
62    while val:
63        md4 = val[0:16]
64        size = struct.unpack('!I', val[16:20])[0]
65        val = val[20:]
66        subkey = "%s-%d" % (binascii.hexlify(md4), size)
67        subval = mc.get(subkey)
68        if not subval:
69            print "%s not found" % subkey
70        buf = buf + subval
71    val = buf
72if val:
73    magic = val[0:4]
74    if magic == MEMCCACHE_MAGIC:
75        val = val[4:]
76        obj = get_blob(val)
77        val = val[4+len(obj):]
78        stderr = get_blob(val)
79        val = val[4+len(stderr):]
80        dia = get_blob(val)
81        val = val[4+len(dia):]
82        dep = get_blob(val)
83        val = val[4+len(dep):]
84        assert len(val) == 0
85        print "%s: %d %d %d %d" % (key, len(obj), len(stderr), len(dia), len(dep))
86    else:
87        print "wrong magic"
88else:
89    print "key missing"
90