コード例 #1
0
ファイル: jbhtsimple.c プロジェクト: baskard/stasis
int test(void) {

	test_pair_t one = { 1, "one" };
	test_pair_t two = { 2, "two" };
	test_pair_t three = { 3, "three" };
	test_pair_t four = { 4, "four" };

	int i;
	int xid = Tbegin();

	jbHashTable_t *ht = jbHtCreate(xid, 79);
	if( jbHtInsert(xid, ht, &one.key, sizeof(int), one.value, sizeof(char)*4) ||
			jbHtInsert(xid, ht, &two.key, sizeof(int), two.value, sizeof(char)*4) ||
			jbHtInsert(xid, ht, &three.key, sizeof(int), three.value, sizeof(char)*6) ||
			jbHtInsert(xid, ht, &four.key, sizeof(int), four.value, sizeof(char)*5)
	  ) {
		return -1;
	}

	Tcommit(xid);
	xid = Tbegin();

	for( i = 1; i <= 4; i++ ) {
		char buf[7];
		jbHtLookup(xid, ht, &i, sizeof(int), buf);
		printf("key %u: %s\n", i, buf);
	}

	jbHtDelete(xid, ht);

	Tcommit(xid);

	return 0;
}
コード例 #2
0
ファイル: check_regions.c プロジェクト: baskard/stasis
} END_TEST

START_TEST(regions_lockSmokeTest) {
  Tinit();
  int xid = Tbegin();
  pageid_t pageid = TregionAlloc(xid, 100,0);
  fsckRegions(xid);
  Tcommit(xid);


  xid = Tbegin();
  int xid2 = Tbegin();

  TregionDealloc(xid, pageid);

  for(int i = 0; i < 50; i++) {
    TregionAlloc(xid2, 1, 0);
  }

  fsckRegions(xid);
  Tabort(xid);
  fsckRegions(xid2);
  Tcommit(xid2);
  Tdeinit();
} END_TEST
コード例 #3
0
ファイル: check_boundedLog.c プロジェクト: baskard/stasis
}END_TEST

/** @test  More complicated case of log w/ hard bound; many xacts at a time.
*/
START_TEST(boundedLogConcurrentTest) {
  stasis_log_type = LOG_TO_MEMORY;
  stasis_log_in_memory_max_entries = 1000;
  stasis_log_softcommit = 1;
  Tinit();
  int xid = Tbegin();
  pageid_t region_start = TregionAlloc(xid, NUM_XACTS, 0);
  Tcommit(xid);

  for(int64_t i = 0; i < NUM_XACTS; i++) {
    int xids[NUM_CONCURRENT_XACTS];
    for(int j = 0; j < NUM_CONCURRENT_XACTS; j++) {
      xids[j] = Tbegin();
    }
    for(int j = 0; j < NUM_CONCURRENT_XACTS; j++) {
      TinitializeFixedPage(xids[j], region_start + i, sizeof(uint64_t));
      recordid rid = {region_start + i, 0, sizeof(uint64_t)};
      Tset(xids[j], rid, &i);
      i++;
    }
    for(int j = 0; j < NUM_CONCURRENT_XACTS; j++) {
      Tcommit(xids[j]);
    }
  }

  Tdeinit();

}END_TEST
コード例 #4
0
ファイル: naiveHash.c プロジェクト: DreamtoucherN01/stasis
int main(int argc, char** argv) {

  assert(argc == 3);

  int xact_count = atoi(argv[1]);
  int count = atoi(argv[2]);

  /*  unlink("storefile.txt");
  unlink("logfile.txt");
  unlink("blob0_file.txt");
  unlink("blob1_file.txt");*/

  Tinit();
  
  int xid = Tbegin();

  recordid hash = TnaiveHashCreate(xid, sizeof(int), sizeof(int));

  Tcommit(xid);

  int i = 0;
  int k;
  for(k = 0; k < xact_count; k++) {
    xid = Tbegin();
    for(; i < (count*(k+1)) ; i++) {
      TnaiveHashInsert(xid, hash, &i, sizeof(int), &i, sizeof(int));
    }
    Tcommit(xid);

  }
  

  Tdeinit();

}
コード例 #5
0
ファイル: fisubject.c プロジェクト: baskard/stasis
static void* 
threadFunc(void* arg_ptr) {
  int j, k, startKey, endKey;
  int xid, count = 0;
  int bufferCurrentLength, bufferTotalSize;
  char* insertBuffer;

  /* Allocate the buffer that stores all outstanding hash table insertions. */
  bufferTotalSize = BUFFER_INITIAL_LENGTH;
  bufferCurrentLength = 0;
  insertBuffer = stasis_malloc(bufferTotalSize, char);

  xid = Tbegin();
  
  k = (intptr_t) arg_ptr;

  startKey = baseKey + (k * opsPerThread);
  endKey   = startKey + opsPerThread;

  for (j = startKey; j < endKey; j++) {
    ThashInsert(xid, hashTable, (byte*)&j, sizeof(int), (byte*)&j, sizeof(int));
    writeKeyToBuffer(&insertBuffer, &bufferCurrentLength, &bufferTotalSize, j);
    count++;
    
    if ((count % opsPerTransaction) == 0) {
      /* Prior to committing the transaction, write the hash table insertion buffer to 
       * the insert-log so that we can keep track of which insertions were possibly 
       * committed.  After the Tcommit() call, write the insertion buffer to the commit-
       * log so that we can keep track of which insertions were definitely committed.
       */
      writeBufferToLog(insertLog, insertBuffer, bufferCurrentLength);
      Tcommit(xid);
      writeBufferToLog(commitLog, insertBuffer, bufferCurrentLength);
      bufferCurrentLength = 0;

      xid = Tbegin();
      count = 0;
    }
  }

  /* Prior to committing the transaction, write the hash table insertion buffer to 
   * the insert-log so that we can keep track of which insertions were possibly 
   * committed.  After the Tcommit() call, write the insertion buffer to the commit-
   * log so that we can keep track of which insertions were definitely committed.
   */
  writeBufferToLog(insertLog, insertBuffer, bufferCurrentLength);
  Tcommit(xid);
  writeBufferToLog(commitLog, insertBuffer, bufferCurrentLength);
  
  return NULL;
}
コード例 #6
0
ファイル: prepare_2.c プロジェクト: glycerine/stasis
int test() {
  int i;
  int writeVal, readVal;
  
  /** These need to be reset manually. */
  int xid = 2; 
  recordid rec = { 0,0,sizeof(int) };


  InitiateRecovery();

  printf("\nRunning prepare testing commit.\n");
  

  Tread(xid, rec, &readVal);
  printf("value read is %d\n", readVal);

  Tcommit(xid);

  xid = Tbegin();

  printf("xid = %d\n", xid);

  Tread(xid, rec, &readVal);
  printf("value read is %d\n", readVal);

  Tabort(xid);

  exit(-1);

}
コード例 #7
0
ファイル: jbhashdisk.c プロジェクト: Zhoutall/stasis
int test() {

	unsigned int i, xid;
	const unsigned int INSERT_NUM = 10000; /* should be > JB_HASHTABLE_SIZE */
	char value[22]; /* should be log(INSERT_NUM)+8 */
	jbHashTable_t *ht; 

	xid = Tbegin();
	ht = jbHtCreate(xid, 1000);

	for( i = 0; i < INSERT_NUM; i++ ) {
		sprintf(value, "value: %u\n", i);
		jbHtInsert(xid, ht, &i, sizeof(int), value, sizeof(char)*strlen(value));
	}

	Tcommit(xid);
	xid = Tbegin();

	for( i = 0; i < INSERT_NUM; i++ ) {
		jbHtLookup(xid, ht, &i, sizeof(int), value);
		printf("%s", value);
	}

	jbHtDelete(xid, ht);

	Tabort(xid);

	return 0;
}
コード例 #8
0
ファイル: toplevel.c プロジェクト: DreamtoucherN01/stasis
int main(int argc, char * argv[]) {

  Tinit();
  ReferentialAlgebra_init();

  recordid rootEntry;
  recordid hash;
  int xid = Tbegin();
  if(TrecordType(xid, ROOT_RECORD) == INVALID_SLOT) {
    printf("Creating new store\n");

    rootEntry = Talloc(xid, sizeof(recordid));
    assert(rootEntry.page == ROOT_RECORD.page);
    assert(rootEntry.slot == ROOT_RECORD.slot);

    hash = ReferentialAlgebra_allocContext(xid);

    Tset(xid, rootEntry, &hash);

  } else {
    printf("Opened existing store\n");
    rootEntry.page = ROOT_RECORD.page;
    rootEntry.slot = ROOT_RECORD.slot;
    rootEntry.size = sizeof(recordid);

    Tread(xid, rootEntry, &hash);

  }

  context = ReferentialAlgebra_openContext(xid,hash);

  Tcommit(xid);

  FILE * in;
  if(argc == 3) { // listen on socket
    if(strcmp("--socket", argv[1])) {
      printf("usage:\n\n%s\n%s <filename>\n%s --socket addr:port\n",
	     argv[0],argv[0],argv[0]);
    } else {
      startServer(argv[2], hash);
    }

    printf("Shutting down...\n");
  } else {
    if(argc == 2) {
      in = fopen(argv[1], "r");
      if(!in) {
	printf("Couldn't open input file.\n");
	return 1;
      }
    } else {
      in = stdin;
    }
    openInterpreter(in, stdout, hash);
  }
  Tdeinit();
}
コード例 #9
0
int main(int argc, char** argv) {

  assert(argc == 3 || argc == 4);

  int thread_count = atoi(argv[1]);
  count = atoi(argv[2]);

  alwaysCommit = (argc==4);

  unlink("storefile.txt");
  unlink("logfile.txt");
  unlink("blob0_file.txt");
  unlink("blob1_file.txt");

  pthread_t * workers = stasis_malloc(thread_count, pthread_t);

  Tinit();
  int xid = Tbegin();
  //  hash = ThashCreate(xid, sizeof(int), sizeof(int));
  hash = ThashCreate(xid, VARIABLE_LENGTH, VARIABLE_LENGTH);
  
  Tcommit(xid);

  int k;

  /* threads have static thread sizes.  Ughh. */
  pthread_attr_t attr;
  pthread_attr_init(&attr);

  pthread_mutex_init(&mutex, NULL);

  pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
  //  pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
  pthread_mutex_lock(&mutex);


  for(k = 0; k < thread_count; k++) {
    int * k_copy = stasis_alloc(int);
    *k_copy = k ;
    pthread_create(&workers[k], &attr, go, k_copy);

  }

  pthread_mutex_unlock(&mutex);

  for(k = 0; k < thread_count; k++) {
    pthread_join(workers[k],NULL);
  }

  Tdeinit();

  printf("Committed %d times, put %d times.\n", commitCount, putCount);
}
コード例 #10
0
ファイル: test1.c プロジェクト: baskard/stasis
int test(int argc, char **argv) {
	int xid;
	int writeVals[NUM_TRIALS];
	int readVals[NUM_TRIALS];
	recordid recs[NUM_TRIALS];

	int i;
	int failed = 0;

	printf("\nRunning %s\n", __FILE__);

	xid = Tbegin();

	for (i = 0; i < NUM_TRIALS; i++) {
		writeVals[i] = rand();

		recs[i] = Talloc(xid, sizeof(int));

		Tset(xid, recs[i], &writeVals[i]);
	}

	Tcommit(xid);
	xid = Tbegin();

	for (i = 0; i < NUM_TRIALS; i++) {
		Tread(xid, recs[i], &readVals[i]);

		if (VERBOSE) 
			printf("value set is %d, value read is %d\n", writeVals[i], readVals[i]); 

		if (writeVals[i] != readVals[i]) 
			failed = 1;
	}

	Tcommit(xid);

	printf("%s\n\n", failed ? "****FAILED****" : "PASSED");

	return failed;
}
コード例 #11
0
ファイル: check_lsmTree.c プロジェクト: Zhoutall/stasis
void insertProbeIter(lsmkey_t NUM_ENTRIES) {
  int intcmp = 0;
  lsmTreeRegisterComparator(intcmp,cmp);
  TlsmRegionAllocConf_t alloc_conf = LSM_REGION_ALLOC_STATIC_INITIALIZER;

  stasis_page_impl_register(lsmRootImpl());
  Tinit();
  int xid = Tbegin();
  recordid tree = TlsmCreate(xid, intcmp,
			     TlsmRegionAlloc, &alloc_conf,
			     sizeof(lsmkey_t));
  long oldpagenum = -1;
  for(lsmkey_t i = 0; i < NUM_ENTRIES; i++) {
    long pagenum = TlsmFindPage(xid, tree, (byte*)&i);
    assert(pagenum == -1 || pagenum == oldpagenum || oldpagenum == -1);
    DEBUG("TlsmAppendPage %d\n",i);
    TlsmAppendPage(xid, tree, (const byte*)&i, TlsmRegionAlloc, &alloc_conf, i + OFFSET);
    pagenum = TlsmFindPage(xid, tree, (byte*)&i);
    oldpagenum = pagenum;
    assert(pagenum == i + OFFSET);
  }

  for(lsmkey_t i = 0; i < NUM_ENTRIES; i++) {
    long pagenum = TlsmFindPage(xid, tree, (byte*)&i);
    assert(pagenum == i + OFFSET);
  }

  int64_t count = 0;

  lladdIterator_t * it = lsmTreeIterator_open(xid, tree);

  while(lsmTreeIterator_next(xid, it)) {
    lsmkey_t * key;
    lsmkey_t **key_ptr = &key;
    int size = lsmTreeIterator_key(xid, it, (byte**)key_ptr);
    assert(size == sizeof(lsmkey_t));
    long *value;
    long **value_ptr = &value;
    size = lsmTreeIterator_value(xid, it, (byte**)value_ptr);
    assert(size == sizeof(pageid_t));
    assert(*key + OFFSET == *value);
    assert(*key == count);
    count++;
  }
  assert(count == NUM_ENTRIES);

  lsmTreeIterator_close(xid, it);

  Tcommit(xid);
  Tdeinit();
}
コード例 #12
0
ファイル: commit-speed.c プロジェクト: glycerine/stasis
int test()
{
	struct timeval start, end, total;
	recordid rids[TESTS];
	long commited[TESTS];
	long aborted[TESTS];
	int i, j, xid = Tbegin();

	for( i = 0; i < TESTS; i++ ) {
		rids[i] = Talloc(xid, sizeof(long));
		commited[i] = random();
		aborted[i] = random();
		Tset(xid, rids[i], &commited[i]);
	}

	gettimeofday(&start, NULL);
	Tcommit(xid);
	gettimeofday(&end, NULL);
	timersub(&end, &start, &total);
	printf("commit %u: %ld.%ld\n", TESTS, total.tv_sec, total.tv_usec);

	for( j = 0; j < 10; j++ ) {

		xid = Tbegin();

		for( i = 0; i < TESTS*j; i++ ) {
			Tset(xid, rids[random() % TESTS], &aborted[i%TESTS]);
		}

		gettimeofday(&start, NULL);
		Tcommit(xid);
		gettimeofday(&end, NULL);
		timersub(&end, &start, &total);
		printf("commit %u: %ld.%ld\n", TESTS*j, total.tv_sec, total.tv_usec);
	}

	return 0;
}
コード例 #13
0
ファイル: check_regions.c プロジェクト: baskard/stasis
} END_TEST

START_TEST(regions_recoveryTest) {

  Tinit();

  pageid_t pages[50];
  int xid1 = Tbegin();
  int xid2 = Tbegin();
  for(int i = 0; i < 50; i+=2) {
    pages[i] = TregionAlloc(xid1, stasis_util_random64(4)+1, 0);
    pages[i+1] = TregionAlloc(xid2, stasis_util_random64(2)+1, 0);
  }

  fsckRegions(xid1);

  Tcommit(xid1);

  Tdeinit();

  if(TdurabilityLevel() == VOLATILE) { return; }

  Tinit();

  int xid = Tbegin();
  fsckRegions(xid);

  for(int i = 0; i < 50; i+=2) {
    TregionDealloc(xid, pages[i]);
  }

  fsckRegions(xid);
  Tabort(xid);
  fsckRegions(Tbegin());
  Tdeinit();

  Tinit();
  fsckRegions(Tbegin());
  Tdeinit();

} END_TEST
コード例 #14
0
ファイル: check_logtable.cpp プロジェクト: Bathtor/bLSM
void insertProbeIter(size_t NUM_ENTRIES)
{
    srand(1000);
    unlink("storefile.txt");
    unlink("logfile.txt");
    system("rm -rf stasis_log/");

    sync();

    bLSM::init_stasis();

    int xid = Tbegin();

    Tcommit(xid);

    xid = Tbegin();

    mergeManager merge_mgr(0);
    mergeStats * stats = merge_mgr.get_merge_stats(1);

    diskTreeComponent *ltable_c1 = new diskTreeComponent(xid, 1000, 10000, 5, stats);

    std::vector<std::string> data_arr;
    std::vector<std::string> key_arr;
    preprandstr(NUM_ENTRIES, data_arr, 5*4096, true);
    preprandstr(NUM_ENTRIES+200, key_arr, 50, true);//well i can handle upto 200
    
    std::sort(key_arr.begin(), key_arr.end(), &mycmp);

    removeduplicates(key_arr);
    if(key_arr.size() > NUM_ENTRIES)
        key_arr.erase(key_arr.begin()+NUM_ENTRIES, key_arr.end());
    
    NUM_ENTRIES=key_arr.size();
    
    if(data_arr.size() > NUM_ENTRIES)
        data_arr.erase(data_arr.begin()+NUM_ENTRIES, data_arr.end());  
    
    printf("Stage 1: Writing %llu keys\n", (unsigned long long)NUM_ENTRIES);

    for(size_t i = 0; i < NUM_ENTRIES; i++)
    {
        //prepare the tuple
        dataTuple* newtuple = dataTuple::create(key_arr[i].c_str(), key_arr[i].length()+1, data_arr[i].c_str(), data_arr[i].length()+1);

        ltable_c1->insertTuple(xid, newtuple);
        dataTuple::freetuple(newtuple);
    }
    printf("\nTREE STRUCTURE\n");
    ltable_c1->print_tree(xid);

    printf("Writes complete.\n");

    ltable_c1->writes_done();

    Tcommit(xid);
    xid = Tbegin();

    printf("Stage 2: Sequentially reading %llu tuples\n", (unsigned long long)NUM_ENTRIES);
    
    size_t tuplenum = 0;
    diskTreeComponent::iterator * tree_itr = ltable_c1->open_iterator();


    dataTuple *dt=0;
    while( (dt=tree_itr->next_callerFrees()) != NULL)
    {
        assert(dt->rawkeylen() == key_arr[tuplenum].length()+1);
        assert(dt->datalen() == data_arr[tuplenum].length()+1);
        tuplenum++;
        dataTuple::freetuple(dt);
        dt = 0;
    }
    delete(tree_itr);
    assert(tuplenum == key_arr.size());
    
    printf("Sequential Reads completed.\n");

    int rrsize=key_arr.size() / 3;
    printf("Stage 3: Randomly reading %d tuples by key\n", rrsize);

    for(int i=0; i<rrsize; i++)
    {
        //randomly pick a key
        int ri = rand()%key_arr.size();

		dataTuple *dt = ltable_c1->findTuple(xid, (const dataTuple::key_t) key_arr[ri].c_str(), (size_t)key_arr[ri].length()+1);

        assert(dt!=0);
        assert(dt->rawkeylen() == key_arr[ri].length()+1);
        assert(dt->datalen() == data_arr[ri].length()+1);
        dataTuple::freetuple(dt);
        dt = 0;        
    }

    printf("Random Reads completed.\n");
    Tcommit(xid);
    bLSM::deinit_stasis();
}
コード例 #15
0
ファイル: strings.c プロジェクト: Zhoutall/stasis
int test() {
	int xid;
	int NUM_TRIALS=100;
	recordid rec;

	/* counters */
	int i;
	char c;

	/* used for making the random strings*/
	double r;
	int start, end;

	/* used to make a long string */	
	char first_printable_ascii = ' ';
	char last_printable_ascii = '~';
	int ascii_length = (int)(last_printable_ascii - first_printable_ascii);
	char *ASCII = (char *)malloc(sizeof(char) * ascii_length);

	/* an array of strings */
	char **strings = (char **)malloc(sizeof(char*) * NUM_TRIALS);

	/* output buffer */
	char *out_buffer = (char *)malloc(sizeof(char) * ascii_length);


	srand(SEED);

	/* create the long string from which random strings will be made */
	for (c = 0; c < ascii_length; c++) {
		ASCII[(int)c] = first_printable_ascii + c;
	}

	for (i = 0; i < NUM_TRIALS; i++) {

		r = ((double)rand()/(double)((double)RAND_MAX+1)); /* returns [0, 1)*/
		r = r*ascii_length;
		start = (int)r; /* an int in the rand [0, ascii_length) */
			
		r = ((double)rand()/(double)((double)RAND_MAX+1)); /* returns [0, 1)*/
		r = r*ascii_length;
		end = (int)r; /* an int in the rand [0, ascii_length) */
	
		if (start == end) {
			i--;
			continue;
		}

		if (end < start) {
			int swap = start;
			start = end;
			end = swap;
		}
		

		strings[i] = (char *)malloc(sizeof(char) * (end - start) + 1);
		strncpy(strings[i], ASCII + start, end-start);
		strings[i][end-start-1] = '\0'; /* make the string null terminated */
		
	}

	for (i = 0; i < NUM_TRIALS; i++) {
		xid = Tbegin();
		rec = Talloc(xid, sizeof(char)*(strlen(strings[i]) +1));
		Tset(xid, rec, strings[i]);

		Tread(xid, rec, out_buffer);
			
		if (VERBOSE) {
			printf("xid %d set rid (%d, %d) to [%s], and read [%s]\n", xid, rec.page, rec.slot, strings[i], out_buffer);
		}		
		assert(strcmp(strings[i], out_buffer) == 0); 
		Tcommit(xid);
	}
	
	return 0;
}
コード例 #16
0
ファイル: fisubject.c プロジェクト: baskard/stasis
int
runSubject(void) {
  pthread_t* threads;
  pthread_attr_t attr;
  intptr_t k;
  int xid, fd;

  /* Need the following sleep call for debugging. */
  //sleep(45);

  printf("\tRunning Subject Process\n"); fflush(stdout);

  readGlobalsFromSharedBuffer();

  initHashTable = 1;

  Tinit();
  
  if (iteration == 0) {
    /* Create the transactional hash table data structure. */
    xid = Tbegin();
    hashTable = ThashCreate(xid, sizeof(int), sizeof(int));
    Tcommit(xid);

    /* Write the hash table recordid to a file, so it can be 
     * reloaded during subsequent iterations.
     */
    fd = open("recordid.txt", O_CREAT | O_WRONLY | O_SYNC, 0777);
    write(fd, (char*) &hashTable, sizeof(recordid));
    close(fd);
  }
  else {
    /* Otherwise, read in the hash table from disk. */
    fd = open("recordid.txt", O_RDONLY, 0777);
    read(fd, (char*) &hashTable, sizeof(recordid));
    close(fd);
  }

  initHashTable = 0;
  
  /* Open the insert and commit log files. The insert-log keeps track of all insertions
   * that were made to the hash-table, not all of which may have been committed.  The
   * commit-log keeps track of all insertions that were definitely committed.
   */
  insertLog = open("inserts.txt", O_CREAT | O_RDWR | O_APPEND, 0777);
  commitLog = open("commits.txt", O_CREAT | O_RDWR | O_APPEND, 0777);

  /* Allocate the worker threads. */
  threads = stasis_malloc(numThreads, pthread_t);
  
  pthread_attr_init(&attr);
  pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);

  pthread_mutex_init(&hashTableMutex, NULL);

  for (k = 0; k < numThreads; k++) {
    pthread_create(&threads[k], &attr, threadFunc, (void*) k);
  }
  
  for (k = 0; k < numThreads; k++) {
    pthread_join(threads[k], NULL);
  }

  /* Close the insert and commit log files. */
  close(insertLog);
  close(commitLog);
  
  Tdeinit();

  printf("\t\tSubject Process Exiting Normally\n"); fflush(stdout);

  return 0;
}
コード例 #17
0
ファイル: twentyfour2.c プロジェクト: Zhoutall/stasis
int test() {
  int xid;
  char *handle_in = "jkit";
  char *name_in = "Jimmy Kittiyachavalit";
  int phone_in = 8821417;
  
  char *handle_out = (char *)malloc(strlen(handle_in)+1);
  char *name_out = (char *)malloc(strlen(name_in)+1);
  int phone_out;
  
  recordid r_name, r_handle, r_phone;
  
  xid = Tbegin();
  
  r_handle = Talloc(xid, strlen(handle_in)+1);
  r_name = Talloc(xid, strlen(name_in)+1);
  r_phone = Talloc(xid, sizeof(int));

  Tset(xid, r_handle, handle_in);
  printf("set handle to [%s]\n", handle_in);
  Tset(xid, r_name, name_in);
  printf("set name to [%s]\n", name_in);
  Tset(xid, r_phone, &phone_in);
  printf("set name to [%d]\n", phone_in);
  
  Tread(xid, r_handle, handle_out);
  printf("read handle is [%s]\n", handle_out);
  Tread(xid, r_name, name_out);
  printf("read name is [%s]\n", name_out);
  Tread(xid, r_phone, &phone_out);
  printf("read name is [%d]\n", phone_out);
    
  
  Tcommit(xid);



  xid = Tbegin();
  handle_in = "tikj";
  name_in = "tilavahcayittik ymmij";
  phone_in = 3142116;
  handle_out = (char *)malloc(strlen(handle_in)+1);
  name_out = (char *)malloc(strlen(name_in)+1);
  phone_out = 0;
  Tset(xid, r_handle, handle_in);
  printf("set handle to [%s]\n", handle_in);
  Tset(xid, r_name, name_in);
  printf("set name to [%s]\n", name_in);
  Tset(xid, r_phone, &phone_in);
  printf("set name to [%d]\n", phone_in);
  
  Tread(xid, r_handle, handle_out);
  printf("read handle is [%s]\n", handle_out);
  Tread(xid, r_name, name_out);
  printf("read name is [%s]\n", name_out);
  Tread(xid, r_phone, &phone_out);
  printf("read name is [%d]\n", phone_out);
  
  printf("aborted the transaction\n");  

  Tabort(xid);

  xid = Tbegin();
  handle_out = (char *)malloc(strlen(handle_in)+1);
  name_out = (char *)malloc(strlen(name_in)+1);
  phone_out = 0;
  Tread(xid, r_handle, handle_out);
  printf("read handle is [%s]\n", handle_out);
  Tread(xid, r_name, name_out);
  printf("read name is [%s]\n", name_out);
  Tread(xid, r_phone, &phone_out);
  printf("read name is [%d]\n", phone_out);
  

  Tcommit(xid);
  
  return 0;
}
コード例 #18
0
ファイル: toplevel.c プロジェクト: DreamtoucherN01/stasis
int openInterpreter(FILE * in, FILE * out, recordid hash) {
  char * line = NULL;
  size_t len = 0;
  int AUTOCOMMIT = 1;
  int debug = 0;
  int xid = -1;
  size_t read;

  fprintf(out, "> ");
  int ret = 0;
  if(!AUTOCOMMIT) { xid = Tbegin(); }
  while((read = getline(&line, &len, in)) != -1) {
    if(line[0] == '!') {
      if(!strncmp(line+1,"debug",strlen("debug"))) {
	debug = !debug;
	if(debug)
	  fprintf(out, "Enabling debugging\n");
	else
	  fprintf(out, "Disabling debugging\n");
      } else if(!strncmp(line+1,"regions",strlen("regions"))) {
	fprintf(out, "Boundary tag pages:\n");
	pageid_t pid = REGION_FIRST_TAG;
	boundary_tag tag;
	TregionReadBoundaryTag(-1,pid,&tag);
	int done = 0;
	while(!done) {
	  fprintf(out, "\tpageid=%lld\ttype=%d\tsize=%lld\n", pid, tag.allocation_manager, tag.size);
	  if(tag.size == UINT32_MAX) { fprintf(out, "\t[EOF]\n"); }
	  int err = TregionNextBoundaryTag(-1,&pid,&tag,0);
	  if(!err) { done = 1; }
	}
      } else if(!strncmp(line+1,"autocommit",strlen("autocommit"))) {
	if(AUTOCOMMIT) {
	  // we're not in a transaction
	  fprintf(out, "Disabling autocommit\n");
	  AUTOCOMMIT = 0;
	  xid = Tbegin();
	} else {
	  fprintf(out, "Enabling autocommit\n");
	  AUTOCOMMIT = 1;
	  Tcommit(xid);
	}
   /* } else if(!strncmp(line+1,"parseTuple",strlen("parseToken"))) {
	char * c = line + 1 + strlen("parseToken");
	char ** toks = parseTuple(&c);
	for(int i = 0; toks[i]; i++) {
	  fprintf(out, "col %d = ->%s<-\n", i, toks[i]);
	}
	fprintf(out, "trailing stuff: %s", c);
      } else if(!strncmp(line+1,"parseExpression",
			 strlen("parseExpression"))) {
	char * c = line + 1 + strlen("parseExpression");
	lladdIterator_t * it = parseExpression(xid, hash, &c);
	it = 0; */
      } else if(!strncmp(line+1,"exit",strlen("exit"))) {
	break;
      } else if(!strncmp(line+1,"shutdown",strlen("shutdown"))) {
	ret = SHUTDOWN_SERVER;
	break;
      }
    } else {
      expr_list * results = 0;
      parse(line, &results);
      for(int i = 0; results && i < results->count; i++) {
	expr * e = results->ents[i];
	switch(e->typ) {
	case query_typ: {
	  lladdIterator_t * it = ReferentialAlgebra_ExecuteQuery(xid, context, e->u.q);
	  if(it) {
	    while(Titerator_next(xid,it)) {
	      byte * tup;
	      Titerator_value(xid,it, &tup);
	      char * tupleString = stringTuple(*(tuple_t*)tup);
	      fprintf(out, "%s\n", tupleString);
	      free(tupleString);
	    }
	    Titerator_close(xid,it);
	  }
	} break;
	case insert_typ: {
	  if(AUTOCOMMIT) { xid = Tbegin(); }
	  ReferentialDML_ExecuteInsert(xid, context, e->u.i);
	  if(AUTOCOMMIT) { Tcommit(xid); xid = -1;}
	} break;
	case delete_typ: {
	  if(AUTOCOMMIT) { xid = Tbegin(); }
	  ReferentialDML_ExecuteDelete(xid, context, e->u.d);
	  if(AUTOCOMMIT) { Tcommit(xid); xid = -1;}
	} break;
	case create_typ: {
	  if(AUTOCOMMIT) { xid = Tbegin(); }
	  ReferentialDDL_CreateTable(xid, context, e->u.c);
	  if(AUTOCOMMIT) { xid = Tcommit(xid); xid = -1;}
	} break;
	default:
	  abort();
	}
      }

      //XXX typecheck(context, results);
      if(results) {
	char * str = pp_expr_list(results);
	printf("%s", str);
	free(str);
      } else {
	printf("No results\n");
      }
    }
    fprintf(out, "> ");
  }
  if(!AUTOCOMMIT) { Tcommit(xid); }

  free(line);
  fprintf(out, "\n");
  return ret;
}
コード例 #19
0
ファイル: stasis_jni_Stasis.c プロジェクト: bloom-lang/jol
JNIEXPORT void JNICALL Java_stasis_jni_Stasis_commit
  (JNIEnv *e, jclass c, jlong xid) {
  printf("commiting %d\n", xid);
  Tcommit((int)xid);
}
コード例 #20
0
ファイル: inc_dec.c プロジェクト: Zhoutall/stasis
int test() {
  int i;
  int xid, writeVal, readVal;
  recordid rec;
  
  printf("\nRunning test1\n");
  

  writeVal = 10;
  
  xid = Tbegin();

  rec = Talloc(xid, sizeof(int));

  Tset(xid, rec, &writeVal);
  Tread(xid, rec, &readVal);
  
  printf("value set is %d, value read is %d\n", writeVal, readVal);
    
  Tcommit(xid);

  xid = Tbegin();
  Tread(xid, rec, &readVal);
  printf("value read is %d\n", readVal);

  Tincrement(xid, rec);
  printf("calling Tincrement\n");

  Tread(xid, rec, &readVal);
  printf("value read is %d\n", readVal);

  Tincrement(xid, rec);
  printf("calling Tincrement\n");

  Tread(xid, rec, &readVal);
  printf("value read is %d\n", readVal);

  Tabort(xid);
  printf("aborting\n");
  xid = Tbegin();

  Tread(xid, rec, &readVal);
  printf("value read is %d\n", readVal);

  Tincrement(xid, rec);
  printf("calling Tincrement\n");

  Tread(xid, rec, &readVal);
  printf("value read is %d\n", readVal);

  Tdecrement(xid, rec);
  printf("calling Tdecrement\n");

  Tread(xid, rec, &readVal);
  printf("value read is %d\n", readVal);
  Tdecrement(xid, rec);
  printf("calling Tdecrement\n");

  Tread(xid, rec, &readVal);
  printf("value read is %d\n", readVal);
  Tdecrement(xid, rec);
  printf("calling Tdecrement\n");

  Tread(xid, rec, &readVal);
  printf("value read is %d\n", readVal);

  for (i = 0; i < 10; i++) {
    Tdecrement(xid, rec);
    printf("calling Tdecrement\n");
    
    Tread(xid, rec, &readVal);
    printf("value read is %d\n", readVal);
  }

  Tcommit(xid);
  printf("committing\n");
  xid = Tbegin();

  Tread(xid, rec, &readVal);
  printf("value read is %d\n", readVal);

  Tdecrement(xid, rec);
  printf("calling Tdecrement\n");

  Tread(xid, rec, &readVal);
  printf("value read is %d\n", readVal);

  Tincrement(xid, rec);
  printf("calling Tincrement\n");

  Tread(xid, rec, &readVal);
  printf("value read is %d\n", readVal);

  Tdecrement(xid, rec);
  printf("calling Tdecrement\n");

  Tread(xid, rec, &readVal);
  printf("value read is %d\n", readVal);

  
  

  printf("\n");
  return 0;

}
コード例 #21
0
ファイル: check_regions.c プロジェクト: baskard/stasis
} END_TEST

START_TEST(regions_lockRandomizedTest) {
  Tinit();

  const int NUM_XACTS = 100;
  const int NUM_OPS   = 10000;
  const int FUDGE = 10;
  int xids[NUM_XACTS];

  pageid_t * xidRegions[NUM_XACTS + FUDGE];
  int xidRegionCounts[NUM_XACTS + FUDGE];

  int longXid = Tbegin();

  time_t seed = time(0);
  printf("\nSeed = %ld\n", seed);
  srandom(seed);

  for(int i = 0; i < NUM_XACTS; i++) {
    xids[i] = Tbegin();
    assert(xids[i] < NUM_XACTS + FUDGE);
    xidRegions[xids[i]] = stasis_malloc(NUM_OPS, pageid_t);
    xidRegionCounts[xids[i]] = 0;
  }
  int activeXacts = NUM_XACTS;

  for(int i = 0; i < NUM_OPS; i++) {
    pageid_t j;
    if(!(i % (NUM_OPS/NUM_XACTS))) {
      // abort or commit one transaction randomly.
      activeXacts --;
      j = stasis_util_random64(activeXacts);

      if(stasis_util_random64(2)) {
	Tcommit(xids[j]);
      } else {
	Tabort(xids[j]);
      }

      if(activeXacts == 0) {
	break;
      }
      for(; j < activeXacts; j++) {
	xids[j] = xids[j+1];
      }
      fsckRegions(longXid);
    }

    j = stasis_util_random64(activeXacts);

    if(stasis_util_random64(2)) {
      // alloc
      xidRegions[xids[j]][xidRegionCounts[xids[j]]] = TregionAlloc(xids[j], stasis_util_random64(100), 0);
	xidRegionCounts[xids[j]]++;
    } else {
      // free
      if(xidRegionCounts[xids[j]]) {
	pageid_t k = stasis_util_random64(xidRegionCounts[xids[j]]);

	TregionDealloc(xids[j], xidRegions[xids[j]][k]);

	xidRegionCounts[xids[j]]--;

	for(; k < xidRegionCounts[xids[j]]; k++) {
	  xidRegions[xids[j]][k] = xidRegions[xids[j]][k+1];
	}
      }
    }
  }

  for(int i = 0; i < activeXacts; i++) {
    Tabort(i);
    fsckRegions(longXid);
  }

  Tcommit(longXid);

  Tdeinit();
} END_TEST
コード例 #22
0
ファイル: test3.c プロジェクト: baskard/stasis
int test(int argc, char **argv) {
  int xids[NUM_TRIALS];
  int initVals[NUM_TRIALS];
  int writeVals[NUM_TRIALS];
  int readVals[NUM_TRIALS];
  int commits[NUM_TRIALS];
  int i;
  recordid recs[NUM_TRIALS];
  int failed = 0;

  printf("\nRunning %s\n", __FILE__);

  for (i = 0; i < NUM_TRIALS; i++) {
    xids[i] = Tbegin();
    initVals[i] = rand();
    recs[i] = Talloc(xids[i], sizeof(int));
    Tset(xids[i], recs[i], &initVals[i]);
    Tcommit(xids[i]);
  }

  

  for (i = 0; i < NUM_TRIALS; i++) {
    xids[i] = Tbegin();
    commits[i] = 0;
    writeVals[i] = rand();
  }

  for (i = 0; i < NUM_TRIALS; i++) {
    Tset(xids[i], recs[i], &writeVals[i]);
  }
  
  for (i = 0; i < NUM_TRIALS; i++) {
    if (rand() % 2) { 
      Tcommit(xids[i]);
      commits[i] = 1;
    } else {
      Tabort(xids[i]);
   }
  }

  for (i = 0; i < NUM_TRIALS; i++) {
      Tread(xids[i], recs[i], &readVals[i]);
  }


  for (i = 0; i < NUM_TRIALS; i++) {
    if (VERBOSE) {
      if (commits[i])
         printf("xid %d commited value %d, and read %d\n", xids[i], writeVals[i], readVals[i]);
      else
         printf("xid %d aborted while setting value %d, and read %d and should've read %d\n", xids[i], writeVals[i], readVals[i], initVals[i]);
          
    }
    
  if (commits[i]) {
     if (writeVals[i] != readVals[i])
        failed = 1;
  } else {
     if (initVals[i] != readVals[i])
        failed = 1;    
  }  
}  
  
  printf("%s\n\n", failed ? "****FAILED****" : "PASSED");

  return failed;
}
コード例 #23
0
ファイル: check_regions.c プロジェクト: baskard/stasis
END_TEST

START_TEST(regions_randomizedTest) {
  Tinit();
  time_t seed = time(0);
  printf("Seed = %ld: ", seed);
  srandom(seed);
  int xid = Tbegin();
  pageid_t pagesAlloced = 0;
  pageid_t regionsAlloced = 0;
  double max_blowup = 0;
  pageid_t max_region_count = 0;
  pageid_t max_waste = 0;
  pageid_t max_size = 0;
  pageid_t max_ideal_size = 0;
  for(int i = 0; i < 10000; i++) {
    if(!(i % 100)) {
      Tcommit(xid);
      xid = Tbegin();
    }
    if(!(i % 100)) {
      fsckRegions(xid);
    }

    if(stasis_util_random64(2)) {
      unsigned int size = stasis_util_random64(100);
      TregionAlloc(xid, size, 0);
      pagesAlloced += size;
      regionsAlloced ++;
    } else {
      if(regionsAlloced) {
	pageid_t victim = stasis_util_random64(regionsAlloced);
	pageid_t victimSize;
	pageid_t victimPage;
	TregionFindNthActive(xid, victim, &victimPage, &victimSize);
	TregionDealloc(xid, victimPage);
	pagesAlloced -= victimSize;
	regionsAlloced --;
      } else {
	i--;
      }
    }

    if(regionsAlloced) {
      pageid_t lastRegionStart;
      pageid_t lastRegionSize;

      TregionFindNthActive(xid, regionsAlloced-1, &lastRegionStart, &lastRegionSize);
      pageid_t length = lastRegionStart + lastRegionSize+1;
      pageid_t ideal  = pagesAlloced + regionsAlloced + 1;
      double blowup = (double)length/(double)ideal;
      unsigned long long bytes_wasted = length - ideal;
      // printf("Region count = %d, blowup = %d / %d = %5.2f\n", regionsAlloced, length, ideal, blowup);
      if(max_blowup < blowup) {
	max_blowup = blowup;
      }
      if(max_waste < bytes_wasted) {
	max_waste = bytes_wasted;
      }
      if(max_size < length) {
	max_size = length;
      }
      if(max_ideal_size < ideal) {
	max_ideal_size = ideal;
      }
      if(max_region_count < regionsAlloced) {
	max_region_count = regionsAlloced;
      }
    }
  }
  fsckRegions(xid);
  Tcommit(xid);

  Tdeinit();
  printf("Max # of regions = %lld, page file size = %5.2fM, ideal page file size = %5.2fM, (blowup = %5.2f)\n",
	 //peak bytes wasted = %5.2fM, blowup = %3.2f\n",
	 max_region_count,
	 ((double)max_size * PAGE_SIZE)/(1024.0*1024.0),
	 ((double)max_ideal_size * PAGE_SIZE)/(1024.0*1024.0),
	 (double)max_size/(double)max_ideal_size);
  //	 ((double)max_waste * PAGE_SIZE)/(1024.0*1024.0),
  //	 max_blowup);
  if((double)max_size/(double)max_ideal_size > 5) {
    // max_blowup isn't what we want here; it measures the peak
    // percentage of the file that is unused.  Instead, we want to
    // measure the actual and ideal page file sizes for this run.
    printf("ERROR: Excessive blowup (max allowable is 5)\n");
    abort();
  }

} END_TEST
コード例 #24
0
ファイル: check_merge.cpp プロジェクト: Bathtor/bLSM
void insertProbeIter(size_t NUM_ENTRIES)
{
    srand(1000);
    unlink("storefile.txt");
    unlink("logfile.txt");
    system("rm -rf stasis_log/");

    bLSM::init_stasis();

    //data generation
    std::vector<std::string> * data_arr = new std::vector<std::string>;
    std::vector<std::string> * key_arr = new std::vector<std::string>;
    
    preprandstr(NUM_ENTRIES, data_arr, 10*8192, true);
    preprandstr(NUM_ENTRIES+200, key_arr, 100, true);
    
    std::sort(key_arr->begin(), key_arr->end(), &mycmp);

    removeduplicates(key_arr);
    scramble(key_arr);


    if(key_arr->size() > NUM_ENTRIES)
        key_arr->erase(key_arr->begin()+NUM_ENTRIES, key_arr->end());
    
    NUM_ENTRIES=key_arr->size();
    
    if(data_arr->size() > NUM_ENTRIES)
        data_arr->erase(data_arr->begin()+NUM_ENTRIES, data_arr->end());

    int xid = Tbegin();

    bLSM * ltable = new bLSM(10 * 1024 * 1024, 1000, 10000, 5);
    mergeScheduler mscheduler(ltable);

    recordid table_root = ltable->allocTable(xid);

    Tcommit(xid);

    mscheduler.start();

    printf("Stage 1: Writing %llu keys\n", (unsigned long long)NUM_ENTRIES);
    
    struct timeval start_tv, stop_tv, ti_st, ti_end;
    double insert_time = 0;
    int64_t datasize = 0;
    std::vector<pageid_t> dsp;
    gettimeofday(&start_tv,0);
    for(size_t i = 0; i < NUM_ENTRIES; i++)
    {
        //prepare the key
        dataTuple *newtuple = dataTuple::create((*key_arr)[i].c_str(), (*key_arr)[i].length()+1,(*data_arr)[i].c_str(), (*data_arr)[i].length()+1);

        /*
        printf("key: \t, keylen: %u\ndata:  datalen: %u\n",
               //newtuple.key,
               *newtuple.keylen,
               //newtuple.data,
               *newtuple.datalen);
               */
        
        datasize += newtuple->byte_length();

        gettimeofday(&ti_st,0);        
        ltable->insertTuple(newtuple);
        gettimeofday(&ti_end,0);
        insert_time += tv_to_double(ti_end) - tv_to_double(ti_st);

        dataTuple::freetuple(newtuple);
        
    }
    gettimeofday(&stop_tv,0);
    printf("insert time: %6.1f\n", insert_time);
    printf("insert time: %6.1f\n", (tv_to_double(stop_tv) - tv_to_double(start_tv)));

    printf("\nTREE STRUCTURE\n");
    //ltable.get_tree_c1()->print_tree(xid);
    printf("datasize: %lld\n", (long long)datasize);
    //sleep(20);

    xid = Tbegin();


    printf("Stage 2: Looking up %llu keys:\n", (unsigned long long)NUM_ENTRIES);

    int found_tuples=0;
    for(int i=NUM_ENTRIES-1; i>=0; i--)
    {        
        int ri = i;
        //printf("key index%d\n", i);
        fflush(stdout);

        //get the key
        uint32_t keylen = (*key_arr)[ri].length()+1;        
        dataTuple::key_t rkey = (dataTuple::key_t) malloc(keylen);
        memcpy((byte*)rkey, (*key_arr)[ri].c_str(), keylen);
        //for(int j=0; j<keylen-1; j++)
        //rkey[j] = (*key_arr)[ri][j];
        //rkey[keylen-1]='\0';

        //find the key with the given tuple
        dataTuple *dt = ltable->findTuple(xid, rkey, keylen);

        assert(dt!=0);
        //if(dt!=0)
        {
			found_tuples++;
			assert(dt->rawkeylen() == (*key_arr)[ri].length()+1);
			assert(dt->datalen() == (*data_arr)[ri].length()+1);
			dataTuple::freetuple(dt);
        }
        dt = 0;
        free(rkey);
    }
    printf("found %d\n", found_tuples);

    key_arr->clear();
    data_arr->clear();
    delete key_arr;
    delete data_arr;
    
    mscheduler.shutdown();
    printf("merge threads finished.\n");
    gettimeofday(&stop_tv,0);
    printf("run time: %6.1f\n", (tv_to_double(stop_tv) - tv_to_double(start_tv)));


    
    Tcommit(xid);
    delete ltable;
    bLSM::deinit_stasis();
}
コード例 #25
0
ファイル: mergeScheduler.cpp プロジェクト: Bathtor/bLSM
void * mergeScheduler::diskMergeThread()
{
    int xid;

    assert(ltable_->get_tree_c2());


    int merge_count =0;
    mergeStats * stats = ltable_->merge_mgr->get_merge_stats(2);
    
    while(true)
    {

        // 2: wait for input
        rwlc_writelock(ltable_->header_mut);
        ltable_->merge_mgr->new_merge(2);
        int done = 0;
        // get a new input for merge
        while(!ltable_->get_tree_c1_mergeable())
        {
            pthread_cond_signal(&ltable_->c1_needed);

            if(!ltable_->is_still_running()){
                done = 1;
                break;
            }
            
            DEBUG("dmt:\twaiting for block ready cond\n");
            
            rwlc_cond_wait(&ltable_->c1_ready, ltable_->header_mut);

            DEBUG("dmt:\tblock ready\n");
        }        
        if(done==1)
        {
            rwlc_unlock(ltable_->header_mut);
            break;
        }

        stats->starting_merge();

        // 3: begin
        xid = Tbegin();

        // 4: do the merge.
        //create the iterators
        diskTreeComponent::iterator *itrA = ltable_->get_tree_c2()->open_iterator();
        diskTreeComponent::iterator *itrB = ltable_->get_tree_c1_mergeable()->open_iterator(ltable_->merge_mgr, 0.05, &ltable_->c1_flushing);

        //create a new tree
        diskTreeComponent * c2_prime = new diskTreeComponent(xid, ltable_->internal_region_size, ltable_->datapage_region_size, ltable_->datapage_size, stats, (uint64_t)(ltable_->max_c0_size * *ltable_->R() + stats->base_size)/ 1000);
//        diskTreeComponent * c2_prime = new diskTreeComponent(xid, ltable_->internal_region_size, ltable_->datapage_region_size, ltable_->datapage_size, stats);

        rwlc_unlock(ltable_->header_mut);

        //do the merge
        DEBUG("dmt:\tMerging:\n");

        merge_iterators<typeof(*itrA),typeof(*itrB)>(xid, c2_prime, itrA, itrB, ltable_, c2_prime, stats, true);

        delete itrA;
        delete itrB;

        //5: force write the new region to disk
        c2_prime->force(xid);

        // (skip 6, 7, 8, 8.5, 9))

        rwlc_writelock(ltable_->header_mut);
        //12
        ltable_->get_tree_c2()->dealloc(xid);
        delete ltable_->get_tree_c2();
        //11.5
        ltable_->get_tree_c1_mergeable()->dealloc(xid);
        //11
        delete ltable_->get_tree_c1_mergeable();
        ltable_->set_tree_c1_mergeable(0);

        //writes complete
        //now atomically replace the old c2 with new c2
        //pthread_mutex_lock(a->block_ready_mut);

        merge_count++;        
        //update the current optimal R value
        *(ltable_->R()) = std::max(MIN_R, sqrt( ((double)stats->output_size()) / ((double)ltable_->mean_c0_run_length) ) );
        
        DEBUG("\nR = %f\n", *(ltable_->R()));

        DEBUG("dmt:\tmerge_count %lld\t#written bytes: %lld\n optimal r %.2f", stats.stats_merge_count, stats.output_size(), *(a->r_i));
        // 10: C2 is never too big
        ltable_->set_tree_c2(c2_prime);
        stats->handed_off_tree();

        DEBUG("dmt:\tUpdated C2's position on disk to %lld\n",(long long)-1);
        // 13
        ltable_->update_persistent_header(xid);
        Tcommit(xid);

        rwlc_unlock(ltable_->header_mut);
//        stats->pretty_print(stdout);
        ltable_->merge_mgr->finished_merge(2);


    }
    return 0;
}
コード例 #26
0
ファイル: lsm_microbenchmarks.cpp プロジェクト: Bathtor/bLSM
int main (int argc, char * argv[]) {
	double MB = 1024 * 1024;
	uint64_t mb = 20000; // size of run, in megabytes.

	enum run_type mode = ALL;

	const uint64_t num_pages = mb * (MB / PAGE_SIZE);

	stasis_buffer_manager_size = (512 * MB) / PAGE_SIZE;

//	stasis_buffer_manager_hint_writes_are_sequential = 1;
//	stasis_dirty_page_table_flush_quantum = (8 * MB) / PAGE_SIZE; // XXX if set to high-> segfault
//	stasis_dirty_page_count_hard_limit = (16 * MB) / PAGE_SIZE;
//	stasis_dirty_page_count_soft_limit = (10 * MB) / PAGE_SIZE;
//	stasis_dirty_page_low_water_mark = (8 * MB) / PAGE_SIZE;

	// Hard disk preferred.
	/*	stasis_dirty_page_table_flush_quantum = (4 * MB) / PAGE_SIZE; // XXX if set to high-> segfault
	stasis_dirty_page_count_hard_limit = (12 * MB) / PAGE_SIZE;
	stasis_dirty_page_count_soft_limit = (8 * MB) / PAGE_SIZE;
	stasis_dirty_page_low_water_mark = (4 * MB) / PAGE_SIZE;*/

	// SSD preferred.
	stasis_dirty_page_table_flush_quantum = (4 * MB) / PAGE_SIZE; // XXX if set to high-> segfault
	stasis_dirty_page_count_hard_limit = (40 * MB) / PAGE_SIZE;
	stasis_dirty_page_count_soft_limit = (32 * MB) / PAGE_SIZE;
	stasis_dirty_page_low_water_mark   = (16 * MB) / PAGE_SIZE;

	stasis_dirty_page_table_flush_quantum = (4 * MB) / PAGE_SIZE; // XXX if set to high-> segfault
	stasis_dirty_page_count_hard_limit = (48 * MB) / PAGE_SIZE;
	stasis_dirty_page_count_soft_limit = (40 * MB) / PAGE_SIZE;
	stasis_dirty_page_low_water_mark   = (32 * MB) / PAGE_SIZE;

	printf("stasis_buffer_manager_size=%lld\n", (long long)stasis_buffer_manager_size * PAGE_SIZE);
	printf("Hard limit=%lld\n", (long long)((stasis_dirty_page_count_hard_limit*PAGE_SIZE)/MB));
	printf("Hard limit is %f pct.\n", 100.0 * ((double)stasis_dirty_page_count_hard_limit)/((double)stasis_buffer_manager_size));

	bLSM::init_stasis();

	regionAllocator * readableAlloc = NULL;
	if(!mode) {
		int xid = Tbegin();
		regionAllocator * alloc = new regionAllocator(xid, num_pages);
		printf("Starting first write of %lld mb\n", (long long)mb);
		struct timeval start, start_sync, stop; double elapsed;
		gettimeofday(&start, 0);
		pageid_t extent = alloc->alloc_extent(xid, num_pages);
		for(uint64_t i = 0; i < num_pages; i++) {
			Page * p = loadUninitializedPage(xid, i+extent);
			stasis_dirty_page_table_set_dirty((stasis_dirty_page_table_t*)stasis_runtime_dirty_page_table(), p);
			releasePage(p);
		}
		gettimeofday(&start_sync,0);
		alloc->force_regions(xid);
		readableAlloc = alloc;
		Tcommit(xid);
//		alloc = new RegionAllocator(xid, num_pages);
		gettimeofday(&stop, 0);
		elapsed = stasis_timeval_to_double(stasis_subtract_timeval(stop, start));
		printf("Write took %f seconds (%f mb/sec)\n", elapsed, ((double)mb)/elapsed);
		printf("Sync took %f seconds.\n", stasis_timeval_to_double(stasis_subtract_timeval(stop, start_sync)));

	}

	if(!mode) {
		int xid = Tbegin();
		regionAllocator * alloc = new regionAllocator(xid, num_pages);
		printf("Starting write with parallel read of %lld mb\n", (long long)mb);
		struct timeval start, start_sync, stop; double elapsed;
		gettimeofday(&start, 0);

		pageid_t region_length;
		pageid_t region_count;
		pageid_t * old_extents = readableAlloc->list_regions(xid, &region_length, &region_count);
		pageid_t extent = alloc->alloc_extent(xid, num_pages);
		assert(region_count == 1);
		for(uint64_t i = 0; i < num_pages/2; i++) {
			Page * p = loadUninitializedPage(xid, i+extent);
			stasis_dirty_page_table_set_dirty((stasis_dirty_page_table_t*)stasis_runtime_dirty_page_table(), p);
			releasePage(p);
			p = loadPage(xid, i+old_extents[0]);
			releasePage(p);
		}
		gettimeofday(&start_sync,0);
		alloc->force_regions(xid);
		delete alloc;
		Tcommit(xid);
//		alloc = new RegionAllocator(xid, num_pages);
		gettimeofday(&stop, 0);
		elapsed = stasis_timeval_to_double(stasis_subtract_timeval(stop, start));
		printf("Write took %f seconds (%f mb/sec)\n", elapsed, ((double)mb)/elapsed);
		printf("Sync took %f seconds.\n", stasis_timeval_to_double(stasis_subtract_timeval(stop, start_sync)));

	}

	if(!mode) {
		int xid = Tbegin();
		struct timeval start, start_sync, stop; double elapsed;
		printf("Starting write of giant datapage\n");
		gettimeofday(&start, 0);
		regionAllocator * alloc = new regionAllocator(xid, num_pages);
		dataPage * dp = new DataPage(xid, num_pages-1, alloc);
		byte * key = (byte*)calloc(100, 1);
		byte * val = (byte*)calloc(900, 1);
		dataTuple * tup = dataTuple::create(key, 100, val, 900);
		free(key);
		free(val);
		while(1) {
			if(!dp->append(tup)) {
				break;
			}
		}
		gettimeofday(&start_sync,0);
		alloc->force_regions(xid);

		gettimeofday(&stop, 0);
		Tcommit(xid);
		elapsed = stasis_timeval_to_double(stasis_subtract_timeval(stop, start));
		printf("Write took %f seconds (%f mb/sec)\n", elapsed, ((double)mb)/elapsed);
		printf("Sync took %f seconds.\n", stasis_timeval_to_double(stasis_subtract_timeval(stop, start_sync)));
	}
	if(!mode) {
		int xid = Tbegin();
		struct timeval start, start_sync, stop; double elapsed;
		printf("Starting write of many small datapages\n");
		gettimeofday(&start, 0);
		regionAllocator * alloc = new regionAllocator(xid, num_pages);
		byte * key = (byte*)calloc(100, 1);
		byte * val = (byte*)calloc(900, 1);
		dataTuple * tup = dataTuple::create(key, 100, val, 900);
		free(key);
		free(val);
		dataPage * dp = 0;
		uint64_t this_count = 0;
		uint64_t count  = 0;
		uint64_t dp_count = 0;
		while((count * 1000) < (mb * 1024*1024)) {
			if((!dp) || !dp->append(tup)) {
				dp = new DataPage(xid, 2, alloc);
				dp_count++;
			}
			count++;
			this_count++;
//			if(((this_count * 1000) > (1024 * 1024 * 16))) {
//				alloc->force_regions(xid);
//				this_count = 0;
//				gettimeofday(&stop, 0);
//				elapsed = stasis_timeval_to_double(stasis_subtract_timeval(stop, start));
//				printf("Write took %f seconds (%f mb/sec)\n", elapsed, ((double)(count*1000))/(1024*1024*elapsed));
//			}
		}
		gettimeofday(&start_sync,0);
		alloc->force_regions(xid);
		gettimeofday(&stop, 0);
		Tcommit(xid);
		elapsed = stasis_timeval_to_double(stasis_subtract_timeval(stop, start));
		printf("Write took %f seconds (%f mb/sec)\n", elapsed, ((double)(count*1000))/(elapsed*1024*1024));
		printf("Sync took %f seconds.\n", stasis_timeval_to_double(stasis_subtract_timeval(stop, start_sync)));
	}

	if(!mode) {
		int xid = Tbegin();
		struct timeval start, start_sync, stop; double elapsed;
		printf("Starting two parallel writes of many small datapages\n");
		gettimeofday(&start, 0);
		regionAllocator * alloc = new regionAllocator(xid, num_pages/2);
		regionAllocator * alloc2 = new regionAllocator(xid, num_pages/2);
		byte * key = (byte*)calloc(100, 1);
		byte * val = (byte*)calloc(900, 1);
		dataTuple * tup = dataTuple::create(key, 100, val, 900);
		free(key);
		free(val);
		dataPage * dp = 0;
		dataPage * dp2 = 0;
		uint64_t this_count = 0;
		uint64_t count  = 0;
		uint64_t dp_count = 0;
		while((count * 1000) < (mb * 1024*1024)) {
			if((!dp) || !dp->append(tup)) {
				dp = new DataPage(xid, 2, alloc);
				dp_count++;
			}
			if((!dp2) || !dp2->append(tup)) {
				dp2 = new DataPage(xid, 2, alloc2);
				//dp_count++;
			}
			count += 2;
			this_count++;
//			if(((this_count * 1000) > (1024 * 1024 * 16))) {
//				alloc->force_regions(xid);
//				this_count = 0;
//				gettimeofday(&stop, 0);
//				elapsed = stasis_timeval_to_double(stasis_subtract_timeval(stop, start));
//				printf("Write took %f seconds (%f mb/sec)\n", elapsed, ((double)(count*1000))/(1024*1024*elapsed));
//			}
		}
		gettimeofday(&start_sync,0);
		alloc->force_regions(xid);
		alloc2->force_regions(xid);
		gettimeofday(&stop, 0);
		Tcommit(xid);
		elapsed = stasis_timeval_to_double(stasis_subtract_timeval(stop, start));
		printf("Write took %f seconds (%f mb/sec)\n", elapsed, ((double)(count*1000))/(elapsed*1024*1024));
		printf("Sync took %f seconds.\n", stasis_timeval_to_double(stasis_subtract_timeval(stop, start_sync)));

	}

	regionAllocator * read_alloc = NULL;
	regionAllocator * read_alloc2 = NULL;
	regionAllocator * read_alloc3 = NULL;
	regionAllocator * read_alloc4 = NULL;

	if(!mode) {
		int xid = Tbegin();
		struct timeval start, start_sync, stop; double elapsed;
		printf("Starting four parallel writes of many small datapages\n");
		gettimeofday(&start, 0);
		regionAllocator * alloc = new regionAllocator(xid, num_pages/4);
		regionAllocator * alloc2 = new regionAllocator(xid, num_pages/4);
		regionAllocator * alloc3 = new regionAllocator(xid, num_pages/4);
		regionAllocator * alloc4 = new regionAllocator(xid, num_pages/4);
		byte * key = (byte*)calloc(100, 1);
		byte * val = (byte*)calloc(900, 1);
		dataTuple * tup = dataTuple::create(key, 100, val, 900);
		free(key);
		free(val);
		dataPage * dp = 0;
		dataPage * dp2 = 0;
		dataPage * dp3 = 0;
		dataPage * dp4 = 0;
		uint64_t this_count = 0;
		uint64_t count  = 0;
		uint64_t dp_count = 0;

		while((count * 1000) < (mb * 1024*1024)) {
			if((!dp) || !dp->append(tup)) {
				dp = new DataPage(xid, 2, alloc);
				dp_count++;
			}
			if((!dp2) || !dp2->append(tup)) {
				dp2 = new DataPage(xid, 2, alloc2);
				//dp_count++;
			}
			if((!dp3) || !dp3->append(tup)) {
				dp3 = new DataPage(xid, 2, alloc3);
				//dp_count++;
			}
			if((!dp4) || !dp4->append(tup)) {
				dp4 = new DataPage(xid, 2, alloc4);
				//dp_count++;
			}
			count += 4;
			this_count++;
//			if(((this_count * 1000) > (1024 * 1024 * 16))) {
//				alloc->force_regions(xid);
//				this_count = 0;
//				gettimeofday(&stop, 0);
//				elapsed = stasis_timeval_to_double(stasis_subtract_timeval(stop, start));
//				printf("Write took %f seconds (%f mb/sec)\n", elapsed, ((double)(count*1000))/(1024*1024*elapsed));
//			}
		}
		gettimeofday(&start_sync,0);
		alloc->force_regions(xid);
		alloc2->force_regions(xid);
		alloc3->force_regions(xid);
		alloc4->force_regions(xid);
		gettimeofday(&stop, 0);
		Tcommit(xid);
		elapsed = stasis_timeval_to_double(stasis_subtract_timeval(stop, start));
		printf("Write took %f seconds (%f mb/sec)\n", elapsed, ((double)(count*1000))/(elapsed*1024*1024));
		printf("Sync took %f seconds.\n", stasis_timeval_to_double(stasis_subtract_timeval(stop, start_sync)));
		read_alloc = alloc;
		read_alloc2 = alloc2;
		read_alloc3 = alloc3;
		read_alloc4 = alloc4;

	}

	if(!mode) {
		int xid = Tbegin();
		struct timeval start, start_sync, stop; double elapsed;
		printf("Starting four parallel writes of many small datapages\n");
		gettimeofday(&start, 0);
		regionAllocator * alloc = new regionAllocator(xid, num_pages/4);
		regionAllocator * alloc2 = new regionAllocator(xid, num_pages/4);
		regionAllocator * alloc3 = new regionAllocator(xid, num_pages/4);
		regionAllocator * alloc4 = new regionAllocator(xid, num_pages/4);
		byte * key = (byte*)calloc(100, 1);
		byte * val = (byte*)calloc(900, 1);
		dataTuple * tup = dataTuple::create(key, 100, val, 900);
		free(key);
		free(val);
		dataPage * dp = 0;
		dataPage * dp2 = 0;
		dataPage * dp3 = 0;
		dataPage * dp4 = 0;
		uint64_t this_count = 0;
		uint64_t count  = 0;
		uint64_t dp_count = 0;

		pageid_t n1, n2, n3, n4;
		pageid_t l1, l2, l3, l4;
		pageid_t * regions1, * regions2, * regions3, * regions4;
 
		regions1 = read_alloc->list_regions(xid, &l1, &n1);
		regions2 = read_alloc2->list_regions(xid, &l2, &n2);
		regions3 = read_alloc3->list_regions(xid, &l3, &n3);
		regions4 = read_alloc4->list_regions(xid, &l4, &n4);

		pageid_t i1 = regions1[0];
		pageid_t i2 = regions2[0];
		pageid_t i3 = regions3[0];
		pageid_t i4 = regions4[0];

		dataPage * rdp  = new DataPage(xid, 0, i1);
		dataPage * rdp2 = new DataPage(xid, 0, i2);
		dataPage * rdp3 = new DataPage(xid, 0, i3);
		dataPage * rdp4 = new DataPage(xid, 0, i4);

		dataPage::iterator it1 = rdp->begin();
		dataPage::iterator it2 = rdp2->begin();
		dataPage::iterator it3 = rdp3->begin();
		dataPage::iterator it4 = rdp4->begin();

		while((count * 1000) < (mb * 1024*1024)) {
			if((!dp) || !dp->append(tup)) {
				dp = new DataPage(xid, 2, alloc);
				dp_count++;
			}
			if((!dp2) || !dp2->append(tup)) {
				dp2 = new DataPage(xid, 2, alloc2);
				//dp_count++;
			}
			if((!dp3) || !dp3->append(tup)) {
				dp3 = new DataPage(xid, 2, alloc3);
				//dp_count++;
			}
			if((!dp4) || !dp4->append(tup)) {
				dp4 = new DataPage(xid, 2, alloc4);
				//dp_count++;
			}
			dataTuple * t;
			if((!rdp) || !(t = it1.getnext())) {
			  i1+= rdp->get_page_count();
			  if(rdp) delete rdp;
			  rdp = new DataPage(xid, 0, i1);
			  //			  i1++;
			  it1 = rdp->begin();
			  t = it1.getnext();
			}
			if(t) dataTuple::freetuple(t);
			if((!rdp2) || !(t = it2.getnext())) {
			  i2+= rdp2->get_page_count();
			  if(rdp2) delete rdp2;
			  rdp2 = new DataPage(xid, 0, i2);
			  //			  i2++;
			  it2 = rdp2->begin();
			  t = it2.getnext();
			}
			if(t) dataTuple::freetuple(t);
			if((!rdp3) || !(t = it3.getnext())) {
			  i3+= rdp3->get_page_count();
			  if(rdp3) delete rdp3;
			  rdp3 = new DataPage(xid, 0, i3);
			  //			  i3++;
			  it3 = rdp3->begin();
			  t = it3.getnext();
			}
			if(t) dataTuple::freetuple(t);
			if((!rdp4) || !(t = it4.getnext())) {
			  i4+= rdp4->get_page_count();
			  if(rdp4) delete rdp4;
			  rdp4 = new DataPage(xid, 0, i4);
			  //			  i4++;
			  it4 = rdp4->begin();
			  t = it4.getnext();
			}
			if(t) dataTuple::freetuple(t);

			count += 8;
			this_count++;
//			if(((this_count * 1000) > (1024 * 1024 * 16))) {
//				alloc->force_regions(xid);
//				this_count = 0;
//				gettimeofday(&stop, 0);
//				elapsed = stasis_timeval_to_double(stasis_subtract_timeval(stop, start));
//				printf("Write took %f seconds (%f mb/sec)\n", elapsed, ((double)(count*1000))/(1024*1024*elapsed));
//			}
		}
		gettimeofday(&start_sync,0);
		alloc->force_regions(xid);
		alloc2->force_regions(xid);
		alloc3->force_regions(xid);
		alloc4->force_regions(xid);
		gettimeofday(&stop, 0);
		Tcommit(xid);
		elapsed = stasis_timeval_to_double(stasis_subtract_timeval(stop, start));
		printf("Write took %f seconds (%f mb/sec)\n", elapsed, ((double)(count*1000))/(elapsed*1024*1024));
		printf("Sync took %f seconds.\n", stasis_timeval_to_double(stasis_subtract_timeval(stop, start_sync)));
		read_alloc = alloc;
		read_alloc2 = alloc2;
		read_alloc3 = alloc3;
		read_alloc4 = alloc4;

	}


	bLSM::deinit_stasis();
}
コード例 #27
0
JNIEXPORT void JNICALL Java_stasis_jni_Stasis_commit
  (JNIEnv *e, jclass c, jlong xid) {
  DEBUG("commiting %lld\n", (long long)xid);
  Tcommit((int)xid);
}
コード例 #28
0
} END_TEST

START_TEST(pagedListCheck) {
  Tinit();

  int xid = Tbegin();

  recordid list = TpagedListAlloc(xid);

  int a;
  recordid b;
  int i;

  printf("\n");
  for(i = 0; i < NUM_ENTRIES; i++) {

    if(!(i % (NUM_ENTRIES/10))) {
      printf("."); fflush(stdout);
    }

    a = i;
    b.page = i+1;
    b.slot = i+2;
    b.size = i+3;

    int ret;

    {
      byte * t;

      ret = TpagedListFind(xid, list, (byte*)&a, sizeof(int), &t);
      assert(-1 == ret);
    }
    ret = TpagedListInsert(xid, list, (byte*)&a, sizeof(int), (byte*)&b, sizeof(recordid));

    assert(!ret);

    recordid * bb;
    recordid ** bbb = &bb;
    ret = TpagedListFind(xid, list, (byte*)&a, sizeof(int), (byte**)bbb);

    assert(ret == sizeof(recordid));
    assert(!memcmp(bb, &b, sizeof(recordid)));
  }
  Tcommit(xid);
  printf("\n");
  xid = Tbegin();
  for(i = 0; i < NUM_ENTRIES; i++ ) {

    if(!(i % (NUM_ENTRIES/10))) {
      printf("."); fflush(stdout);
    }

    a = i;
    b.page = i+1;
    b.slot = i+2;
    b.size = i+3;

    recordid * bb;
    recordid ** bbb = &bb;
    int ret = TpagedListFind(xid, list, (byte*)&a, sizeof(int), (byte**)bbb);

    assert(ret == sizeof(recordid));
    assert(!memcmp(bb, &b, sizeof(recordid)));


    if(!(i % 10)) {

      ret = TpagedListRemove(xid, list, (byte*)&a, sizeof(int));

      assert(ret);

      free(bb);
      bb = 0;

      ret = TpagedListFind(xid, list, (byte*)&a, sizeof(int), (byte**)bbb);

      assert(-1==ret);
      assert(!bb);
    }
  }
  Tabort(xid);

  xid = Tbegin();
  printf("\n");
  for(i = 0; i < NUM_ENTRIES; i++) {

    if(!(i % (NUM_ENTRIES/10))) {
      printf("."); fflush(stdout);
    }

    a = i;
    b.page = i+1;
    b.slot = i+2;
    b.size = i+3;

    recordid * bb;
    recordid ** bbb = &bb;
    int ret = TpagedListFind(xid, list, (byte*)&a, sizeof(int), (byte**)bbb);

    assert(ret == sizeof(recordid));
    assert(!memcmp(bb, &b, sizeof(recordid)));
  }

  byte * seen = stasis_calloc(NUM_ENTRIES, byte);

  lladd_pagedList_iterator * it = TpagedListIterator(xid, list);

  int keySize;
  int valueSize;
  int * key = 0;
  int ** bkey = &key;
  recordid * value = 0;
  recordid ** bvalue = &value;

  while(TpagedListNext(xid, it, (byte**)bkey, &keySize, (byte**)bvalue, &valueSize)) {
    assert(!seen[*key]);
    seen[*key] = 1;

    assert(value->page == *key+1);
    assert(value->slot == *key+2);
    assert(value->size == *key+3);


    free(key);
    free(value);
    key = 0;
    value = 0;
  }

  for(i = 0; i < NUM_ENTRIES; i++) {
    assert(seen[i] == 1);
  }

  Tcommit(xid);
  Tdeinit();

} END_TEST
コード例 #29
0
ファイル: check_mergetuple.cpp プロジェクト: Bathtor/bLSM
void insertProbeIter(size_t NUM_ENTRIES)
{
    srand(1000);
    unlink("storefile.txt");
    unlink("logfile.txt");
    system("rm -rf stasis_log/");

    sync();

    bLSM::init_stasis();

    double delete_freq = .05;
    double update_freq = .15;

    //data generation
    typedef std::vector<std::string> key_v_t;
    const static size_t max_partition_size = 100000;
    int KEY_LEN = 100;
    std::vector<key_v_t*> *key_v_list = new std::vector<key_v_t*>;
    int list_size = NUM_ENTRIES / max_partition_size + 1;
    for(int i =0; i<list_size; i++)
    {
        key_v_t * key_arr = new key_v_t;
        if(NUM_ENTRIES < max_partition_size*(i+1))
            preprandstr(NUM_ENTRIES-max_partition_size*i, key_arr, KEY_LEN, true);
        else
            preprandstr(max_partition_size, key_arr, KEY_LEN, true);
    
        std::sort(key_arr->begin(), key_arr->end(), &mycmp);
        key_v_list->push_back(key_arr);
        printf("size partition %llu is %llu\n", (unsigned long long)i+1, (unsigned long long)key_arr->size());
    }

    key_v_t * key_arr = new key_v_t;
    
    std::vector<key_v_t::iterator*> iters;
    for(int i=0; i<list_size; i++)
    {
        iters.push_back(new key_v_t::iterator((*key_v_list)[i]->begin()));
    }

    size_t lc = 0;
    while(true)
    {
        int list_index = -1;
        for(int i=0; i<list_size; i++)
        {
            if(*iters[i] == (*key_v_list)[i]->end())
                continue;
            
            if(list_index == -1 || mycmp(**iters[i], **iters[list_index]))
                list_index = i;
        }

        if(list_index == -1)
            break;
        
        if(key_arr->size() == 0 || mycmp(key_arr->back(), **iters[list_index]))
            key_arr->push_back(**iters[list_index]);

        (*iters[list_index])++;        
        lc++;
        if(lc % max_partition_size == 0)
            printf("%llu/%llu completed.\n", (unsigned long long)lc, (unsigned long long)NUM_ENTRIES);
    }

    for(int i=0; i<list_size; i++)
    {
        (*key_v_list)[i]->clear();
        delete (*key_v_list)[i];
        delete iters[i];
    }
    key_v_list->clear();
    delete key_v_list;
    
    printf("key arr size: %llu\n", (unsigned long long)key_arr->size());

    if(key_arr->size() > NUM_ENTRIES)
        key_arr->erase(key_arr->begin()+NUM_ENTRIES, key_arr->end());
    
    NUM_ENTRIES=key_arr->size();
    
    int xid = Tbegin();

    bLSM *ltable = new bLSM(10 * 1024 * 1024, 1000, 1000, 40);
    mergeScheduler mscheduler(ltable);

    recordid table_root = ltable->allocTable(xid);

    Tcommit(xid);

    mscheduler.start();

    printf("Stage 1: Writing %llu keys\n", (unsigned long long)NUM_ENTRIES);
    
    struct timeval start_tv, stop_tv, ti_st, ti_end;
    double insert_time = 0;
    int delcount = 0, upcount = 0;
    int64_t datasize = 0;
    std::vector<pageid_t> dsp;
    std::vector<int> del_list;
    gettimeofday(&start_tv,0);
    for(size_t i = 0; i < NUM_ENTRIES; i++)
    {
        //prepare the data
        std::string ditem;
        getnextdata(ditem, 8192);

        //prepare the key
        dataTuple *newtuple = dataTuple::create((*key_arr)[i].c_str(), (*key_arr)[i].length()+1, ditem.c_str(), ditem.length()+1);
        
        datasize += newtuple->byte_length();

        gettimeofday(&ti_st,0);        
        ltable->insertTuple(newtuple);
        gettimeofday(&ti_end,0);
        insert_time += tv_to_double(ti_end) - tv_to_double(ti_st);

        dataTuple::freetuple(newtuple);

        double rval = ((rand() % 100)+.0)/100;        
        if( rval < delete_freq) //delete a key 
        {
            int del_index = i - (rand()%50); //delete one of the last inserted 50 elements
            if(del_index >= 0 && std::find(del_list.begin(), del_list.end(), del_index) == del_list.end())
            {
                delcount++;

                dataTuple *deltuple = dataTuple::create((*key_arr)[del_index].c_str(), (*key_arr)[del_index].length()+1);

                gettimeofday(&ti_st,0);        
                ltable->insertTuple(deltuple);
                gettimeofday(&ti_end,0);
                insert_time += tv_to_double(ti_end) - tv_to_double(ti_st);

                dataTuple::freetuple(deltuple);

                del_list.push_back(del_index);
                
            }            
        }
        else if(rval < delete_freq + update_freq) //update a record
        {
            int up_index = i - (rand()%50); //update one of the last inserted 50 elements
            if(up_index >= 0 && std::find(del_list.begin(), del_list.end(), up_index) == del_list.end()) 
            {//only update non-deleted elements
                getnextdata(ditem, 512);

                upcount++;
                dataTuple *uptuple = dataTuple::create((*key_arr)[up_index].c_str(), (*key_arr)[up_index].length()+1,
													   ditem.c_str(), ditem.length()+1);
                gettimeofday(&ti_st,0);        
                ltable->insertTuple(uptuple);
                gettimeofday(&ti_end,0);
                insert_time += tv_to_double(ti_end) - tv_to_double(ti_st);

                dataTuple::freetuple(uptuple);
            }            

        }
        
    }
    gettimeofday(&stop_tv,0);
    printf("insert time: %6.1f\n", insert_time);
    printf("insert time: %6.1f\n", (tv_to_double(stop_tv) - tv_to_double(start_tv)));
    printf("#deletions: %d\n#updates: %d\n", delcount, upcount);

    printf("\nTREE STRUCTURE\n");
    printf("datasize: %llu\n", (unsigned long long)datasize);

    xid = Tbegin();



    printf("Stage 2: Looking up %llu keys:\n", (unsigned long long)NUM_ENTRIES);

    int found_tuples=0;
    for(int i=NUM_ENTRIES-1; i>=0; i--)
    {        
        int ri = i;

        //get the key
        uint32_t keylen = (*key_arr)[ri].length()+1;        
        dataTuple::key_t rkey = (dataTuple::key_t) malloc(keylen);
        memcpy((byte*)rkey, (*key_arr)[ri].c_str(), keylen);

        //find the key with the given tuple
        dataTuple *dt = ltable->findTuple(xid, rkey, keylen);

        if(std::find(del_list.begin(), del_list.end(), i) == del_list.end())
        {
            assert(dt!=0);
            assert(!dt->isDelete());
            found_tuples++;
            assert(dt->rawkeylen() == (*key_arr)[ri].length()+1);
            dataTuple::freetuple(dt);
        }
        else
        {
            if(dt!=0)
            {
                assert(dt->rawkeylen() == (*key_arr)[ri].length()+1);
                assert(dt->isDelete());
                dataTuple::freetuple(dt);
            }
        }
        dt = 0;
        free(rkey);
    }
    printf("found %d\n", found_tuples);




    
    key_arr->clear();
    //data_arr->clear();
    delete key_arr;
    //delete data_arr;
    
    mscheduler.shutdown();
    printf("merge threads finished.\n");
    gettimeofday(&stop_tv,0);
    printf("run time: %6.1f\n", (tv_to_double(stop_tv) - tv_to_double(start_tv)));


    
    Tcommit(xid);
    delete ltable;
    bLSM::deinit_stasis();
}
コード例 #30
0
ファイル: mergeScheduler.cpp プロジェクト: Bathtor/bLSM
/**
 *  Merge algorithm: Outsider's view
 *<pre>
  1: while(1)
  2:    wait for c0_mergable
  3:    begin
  4:    merge c0_mergable and c1 into c1'  # Blocks; tree must be consistent at this point
  5:    force c1'                          # Blocks
  6:    if c1' is too big      # Blocks; tree must be consistent at this point.
  7:       c1_mergable = c1'
  8:       c1 = new_empty
8.5:       delete old c1_mergeable  # Happens in other thread (not here)
  9:    else
 10:       c1 = c1'
 11:    c0_mergeable = NULL
 11.5:    delete old c0_mergeable
 12:    delete old c1
 13:    commit
  </pre>
     Merge algorithm: actual order: 1 2 3 4 5 6 12 11.5 11 [7 8 (9) 10] 13
 */
void * mergeScheduler::memMergeThread() {

    int xid;

    assert(ltable_->get_tree_c1());
    
    int merge_count =0;
    mergeStats * stats = ltable_->merge_mgr->get_merge_stats(1);
    
    while(true) // 1
    {
        rwlc_writelock(ltable_->header_mut);
        ltable_->merge_mgr->new_merge(1);
        int done = 0;
        // 2: wait for c0_mergable
        // the merge iterator will wait until c0 is big enough for us to proceed.
        if(!ltable_->is_still_running()) {
          done = 1;
        }
        if(done==1)
        {
            pthread_cond_signal(&ltable_->c1_ready);  // no block is ready.  this allows the other thread to wake up, and see that we're shutting down.
            rwlc_unlock(ltable_->header_mut);
            break;
        }

        stats->starting_merge();

        lsn_t merge_start = ltable_->get_log_offset();
        printf("\nstarting memory merge. log offset is %lld\n", merge_start);
        // 3: Begin transaction
        xid = Tbegin();

        // 4: Merge

        //create the iterators
        diskTreeComponent::iterator *itrA = ltable_->get_tree_c1()->open_iterator();
        const int64_t min_bloom_target = ltable_->max_c0_size;

        //create a new tree
        diskTreeComponent * c1_prime = new diskTreeComponent(xid,  ltable_->internal_region_size, ltable_->datapage_region_size, ltable_->datapage_size, stats, (stats->target_size < min_bloom_target ? min_bloom_target : stats->target_size) / 100);

        ltable_->set_tree_c1_prime(c1_prime);

        rwlc_unlock(ltable_->header_mut);

        // needs to be past the rwlc_unlock...
        memTreeComponent::batchedRevalidatingIterator *itrB =
            new memTreeComponent::batchedRevalidatingIterator(ltable_->get_tree_c0(), ltable_->merge_mgr, ltable_->max_c0_size, &ltable_->c0_flushing, 100, &ltable_->rb_mut);

        //: do the merge
        DEBUG("mmt:\tMerging:\n");

        merge_iterators<typeof(*itrA),typeof(*itrB)>(xid, c1_prime, itrA, itrB, ltable_, c1_prime, stats, false);

        delete itrA;
        delete itrB;

        // 5: force c1'

        //force write the new tree to disk
        c1_prime->force(xid);

        rwlc_writelock(ltable_->header_mut);

        merge_count++;        
        DEBUG("mmt:\tmerge_count %lld #bytes written %lld\n", stats.stats_merge_count, stats.output_size());

        // Immediately clean out c0 mergeable so that writers may continue.

        // first, we need to move the c1' into c1.

        // 12: delete old c1
        ltable_->get_tree_c1()->dealloc(xid);
        delete ltable_->get_tree_c1();

        // 10: c1 = c1'
        ltable_->set_tree_c1(c1_prime);
        ltable_->set_tree_c1_prime(0);

        ltable_->set_c0_is_merging(false);
        double new_c1_size = stats->output_size();
        pthread_cond_signal(&ltable_->c0_needed);

        ltable_->update_persistent_header(xid, merge_start);
        Tcommit(xid);

        ltable_->truncate_log();

        //TODO: this is simplistic for now
        //6: if c1' is too big, signal the other merger

        // XXX move this to mergeManager, and make bytes_in_small be protected.
        if(stats->bytes_in_small) {
          // update c0 effective size.
          double frac = 1.0/(double)merge_count;
          ltable_->num_c0_mergers = merge_count;
          ltable_->mean_c0_run_length=
            (int64_t) (
             ((double)ltable_->mean_c0_run_length)*(1-frac) +
             ((double)stats->bytes_in_small*frac));
          //ltable_->merge_mgr->get_merge_stats(0)->target_size = ltable_->mean_c0_run_length;
        }

        printf("\nMerge done. R = %f MemSize = %lld Mean = %lld, This = %lld, Count = %d factor %3.3fcur%3.3favg\n", *ltable_->R(), (long long)ltable_->max_c0_size, (long long int)ltable_->mean_c0_run_length, stats->bytes_in_small, merge_count, ((double)stats->bytes_in_small) / (double)ltable_->max_c0_size, ((double)ltable_->mean_c0_run_length) / (double)ltable_->max_c0_size);

        assert(*ltable_->R() >= MIN_R);
        // XXX don't hardcode 1.05, which will break for R > ~20.
        bool signal_c2 = (1.05 * new_c1_size / ltable_->mean_c0_run_length > *ltable_->R());
        DEBUG("\nc1 size %f R %f\n", new_c1_size, *ltable_->R());
        if( signal_c2  )
        {
            DEBUG("mmt:\tsignaling C2 for merge\n");
            DEBUG("mmt:\tnew_c1_size %.2f\tMAX_C0_SIZE %lld\ta->max_size %lld\t targetr %.2f \n", new_c1_size,
                   ltable_->max_c0_size, a->max_size, target_R);

            // XXX need to report backpressure here!
            while(ltable_->get_tree_c1_mergeable()) {
                ltable_->c1_flushing = true;
                rwlc_cond_wait(&ltable_->c1_needed, ltable_->header_mut);
                ltable_->c1_flushing = false;
            }

            xid = Tbegin();

            // we just set c1 = c1'.  Want to move c1 -> c1 mergeable, clean out c1.

          // 7: and perhaps c1_mergeable
          ltable_->set_tree_c1_mergeable(ltable_->get_tree_c1()); // c1_prime == c1.
          stats->handed_off_tree();

          // 8: c1 = new empty.
          ltable_->set_tree_c1(new diskTreeComponent(xid, ltable_->internal_region_size, ltable_->datapage_region_size, ltable_->datapage_size, stats, 10));

          pthread_cond_signal(&ltable_->c1_ready);
          ltable_->update_persistent_header(xid);
          Tcommit(xid);

        }

//        DEBUG("mmt:\tUpdated C1's position on disk to %lld\n",ltable_->get_tree_c1()->get_root_rec().page);
        // 13

        rwlc_unlock(ltable_->header_mut);

        ltable_->merge_mgr->finished_merge(1);
//        stats->pretty_print(stdout);

        //TODO: get the freeing outside of the lock
    }

    return 0;

}