/** * Request ready. * @ingroup globus_gass_transfer_protocol * * This function notifies the GASS Transfer Library that new request * generated by a client has begun processing in a protocol module, * and that protocol module is now ready to send or receive data to handle * this request. * * @param request * The request handle used for this request. This was created by * the user calling one of the functions in the "@ref * globus_gass_transfer_client" section of this manual. * @param proto * The protocol-module specific request structure. This structure * contains a set of function pointers to allow GASS to continue * to process this request. * * @see globus_gass_transfer_proto_request_referred(), * globus_gass_transfer_proto_request_denied() */ void globus_gass_transfer_proto_request_ready( globus_gass_transfer_request_t request, globus_gass_transfer_request_proto_t * proto) { globus_gass_transfer_request_struct_t * req; globus_gass_transfer_callback_t callback; void * callback_arg; globus_i_gass_transfer_lock(); req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { goto finish; } switch(req->status) { case GLOBUS_GASS_TRANSFER_REQUEST_STARTING3: req->status = GLOBUS_GASS_TRANSFER_REQUEST_PENDING; req->proto = proto; if(req->type == GLOBUS_GASS_TRANSFER_REQUEST_TYPE_PUT || req->type == GLOBUS_GASS_TRANSFER_REQUEST_TYPE_APPEND) { globus_i_gass_transfer_recv_dispatcher(request); } else { globus_i_gass_transfer_send_dispatcher(request); } globus_i_gass_transfer_unlock(); return; case GLOBUS_GASS_TRANSFER_REQUEST_STARTING: req->status = GLOBUS_GASS_TRANSFER_REQUEST_PENDING; req->proto = proto; callback = req->callback; callback_arg = req->callback_arg; globus_i_gass_transfer_unlock(); callback(callback_arg, request); return; case GLOBUS_GASS_TRANSFER_REQUEST_USER_FAIL: case GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL3: req->status = GLOBUS_GASS_TRANSFER_REQUEST_FAILED; req->proto = proto; callback = req->callback; callback_arg = req->callback_arg; globus_i_gass_transfer_unlock(); callback(callback_arg, request); globus_i_gass_transfer_lock(); /* free up references to request and proto */ req->proto->destroy(req->proto, request); /* free up GASS's reference to this request */ globus_i_gass_transfer_request_destroy(request); break; case GLOBUS_GASS_TRANSFER_REQUEST_ACTING: case GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_REFERRING: case GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_FAILING: case GLOBUS_GASS_TRANSFER_REQUEST_PENDING: case GLOBUS_GASS_TRANSFER_REQUEST_FAILED: case GLOBUS_GASS_TRANSFER_REQUEST_REFERRING: case GLOBUS_GASS_TRANSFER_REQUEST_REFERRED: case GLOBUS_GASS_TRANSFER_REQUEST_DENIED: case GLOBUS_GASS_TRANSFER_REQUEST_DONE: case GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL1: case GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL2: case GLOBUS_GASS_TRANSFER_REQUEST_STARTING2: case GLOBUS_GASS_TRANSFER_REQUEST_ACCEPTING: case GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_PENDING: case GLOBUS_GASS_TRANSFER_REQUEST_FAILING: case GLOBUS_GASS_TRANSFER_REQUEST_FINISHING: globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_ACTING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_REFERRING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_FAILING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_PENDING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_FAILED); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_REFERRING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_REFERRED); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_DENIED); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_DONE); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL1); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL2); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_STARTING2); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_ACCEPTING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_PENDING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_FAILING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_FINISHING); /* FALLSTHROUGH */ case GLOBUS_GASS_TRANSFER_REQUEST_INVALID: goto finish; } finish: globus_i_gass_transfer_unlock(); return; }
/** * Receive a byte array associated with a request handle. * @ingroup globus_gass_transfer_data * * This function receives a block of data from a server or client as * part of the processing for a request. Multiple data blocks may be * registered with the GASS transfer library at once. * * When processing a server request, this function may only be used in * conjunction with "put" or "append" requests. The user must call * globus_gass_transfer_authorize() before calling this function. * * When processing a client request, this function may only be used in * conjunction with "get" requests. This function may not * be called before either the callback function has been invoked, or the * blocking globus_gass_tranfser_put() or globus_gass_transfer_append() * function has returned. * * @param request * The request handle with which this block of bytes is associated. * @param bytes * A user-supplied buffer containing the data associated with the * request. * @param max_length * The length of the @a bytes array. * @param wait_for_length * The minimum amount of data to wait for before invoking the @a * callback function. A partial byte array of at least this amount * will be returned in the callback, unless end-of-file is reached * before this amount. * @param callback * Function to call once the @a bytes array has been received. * @param user_arg * Argument to be passed to the @a callback function. * * @retval GLOBUS_SUCCESS * The @a bytes array was successfully registered with the GASS * transfer library. The @a callback function will be invoked once * it has been received. * @retval GLOBUS_GASS_TRANSFER_ERROR_NULL_POINTER * The @a bytes or @a callback parameter was NULL. * @retval GLOBUS_GASS_TRANSFER_ERROR_INVALID_USER * The @a request was invalid, or it is not one on which bytes * can be sent. * @retval GLOBUS_GASS_TRANSFER_ERROR_NOT_INITIALIZED * The callback to a non-blocking file request has not been invoked * yet, a blocking file request has not returned, or the request has * not yet been authorized. * @retval GLOBUS_GASS_TRANSFER_ERROR_REQUEST_FAILED * The @a request has failed by either the client, server, or protocol * module implementation. * @retval GLOBUS_GASS_TRANSFER_ERROR_DONE * The @a request has already been completed. */ int globus_gass_transfer_receive_bytes( globus_gass_transfer_request_t request, globus_byte_t * bytes, globus_size_t max_length, globus_size_t wait_for_length, globus_gass_transfer_bytes_callback_t callback, void * user_arg) { int rc; globus_gass_transfer_pending_t * pending; globus_gass_transfer_request_struct_t * req; globus_i_gass_transfer_lock(); /* Sanity check on passed arguments */ if(bytes == GLOBUS_NULL) { rc = GLOBUS_GASS_TRANSFER_ERROR_NULL_POINTER; goto error_exit; } if(callback == GLOBUS_NULL) { rc = GLOBUS_GASS_TRANSFER_ERROR_NULL_POINTER; goto error_exit; } req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { rc = GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE; goto error_exit; } /* * Verify that the request is in a state that allows new data * blocks to be received */ rc = globus_l_gass_transfer_state_check(req); if(rc != GLOBUS_SUCCESS) { goto error_exit; } if(req->client_side == GLOBUS_FALSE && req->type != GLOBUS_GASS_TRANSFER_REQUEST_TYPE_PUT && req->type != GLOBUS_GASS_TRANSFER_REQUEST_TYPE_APPEND) { rc = GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE; goto error_exit; } else if(req->client_side != GLOBUS_FALSE && req->type != GLOBUS_GASS_TRANSFER_REQUEST_TYPE_GET) { rc = GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE; goto error_exit; } /* * Create a pending data structure, to be queued up in the request's * fifo. */ pending = (globus_gass_transfer_pending_t *) globus_malloc(sizeof(globus_gass_transfer_pending_t)); if(pending == GLOBUS_NULL) { rc = GLOBUS_GASS_TRANSFER_ERROR_MALLOC_FAILED; goto error_exit; } pending->last_data = GLOBUS_FALSE; pending->length = max_length; pending->wait_for_length = wait_for_length; pending->pending = GLOBUS_FALSE; pending->request = request; pending->bytes = bytes; pending->callback = callback; pending->callback_arg = user_arg; globus_fifo_enqueue(&req->pending_data, pending); /* * Call the recv dispatcher to (maybe) receive some more data from the * protocol module. */ globus_i_gass_transfer_recv_dispatcher(request); globus_i_gass_transfer_unlock(); return GLOBUS_SUCCESS; error_exit: globus_i_gass_transfer_unlock(); return rc; }