26
26
27
27
#include <lastseen.h>
28
28
#include <logging.h>
29
+ #include <string_lib.h>
29
30
30
31
typedef struct
31
32
{
@@ -34,6 +35,12 @@ typedef struct
34
35
double var ;
35
36
} QPoint0 ;
36
37
38
+ typedef struct
39
+ {
40
+ time_t lastseen ;
41
+ QPoint Q ; // Average time between connections (rolling weighted average)
42
+ } KeyHostSeen1 ;
43
+
37
44
#define QPOINT0_OFFSET 128
38
45
39
46
/*
@@ -48,142 +55,95 @@ typedef struct
48
55
49
56
static bool LastseenMigrationVersion0 (DBHandle * db )
50
57
{
51
- bool errors = false;
52
- DBCursor * cursor ;
58
+ /* For some reason DB migration for LMDB was disabled in 2014 (in commit
59
+ * 8611970bfa33be7b3cf0724eb684833e08582850). Unfortunately there is no
60
+ * mention as to why this was done. Maybe it was not working?
61
+ *
62
+ * However, we're re-enabling it now (10 years later). Since this
63
+ * migration function has not been active for the last 10 years, the
64
+ * safest thing is to remove the migration logic, and only update the
65
+ * version number.
66
+ *
67
+ * If you have not upgraded CFEngine in the last 10 years, this will be
68
+ * the least of your problems.
69
+ */
70
+ return WriteDB (db , "version" , "1" , sizeof ("1" ));
71
+ }
53
72
73
+ static bool LastseenMigrationVersion1 (DBHandle * db )
74
+ {
75
+ DBCursor * cursor ;
54
76
if (!NewDBCursor (db , & cursor ))
55
77
{
78
+ Log (LOG_LEVEL_ERR ,
79
+ "Unable to create database cursor during lastseen migration" );
56
80
return false;
57
81
}
58
82
59
83
char * key ;
60
84
void * value ;
61
- int ksize , vsize ;
85
+ int key_size , value_size ;
62
86
63
- while (NextDB (cursor , & key , & ksize , & value , & vsize ))
87
+ // Iterate through all key-value pairs
88
+ while (NextDB (cursor , & key , & key_size , & value , & value_size ))
64
89
{
65
- if (ksize == 0 )
90
+ if (key_size == 0 )
66
91
{
67
- Log (LOG_LEVEL_INFO , "LastseenMigrationVersion0: Database structure error -- zero-length key." );
92
+ Log (LOG_LEVEL_WARNING ,
93
+ "Found zero-length key during lastseen migration" );
68
94
continue ;
69
95
}
70
96
71
- /* Only look for old [+-]kH -> IP<QPoint> entries */
72
- if (( key [0 ] != '+' ) && ( key [ 0 ] != '-' ) )
97
+ // Only look for old KeyHostSeen entries
98
+ if (key [0 ] != 'q' )
73
99
{
74
- /* Warn about completely unexpected keys */
75
-
76
- if ((key [0 ] != 'q' ) && (key [0 ] != 'k' ) && (key [0 ] != 'a' ))
100
+ // Warn about completely unexpected keys
101
+ if ((key [0 ] != 'k' ) && (key [0 ] != 'a' ) && !StringEqualN (key , "version" , key_size ))
77
102
{
78
- Log (LOG_LEVEL_INFO , "LastseenMigrationVersion0: Malformed key found '%s'" , key );
103
+ Log (LOG_LEVEL_WARNING ,
104
+ "Found unexpected key '%s' during lastseen migration. "
105
+ "Only expecting 'version' or 'k', 'a' and 'q[i|o]' prefixed keys." ,
106
+ key );
79
107
}
80
-
81
- continue ;
82
- }
83
-
84
- bool incoming = key [0 ] == '-' ;
85
- const char * hostkey = key + 1 ;
86
-
87
- /* Only migrate sane data */
88
- if (vsize != QPOINT0_OFFSET + sizeof (QPoint0 ))
89
- {
90
- Log (LOG_LEVEL_INFO ,
91
- "LastseenMigrationVersion0: invalid value size for key '%s', entry is deleted" ,
92
- key );
93
- DBCursorDeleteEntry (cursor );
94
- continue ;
95
- }
96
-
97
- /* Properly align the data */
98
- const char * old_data_address = (const char * ) value ;
99
- QPoint0 old_data_q ;
100
- memcpy (& old_data_q , (const char * ) value + QPOINT0_OFFSET ,
101
- sizeof (QPoint0 ));
102
-
103
- char hostkey_key [CF_BUFSIZE ];
104
- snprintf (hostkey_key , CF_BUFSIZE , "k%s" , hostkey );
105
-
106
- if (!WriteDB (db , hostkey_key , old_data_address , strlen (old_data_address ) + 1 ))
107
- {
108
- Log (LOG_LEVEL_INFO , "Unable to write version 1 lastseen entry for '%s'" , key );
109
- errors = true;
110
- continue ;
111
- }
112
-
113
- char address_key [CF_BUFSIZE ];
114
- snprintf (address_key , CF_BUFSIZE , "a%s" , old_data_address );
115
-
116
- if (!WriteDB (db , address_key , hostkey , strlen (hostkey ) + 1 ))
117
- {
118
- Log (LOG_LEVEL_INFO , "Unable to write version 1 reverse lastseen entry for '%s'" , key );
119
- errors = true;
120
- continue ;
121
- }
122
-
123
- char quality_key [CF_BUFSIZE ];
124
- snprintf (quality_key , CF_BUFSIZE , "q%c%s" , incoming ? 'i' : 'o' , hostkey );
125
-
126
- /*
127
- Ignore malformed connection quality data
128
- */
129
-
130
- if ((!isfinite (old_data_q .q ))
131
- || (old_data_q .q < 0 )
132
- || (!isfinite (old_data_q .expect ))
133
- || (!isfinite (old_data_q .var )))
134
- {
135
- Log (LOG_LEVEL_INFO , "Ignoring malformed connection quality data for '%s'" , key );
136
- DBCursorDeleteEntry (cursor );
137
108
continue ;
138
109
}
139
110
140
- KeyHostSeen data = {
141
- .lastseen = (time_t )old_data_q .q ,
142
- .Q = {
143
- /*
144
- Previously .q wasn't stored in database, but was calculated
145
- every time as a difference between previous timestamp and a
146
- new timestamp. Given we don't have this information during
147
- the database upgrade, just assume that last reading is an
148
- average one.
149
- */
150
- .q = old_data_q .expect ,
151
- .dq = 0 ,
152
- .expect = old_data_q .expect ,
153
- .var = old_data_q .var ,
154
- }
111
+ KeyHostSeen1 * old_value = value ;
112
+ KeyHostSeen new_value = {
113
+ .acknowledged = true, // We don't know, assume yes
114
+ .lastseen = old_value -> lastseen ,
115
+ .Q = old_value -> Q ,
155
116
};
156
117
157
- if (!WriteDB (db , quality_key , & data , sizeof (data )))
158
- {
159
- Log (LOG_LEVEL_INFO , "Unable to write version 1 connection quality key for '%s'" , key );
160
- errors = true;
161
- continue ;
162
- }
163
-
164
- if (!DBCursorDeleteEntry (cursor ))
118
+ // This will overwrite the entry
119
+ if (!DBCursorWriteEntry (cursor , & new_value , sizeof (new_value )))
165
120
{
166
- Log (LOG_LEVEL_INFO , "Unable to delete version 0 lastseen entry for '%s'" , key );
167
- errors = true;
121
+ Log (LOG_LEVEL_ERR ,
122
+ "Unable to write version 2 of entry for key '%s' during lastseen migration." ,
123
+ key );
124
+ return false;
168
125
}
169
126
}
170
127
171
- if (DeleteDBCursor (cursor ) == false )
128
+ if (! DeleteDBCursor (cursor ))
172
129
{
173
- Log (LOG_LEVEL_ERR , "LastseenMigrationVersion0: Unable to close cursor" );
174
- errors = true ;
130
+ Log (LOG_LEVEL_ERR , "Unable to close cursor during lastseen migration " );
131
+ return false ;
175
132
}
176
133
177
- if ((! errors ) && (! WriteDB (db , "version" , "1 " , sizeof ("1" ) )))
134
+ if (! WriteDB (db , "version" , "2 " , sizeof ("2" )))
178
135
{
179
- errors = true;
136
+ Log (LOG_LEVEL_ERR , "Failed to update version number during lastseen migration" );
137
+ return false;
180
138
}
181
139
182
- return !errors ;
140
+ Log (LOG_LEVEL_INFO , "Migrated lastseen database from version 1 to 2" );
141
+ return true;
183
142
}
184
143
185
144
const DBMigrationFunction dbm_migration_plan_lastseen [] =
186
145
{
187
146
LastseenMigrationVersion0 ,
147
+ LastseenMigrationVersion1 ,
188
148
NULL
189
149
};
0 commit comments