The lifecycle of a forwarded CSI call is shown as follows. The transitions happen after the completions of the API calls. Unsupported Server-side +-------------+ API version +-------------+ WriteAndFinish +---+ | INITIALIZED | +---------> FINISHING +----------------> X | +------+------+ | +------^------+ +---+ Server-side | +------+ |
| 1892 | // +-------------+ +-------------+ |
| 1893 | // |
| 1894 | void CSIProxy::serve(ServerCompletionQueue* completionQueue) |
| 1895 | { |
| 1896 | // Serve the first call. The ownership of the `Call` object is passed to the |
| 1897 | // completion queue, and will be retrieved later in the loop below. |
| 1898 | Call* first = new Call(); |
| 1899 | service->RequestCall( |
| 1900 | &first->serverContext, |
| 1901 | &first->serverReaderWriter, |
| 1902 | completionQueue, |
| 1903 | completionQueue, |
| 1904 | first); |
| 1905 | |
| 1906 | void* tag; |
| 1907 | bool ok = false; |
| 1908 | |
| 1909 | // See the link below for details of `ok`: |
| 1910 | // https://grpc.io/grpc/cpp/classgrpc_1_1_completion_queue.html#a86d9810ced694e50f7987ac90b9f8c1a // NOLINT |
| 1911 | while (completionQueue->Next(&tag, &ok)) { |
| 1912 | // Retrieve the ownership of the next ready `Call` object from the |
| 1913 | // completion queue. |
| 1914 | Call* call = reinterpret_cast<Call*>(tag); |
| 1915 | |
| 1916 | switch (call->state) { |
| 1917 | case Call::State::INITIALIZED: { |
| 1918 | if (!ok) { |
| 1919 | // Server-side `RequestCall`: the server has been shutdown so continue |
| 1920 | // to drain the queue. |
| 1921 | break; |
| 1922 | } |
| 1923 | |
| 1924 | call->state = Call::State::REQUESTED; |
| 1925 | |
| 1926 | // Make a server-side `Read` call and return the ownership back to the |
| 1927 | // completion queue. |
| 1928 | call->serverReaderWriter.Read(&call->request, call); |
| 1929 | |
| 1930 | // Serve the next call while processing this one. The ownership of the |
| 1931 | // new `Call` object is passed to the completion queue, and will be |
| 1932 | // retrieved in a later iteration. |
| 1933 | Call* next = new Call(); |
| 1934 | service->RequestCall( |
| 1935 | &next->serverContext, |
| 1936 | &next->serverReaderWriter, |
| 1937 | completionQueue, |
| 1938 | completionQueue, |
| 1939 | next); |
| 1940 | |
| 1941 | break; |
| 1942 | } |
| 1943 | case Call::State::REQUESTED: { |
| 1944 | if (!ok) { |
| 1945 | // Server-side `Read`: the client has done a `WritesDone` already, so |
| 1946 | // clean up the call and move to the next iteration immediately. |
| 1947 | delete call; |
| 1948 | continue; |
| 1949 | } |
| 1950 | |
| 1951 | // The expected method names are of the following form: |
nothing calls this directly
no test coverage detected