-
Notifications
You must be signed in to change notification settings - Fork 54
/
sequential_pattern_detector.cpp
132 lines (119 loc) · 4.21 KB
/
sequential_pattern_detector.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
* ssd_sequential_writes_detector.cpp
*
* Created on: Jul 23, 2012
* Author: niv
*/
#include "ssd.h"
using namespace ssd;
using namespace std;
#define LIFE_TIME 400 // the number of sequential writes before we recognize the pattern as sequential
Sequential_Pattern_Detector::Sequential_Pattern_Detector(uint threshold)
: sequential_writes_key_lookup(),
registration_counter(0),
listener(NULL),
sequential_writes_identification_and_data(),
threshold(threshold),
io_num(0) {}
Sequential_Pattern_Detector::~Sequential_Pattern_Detector() {
map<logical_address, sequential_writes_tracking*>::iterator i = sequential_writes_identification_and_data.begin();
for (; i != sequential_writes_identification_and_data.end(); i++) {
sequential_writes_tracking* s = (*i).second;
if (s != NULL) {
delete s;
}
}
sequential_writes_identification_and_data.clear();
}
sequential_writes_tracking const& Sequential_Pattern_Detector::register_event(logical_address lb, double time) {
//printf("lb=%ld \tt=%f\tA=%d\tB=%d\n", lb, time, sequential_writes_identification_and_data.count(lb), sequential_writes_key_lookup.count(lb));
sequential_writes_tracking * swt;
if (sequential_writes_identification_and_data.count(lb) == 1) {
swt = restart_pattern(lb, time);
}
else if (sequential_writes_key_lookup.count(lb) == 1) {
swt =process_next_write(lb, time);
}
else {
swt = init_pattern(lb, time);
}
if (++registration_counter % 50 == 0) {
remove_old_sequential_writes_metadata(time);
}
io_num++;
return *swt;
}
sequential_writes_tracking* Sequential_Pattern_Detector::init_pattern(int key, double time) {
if (PRINT_LEVEL > 1) {
printf("init_pattern: %d \n", key);
}
sequential_writes_key_lookup[key + 1] = key;
sequential_writes_tracking* swt = new sequential_writes_tracking(time, key);
swt->last_io_num = io_num;
sequential_writes_identification_and_data[key] = swt;
return swt;
}
sequential_writes_tracking* Sequential_Pattern_Detector::process_next_write(int lb, double time) {
int key = sequential_writes_key_lookup[lb];
sequential_writes_tracking* swm = sequential_writes_identification_and_data[key];
swm->counter++;
swm->last_arrival_timestamp = time;
swm->last_io_num = io_num;
sequential_writes_key_lookup.erase(lb);
sequential_writes_key_lookup[lb + 1] = key;
return swm;
}
sequential_writes_tracking * Sequential_Pattern_Detector::restart_pattern(int key, double time) {
assert(sequential_writes_identification_and_data.count(key) == 1);
sequential_writes_tracking* swm = sequential_writes_identification_and_data[key];
if (swm->counter < threshold) {
return swm;
}
assert(swm->counter != 0);
swm->num_times_pattern_has_repeated++;
sequential_writes_key_lookup.erase(key + swm->counter);
sequential_writes_key_lookup[key + 1] = key;
swm->counter = 1;
swm->last_arrival_timestamp = time;
swm->last_io_num = io_num;
if (PRINT_LEVEL > 0) {
printf("SEQUENTIAL PATTERN RESTARTED! key: %d\n", key);
}
return swm;
}
void Sequential_Pattern_Detector::set_listener(Sequential_Pattern_Detector_Listener * new_listener) {
listener = new_listener;
}
// TODO: invoke this method from somewhere
void Sequential_Pattern_Detector::remove_old_sequential_writes_metadata(double time) {
map<logical_address, sequential_writes_tracking*>::iterator iter = sequential_writes_identification_and_data.begin();
while(iter != sequential_writes_identification_and_data.end())
{
logical_address key = (*iter).first;
if ((*iter).second->last_io_num + 200 < io_num) {
if (PRINT_LEVEL > 1) {
printf("deleting seq write with key %d:\n", key);
}
uint next_expected_lba = (*iter).second->counter + key;
sequential_writes_key_lookup.erase(next_expected_lba);
delete (*iter).second;
sequential_writes_identification_and_data.erase(iter++);
//sequential_writes_identification_and_data.erase(iter);
if (listener != NULL) {
listener->sequential_event_metadata_removed(key, time);
}
assert(sequential_writes_identification_and_data.count(key) == 0);
//++iter;
} else {
++iter;
}
}
}
sequential_writes_tracking::sequential_writes_tracking(double time, long key)
: counter(1),
num_times_pattern_has_repeated(0),
key(key),
last_arrival_timestamp(time),
init_timestamp(time),
last_io_num(0)
{}