// Code generated by cmd/cgo; DO NOT EDIT.

//line /build/output/build/docker-engine-29.7.2/daemon/logger/journald/internal/sdjournal/sdjournal.go:1:1
//go:build linux && cgo && !static_build && journald

package sdjournal

// #cgo pkg-config: libsystemd
// #include <stdlib.h>
// #include <systemd/sd-journal.h>
//
// static int add_match(sd_journal *j, _GoString_ s) {
// 	return sd_journal_add_match(j, _GoStringPtr(s), _GoStringLen(s));
// }
import _ "unsafe"

import (
	"fmt"
	"runtime"
	"strings"
	"syscall"
	"time"
	"unsafe"
)

// Status is an sd-journal status code.
type Status int

// Status values for Process() and Wait().
const (
	StatusNOP        = Status(( /*line :28:28*/_Ciconst_SD_JOURNAL_NOP /*line :28:43*/))        // SD_JOURNAL_NOP
	StatusAPPEND     = Status(( /*line :29:28*/_Ciconst_SD_JOURNAL_APPEND /*line :29:46*/))     // SD_JOURNAL_APPEND
	StatusINVALIDATE = Status(( /*line :30:28*/_Ciconst_SD_JOURNAL_INVALIDATE /*line :30:50*/)) // SD_JOURNAL_INVALIDATE
)

const (
	// ErrInvalidReadPointer is the error returned when the read pointer is
	// in an invalid position.
	ErrInvalidReadPointer = syscall.EADDRNOTAVAIL
)

// Journal is a handle to an open journald journal.
type Journal struct {
	j      * /*line :41:10*/_Ctype_sd_journal /*line :41:22*/
	noCopy noCopy //nolint:unused // Exists only to mark values uncopyable for `go vet`.
}

// Open opens the log journal for reading.
//
// The returned Journal value may only be used from the same operating system
// thread which Open was called from. Using it from only a single goroutine is
// not sufficient; runtime.LockOSThread must also be used.
func Open(flags int) (*Journal, error) {
	j := &Journal{}
	if rc := func() _Ctype_int{ _cgoBase0 := /*line :52:29*/&j.j; _cgo0 := _cgoBase0; var _cgo1 _Ctype_int = _Ctype_int /*line :52:40*/(flags); _cgoCheckPointer(_cgoBase0, 0 == 0); return /*line :52:48*/_Cfunc_sd_journal_open(_cgo0, _cgo1); }(); rc != 0 {
		return nil, fmt.Errorf("journald: error opening journal: %w", syscall.Errno(-rc))
	}
	runtime.SetFinalizer(j, (*Journal).Close)
	return j, nil
}

// OpenDir opens the journal files at the specified absolute directory path for
// reading.
//
// The returned Journal value may only be used from the same operating system
// thread which Open was called from. Using it from only a single goroutine is
// not sufficient; runtime.LockOSThread must also be used.
func OpenDir(path string, flags int) (*Journal, error) {
	j := &Journal{}
	cpath := ( /*line :67:11*/_Cfunc_CString /*line :67:19*/)(path)
	defer func() func() { _cgo0 := /*line :68:15*/unsafe.Pointer(cpath); return func() { _cgoCheckPointer(_cgo0, nil); /*line :68:37*/_Cfunc_free(_cgo0); }}()()
	if rc := func() _Ctype_int{ _cgoBase0 := /*line :69:39*/&j.j; _cgo0 := _cgoBase0; var _cgo1 *_Ctype_char = /*line :69:45*/cpath; var _cgo2 _Ctype_int = _Ctype_int /*line :69:57*/(flags); _cgoCheckPointer(_cgoBase0, 0 == 0); return /*line :69:65*/_Cfunc_sd_journal_open_directory(_cgo0, _cgo1, _cgo2); }(); rc != 0 {
		return nil, fmt.Errorf("journald: error opening journal: %w", syscall.Errno(-rc))
	}
	runtime.SetFinalizer(j, (*Journal).Close)
	return j, nil
}

// Close closes the journal. The return value is always nil.
func (j *Journal) Close() error {
	if j.j != nil {
		func() { _cgo0 := /*line :79:22*/j.j; _cgoCheckPointer(_cgo0, nil); /*line :79:26*/_Cfunc_sd_journal_close(_cgo0); }()
		runtime.SetFinalizer(j, nil)
		j.j = nil
	}
	return nil
}

// Process processes journal events.
//
// https://www.freedesktop.org/software/systemd/man/sd_journal_process.html
func (j *Journal) Process() (Status, error) {
	s := func() _Ctype_int{ _cgo0 := /*line :90:28*/j.j; _cgoCheckPointer(_cgo0, nil); return /*line :90:32*/_Cfunc_sd_journal_process(_cgo0); }()
	if s < 0 {
		return 0, fmt.Errorf("journald: error processing events: %w", syscall.Errno(-s))
	}
	return Status(s), nil
}

// InitializeInotify sets up change notifications for the journal.
func (j *Journal) InitializeInotify() error {
	if rc := func() _Ctype_int{ _cgo0 := /*line :99:31*/j.j; _cgoCheckPointer(_cgo0, nil); return /*line :99:35*/_Cfunc_sd_journal_get_fd(_cgo0); }(); rc < 0 {
		return fmt.Errorf("journald: error initializing inotify watches: %w", syscall.Errno(-rc))
	}
	return nil
}

// AddMatch adds a match by which to filter the entries of the journal file.
//
// https://www.freedesktop.org/software/systemd/man/sd_journal_add_match.html
func (j *Journal) AddMatch(field, value string) error {
	m := field + "=" + value
	if rc := func() _Ctype_int{ _cgo0 := /*line :110:23*/j.j; var _cgo1 string = /*line :110:28*/m; _cgoCheckPointer(_cgo0, nil); return /*line :110:30*/_Cfunc_add_match(_cgo0, _cgo1); }(); rc != 0 {
		return fmt.Errorf("journald: error adding match %q: %w", m, syscall.Errno(-rc))
	}
	return nil
}

// Next advances the read pointer to the next entry.
func (j *Journal) Next() (bool, error) {
	rc := func() _Ctype_int{ _cgo0 := /*line :118:26*/j.j; _cgoCheckPointer(_cgo0, nil); return /*line :118:30*/_Cfunc_sd_journal_next(_cgo0); }()
	if rc < 0 {
		return false, fmt.Errorf("journald: error advancing read pointer: %w", syscall.Errno(-rc))
	}
	return rc > 0, nil
}

// Previous sets back the read pointer to the previous entry.
func (j *Journal) Previous() (bool, error) {
	rc := func() _Ctype_int{ _cgo0 := /*line :127:30*/j.j; _cgoCheckPointer(_cgo0, nil); return /*line :127:34*/_Cfunc_sd_journal_previous(_cgo0); }()
	if rc < 0 {
		return false, fmt.Errorf("journald: error setting back read pointer: %w", syscall.Errno(-rc))
	}
	return rc > 0, nil
}

// PreviousSkip sets back the read pointer by skip entries, returning the number
// of entries set back. skip must be less than or equal to 2147483647
// (2**31 - 1).
//
// skip == 0 is a special case: PreviousSkip(0) resolves the read pointer to a
// discrete position without setting it back to a different entry. The trouble
// is, it always returns zero on recent libsystemd versions. There is no way to
// tell from the return values whether or not it successfully resolved the read
// pointer to a discrete entry.
// https://github.com/systemd/systemd/pull/5930#issuecomment-300878104
func (j *Journal) PreviousSkip(skip uint) (int, error) {
	rc := func() _Ctype_int{ _cgo0 := /*line :145:35*/j.j; var _cgo1 _Ctype_uint64_t = _Ctype_uint64_t /*line :145:50*/(skip); _cgoCheckPointer(_cgo0, nil); return /*line :145:57*/_Cfunc_sd_journal_previous_skip(_cgo0, _cgo1); }()
	if rc < 0 {
		return 0, fmt.Errorf("journald: error setting back read pointer: %w", syscall.Errno(-rc))
	}
	return int(rc), nil
}

// SeekHead sets the read pointer to the position before the oldest available entry.
//
// BUG: SeekHead() followed by Previous() has unexpected behavior.
// https://github.com/systemd/systemd/issues/17662
func (j *Journal) SeekHead() error {
	if rc := func() _Ctype_int{ _cgo0 := /*line :157:34*/j.j; _cgoCheckPointer(_cgo0, nil); return /*line :157:38*/_Cfunc_sd_journal_seek_head(_cgo0); }(); rc != 0 {
		return fmt.Errorf("journald: error seeking to head of journal: %w", syscall.Errno(-rc))
	}
	return nil
}

// SeekTail sets the read pointer to the position after the most recent available entry.
//
// BUG: SeekTail() followed by Next() has unexpected behavior.
// https://github.com/systemd/systemd/issues/9934
func (j *Journal) SeekTail() error {
	if rc := func() _Ctype_int{ _cgo0 := /*line :168:34*/j.j; _cgoCheckPointer(_cgo0, nil); return /*line :168:38*/_Cfunc_sd_journal_seek_tail(_cgo0); }(); rc != 0 {
		return fmt.Errorf("journald: error seeking to tail of journal: %w", syscall.Errno(-rc))
	}
	return nil
}

// SeekRealtime seeks to a position with a realtime (wallclock) timestamp after t.
//
// Note that the realtime clock is not necessarily monotonic. If a realtime
// timestamp is ambiguous, the position seeked to is not defined.
func (j *Journal) SeekRealtime(t time.Time) error {
	if rc := func() _Ctype_int{ _cgo0 := /*line :179:43*/j.j; var _cgo1 _Ctype_uint64_t = _Ctype_uint64_t /*line :179:58*/(t.UnixMicro()); _cgoCheckPointer(_cgo0, nil); return /*line :179:74*/_Cfunc_sd_journal_seek_realtime_usec(_cgo0, _cgo1); }(); rc != 0 {
		return fmt.Errorf("journald: error seeking to time %v: %w", t, syscall.Errno(-rc))
	}
	return nil
}

// Wait blocks until the journal gets changed or timeout has elapsed.
// Pass a negative timeout to wait indefinitely.
func (j *Journal) Wait(timeout time.Duration) (Status, error) {
	var dur  /*line :188:10*/_Ctype_uint64_t /*line :188:20*/
	if timeout < 0 {
		// Wait indefinitely.
		dur = ^ /*line :191:10*/_Ctype_uint64_t /*line :191:20*/(0) // (uint64_t) -1
	} else {
		dur =  /*line :193:9*/_Ctype_uint64_t /*line :193:19*/(timeout.Microseconds())
	}
	s := func() _Ctype_int{ _cgo0 := /*line :195:25*/j.j; var _cgo1 _Ctype_uint64_t = /*line :195:30*/dur; _cgoCheckPointer(_cgo0, nil); return /*line :195:34*/_Cfunc_sd_journal_wait(_cgo0, _cgo1); }()
	if s < 0 {
		return 0, fmt.Errorf("journald: error waiting for event: %w", syscall.Errno(-s))
	}
	return Status(s), nil
}

// Realtime returns the realtime timestamp of the current journal entry.
func (j *Journal) Realtime() (time.Time, error) {
	var stamp  /*line :204:12*/_Ctype_uint64_t /*line :204:22*/
	if rc := func() _Ctype_int{ _cgo0 := /*line :205:42*/j.j; var _cgo1 *_Ctype_uint64_t = /*line :205:47*/&stamp; _cgoCheckPointer(_cgo0, nil); return /*line :205:54*/_Cfunc_sd_journal_get_realtime_usec(_cgo0, _cgo1); }(); rc != 0 {
		return time.Time{}, fmt.Errorf("journald: error getting journal entry timestamp: %w", syscall.Errno(-rc))
	}
	return time.UnixMicro(int64(stamp)), nil
}

// Data returns all data fields for the current journal entry.
func (j *Journal) Data() (map[string]string, error) {
	// Copying all the data fields for the entry into a map is more optimal
	// than you might think. Doing so has time complexity O(N), where N is
	// the number of fields in the entry. Looking up a data field in the map
	// is amortized O(1), so the total complexity to look up M data fields
	// is O(N+M). By comparison, looking up a data field using the
	// sd_journal_get_data function has time complexity of O(N) as it is
	// implemented as a linear search through the entry's fields. Therefore
	// looking up M data fields in an entry by calling sd_journal_get_data
	// in a loop would have time complexity of O(N*M).

	m := make(map[string]string)
	j.restartData()
	for {
		var (
			data   unsafe.Pointer
			length  /*line :228:11*/_Ctype_size_t /*line :228:19*/
		)
		rc := func() _Ctype_int{ _cgo0 := /*line :230:37*/j.j; _cgoBase1 := /*line :230:42*/&data; _cgo1 := _cgoBase1; var _cgo2 *_Ctype_size_t = /*line :230:49*/&length; _cgoCheckPointer(_cgo0, nil); _cgoCheckPointer(_cgoBase1, 0 == 0); return /*line :230:57*/_Cfunc_sd_journal_enumerate_data(_cgo0, _cgo1, _cgo2); }()
		if rc == 0 {
			return m, nil
		} else if rc < 0 {
			return m, fmt.Errorf("journald: error enumerating entry data: %w", syscall.Errno(-rc))
		}

		k, v, _ := strings.Cut(( /*line :237:26*/_Cfunc_GoStringN /*line :237:36*/)((* /*line :237:40*/_Ctype_char /*line :237:46*/)(data),  /*line :237:55*/_Ctype_int /*line :237:60*/(length)), "=")
		m[k] = v
	}
}

func (j *Journal) restartData() {
	func() { _cgo0 := /*line :243:28*/j.j; _cgoCheckPointer(_cgo0, nil); /*line :243:32*/_Cfunc_sd_journal_restart_data(_cgo0); }()
}

// SetDataThreshold may be used to change the data field size threshold for data
// returned by j.Data(). The threshold is a hint only; larger data fields might
// still be returned.
//
// The default threshold is 64K. To retrieve the complete data fields this
// threshold should be turned off by setting it to 0.
//
// https://www.freedesktop.org/software/systemd/man/sd_journal_set_data_threshold.html
func (j *Journal) SetDataThreshold(v uint) error {
	if rc := func() _Ctype_int{ _cgo0 := /*line :255:43*/j.j; var _cgo1 _Ctype_size_t = _Ctype_size_t /*line :255:56*/(v); _cgoCheckPointer(_cgo0, nil); return /*line :255:60*/_Cfunc_sd_journal_set_data_threshold(_cgo0, _cgo1); }(); rc != 0 {
		return fmt.Errorf("journald: error setting journal data threshold: %w", syscall.Errno(-rc))
	}
	return nil
}

type noCopy struct{}

func (noCopy) Lock()   {}
func (noCopy) Unlock() {}
