import struct


def parse_zxid(text):
    """
    Parse a zookeeper transaction id into its epoch and number.

    zxid is the global (cluster wide) transaction identifier.
    The upper 32 bits of which are the epoch number (changes when leadership changes)
    and the lower 32 bits which are the xid (transaction id) proper
    """
    if text is None:
        return
        
    if text == '0xffffffffffffffff':
        return None
    
    # Parse as a 64 bit hex int
    zxid = int(text.strip(), 16)

    # convert to bytes
    try:
        zxid_bytes = struct.pack('>q', zxid)
    except struct.error as e:
        raise ValueError("Unable to pack struct, from value: %s, input: %s - %s" % (zxid, text, e))
    # the higher order 4 bytes is the epoch
    (zxid_epoch,) = struct.unpack('>i', zxid_bytes[0:4])
    # the lower order 4 bytes is the count
    (zxid_count,) = struct.unpack('>i', zxid_bytes[4:8])

    return zxid_epoch, zxid_count