2010-05-19 23:42:06 +00:00
|
|
|
/*
|
|
|
|
* mergeManager.h
|
|
|
|
*
|
|
|
|
* Created on: May 19, 2010
|
|
|
|
* Author: sears
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef MERGEMANAGER_H_
|
|
|
|
#define MERGEMANAGER_H_
|
|
|
|
|
|
|
|
#include <stasis/common.h>
|
|
|
|
#undef try
|
|
|
|
#undef end
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <stdio.h>
|
2010-05-21 23:43:17 +00:00
|
|
|
#include <datatuple.h>
|
|
|
|
|
|
|
|
template<class TUPLE>
|
|
|
|
class logtable;
|
2010-05-19 23:42:06 +00:00
|
|
|
class mergeStats;
|
|
|
|
|
|
|
|
class mergeManager {
|
2010-05-26 00:58:17 +00:00
|
|
|
public:
|
2010-06-21 22:59:05 +00:00
|
|
|
static const int UPDATE_PROGRESS_DELTA = 10 * 1024 * 1024;
|
2010-07-14 21:46:27 +00:00
|
|
|
const double UPDATE_PROGRESS_PERIOD; // in seconds, defined in constructor.
|
2010-06-21 22:59:05 +00:00
|
|
|
static const int FORCE_INTERVAL = 25 * 1024 * 1024;
|
2010-06-02 21:47:58 +00:00
|
|
|
static double tv_to_double(struct timeval * tv) {
|
2010-05-19 23:42:06 +00:00
|
|
|
return (double)tv->tv_sec + ((double)tv->tv_usec)/1000000.0;
|
|
|
|
}
|
2010-06-02 21:47:58 +00:00
|
|
|
static double ts_to_double(struct timespec * ts) {
|
2010-05-19 23:42:06 +00:00
|
|
|
return (double)ts->tv_sec + ((double)ts->tv_nsec)/1000000000.0;
|
|
|
|
}
|
2010-06-02 21:47:58 +00:00
|
|
|
static void double_to_ts(struct timespec *ts, double time) {
|
2010-05-19 23:42:06 +00:00
|
|
|
ts->tv_sec = (time_t)(time);
|
|
|
|
ts->tv_nsec = (long)((time - (double)ts->tv_sec) * 1000000000.0);
|
|
|
|
}
|
|
|
|
uint64_t long_tv(struct timeval& tv) {
|
|
|
|
return (1000000ULL * (uint64_t)tv.tv_sec) + ((uint64_t)tv.tv_usec);
|
|
|
|
}
|
2010-05-21 23:43:17 +00:00
|
|
|
mergeManager(logtable<datatuple> *ltable);
|
2010-12-14 00:06:32 +00:00
|
|
|
mergeManager(logtable<datatuple> *ltable, int xid, recordid rid);
|
|
|
|
void marshal(int xid, recordid rid);
|
|
|
|
recordid talloc(int xid);
|
2010-05-19 23:42:06 +00:00
|
|
|
~mergeManager();
|
|
|
|
|
2010-12-17 18:48:26 +00:00
|
|
|
void finished_merge(int merge_level);
|
2010-06-02 21:47:58 +00:00
|
|
|
void new_merge(int mergelevel);
|
2010-05-19 23:42:06 +00:00
|
|
|
void set_c0_size(int64_t size);
|
2010-06-05 00:41:52 +00:00
|
|
|
void update_progress(mergeStats *s, int delta);
|
2010-12-14 01:49:23 +00:00
|
|
|
double c1_c2_progress_delta();
|
|
|
|
|
2010-08-24 00:40:48 +00:00
|
|
|
void tick(mergeStats * s);
|
2010-05-26 00:58:17 +00:00
|
|
|
mergeStats* get_merge_stats(int mergeLevel);
|
2010-06-02 21:47:58 +00:00
|
|
|
void read_tuple_from_small_component(int merge_level, datatuple * tup);
|
2010-08-30 22:22:25 +00:00
|
|
|
void read_tuple_from_large_component(int merge_level, datatuple * tup) {
|
|
|
|
if(tup)
|
|
|
|
read_tuple_from_large_component(merge_level, 1, tup->byte_length());
|
|
|
|
}
|
|
|
|
void read_tuple_from_large_component(int merge_level, int tuple_count, pageid_t byte_len);
|
|
|
|
|
2010-06-02 21:47:58 +00:00
|
|
|
void wrote_tuple(int merge_level, datatuple * tup);
|
|
|
|
void pretty_print(FILE * out);
|
2010-08-23 23:28:29 +00:00
|
|
|
void *pretty_print_thread();
|
2010-05-19 23:42:06 +00:00
|
|
|
|
|
|
|
private:
|
2010-12-17 18:48:26 +00:00
|
|
|
/**
|
|
|
|
* How far apart are the c0-c1 and c1-c2 mergers?
|
|
|
|
*
|
|
|
|
* This is c1->out_progress - c2->in_progress. We want the downstream merger
|
|
|
|
* to be slightly ahead of the upstream one so that we can mask latency blips
|
|
|
|
* due to tearing down the downstream merger and starting the new one.
|
|
|
|
* Therefore, this should always be slightly negative.
|
|
|
|
*
|
|
|
|
* TODO remove c1_c2_delta, which is derived, but difficult (from a synchronization perspective) to compute?
|
|
|
|
*/
|
2010-12-14 01:49:23 +00:00
|
|
|
double c1_c2_delta;
|
2010-12-17 18:48:26 +00:00
|
|
|
/** Helper method for the constructors */
|
2010-12-14 00:06:32 +00:00
|
|
|
void init_helper(void);
|
2010-12-17 18:48:26 +00:00
|
|
|
/**
|
|
|
|
* Serialization format for Stasis merge statistics header.
|
|
|
|
*
|
|
|
|
* The small amount of state maintained by mergeManager consists of derived
|
|
|
|
* and runtime-only fields. This struct reflects that, and only contains
|
|
|
|
* pointers to marshaled versions of the per-tree component statistics.
|
|
|
|
*/
|
2010-12-14 00:06:32 +00:00
|
|
|
struct marshalled_header {
|
2010-12-17 18:48:26 +00:00
|
|
|
recordid c0; // Probably redundant, but included for symmetry.
|
2010-12-14 00:06:32 +00:00
|
|
|
recordid c1;
|
|
|
|
recordid c2;
|
|
|
|
};
|
2010-12-17 18:48:26 +00:00
|
|
|
/**
|
|
|
|
* A pointer to the logtable that we manage statistics for. Most usages of
|
|
|
|
* this are layering violations; the main exception is in pretty_print.
|
|
|
|
*
|
|
|
|
* TODO: remove mergeManager->ltable?
|
|
|
|
*/
|
2010-05-21 23:43:17 +00:00
|
|
|
logtable<datatuple>* ltable;
|
2010-12-17 18:48:26 +00:00
|
|
|
mergeStats * c0; /// Per-tree component statistics for c0 and c0_mergeable (the latter should always be null...)
|
|
|
|
mergeStats * c1; /// Per-tree component statistics for c1 and c1_mergeable.
|
|
|
|
mergeStats * c2; /// Per-tree component statistics for c2.
|
2010-12-14 01:49:23 +00:00
|
|
|
|
|
|
|
// The following fields are used to shut down the pretty print thread.
|
2010-08-23 23:28:29 +00:00
|
|
|
bool still_running;
|
|
|
|
pthread_cond_t pp_cond;
|
|
|
|
pthread_t pp_thread;
|
2010-05-19 23:42:06 +00:00
|
|
|
};
|
|
|
|
#endif /* MERGEMANAGER_H_ */
|