client.py 6.15 KB
Newer Older
Matthieu Dorier's avatar
Matthieu Dorier committed
1 2
# (C) 2018 The University of Chicago
# See COPYRIGHT in top-level directory.
Matthieu Dorier's avatar
Matthieu Dorier committed
3
import _pybakeclient
4
from pybake.target import *
Matthieu Dorier's avatar
Matthieu Dorier committed
5 6 7
import pymargo

class BakeClient():
8 9 10 11 12
    """
    The BakeClient class wraps a bake_client_t structure at C level.
    It registers the RPCs necessary to interact with a Bake provider.
    It can be used to create provider handles pointing to Bake providers.
    """
Matthieu Dorier's avatar
Matthieu Dorier committed
13

14 15 16
    def __init__(self, mid):
        """
        Constructor. Initializes a new BakeClient with a MargoInstance.
Matthieu Dorier's avatar
Matthieu Dorier committed
17

18 19 20 21
        Args:
            mid (MargoInstance): MargoInstance on which to register RPCs.
        """
        self._client = _pybakeclient.client_init(mid._mid)
Matthieu Dorier's avatar
Matthieu Dorier committed
22

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
    def create_provider_handle(self, addr, provider_id):
        """
        Creates a BakeProviderHandle object pointing to the given
        address and provider id.

        Args:
            addr (MargoAddress): Address of the Bake provider.
            provider_id (int): ID of the provider.
        """
        ph = _pybakeclient.provider_handle_create(self._client, addr.get_hg_addr(), provider_id)
        return BakeProviderHandle(ph)

    def shutdown_service(self, addr):
        """
        Shut down a MargoInstance running at a particular address.

        Args:
            addr (MargoAddress): Address of the MargoInstance to shut down.
        """
        _pybakeclient.shutdown_service(self._client, addr.get_hg_addr())
Matthieu Dorier's avatar
Matthieu Dorier committed
43
	
44 45 46 47 48
    def finalize(self):
        """
        Finalizes the underlying bake_client_t structure.
        """
        _pybakeclient.client_finalize(self._client)
Matthieu Dorier's avatar
Matthieu Dorier committed
49 50

class BakeProviderHandle():
51 52 53 54
    """
    The BakeProviderHandle class represents a handle to a remote Bake provider.
    Internally, this class wraps a bake_provider_handle_t C structure.
    """
Matthieu Dorier's avatar
Matthieu Dorier committed
55

56 57 58 59 60 61 62
    def __init__(self, ph):
        """
        Constructor. This is not supposed to be called by users.
        Users should create a BakeProviderHandle from a BakeClient clt
        by calling clt.create_provider_handle.
        """
        self._ph = ph
Matthieu Dorier's avatar
Matthieu Dorier committed
63
	
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
    def __del__(self):
        """
        Explicit destructor to call provider_handle_release on the underlying
        bake_provider_handle_t C structure.
        """
        _pybakeclient.provider_handle_release(self._ph)

    def get_eager_limit(self):
        """
        Get the threshold size bellow which this provider
        handle will embed data within the RPC arguments.
        """
        return _pybakeclient.get_eager_limit(self._ph)

    def set_eager_limit(self, limit):
        """
        Set the threshold size bellow which this provider handle
        will embed data within the RPC arguments.
        """ 
        return _pybakeclient.set_eager_limit(self._ph, limit)

    def probe(self, max_targets=0):
        """
        Get the list of BakeTargetIDs of targets located in
        this provider. If max_targets is not specified, this
        function will return all the target ids.
        """
        if(max_targets != 0):
            tgts = _pybakeclient.probe(self._ph, max_targets)
        else:
            num_targets = 32
            while(True):
                tgts = _pybakeclient.probe(self._ph, num_targets)
                if(len(tgts) == num_targets):
                    num_targets *= 2
                else:
                    break
        result = []
        for tgt in tgts:
            result.append(BakeTargetID(tgt))
        return result

    def create(self, bti, region_size):
        """
        Creates a region in the specified target, with a given size.

        Args:
            bti (BakeTargetID): ID of the bake target in which to create the region.
            region_size (int): size of the region to create.

        Returns:
            A BakeRegionID object representing the region.
        """
        rid = _pybakeclient.create(self._ph, bti._tid, region_size)
        return BakeRegionID(rid)

    def write(self, rid, offset, data):
        """
        Writes data in a region, at a specified offset.

        Args:
            rid (BakeRegionID): region in which to write.
            offset (int): offset at which to write.
            data (str): data to write.
        """
        return _pybakeclient.write(self._ph, rid._rid, offset, data)

    def persist(self, rid):
        """
        Make the changes to a given region persist.
        
        Args:
            rid (BakeRegionID): region to persist.
        """
        return _pybakeclient.persist(self._ph, rid._rid)

    def create_write_persist(self, bti, data):
        """
        Creates a new region, write data to it at a given offset,
        and persist the region.

        Args:
            bti (BakeTargetID): target id in which to create the region.
            size (int): size of the region to create.
            offset (int): offset at which to write data in the region.
            data (str): data to write.
        """
        rid = _pybakeclient.create_write_persist(self._ph, bti._tid, data)
        return BakeRegionID(rid)

    def get_size(self, rid):
        """
        Get the size of a given region.

        Args:
            rid (BakeRegionID): region id.

        Returns:
            The size (ind) of the provided region.
        """
        return _pybakeclient.get_size(self._ph, rid._rid)

    def read(self, rid, offset=0, size=-1):
        """
        Reads the data contained in a given region, at a given offset
        and with a given size. If the size is not provided,
        this function will first send an RPC to get the current region size
        and then read from the offset up to the end of the region. If the
        offset is not provided, the entire region is read.

        Args:
            rid (BakeRegionID): region id.
            offset (int): offset at which to read.
            size (int): size to read.

        Returns:
            The data read, in the form of a string, or None if an
            error occured.
        """
        if(size < 0):
            size = self.get_size(rid) - offset
        return _pybakeclient.read(self._ph, rid._rid, offset, size)
    
    def remove(self, rid):
        """
        Remove a region from its target.

        Args:
            rid (BakeRegionID): region to remove.
        """
        _pybakeclient.remove(self._ph, rid._rid)