@cryptotaxi247 / netdata-1 / commits / a1c270337

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