Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Problem with application-variables - CFLOCK?

New Here ,
May 13, 2008 May 13, 2008
Hi,

i have a problem with my application. It is a multi-user application with 100 parallel-users and CFMX 7.

The problem wich occures is with application variables. These are mainly structs wich get filled onApplicationStart(). The problem is, that the variables suddenly disappear, they are empty.

I have read about CFLock and found out, that it is necesseary to use cflock. And i found out, that onApplicationStart does correct locking automatically. That is where i do not understand the problem. The variables get intialized correctly and in further they only get read-access. Why can they be corrupted?

My other question about that is, wheather i need cflock for all Read-Access to Application and Session-Variables, even if there happens no writing to the variables?

Best Regards,
Andreas
625
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
May 13, 2008 May 13, 2008
Without seeing any of your code, it's a bit hard to make an informed
comment on much of this.

Post your onApplicationStart() method, and perhaps any other code in the
app that has the application variables on the left-hand-side of any
assignment expressions.

If your shared-scope usage is simple

<cfset application.x = y>

Then there's unlikely to be a need to lock it.

If, however, the expression is more like:

<cfset application.x = someLongRunningMethod()>

Or if the code that creates the application-scoped variable is
self-referential and is spread over multiple statements, then you might
need to lock the assignment operation to prevent "race conditions" (google
it).

--
Adam
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
May 13, 2008 May 13, 2008
Hi Adam,

thanks for your answer and help.

My Application.cfc looks like this:

<cffunction name="onApplicationStart" returntype="void">
<cfscript>
Application.DSN="cargorent";
Application.DBT="Oracle80";
// create the translation object
Application.oTrans = createObject( "component", "cargorent.cfc.crtranslate" );
Application.oTrans.init();
// create the PopUp Object
Application.oPopUp = createObject( "component", "cargorent.cfc.crPopUp" );
</cfscript>
<cfinclude template="Login/computer_setting/setting.cfm">
<cfinclude template="Login/IniValues.cfm">
<cfinclude template="Login/Version.cfm"><!--- This includes the Version information --->
<cfinclude template="Login/Lists.cfm">
</cffunction>


the "problem-code" is in Lists.cfm. In this CFM, nearly 20 querys will be executed and afterwards converted into structs. This is done like this:


// --- Code from Lists.cfm --- Called by onApplicationStart()
<cfquery name="qToStatus" datasource="#Application.DSN#" dbtype="#Application.DBT#">
SELECT td_text, td_internal_text FROM textual_definition
WHERE td_type = 'TOUR_STATUS' ORDER BY td_key1
</cfquery>
<cfscript>
application.TourStatus = ArrayNew(1);
for( i=1; i lte qToStatus.RecordCount; i=i+1 )
{
application.TourStatus = StructNew();
application.TourStatus
.text = qToStatus.TD_TEXT ;
application.TourStatus
.value = qToStatus.TD_INTERNAL_TEXT ;
}
</cfscript>
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
May 13, 2008 May 13, 2008
> the "problem-code" is in Lists.cfm. In this CFM, nearly 20 querys will be
> executed and afterwards converted into structs. This is done like this:

Right. And what's the specific error?

Have you trapped the error, done a <cfdump> of the application scope and
checked to see if it's the whole lot going awry, or just some values?

> // --- Code from Lists.cfm --- Called by onApplicationStart()
> <cfquery name="qToStatus" datasource="#Application.DSN#"
> dbtype="#Application.DBT#">

As far as I know, datasource and dbtype are mutually exclusive attributes
in a <cfquery>, since CF5. I doubt this will be part of your issue, but
it's worth noting.


> application.TourStatus = ArrayNew(1);
> for( i=1; i lte qToStatus.RecordCount; i=i+1 )
> {
> application.TourStatus = StructNew();
> application.TourStatus
.text = qToStatus.TD_TEXT ;
> application.TourStatus
.value = qToStatus.TD_INTERNAL_TEXT ;
> }

I think as it stands, it'd be OK how it's being called from
OnApplicationStart(). I presume only the first request for a given
application will ever enter that method's body.


However is there anywhere else this could could be being included? I'm
guessing "yes", otherwise you wouldn't have it in an include file.

What happens when two separate requests hit this code?

Request 1 could get to - for example - the 20th iteration of this loop;
then request 2 comes along and blows the array away and starts populating
it again. Now you have two requests populating the array at the same time.

This is what I was referring to as a race condition. Did you google it?
;-)

If that code is being called anywhere other than via onApplicationStart(),
it needs to be exclusively locked, and - for good measure - reads to it
should be read-locked.

--
Adam
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
May 14, 2008 May 14, 2008
> Right. And what's the specific error?
The specific error is that the following error message will be outputted:
“The element of position 2, of dimension 2, of an array object used as part of an expression, cannot be found.”
The array is in this case the struct.

> Have you trapped the error, done a <cfdump> of the application scope and
> checked to see if it's the whole lot going awry, or just some values?
I have not used cfdump for it, because the server had to be immediately restarted for our customers. But i think, that it is not completely empty, because the index runs to pos2 of dimenstion2.


> However is there anywhere else this could could be being included? I'm
> guessing "yes", otherwise you wouldn't have it in an include file.
No, the code is only called from onApplicationStart(). Therefore I don´t believe in an race conditions problem.

But I have found another unclear question. The application.cfc has a method onRequestStart() which proofes wheater the user is logged in. If he isn´t, then another page will be called. What happens in this case ? Will onApplicationStart() be called before? Or only if onRequestStart() returns true?

Here is the code from onRequestStart()
<cffunction name="onRequestStart" returntype="boolean">
<cfargument name="Requestedpage" required="yes" />
<cfscript>
var lFile = "/cargorent/Login.cfm";
var iPosn = ListFindNoCase( lFile, Arguments.Requestedpage );
if( iPosn gt 0 )
return true;

if( NOT IsDefined( "session.user.Loginname" ) or session.user.Loginname eq "" )
{
WriteOutput( "<p><p> The current user is no longer valid, please log in again.</p></p>" & chr(10) & chr(13) );
WriteOutput( "<script language=""javascript"">parent.location = "" http://" & CGI.HTTP_HOST & "/Login/Login.cfm"";</script>" );
return false;
}

return true;
</cfscript>
</cffunction>
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
May 14, 2008 May 14, 2008
> ?The element of position 2, of dimension 2, of an array object used as part of
> an expression, cannot be found.?
> The array is in this case the struct.

Well, OK, that could be a problem. Arrays are not structs: they are two
different things, are not interchangeable, and have completely different
sets of functions to utilise them. You cannot treat a struct as an array.
If CF is claiming your "struct" is an array, then it actually *is* an
array, not a struct.

What's the line of code which is generating that error?

I suppose one could get this error if you have an array of structs thus:

myArray .key1
myArray
.key2

(etc)

and you're trying to reference it with a numeric key rather than by key
name, eg:

myArray

When n is an integer value, rather than a string (which corresponds to the
name of the key).


> > Have you trapped the error, done a <cfdump> of the application scope and
> > checked to see if it's the whole lot going awry, or just some values?
> I have not used cfdump for it, because the server had to be immediately
> restarted for our customers. But i think, that it is not completely empty,
> because the index runs to pos2 of dimenstion2.

So does this not happen in your dev / testing environment?


> Will
> onApplicationStart() be called before? Or only if onRequestStart() returns true?

I would ass-u-me that the application one would be called before the
request one. It's pretty easy for you to test this though, I should think?

(Sorry: for reasons beyond the scope of this conversation, we're still
forced to use Application.cfm in our software, so I've only a passing
knowledge of how Application.cfc works).


> Here is the code from onRequestStart()
> <cffunction name="onRequestStart" returntype="boolean">
> <cfargument name="Requestedpage" required="yes" />
> <cfscript>
> var lFile = "/cargorent/Login.cfm";
> var iPosn = ListFindNoCase( lFile, Arguments.Requestedpage );
> if( iPosn gt 0 )
> return true;
>
> if( NOT IsDefined( "session.user.Loginname" ) or session.user.Loginname eq
> "" )
> {
> WriteOutput( "<p><p> The current user is no longer valid, please log in
> again.</p></p>" & chr(10) & chr(13) );
> WriteOutput( "<script language=""javascript"">parent.location = "" http://"
> & CGI.HTTP_HOST & "/Login/Login.cfm"";</script>" );
> return false;
> }
>
> return true;
> </cfscript>
> </cffunction>

One thing I will say here is that I really think you should be separating
your processing from your display. A function should do processing. it
should pass that processing back to a CFM template which should handle
whatever needs to be displayed on the browser. Although that's nowt to do
with your current issue.

--
Adam
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
May 14, 2008 May 14, 2008
Hi,

thanks for your help.

I was wrong, the struct is actually an array with an struct at the End. It is generated by this code:

application.aType = arrayNew(2);
iQuery = 1;
bEnd = false;
for( y=1; y lte qMaxFahrzeugtyp.maxOrdnung; y=y+1 )
{
for( x=1; x lte qMaxFahrzeugtyp.maxSpalte; x=x+1)
{
application.aType = StructNew();
if( iQuery lte qFahrzeugtyp.Recordcount and qFahrzeugtyp.FZTYP_SPALTE[iQuery] eq x AND qFahrzeugtyp.FZTYP_ORDNUNG[iQuery] eq y)
{
application.aType.name = qFahrzeugtyp.FZTYP_Fahrzeugtyp[iQuery];
application.aType.id = qFahrzeugtyp.FZTYP_ID[iQuery];
application.aType.code = qFahrzeugtyp.FZTYP_KUERZEL[iQuery];
iQuery = iQuery + 1;
}
else
{
application.aType.name = "";
application.aType.id = 0;
application.aType.code = "";
}
}



the Code where the Problem happend is:


function FindVehicleTypeCode( iID )
{
var stCode = "";
for( c=1; c lte ArrayLen( application.aType[1] ); c=c+1 )
{
for( o=1; o lte ArrayLen( application.aType ); o=o+1 )
{
if( application.aType.ID eq iID )
{
stCode = application.aType.code;
break;
}
}
}
return( stCode );
}

>>So does this not happen in your dev / testing environment?
No, the error does only happen once or twice a week on the productive server and not always with the same variable.
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
May 14, 2008 May 14, 2008
> function FindVehicleTypeCode( iID )
> {
> var stCode = "";
> for( c=1; c lte ArrayLen( application.aType[1] ); c=c+1 )
> for( o=1; o lte ArrayLen( application.aType ); o=o+1 )

You seem to have a logic error here.

It should be like this:
> for( o=1; o lte ArrayLen( application.aType ); o=o+1 )
> for( c=1; c lte ArrayLen( application.aType ); c=c+1 )

From what you've given us, there's nothing to say that the length of
application.aType[1] is going to be the same as application.aType[2] or
application.aType in general, so you can't simply go off the length for
the first array to determine how many elements their are in each of the
first dimension's elements second-dimension array.

Also, you should be VARing all the variables you use local to a function,
btw.

Can I suggest you wrap the erroring code in a try/catch block, and in the
catch use <cfsavecontent> to save the output of a dump of the relevant
variables, then write that to file (and then rethrow the error, so
processing stops).

Capture the info, have a look at it, the answer could well present itself.

I suspect it's the error I mentioned above.

--
Adam
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
May 14, 2008 May 14, 2008
yes, onApplicationStart() method runs before onRequestStart().

furthermore, it runs ONLY ONCE when your app receives the first request
after it has timed out/been restarted.

onApplicationStart() will NOT run again until the server is restarted,
or the application times out (no new requests received during time
period specified in CF Admin or in Application.cfc), or you call the
method explicitly in your code.

Azadi Saryev
Sabai-dee.com
http://www.sabai-dee.com/
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
May 15, 2008 May 15, 2008
Thanks for your Help !

this part of code seems to be a problem. Maybe this is the reason, why the struct sometimes crashes. This problem is really strange, cause it does not occure always. There are a lot of days, without this problem. I will fix this and hope the problem is solved.

>>Also, you should be VARing all the variables you use local to a function,
btw.

what is a local function ?

Greetings and thanks for your help,
Andreas
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
May 15, 2008 May 15, 2008
LATEST
> >>Also, you should be VARing all the variables you use local to a function,

>
> what is a local function ?

The variable is local, not the function ;-)

Read this -
http://livedocs.adobe.com/coldfusion/8/htmldocs/buildingComponents_29.html
- esp the last section on the VAR keyword.

--
Adam
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Resources