# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. """Base definitions for RPC.""" # pylint: disable=invalid-name import errno import json import logging import random import socket import struct import time # Magic header for RPC data plane RPC_MAGIC = 0xFF271 # magic header for RPC tracker(control plane) RPC_TRACKER_MAGIC = 0x2F271 # sucess response RPC_CODE_SUCCESS = RPC_MAGIC + 0 # duplicate key in proxy RPC_CODE_DUPLICATE = RPC_MAGIC + 1 # cannot found matched key in server RPC_CODE_MISMATCH = RPC_MAGIC + 2 logger = logging.getLogger("RPCServer") class TrackerCode: """Enumeration code for the RPC tracker""" FAIL = -1 SUCCESS = 0 PING = 1 STOP = 2 PUT = 3 REQUEST = 4 UPDATE_INFO = 5 SUMMARY = 6 GET_PENDING_MATCHKEYS = 7 RPC_SESS_MASK = 128 # Use "127.0.0.1" or "::1" if there is a need to force ip4 or ip6 # connection for "localhost". def get_addr_family(addr): res = socket.getaddrinfo(addr[0], addr[1], 0, 0, socket.IPPROTO_TCP) return res[0][0] def recvall(sock, nbytes): """Receive all nbytes from socket. Parameters ---------- sock: Socket The socket nbytes : int Number of bytes to be received. """ res = [] nread = 0 while nread < nbytes: chunk = sock.recv(min(nbytes - nread, 1024)) if not chunk: raise OSError("connection reset") nread += len(chunk) res.append(chunk) return b"".join(res) def sendjson(sock, data): """send a python value to remote via json Parameters ---------- sock : Socket The socket data : object Python value to be sent. """ data = json.dumps(data) sock.sendall(struct.pack(" timeout: raise RuntimeError(f"Failed to connect to server {addr!s}") logger.warning(f"Cannot connect to tracker {addr!s}, retry in {retry_period:g} secs...") time.sleep(retry_period)