Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/nightly-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
type: boolean
default: false
schedule:
- cron: '0 2 * * *'
- cron: "0 2 * * *"

jobs:
PackageUpdate:
Expand All @@ -31,7 +31,7 @@ jobs:
cache-assets: true
secrets:
token: ${{ secrets.ACCESS_TOKEN }}
DeviceDetectionUrl: ${{ secrets.IPI_DATA_FILE_URL }}
DeviceDetectionUrl: ${{ secrets.IPI_DATA_FILE_SAMPLE_URL }} # TODO: Do not merge PR untill you see this line IPI_DATA_FILE_URL

Publish:
if: ${{ !cancelled() }}
Expand All @@ -45,4 +45,4 @@ jobs:
cache-assets: true
secrets:
token: ${{ secrets.ACCESS_TOKEN }}
DeviceDetectionUrl: ${{ secrets.IPI_DATA_FILE_URL }}
DeviceDetectionUrl: ${{ secrets.IPI_DATA_FILE_SAMPLE_URL }} # TODO: Do not merge PR untill you see this line IPI_DATA_FILE_URL
2 changes: 1 addition & 1 deletion .github/workflows/nightly-pull-requests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ jobs:
cache-assets: true
secrets:
token: ${{ secrets.ACCESS_TOKEN }}
DeviceDetectionUrl: ${{ secrets.IPI_DATA_FILE_URL }}
DeviceDetectionUrl: ${{ secrets.IPI_DATA_FILE_SAMPLE_URL }} # TODO: Do not merge PR untill you see this line IPI_DATA_FILE_URL
10 changes: 9 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
.idea
# IDE specific files
.idea/
.idea/*
.vscode/
.vscode/*
*.swp
*.swo
*~
.DS_Store

4.**/
19 changes: 19 additions & 0 deletions ipi_interop/exception.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ package ipi_interop
//#include <string.h>
//#include "ip-intelligence-cxx.h"
import "C"
import "runtime"

const StatusNotSet = C.FIFTYONE_DEGREES_STATUS_NOT_SET

Expand All @@ -33,14 +34,32 @@ type Exception struct {
CPtr *C.Exception
}

// exceptionFinalizer check if C resource has been explicitly
// freed by Free method. Panic if it was not.
func exceptionFinalizer(e *Exception) {
if e.CPtr != nil {
panic("ERROR: Exception should be freed explicitly by its Free method.")
}
}

// NewException creates a new Exception object
func NewException() *Exception {
ce := new(C.Exception)
e := &Exception{ce}
e.Clear()
runtime.SetFinalizer(e, exceptionFinalizer)
return e
}

// Free frees the Exception object and sets CPtr to nil
func (e *Exception) Free() {
if e.CPtr != nil {
// Exception is Go-allocated, just set to nil
// No C.free needed as it's not C.malloc'd
e.CPtr = nil
}
}

// Clear resets the Exception object
func (e *Exception) Clear() {
e.CPtr.file = nil
Expand Down
4 changes: 4 additions & 0 deletions ipi_interop/resource_ipi.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (
// fiftyoneDegreesIpiInitManagerFromFile.
func InitManagerFromFile(manager *ResourceManager, config ConfigIpi, properties string, filePath string) error {
exp := NewException()
defer exp.Free()

cPath := C.CString(filePath)
defer C.free(unsafe.Pointer(cPath))
Expand Down Expand Up @@ -71,6 +72,7 @@ func InitManagerFromFile(manager *ResourceManager, config ConfigIpi, properties
// fiftyoneDegreesIpiReloadManagerFromFile.
func (manager *ResourceManager) ReloadFromFile(config ConfigIpi, properties string, filePath string) error {
exp := NewException()
defer exp.Free()

cPath := C.CString(filePath)
defer C.free(unsafe.Pointer(cPath))
Expand Down Expand Up @@ -107,6 +109,8 @@ func (manager *ResourceManager) ReloadFromFile(config ConfigIpi, properties stri
// fiftyoneDegreesIpiReloadManagerFromOriginalFile
func (manager *ResourceManager) ReloadFromOriginalFile() error {
exp := NewException()
defer exp.Free()

C.IpiReloadManagerFromOriginalFile(
manager.CPtr,
exp.CPtr,
Expand Down
32 changes: 19 additions & 13 deletions ipi_interop/results_ipi.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ func NewResultsIpi(manager *ResourceManager) *ResultsIpi {
var cResults interface{} = (*[math.MaxInt32 / int(C.sizeof_ResultIpi)]C.ResultIpi)(unsafe.Pointer(r.items))[:r.capacity:r.capacity]

res := &ResultsIpi{
CPtr: r,
CResults: &cResults,
CPtr: r,
CResults: &cResults,
}
runtime.SetFinalizer(res, resultsFinalizer)

Expand All @@ -62,6 +62,7 @@ func NewResultsIpi(manager *ResourceManager) *ResultsIpi {
// Returns an error if the operation fails.
func (r *ResultsIpi) ResultsIpiFromIpAddress(ipAddress string) error {
exception := NewException()
defer exception.Free()

char := C.CString(ipAddress)
defer C.free(unsafe.Pointer(char))
Expand Down Expand Up @@ -113,7 +114,6 @@ func (r *ResultsIpi) GetPropertyIndexByName(propertyName string) int {
return int(i)
}


// getPropertyNameSafe retrieves the property name associated with a required index from the given dataset safely.
// Returns an empty string if the required index is invalid or out of bounds.
func (r *ResultsIpi) getPropertyNameSafe(dataSet *C.DataSetIpi, requiredIndex C.int) string {
Expand All @@ -136,21 +136,24 @@ type header struct {
rawWeighting C.uint16_t
}



// GetWeightedValuesByIndexes retrieves weighted values using pre-computed property indexes
// and a property name resolver function to avoid expensive CGO calls for name resolution.
// The resolver function should provide fast index→name mapping (e.g., from Engine's cache).
func (r *ResultsIpi) GetWeightedValuesByIndexes(indexes []int, propertyNameResolver func(int) string) (Values, error) {
dataSet := (*C.DataSetIpi)(r.CPtr.b.dataSet)
exception := NewException()
defer exception.Free()

var cIndexes *C.int
var cIndexesCount C.uint

if len(indexes) > 0 {
// Allocate C memory for the array
cIndexes = (*C.int)(C.malloc(C.size_t(len(indexes)) * C.size_t(unsafe.Sizeof(C.int(0)))))
if cIndexes == nil {
return nil, fmt.Errorf("failed to allocate memory for indexes")
}

defer C.free(unsafe.Pointer(cIndexes))

// Copy Go slice elements to C array
Expand All @@ -168,12 +171,12 @@ func (r *ResultsIpi) GetWeightedValuesByIndexes(indexes []int, propertyNameResol
cIndexesCount,
nil, exception.CPtr,
)
// Release the collection
defer C.fiftyoneDegreesWeightedValuesCollectionRelease(&collection)

if !exception.IsOkay() {
return nil, fmt.Errorf(C.GoString(C.ExceptionGetMessage(exception.CPtr)))
}

// Release the collection
defer C.fiftyoneDegreesWeightedValuesCollectionRelease(&collection)

values := make(Values, collection.itemsCount)

Expand Down Expand Up @@ -226,12 +229,15 @@ func (r *ResultsIpi) GetWeightedValuesByIndexes(indexes []int, propertyNameResol
val = C.GoString(weightedString.value)
}

// Calculate weight
weight := float64(nextHeader.rawWeighting) / uint16Max

// append values to the map
values.Append(propName, val, weight)
// For MCC property, append with weight; for all others, append without weight
if propName == "Mcc" {
weight := float64(nextHeader.rawWeighting) / uint16Max
values.AppendWithWeight(propName, val, weight)
} else {
values.Append(propName, val)
}
}

return values, nil
}
}
26 changes: 24 additions & 2 deletions ipi_interop/weighted_value.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
* ********************************************************************* */
package ipi_interop

// WeightedValue represents a value paired with a specific weight for use in weighted calculations or prioritization.
// WeightedValue represents a value that may include a weight (used for MCC property).
// For non-weighted properties, Weight will be 0.0.
type WeightedValue struct {
Value interface{}
Weight float64
Expand All @@ -30,6 +31,16 @@ type WeightedValue struct {
// Values is a map where each key is a string representing a property, and the value is a slice of WeightedValue pointers.
type Values map[string][]*WeightedValue

// GetValueByProperty retrieves the first value for the specified property (ignoring weight).
// This is the recommended method for all properties except MCC.
// Returns the value and a boolean indicating success or failure.
func (v Values) GetValueByProperty(property string) (interface{}, bool) {
if val, ok := v[property]; ok && len(val) > 0 {
return val[0].Value, true
}
return "", false
}

// GetValueWeightByProperty retrieves the first value and its weight for the specified property.
// Returns the value, weight, and a boolean indicating success or failure.
func (v Values) GetValueWeightByProperty(property string) (interface{}, float64, bool) {
Expand All @@ -39,7 +50,18 @@ func (v Values) GetValueWeightByProperty(property string) (interface{}, float64,
return "", 0, false
}

func (v Values) Append(property string, value interface{}, weight float64) {
// Append adds a value without weight (Weight will be set to 0.0).
// Use this for all properties except MCC.
func (v Values) Append(property string, value interface{}) {
v[property] = append(v[property], &WeightedValue{
Value: value,
Weight: 0.0,
})
}

// AppendWithWeight adds a value with a specific weight.
// This should only be used for MCC property.
func (v Values) AppendWithWeight(property string, value interface{}, weight float64) {
v[property] = append(v[property], &WeightedValue{
Value: value,
Weight: weight,
Expand Down
Loading
Loading