/* Very evil memory reclaimer, tries to allocate specified amount of 
   memory in smaller chunks, then releases everything (by exiting)

   (c) Domas Mituzas, MySQL AB, 2006
   This code is in public domain
*/

#define CHUNK 134217728L
#define TRIES 60 /* 60 Seconds */


#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main (int argc, char const* argv[])
{	
	size_t bytes;
	size_t chunk;
	void * p;
	int tries;
	
	if (argc<2) {
		fprintf(stderr,"Please provide an argument (memory size in megabytes)\n");
		exit(-1);
	}
	
	if ((bytes=(size_t)(atol(argv[1])*1024L*1024L))==0) {
		fprintf(stderr,"Please provide a valid number\n");
		exit(-1);
	}

	while (bytes>0) {
		if (bytes>=CHUNK) {
			chunk=CHUNK;
			bytes-=CHUNK;
		} else {
			chunk=bytes;
			bytes=0;
		}
		tries = 0;
		while (tries++<TRIES) {
			printf("Try %2d: allocating and filling %llu bytes, %llu remaining\n",
				tries, (unsigned long long)chunk, (unsigned long long)bytes);
			p=malloc(chunk);
			if (p==NULL) { /* Retry */
				sleep(1);
				continue;
			}
			memset(p,105,chunk); /* Fill with junk, so that memory is actually given by VM */
			break;
		}
		if (p==NULL) { /* Failed for all tries!!!! */
			fprintf(stderr,"Could not allocate all memory - %llu remaining\n", chunk + bytes);
			exit(-1);
		}
	}
	printf("Done\n");
	return 0;
}
