// Export data from RRD file(s) func (e *Exporter) xport(start, end time.Time, step time.Duration) (XportResult, error) { cStart := C.time_t(start.Unix()) cEnd := C.time_t(end.Unix()) cStep := C.ulong(step.Seconds()) args := e.makeArgs(start, end, step) mutex.Lock() defer mutex.Unlock() var ( ret C.int cXSize C.int cColCnt C.ulong cLegends **C.char cData *C.double ) err := makeError(C.rrdXport( &ret, C.int(len(args)), &args[0], &cXSize, &cStart, &cEnd, &cStep, &cColCnt, &cLegends, &cData, )) if err != nil { return XportResult{start, end, step, nil, 0, nil}, err } start = time.Unix(int64(cStart), 0) end = time.Unix(int64(cEnd), 0) step = time.Duration(cStep) * time.Second colCnt := int(cColCnt) legends := make([]string, colCnt) for i := 0; i < colCnt; i++ { legend := C.arrayGetCString(cLegends, C.int(i)) legends[i] = C.GoString(legend) C.free(unsafe.Pointer(legend)) } C.free(unsafe.Pointer(cLegends)) rowCnt := (int(cEnd)-int(cStart))/int(cStep) + 1 valuesLen := colCnt * rowCnt values := make([]float64, valuesLen) sliceHeader := (*reflect.SliceHeader)((unsafe.Pointer(&values))) sliceHeader.Cap = valuesLen sliceHeader.Len = valuesLen sliceHeader.Data = uintptr(unsafe.Pointer(cData)) return XportResult{start, end, step, legends, rowCnt, values}, nil }
// Fetch retrieves data from RRD file. func Fetch(filename, cf string, start, end time.Time, step time.Duration) (FetchResult, error) { var null **C.char fn := C.CString(filename) defer freeCString(fn) cCf := C.CString(cf) defer freeCString(cCf) cStart := C.time_t(start.Unix()) cEnd := C.time_t(end.Unix()) cStep := C.ulong(step.Seconds()) var ( ret C.int cDsCnt C.ulong cDsNames **C.char cData *C.double ) err := makeError(C.rrdFetch(&ret, fn, cCf, &cStart, &cEnd, &cStep, &cDsCnt, &cDsNames, &cData)) if err != nil { return FetchResult{filename, cf, start, end, step, nil, 0, nil}, err } if cDsNames == null { return FetchResult{filename, cf, start, end, step, nil, 0, nil}, Error("malloc error") } start = time.Unix(int64(cStart), 0) end = time.Unix(int64(cEnd), 0) step = time.Duration(cStep) * time.Second dsCnt := int(cDsCnt) dsNames := make([]string, dsCnt) for i := 0; i < dsCnt; i++ { dsName := C.arrayGetCString(cDsNames, C.int(i)) dsNames[i] = C.GoString(dsName) C.free(unsafe.Pointer(dsName)) } C.free(unsafe.Pointer(cDsNames)) rowCnt := (int(cEnd)-int(cStart))/int(cStep) + 1 valuesLen := dsCnt * rowCnt var values []float64 sliceHeader := (*reflect.SliceHeader)((unsafe.Pointer(&values))) sliceHeader.Cap = valuesLen sliceHeader.Len = valuesLen sliceHeader.Data = uintptr(unsafe.Pointer(cData)) return FetchResult{filename, cf, start, end, step, dsNames, rowCnt, values}, nil }