Perl, SVN::Hooks, and SVN::Hooks::Notify - perl

Can anyone tell me offhand if SVN::Hooks::Notify's NOTIFY and NOTIFY_DEFAULTS blocks replace (or rather, stop the evaluation of) the POST_COMMIT block? My PRE_COMMIT block works fine, and my existing NOTIFY/NOTIFY_DEFAULTS blocks process just fine.
However, nothing I have under the POST_COMMIT block fires at all... and yes, hooks/post-commit is linked to the script. The perdocs for svn::hooks::notify state that it runs within POST_COMMIT, but I would prefer to do some extra processing first before kicking off a notification email (eg, inserting pertinent information into a db table for later use).

The NOTIFY block sets a post-commit hook; there is no separate hook for notify.
And as far as I can tell from the SVN::Hook source, you can have set as many of a given hook as you want, and they will run in the order you add them in. So you may need to do e.g.:
use SVN::Hooks;
BEGIN {
POST_COMMIT { ... }
}
use SVN::Hooks::Notify;
to have your other hook come before the notify hook.

Related

How I can match bags an passenger in the reclaim area?

I'm simulating a security control process, and i can't do that each passenger pickup their baggage. I have tried with Match, Combine, Pickup, but I still can't execute the commands correctly.
I've created the follow flowchart, and the problem is in the wReclaimPax, pickup and wReclaimBags blocks (you can see them in the picture).
https://ibb.co/v3V57Tm
I saw this link Anylogic - Combined multiple items back to original owner to understand something, but I still need help.
I've created 3 functions:
isMatch:
if(equipaje.pasajeroLink.equals(pasajero.equipajeLink)){
return true;
}
return false;
paxBags:
for(int i=0;i<wait.size();i++){
Pasajero p=(Pasajero)wait.get(i);
if(isMatch(p,bag))
return p;
}
return null;
bagsPax:
for(int i=0;i<wait.size();i++){
Equipaje e=(Equipaje)wait.get(i);
if(isMatch(pasajero,e))
return e;
}
return null;
Assumed context
You haven't really explained how your code is related to your process but I'm assuming the following:
Because this is luggage-retrieval, you want to ensure that a passenger
agent (Pasajero) only enters the Pickup block (representing taking bag from
carousel) when his bag (Equipaje agent by the look of it) has
arrived into the wReclaimBag Wait, and been released from it to
queue4 Queue.
For this you need triggers (to remove agents from Wait blocks) when
either a passenger (Pasajero) arrives in wReclaimPax Wait, or a bag (Equipaje) arrives
in the wReclaimBag Wait (because you don't know whether the passenger or their bag will get to their respective Wait blocks first).
So your paxBags function is called in on-entry action of the wReclaimBag Wait, and your bagsPax function in the on-entry action of the wReclaimPax Wait.
Possible problems with current approach
Without knowing more of your model it's hard to say but problems I can think of based on what you've supplied are:
Your functions return the Pasajero or Equipaje if there is one that matches. Your match check relies seemingly on bidirectional connections (links) between Pasajero and Equipaje. Obviously if they're not setup properly the model won't work and, if you're using bidirectional connections you shouldn't need to check both ends.
Your functions need calling so that, if they return non null, they then free the matching agent from the other Wait block, and free themselves. Are you doing that? Without checking, there may be issues with calling free for yourself as you enter a Wait block (since this kind of depends on AnyLogic internals as to whether you count as being 'in' the block at this stage and can be freed). If this seems to be the problem you could create a timeout 0 dynamic event instance to do the free so that you're not doing it within the scope of the on-enter action.
Your pickup block (since it's been setup so that the entering agent will always want to pickup the first agent (Equipaje) in queue4) just needs to be set as waiting for quantity 1 (though see below).
If you've done all this the most likely problem is that the underlying events ordering of AnyLogic is affecting things. When you free agents I'm fairly sure the freeing actually happens in a timeout 0 event scheduled under-the-covers. So it may be that the passenger arrives at the Pickup before their Equipment arrives in queue4 though, if you set the Pickup to be "Exact quantity (wait for)", with quantity of 1, it should handle that.
The animation of the process (numbers in/out/within each block and details when clicking on blocks) should also help you debug what is going wrong; e.g., are bags being left in the Wait when they should have been released, etc.
P.S. With this kind of thing you should always create a minimal example model to make testing the issue/solution easier (and for sharing in help forums such as this where the rest of the complexity of your model is irrelevant). Often you find the problem 'naturally' in the process of trying to construct such a model that reproduces your problem in a minimal way.

SugarCrm: How to find caller of a logic hook

Suppose we have a before save logic hook on leads, now How we can detect if this called logic hook is:
a crm user who is saving a lead form
is a lead captured from on of entry points
is a save triggered by soap calls
is a workflow which is modifying lead fields
is called because of csv import
...
I have checked some of the behaviors, it seems logic hooks are not called on workflows (at least in my test)
Also I hope to figure out this issue in global variables, but there are a lot of global variables.
So How I can detect caller of a logic hook ?
The best way that I found to figure this out is to add a:
$GLOBALS['log']->fatal(print_r($_REQUEST,true));
To your logic hook. Then test each scenario that you need to account for and see how the request differs. Also check $_SESSION. You'll be able to find a few things that you can depend upon for your logic.
That's what I did eventually. I share some of my observations so it may help the others (these are statements, based on the case some of them may applies)
in third party entry point calls $_SESSION is empty, in direct entry point calls is not so. Also in rest calls session is not empty.
rest calls have $_REQUEST[rest_data] and others don't.
entry point calls have $_REQUEST[entryPoint] available in the array
global $current_user is available, but the id var ($current_user->id) is a string only in the case a user is submitting a form in crm.
in inline editing $_REQUEST[action] is equal to saveHTMLField
in user calls $_SERVER[HTTP_USER_AGENT] is available and in other calls it is not.
In a simple case this code shows how to detect user calls:
$trigger = false;
global $current_user;
if (!isset($current_user->id) || !strlen($current_user->id) > 2)
$trigger = true;
if ($trigger) {
//#My Custome Code
}

API function to add an Action to an Event or Schedule?

I need to add an Action to a Schedule object that is being created through the API. There are documented interfaces to set almost all the options except the Action. How are Actions attached to these Objects?
When I attempt to programmatically add a new event, read from a separate configuration file, to a Schedule object I get errors stating that the Schedule has already been initialized and that I must construct a new object and add its configuration manually. I can do most of that using the available Schedule API. I can set up everything about the Schedule except the Action code.
The Schedule is used in a Process Model. Looking at the model in the Java editor, I see the code I'm trying to replicate via the API in a function that looks like this:
#Override
#AnyLogicInternalCodegenAPI
public void executeActionOf( EventTimeout _e ) {
if ( _e == _fuelDeliverySchedule_Action_xjal ) {
Schedule<Integer> self = this.fuelDeliverySchedule;
Integer value = fuelDeliverySchedule.getValue();
logger.info("{} received {} pounds of fuel", this.getName(), this.fuelDeliverySchedule.getValue());
this.fuelAvailablePounds += fuelDeliverySchedule.getValue();
;
_fuelDeliverySchedule_Action_xjal.restartTo( fuelDeliverySchedule.getTimeOfNextValue() );
return;
}
super.executeActionOf( _e );
}
Maybe I can use something like this to create my own action function, but I'm not sure how to make the Scheduled event use it.
Thanks,
Thom
[Edited (expanded/rewrote) 03.11.2014 after more user detail on the context.]
You clarified the context with
When I attempt to programatically add "a thing that happens", read
from a separate configuration file, to a Schedule object I get errors
stating that the Schedule has already been initialized and that I must
construct a new object and add its configuration manually. I can do
most of that using the available Schedule API. I can set up everything
about the Schedule except the Action code.
(You might want to edit that into the question... In general, it's always good to explain the context for why you're trying to do the thing.)
I think I understand now. I presume that your config file contains scheduling details and, when you say you were trying to "add a thing that happens" (which errored), you meant that you were trying to change the scheduling 'pattern' in the Schedule. So your problem is that, since you couldn't adjust a pre-existing schedule, you had to instantiate (create) your own programmatically, but the Schedule API doesn't allow you to set the action code (as seen on the GUI schedule element).
This is a fairly involved solution so bear with me. I give a brief 'tl;dr'
summary before diving into the detail.
Summary
You can't programmatically code an AnyLogic action (for any element) because that would amount to
dynamically creating a Java class. Solving your problem requires recognising
that the schedule GUI element creates both a Schedule instance and a
timeout event (EventTimeout) instance to trigger the action. You can therefore create these two elements explicitly yourself (the former dynamically). The trick is to reset the timeout event when you replace the Schedule instance (to trigger at the next 'flip' point of the new Schedule).
[Actually, from your wording, I suspect that the action is always the same but, for generality, I show how you could handle it if your config file details might want to change the nature of the action as well as those of the scheduling pattern.]
Detail
The issue is that the GUI element (confusingly) isn't just a Schedule instance
in terms of the code it generates. There is one (with the same name as that of
the GUI element), which just contains the schedule 'pattern' and, as in the API,
has methods to determine when the next on/off period (for an on/off schedule) occurs. (So
it is kind of fancy calendar functionality.) But AnyLogic also generates a
timeout event to actually perform the action; if you look further in the code
generated, you'll see stuff similar to the below (assuming your GUI schedule is called
fuelSchedule, with Java comments added by
me):
// Definition of the timeout event
#AnyLogicInternalCodegenAPI
public EventTimeout _fuelSchedule_Action_xjal = new EventTimeout(this);
// First occurrence time of the event as the next schedule on/off change
// time
#Override
#AnyLogicInternalCodegenAPI
public double getFirstOccurrenceTime( EventTimeout _e ) {
if ( _e == _fuelSchedule_Action_xjal ) return fuelSchedule.getTimeOfValue() == time() ? time() : fuelSchedule.getTimeOfNextValue();
return super.getFirstOccurrenceTime( _e );
}
// After your user action code, the event is rescheduled for the next
// schedule on/off change time
_fuelSchedule_Action_xjal.restartTo( fuelSchedule.getTimeOfNextValue() );
i.e., this creates an event which triggers each time the schedule 'flips', and performs the action specified in the GUI schedule element.
So there is no action to change on the Schedule instance; it's actually related to the EventTimeout instance. However, you can't programmatically change it there (or create a new one dynamically) for the same reason that you can't change the action of any AnyLogic element:
this would effectively be programmatically
creating a Java class definition, which isn't possible without very specialised
Java code. (You can create Java source code in a string and
dynamically run a Java compiler on it to generate a class. However, this is very
'advanced' Java, has lots of potential pitfalls, and I would definitely not
recommend going that route. You would also have to be creating source for a user subclass
of EventTimeout, since you don't know the correct source code for AnyLogic's proprietary EventTimeout class, and this might change per release in any case.)
But you shouldn't need to: there should be a strict set of possible actions that your config file can contain. (They can't be arbitrary Java code snippets, since they have to 'fit in' with the simulation.) So you can do what you want by programmatically creating the Schedule but with a GUI-created timeout event that you adjust accordingly(assuming an off/on schedule here and that there is
only one schedule active at once; obviously tweak this skeleton to your needs
and I haven't completely tested this in AnyLogic):
1. Have an AnyLogic variable activeAction which specifies the current active
action. (I take this as an int here for simplicity, but it's better to use a
Java enum which is the same as an AnyLogic 7 Option List, and can just be
created in raw Java in AnyLogic 6.)
2. Create a variable in the GUI, say called fuelSchedule, of type Schedule but with initial value null. Create a separate timeout event, say called fuelScheduleTrigger, in User Control mode, with action as:
// Perform the appropriate action (dependent on activeAction)
doAppropriateScheduleAction();
// Set the event to retrigger at the next schedule on/off switch time
fuelScheduleTrigger.restartTo(fuelSchedule.getTimeOfNextValue());
(Being in User Control mode, this event isn't yet triggered to initially fire, which is what we want.)
3. Code a set of functions for each of the different action alternatives; let's say
there are only 2 (fuelAction1 and fuelAction2) here as an example. Code
doAppropriateScheduleAction as:
if (activeAction == 1) {
fuelAction1();
}
else if (activeAction == 2) {
fuelAction2();
}
4. In your code which reads the config file and gets updated schedule info.
(presumably run from a cyclic timeout event or similar), have this replace
fuelSchedule with a new instance with the revised schedule pattern (as you've
been doing), set activeAction appropriately, and then reset the timeout event to
the new fuelSchedule.getTimeOfValue() time:
[set up fuelSchedule and activeAction]
// Reset schedule action to match revised schedule
fuelScheduleTrigger.restartTo(fuelSchedule.getTimeOfNextValue());
I think this works OK in the edge case when the new Schedule had its next 'flip' at the time
you set it up. (If you restart an event to the current time, I think it schedules an event OK at the current time which will occur next if there are no other events also scheduled for the current time; actually, it will definitely occur next if you are using a LIFO simultaneous-time-scheduling regime---see my blog post.)
Alternative & AnyLogic Enhancement
An alternative is to create a 'full' schedule in the GUI with action as earlier. Your config file reading code can replace the underlying Schedule instance and then reset the internal AnyLogic-generated timeout event. However, this is less preferable because you are relying on an internally-named AnyLogic event (which might also change in future AnyLogic releases, breaking your code).
AnyLogic could help this situation by adding a method to the Schedule API that gets the related timeout event; e.g., getActionTriggeringEventTimeout(). Then you would be able to 'properly' restart it and the Schedule API would make much clearer that the Schedule was always associated with an EventTimeout that did the triggering for the action.
Of course, AnyLogic could also go further by changing Schedule to allow scheduling details to be changed dynamically (and internally handling the required updates to the timeout event if it continued to be designed like that), but that's a lot more work and there may be deeper technical reasons why they wanted the schedule pattern to be fixed once the Schedule is initialised.
Any AnyLogic support staff reading?

why script can not be suspended/paused?

I wrote this simple AHK script, it's working. But rightclick systray icon- suspend/pause, it just still keep working. Is it because of something in my code? or about win7 x64?
#Persistent
return
OnClipboardChange:
WinGetActiveTitle, OutputVar
IfWinExist, collect.doc
{
WinActivate ; use the window found above
send,^v
send,{Enter}
winactivate,%Outputvar%
}
else
tooltip,need collect doc,400,400
Sleep 100
return
Both Pause and Suspend are not meant to block automatically called subroutines like OnClipboardChange or GuiClose. Pause merely blocks the current thread, which means that every newly created thread will still run, and a clipboard change does create a new thread. Ergo, Pause can't block it.
In such cases, you need to implement an own piece of logic within the "event subroutine" that checks some kind of state.
Going with your premise to make the functionality depend on the paused state, a fairly easy way would be to check for the built-in A_IsPaused:
OnClipboardChange:
if(A_IsPaused) {
return
}
msgbox, 'sup?
return
There are certainly many ways to implement this. You could also define your own hotkey to activate/deactivate/toggle a custom state.
P.S:
Activating a window only to paste some text seems a bit unnecessary and bothersome to me; have a look at the Control commands (e.g. Control, EditPaste) or access Word via COM. Depending on what you do, I believe directly writing to a text file and/or in-memory storage might be a better alternative to a running Word instance anyway.
P.P.S:
You might want to be careful with such a negligent clipboard logger. I assume you don't want every kind of data (e.g. passwords) showing up there.

Delphi: App initialization - best practices / approach

I run into this regularly, and am just looking for best practice/approach. I have a database / datamodule-containing app, and want to fire up the database/datasets on startup w/o having "active at runtime" set to true at design time (database location varies). Also run a web "check for updates" routine when the app starts up.
Given TForm event sequences, and results from various trial and error, I'm currently using this approach:
I use a "Globals" record set up in the main form to store all global vars, have one element of that called Globals.AppInitialized (boolean), and set it to False in the Initialization section of the main form.
At the main form's OnShow event (all forms are created by then), I test Globals.AppInitialized; if it's false, I run my "Initialization" stuff, and then finish by setting Globals.AppInitialized := True.
This seems to work pretty well, but is it the best approach? Looking for insight from others' experience, ideas and opinions. TIA..
I generally always turn off auto creation of all forms EXCEPT for the main form and possibly the primary datamodule.
One trick that I learned you can do, is add your datamodule to your project, allow it to auto-create and create BEFORE your main form. Then, when your main form is created, the onCreate for the datamodule will have already been run.
If your application has some code to say, set the focus of a control (something you can't do on creation, since its "not visible yet") then create a user message and post it to the form in your oncreate. The message SHOULD (no guarantee) be processed as soon as the forms message loop is processed. For example:
const
wm_AppStarted = wm_User + 101;
type
Form1 = class(tForm)
:
procedure wmAppStarted(var Msg:tMessage); message wm_AppStarted;
end;
// in your oncreate event add the following, which should result in your wmAppStarted event firing.
PostMessage(handle,wm_AppStarted,0,0);
I can't think of a single time that this message was never processed, but the nature of the call is that it is added to the message queue, and if the queue is full then it is "dropped". Just be aware that edge case exists.
You may want to directly interfere with the project source (.dpr file) after the form creation calls and before the Application.Run. (Or even earlier in case.)
This is how I usually handle such initialization stuff:
...
Application.CreateForm(TMainForm, MainForm);
...
MainForm.ApplicationLoaded; // loads options, etc..
Application.Run;
...
I don't know if this is helpful, but some of my applications don't have any form auto created, i.e. they have no mainform in the IDE.
The first form created with the Application object as its owner will automatically become the mainform. Thus I only autocreate one datamodule as a loader and let this one decide which datamodules to create when and which forms to create in what order. This datamodule has a StartUp and ShutDown method, which are called as "brackets" around Application.Run in the dpr. The ShutDown method gives a little more control over the shutdown process.
This can be useful when you have designed different "mainforms" for different use cases of your application or you can use some configuration files to select different mainforms.
There actually isn't such a concept as a "global variable" in Delphi. All variables are scoped to the unit they are in and other units that use that unit.
Just make the AppInitialized and Initialization stuff as part of your data module. Basically have one class (or datamodule) to rule all your non-UI stuff (kind of like the One-Ring, except not all evil and such.)
Alternatively you can:
Call it from your splash screen.
Do it during log in
Run the "check for update" in a background thread - don't force them to update right now. Do it kind of like Firefox does.
I'm not sure I understand why you need the global variables? Nowadays I write ALL my Delphi apps without a single global variable. Even when I did use them, I never had more than a couple per application.
So maybe you need to first think why you actually need them.
I use a primary Data Module to check if the DB connection is OK and if it doesn't, show a custom component form to setup the db connection and then loads the main form:
Application.CreateForm(TDmMain, DmMain);
if DmMain.isDBConnected then
begin
Application.CreateForm(TDmVisualUtils, DmVisualUtils);
Application.CreateForm(TfrmMain, frmMain);
end;
Application.Run;
One trick I use is to place a TTimer on the main form, set the time to something like 300ms, and perform any initialization (db login, network file copies, etc). Starting the application brings up the main form immediately and allows any initialization 'stuff' to happen. Users don't startup multiple instances thinking "Oh..I didn't dbl-click...I'll do it again.."