static
void
globus_l_gram_streamer_data_callback(
    void *                              arg,
    globus_gass_transfer_request_t      request,
    globus_byte_t *                     bytes,
    globus_size_t                       length,
    globus_bool_t                       last_data)
{
    globus_gram_streamer_monitor_t *    monitor = arg;
    globus_gram_stream_t *              stream;
    globus_gass_transfer_request_status_t
                                        status;

    globus_mutex_lock(&monitor->mutex);
    stream = globus_gass_transfer_request_get_user_pointer(request);
    free(bytes);
    stream->blocks--;
    status = globus_gass_transfer_request_get_status(request);

    if (last_data && stream->blocks == 0)
    {
        switch (status)
        {
        case GLOBUS_GASS_TRANSFER_REQUEST_INVALID:
        case GLOBUS_GASS_TRANSFER_REQUEST_STARTING:
        case GLOBUS_GASS_TRANSFER_REQUEST_FAILED:
        case GLOBUS_GASS_TRANSFER_REQUEST_DENIED:
        case GLOBUS_GASS_TRANSFER_REQUEST_REFERRED:
            globus_gass_transfer_request_destroy(request);
            if (stream->state != GLOBUS_GRAM_STREAM_RESTART)
            {
                stream->state = GLOBUS_GRAM_STREAM_FAIL;
                globus_cond_signal(&monitor->cond);
            }
            break;
        case GLOBUS_GASS_TRANSFER_REQUEST_DONE:
            globus_gass_transfer_request_destroy(request);
            if (stream->state == GLOBUS_GRAM_STREAM_ACTIVE)
            {
                stream->state = GLOBUS_GRAM_STREAM_DONE;
            }
            globus_cond_signal(&monitor->cond);
            break;
        case GLOBUS_GASS_TRANSFER_REQUEST_PENDING:
            break;
        default:
            fprintf(stderr, "%d:GASS Transfer returned invalid status: %d\n",
                    GLOBUS_GRAM_PROTOCOL_ERROR_MALLOC_FAILED,
                    (int) status);
            exit(EXIT_FAILURE);
        }
    }
    globus_mutex_unlock(&monitor->mutex);
}
static
void
globus_l_gram_streamer_request_ready(
    void *                              arg,
    globus_gass_transfer_request_t      request)
{
    globus_gram_streamer_monitor_t *    monitor = arg;
    globus_gram_stream_t *              stream;
    globus_gass_transfer_request_status_t
                                        status;
    globus_mutex_lock(&monitor->mutex);
    stream = globus_gass_transfer_request_get_user_pointer(request);
    status = globus_gass_transfer_request_get_status(request);

    switch (status)
    {
    case GLOBUS_GASS_TRANSFER_REQUEST_INVALID:
    case GLOBUS_GASS_TRANSFER_REQUEST_STARTING:
        globus_gass_transfer_request_destroy(request);
        stream->state = GLOBUS_GRAM_STREAM_FAIL;
        globus_cond_signal(&monitor->cond);
        break;
    case GLOBUS_GASS_TRANSFER_REQUEST_FAILED:
    case GLOBUS_GASS_TRANSFER_REQUEST_DENIED:
        globus_gass_transfer_request_destroy(request);
        stream->state = GLOBUS_GRAM_STREAM_FAIL;
        globus_cond_signal(&monitor->cond);
        break;
    case GLOBUS_GASS_TRANSFER_REQUEST_REFERRED:
        globus_gass_transfer_request_destroy(request);
        stream->state = GLOBUS_GRAM_STREAM_DONE;
        globus_cond_signal(&monitor->cond);
        break;
    case GLOBUS_GASS_TRANSFER_REQUEST_DONE:
        globus_gass_transfer_request_destroy(request);
        stream->state = GLOBUS_GRAM_STREAM_DONE;
        globus_cond_signal(&monitor->cond);
        break;
    case GLOBUS_GASS_TRANSFER_REQUEST_PENDING:
        stream->state = GLOBUS_GRAM_STREAM_ACTIVE;
        break;
    default:
        fprintf(stderr, "%d:GASS Transfer returned invalid status: %d\n",
                GLOBUS_GRAM_PROTOCOL_ERROR_MALLOC_FAILED,
                (int) status);
        exit(EXIT_FAILURE);
    }
    globus_mutex_unlock(&monitor->mutex);
}
/******************************************************************************
Function: globus_l_gass_server_ez_put_memory_done()

Description: 

Parameters: 

Returns: 
******************************************************************************/
static void
globus_gass_server_ez_put_memory_done(void * arg,
                                       globus_gass_transfer_request_t request,
                                       globus_byte_t buffer[],
                                       globus_size_t receive_length,
				       globus_bool_t last_data)
{
    globus_gass_server_ez_request_t *r=GLOBUS_NULL;
    globus_size_t max_length;
    unsigned long lastnl, x;
    int status;
    const int buffer_length=1024;
    
    /* This callback handles line-buffered put requests. 
     */    

    r = (globus_gass_server_ez_request_t *)arg;

    status=globus_gass_transfer_request_get_status(request);
    lastnl = 0UL;


    /* find last \n in the buffer, since we are line-buffering */
    max_length=receive_length;
    for(x = max_length; x > 0UL; x--)
    {
	if(buffer[x-1] == '\n')
	{
	    lastnl = x;
	    break;
	}
    }
    
    if(status == GLOBUS_GASS_TRANSFER_REQUEST_PENDING && !last_data)
    {
	/* data arrived, and more will be available, so write up until
	 * the last \n we've received and save the rest
	 */
	if(r->line_buffer != GLOBUS_NULL &&
	   lastnl != 0UL &&
	    r->line_buffer_used != 0UL)
	{
	    globus_l_gass_server_ez_write(r->fd,
				r->line_buffer,
				r->line_buffer_used);
	    r->line_buffer_used = 0UL;
	}
	
	if(lastnl != 0UL)
	{
	    globus_l_gass_server_ez_write(r->fd,
				buffer,
				lastnl);
	}
	else
	{
	    lastnl = 0;
	}
	if(r->line_buffer_used + receive_length - lastnl >
	   r->line_buffer_length)
	{
	    r->line_buffer = (globus_byte_t *)
		realloc(r->line_buffer,
			r->line_buffer_used + receive_length - lastnl);
	    r->line_buffer_length = r->line_buffer_used + receive_length - lastnl;
	    memcpy(r->line_buffer + r->line_buffer_used,
		   buffer + lastnl,
		   receive_length - lastnl);
	    r->line_buffer_used += receive_length - lastnl;
	}
	else
	{
	    memcpy(r->line_buffer + r->line_buffer_used,
		   buffer + lastnl,
		   receive_length - lastnl);
	    r->line_buffer_used += receive_length - lastnl;
	}
	
	globus_gass_transfer_receive_bytes(request,
				  	   buffer,
					   buffer_length,
					   1UL,
					   globus_gass_server_ez_put_memory_done,
					   arg);
					
    }
    else
    {
	
	if(r->line_buffer != GLOBUS_NULL &&
	   r->line_buffer_used != 0UL)
	{
	    globus_l_gass_server_ez_write(r->fd,
				r->line_buffer,
				r->line_buffer_used);
	}
	if(receive_length != 0UL)
	{
	    globus_l_gass_server_ez_write(r->fd,
				buffer,
				receive_length);
	}

	    
	if(r->fd!=fileno(stdout) && r->fd!=fileno(stderr))
	{
    if(-1 == close(r->fd))
      printf("close error(fd: %d): %s\n", r->fd, strerror( errno ));
	}

	if(buffer != GLOBUS_NULL)
	{
	    globus_free(buffer);
	}  

	globus_gass_transfer_request_destroy(request);
		

	if(r->linebuffer)
	{
	    globus_free(r->line_buffer);
	} 
	globus_free(r);
    }
} /* globus_l_gass_server_ez_put_memory_done() */