From twoerner at gmail.com Wed Jan 11 08:40:08 2023 From: twoerner at gmail.com (Trevor Woerner) Date: Wed, 11 Jan 2023 11:40:08 -0500 Subject: [cups-devel] flexible datastore proposal Message-ID: <20230111164008.GA9667@localhost> Hi CUPS community, I work for a company that is interested in using CUPS for office printing. One of the areas we would like to focus on is high uptime and high availability. Looking through the CUPS code we're drawn to the "array" class which is used to store several sets of information useful to the CUPS server. Being entirely in-memory, should an instance of CUPS be down or unavailable for any reason, uptime and availability would suffer. One thought we had would be to move all those sets of information currently being stored in the in-memory arrays to a set of database tables. Databases can be replicated and otherwise be made highly distributed and available quite easily. This way if a CUPS server goes down or is unavailable for whatever reason, a new CUPS server could be spun up and simply continue on where the other one left off. It's probably more complicated than that, but at the very least getting that information out of each running process and into a distributed location would be a start. We realize that the current in-memory arrays work perfectly fine for most use-cases. We wouldn't want to force users to use a database. Therefore we're not proposing to replace the array, but rather to add a layer of indirection which, by default, would continue to use the array, but could be pointed at a database should the user so choose. By way of a concrete example, take the cupsArrayAdd() function: 1. My first step would be to go through the CUPS code base and replace each instance of cupsArrayAdd with, say, cupsDatastoreAdd (except in the array test files) 2. Then I would add an optional ./configure time option such as: $ ./configure --with-datastore=Array Currently the only option would be Array, as a first step, but eventually other options could be "Database" or "ODBC". If --with-datastore is not specified, the default is "Array" 3. I create a cups/datastore.h file in which I use C preprocessor statements to: #define _DATASTORE_FN(ds,fn) cups##ds##fn #define DATASTORE_FN(ds,fn) _DATASTORE_FN(ds,fn) #define cupsDatastoreAdd DATASTORE_FN(CUPS_DEFAULT_DATASTORE,Add) which, in this case, simply redefines cupsDatastoreAdd back to cupsArrayAdd. As a result, this has no effect whatsoever on the existing array class or code in the default configuration. None of that code would need to be changed or littered with ugly #ifdefs etc 4. Going forward I then add more options to the --with-datastore ./configure option and write a corresponding set of cupsXXYY functions (where XX specifies the specific datastore and YY are the individual functions such as "Add" etc.) Certain datastore options might also require additional ./configure options or perhaps require a datastore-specific configuration file. For example: $ ./configure --with-datastore=ODBC --database=sqlite This would also generate and use a conf/.conf.in file and/or a conf/.conf.in file to allow the user to specify certificates, authentication, server, port, and other database information. If this (or some variation thereof) sounds interesting to you, we'd like to work on the code changes then work with you to get it upstreamed to your satisfaction. Thoughts? Best regards, Trevor