prevent crashes on startup with memory mode = map; re-organize rrdset_done() for faster gaps; #2364
Costa Tsaousis (ktsaou) committed
Jun 21, 2017 at 03:06 UTC
a1c270337fc25ae2710fc4378d0055c9a7e6351e
1 file changed
+217
-163
src/rrdset.c
+217
-163
@@ -444,12 +444,16 @@ RRDSET *rrdset_create_custom(
444
memset(&st->rrdset_rwlock, 0, sizeof(netdata_rwlock_t));
445
446
st->name = NULL;
447
+ st->config_section = NULL;
448
st->type = NULL;
449
st->family = NULL;
449
- st->context = NULL;
450
st->title = NULL;
451
st->units = NULL;
452
+ st->context = NULL;
453
+ st->cache_dir = NULL;
454
st->dimensions = NULL;
455
+ st->rrdfamily = NULL;
456
+ st->rrdhost = NULL;
457
st->next = NULL;
458
st->variables = NULL;
459
st->alarms = NULL;
@@ -708,6 +712,209 @@ static inline void rrdset_done_push_exclusive(RRDSET *st) {
712
rrdset_unlock(st);
713
}
714
715
+
716
+static inline size_t rrdset_done_interpolate(
717
+ RRDSET *st
718
+ , usec_t update_every_ut
719
+ , usec_t last_stored_ut
720
+ , usec_t next_store_ut
721
+ , usec_t last_collect_ut
722
+ , usec_t now_collect_ut
723
+ , char store_this_entry
724
+ , uint32_t storage_flags
725
+) {
726
+ RRDDIM *rd;
727
+
728
+ size_t stored_entries = 0; // the number of entries we have stored in the db, during this call to rrdset_done()
729
+
730
+ usec_t first_ut = last_stored_ut, last_ut = 0;
731
+ ssize_t iterations = (ssize_t)((now_collect_ut - last_stored_ut) / (update_every_ut));
732
+ if((now_collect_ut % (update_every_ut)) == 0) iterations++;
733
+
734
+ for( ; next_store_ut <= now_collect_ut ; last_collect_ut = next_store_ut, next_store_ut += update_every_ut, iterations-- ) {
735
+ #ifdef NETDATA_INTERNAL_CHECKS
736
+ if(iterations < 0) { error("INTERNAL CHECK: %s: iterations calculation wrapped! first_ut = %llu, last_stored_ut = %llu, next_store_ut = %llu, now_collect_ut = %llu", st->name, first_ut, last_stored_ut, next_store_ut, now_collect_ut); }
737
+
738
+ if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) {
739
+ debug(D_RRD_STATS, "%s: last_stored_ut = %0.3Lf (last updated time)", st->name, (long double)last_stored_ut/1000000.0);
740
+ debug(D_RRD_STATS, "%s: next_store_ut = %0.3Lf (next interpolation point)", st->name, (long double)next_store_ut/1000000.0);
741
+ }
742
+ #endif
743
+
744
+ last_ut = next_store_ut;
745
+
746
+ rrddim_foreach_read(rd, st) {
747
+ calculated_number new_value;
748
+
749
+ switch(rd->algorithm) {
750
+ case RRD_ALGORITHM_INCREMENTAL:
751
+ new_value = (calculated_number)
752
+ ( rd->calculated_value
753
+ * (calculated_number)(next_store_ut - last_collect_ut)
754
+ / (calculated_number)(now_collect_ut - last_collect_ut)
755
+ );
756
+
757
+ #ifdef NETDATA_INTERNAL_CHECKS
758
+ if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)))
759
+ debug(D_RRD_STATS, "%s/%s: CALC2 INC "
760
+ CALCULATED_NUMBER_FORMAT " = "
761
+ CALCULATED_NUMBER_FORMAT
762
+ " * %llu"
763
+ " / %llu"
764
+ , st->id, rd->name
765
+ , new_value
766
+ , rd->calculated_value
767
+ , (next_store_ut - last_stored_ut)
768
+ , (now_collect_ut - last_stored_ut)
769
+ );
770
+ #endif
771
+
772
+ rd->calculated_value -= new_value;
773
+ new_value += rd->last_calculated_value;
774
+ rd->last_calculated_value = 0;
775
+ new_value /= (calculated_number)st->update_every;
776
+
777
+ if(unlikely(next_store_ut - last_stored_ut < update_every_ut)) {
778
+
779
+ #ifdef NETDATA_INTERNAL_CHECKS
780
+ if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)))
781
+ debug(D_RRD_STATS, "%s/%s: COLLECTION POINT IS SHORT " CALCULATED_NUMBER_FORMAT " - EXTRAPOLATING",
782
+ st->id, rd->name
783
+ , (calculated_number)(next_store_ut - last_stored_ut)
784
+ );
785
+ #endif
786
+
787
+ new_value = new_value * (calculated_number)(st->update_every * 1000000) / (calculated_number)(next_store_ut - last_stored_ut);
788
+ }
789
+ break;
790
+
791
+ case RRD_ALGORITHM_ABSOLUTE:
792
+ case RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL:
793
+ case RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL:
794
+ default:
795
+ if(iterations == 1) {
796
+ // this is the last iteration
797
+ // do not interpolate
798
+ // just show the calculated value
799
+
800
+ new_value = rd->calculated_value;
801
+ }
802
+ else {
803
+ // we have missed an update
804
+ // interpolate in the middle values
805
+
806
+ new_value = (calculated_number)
807
+ ( ( (rd->calculated_value - rd->last_calculated_value)
808
+ * (calculated_number)(next_store_ut - last_collect_ut)
809
+ / (calculated_number)(now_collect_ut - last_collect_ut)
810
+ )
811
+ + rd->last_calculated_value
812
+ );
813
+
814
+ #ifdef NETDATA_INTERNAL_CHECKS
815
+ if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)))
816
+ debug(D_RRD_STATS, "%s/%s: CALC2 DEF "
817
+ CALCULATED_NUMBER_FORMAT " = ((("
818
+ "(" CALCULATED_NUMBER_FORMAT " - " CALCULATED_NUMBER_FORMAT ")"
819
+ " * %llu"
820
+ " / %llu) + " CALCULATED_NUMBER_FORMAT
821
+ , st->id, rd->name
822
+ , new_value
823
+ , rd->calculated_value, rd->last_calculated_value
824
+ , (next_store_ut - first_ut)
825
+ , (now_collect_ut - first_ut), rd->last_calculated_value
826
+ );
827
+ #endif
828
+ }
829
+ break;
830
+ }
831
+
832
+ if(unlikely(!store_this_entry)) {
833
+ rd->values[st->current_entry] = pack_storage_number(0, SN_NOT_EXISTS);
834
+ continue;
835
+ }
836
+
837
+ if(likely(rd->updated && rd->collections_counter > 1 && iterations < st->gap_when_lost_iterations_above)) {
838
+ rd->values[st->current_entry] = pack_storage_number(new_value, storage_flags );
839
+ rd->last_stored_value = new_value;
840
+
841
+ #ifdef NETDATA_INTERNAL_CHECKS
842
+ if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)))
843
+ debug(D_RRD_STATS, "%s/%s: STORE[%ld] "
844
+ CALCULATED_NUMBER_FORMAT " = " CALCULATED_NUMBER_FORMAT
845
+ , st->id, rd->name
846
+ , st->current_entry
847
+ , unpack_storage_number(rd->values[st->current_entry]), new_value
848
+ );
849
+ #endif
850
+
851
+ }
852
+ else {
853
+
854
+ #ifdef NETDATA_INTERNAL_CHECKS
855
+ if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)))
856
+ debug(D_RRD_STATS, "%s/%s: STORE[%ld] = NON EXISTING "
857
+ , st->id, rd->name
858
+ , st->current_entry
859
+ );
860
+ #endif
861
+
862
+ rd->values[st->current_entry] = pack_storage_number(0, SN_NOT_EXISTS);
863
+ rd->last_stored_value = NAN;
864
+ }
865
+
866
+ stored_entries++;
867
+
868
+ if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) {
869
+ calculated_number t1 = new_value * (calculated_number)rd->multiplier / (calculated_number)rd->divisor;
870
+ calculated_number t2 = unpack_storage_number(rd->values[st->current_entry]);
871
+
872
+ #ifdef NETDATA_INTERNAL_CHECKS
873
+ calculated_number accuracy = accuracy_loss(t1, t2);
874
+ debug(D_RRD_STATS, "%s/%s: UNPACK[%ld] = " CALCULATED_NUMBER_FORMAT " FLAGS=0x%08x (original = " CALCULATED_NUMBER_FORMAT ", accuracy loss = " CALCULATED_NUMBER_FORMAT "%%%s)"
875
+ , st->id, rd->name
876
+ , st->current_entry
877
+ , t2
878
+ , get_storage_number_flags(rd->values[st->current_entry])
879
+ , t1
880
+ , accuracy
881
+ , (accuracy > ACCURACY_LOSS) ? " **TOO BIG** " : ""
882
+ );
883
+ #endif
884
+
885
+ rd->collected_volume += t1;
886
+ rd->stored_volume += t2;
887
+
888
+ #ifdef NETDATA_INTERNAL_CHECKS
889
+ accuracy = accuracy_loss(rd->collected_volume, rd->stored_volume);
890
+ debug(D_RRD_STATS, "%s/%s: VOLUME[%ld] = " CALCULATED_NUMBER_FORMAT ", calculated = " CALCULATED_NUMBER_FORMAT ", accuracy loss = " CALCULATED_NUMBER_FORMAT "%%%s"
891
+ , st->id, rd->name
892
+ , st->current_entry
893
+ , rd->stored_volume
894
+ , rd->collected_volume
895
+ , accuracy
896
+ , (accuracy > ACCURACY_LOSS) ? " **TOO BIG** " : ""
897
+ );
898
+ #endif
899
+
900
+ }
901
+ }
902
+ // reset the storage flags for the next point, if any;
903
+ storage_flags = SN_EXISTS;
904
+
905
+ st->counter++;
906
+ st->current_entry = ((st->current_entry + 1) >= st->entries) ? 0 : st->current_entry + 1;
907
+ last_stored_ut = next_store_ut;
908
+ }
909
+
910
+ if(likely(last_ut)) {
911
+ st->last_updated.tv_sec = (time_t) (last_ut / USEC_PER_SEC);
912
+ st->last_updated.tv_usec = 0;
913
+ }
914
+
915
+ return stored_entries;
916
+}
917
+
918
void rrdset_done(RRDSET *st) {
919
if(unlikely(netdata_exit)) return;
920
@@ -729,9 +936,6 @@ void rrdset_done(RRDSET *st) {
936
store_this_entry = 1, // boolean: 1 = store this entry, 0 = don't store this entry
937
first_entry = 0; // boolean: 1 = this is the first entry seen for this chart, 0 = all other entries
938
732
- unsigned int
733
- stored_entries = 0; // the number of entries we have stored in the db, during this call to rrdset_done()
734
-
939
usec_t
940
last_collect_ut, // the timestamp in microseconds, of the last collected value
941
now_collect_ut, // the timestamp in microseconds, of this collected value (this is NOW)
@@ -1044,165 +1248,15 @@ void rrdset_done(RRDSET *st) {
1248
#endif
1249
}
1250
1047
- usec_t first_ut = last_stored_ut;
1048
- long long iterations = (now_collect_ut - last_stored_ut) / (update_every_ut);
1049
- if((now_collect_ut % (update_every_ut)) == 0) iterations++;
1050
-
1051
- for( ; next_store_ut <= now_collect_ut ; last_collect_ut = next_store_ut, next_store_ut += update_every_ut, iterations-- ) {
1052
-#ifdef NETDATA_INTERNAL_CHECKS
1053
- if(iterations < 0) { error("INTERNAL CHECK: %s: iterations calculation wrapped! first_ut = %llu, last_stored_ut = %llu, next_store_ut = %llu, now_collect_ut = %llu", st->name, first_ut, last_stored_ut, next_store_ut, now_collect_ut); }
1054
-#endif
1055
-
1056
- if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) {
1057
- debug(D_RRD_STATS, "%s: last_stored_ut = %0.3Lf (last updated time)", st->name, (long double)last_stored_ut/1000000.0);
1058
- debug(D_RRD_STATS, "%s: next_store_ut = %0.3Lf (next interpolation point)", st->name, (long double)next_store_ut/1000000.0);
1059
- }
1060
-
1061
- st->last_updated.tv_sec = (time_t) (next_store_ut / USEC_PER_SEC);
1062
- st->last_updated.tv_usec = 0;
1063
-
1064
- rrddim_foreach_read(rd, st) {
1065
- calculated_number new_value;
1066
-
1067
- switch(rd->algorithm) {
1068
- case RRD_ALGORITHM_INCREMENTAL:
1069
- new_value = (calculated_number)
1070
- ( rd->calculated_value
1071
- * (calculated_number)(next_store_ut - last_collect_ut)
1072
- / (calculated_number)(now_collect_ut - last_collect_ut)
1073
- );
1074
-
1075
- if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)))
1076
- debug(D_RRD_STATS, "%s/%s: CALC2 INC "
1077
- CALCULATED_NUMBER_FORMAT " = "
1078
- CALCULATED_NUMBER_FORMAT
1079
- " * %llu"
1080
- " / %llu"
1081
- , st->id, rd->name
1082
- , new_value
1083
- , rd->calculated_value
1084
- , (next_store_ut - last_stored_ut)
1085
- , (now_collect_ut - last_stored_ut)
1086
- );
1087
-
1088
- rd->calculated_value -= new_value;
1089
- new_value += rd->last_calculated_value;
1090
- rd->last_calculated_value = 0;
1091
- new_value /= (calculated_number)st->update_every;
1092
-
1093
- if(unlikely(next_store_ut - last_stored_ut < update_every_ut)) {
1094
- if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)))
1095
- debug(D_RRD_STATS, "%s/%s: COLLECTION POINT IS SHORT " CALCULATED_NUMBER_FORMAT " - EXTRAPOLATING",
1096
- st->id, rd->name
1097
- , (calculated_number)(next_store_ut - last_stored_ut)
1098
- );
1099
- new_value = new_value * (calculated_number)(st->update_every * 1000000) / (calculated_number)(next_store_ut - last_stored_ut);
1100
- }
1101
- break;
1102
-
1103
- case RRD_ALGORITHM_ABSOLUTE:
1104
- case RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL:
1105
- case RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL:
1106
- default:
1107
- if(iterations == 1) {
1108
- // this is the last iteration
1109
- // do not interpolate
1110
- // just show the calculated value
1111
-
1112
- new_value = rd->calculated_value;
1113
- }
1114
- else {
1115
- // we have missed an update
1116
- // interpolate in the middle values
1117
-
1118
- new_value = (calculated_number)
1119
- ( ( (rd->calculated_value - rd->last_calculated_value)
1120
- * (calculated_number)(next_store_ut - last_collect_ut)
1121
- / (calculated_number)(now_collect_ut - last_collect_ut)
1122
- )
1123
- + rd->last_calculated_value
1124
- );
1125
-
1126
- if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)))
1127
- debug(D_RRD_STATS, "%s/%s: CALC2 DEF "
1128
- CALCULATED_NUMBER_FORMAT " = ((("
1129
- "(" CALCULATED_NUMBER_FORMAT " - " CALCULATED_NUMBER_FORMAT ")"
1130
- " * %llu"
1131
- " / %llu) + " CALCULATED_NUMBER_FORMAT
1132
- , st->id, rd->name
1133
- , new_value
1134
- , rd->calculated_value, rd->last_calculated_value
1135
- , (next_store_ut - first_ut)
1136
- , (now_collect_ut - first_ut), rd->last_calculated_value
1137
- );
1138
- }
1139
- break;
1140
- }
1141
-
1142
- if(unlikely(!store_this_entry)) {
1143
- rd->values[st->current_entry] = pack_storage_number(0, SN_NOT_EXISTS);
1144
- continue;
1145
- }
1146
-
1147
- if(likely(rd->updated && rd->collections_counter > 1 && iterations < st->gap_when_lost_iterations_above)) {
1148
- rd->values[st->current_entry] = pack_storage_number(new_value, storage_flags );
1149
- rd->last_stored_value = new_value;
1150
-
1151
- if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)))
1152
- debug(D_RRD_STATS, "%s/%s: STORE[%ld] "
1153
- CALCULATED_NUMBER_FORMAT " = " CALCULATED_NUMBER_FORMAT
1154
- , st->id, rd->name
1155
- , st->current_entry
1156
- , unpack_storage_number(rd->values[st->current_entry]), new_value
1157
- );
1158
- }
1159
- else {
1160
- if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)))
1161
- debug(D_RRD_STATS, "%s/%s: STORE[%ld] = NON EXISTING "
1162
- , st->id, rd->name
1163
- , st->current_entry
1164
- );
1165
- rd->values[st->current_entry] = pack_storage_number(0, SN_NOT_EXISTS);
1166
- rd->last_stored_value = NAN;
1167
- }
1168
-
1169
- stored_entries++;
1170
-
1171
- if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) {
1172
- calculated_number t1 = new_value * (calculated_number)rd->multiplier / (calculated_number)rd->divisor;
1173
- calculated_number t2 = unpack_storage_number(rd->values[st->current_entry]);
1174
- calculated_number accuracy = accuracy_loss(t1, t2);
1175
- debug(D_RRD_STATS, "%s/%s: UNPACK[%ld] = " CALCULATED_NUMBER_FORMAT " FLAGS=0x%08x (original = " CALCULATED_NUMBER_FORMAT ", accuracy loss = " CALCULATED_NUMBER_FORMAT "%%%s)"
1176
- , st->id, rd->name
1177
- , st->current_entry
1178
- , t2
1179
- , get_storage_number_flags(rd->values[st->current_entry])
1180
- , t1
1181
- , accuracy
1182
- , (accuracy > ACCURACY_LOSS) ? " **TOO BIG** " : ""
1183
- );
1184
-
1185
- rd->collected_volume += t1;
1186
- rd->stored_volume += t2;
1187
- accuracy = accuracy_loss(rd->collected_volume, rd->stored_volume);
1188
- debug(D_RRD_STATS, "%s/%s: VOLUME[%ld] = " CALCULATED_NUMBER_FORMAT ", calculated = " CALCULATED_NUMBER_FORMAT ", accuracy loss = " CALCULATED_NUMBER_FORMAT "%%%s"
1189
- , st->id, rd->name
1190
- , st->current_entry
1191
- , rd->stored_volume
1192
- , rd->collected_volume
1193
- , accuracy
1194
- , (accuracy > ACCURACY_LOSS) ? " **TOO BIG** " : ""
1195
- );
1196
-
1197
- }
1198
- }
1199
- // reset the storage flags for the next point, if any;
1200
- storage_flags = SN_EXISTS;
1201
-
1202
- st->counter++;
1203
- st->current_entry = ((st->current_entry + 1) >= st->entries) ? 0 : st->current_entry + 1;
1204
- last_stored_ut = next_store_ut;
1205
- }
1251
+ rrdset_done_interpolate(st
1252
+ , update_every_ut
1253
+ , last_stored_ut
1254
+ , next_store_ut
1255
+ , last_collect_ut
1256
+ , now_collect_ut
1257
+ , store_this_entry
1258
+ , storage_flags
1259
+ );
1260
1261
st->last_collected_total = st->collected_total;
1262