Cached Row Set

I have the following JSP for CachedRowSet :
It works okey for the first time but when I click on next it is giving me : The environment is WebSphere 3.5 on AS400
Note: A servlet gathers the regular resultset , populates the CachedRowSet with it and then puts the CachedRowset in to the session and sendRedirects the request to this jsp...
Any ideas greatly appriciated...
Thanks
Cuneyt
ERROR START
java.lang.NullPointerException
sun/jdbc/rowset/CachedRowSet.checkIndex(I)V+0 (CachedRowSet.java:1338)
ERROR END
JSP CODE START:
<!-- Sample JSP file -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<%@ page import="java.util.*, sun.jdbc.rowset.CachedRowSet"%>
<HTML>
<HEAD>
<jsp:useBean id="crsItems" class="sun.jdbc.rowset.CachedRowSet" scope="session">
<%
     crsItems = (CachedRowSet) session.getAttribute("crsItemResults");
     session.removeAttribute("crsItemResults");     
     crsItems.first();
%>
This is the first time start up...
</jsp:useBean>
<META name="GENERATOR" content="IBM WebSphere Page Designer V3.5.2 for Windows">
<META http-equiv="Content-Style-Type" content="text/css">
<TITLE></TITLE>
<LINK rel="stylesheet" href="file:///P:/CUSTOM~1/Genesys/STUDIO~1/GENESY~1/theme/Master.css" type="text/css">
<SCRIPT LANGUAGE="JavaScript" SRC="file:///P:/CUSTOM~1/Genesys/STUDIO~1/GENESY~1/GCMFunctions.js"></SCRIPT>
<SCRIPT language="JavaScript">
xLocation = document.location;
xLocation = xLocation.toString();
xRoot = xLocation.substring(0,xLocation.indexOf('/servlet'));
if (xRoot == "") xRoot = xLocation.substring(0,xLocation.lastIndexOf('/'));
function showGroup(){
     parent.document.frames[1].location = xRoot + "file:///P:/CUSTOM~1/Genesys/STUDIO~1/GENESY~1/" + "wait-iframe.html?cmd=Group";
</SCRIPT>
</HEAD>
<BODY BGCOLOR="#FFFFFF" onLoad="showGroup();">
This is the second time
<%
     if ( request.getParameter("next") != null ) {
          out.println("next me");
          if (crsItems.next()) out.println("yes next");
          else out.println("no next");
%>
<FORM METHOD="POST">
     <INPUT TYPE="text" NAME="field1" VALUE="<%=crsItems.getString(1)%>">
     <BR>
     <FONT size="2" face="Tahoma">
     <INPUT type="submit" name="previous" value="Previous Item" class="PButtonOut" onmouseover="this.className='PButtonIn'" onmouseout="this.className='PButtonOut'">
     </FONT><FONT size="2" face="Tahoma">
     <INPUT type="submit" name="next" value="Next Item" class="PButtonOut" onmouseover="this.className='PButtonIn'" onmouseout="this.className='PButtonOut'">
     </FONT>
</FORM>
</BODY>
</HTML>
END OF JSP CODE

I think the problem lies in how you use <jsp:useBean>.
On first entry to this page, I assume that the CachedRowSet has been populated and stored as a session attribute with key "crsItemResults".
For this first time through, the session context will not contain an attribute "crsItems" and so the <jsp:useBean name= "crsItems"....> will do the following:
1. Instantiate a CachedRowSet object with default constructor, define a local variable "crsItems" and assign it as the reference to the new CachedRowSet.
2. Add a session attribute with key "crsItems" and value = the new (and empty) CachedRowSet instance.
3. Perform the initialization code inside the <jsp:useBean> tag.
crsItems = (CachedRowSet) session.getAttribute("crsItemResults");
Retrieves the pre-populated CachedRowSet from the session context and assigns the reference to local variable crsItems.
session.removeAttribute("crsItemResults");
Remove the original session attribute.
At the end of this code, the local variable "crsItems" refers to the populated CachedRowSet but the session attribute "crsItems" refers to an empty CachedRowSet.
On the second time through, the "crsItems" session attribute is retrieved and local variable "crsItems" references the empty CachedRowSet. The original data is no longer available which results in your error.
It's a long-winded theory but I hope it helps. Fixing the problem should be easy - either save the original CachedRowSet with session attribute key "crsItems" and remove the init code or add a line in the init code to re-save the "crsItems" attribute.

Similar Messages

  • 10.2.0.1 (Linux) DB will not cache rows from large IOT

    Hi I have a 1.6gig IOT, I'll call "mytable" that I'm trying to get the DB to cache rows from. I have done an
    alter table mytable storage(buffer_pool keep);
    and when I query the IOT index from dba_indexes it says KEEP for buffer_pool.
    My db_keep_cache_size is set to 912M, db_cache_size=1G, sga_target=0, sga_max_size=2G.
    The problem that I can see is this, the keys for the table are name and day when I say
    select * from mytable where name='HIHI' and day='22-FEB-10';
    it reads from disk every time. I have turned autotrace on and it is doing a FAST FULL SCAN of the IOT index.
    How do I force Oracle to put these rows into the keep cache and read from memory?
    I'm using DB - 10.2.0.1
    Thanks.

    1. If I run that query shown above it give me this -->
    TZTEST (RUN FROM DB HOME)
    The patch has been applied correctly
    I also ran the following -->
    SQL> select to_timestamp_tz('2007-03-28 10:00:00 US/EASTERN','YYYY-MM-DD HH24:MI:SS TZR') from dual;
    TO_TIMESTAMP_TZ('2007-03-2810:00:00US/EASTERN','YYYY-MM-DDHH24:MI:SSTZR')
    28-MAR-07 10.00.00.000000000 AM US/EASTERN
    Is there something else I can run to verify the time in sqlplus?
    2. The time on the OS is using NTP and it is correct. If I push the date back on the OS to a month ago, the EM time is fine. But with today's date that was affected due to 2007 dst, then it is screwed up.
    How can I see the time change from SQLPLus?
    Please let me know. Thank you
    Message was edited by:
    user602765

  • Default and secondary row sets not working as expected

    I am trying the following code to understand how the default and secondary row sets work in ADF. However, the implementation doesn't seem straightforward.
    public void testRowSets(){
      CountryVOImpl vo = (CountryVOImpl)findViewObject("Countries");
      vo.setApplyViewCriteriaName("CountryVOSearchByRegionIdVC");
      vo.setbindRegionId(new Integer(4));
      vo.executeQuery();
      RowSetIterator iter1 = vo.getRowSetIterator();
      while (iter1.hasNext()){
      System.out.println("default iterator, for region id 4, has countries="+iter1.next().getAttribute("CountryName")); //prints Zimbabwe,Nigeria,Israel
      RowSet rowSet = vo.createRowSet("secondaryRowSet");
      vo.setbindRegionId(new Integer(4)); 
      vo.setQueryMode(ViewObject.QUERY_MODE_SCAN_VIEW_ROWS);
      rowSet.executeQuery();
      while (rowSet.hasNext()){
      System.out.println("secondary row set, for region id 4, has countries="+rowSet.next().getAttribute("CountryName")); //prints nothing
      rowSet.closeRowSet();      
      RowSetIterator iter = vo.getRowSetIterator();
      System.out.println("default row set iterator row count="+iter.getEstimatedRangePageCount());
      iter.reset();
      while (iter.hasNext()){
      System.out.println("default row set iterator, for region id 4, has countries="+iter.next().getAttribute("CountryName"));
    Now, iter1 prints X, Y, and Z country names (line #9).The secondary row set prints no countries (line #17). After executeQuery() on the secondary row set, the default row set iterator also prints nothing (line #25). Believe the secondary row set has a different query collection only as long as the row filter is different, and in the case above it's the same. But if that's the case then when we perform rowSet.executeQuery in QUERY_MODE_SCAN_VIEW_ROWS, why does it not see the records in the default row set which have already been placed in the cache by iteration over the default row set?
    NOTE: Changed the subject in the hope to get more suggestions/answers

    have you tried resetting the rowset after the first iteration - my guess its pointing to the end after the first iteration. So perhaps try closing the rowsetitertor first
    iter1 .closeRowSetIterator();
    and then
    RowSetIterator iter=vo.createRowSetIterator('secondaryRowSetIterator')

  • Dynamic Calc processor cannot lock more than [100] ESM blocks during the calculation, please increase CalcLockBlock setting and then retry(a small data cache setting could also cause this problem, please check the data cache size setting).

    Hi,
    Our Environment is Essbase 11.1.2.2 and working on Essbase EAS and Shared Services components.One of our user tried to run the Cal Script of one Application and faced this error.
    Dynamic Calc processor cannot lock more than [100] ESM blocks during the calculation, please increase CalcLockBlock setting and then retry(a small data cache setting could also cause this problem, please check the data cache size setting).
    I have done some Google and found that we need to add something in Essbase.cfg file like below.
    1012704 Dynamic Calc processor cannot lock more than number ESM blocks during the calculation, please increase CalcLockBlock setting and then retry (a small data cache setting could also cause this problem, please check the data cache size setting).
    Possible Problems
    Analytic Services could not lock enough blocks to perform the calculation.
    Possible Solutions
    Increase the number of blocks that Analytic Services can allocate for a calculation:
    Set the maximum number of blocks that Analytic Services can allocate to at least 500. 
    If you do not have an $ARBORPATH/bin/essbase.cfg file on the server computer, create one using a text editor.
    In the essbase.cfg file on the server computer, set CALCLOCKBLOCKHIGH to 500.
    Stop and restart Analytic Server.
    Add the SET LOCKBLOCK HIGH command to the beginning of the calculation script.
    Set the data cache large enough to hold all the blocks specified in the CALCLOCKBLOCKHIGH setting. 
    Determine the block size.
    Set the data catche size.
    Actually in our Server Config file(essbase.cfg) we dont have below data  added.
    CalcLockBlockHigh 2000
    CalcLockBlockDefault 200
    CalcLockBlocklow 50
    So my doubt is if we edit the Essbase.cfg file and add the above settings and restart the services will it work?  and if so why should we change the Server config file if the problem is with one application Cal Script. Please guide me how to proceed.
    Regards,
    Naveen

    Your calculation needs to hold more blocks in memory than your current set up allows.
    From the docs (quoting so I don't have to write it, not to be a smarta***:
    CALCLOCKBLOCK specifies the number of blocks that can be fixed at each level of the SET LOCKBLOCK HIGH | DEFAULT | LOW calculation script command.
    When a block is calculated, Essbase fixes (gets addressability to) the block along with the blocks containing its children. Essbase calculates the block and then releases it along with the blocks containing its children. By default, Essbase allows up to 100 blocks to be fixed concurrently when calculating a block. This is sufficient for most database calculations. However, you may want to set a number higher than 100 if you are consolidating very large numbers of children in a formula calculation. This ensures that Essbase can fix all the required blocks when calculating a data block and that performance will not be impaired.
    Example
    If the essbase.cfg file contains the following settings:
    CALCLOCKBLOCKHIGH 500  CALCLOCKBLOCKDEFAULT 200  CALCLOCKBLOCKLOW 50 
    then you can use the following SET LOCKBLOCK setting commands in a calculation script:
    SET LOCKBLOCK HIGH; 
    means that Essbase can fix up to 500 data blocks when calculating one block.
    Support doc is saying to change your config file so those settings can be made available for any calc script to use.
    On a side note, if this was working previously and now isn't then it is worth investigating if this is simply due to standard growth or a recent change that has made an unexpected significant impact.

  • SQL to read with the DISABLE STORAGE IN ROW set

    I am having problems inserting a clob > 4k. I have changed my default setting to DISABLE STORAGE IN ROW. The problem is, when my clob
    4k, I get a null pointer exception on my read. THE INSERT:
    insert into XML_W_BOOKING (WORKCONVERSATIONID, FREQUENTFLYERNUMBER, XMLSTRING)values(WORKCONVERSATIONID_SEQ.NEXTVAL, pCntr.frequentFlyerNumber, EMPTY_CLOB());
    THE UPDATE:
    PreparedStatement pstmt = this.connection.prepareStatement("update XML_W_BOOKING set XMLSTRING = ? where WORKCONVERSATIONID = ?");
    pstmt.setAsciiStream(1, new StringBufferInputStream(pCntr.xmlString), pCntr.xmlString.length());
    pstmt.setLong(2, pCntr.workConversationId);
    pstmt.executeQuery();
    pstmt.close();
    THE READ:
    myContainer.workConversationId= pRset.getLong(1);
    myContainer.frequentFlyerNumber=pRset.getLong(2);
    java.sql.Clob clob = pRset.getClob(3);
    int c;
    int length = new Long(clob.length()).intValue();
    StringBuffer strBuf = new StringBuffer(length);
    BufferedInputStream bin = new BufferedInputStream(pRset.getAsciiStream(3));
    while((c = bin.read()) != -1){
    strBuf.append((char)c);
    String str = strBuf.toString();
    System.out.println("str: " + str);
    myContainer.xmlString = str;
    Any suggestions? Is there a special sql statement I should be using to read when the "DISABLE STORAGE IN ROW" setting? I am using Oracle 8i and wls 5.1.
    IP: Logged
    null

    Enable/Disable storage in row is used for LOB columns. If enable storage in row is specified and the length of the LOB field is less than 4K then the LOB is stored along with other table data, else it is stored in a seperate segment. If disable storage in row is specified then LOB data is stored always in a seperate segment. When the LOB is stored in a seperate segment the storage parameters are determined by the values specified for CHUNKS and PCTVERSION. One chunk stores only one LOB data even if enough space is aavailable in the chunk. If the size of LOB data is small then enable storage.
    To calculate the space used by the tables use the query below
    For Table Data
    select segment_name, sum(bytes) from user_segments where segment_name in ('TABLE', 'TABLE1', 'TABLE2') group by segment_name;
    For LOB's
    select segment_name, sum(bytes) from user_segments where segment_name in (select segment_name from user_lobs where table_name in('TABLE', 'TABLE1', 'TABLE2'))
    group by segment_name;
    Jayant

  • How to Handle Multiple row sets in BPEL

    Hi,
    I'm going to return list of records from a stored procedure, and try to catch it using BPEL and then those records should be insert to
    another stored procedure to insert those values to a Table.
    (Second Stored Procedure will do the INSERT function)
    Using ref cursor i can get row set. Is it possible to use Ref Cursor as IN parameter to next procedure??
    or else how can i handle this???
    thank you...

    Is your data model right? If you are adding in one and deleting in another it sounds to me more like a process that an entity, in which case you may revisit your data model and simplify it, add in a session bean with the process method to co-ordinate between the two.
    However, if you want to map multiple different tables within a single entity bean it is possible and just part of the mapping. How you actualyl specify it depends on which implementation you are working with.
    Cheers,
    Peter.

  • Can't insert new row in last position in row set

    I am trying to programmatically insert a new row into the last slot of a View Object's default row set.
    I normally can do this:
    Row newRow = vo.createRow();
    // set stuff on the row
    vo.last();
    vo.next();
    vo.insert(newRow);and, voila, the row is in the last position.
    But on this particualr view object, when I do the above, the row is inserted in the first slot.
    There doesn't seem to be anything unusual about the View object. it is a child Vo in the data model, but that shouldn't matter.
    When I debug with vo.getCurrentRowSlot(), even after performing last(); next();, vo.getCurrentRowSlot() returns 0, never 3.
    Has anyone else run into this behavior and if so, any resolution or explanation?
    FYI, I was able to use the following workaround:
    Row lastRow = vo.last();
    if (lastRow != null){
        int indx = vo.getRangeIndexOf(lastRow) + 1;
        vo.insertRowAtRangeIndex(indx, newRow);
    } else {
       vo.insertRow(newRow);
    }   

    would this solve your problem
    http://kohlivikram.blogspot.com/2008/10/add-new-row-in-adf-table-on-button.html

  • How to use open Row set in sql server 2014

    Hello All,
    How to open the row set using sql server 2014 using link server connection.

    Hi  denyy,
    Are you referring to the OPENROWSET function in SQL Server 2014?
    The OPENROWSET method is an alternative to accessing tables in a linked server and is a one-time, ad hoc method of connecting and accessing remote data by using OLE DB. The examples below demonstrate how to use the OPENROWSET function:
    A. Using OPENROWSET with SELECT and the SQL Server Native Client OLE DB Provider
    SELECT a.*
    FROM OPENROWSET('SQLNCLI', 'Server=Seattle1;Trusted_Connection=yes;',
    'SELECT GroupName, Name, DepartmentID
    FROM AdventureWorks2012.HumanResources.Department
    ORDER BY GroupName, Name') AS a;
    B. Using the Microsoft OLE DB Provider for Jet
    SELECT CustomerID, CompanyName
    FROM OPENROWSET('Microsoft.Jet.OLEDB.4.0',
    'C:\Program Files\Microsoft Office\OFFICE11\SAMPLES\Northwind.mdb';
    'admin';'',Customers);
    GO
    C. Using OPENROWSET to bulk insert file data into a varbinary(max) column
    USE AdventureWorks2012;
    GO
    CREATE TABLE myTable(FileName nvarchar(60),
    FileType nvarchar(60), Document varbinary(max));
    GO
    INSERT INTO myTable(FileName, FileType, Document)
    SELECT 'Text1.txt' AS FileName,
    '.txt' AS FileType,
    * FROM OPENROWSET(BULK N'C:\Text1.txt', SINGLE_BLOB) AS Document;
    GO
    D. Using the OPENROWSET BULK provider with a format file to retrieve rows from a text file
    SELECT a.* FROM OPENROWSET( BULK 'c:\test\values.txt',
    FORMATFILE = 'c:\test\values.fmt') AS a;
    Reference:
    OPENROWSET (Transact-SQL)
    Using the OPENROWSET function in SQL Server
    Thanks,
    Lydia Zhang
    If you have any feedback on our support, please click
    here.

  • No row set iterator in transactionvo1

    if any error occurs in my code
    in my catch block i am doing getdbtransaction.rollback()
    but when i go to ui and try to perform the next transaction ... i am getting error as no row set iterator in transactionvo1
    how can i handle this to perform next transaction.

    User, you need to give more information about your environment like jdev version and use case to get a good answer.
    What I can tell you is that a rollback also rests the state of the current iterator so that you don't have a current row in the UI.
    This will cause the error you see.
    Timo

  • How can I learn about Row Set Navigator

    I would like to learn about Row Set Navigator and all DataWebBeans classes. Where do I find these informations.

    jdeveloepr has online documentation for all of this
    also review the tutorials ... provided there .

  • FSG Reports : Row Set Account assignments (Display Type to show Account nar

    I have an FSG related issue. I've defined a report using a basic row set and a column set. In my row set, I've used account assignments and the display type as 'Expand' to my natural account. Is it possible to show the narration of the account in the report instead of the natural account number?
    For example, My report now displays '1401' - which is the natural account number. I want to display its narration which reads 'Revenue'
    Miranga

    Hi Miranga,
    it is possible to display the Account code description .. infact you can display both account code and description ... for which you need to create a ROW ORDER and attach it to your FSG Report ...
    Perform the below steps :
    1) Switch responsibility to General Ledger
    2) Navigate to Reports > Define > Order
    3) Enter a name for the ROW ORDER field
    4) In the Account Display section, enter SEQ as 1, Segment as ACCOUNT, order by as VALUE and DISPLAY as VALUE AND DESCRIPTION and Width as 15 ..
    You can increase/decrease the width based on the how the data is appearing in your report output ...
    5) Save the record ..
    6) Navigate to Reports > Define > Report
    7) Query your report ....
    8) In the optional Components section, click on the Row Order field and select the row order you have configured above from List of values ..
    9) Save the changes made to the report ...
    10) Run the FSG report afresh and see the output ...
    Regards,
    Ivruksha

  • FSG Row set Definition

    Hi ,
    In FSG Report Row set Definition,
    we have assigned the one parent account and choose expand for the Natural account . But the requirement is to fetch from multiple set of books , so we copied the same account assignment and assigned different set of books also ... Now my question here is ,
    when i run the report , it shows different row for each set of books .
    is it possible to combine all the rows of the different set of books?
    We are in release 11.5.10.2
    Thanks
    Regards
    Muthu

    Hello Muthu.
    On the query bellow, change the period name, the SOB id and the currency to your needs, run it, and let me know what other info you will need.
    SELECT cc.segment1, cc.segment2, nvl(sum(b.period_net_dr - b.period_net_cr),0) "Period Balance"
    FROM gl_balances b, gl_code_combinations cc
    WHERE cc.code_combination_id = b.code_combination_id
    AND b.set_of_books_id = 52
    AND b.period_name = 'Abril-2011'
    AND b.actual_flag = 'A'
    AND b.currency_code = 'EUR'
    GROUP BY cc.segment1, cc.segment2
    ORDER BY cc.segment2
    Octavio

  • Caching Result Set ?

    folks
    I have a search page which returns a result set and the results are put in the session to be able to access when user clicks on the page numbers(pagination) in the results pane.
    Is there any way we can store or cache this and access instead of fetching it off the session.

    You can store the data as a multi dimensional array in javascript on the rendered jsp page as a javascript function. It exists on the client side (browser) and you can use an onClick event on the page's button to call up various parts of the array and display it to the user. That way, your user doesnt have to submit the page back to the servlet to pagenate to the next page. The data shows up immidiately instead. You'll have to read up on javascript to learn how to do this. (Also I assume you are storing the resultant data in some type of array and not the raw resultSet).
    However, if so much data is returned to the user he needs pagenation, I suggest you add filter textfields to allow him to limit what data is returned so pagenation is not needed. Pagenation implies there is too much data for the user to effectively use at once (no one likes scrolling down a list of 200 items). For instance, instead of displaying all names in a list, add a filter so the user can search for all last names that begain with an A, or B, etc through Z. Then, when displayed to the user, show the list sorted by your filter criteria (lastName). If there is still too much data in the list, I suggest putting up a vertical scrollbar rather than pagenation.

  • IView Caching BrowserOnly setting

    Hi,
    Can anyone shed some light on the BrowserOnly setting that is available in the Load properties of an iView? It does not seem to do anything in particular and all i can find on SAP Help is this....
    http://help.sap.com/saphelp_erp2004/helpdata/en/75/e3fc40b3c7fa6fe10000000a1550b0/frameset.htm
    Apparently it is supposed to allow caching only in the browser cache and not in the PRT cache... but the iViews I am testing are not stored in the Browser Cache for some reason....
    Any experience on this would be a great help.
    BRgds,
    Simon

    Make sure:
    1-your the local cache on your browser is not full
    2-your system wide setting is not over riding the iView level setting - system setting can be found here:
    System Administration > System Configuration
    from Detailed Navigation: Service Configuration
    more details are found here:
    http://help.sap.com/saphelp_nw04/helpdata/en/1c/3f1c409ce22402e10000000a1550b0/content.htm
    We wanted to do the opposite, to make the iViews not cache on the browser which contain sensitive data, particularly due to users that share computers. So we had to change the iView cache property to None. The BrowserOnly setting should be used with iViews that don't need to change often for improving performance of the Portal.

  • Warning: Cache size set too large?

    I've recently installed a SSD to work as a dedicated cache drive, and I've directed the 3 cache settings in AE (CS6) to it.
    The drive is 240GB, but I can't put the cache size over 150GB without getting a warning that it's set too high. Is this true? Am I wasting almost 100GB?

    Use your drive for something else. 150GB is a huge huge cache. The CS6 disk cache is glitchy anyway. I have mine turned off most of the time.

Maybe you are looking for

  • Need help to avoid ORA-04030 error

    Oracle version : 11.1.0.6.0 OS - Solaris 64bit Sparc Hi All, Today we have recieved the below error messeges in the alert log. ORA-04030: out of process memory when trying to allocate 56 bytes (callheap,kghscAllocDataElem:dataElem) ORA-04030: out of

  • Message on SRM portal

    Hi .. When i am trying to modify employee data on SRM portal, i am getting this message "Resource is currently being used by another user" . Pls try later. i am trying to bind an employee to a purchase organisation. Please let me know how go to about

  • Iphone5S 7.0.5 losing 3G connection

    I Just have my Iphone5s with iMachines(Malaysia) My iphone5s unable to reconnect back 3G connection after lost connection in no service area but it should be able to reconnect back 3G as soon as i enter back the area have 3G signal I need to restart

  • Enterprise (specifically 6.5) best practices from a server standpoint?

    I am a system administrator for a decent sized company that relies on 6.5 for our financial reporting. We're having a rough time getting it to be both fast and reliable. For instance if we disable oplocks (recommended to prevent corruption), consolid

  • IOS 8/iphone 6 photo auto - orientation

    I was taking some pictures with my iPhone 6 and realize a lot of times the pictures coming out with the wrong orientation. some of the horizontal shots came out to be vertical.  Anyone has the same issue?  is this a bug or hardware issue? Thanks.