{"id":18382417,"url":"https://github.com/ntd/xsettings","last_synced_at":"2026-04-27T20:31:59.773Z","repository":{"id":212075361,"uuid":"730643002","full_name":"ntd/xsettings","owner":"ntd","description":"Persistent storage backend for open62541 based OPC/UA servers","archived":false,"fork":false,"pushed_at":"2025-04-30T05:16:32.000Z","size":25,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-30T06:25:17.381Z","etag":null,"topics":["linux","mmap","opcua","open62541","persistent","real-time","storage"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ntd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-12-12T11:15:06.000Z","updated_at":"2025-04-30T05:16:35.000Z","dependencies_parsed_at":"2024-12-24T06:11:57.043Z","dependency_job_id":"b73d3ac8-fcc8-4593-a38a-f15ff2657d81","html_url":"https://github.com/ntd/xsettings","commit_stats":{"total_commits":6,"total_committers":1,"mean_commits":6.0,"dds":0.0,"last_synced_commit":"3a0f36f217f67eea66d7e79ab4cd4aaa2a17c6ba"},"previous_names":["ntd/xsettings"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ntd/xsettings","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ntd%2Fxsettings","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ntd%2Fxsettings/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ntd%2Fxsettings/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ntd%2Fxsettings/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ntd","download_url":"https://codeload.github.com/ntd/xsettings/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ntd%2Fxsettings/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32354566,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-27T20:07:02.737Z","status":"ssl_error","status_checked_at":"2026-04-27T20:07:00.910Z","response_time":128,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["linux","mmap","opcua","open62541","persistent","real-time","storage"],"created_at":"2024-11-06T01:05:34.399Z","updated_at":"2026-04-27T20:31:59.750Z","avatar_url":"https://github.com/ntd.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"*XSettings* provides a basic persistent storage backend for a specific\nset of variables in [open62541](https://github.com/open62541/open62541)\nbased OPC/UA servers. It is implemented in the simplest way I know of,\ni.e. directly mmap()ing the struct containing all variable values to a\nbinary file. Any time a variable changes, the mapped memory is msync()ed\n**asynchronously**, so this code can be used in real-time contexts.\n\nHow to use\n----------\n\nTo get the introspection data needed, the code heavily leverages the\npreprocessor using the [X-Macro](https://en.wikipedia.org/wiki/X_macro)\ntechnique (hence the X in *XSettings*). This in turn means this project\ncannot be a library: the source code must be embedded in some way into\nyour project.\n\nThe typical way of doing that is:\n\n1. copy `xsettings.c` and `xsettings.h` into your source folder;\n2. define your schema by creating `xsettings-schema.h`;\n3. call the relevant *XSettings* APIs from your code;\n4. integrate your build system accordingly.\n\nRefer to the `demo` folder for a basic example. Actually `UA_Boolean`,\n`UA_Int32`, `UA_UInt32`, `UA_Double` and `UA_String` (up to 255 bytes)\ntypes are implemented.\n\nHow it works\n------------\n\nWhen you call `xsettings_register()`, *XSettings* populates the folder\nyou specified with all the settings you defined in your schema. Their\nlast values will be remembered via the mapped binary file.\n\nWARNING! You must create the binary file backing up your *XSettings*\nschema before using them, otherwise `xsettings_register()` will fail.\nThe following shell session highlights the issue using the demo program\nincuded in this project as an example:\n\n```sh\n$ ./xsettings-demo\n... Failure: status code is BadNotFound\n$ ./xsettings-demo -d\n... Failure: status code is BadNotFound\n$ ./xsettings-demo -c\n... Creating settings\n$ ./xsettings-demo -d\n#define XSTRING_LEN 255\n#define XSETTINGS \\\n    /*NAME     TYPE       DEFAULT   DESCRIPTION */ \\\n    X(Boolean, XBOOLEAN,     true, \"Boolean flag setting\") \\\n    X(Int32,   XINT32,       -123, \"Integer (32 bits) setting\") \\\n    X(UInt32,  XUINT32,       321, \"Unsigned integer (32 bits) setting\") \\\n    X(Double,  XDOUBLE,    -9.876, \"Double floating point setting\") \\\n    X(String,  XSTRING, \"String\", \"String setting, up to 255 chars\") \\\n/* EOF */\n$ ./xsettings-demo\n... TCP network layer listening on ...\n```\n\nDocumentation\n-------------\n\nThere are only 5 public functions.\n\n- `XSettings xsettings_new(const char *file)`\u003cbr\u003e\n  It must be called before any other function, passing the name of the\n  file to be mapped. If that file does not exist, it can be created by\n  a subsequent `xsettings_reset()` call. The resulting opaque pointer\n  must be freed with `xsettings_free()` when done.\n- `void xsettings_free(XSettings xsettings)`\u003cbr\u003e\n  No other *XSettings* function should be called after.\n- `UA_StatusCode xsettings_reset(XSettings xsettings)`\u003cbr\u003e\n  It creates the file to be mapped (or overwrites it) using the default\n  values specified in `xsettings-schema.h`.\n- `UA_StatusCode xsettings_dump(XSettings xsettings)`\u003cbr\u003e\n  It dumps to stdout the contents of the mapped file. The format is\n  purposedly compatible with `xsettings-schema.h`, so you can easily\n  overwrite it to e.g. update the default values.\n- `UA_StatusCode xsettings_register(XSettings xsettings, UA_Server *opcua, UA_NodeId folder)`\u003cbr\u003e\n  The real meat of this project: mmap() the file (so it must exists!)\n  and register all fields found in your schema as\n  [data source](https://www.open62541.org/doc/1.3/server.html#data-source-callback)\n  variables under the `folder` node.\n\nBuilding the demo\n-----------------\n\nTo build the demo program you must have `open62541` preinstalled. Then\nyou can compile it in the usual `meson` way:\n```sh\n$ meson setup build\n...\n$ meson compile -C build\n...\n$ cd build/demo\n$ ./xsettings-demo -c\n... Creating settings\n$ ./xsettings-demo\n...\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fntd%2Fxsettings","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fntd%2Fxsettings","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fntd%2Fxsettings/lists"}