@@ -255,6 +255,33 @@ package sdjournal
255255// return sd_journal_enumerate_data(j, data, length);
256256// }
257257//
258+ // int
259+ // my_sd_journal_query_unique(void *f, sd_journal *j, const char *field)
260+ // {
261+ // int(*sd_journal_query_unique)(sd_journal *, const char *);
262+ //
263+ // sd_journal_query_unique = f;
264+ // return sd_journal_query_unique(j, field);
265+ // }
266+ //
267+ // int
268+ // my_sd_journal_enumerate_unique(void *f, sd_journal *j, const void **data, size_t *length)
269+ // {
270+ // int(*sd_journal_enumerate_unique)(sd_journal *, const void **, size_t *);
271+ //
272+ // sd_journal_enumerate_unique = f;
273+ // return sd_journal_enumerate_unique(j, data, length);
274+ // }
275+ //
276+ // void
277+ // my_sd_journal_restart_unique(void *f, sd_journal *j)
278+ // {
279+ // void(*sd_journal_restart_unique)(sd_journal *);
280+ //
281+ // sd_journal_restart_unique = f;
282+ // sd_journal_restart_unique(j);
283+ // }
284+ //
258285import "C"
259286import (
260287 "bytes"
@@ -938,3 +965,60 @@ func (j *Journal) GetUsage() (uint64, error) {
938965
939966 return uint64 (out ), nil
940967}
968+
969+ // GetUniqueValues returns all unique values for a given field.
970+ func (j * Journal ) GetUniqueValues (field string ) ([]string , error ) {
971+ var result []string
972+
973+ sd_journal_query_unique , err := getFunction ("sd_journal_query_unique" )
974+ if err != nil {
975+ return nil , err
976+ }
977+
978+ sd_journal_enumerate_unique , err := getFunction ("sd_journal_enumerate_unique" )
979+ if err != nil {
980+ return nil , err
981+ }
982+
983+ sd_journal_restart_unique , err := getFunction ("sd_journal_restart_unique" )
984+ if err != nil {
985+ return nil , err
986+ }
987+
988+ j .mu .Lock ()
989+ defer j .mu .Unlock ()
990+
991+ f := C .CString (field )
992+ defer C .free (unsafe .Pointer (f ))
993+
994+ r := C .my_sd_journal_query_unique (sd_journal_query_unique , j .cjournal , f )
995+
996+ if r < 0 {
997+ return nil , fmt .Errorf ("failed to query journal: %d" , syscall .Errno (- r ))
998+ }
999+
1000+ // Implements the SD_JOURNAL_FOREACH_UNIQUE macro from sd-journal.h
1001+ var d unsafe.Pointer
1002+ var l C.size_t
1003+ C .my_sd_journal_restart_unique (sd_journal_restart_unique , j .cjournal )
1004+ for {
1005+ r = C .my_sd_journal_enumerate_unique (sd_journal_enumerate_unique , j .cjournal , & d , & l )
1006+ if r == 0 {
1007+ break
1008+ }
1009+
1010+ if r < 0 {
1011+ return nil , fmt .Errorf ("failed to read message field: %d" , syscall .Errno (- r ))
1012+ }
1013+
1014+ msg := C .GoStringN ((* C .char )(d ), C .int (l ))
1015+ kv := strings .SplitN (msg , "=" , 2 )
1016+ if len (kv ) < 2 {
1017+ return nil , fmt .Errorf ("failed to parse field" )
1018+ }
1019+
1020+ result = append (result , kv [1 ])
1021+ }
1022+
1023+ return result , nil
1024+ }
0 commit comments