code: def start_client(num_clients, num_servers):
      os.environ["DGL_DIST_MODE"] = "distributed"
      # Note: connect to server first !
      dgl.distributed.initialize(ip_config="kv_ip_config.txt")
      # Init kvclient
      kvclient = dgl.distributed.KVClient(
          ip_config="kv_ip_config.txt", num_servers=num_servers
      )
      kvclient.map_shared_data(partition_book=gpb)
      assert dgl.distributed.get_num_client() == num_clients
      kvclient.init_data(
          name="data_1",
          shape=F.shape(data_1),
          dtype=F.dtype(data_1),
          part_policy=edge_policy,
          init_func=init_zero_func,
      )
      kvclient.init_data(
          name="data_2",
          shape=F.shape(data_2),
          dtype=F.dtype(data_2),
          part_policy=node_policy,
          init_func=init_zero_func,
      )
  
      # Test data_name_list
      name_list = kvclient.data_name_list()
      print(name_list)
      assert "data_0" in name_list
      assert "data_0_1" in name_list
      assert "data_0_2" in name_list
      assert "data_0_3" in name_list
      assert "data_1" in name_list
      assert "data_2" in name_list
      # Test get_meta_data
      meta = kvclient.get_data_meta("data_0")
      dtype, shape, policy = meta
      assert dtype == F.dtype(data_0)
      assert shape == F.shape(data_0)
      assert policy.policy_str == "node~_N"
  
      meta = kvclient.get_data_meta("data_0_1")
      dtype, shape, policy = meta
      assert dtype == F.dtype(data_0_1)
      assert shape == F.shape(data_0_1)
      assert policy.policy_str == "node~_N"
  
      meta = kvclient.get_data_meta("data_0_2")
      dtype, shape, policy = meta
      assert dtype == F.dtype(data_0_2)
      assert shape == F.shape(data_0_2)
      assert policy.policy_str == "node~_N"
  
      meta = kvclient.get_data_meta("data_0_3")
      dtype, shape, policy = meta
      assert dtype == F.dtype(data_0_3)
      assert shape == F.shape(data_0_3)
      assert policy.policy_str == "node~_N"
  
      meta = kvclient.get_data_meta("data_1")
      dtype, shape, policy = meta
      assert dtype == F.dtype(data_1)
      assert shape == F.shape(data_1)
      assert policy.policy_str == "edge~_N:_E:_N"
  
      meta = kvclient.get_data_meta("data_2")
      dtype, shape, policy = meta
      assert dtype == F.dtype(data_2)
      assert shape == F.shape(data_2)
      assert policy.policy_str == "node~_N"
  
      # Test push and pull
      id_tensor = F.tensor([0, 2, 4], F.int64)
      data_tensor = F.tensor(
          [[6.0, 6.0], [6.0, 6.0], [6.0, 6.0]], F.float32
      )
      kvclient.push(
          name="data_0", id_tensor=id_tensor, data_tensor=data_tensor
      )
      kvclient.push(
          name="data_1", id_tensor=id_tensor, data_tensor=data_tensor
      )
      kvclient.push(
          name="data_2", id_tensor=id_tensor, data_tensor=data_tensor
      )
      res = kvclient.pull(name="data_0", id_tensor=id_tensor)
      assert_array_equal(F.asnumpy(res), F.asnumpy(data_tensor))
      res = kvclient.pull(name="data_1", id_tensor=id_tensor)
      assert_array_equal(F.asnumpy(res), F.asnumpy(data_tensor))
      res = kvclient.pull(name="data_2", id_tensor=id_tensor)
      assert_array_equal(F.asnumpy(res), F.asnumpy(data_tensor))
      # Register new push handler
      kvclient.register_push_handler("data_0", udf_push)
      kvclient.register_push_handler("data_1", udf_push)
      kvclient.register_push_handler("data_2", udf_push)
      # Test push and pull
      kvclient.push(
          name="data_0", id_tensor=id_tensor, data_tensor=data_tensor
      )
      kvclient.push(
          name="data_1", id_tensor=id_tensor, data_tensor=data_tensor
      )
      kvclient.push(
          name="data_2", id_tensor=id_tensor, data_tensor=data_tensor
      )
      kvclient.barrier()
      data_tensor = data_tensor * data_tensor
      res = kvclient.pull(name="data_0", id_tensor=id_tensor)
      assert_array_equal(F.asnumpy(res), F.asnumpy(data_tensor))
      res = kvclient.pull(name="data_1", id_tensor=id_tensor)
      assert_array_equal(F.asnumpy(res), F.asnumpy(data_tensor))
      res = kvclient.pull(name="data_2", id_tensor=id_tensor)
      assert_array_equal(F.asnumpy(res), F.asnumpy(data_tensor))
  
      # Test delete data
      kvclient.delete_data("data_0")
      kvclient.delete_data("data_1")
      kvclient.delete_data("data_2")
  
      # Register new push handler
      kvclient.init_data(
          name="data_3",
          shape=F.shape(data_2),
          dtype=F.dtype(data_2),
          part_policy=node_policy,
          init_func=init_zero_func,
      )
      kvclient.register_push_handler("data_3", add_push)
      data_tensor = F.tensor(
          [[6.0, 6.0], [6.0, 6.0], [6.0, 6.0]], F.float32
      )
      kvclient.barrier()
      time.sleep(kvclient.client_id + 1)
      print("add...")
      kvclient.push(
          name="data_3", id_tensor=id_tensor, data_tensor=data_tensor
      )
      kvclient.barrier()
      res = kvclient.pull(name="data_3", id_tensor=id_tensor)
      data_tensor = data_tensor * num_clients
      assert_array_equal(F.asnumpy(res), F.asnumpy(data_tensor))
  
imports: import multiprocessing
  import os
  import socket
  import time
  import unittest
  import backend
  import dgl
  import numpy
  from dgl.graph_index import create_graph_index
  from numpy.testing import assert_array_equal
  from scipy import sparse
  from utils import generate_ip_config, reset_envs
label_desc: Use image node_id 7 for calling a global function with example usage: start_client(num_clients, num_servers) without return types