/** * Destroy a request handle. * @ingroup globus_gass_transfer_request * * This function destroys the caller's reference to a request handle. * It must be called for all request handles which are created by calling * functions in the "@ref globus_gass_transfer_client" or * "@ref globus_gass_transfer_server" sections of this manual. * After calling the function, the caller must not attempt to use the * request handle for any purpose. * * @param request * The request to destroy. * @retval GLOBUS_SUCCESS * The request handle reference was successfully destroyed. * @retval GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE * Either an invalid request handle or one which is actively being * used was passed to this function as the @a request parameter. */ int globus_gass_transfer_request_destroy( globus_gass_transfer_request_t request) { globus_gass_transfer_request_struct_t * req; int rc; globus_i_gass_transfer_lock(); req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { rc = GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE; goto finish; } if(req->status != GLOBUS_GASS_TRANSFER_REQUEST_FAILED && req->status != GLOBUS_GASS_TRANSFER_REQUEST_DONE && req->status != GLOBUS_GASS_TRANSFER_REQUEST_FINISHING && req->status != GLOBUS_GASS_TRANSFER_REQUEST_FAILING && req->status != GLOBUS_GASS_TRANSFER_REQUEST_REFERRED && req->status != GLOBUS_GASS_TRANSFER_REQUEST_REFERRING && req->status != GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_FAILING && req->status != GLOBUS_GASS_TRANSFER_REQUEST_DENIED) { rc = GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE; goto finish; } rc = globus_i_gass_transfer_request_destroy(request); finish: globus_i_gass_transfer_unlock(); return rc; }
/* * Function: globus_gass_transfer_fail() * * Description: User-triggered error. Signal failure to the * protocol module, and call any oustanding callbacks * * Parameters: * * Returns: */ int globus_gass_transfer_fail( globus_gass_transfer_request_t request, globus_gass_transfer_callback_t callback, void * callback_arg) { globus_gass_transfer_request_struct_t * req; int rc = GLOBUS_SUCCESS; globus_i_gass_transfer_lock(); req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { rc = GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE; goto finish; } if(callback == GLOBUS_NULL) { rc = GLOBUS_GASS_TRANSFER_ERROR_NULL_POINTER; goto finish; } rc = globus_i_gass_transfer_fail(request, req, callback, callback_arg); finish: globus_i_gass_transfer_unlock(); return rc; }
/* * Function: globus_i_gass_transfer_send_disaptcher() * * Description: if the head of the pending fifo should be * sent over, send it. * * Parameters: * * Returns: */ void globus_i_gass_transfer_send_dispatcher( globus_gass_transfer_request_t request) { globus_gass_transfer_pending_t * head; globus_gass_transfer_request_struct_t * req; req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { return; } /* If we are not in the PENDING state, we should not look at the queue */ if(req->status != GLOBUS_GASS_TRANSFER_REQUEST_PENDING) { return; } /* If the fifo is empty, there is nothing to do */ if(globus_fifo_empty(&req->pending_data)) { return; } head = globus_fifo_peek(&req->pending_data); if(head->pending == GLOBUS_TRUE) { /* * If the first in the fifo has already been sent to * the protocol module, there is nothing to do */ return; } else { head->pending = GLOBUS_TRUE; req->status = GLOBUS_GASS_TRANSFER_REQUEST_ACTING; globus_i_gass_transfer_unlock(); req->proto->send_buffer(req->proto, request, head->bytes, head->length, head->last_data); globus_i_gass_transfer_lock(); } }
/** * Check the status of a request. * @ingroup globus_gass_transfer_request * * This function queries a request to determine the status of the request. * This function should be called after EOF has been reached, or after * the initial get, put, or append has returned or had it's callback function * called to determine if it is possible to procede, or whether the file * transfer was successfully processed. * * @param request * The request handle to query. * * @return A #globus_gass_transfer_request_status_t indicating * the current status of the request. */ globus_gass_transfer_request_status_t globus_gass_transfer_request_get_status( globus_gass_transfer_request_t request) { globus_gass_transfer_request_struct_t * req; req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req != GLOBUS_NULL) { switch(req->status) { case GLOBUS_GASS_TRANSFER_REQUEST_STARTING3: case GLOBUS_GASS_TRANSFER_REQUEST_PENDING: case GLOBUS_GASS_TRANSFER_REQUEST_ACTING: case GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_PENDING: case GLOBUS_GASS_TRANSFER_REQUEST_ACCEPTING: return GLOBUS_GASS_TRANSFER_REQUEST_PENDING; case GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_FAILING: case GLOBUS_GASS_TRANSFER_REQUEST_FAILING: case GLOBUS_GASS_TRANSFER_REQUEST_FAILED: case GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL1: case GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL2: case GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL3: case GLOBUS_GASS_TRANSFER_REQUEST_USER_FAIL: return GLOBUS_GASS_TRANSFER_REQUEST_FAILED; case GLOBUS_GASS_TRANSFER_REQUEST_FINISHING: case GLOBUS_GASS_TRANSFER_REQUEST_DONE: return GLOBUS_GASS_TRANSFER_REQUEST_DONE; case GLOBUS_GASS_TRANSFER_REQUEST_STARTING: case GLOBUS_GASS_TRANSFER_REQUEST_STARTING2: return GLOBUS_GASS_TRANSFER_REQUEST_STARTING; case GLOBUS_GASS_TRANSFER_REQUEST_REFERRED: case GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_REFERRING: case GLOBUS_GASS_TRANSFER_REQUEST_REFERRING: return GLOBUS_GASS_TRANSFER_REQUEST_REFERRED; case GLOBUS_GASS_TRANSFER_REQUEST_DENIED: return GLOBUS_GASS_TRANSFER_REQUEST_DENIED; case GLOBUS_GASS_TRANSFER_REQUEST_INVALID: return GLOBUS_GASS_TRANSFER_REQUEST_INVALID; } } return GLOBUS_GASS_TRANSFER_REQUEST_INVALID; }
/** * Get the subject string associated with a request. * @ingroup globus_gass_transfer_request * * This function queries a request handle to determine the subject * identity of the client who initiated the request. * The string must not be freed by the caller. * * @param request * A handle to the request to query. * * @return A string containing the request initiator's subject identity. * If the request handle is invalid or a credential was not used * to initiate the request, this value will be GLOBUS_NULL. */ char * globus_gass_transfer_request_get_subject( globus_gass_transfer_request_t request) { globus_gass_transfer_request_struct_t * req; req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { return GLOBUS_NULL; } else { return req->subject; } }
/** * Get an string describing why a request was denied. * @ingroup globus_gass_transfer_request * * This function queries a request which was denied by a server to * determine why it was denied. The denial reason will be expressed * as a response string. The string must be freed by the caller. * * @param request * A handle to the request to query. * * @return A string indicating why the request * was denied. If the request handle is invalid or the * request was not denied, then this function returns GLOBUS_NULL. * @see globus_gass_transfer_request_get_denial_reason() */ char * globus_gass_transfer_request_get_denial_message( globus_gass_transfer_request_t request) { globus_gass_transfer_request_struct_t * req; req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { return GLOBUS_NULL; } else { return globus_libc_strdup(req->denial_message); } }
/** * Get an integer code describing why the request was denied. * @ingroup globus_gass_transfer_request * * This function queries a request which was denied by a server to * determine why it was denied. The denial reason will be expressed * in a protocol-specific response code. Knowledge of the protocol * is needed to understand this response. * * @param request * A handle to the request to query. * * @return A protocol-specific integer indicating why the request * was denied. If the request handle is invalid or the * request was not denied, then this function returns 0. * @see globus_gass_transfer_request_get_denial_message() */ int globus_gass_transfer_request_get_denial_reason( globus_gass_transfer_request_t request) { globus_gass_transfer_request_struct_t * req; req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { return 0; } else { return req->denial_reason; } }
/** * Determine the type of a request. * @ingroup globus_gass_transfer_request * * This function is used by GASS server implementations to discover what * type of operation the client is requesting for an URL. * * @param request * The request to query. * * @return The @link #globus_gass_transfer_request_type_t type@endlink * of the request. */ globus_gass_transfer_request_type_t globus_gass_transfer_request_get_type( globus_gass_transfer_request_t request) { globus_gass_transfer_request_struct_t * req; req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { return GLOBUS_GASS_TRANSFER_REQUEST_TYPE_INVALID; } else { return req->type; } }
/** * Get the length of a file to be transferred using GASS. * @ingroup globus_gass_transfer_request * * This function queries the request handle to determine the amount of * data that will be transferred to copy the URL. The length may be * @a GLOBUS_GASS_TRANSFER_LENGTH_UNKNOWN if the sender can not determine the length * before making or authorizing the request. * * @param request * The request to query. * * @return The length of the file located at the request's URL, or * @a GLOBUS_GASS_TRANSFER_LENGTH_UNKNOWN if that cannot be determined. */ globus_size_t globus_gass_transfer_request_get_length( globus_gass_transfer_request_t request) { globus_gass_transfer_request_struct_t * req; req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { return GLOBUS_GASS_TRANSFER_LENGTH_UNKNOWN; } else { return req->length; } }
/** * Set the length of a transfer associated request handle. * @ingroup globus_gass_transfer_request * * This function modifies the given request handle so that it's length field * is set to give length parameter. * * This function must only be called by protocol modules when constructing * a request handle when receiving the response to a get request. This * function can only be called once per request handle. * * @param request * A handle to the request to modify. * @param length * The length of the file request. * * @retval GLOBUS_SUCCESS * The URL was set for the request handle. * @retval GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE * The request handle was invalid, or the URL had already been set. */ void globus_gass_transfer_request_set_length( globus_gass_transfer_request_t request, globus_size_t length) { globus_gass_transfer_request_struct_t * req; req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { return ; } else { req->length = length; } }
/** * Extract referral information from a request handle. * @ingroup globus_gass_transfer_request * * This function queries the request handle to determine any referral * information that it contains. This function should only be called * on request handles in the GLOBUS_GASS_TRANSFER_REQUEST_REFERRED * state. If no referral information is stored in the request handle, * then the referral will be initialized to an empty referral. * The referral must be destroyed by calling * globus_gass_transfer_referral_destroy() by the caller. * * @param request * The request handle to query. * @param referral * A pointer to an uninitialized referral structure. It will be * populated by calling this function. * * @retval GLOBUS_SUCCESS * The referral was successfully extracted from the request * handle. * @retval GLOBUS_GASS_TRANSFER_ERROR_NULL_POINTER * The referral pointer was GLOBUS_NULL; */ int globus_gass_transfer_request_get_referral( globus_gass_transfer_request_t request, globus_gass_transfer_referral_t * referral) { globus_gass_transfer_request_struct_t * req; /* Sanity check of arguments */ if(referral == GLOBUS_NULL) { return GLOBUS_GASS_TRANSFER_ERROR_NULL_POINTER; } /* Check for illegal handle */ req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { return GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE; } else if(req->referral_count == 0) { referral->url = GLOBUS_NULL; referral->count = 0; return GLOBUS_SUCCESS; } else { globus_size_t i; referral->url = globus_malloc(sizeof(char *) * req->referral_count); for(i = 0; i < req->referral_count; i++) { referral->url[i] = globus_libc_strdup(req->referral_url[i]); } referral->count = req->referral_count; return GLOBUS_SUCCESS; } }
/** * Get the user pointer associated with a request * @ingroup globus_gass_transfer_request * * This function extracts the user pointer from a request handle. The * user-pointer may be used by the application which is generating or * servicing the request to store a pointer to any application-specific * piece of data. * * @param request * The request to query. * * @return The user pointer's value. */ void * globus_gass_transfer_request_get_user_pointer( globus_gass_transfer_request_t request) { globus_gass_transfer_request_struct_t * req; req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL|| req->type == GLOBUS_GASS_TRANSFER_REQUEST_TYPE_INVALID) { return GLOBUS_NULL; } else { return req->user_pointer; } }
/** * Set the user pointer associated with a request handle. * @ingroup globus_gass_transfer_request * * This function sets the user pointer from a request handle. The * user-pointer may be used by the application which is generating or * servicing the request to store a pointer to any application-specific * piece of data. * * @param request * The request to modify. * @param user_pointer * The new value of the user pointer for the request. * * @retval GLOBUS_SUCCES * The user pointer's value was set. * @retval GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE * An invalid request handle was passed to this function */ int globus_gass_transfer_request_set_user_pointer( globus_gass_transfer_request_t request, void * user_pointer) { globus_gass_transfer_request_struct_t * req; req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { return GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE; } else { req->user_pointer = user_pointer; return GLOBUS_SUCCESS; } }
/** * Set the type of a request. * @ingroup globus_gass_transfer_request * * This function modifies a request handle by setting the type of * operation that it is being used for. This function may only be * called once per handle, and only from a GASS protocol module * implementation. * * @param request * The request handle to modify. * @param type * The type of operation that this request handle will be used for. * * @retval GLOBUS_SUCCESS * The request handle's type has been set. * @retval GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE * The request handle was invalid or it's type was already set. * The request handle was not modified. * * @note Only GASS Protocol modules may call this function. */ int globus_gass_transfer_request_set_type( globus_gass_transfer_request_t request, globus_gass_transfer_request_type_t type) { globus_gass_transfer_request_struct_t * req; req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL|| req->type != GLOBUS_GASS_TRANSFER_REQUEST_TYPE_INVALID) { return GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE; } else { req->type = type; return GLOBUS_SUCCESS; } }
/** * Set the URL to which a request handle refers. * @ingroup globus_gass_transfer_request * * This function modifies the given request handle so that it's URL field * is set to string pointed to by @a url. * * No copy is made of the string, so the caller must not free it. It must * be allocated by calling one of the memory allocators in globus_libc, as * it will be freed when the request handle is destroyed. * * This function must only be called by protocol modules when constructing * a request handle when accepting a new request. This function can only * be called once per request handle. * * @param request * A handle to the request to modify. * @param url * A string containing the URL that this request will be associated * with. * * @retval GLOBUS_SUCCESS * The URL was set for the request handle. * @retval GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE * The request handle was invalid, or the URL had already been set. */ int globus_gass_transfer_request_set_url( globus_gass_transfer_request_t request, char * url) { globus_gass_transfer_request_struct_t * req; req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL || req->url != GLOBUS_NULL) { return GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE; } else { req->url = url; return GLOBUS_SUCCESS; } }
/** * @ingroup globus_gass_transfer_request */ int globus_gass_transfer_request_set_subject( globus_gass_transfer_request_t request, char * subject) { globus_gass_transfer_request_struct_t * req; req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { return GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE; } else if(req->subject != GLOBUS_NULL) { return GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE; } else { req->subject = subject; return GLOBUS_SUCCESS; } }
static void globus_l_gass_transfer_operation_complete( globus_gass_transfer_request_t request, globus_byte_t * bytes, globus_size_t nbytes, globus_bool_t failed, globus_bool_t last_data, globus_gass_transfer_dispatch_func_t dispatcher) { globus_gass_transfer_request_struct_t * req; globus_gass_transfer_pending_t * head; globus_gass_transfer_callback_t fail_callback=GLOBUS_NULL; 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_ACTING: if(! last_data) { /* * normal operation, go back to pending state, callback * to user */ req->status = GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_PENDING; while(req->status == GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_PENDING || ( (req->status == GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_FAILING || req->status == GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_REFERRING) && !globus_fifo_empty(&req->pending_data))) { head = globus_fifo_dequeue(&req->pending_data); /* Call back to user */ globus_i_gass_transfer_unlock(); head->callback(head->callback_arg, request, head->bytes, nbytes, last_data); globus_i_gass_transfer_lock(); nbytes = 0; last_data = GLOBUS_TRUE; globus_free(head); if(req->status == GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_PENDING) { req->status = GLOBUS_GASS_TRANSFER_REQUEST_PENDING; } } if(req->status == GLOBUS_GASS_TRANSFER_REQUEST_PENDING) { /* dispatch next, if available */ dispatcher(request); break; } else if(req->status == GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_FAILING) { req->status = GLOBUS_GASS_TRANSFER_REQUEST_FAILED; fail_callback = req->fail_callback; callback_arg = req->fail_callback_arg; /* free up references to request and proto */ req->proto->destroy(req->proto, request); /* free up the GASS's reference to this request */ globus_i_gass_transfer_request_destroy(request); globus_i_gass_transfer_unlock(); if(fail_callback != GLOBUS_NULL) { fail_callback(callback_arg, request); } return; } } else { /* failed or done */ if(failed) { req->status = GLOBUS_GASS_TRANSFER_REQUEST_FAILING; last_data = GLOBUS_TRUE; } else { req->status = GLOBUS_GASS_TRANSFER_REQUEST_FINISHING; } while(!globus_fifo_empty(&req->pending_data)) { head = globus_fifo_dequeue(&req->pending_data); /* Call back to user */ globus_i_gass_transfer_unlock(); head->callback(head->callback_arg, request, head->bytes, nbytes, last_data); globus_i_gass_transfer_lock(); nbytes = 0; globus_free(head); } fail_callback = req->fail_callback; callback_arg = req->fail_callback_arg; /* free up references to request and proto */ req->proto->destroy(req->proto, request); /* free up the proto's and GASS's reference to this request */ globus_i_gass_transfer_request_destroy(request); if(globus_i_gass_transfer_deactivating) { globus_i_gass_transfer_request_destroy(request); } globus_i_gass_transfer_unlock(); if(fail_callback != GLOBUS_NULL) { fail_callback(callback_arg, request); } return; } break; case GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_FAILING: req->status = GLOBUS_GASS_TRANSFER_REQUEST_FAILING; last_data = GLOBUS_TRUE; while(!globus_fifo_empty(&req->pending_data)) { head = globus_fifo_dequeue(&req->pending_data); /* Call back to user */ globus_i_gass_transfer_unlock(); head->callback(head->callback_arg, request, head->bytes, nbytes, last_data); globus_free(head); nbytes = 0; globus_i_gass_transfer_lock(); } fail_callback = req->fail_callback; callback_arg = req->fail_callback_arg; /* free up references to request and proto */ req->proto->destroy(req->proto, request); /* free up the proto's and GASS's reference to this request */ globus_i_gass_transfer_request_destroy(request); globus_i_gass_transfer_unlock(); fail_callback(callback_arg, request); return; case GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_REFERRING: req->status = GLOBUS_GASS_TRANSFER_REQUEST_REFERRING; last_data = GLOBUS_TRUE; while(!globus_fifo_empty(&req->pending_data)) { head = globus_fifo_dequeue(&req->pending_data); /* Call back to user */ globus_i_gass_transfer_unlock(); head->callback(head->callback_arg, request, head->bytes, nbytes, last_data); globus_free(head); nbytes = 0; globus_i_gass_transfer_lock(); } /* free up references to request and proto */ req->proto->destroy(req->proto, request); /* free up the proto's and GASS's reference to this request */ globus_i_gass_transfer_request_destroy(request); globus_i_gass_transfer_unlock(); return; case GLOBUS_GASS_TRANSFER_REQUEST_PENDING: case GLOBUS_GASS_TRANSFER_REQUEST_FAILING: case GLOBUS_GASS_TRANSFER_REQUEST_FAILED: case GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL1: case GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL2: case GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL3: case GLOBUS_GASS_TRANSFER_REQUEST_USER_FAIL: case GLOBUS_GASS_TRANSFER_REQUEST_REFERRED: case GLOBUS_GASS_TRANSFER_REQUEST_DENIED: case GLOBUS_GASS_TRANSFER_REQUEST_DONE: case GLOBUS_GASS_TRANSFER_REQUEST_STARTING: case GLOBUS_GASS_TRANSFER_REQUEST_STARTING2: case GLOBUS_GASS_TRANSFER_REQUEST_STARTING3: case GLOBUS_GASS_TRANSFER_REQUEST_ACCEPTING: case GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_PENDING: case GLOBUS_GASS_TRANSFER_REQUEST_FINISHING: case GLOBUS_GASS_TRANSFER_REQUEST_REFERRING: globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_PENDING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_FAILING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_FAILED); 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_SERVER_FAIL3); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_USER_FAIL); 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_STARTING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_STARTING2); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_STARTING3); 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_FINISHING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_REFERRING); goto finish; case GLOBUS_GASS_TRANSFER_REQUEST_INVALID: goto finish; } finish: globus_i_gass_transfer_unlock(); return; }
/** * Request referred. * @ingroup globus_gass_transfer_protocol * * This function notifies the GASS Transfer Library that new request * generated by a client calling one of the functions in the * "@ref globus_gass_transfer_client" section of the manual has been * referred to another URL by the server, and so processing has stopped. * * @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 url * An array of url strings containing alternate locations for this * file. The GASS transfer library is responsible for freeing this * array. It must be allocated using one of the * memory allocators defined in the Globus Common Library. * @param num_urls * The length of the @a url array. * * @see globus_gass_transfer_proto_request_ready(), * globus_gass_transfer_proto_request_denied(), * globus_gass_transfer_proto_request_referred() */ void globus_gass_transfer_proto_request_referred( globus_gass_transfer_request_t request, char ** url, globus_size_t num_urls) { globus_gass_transfer_request_struct_t * req; globus_gass_transfer_callback_t callback; void * callback_arg; globus_size_t i; globus_gass_transfer_pending_t * head; 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_STARTING: req->status = GLOBUS_GASS_TRANSFER_REQUEST_REFERRED; req->referral_url = url; req->referral_count = num_urls; callback = req->callback; callback_arg = req->callback_arg; globus_i_gass_transfer_unlock(); callback(callback_arg, request); globus_i_gass_transfer_lock(); /* free up GASS's reference to the request */ globus_i_gass_transfer_request_destroy(request); break; case GLOBUS_GASS_TRANSFER_REQUEST_USER_FAIL: req->status = GLOBUS_GASS_TRANSFER_REQUEST_FAILED; req->referral_url = url; req->referral_count = num_urls; callback = req->callback; callback_arg = req->callback_arg; globus_i_gass_transfer_unlock(); callback(callback_arg, request); globus_i_gass_transfer_lock(); /* free up GASS's reference to the request */ globus_i_gass_transfer_request_destroy(request); break; case GLOBUS_GASS_TRANSFER_REQUEST_ACTING: /* request is in progress, when operation completes, * the callback queue will be drained */ req->status = GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_REFERRING; req->referral_url = url; req->referral_count = num_urls; break; case GLOBUS_GASS_TRANSFER_REQUEST_PENDING: req->status = GLOBUS_GASS_TRANSFER_REQUEST_REFERRING; while(!globus_fifo_empty(&req->pending_data)) { head = globus_fifo_dequeue(&req->pending_data); /* Call back to user */ globus_i_gass_transfer_unlock(); head->callback(head->callback_arg, request, head->bytes, 0, GLOBUS_TRUE); globus_i_gass_transfer_lock(); globus_free(head); req->status = GLOBUS_GASS_TRANSFER_REQUEST_REFERRED; } /* free up references to request and proto */ req->proto->destroy(req->proto, request); /* free up the GASS's reference to this request */ globus_i_gass_transfer_request_destroy(request); break; case GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_PENDING: /* user callback in progress */ req->status = GLOBUS_GASS_TRANSFER_REQUEST_REFERRING; req->referral_url = url; req->referral_count = num_urls; /* callbacks are going to occur after the current * one completes (in the operation_complete function * above) */ break; case GLOBUS_GASS_TRANSFER_REQUEST_FAILED: 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_SERVER_FAIL3: case GLOBUS_GASS_TRANSFER_REQUEST_STARTING2: case GLOBUS_GASS_TRANSFER_REQUEST_STARTING3: case GLOBUS_GASS_TRANSFER_REQUEST_ACCEPTING: case GLOBUS_GASS_TRANSFER_REQUEST_FAILING: case GLOBUS_GASS_TRANSFER_REQUEST_FINISHING: case GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_FAILING: /* free urls, no state change */ goto free_urls; case GLOBUS_GASS_TRANSFER_REQUEST_REFERRING: case GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_REFERRING: globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_REFERRING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_REFERRING); goto free_urls; case GLOBUS_GASS_TRANSFER_REQUEST_INVALID: goto finish; } finish: globus_i_gass_transfer_unlock(); return; free_urls: for(i = 0; i < num_urls; i++) { globus_free(url[i]); } globus_free(url); return; }
/** * Request denied. * @ingroup globus_gass_transfer_protocol * * This function notifies the GASS Transfer Library that new request * generated by a client calling one of the functions in the * "@ref globus_gass_transfer_client" section of the manual has been * denied by the server, and so cannot be processed by * the protocol module. * * @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 reason * A protocol-specific reason code. * @param message * A string containing a message describing why the request * was denied. The GASS Transfer library is responsible for * freeing this message. It must be allocated using one of the * memory allocators defined in the Globus Common Library. * * @see globus_gass_transfer_proto_request_ready(), * globus_gass_transfer_proto_request_referred() */ void globus_gass_transfer_proto_request_denied( globus_gass_transfer_request_t request, int reason, char * message) { 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_STARTING: case GLOBUS_GASS_TRANSFER_REQUEST_USER_FAIL: req->status = GLOBUS_GASS_TRANSFER_REQUEST_DENIED; req->denial_reason = reason; req->denial_message = message; callback = req->callback; callback_arg = req->callback_arg; globus_i_gass_transfer_unlock(); callback(callback_arg, request); globus_i_gass_transfer_lock(); /* free up proto's and GASS's reference to the request */ globus_i_gass_transfer_request_destroy(request); break; case GLOBUS_GASS_TRANSFER_REQUEST_REFERRED: case GLOBUS_GASS_TRANSFER_REQUEST_REFERRING: case GLOBUS_GASS_TRANSFER_REQUEST_DENIED: case GLOBUS_GASS_TRANSFER_REQUEST_DONE: 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_SERVER_FAIL1: case GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL2: case GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL3: case GLOBUS_GASS_TRANSFER_REQUEST_STARTING2: case GLOBUS_GASS_TRANSFER_REQUEST_STARTING3: 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_REFERRED); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_REFERRING); 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_ACTING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_FAILING); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_ACTING_TO_REFERRING); 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_SERVER_FAIL1); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL2); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_SERVER_FAIL3); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_STARTING2); globus_assert(req->status != GLOBUS_GASS_TRANSFER_REQUEST_STARTING3); 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); goto finish; case GLOBUS_GASS_TRANSFER_REQUEST_INVALID: goto finish; } finish: globus_i_gass_transfer_unlock(); return; }
/** * New listener request. * @ingroup globus_gass_transfer_protocol * * This function notifies the GASS Transfer Library that new request * generated by a server calling the globus_gass_transfer_register_accept() * function has begun processing in a protocol module, * and that protocol module is now ready to send or receive data to handle * this request. * * @param listener * The listener handle used to accept 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. */ void globus_gass_transfer_proto_new_listener_request( globus_gass_transfer_listener_t listener, globus_gass_transfer_request_t request, globus_gass_transfer_request_proto_t * proto) { globus_gass_transfer_listener_struct_t * l; globus_gass_transfer_request_struct_t * req; globus_i_gass_transfer_lock(); l = globus_handle_table_lookup(&globus_i_gass_transfer_listener_handles, listener); if(l == GLOBUS_NULL) { globus_i_gass_transfer_unlock(); return; } req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { globus_i_gass_transfer_unlock(); return; } req->proto = proto; switch(l->status) { case GLOBUS_GASS_TRANSFER_LISTENER_ACCEPTING: l->status = GLOBUS_GASS_TRANSFER_LISTENER_STARTING; if(proto == GLOBUS_NULL) { req->status = GLOBUS_GASS_TRANSFER_REQUEST_FAILED; /* Destroy GASS's reference to this request proto */ globus_i_gass_transfer_request_destroy(request); } else { req->status = GLOBUS_GASS_TRANSFER_REQUEST_STARTING2; globus_assert(req->type != GLOBUS_GASS_TRANSFER_REQUEST_TYPE_INVALID); } /* Callback to user, regarding this request */ globus_i_gass_transfer_unlock(); req->callback(req->callback_arg, request); return; case GLOBUS_GASS_TRANSFER_LISTENER_CLOSING2: l->status = GLOBUS_GASS_TRANSFER_LISTENER_CLOSED; req->status = GLOBUS_GASS_TRANSFER_REQUEST_FAILED; /* Callback to user, regarding this request */ globus_i_gass_transfer_unlock(); req->callback(req->callback_arg, request); globus_i_gass_transfer_lock(); /* * Fail and destroy this request, since the user * has called the close function on this listener */ if(req->proto) { req->proto->fail(req->proto, request); req->proto->destroy(req->proto, request); } /* Destroy GASS's reference to this request proto */ globus_i_gass_transfer_request_destroy(request); /* Callback to user, regarding this listener */ globus_i_gass_transfer_unlock(); l->close_callback(l->close_callback_arg, listener); l->proto->destroy(l->proto, listener); globus_i_gass_transfer_lock(); /* Destroy GASS's reference to this listener */ globus_i_gass_transfer_listener_destroy(listener); globus_i_gass_transfer_listener_destroy(listener); globus_i_gass_transfer_unlock(); return; case GLOBUS_GASS_TRANSFER_LISTENER_STARTING: case GLOBUS_GASS_TRANSFER_LISTENER_INVALID: case GLOBUS_GASS_TRANSFER_LISTENER_READY: case GLOBUS_GASS_TRANSFER_LISTENER_LISTENING: case GLOBUS_GASS_TRANSFER_LISTENER_CLOSING1: case GLOBUS_GASS_TRANSFER_LISTENER_CLOSED: globus_assert(l->status != GLOBUS_GASS_TRANSFER_LISTENER_STARTING); globus_assert(l->status != GLOBUS_GASS_TRANSFER_LISTENER_INVALID); globus_assert(l->status != GLOBUS_GASS_TRANSFER_LISTENER_READY); globus_assert(l->status != GLOBUS_GASS_TRANSFER_LISTENER_LISTENING); globus_assert(l->status != GLOBUS_GASS_TRANSFER_LISTENER_CLOSING1); globus_assert(l->status != GLOBUS_GASS_TRANSFER_LISTENER_CLOSED); } globus_i_gass_transfer_unlock(); return; }
/** * 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; }
/** * Server listener ready. * @ingroup globus_gass_transfer_protocol * * This function notifies the GASS Transfer Library that the protocol module * has decided that a new request can be accepted on this particular listener. * It must only be called after the GASS Transfer Library has called the * @link globus_gass_transfer_listener_proto_t::listen listen function@endlink * in a #globus_gass_transfer_listener_proto_t protocol module-specific * listener structure. * * @param listener * The listener handle which is now ready for accepting a new * connection. */ void globus_gass_transfer_proto_listener_ready( globus_gass_transfer_listener_t listener) { globus_gass_transfer_listener_struct_t * l; globus_gass_transfer_listen_callback_t callback; void * callback_arg; globus_gass_transfer_listen_callback_t close_callback = GLOBUS_NULL; void * close_callback_arg; globus_i_gass_transfer_lock(); l = globus_handle_table_lookup(&globus_i_gass_transfer_listener_handles, listener); if(l == GLOBUS_NULL) { goto error_exit; } switch(l->status) { case GLOBUS_GASS_TRANSFER_LISTENER_INVALID: goto error_exit; case GLOBUS_GASS_TRANSFER_LISTENER_LISTENING: l->status = GLOBUS_GASS_TRANSFER_LISTENER_READY; callback = l->listen_callback; callback_arg = l->listen_callback_arg; globus_i_gass_transfer_unlock(); callback(callback_arg, listener); return; case GLOBUS_GASS_TRANSFER_LISTENER_CLOSING1: l->status = GLOBUS_GASS_TRANSFER_LISTENER_CLOSED; callback = l->listen_callback; callback_arg = l->listen_callback_arg; close_callback = l->close_callback; close_callback_arg = l->close_callback_arg; /* Destroy our reference to the proto */ l->proto->destroy(l->proto, listener); /* * Destroy GASS's reference * to this listener */ globus_i_gass_transfer_listener_destroy(listener); globus_i_gass_transfer_unlock(); callback(callback_arg, listener); if(close_callback) { close_callback(close_callback_arg, listener); } globus_i_gass_transfer_lock(); globus_i_gass_transfer_listener_destroy(listener); globus_i_gass_transfer_unlock(); return; case GLOBUS_GASS_TRANSFER_LISTENER_READY: case GLOBUS_GASS_TRANSFER_LISTENER_STARTING: case GLOBUS_GASS_TRANSFER_LISTENER_ACCEPTING: case GLOBUS_GASS_TRANSFER_LISTENER_CLOSING2: case GLOBUS_GASS_TRANSFER_LISTENER_CLOSED: globus_assert(l->status != GLOBUS_GASS_TRANSFER_LISTENER_READY); globus_assert(l->status != GLOBUS_GASS_TRANSFER_LISTENER_STARTING); globus_assert(l->status != GLOBUS_GASS_TRANSFER_LISTENER_ACCEPTING); globus_assert(l->status != GLOBUS_GASS_TRANSFER_LISTENER_CLOSING2); globus_assert(l->status != GLOBUS_GASS_TRANSFER_LISTENER_CLOSED); break; } globus_i_gass_transfer_unlock(); return; error_exit: globus_i_gass_transfer_unlock(); }
static void globus_l_gass_transfer_drain_callbacks( void * arg) { globus_gass_transfer_request_t request; globus_gass_transfer_request_struct_t * req; globus_gass_transfer_callback_t callback; void * callback_arg; request = (globus_gass_transfer_request_t) arg; req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { return; } if(globus_i_gass_transfer_deactivating) { callback = globus_i_gass_transfer_deactivate_callback; callback_arg = GLOBUS_NULL; } else { callback = req->fail_callback; callback_arg = req->fail_callback_arg; } /* drain queue of pending data requests */ while(!globus_fifo_empty(&req->pending_data)) { globus_gass_transfer_pending_t * pending; pending = globus_fifo_dequeue(&req->pending_data); if(!globus_i_gass_transfer_deactivating) { globus_i_gass_transfer_unlock(); pending->callback(pending->callback_arg, request, pending->bytes, 0, GLOBUS_TRUE); globus_i_gass_transfer_lock(); } globus_free(pending); } /* 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); if(callback) { callback(callback_arg, request); } }
/** * 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; }
/** * Send a byte array associated with a request handle. * @ingroup globus_gass_transfer_data * * This function sends a block of data to 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 "get" 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 "put" or "append" 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 send_length * The length of the @a bytes array. * @param last_data * A flag to indicate whether this is the final block of data * for the request. If this is true, then the @a callback * function will be delayed until the server acknowledges that * the file has been completely received. * @param callback * Function to call once the @a bytes array has been sent. * @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 sent. * @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_send_bytes( globus_gass_transfer_request_t request, globus_byte_t * bytes, globus_size_t send_length, globus_bool_t last_data, 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; } 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; } else 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; } /* * Verify that the request is in a state that allows new data * blocks to be sent */ rc = globus_l_gass_transfer_state_check(req); if(rc != GLOBUS_SUCCESS) { goto error_exit; } /* * Verify that the sending this amount of data won't overflow the * original request size. */ rc = globus_l_gass_transfer_size_check(req, send_length); if(rc != GLOBUS_SUCCESS) { 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 = last_data; pending->length = send_length; pending->pending = GLOBUS_FALSE; pending->request = request; pending->bytes = bytes; pending->callback = callback; pending->callback_arg = user_arg; /* * Posted length is the total amount of data which has been queued * for this request. It is used for detecting overflows. */ req->posted_length += send_length; globus_fifo_enqueue(&req->pending_data, pending); /* * Call the send dispatcher to (maybe) send some more data to the * protocol module to send over the connection. */ globus_i_gass_transfer_send_dispatcher(request); globus_i_gass_transfer_unlock(); return GLOBUS_SUCCESS; error_exit: globus_i_gass_transfer_unlock(); return rc; }
/** * Dereference a request handle. * * This function decreases the reference count on an GASS Transfer * request handle. If the reference count becomes zero, then the * #globus_gass_transfer_request_struct_t associated with the handle * is destroyed. * * @note This function must be called with the request handle mutex locked. * * @param request * The request to destroy. * * @retval GLOBUS_SUCCESS * The request handle's reference count was decremented. The request * structure is freed if this was the final reference to the handle. * @retval GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE * The request handle was not valid. * @see globus_gass_transfer_request_destroy() */ int globus_i_gass_transfer_request_destroy( globus_gass_transfer_request_t request) { globus_bool_t referenced; globus_gass_transfer_request_struct_t * req; req = globus_handle_table_lookup(&globus_i_gass_transfer_request_handles, request); if(req == GLOBUS_NULL) { return GLOBUS_GASS_TRANSFER_ERROR_INVALID_USE; } referenced = globus_handle_table_decrement_reference(&globus_i_gass_transfer_request_handles, request); if(!referenced) { int i; globus_list_t * tmp; tmp = globus_list_search(globus_i_gass_transfer_requests, (void *) (intptr_t) request); #if DEBUG_GASS_TRANSFER printf(_GTSL("removing from list\n")); #endif if (tmp) { globus_list_remove(&globus_i_gass_transfer_requests, tmp); globus_cond_signal(&globus_i_gass_transfer_shutdown_cond); if(req->attr) { globus_object_free(req->attr); } globus_fifo_destroy(&req->pending_data); if (req->url) { globus_free(req->url); } /* free referral */ for(i = 0; i < req->referral_count; i++) { globus_free(req->referral_url[i]); } if(req->referral_url) { globus_free(req->referral_url); } req->referral_url = GLOBUS_NULL; req->referral_count = 0; /* free deny message */ if(req->denial_message) { globus_free(req->denial_message); } /* free subject name */ if(req->subject) { globus_free(req->subject); } globus_free(req); request = GLOBUS_NULL_HANDLE; } return GLOBUS_SUCCESS; } else { return GLOBUS_SUCCESS; } }