RAM drive not available again in lucee(RAM error)

Hi,

The following issue exists in our server for long now.

in-memory file is used.

lucee.runtime.exp.ApplicationException: parentdirectory directory for [ram:///filename.txt] 
doesnot exist.

Please have a look at the full log attached as screenshot. The issue has
been a headache for months now. The strange fact is that after the lucee
restart the issue no longer seems to exist.

The first thing you should do is update a current version of Lucee.

Then, if the problem persists, report it again, and if you believe this
to be a bug then please open a ticket for it in the JIRA at
https://luceeserver.atlassian.net/

Igal Sapir
Lucee Core Developer
Lucee.org http://lucee.org/

I would say if you need that much ram you should use a cache server like redis or ehcache

With regards to your error I am not sure. Is there something else that might be deleting the file? Have you put a lock round the transaction?

Mark Drew

  • Sent by typing with my thumbs.

Hi Mark,

Don’t know if you mean this, but the guys from hosting give me this:

JAVA_OPTS="-Xms55296m -Xmx55296m -XX:MaxPermSize=6144m “;

Regards,

Dick Goosen

Hi Mark,

Thanks for your response. I just created a post on https://luceeserver.atlassian.net. I manage a French property portal (www.franimo.com) and this error keeps on appearing since Railo 4. I increased RAM on the server to 64 GB’s. Use a lot of caching, perhaps the RAM still becomes overloaded anyway.

Regards,

Dick Goosen

Hi,

OS is Cent Os version Java I need to ask. Physical RAM 65 GB. This error also occurred when I only had 8 GBS’s of physical RAM.

Regards,

Dick Goosen

This error is keeps on appearing since I use Railo.

JAVA_OPTS="-Xms55296m -Xmx55296m -XX:MaxPermSize=6144m “;
Sheesh… That’s a LOT of memory. Are you sure that you need that much?

What OS are you running on? What version of Java? How much physical
RAM does the machine have?

Igal Sapir
Lucee Core Developer
Lucee.org http://lucee.org/

Hi Mark,

I have posted this question to the person who could shed more light on this. I will answer asap.

Regards,

Dick Goosen

You’re allocating about 85% of the machine’s RAM to the JVM. If that’s
necessary then fine, but most likely it is not. Allocating that much
memory can cause other issues with garbage disposal etc., so if it’s not
needed you should really reconsider that.

Also, I advised that the first thing you should do is update to a
current version of Lucee, which I don’t think that you did.

Igal Sapir
Lucee Core Developer
Lucee.org http://lucee.org/

How much ram is lucee/tomcat using? What’s the /tomcat/bin/setenv.sh saying?

Regards

Mark Drew

You mean you have ALWAYS had this issue rather than a specific version?

Again, I would suggest you post his here: https://luceeserver.atlassian.net/

so that it can get seen by the developers. See if you can create a test case that can be reproduced.

Please add information such as how much memory is available to Lucee, maybe you are just running out of memory and you can’t add that file to ram. (or it gets cleared out pretty quickly)

Regards

Mark Drew

Can you share the code on that page? Thanks.

Mark Drew

  • Sent by typing with my thumbs.

We scheduled updating Lucee this morning 9.00 hours (European Paris time). How much allocating do you think is needed?

Regards,

Dick Goosen

Hi Mark,

The file is not deleted. The filename.txt is an example. It is s definitely the RAM which does not exists. If I restart the Lucee server it is there again. This is the function called, I use a lock.

<cffunction name="grabImage" returnType="string" access="public" hint="grabs an image makes a thumb and puts it in the proper directory" output="false">
		<cfargument name="propertyId" type="numeric" required="false" default="0">
		<cfargument name="agentId" type="numeric" required="false" default="5">
		<cfargument name="fileUrl" type="string" required="true">
		<cfargument name="newImageWidth" type="numeric" required="true">
		<cfargument name="imageType" type="string" default="" required="false">
		<cfargument name="imageName" type="string" default="" required="false">
		<cfargument name="deleteRam" type="boolean" default="true" required="false">
		
		<!--- remove spaces in images --->
		<cfset variables.fileUrl2=replace(trim(arguments.fileUrl)," ", "%20", "all")>
		
			<!--- create new filename --->
			
			<cfif arguments.imageName is "">
				<!--- create unique image name if no image name is provided --->
				<cfset variables.imgName2 = lCase(listFirst(CreateUUID(), "-")) & right(TimeFormat(Now(),"hhmmss"), 3)>
				<cfset variables.imgName2=ListAppend(variables.imgName2,"jpg",".")>
				
			<cfelse>
				<cfset variables.imgName2=arguments.imageName>
			</cfif>	
				

			<cfif deleteRam is false>
				<cffile action="readBinary" variable="imageGet" file="#variables.fileUrl2#">
				<cffile action="write" output="#imageGet#" file="ram://#variables.imgName2#">
			</cfif>
			
			
			
			
			
			
			<!--- Create thumbnail, note this does not resize the image in memory, just the image that is  written to disk.--->
			<cfset cfImage = imageNew("ram://#variables.imgName2#")>
			
			<cfset imageData = imageInfo(cfImage)>
			
			<cfset imageWidth=imageData.width>
			<cfset imageHeight=imageData.height>
			
			<cfset theDivisionNewImage=arguments.newImageWidth/imageWidth>
			<cfset newImageHeight=round(imageHeight*theDivisionNewImage)>
			
			<cfparam name="imageTypeId" default="1">
			
			<cfswitch expression="#arguments.imageType#">
				<cfcase value="thumb">
					<!--- Check if main thumb is already there --->
					<cfquery datasource="#request.datasourceName#" name="checkMainThumb">
					SELECT * FROM pictures p WHERE picture_type_id=4 and property_id =#arguments.propertyId#
					</cfquery>
					<cfif checkMainThumb.recordCount GT 0>
						<cfset imageTypeId="2">
					<cfelse>
						<cfset imageTypeId="4">
					</cfif>
				</cfcase>
				<cfcase value="logo">
					<cfset imageTypeId="3">
				</cfcase>
			</cfswitch>
			
			<cfset variables.newImageName= "#imageType##variables.imgName2#">
	
			<cfset variables.newImageName2= "#year(now())#/#month(now())#/#variables.newImageName#">
			
			<!--- width new image function --->
			<cfset ImageResize(cfImage,"#newImageWidth#","#newImageHeight#","highestPerformance",1)>
			
			<cfimage source="#cfImage#" action="write" destination="#request.wwwroot_folder#/images/pictures/#variables.newImageName2#" overwrite="yes"> 

			<cfquery datasource="#request.datasourceName#" name="insertProperty">
			INSERT INTO pictures (name,width,height,property_id,picture_type_id,agent_id)
			VALUES ("#variables.newImageName2#",#newImageWidth#,#newImageHeight#,#arguments.propertyId#, #imageTypeId#,#arguments.agentId#)
			</cfquery>
			
			<cfif deleteRam is true>
			<cffile action="delete" file="ram://#variables.imgName2#" />
			
			<!--- extra check delete all existing RAM files not necessary
			<cfdirectory
				name="files"
				action="list"
				directory="ram://"
				recurse="true"
				type="file"
				/>
			    <!--- Loop over all the files on our RAM drive. --->
			    <cfloop query="files">
				<!--- Delete the file. --->
				<cffile
				    action="delete"
				    file="#files.directory##files.name#"
				    />
			    </cfloop> --->
			    
			</cfif>
			

		<cfreturn variables.imgName2>
		
	</cffunction>

It is called from a cfthread like this:

<cflock timeout="360" name="thumbLock" type="exclusive">
						<cfset thereIsAtLeastOneImage=true>
						<!--- the upload is a property image --->
						<cfinvoke component="app.cfc.grabber" method="grabImage"
							propertyId="#arguments.propId#"
							agentId="#arguments.aId#"
							fileUrl="#local.imageGetUrl#"
							newImageWidth=1000
							deleteRam=false
							returnvariable="local.imageName">
							
							<!--- <cfset thePath="/images/pictures/#year(now())#/#month(now())#/#imageName#">--->
												
						<cfinvoke component="app.cfc.grabber" method="grabImage"
							propertyId="#arguments.propId#"
							agentId="#arguments.aId#"
							fileUrl="ram://#local.imageName#.jpg"
							newImageWidth=350
							imageType="thumb"
							imageName="#local.imageName#"
							returnvariable="imageNameThumb"
							>
					</cflock>

Hope you can help.

Kind regards,

Dick

aside, how come you aren’t using cfqueryparam?

I got this code working fine locally (it ignores the database and I had to create some paths) but for the ram stuff it works fine. Following the link you passed earlier it seems to be working fine again? (http://www.franimo.nl/test2/ http://www.franimo.nl/test2/) Unless you have changed the code there of course?

Ram should be available just like a file system and working inside a lock should at least stop other things accessing that specific file for the time that you are processing it so not sure what it could be .

Regards

Mark Drew

Hi,

I restarted Lucee then the RAM works fine again.

Regards,

Dick

It really depends on your application, but in most cases 8GB is plenty.

You can set a minimum of 4GB and a maximum of 8GB and watch your
server. If it keeps using around 8GB then you can increase the maximum,
or if you get an Out Of Memory error, of course.

Also, 6GB for MaxPermSize is a waste of memory in most cases. 512MB
should be more than enough usually. If you want to give it more then
use 1GB, but unless you get Out Of Memory errors there is no reason to
increase those values.

If you are running Java 8 then the MaxPermSize argument is ignored
anyway. That’s the reason I asked for the Java version.

To set a minimum memory allocation of 4GB, maximum of 8GB, and
MaxPermSize of 512MB (again, only if you are on Java 7 because on Java 8
that argument is ignored), set your JAVA_OPTS like so:

     JAVA_OPTS="-Xms4096m -Xmx8192m -XX:MaxPermSize=512m";

Igal Sapir
Lucee Core Developer
Lucee.org http://lucee.org/

Hi Mark,

I thought I already did sent you the code. Here it is again:

This is the function called, I use a lock.

<cffunction name="grabImage" returnType="string" access="public" hint="grabs an image makes a thumb and puts it in the proper directory" output="false">
		<cfargument name="propertyId" type="numeric" required="false" default="0">
		<cfargument name="agentId" type="numeric" required="false" default="5">
		<cfargument name="fileUrl" type="string" required="true">
		<cfargument name="newImageWidth" type="numeric" required="true">
		<cfargument name="imageType" type="string" default="" required="false">
		<cfargument name="imageName" type="string" default="" required="false">
		<cfargument name="deleteRam" type="boolean" default="true" required="false">
		
		<!--- remove spaces in images --->
		<cfset variables.fileUrl2=replace(trim(arguments.fileUrl)," ", "%20", "all")>
		
			<!--- create new filename --->
			
			<cfif arguments.imageName is "">
				<!--- create unique image name if no image name is provided --->
				<cfset variables.imgName2 = lCase(listFirst(CreateUUID(), "-")) & right(TimeFormat(Now(),"hhmmss"), 3)>
				<cfset variables.imgName2=ListAppend(variables.imgName2,"jpg",".")>
				
			<cfelse>
				<cfset variables.imgName2=arguments.imageName>
			</cfif>	
				

			<cfif deleteRam is false>
				<cffile action="readBinary" variable="imageGet" file="#variables.fileUrl2#">
				<cffile action="write" output="#imageGet#" file="ram://#variables.imgName2#">
			</cfif>
			
			
			
			
			
			
			<!--- Create thumbnail, note this does not resize the image in memory, just the image that is  written to disk.--->
			<cfset cfImage = imageNew("ram://#variables.imgName2#")>
			
			<cfset imageData = imageInfo(cfImage)>
			
			<cfset imageWidth=imageData.width>
			<cfset imageHeight=imageData.height>
			
			<cfset theDivisionNewImage=arguments.newImageWidth/imageWidth>
			<cfset newImageHeight=round(imageHeight*theDivisionNewImage)>
			
			<cfparam name="imageTypeId" default="1">
			
			<cfswitch expression="#arguments.imageType#">
				<cfcase value="thumb">
					<!--- Check if main thumb is already there --->
					<cfquery datasource="#request.datasourceName#" name="checkMainThumb">
					SELECT * FROM pictures p WHERE picture_type_id=4 and property_id =#arguments.propertyId#
					</cfquery>
					<cfif checkMainThumb.recordCount GT 0>
						<cfset imageTypeId="2">
					<cfelse>
						<cfset imageTypeId="4">
					</cfif>
				</cfcase>
				<cfcase value="logo">
					<cfset imageTypeId="3">
				</cfcase>
			</cfswitch>
			
			<cfset variables.newImageName= "#imageType##variables.imgName2#">
	
			<cfset variables.newImageName2= "#year(now())#/#month(now())#/#variables.newImageName#">
			
			<!--- width new image function --->
			<cfset ImageResize(cfImage,"#newImageWidth#","#newImageHeight#","highestPerformance",1)>
			
			<cfimage source="#cfImage#" action="write" destination="#request.wwwroot_folder#/images/pictures/#variables.newImageName2#" overwrite="yes"> 

			<cfquery datasource="#request.datasourceName#" name="insertProperty">
			INSERT INTO pictures (name,width,height,property_id,picture_type_id,agent_id)
			VALUES ("#variables.newImageName2#",#newImageWidth#,#newImageHeight#,#arguments.propertyId#, #imageTypeId#,#arguments.agentId#)
			</cfquery>
			
			<cfif deleteRam is true>
			<cffile action="delete" file="ram://#variables.imgName2#" />
			
			<!--- extra check delete all existing RAM files not necessary
			<cfdirectory
				name="files"
				action="list"
				directory="ram://"
				recurse="true"
				type="file"
				/>
			    <!--- Loop over all the files on our RAM drive. --->
			    <cfloop query="files">
				<!--- Delete the file. --->
				<cffile
				    action="delete"
				    file="#files.directory##files.name#"
				    />
			    </cfloop> --->
			    
			</cfif>
			

		<cfreturn variables.imgName2>
		
	</cffunction>

It is called from a cfthread like this:

<cflock timeout="360" name="thumbLock" type="exclusive">
						<cfset thereIsAtLeastOneImage=true>
						<!--- the upload is a property image --->
						<cfinvoke component="app.cfc.grabber" method="grabImage"
							propertyId="#arguments.propId#"
							agentId="#arguments.aId#"
							fileUrl="#local.imageGetUrl#"
							newImageWidth=1000
							deleteRam=false
							returnvariable="local.imageName">
							
							<!--- <cfset thePath="/images/pictures/#year(now())#/#month(now())#/#imageName#">--->
												
						<cfinvoke component="app.cfc.grabber" method="grabImage"
							propertyId="#arguments.propId#"
							agentId="#arguments.aId#"
							fileUrl="ram://#local.imageName#.jpg"
							newImageWidth=350
							imageType="thumb"
							imageName="#local.imageName#"
							returnvariable="imageNameThumb"
							>
					</cflock>

Hope you can help.

Kind regards,

Dick