I am trying to create an aggregate function which returns the value of a column in the row which has the least/greatest timestamp. Below is the code which throws a segmentation fault for some large input.
PG_FUNCTION_INFO_V1(minmax);
Datum minmax(PG_FUNCTION_ARGS) {
if(PG_ARGISNULL(1) || PG_ARGISNULL(2) || PG_ARGISNULL(3)) {
if(PG_ARGISNULL(0)) {
PG_RETURN_NULL();
}
else {
PG_RETURN_HEAPTUPLEHEADER(PG_GETARG_HEAPTUPLEHEADER(0));
}
}
Timestamp epoch = PG_GETARG_TIMESTAMP(1);
Datum col = PG_GETARG_DATUM(2);
Oid element_type = get_fn_expr_argtype(fcinfo->flinfo, 2);
bool is_min = PG_GETARG_BOOL(3);
Timestamp minmax_epoch = is_min ? LONG_MAX : LONG_MIN;
Datum minmax_col;
if(PG_ARGISNULL(0)) {
// first call
minmax_epoch = epoch;
minmax_col = col;
}
else {
// state
HeapTupleHeader hth_state = PG_GETARG_HEAPTUPLEHEADER(0);
bool isnull_state_minmax_timestamp;
Datum d_state_minmax_timestamp = GetAttributeByNum(hth_state, (AttrNumber) 1, &isnull_state_minmax_timestamp);
minmax_epoch = DatumGetInt64(d_state_minmax_timestamp);
if((is_min && epoch < minmax_epoch) || (!is_min && epoch > minmax_epoch)) {
minmax_epoch = epoch;
minmax_col = col;
}
else {
PG_RETURN_HEAPTUPLEHEADER(hth_state);
}
}
// return state
TupleDesc tupdesc;
Datum values[2];
bool nulls[2];
MemSet(values, 0, sizeof(values));
MemSet(nulls, 0, sizeof(nulls));
tupdesc = CreateTemplateTupleDesc(2, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "minmax_timestamp", INT8OID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "minmax_col", element_type, -1, 0);
tupdesc = BlessTupleDesc(tupdesc);
values[0] = Int64GetDatum(minmax_epoch);
values[1] = minmax_col;
HeapTuple rettuple = heap_form_tuple(tupdesc, values, nulls);
PG_RETURN_DATUM(HeapTupleGetDatum(rettuple));
}
PG_FUNCTION_INFO_V1(get_minmax);
Datum get_minmax(PG_FUNCTION_ARGS) {
if(PG_ARGISNULL(0)) {
PG_RETURN_NULL();
}
else {
// state
//error here
HeapTupleHeader hth_state = PG_GETARG_HEAPTUPLEHEADER(0);
bool isnull_state_minmax_col;
Datum d_state_minmax_col = GetAttributeByNum(hth_state, (AttrNumber) 2, &isnull_state_minmax_col);
PG_RETURN_DATUM(d_state_minmax_col);
}
}
The seg fault seems to be in the function get_minmax getting the PG_GETARG_HEAPTUPLEHEADER argument. May be I am not building it properly in minmax function.
Doesn't seem to be anything wrong with the above code. I was using the aggregate function in greenplum and not postgresql. For those writing aggregate functions in greenplum and implementing PREFUNC, make sure to check if both the arguments are NULL and handle accordingly.
Experts do suggest if any improvements can be made to the above function in terms of memory usage, etc
Related
I have been using libconfig for config files in a project. When I remove the double quotes from sources by source_to_use, config_read_file() returns config_true and also has a syntax error. The syntax error will cause my getter for the source_to_use option to go to the default case. Also because of this my getter for the source array, will also go to the else case. Could this just be me making a simple syntax error with the libconfig format?
This is the config file I am using:
#config for walld
#colors
colors = TRUE;
source_to_use: "sources";
default:
[
"/home/seth/Pictures/kimi.png"
];
sources:
[
"/home/seth/.walld/persona",
"/home/seth/.walld/image-urls"
];
This is the function I have reading it:
settings* read_config(const char* config_file, const char* home_dir) {
settings* options = malloc(sizeof(settings));
config_t config;
config_setting_t* setting;
const char* source;
int colors;
config_init(&config);
if (config_read_file(&config, config_file) == CONFIG_TRUE) {
config_destroy(&config);
return NULL;
}
if (config_lookup_bool(&config, "colors", &colors)) {
options->colors = colors;
}
else {
options->colors = 0;
}
if (config_lookup_string(&config, "source_to_use", &source)) {
//NOP
}
else {
source = "default";
}
setting = config_lookup(&config, source);
if (setting != NULL) {
int count = config_setting_length(setting);
linked_node* entry_point = add_node_to_list(NULL, NULL);
linked_node* current = entry_point;
options->sources = entry_point;
for (int i = 0; i < count; i++) {
char* item = config_setting_get_string_elem(setting, i);
current = add_node_to_list(current, item);
}
}
else {
options->sources = malloc(sizeof(linked_node));
int char_count = snprintf(NULL, 0, "%s%s", home_dir, "/.walld/images");
if (char_count <= 0) {
//tough luck
abort();
}
char* default_folder = malloc(char_count + 1U);
if (default_folder == NULL) {
//tough luck
abort();
}
snprintf(default_folder, char_count + 1U, "%s%s", home_dir, "/.walld/images");
options->sources->image = default_folder;
}
config_destroy(&config);
return options;
}
In your read_config function, your first if is:
if (config_read_file(&config, config_file) == CONFIG_TRUE) {
config_destroy(&config);
return NULL;
}
The sense of the if is reversed, so you'll return a NULL if the read of the file is valid.
So, you want to reverse the sense of this if:
if (config_read_file(&config, config_file) != CONFIG_TRUE) {
config_destroy(&config);
return NULL;
}
Or you could [probably] use:
if (config_read_file(&config, config_file) == CONFIG_FALSE) {
I am creating a C lib plus a wrapper for easy use in Swift. The C function takes two parameters, an array pointer and an int pointer:
int crgetproclist(struct kinfo_proc *proc_list, size_t *count) {
int err = 0;
size_t length = 0;
static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
// Call sysctl with a NULL buffer to get proper length
err = sysctl((int *)name, (sizeof(name) / sizeof(*name)) - 1, NULL, &length, NULL, 0);
//if (err) return [-1];
// Get the actual process list
err = sysctl((int *)name, (sizeof(name) / sizeof(*name)) - 1, proc_list, &length, NULL, 0);
//if (err) return [-1];
*count = length / sizeof(struct kinfo_proc);
for (int i = 0; i < *count; i++) {
struct kinfo_proc proc = proc_list[i];
proc = proc;
}
return 1;
}
I call that function from my Swift wrapper:
var data: [Process] = []
override func viewDidLoad() {
super.viewDidLoad()
let proc_list: UnsafeMutablePointer<kinfo_proc> = UnsafeMutablePointer<kinfo_proc>.allocate(capacity: 500)
var count: size_t = 0
let result = crgetproclist(proc_list, &count)
var foobar: [Process] = []
if (result == 1) {
for i in 1..<count {
var proc: kinfo_proc = proc_list[i]
var process = Process(proc: proc)
foobar.append(process) // <---- works
self.data.append(process) // <---- EXC_BAD_ACCESS ????
}
self.data.sort(by: {
(a: Process, b: Process) -> Bool in
return a.name.lowercased() < b.name.lowercased()
})
self.myTable.reloadData()
}
}
class Process: NSObject {
var _proc: kinfo_proc
var pid: pid_t
var name: String
var icon: NSImage?
var isAlive: Bool = false
var uid: uid_t = 0
init(proc: kinfo_proc) {
self._proc = proc
self.pid = proc.kp_proc.p_pid
self.name = String(cString: crgetprocname(pid))
self.uid = crgetuid(pid)
super.init()
}
}
Questions
How to correctly create and pass an UnsafeMutablePointer to the C function? I hard coded capacity: 500 which works, but how to do it correctly without a hardcoded capacity?
When I try to append it to my class variable array data it runs into a EXC_BAD_ACCESS, but when I append it to foobar which is the same type it works. Why? How to assign it to a class variable without memory error?
I can only answer the first part of your question: In order to determine the necessary allocation count for the process list you must allow that crgetproclist() is called with a NULL argument (in the same way as sysctl() can be called with a NULL argument for oldp to get the needed buffer size):
int crgetproclist(struct kinfo_proc *proc_list, size_t *count) {
int err = 0;
size_t length;
static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
if (proc_list == NULL) {
// Call sysctl with a NULL buffer to get proper length
length = 0;
err = sysctl((int *)name, (sizeof(name) / sizeof(*name)), NULL, &length, NULL, 0);
} else {
// Get the actual process list
length = *count * sizeof(struct kinfo_proc);
err = sysctl((int *)name, (sizeof(name) / sizeof(*name)), proc_list, &length, NULL, 0);
}
if (err) return -1;
*count = length / sizeof(struct kinfo_proc);
return 1;
}
Now you can call that function from Swift twice: First to determine the allocation count, and then again to retrieve the process list:
var count: size_t = 0
crgetproclist(nil, &count)
let procList = UnsafeMutablePointer<kinfo_proc>.allocate(capacity: count)
if crgetproclist(procList, &count) == 1 {
for i in 0..<count {
let proc = procList[i]
// ...
}
}
procList.deallocate()
Note also that you can implement the function easily in pure Swift:
func getProcessList() -> [kinfo_proc]? {
var name : [Int32] = [ CTL_KERN, KERN_PROC, KERN_PROC_ALL ]
var length = size_t()
sysctl(&name, UInt32(name.count), nil, &length, nil, 0)
let count = length / MemoryLayout<kinfo_proc>.size
var procList = Array(repeating: kinfo_proc(), count: count)
let result = sysctl(&name, UInt32(name.count), &procList, &length, nil, 0)
guard result == 0 else { return nil } // Some error ...
return Array(procList.prefix(length / MemoryLayout<kinfo_proc>.size))
}
Could someone help me with this one. I'm making BFS algorithm in C programming language, with help of dynamic lists.
This is my code.
// ConsoleApplication3.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <malloc.h>
#define n 6
typedef struct field
{
int x;
int y;
int dist;
struct field *next;
}Field;
// Get row and column number of 4 neighbours
int rows[] = { -1, 0, 0, 1 };
int cols[] = { 0, -1, 1, 0 };
Field *addToEnd(Field *lst, Field field)
{
Field *newField = (Field*)malloc(sizeof Field);
newField = &field;
newField->next = NULL;
if (!lst)
return newField;
else
{
Field *current;
for (current = lst; current->next; current = current->next);
current->next = newField;
return lst;
}
}
// Check if field is/isn't out of range
bool isValid(int row, int col)
{
return (row >= 0) && (row < n) && (col >= 0) && (col < n);
}
int BFS(int mat[][n], Field source, Field destination)
{
bool visited[n][n];
memset(visited, false, sizeof visited);
// Mark the source field as visited
visited[source.x][source.y] = true;
// Create dynamic list
Field *lst = NULL;
source.dist = 0;
// Adding the source field to the list
lst = addToEnd(lst, source);
while (lst)
{
// Getting first element in the list
Field current = *lst;
// If destination is reached then end function
if (current.x == destination.x && current.y == destination.y)
return current.dist;
// Delete first element of the list
Field *toDelete;
toDelete = lst;
lst = lst->next;
free(toDelete);
for (int i = 0; i < 4; i++)
{
int row = current.x + rows[i];
int col = current.y + cols[i];
// If adjacent field is valid, has path and isn't visited add it to the list
if (isValid(row, col) && mat[row][col] == 0 && !visited[row][col])
{
visited[row][col] = true;
Field adjField = { row, col, current.dist + 1 };
lst = addToEnd(lst, adjField);
}
}
}
// Return -1 if destination can't be reached
return -1;
}
int main()
{
int mat[n][n] =
{
{ 0, 0, 0, 0, 0, 0 },
{ 0, 1, 1, 1, 1, 0 },
{ 0, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 1, 1, 0 },
{ 0, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 1, 1, 0 }
};
Field start = { 1, 0 }, end = { 5, 5 };
int number = BFS(mat, start, end);
if (number != -1)
printf("%d\n", number);
else
printf("Destination can't be reached\n");
return 0;
}
Everything except part of code which need to delete first element of list is working. The problem is with free function.
https://i.stack.imgur.com/QpK1j.png
https://i.stack.imgur.com/HXp8d.png
Does anyone have an idea what could be possible wrong with this and how can I fix it?
I like to sort an array with objects that have multiple properties. My objects have a string called name and a boolean called mandatory.
First i want to sort on age, next on the name.
How do I do this?
Ordering by age is easy...:
this.model.mylist.sort((obj1: IObj, obj2: IObj => {
if (obj1.age < obj2.age) {
return -1;
}
if (obj1.age > obj2.age) {
return 1;
}
return 0;
});
Well, you only add comparation for case when the two age values are the same. So something like this should work:
this.model.mylist.sort((obj1: IObj, obj2: IObj) => {
if (obj1.age < obj2.age) {
return -1;
}
if (obj1.age > obj2.age) {
return 1;
}
return obj1.name.localeCompare(obj2.name);
});
Something like this should work. The method compares the current and next values and adds comparison to the case when the two age values are the same. Then assume the column name in order based on age.
private compareTo(val1, val2, typeField) {
let result = 0;
if (typeField == "ftDate") {
result = val1 - val2;
} else {
if (val1 < val2) {
result = - 1;
} else if (val1 > val2) {
result = 1;
} else {
result = 0;
}
}
return result;
}
-
this.model.mylist.sort((a, b) => {
let cols = ["age", "name"];
let i = 0, result = 0, resultordem = 0;
while (result === 0 && i < cols.length) {
let col = cols[i];
let valcol1 = a[col];
let valcol2 = b[col];
let typeField = "string";
if (col == "age") {
typeField = "number";
}
if (valcol1 != "null" && valcol1 != "null") {
resultordem = this.compareTo(valcol1, valcol2, typeField);
if (resultordem != 0) {
break;
}
}
i++;
}
return resultordem;
});
In a 3D scene, I have an Object that has a position that I would like to move using Lua.
eg. box.position.x = 10
box has a metatable ("Object") and so has position ("Vec"). Object has __newindex and __index set to call C functions NewIndexObject and IndexObject respectively. Same with Vec (NewIndexVec and IndexVec).
Object has an id so it can be identified in a list that is stored in the scene and when box.position is accessed all is fine, the C function IndexObject is called and I can extract the id from the stack, it's just when box.position.x = 10 is executed 'NewIndexVec' is called and the only thing on the stack is {table, x, 10} so no way of identifying the object to change its x position.
Is there anyway of pushing values onto a local state? Help!
UPDATE: thank you for getting back to me quickly, below I have distilled the code as much as possible. If you run this code it'll appear to work but I have comments where I'm stuck, it's just getting the first object in the array but I need to choose it by it's ID, Thanks in advance
struct Obj
{
std::string id;
int x,y,z;
Obj()
{
x = 10; y = 20; z = 30;
id = "12345";
}
};
//array of external objects
std::vector<Obj> objects;
int NewObject(lua_State * L)
{
Obj obj;
objects.push_back(obj);
lua_newtable(L);
luaL_getmetatable(L, "MT_Object");
lua_setmetatable(L, -2);
lua_pushstring(L, "id");
lua_pushstring(L, obj.id.c_str());
lua_settable(L, 1);
lua_newtable(L);
luaL_getmetatable(L, "MT_Vec");
lua_setmetatable(L, -2);
lua_pushinteger(L, obj.x);
lua_setfield(L, -2, "x");
lua_pushinteger(L, obj.y);
lua_setfield(L, -2, "y");
lua_pushinteger(L, obj.z);
lua_setfield(L, -2, "z");
lua_setfield(L, -2, "position");
return 1;
}
int IndexVec(lua_State * L)
{
// How do I get the correct object so I can pass its value back
Obj &dunnoObj = objects[0];
std::string key = luaL_checkstring(L,-1);
if(key == "x")
lua_pushinteger(L,dunnoObj.x);
else if(key == "y")
lua_pushinteger(L,dunnoObj.y);
else if(key == "z")
lua_pushinteger(L,dunnoObj.z);
return 1;
}
int NewIndexVec(lua_State * L)
{
// How do I know which object's value to update
Obj &dunnoObj = objects[0];
std::string key = luaL_checkstring(L,-2);
int value = luaL_checkinteger(L,-1);
if(key == "x")
dunnoObj.x = value;
else if(key == "y")
dunnoObj.y = value;
else if(key == "z")
dunnoObj.z = value;
return 0;
}
int main()
{
lua_State * L = luaL_newstate();
luaL_openlibs(L);
luaL_Reg objreg[] =
{
{ "new", NewObject },
{ NULL, NULL }
};
luaL_newmetatable(L, "MT_Object");
luaL_register(L, 0, objreg);
lua_setglobal(L, "Object");
luaL_Reg reg[] =
{
{ "__index", IndexVec },
{ "__newindex", NewIndexVec },
{ NULL, NULL }
};
luaL_newmetatable(L, "MT_Vec");
luaL_register(L, 0, reg);
lua_setglobal(L, "Vec");
int res = luaL_dostring(L, "box = Object.new() box.position.x = 1000 print(box.id .. \" , \" ..box.position.x .. \" , \" .. box.position.y .. \" , \" .. box.position.z)");
if(res)
printf("Error: %s\n", lua_tostring(L, -1));
lua_close(L);
return 0;
}
If I understand you correctly, you don't have to do anything. Tables are tracked by reference, so NewIndexVec doesn't need to know anything about box if its first argument is box.position.
If this answer can't work for some reason, then I'd need more information about your data structure to understand your problem.
Basically, box.position needs to return some obj for which obj.x = 10 is a valid operation and changes exactly what you want it to change.
The problem is that you're trying to keep the same data in two separate places. Keep all the data in the C++ struct, then have NewObject return a userdata that pretends to be a table. Both the Object and the position field should be the same Obj*, but they may have different metatables to simulate different sets of fields.
Thanks, I've posted the code that works
struct Obj
{
unsigned int id;
int x,y,z;
Obj()
{
x = 10; y = 20; z = 30;
id = rand();
}
};
//array of external objects
std::map<unsigned int,Obj> objects;
int NewObject(lua_State * L)
{
Obj obj;
objects[obj.id] = obj;
lua_pushinteger(L, obj.id);
luaL_getmetatable(L, "MT_Object");
lua_setmetatable(L, -2);
return 1;
}
int IndexObj(lua_State * L)
{
unsigned int objid = luaL_checkinteger(L,1);
std::string key = luaL_checkstring(L,-1);
if(key == "position" )
{
Obj *a = (Obj *)lua_newuserdata(L, sizeof(Obj));
*a = objects[objid];
luaL_getmetatable(L, "MT_Vec");
lua_setmetatable(L, -2);
}
else if(key == "id")
lua_pushinteger(L, objid);
else
lua_pushnil(L);
StackDump(L);
return 1;
}
int IndexVec(lua_State * L)
{
Obj *a = (Obj *)lua_touserdata(L, 1);
std::string key = luaL_checkstring(L,-1);
if(key == "x")
lua_pushinteger(L,a->x);
else if(key == "y")
lua_pushinteger(L,a->y);
else if(key == "z")
lua_pushinteger(L,a->z);
return 1;
}
int NewIndexVec(lua_State * L)
{
Obj *a = (Obj *)lua_touserdata(L, 1);
Obj &objRef = objects[a->id];
std::string key = luaL_checkstring(L,-2);
int value = luaL_checkinteger(L,-1);
if(key == "x")
objRef.x = value;
else if(key == "y")
objRef.y = value;
else if(key == "z")
objRef.z = value;
return 0;
}
int main()
{
lua_State * L = luaL_newstate();
luaL_openlibs(L);
luaL_Reg objreg[] =
{
{ "new", NewObject },
{ "__index", IndexObj },
{ "__newindex", NewIndexObj },
{ NULL, NULL }
};
luaL_newmetatable(L, "MT_Object");
luaL_register(L, 0, objreg);
lua_setglobal(L, "Object");
luaL_Reg reg[] =
{
{ "__index", IndexVec },
{ "__newindex", NewIndexVec },
{ NULL, NULL }
};
luaL_newmetatable(L, "MT_Vec");
luaL_register(L, 0, reg);
lua_setglobal(L, "Vec");
int res = luaL_dostring(L, "box = Object.new() box.position.x = 1000 "
"print(box.id .. \" , \" ..box.position.x .. \" , \" .. box.position.y .. \" , \" .. box.position.z)");
if(res)
printf("Error: %s\n", lua_tostring(L, -1));
lua_close(L);
return 0;
}