]>
Commit | Line | Data |
---|---|---|
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 | ||
17 | package array | |
18 | ||
19 | import ( | |
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. | |
31 | type 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. | |
42 | func 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. | |
67 | func (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. | |
104 | func (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. | |
111 | func (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. | |
129 | func (d *Data) DataType() arrow.DataType { return d.dtype } | |
130 | ||
131 | // NullN returns the number of nulls. | |
132 | func (d *Data) NullN() int { return d.nulls } | |
133 | ||
134 | // Len returns the length. | |
135 | func (d *Data) Len() int { return d.length } | |
136 | ||
137 | // Offset returns the offset. | |
138 | func (d *Data) Offset() int { return d.offset } | |
139 | ||
140 | // Buffers returns the buffers. | |
141 | func (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. | |
150 | func 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 | ||
184 | func 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 | } |