]> git.proxmox.com Git - ceph.git/blame - ceph/src/arrow/go/arrow/array/data.go
import quincy 17.2.0
[ceph.git] / ceph / src / arrow / go / arrow / array / data.go
CommitLineData
1d09f67e
TL
1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17package array
18
19import (
20 "hash/maphash"
21 "math/bits"
22 "sync/atomic"
23 "unsafe"
24
25 "github.com/apache/arrow/go/v6/arrow"
26 "github.com/apache/arrow/go/v6/arrow/internal/debug"
27 "github.com/apache/arrow/go/v6/arrow/memory"
28)
29
30// Data represents the memory and metadata of an Arrow array.
31type Data struct {
32 refCount int64
33 dtype arrow.DataType
34 nulls int
35 offset int
36 length int
37 buffers []*memory.Buffer // TODO(sgc): should this be an interface?
38 childData []*Data // TODO(sgc): managed by ListArray, StructArray and UnionArray types
39}
40
41// NewData creates a new Data.
42func NewData(dtype arrow.DataType, length int, buffers []*memory.Buffer, childData []*Data, nulls, offset int) *Data {
43 for _, b := range buffers {
44 if b != nil {
45 b.Retain()
46 }
47 }
48
49 for _, child := range childData {
50 if child != nil {
51 child.Retain()
52 }
53 }
54
55 return &Data{
56 refCount: 1,
57 dtype: dtype,
58 nulls: nulls,
59 length: length,
60 offset: offset,
61 buffers: buffers,
62 childData: childData,
63 }
64}
65
66// Reset sets the Data for re-use.
67func (d *Data) Reset(dtype arrow.DataType, length int, buffers []*memory.Buffer, childData []*Data, nulls, offset int) {
68 // Retain new buffers before releasing existing buffers in-case they're the same ones to prevent accidental premature
69 // release.
70 for _, b := range buffers {
71 if b != nil {
72 b.Retain()
73 }
74 }
75 for _, b := range d.buffers {
76 if b != nil {
77 b.Release()
78 }
79 }
80 d.buffers = buffers
81
82 // Retain new children data before releasing existing children data in-case they're the same ones to prevent accidental
83 // premature release.
84 for _, d := range childData {
85 if d != nil {
86 d.Retain()
87 }
88 }
89 for _, d := range d.childData {
90 if d != nil {
91 d.Release()
92 }
93 }
94 d.childData = childData
95
96 d.dtype = dtype
97 d.length = length
98 d.nulls = nulls
99 d.offset = offset
100}
101
102// Retain increases the reference count by 1.
103// Retain may be called simultaneously from multiple goroutines.
104func (d *Data) Retain() {
105 atomic.AddInt64(&d.refCount, 1)
106}
107
108// Release decreases the reference count by 1.
109// When the reference count goes to zero, the memory is freed.
110// Release may be called simultaneously from multiple goroutines.
111func (d *Data) Release() {
112 debug.Assert(atomic.LoadInt64(&d.refCount) > 0, "too many releases")
113
114 if atomic.AddInt64(&d.refCount, -1) == 0 {
115 for _, b := range d.buffers {
116 if b != nil {
117 b.Release()
118 }
119 }
120
121 for _, b := range d.childData {
122 b.Release()
123 }
124 d.buffers, d.childData = nil, nil
125 }
126}
127
128// DataType returns the DataType of the data.
129func (d *Data) DataType() arrow.DataType { return d.dtype }
130
131// NullN returns the number of nulls.
132func (d *Data) NullN() int { return d.nulls }
133
134// Len returns the length.
135func (d *Data) Len() int { return d.length }
136
137// Offset returns the offset.
138func (d *Data) Offset() int { return d.offset }
139
140// Buffers returns the buffers.
141func (d *Data) Buffers() []*memory.Buffer { return d.buffers }
142
143// NewSliceData returns a new slice that shares backing data with the input.
144// The returned Data slice starts at i and extends j-i elements, such as:
145// slice := data[i:j]
146// The returned value must be Release'd after use.
147//
148// NewSliceData panics if the slice is outside the valid range of the input Data.
149// NewSliceData panics if j < i.
150func NewSliceData(data *Data, i, j int64) *Data {
151 if j > int64(data.length) || i > j || data.offset+int(i) > data.offset+data.length {
152 panic("arrow/array: index out of range")
153 }
154
155 for _, b := range data.buffers {
156 if b != nil {
157 b.Retain()
158 }
159 }
160
161 for _, child := range data.childData {
162 if child != nil {
163 child.Retain()
164 }
165 }
166
167 o := &Data{
168 refCount: 1,
169 dtype: data.dtype,
170 nulls: UnknownNullCount,
171 length: int(j - i),
172 offset: data.offset + int(i),
173 buffers: data.buffers,
174 childData: data.childData,
175 }
176
177 if data.nulls == 0 {
178 o.nulls = 0
179 }
180
181 return o
182}
183
184func Hash(h *maphash.Hash, a *Data) {
185 h.Write((*[bits.UintSize / 8]byte)(unsafe.Pointer(&a.length))[:])
186 h.Write((*[bits.UintSize / 8]byte)(unsafe.Pointer(&a.length))[:])
187 if len(a.buffers) > 0 && a.buffers[0] != nil {
188 h.Write(a.buffers[0].Bytes())
189 }
190 for _, c := range a.childData {
191 Hash(h, c)
192 }
193}