dm-crypt - submit a bio synchronously - device-mapper

dm-crypt.c has calls to dm_submit_bio_remap to submit a bio asynchronously to the underlying layer
device. I have a requirement for synchronous submission of a bio. When I used submit_bio_wait(bio), the call just hangs forever. If I set REQ_SYNC in bio->bi_opf and set both bio->bi_private and bio->bi_end_io to NULL, and then use dm_submit_bio_remap , I get an OOPS with null pointer dereference.
Can you help me with a proper way to submit the bio synchronously inside dm-crypt.c?

Related

Is it possible to set an Actions submission criteria that prevents submission if an object has more than a certain number of linked objects?

I currently have an action that creates a new link between an object of type A, named OA, and an object of type B, named OB.
Our workflow has a constraint such that any object of type B can at most, be linked to 4 objects of type A. As such, I would like to define a submission criterion in the action such that submission is blocked if OB is already linked to 4 objects of type A.
I couldn't find a straightforward way to do this using the Action configuration UI. How could I accomplish this?
The easiest way to accomplish this would be to turn your action into a function backed action. This would allow you to take the following steps to accomplish the desired functionality:
You can search around to all objects of type A that are linked to OB by writing something like:
// Search around to all objects of type A that are linked to OB
const linkedObjects = OB.objectTypeA.all();
// Now get the number of linked objects
const numLinkedObjects = linkedObjects.length;
Prevent the function from running by throwing a UserFacingError if there are more than 4 linked objects
if (numLinkedObjects >= 4) {
throw new UserFacingError("Objects of type B cannot be linked to more than 4
objects of type A");
}
For reference, here are some relevant pages in Foundry’s documentation:
Creating Function Backed Actions (https://www.palantir.com/docs/foundry/action-types/function-actions-getting-started/#getting-started)
Accessing link types in Functions (https://www.palantir.com/docs/foundry/functions/api-objects-links/#link-types)
Throwing UserFacingErrors from Functions (https://www.palantir.com/docs/foundry/functions/user-facing-error/)
While you can certainly do this in a Function-backed action, the tradeoff is that you won't get up front validation of the criteria, but rather the user will submit the action and then will received a toast showing the UserFacingError text. So while this technically achieves the validation, it is a sub-par user experience compared to disabling the button with a message or otherwise catching the condition upstream of the action itself in the workflow.
An alternative, iff you're using the action exclusively through Workshop, (this won't work if you want the action to "stand alone" in object explorer), you can create an object set variable that holds the result of the search around and pass that in as a hidden parameter to the Action. You can then set up the Action submission criteria as normal to check the length of that parameter and provide a message back to the user. You can also use that information in the app itself to, for example, conditionally show or hide some other workflow for the condition.
If you take this approach, make sure to add the hubble-oe:hide-action typeclass to one of the object parameters in the Action Form configuration so that the Action doesn't show up where users could use it through Object Explorer.

Use getBulkProperties2 within userFunction to speed up performance

I am currently querying the property database through getBulkProperties2. The IDs for this query I get from executing a userFunction through executeUserFunction that runs bruteForceFind on the db.
The getBulkProperties2 call takes about 40-50 seconds on some slower laptops within our company. The whole Vue app and UI freezes, due to the nature of single-threaded JS. I have tried to move the bulk call to a WebWorker, but you can't pass a model to the WebWorker because the model object references itself, and therefore can't be serialized (circular reference).
The ideal solution would be executing a bulk call within a userFunction, as it is executed on a WebWorker by design. I don't see a way in the documentation (or the source code that I decompiled) to do something like this.
What is the recommended way to execute a bulk call within a userFunction?
You can call pdb.getObjectProperties within the userFunction. See https://forge.autodesk.com/en/docs/viewer/v7/reference/globals/PropertyDatabase/#getobjectproperties-dbid-propfilter-ignorehidden-propignored
const ignoreHidden = false;
pdb.getObjectProperties( dbId, ['myAttributeName'], ignoreHidden );

How can I run a command from inside another stack command?

I have a callback handler in a stack that looks for telemetry data. When it gets some, I parse it and then want to save it. However, to save it requires other functions and commands in the same stack.
I could put it on the card, but where? I use the openCard end openCard and that's about it in the card.
The stack has all the functions and commands I need. There's no button to press to run the save code - I need it to run automatically.
How can I put the chunk of code on the card and then have the stack 'call it'?
I know how to call commands from the card, but not from the stack.
Generically, you simply call either a command handler or a function handler in-line:
on mouseUp -- a "main" handler
doSomething -- a command handler
dosomethingElse -- another command handler
put doYetAnotherThing(paramList) into field 1 -- a function handler
end mouseUp
on doSomething
well, do something
end doSomething
on doSomethingElse
you get the picture
...
Try making a simple main handler that does silly trivial things for each of the three "subRoutine" calls above. You will be an expert in a matter of hours.
The placement of the three has to be managed. Generally, they reside in the script where the main handler lives. But they can be anywhere in LC.
If you want to call a handler in a card (or any other control) from another script, you can use one of the following commands:
dispatch "command" to control with param1, param2, …
send "command" to control [in time]
put value(command, control) into tResult
Dispatch happily continues even if the command isn't handled by the control. You can check that of course.
Send has the advantage that you can schedule the sending forwards in time, but is a bit harder if you want to also send some parameters.
Value is good candidate if you call a function and want the result back.
Note that ""openCard" and "preOpenCard" messages can be trapped and worked in the stack script, as long as there are no such handlers in the card script. And even if there are, you can "pass" each message after the card script handler is done with it";
Try creating a command on the stack that is called every X times while the user is on that card. This command must be called to itself and to the other manipulators that you use to obtain the data. This same manipulator will be in charge of saving the data.
# Code on the card
local sTelemetryData
on openCard
// If the card belongs to the pile where all the telemetry is or if this pile is a library.
getTelemetryData
// otherwise you will have to call the getTelemetryData command. You can use send, disparsh, or call.
// call "getTelemetryData" to stack "stack name"
end openCard
# Code on the stack
constant kTime = 100
local sPendingMessageID
on getTelemetryData
if the short name of this card is not "TelemetryData"
then exit getTelemetryData
if sPendingMessageID is a number
then cancel sPendingMessageID
// call the commands and functions that look up the telemetry data.
// The data must be stored in the sTelemetryData variable to save it and at once use this variable as a flag
if sTelemetryData is not empty then
// The data is sent to be saved
end if
put empty into sTelemetryData
send "getTelemetryData" to me in kTime milliseconds
put the result into sPendingMessageID
end getTelemetryData

how to catch event in codes after linking events in an array of string inside “events” properties of form object variable in dynamic 4D form?

It's easy to catch events from 4D object's methods of 4D binary form (traditional 4D form) but didn't find any clue to do this in the json dynamic form.
I already gave a try with some 4D commands (CALL FORM, CALL WORKER or POST OUTSIDE CALL) as well to install a project method for a form side by side in a new process inside a loop where I handled events inside that project method. But couldn't get around it. Also I couldn't find any solution/example for this in kb or 4D blog or anywhere.
So any example or database template would be more helpful.
Ravi,
Simply string them in an array named "events".
The docs are your friend for things like this: 4D Manual/Dynamic Forms#Events
The "events" property accepts a JSON array (collection) of strings or
numbers. To call an event, enter the event's name or value (see form
event constant values). For exemple, "events":["onLoad"]) or
"events":[1]
I don't know if you can mix the literal and numeric references. I would expect so but haven't actually tested that.
Edit:
Ravi, if by "catch events in code" you mean have the form you've dynamically created respond to them then you will need to include the name of a project method in the "method" tag. You can't just write some code into an object when you build it dynamically, like you can in regular 4D, but you can call a project method. In that method you can use a Case of statement to test the Form event function to determine which event fired and respond appropriately.
You can't pass parameters to this method. But you can use Object get name or Object get pointer commands to determine the particular object that called it.
For example, let's say I include myMethod as the method. The code for myMethod might look like this:
Case of
:(Form event=On Clicked) // on Clicked is a 4D constant
// do something
:(Form event=on Data Change)
// do something else
End case
Or
Case of
:(Object get name(Object current)="myButton")
Case of
:(Form event=on Clicked)
...
End case
:(Object get name(Object current)="anotherName")
Case of
:(Form event=on Clicked)
...
End case
End case
This illustrates two approaches: 1) you write a separate method for each object or 2) write a single method and determine which object called it. I prefer #2 but that's strictly my opinion.

Read all input in event handler?

Is the readable file event triggered by a channel becoming readable, or by it being readable? In a file event handler, do I have to read all available input to get a new event triggered in the future? Or can I read only 1 character and return, and if there was more input, my handler will automatically be called again directly? Or not directly, but rather put at the end of the event queue, so this would be the preferred way to do it (maybe not just 1 character but for example 1 line) to prevent one stream from blocking the entire program?
It is triggered by a channel being readable, so you can read only a part of input (or read nothing occasionally, being sure that the handler will be called again). However, reading all available input is better for performance (not necessarily all available bytes: if you read line by line, do gets until it returns -1 for fblocked condition).
The sign of input being exhausted is the true value of [fblocked $channel]. That's why the use case with gets and incomplete line of input is possible: even though the channel is technically readable, just not getsable, the event doesn't fire again until new data arrive.