OmniSciDB  5ade3759e0
arrow Namespace Reference

Functions

key_t get_and_copy_to_shm (const std::shared_ptr< Buffer > &data)
 

Function Documentation

◆ get_and_copy_to_shm()

key_t arrow::get_and_copy_to_shm ( const std::shared_ptr< Buffer > &  data)

Definition at line 155 of file ArrowResultSetConverter.cpp.

Referenced by ArrowResultSetConverter::getArrowResultImpl().

155  {
156  if (!data->size()) {
157  return IPC_PRIVATE;
158  }
159  // Generate a new key for a shared memory segment. Keys to shared memory segments
160  // are OS global, so we need to try a new key if we encounter a collision. It seems
161  // incremental keygen would be deterministically worst-case. If we use a hash
162  // (like djb2) + nonce, we could still get collisions if multiple clients specify
163  // the same nonce, so using rand() in lieu of a better approach
164  // TODO(ptaylor): Is this common? Are these assumptions true?
165  auto key = static_cast<key_t>(rand());
166  const auto shmsz = data->size();
167  int shmid = -1;
168  // IPC_CREAT - indicates we want to create a new segment for this key if it doesn't
169  // exist IPC_EXCL - ensures failure if a segment already exists for this key
170  while ((shmid = shmget(key, shmsz, IPC_CREAT | IPC_EXCL | 0666)) < 0) {
171  // If shmget fails and errno is one of these four values, try a new key.
172  // TODO(ptaylor): is checking for the last three values really necessary? Checking
173  // them by default to be safe. EEXIST - a shared memory segment is already associated
174  // with this key EACCES - a shared memory segment is already associated with this key,
175  // but we don't have permission to access it EINVAL - a shared memory segment is
176  // already associated with this key, but the size is less than shmsz ENOENT -
177  // IPC_CREAT was not set in shmflg and no shared memory segment associated with key
178  // was found
179  if (!(errno & (EEXIST | EACCES | EINVAL | ENOENT))) {
180  throw std::runtime_error("failed to create a shared memory");
181  }
182  key = static_cast<key_t>(rand());
183  }
184  // get a pointer to the shared memory segment
185  auto ipc_ptr = shmat(shmid, NULL, 0);
186  if (reinterpret_cast<int64_t>(ipc_ptr) == -1) {
187  throw std::runtime_error("failed to attach a shared memory");
188  }
189 
190  // copy the arrow records buffer to shared memory
191  // TODO(ptaylor): I'm sure it's possible to tell Arrow's RecordBatchStreamWriter to
192  // write directly to the shared memory segment as a sink
193  memcpy(ipc_ptr, data->data(), data->size());
194  // detach from the shared memory segment
195  shmdt(ipc_ptr);
196  return key;
197 }
+ Here is the caller graph for this function: