Example #1
0
size_t
CoolUrlFread(void *ptr, size_t size, size_t nmemb, URL_FILE *file)
{
    size_t want;


	want = nmemb * size;

	fill_buffer(file,want,1);

    // check if theres data in the buffer - if not fill_buffer()
    // either errored or EOF 
	if(!file->buffer_pos)
		return 0;

    // ensure only available data is considered 
	if(file->buffer_pos < want)
		want = file->buffer_pos;

    // xfer data to caller */
	memcpy(ptr, file->buffer, want);

	use_buffer(file,want);

	want = want / size;     // number of items - nb correct op - checked
                            //      with glibc code
    return want;
}
Example #2
0
static void
down (int i)
{
  char buf[10000];
  static void *last;

  if (last && last < (void *) buf)
    {
      printf ("%d: %p < %p\n", i, last, buf);
      marker_hit ();
    }
  last = buf;

  if (i == 500)
    {
      if (munmap (reserved, RESERVED_SIZE) != 0)
        abort ();
      reserved = NULL;
    }

  if (i > 0)
    {
      use_buffer (buf);
      down (i - 1);
    }
  else
    marker_miss ();
}
char *
url_fgets(char *ptr, int size, URL_FILE *file)
{
    int want = size - 1;/* always need to leave room for zero termination */
    int loop;

    switch(file->type)
    {
    case CFTYPE_FILE:
        ptr = fgets(ptr,size,file->handle.file);
        break;

    case CFTYPE_CURL:
        fill_buffer(file,want,1);

        /* check if theres data in the buffer - if not fill either errored or
         * EOF */
        if(!file->buffer_pos)
            return NULL;

        /* ensure only available data is considered */
        if(file->buffer_pos < want)
            want = file->buffer_pos;

        /*buffer contains data */
        /* look for newline or eof */
        for(loop=0;loop < want;loop++)
        {
            if(file->buffer[loop] == '\n')
            {
                want=loop+1;/* include newline */
                break;
            }
        }

        /* xfer data to caller */
        memcpy(ptr, file->buffer, want);
        ptr[want]=0;/* allways null terminate */

        use_buffer(file,want);

        /*printf("(fgets) return %d bytes %d left\n", want,file->buffer_pos);*/
        break;

    default: /* unknown or supported type - oh dear */
        ptr=NULL;
        errno=EBADF;
        break;
    }

    return ptr;/*success */
}
Example #4
0
static size_t curl_file_fread(ALLEGRO_FILE *f, void *ptr, size_t size)
{
   CURL_FILE *cf = al_get_file_userdata(f);

   fill_buffer(cf, size);
   if (!cf->buffer_pos)
      return 0;

   if (cf->buffer_pos < size)
      size = cf->buffer_pos;

   memcpy(ptr, cf->buffer, size);
   use_buffer(cf, size);
   return size;
}
size_t
url_fread(void *ptr, size_t size, size_t nmemb, URL_FILE *file)
{
    size_t want;

    switch(file->type)
    {
    case CFTYPE_FILE:
        want=fread(ptr,size,nmemb,file->handle.file);
        break;

    case CFTYPE_CURL:
        want = nmemb * size;

        fill_buffer(file,want,1);

        /* check if theres data in the buffer - if not fill_buffer()
         * either errored or EOF */
        if(!file->buffer_pos)
            return 0;

        /* ensure only available data is considered */
        if(file->buffer_pos < want)
            want = file->buffer_pos;

        /* xfer data to caller */
        memcpy(ptr, file->buffer, want);

        use_buffer(file,want);

        want = want / size;     /* number of items - nb correct op - checked
                                 * with glibc code*/

        /*printf("(fread) return %d bytes %d left\n", want,file->buffer_pos);*/
        break;

    default: /* unknown or supported type - oh dear */
        want=0;
        errno=EBADF;
        break;

    }
    return want;
}
Example #6
0
File: http.cpp Project: ronj/invent
  std::size_t read(unsigned char* aBuffer, std::size_t aByteCount)
  {
    fill_buffer(iCURLData.get(), aByteCount);
 
    /* check if theres data in the buffer - if not fill_buffer()
     * either errored or EOF */ 
    if(!iCURLData->buffer_pos)
      return 0;
 
    /* ensure only available data is considered */ 
    if(iCURLData->buffer_pos < aByteCount)
      aByteCount = iCURLData->buffer_pos;
 
    /* xfer data to caller */ 
    memcpy(aBuffer, iCURLData->buffer, aByteCount);
 
    use_buffer(iCURLData.get(), aByteCount);
 
    return aByteCount;     /* number of items */ 
  }
Example #7
0
char *
CoolUrlFgets(char *ptr, int size, URL_FILE *file)
{
    int want = size - 1;// always need to leave room for zero termination 
    int loop;

	fill_buffer(file,want,1);

    //check if theres data in the buffer - if not fill either errored or
    //EOF 
	if(!file->buffer_pos)
		return NULL;

    //ensure only available data is considered
	if(file->buffer_pos < want)
		want = file->buffer_pos;

    //buffer contains data 
    // look for newline or eof 
	for(loop=0;loop < want;loop++)
	{
		if(file->buffer[loop] == '\n')
		{
			want=loop+1;//nclude newline 
			break;
		}
	}

    //xfer data to caller 
	memcpy(ptr, file->buffer, want);
	ptr[want]=0;//allways null terminate 

	use_buffer(file,want);

    return ptr;//success 
}
URLIO_FILE *urlio_fopen(const char *url, const char *operation) {
	/* this code could check for URLs or types in the 'url' and
	 basically use the real fopen() for standard files */

	URLIO_FILE *file = NULL;
	URLIO_CONN *conn = NULL;
	(void) operation;
	const size_t want = 1;
	double dSize;

#ifdef URLIO_VERBOSE
	printf("fopen: %s\n", url);
#endif

	file = (URLIO_FILE*) calloc(1, sizeof(URLIO_FILE));
	if (!file)
		return NULL;

	file->handle.file = fopen(url, operation);
	if (file->handle.file) {
		file->type = CFTYPE_FILE; /* marked as FILE */

		file->url = (char*) malloc((strlen(url) + 1) * sizeof(char));
		strcpy(file->url, url);
		file->pos = 0;
		fseek(file->handle.file, 0, SEEK_END);
		file->handle.conn->size = ftell(file->handle.file);
		fseek(file->handle.file, 0, SEEK_SET);
	} else {
		file->type = CFTYPE_CURL; /* marked as URL */

		int wanted_urlio_index = -1;

		for (int i = 0; i < g_urlio_count; i++) {
			if (!strcmp(g_urlio_list[i]->url, url)) {
				printf("stream exists, reuse it\n");
				wanted_urlio_index = i;
				break;
			}
		}

		if (wanted_urlio_index == -1) {
			conn = (URLIO_CONN*) calloc(1, sizeof(URLIO_CONN));
			conn->io[0].curl = curl_easy_init();

			curl_easy_setopt(conn->io[0].curl, CURLOPT_URL, url);
			curl_easy_setopt(conn->io[0].curl, CURLOPT_WRITEDATA,
					&(conn->io[0]));
			curl_easy_setopt(conn->io[0].curl, CURLOPT_VERBOSE, CURL_VERBOSE);
			curl_easy_setopt(conn->io[0].curl, CURLOPT_WRITEFUNCTION,
					write_callback);

			conn->multi_handle = curl_multi_init();
			curl_multi_add_handle(conn->multi_handle, conn->io[0].curl);

			/* lets start the fetch */
			curl_multi_perform(conn->multi_handle, &conn->still_running);

			if ((conn->io[0].buffer_pos == 0) && (!conn->still_running)) {
				/* if still_running is 0 now, we should return NULL */

				/* make sure the easy handle is not in the multi handle anymore */
				curl_multi_remove_handle(conn->multi_handle, conn->io[0].curl);

				/* cleanup */
				curl_easy_cleanup(conn->io[0].curl);

				free(file);
				free(conn);

				file = NULL;
			} else {
				for (int retry = 0; retry < RETRY_TIMES; retry++) {
					fill_buffer(conn, want, 0);

					/* check if there's data in the buffer - if not fill either error or
					 * EOF */
					if (conn->io[0].buffer_pos) {
						use_buffer(conn, want, 0);
						curl_easy_getinfo(conn->io[0].curl,
								CURLINFO_CONTENT_LENGTH_DOWNLOAD, &dSize);
						conn->size = (long) dSize;

#ifdef URLIO_VERBOSE
						printf("stream opened, length: %zu\n", conn->size);
#endif

						break;
					}

					/* halt transaction */
					curl_multi_remove_handle(conn->multi_handle,
							conn->io[0].curl);

					/* restart */
					curl_multi_add_handle(conn->multi_handle, conn->io[0].curl);

					/* ditch buffer - write will recreate - resets stream pos*/
					free(conn->io[0].buffer);
					conn->io[0].buffer = NULL;
					conn->io[0].buffer_pos = 0;
					conn->io[0].buffer_len = 0;
				}

				/* check if there's data in the buffer - if not fill either error or
				 * EOF */
				if (conn->io[0].buffer_pos) {
					/* halt transaction */
					curl_multi_remove_handle(conn->multi_handle,
							conn->io[0].curl);

					/* restart */
					curl_multi_add_handle(conn->multi_handle, conn->io[0].curl);

					/* ditch buffer - write will recreate - resets stream pos*/
					free(conn->io[0].buffer);
					conn->io[0].buffer = NULL;
					conn->io[0].buffer_pos = 0;
					conn->io[0].buffer_len = 0;
				} else {
					/* make sure the easy handle is not in the multi handle anymore */
					curl_multi_remove_handle(conn->multi_handle,
							conn->io[0].curl);

					/* cleanup */
					curl_easy_cleanup(conn->io[0].curl);

					free(file);
					free(conn);

					file = NULL;
				}
			}

			conn->url = (char*) malloc((strlen(url) + 1) * sizeof(char));
			strcpy(conn->url, url);

			if (g_urlio_count == 0)
				g_urlio_list = (URLIO_CONN**) malloc(sizeof(URLIO_CONN*));
			else
				g_urlio_list = (URLIO_CONN**) realloc(g_urlio_list,
						(g_urlio_count + 1) * sizeof(URLIO_CONN*));
			g_urlio_list[g_urlio_count] = conn;

			wanted_urlio_index = g_urlio_count;
			g_urlio_count++;
		}

		file->handle.conn = g_urlio_list[wanted_urlio_index];
	}

	if (file) {
		file->url = (char*) malloc((strlen(url) + 1) * sizeof(char));
		strcpy(file->url, url);
		file->pos = 0;
	}

	return file;
}
static size_t download(void *ptr, size_t pos, size_t wanted, URLIO_CONN *conn) {
	int wanted_bulk_count = (((pos % (CACHE_BULK_SIZE)) + wanted - 1)
			/ (CACHE_BULK_SIZE)) + 1;
	size_t wanted_bulk_id = (pos / (CACHE_BULK_SIZE)) * (CACHE_BULK_SIZE);
	size_t residual = wanted;
	size_t copied = 0L;
	size_t want_per_thread[THREAD_NUM];
	size_t want_total;

	for (int i = 0; i < wanted_bulk_count; i++) {
		int wanted_cache_index = -1;
		int wanted_bulk_index = -1;

		for (int j = 0; j < g_cache_count; j++) {
			if (!strcmp(g_cache_list[j]->url, conn->url)) {
				wanted_cache_index = j;
				break;
			}
		}

		if (wanted_cache_index != -1) {
			for (int j = 0; j < g_cache_list[wanted_cache_index]->bulk_count;
					j++) {
				if (g_cache_list[wanted_cache_index]->bulk_id_list[j]
						== wanted_bulk_id) {
					printf("download: cache hit bulk id %zu\n", wanted_bulk_id);
					wanted_bulk_index = j;
					break;
				}
			}
		}

		if (wanted_bulk_index == -1) { /* missed bulk */
			printf("download: cache is missed\n");

			g_mutex_lock(&g_cache_lock);

			for (int t = 0; t < THREAD_NUM; t++) {
				if (pos + t * (CACHE_BULK_SIZE_PER_THREAD) > conn->size)
					break;
				/* close the stream */
				/* make sure the easy handle is not in the multi handle anymore */
				curl_multi_remove_handle(conn->multi_handle, conn->io[t].curl);

				/* cleanup */
				curl_easy_cleanup(conn->io[t].curl);

				/* reopen the stream and resume at a specific pos */
				conn->io[t].curl = curl_easy_init();

				curl_easy_setopt(conn->io[t].curl, CURLOPT_URL, conn->url);
				curl_easy_setopt(conn->io[t].curl, CURLOPT_WRITEDATA,
						&(conn->io[t]));
				curl_easy_setopt(conn->io[t].curl, CURLOPT_VERBOSE,
						CURL_VERBOSE);
				curl_easy_setopt(conn->io[t].curl, CURLOPT_WRITEFUNCTION,
						write_callback);
				curl_easy_setopt(conn->io[t].curl, CURLOPT_RESUME_FROM_LARGE,
						wanted_bulk_id+t*(CACHE_BULK_SIZE_PER_THREAD)); /* bulk id represents the pointer of the head of a bulk*/

//			/* This tests if multi_handle has been initialzed. It should always be initialized.*/
//			if (!urlio->multi_handle)
//				urlio->multi_handle = curl_multi_init();

				curl_multi_add_handle(conn->multi_handle, conn->io[t].curl);
			}
			/* lets start the fetch */
			curl_multi_perform(conn->multi_handle, &conn->still_running);

			for (int t = 0; t < THREAD_NUM; t++) {
				if (pos + t * (CACHE_BULK_SIZE_PER_THREAD) > conn->size)
					break;
				if ((conn->io[t].buffer_pos == 0) && (!conn->still_running)) {
					/* if still_running is 0 now, we should return NULL */

					for (int q = 0; q < THREAD_NUM; q++) {
						if (pos + q * (CACHE_BULK_SIZE_PER_THREAD) > conn->size)
							break;

						/* make sure the easy handle is not in the multi handle anymore */
						curl_multi_remove_handle(conn->multi_handle,
								conn->io[q].curl);

						/* cleanup */
						curl_easy_cleanup(conn->io[q].curl);
					}

					g_mutex_unlock(&g_cache_lock);
					return 0L;
				}
			}

			/* check if there's data in the buffer - if not fill either error or
			 * EOF */
			for (int t = 0; t < THREAD_NUM; t++) {
				if (pos + t * (CACHE_BULK_SIZE_PER_THREAD) > conn->size)
					break;

				if (conn->io[t].buffer_pos) {
					/* halt transaction */
					curl_multi_remove_handle(conn->multi_handle,
							conn->io[t].curl);

					/* restart */
					curl_multi_add_handle(conn->multi_handle, conn->io[t].curl);

					/* ditch buffer - write will recreate - resets stream pos*/
					free(conn->io[t].buffer);
					conn->io[t].buffer = NULL;
					conn->io[t].buffer_pos = 0L;
					conn->io[t].buffer_len = 0L;
				}
			}

			/* This paragraph reads want of data from the stream */

			for (int t = 0; t < THREAD_NUM; t++) {
				if (pos + t * (CACHE_BULK_SIZE_PER_THREAD) > conn->size)
					break;

				want_per_thread[t] = (CACHE_BULK_SIZE_PER_THREAD);

				fill_buffer(conn, want_per_thread[t], t);

				/* check if there's data in the buffer - if not fill_buffer()
				 * either error or EOF */
				if (!conn->io[t].buffer_pos) {
					g_mutex_unlock(&g_cache_lock);
					return 0L;
				}

				/* ensure only available data is considered */
				if (conn->io[t].buffer_pos < want_per_thread[t])
					want_per_thread[t] = conn->io[t].buffer_pos;

			}

			want_total = 0L;
			for (int t = 0; t < THREAD_NUM; t++) {
				if (pos + t * (CACHE_BULK_SIZE_PER_THREAD) > conn->size)
					break;

				want_total += want_per_thread[t];
			}

			/* Expand cache memory */
			if (wanted_cache_index == -1) {
				if (!g_cache_list)
					g_cache_list = (URLIO_CACHE**) malloc(sizeof(URLIO_CACHE*));
				else
					g_cache_list = (URLIO_CACHE**) realloc(g_cache_list,
							(g_cache_count + 1) * sizeof(URLIO_CACHE*));
				g_cache_list[g_cache_count] = (URLIO_CACHE*) calloc(1,
						sizeof(URLIO_CACHE));
				g_cache_list[g_cache_count]->url = (char*) malloc(
						(strlen(conn->url) + 1) * sizeof(char));
				strcpy(g_cache_list[g_cache_count]->url, conn->url);
				wanted_cache_index = g_cache_count;
				g_cache_count++;
			}

			/* Expand cache memory */
			if (g_cache_list[wanted_cache_index]->bulk_count == 0) {
				g_cache_list[wanted_cache_index]->bulk_list = (char**) malloc(
						sizeof(char*));
				g_cache_list[wanted_cache_index]->bulk_id_list =
						(size_t*) malloc(sizeof(size_t));
				g_cache_list[wanted_cache_index]->bulk_size_list =
						(size_t*) malloc(sizeof(size_t));
				g_cache_list[wanted_cache_index]->bulk_list[g_cache_list[wanted_cache_index]->bulk_count] =
						(char*) malloc(want_total * sizeof(char));
			} else {
				g_cache_list[wanted_cache_index]->bulk_list = (char**) realloc(
						g_cache_list[wanted_cache_index]->bulk_list,
						(g_cache_list[wanted_cache_index]->bulk_count + 1)
								* sizeof(char*));
				g_cache_list[wanted_cache_index]->bulk_id_list =
						(size_t*) realloc(
								g_cache_list[wanted_cache_index]->bulk_id_list,
								(g_cache_list[wanted_cache_index]->bulk_count
										+ 1) * sizeof(size_t));
				g_cache_list[wanted_cache_index]->bulk_size_list =
						(size_t*) realloc(
								g_cache_list[wanted_cache_index]->bulk_size_list,
								(g_cache_list[wanted_cache_index]->bulk_count
										+ 1) * sizeof(size_t));
				g_cache_list[wanted_cache_index]->bulk_list[g_cache_list[wanted_cache_index]->bulk_count] =
						(char*) malloc(want_total * sizeof(char));
			}

			for (int t = 0; t < THREAD_NUM; t++) {
				if (pos + t * (CACHE_BULK_SIZE_PER_THREAD) > conn->size)
					break;
				/* xfer data to caller */
				memcpy(
						g_cache_list[wanted_cache_index]->bulk_list[g_cache_list[wanted_cache_index]->bulk_count]
								+ t * (CACHE_BULK_SIZE_PER_THREAD),
						conn->io[t].buffer, want_per_thread[t]);
			}
			g_cache_list[wanted_cache_index]->bulk_size_list[g_cache_list[wanted_cache_index]->bulk_count] =
					want_total;
			g_cache_list[wanted_cache_index]->bulk_id_list[g_cache_list[wanted_cache_index]->bulk_count] =
					wanted_bulk_id;

			for (int t = 0; t < THREAD_NUM; t++) {
				if (pos + t * (CACHE_BULK_SIZE_PER_THREAD) > conn->size)
					break;
				use_buffer(conn, want_per_thread[t], t);
			}
			wanted_bulk_index = g_cache_list[wanted_cache_index]->bulk_count;

			g_cache_list[wanted_cache_index]->bulk_count++;

			printf("download: obtained bulk id %zu\n", wanted_bulk_id);

			g_mutex_unlock(&g_cache_lock);
		}

		size_t copy_ptr = (i == 0) ? pos % (CACHE_BULK_SIZE) : 0;
		size_t copy_size =
				(residual
						< g_cache_list[wanted_cache_index]->bulk_size_list[wanted_bulk_index]
								- copy_ptr) ?
						residual :
						(g_cache_list[wanted_cache_index]->bulk_size_list[wanted_bulk_index]
								- copy_ptr);
		size_t ptr_ptr = wanted - residual;

		memcpy((char*) ptr + ptr_ptr,
				&g_cache_list[wanted_cache_index]->bulk_list[wanted_bulk_index][copy_ptr],
				copy_size);

		copied += copy_size;
		residual -= copy_size;
		wanted_bulk_id += CACHE_BULK_SIZE;
	}

	return copied;
}