package shmqueue
|
|
import (
|
"context"
|
"fmt"
|
"time"
|
shm "basic.com/valib/goshm.git"
|
)
|
|
const sleepPeriod = time.Duration(5) * time.Millisecond
|
|
// NewBlock shm block with size
|
func NewBlock(size int, key int) ([]byte, int, error) {
|
id, err := shm.Get(key, size, shm.IPC_CREAT|0666)
|
if err != nil || id == -1 {
|
fmt.Printf("NewBlock Get:%x, %v\n", key, err)
|
return nil, -1, err
|
}
|
|
data, err2 := shm.At(id, 0, 0)
|
if err2 != nil {
|
fmt.Printf("NewBlock At:%x, %v\n", key, err2)
|
return nil, -1, err2
|
}
|
|
return data, id, nil
|
}
|
|
// NewBlockOnly shm block with size, no attach
|
func NewBlockOnly(size int, key int) (int, error) {
|
id, err := shm.Get(key, size, shm.IPC_CREAT|0666)
|
if err != nil || id == -1 {
|
fmt.Printf("NewBlock Get:%x, %v\n", key, err)
|
return -1, err
|
}
|
return id, nil
|
}
|
|
// AttachBlock attach exist shm
|
func AttachBlock(key int) ([]byte, int, error) {
|
id, err := shm.Get(key, 0, 0)
|
if err != nil || id == -1 { //no exist
|
fmt.Printf("AttachBlock Get:%x, %v\n", key, err)
|
return nil, -1, err
|
}
|
|
data, err2 := shm.At(id, 0, 0)
|
if err2 != nil {
|
fmt.Printf("AttachBlock Get:%x, %v\n", key, err2)
|
return nil, -1, err2
|
}
|
|
return data, id, nil
|
}
|
|
// ReleaseBlock release shm block
|
func ReleaseBlock(data []byte) {
|
if data != nil {
|
shm.Dt(data)
|
}
|
}
|
|
// CreateRawShm create raw shm block with size, only space, no padding, return data([]byte), id(int)
|
// context for quit
|
func CreateRawShm(ctx context.Context, size int, key int) ([]byte, int) {
|
data, id, err := AttachBlock(key)
|
if err != nil {
|
loopB:
|
for {
|
select {
|
case <-ctx.Done():
|
return nil, -1
|
default:
|
if err == nil {
|
break loopB
|
}
|
time.Sleep(sleepPeriod)
|
data, id, err = NewBlock(size, key)
|
}
|
}
|
}
|
return data, id
|
}
|
|
//AttachRawShm don't create
|
func AttachRawShm(ctx context.Context, key int) ([]byte, int) {
|
data, id, err := AttachBlock(key)
|
if err != nil {
|
loopB:
|
for {
|
select {
|
case <-ctx.Done():
|
return nil, -1
|
default:
|
if err == nil {
|
break loopB
|
}
|
time.Sleep(sleepPeriod)
|
data, id, err = AttachBlock(key)
|
}
|
}
|
}
|
return data, id
|
}
|
|
// CreateShmOnly create shm block with size, only space, no padding, return id(int)
|
// context for quit
|
func CreateShmOnly(ctx context.Context, size int, key int) int {
|
id, err := NewBlockOnly(size, key)
|
if err != nil {
|
loopB:
|
for {
|
select {
|
case <-ctx.Done():
|
return -1
|
default:
|
if err == nil {
|
break loopB
|
}
|
time.Sleep(sleepPeriod)
|
id, err = NewBlockOnly(size, key)
|
}
|
}
|
}
|
return id
|
}
|
|
// CreateShmOnly create shm block with size, only space, no padding, return id(int)
|
// context for quit
|
func CreateShmOnlyTime(ctx context.Context, size int, key int, timeout int) int {
|
id, err := NewBlockOnly(size, key)
|
if err != nil {
|
to := time.NewTimer(time.Duration(timeout) * time.Millisecond)
|
defer to.Stop()
|
loopB:
|
for {
|
select {
|
case <-ctx.Done():
|
return -1
|
case <-to.C:
|
return -1
|
default:
|
if err == nil {
|
break loopB
|
}
|
time.Sleep(sleepPeriod)
|
id, err = NewBlockOnly(size, key)
|
}
|
}
|
}
|
return id
|
}
|
|
// CreatePaddingShm create padding shm block with size, return data-with-padding([]byte), id(int)
|
// context for quit, padding for fill raw shm block
|
func CreatePaddingShm(ctx context.Context, size int, key int, padding []byte) ([]byte, int) {
|
data, id, err := NewBlock(size, key)
|
if err != nil {
|
loopB:
|
for {
|
select {
|
case <-ctx.Done():
|
return nil, -1
|
default:
|
if err == nil {
|
break loopB
|
} else {
|
fmt.Println("createShm error:", err)
|
}
|
time.Sleep(sleepPeriod)
|
data, id, err = NewBlock(size, key)
|
}
|
}
|
}
|
|
copy(data, padding)
|
return data, id
|
}
|
|
// CheckShmExist check if shm is exist or not
|
// if exist, return id and true, else return 0 and false
|
func CheckShmExist(key int) (int, bool) {
|
id, err := shm.Get(key, 0, 0)
|
if err != nil || id == -1 { //no exist
|
fmt.Printf("AttachBlock Get:%x, %v\n", key, err)
|
return 0, false
|
}
|
|
return id, true
|
}
|
|
// DetachShm destroy
|
func DetachShm(data []byte) {
|
ReleaseBlock(data)
|
}
|
|
// Attach attach shmid get block
|
func Attach(id int) ([]byte, error) {
|
return shm.At(id, 0, 0)
|
}
|
|
// Detach detach shm block
|
func Detach(d []byte) error {
|
return shm.Dt(d)
|
}
|
|
// RemoveShmID Remove shmid
|
func RemoveShmID(id int) error {
|
return shm.Rm(id)
|
}
|
|
// RemoveShmKey Remove shmkey
|
func RemoveShmKey(shmkey int) error {
|
d, id, err := AttachBlock(shmkey)
|
if err != nil {
|
return err
|
} else {
|
Detach(d)
|
return shm.Rm(id)
|
}
|
}
|
|
// DetachShmKey detach shmkey
|
func DetachShmKey(shmkey int) error {
|
d, _, err := AttachBlock(shmkey)
|
if err != nil {
|
return err
|
} else {
|
Detach(d)
|
return Detach(d)
|
}
|
}
|
|
// DetachAndRemoveShmKey detach and Remove shmkey
|
func DetachAndRemoveShmKey(shmkey int) error {
|
d, id, err := AttachBlock(shmkey)
|
if err != nil {
|
return err
|
} else {
|
Detach(d)
|
return shm.Rm(id)
|
}
|
}
|
|
func ShmAttachNum(shmId int) (int,error) {
|
var idDs shm.IdDs
|
|
_, err := shm.Ctl(shmId, shm.IPC_STAT, &idDs)
|
if err != nil {
|
return 0, err
|
}
|
|
return int(idDs.Nattch), nil
|
}
|
|
func GetKeyById(shmId int) (int,error) {
|
var idDs shm.IdDs
|
|
_, err := shm.Ctl(shmId, shm.IPC_STAT, &idDs)
|
if err != nil {
|
return 0, err
|
}
|
|
return int(idDs.Perm.Key), nil
|
}
|