hbase-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From li...@apache.org
Subject svn commit: r1589228 - in /hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase: ipc/ ipc/thrift/ regionserver/
Date Tue, 22 Apr 2014 18:18:42 GMT
Author: liyin
Date: Tue Apr 22 18:18:42 2014
New Revision: 1589228

URL: http://svn.apache.org/r1589228
Log:
[HBASE-11046] Add new scanner API definition

Author: daviddeng

Summary: Add a new definition of scanner api for reducing unnecessary RPC calls.

Test Plan: This diff doesn't contain functional change.

Reviewers: liyintang, manukranthk, aaiyer

Reviewed By: manukranthk

CC: hbase-eng@, andrewcox

Differential Revision: https://phabricator.fb.com/D1286894

Task ID: 4184037

Added:
    hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/IRegionScanService.java
    hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/ScannerResult.java
    hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/IRegionScanServer.java
Modified:
    hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/HRegionInterface.java
    hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/ThriftHRegionInterface.java
    hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/thrift/HBaseToThriftAdapter.java
    hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
    hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServerIf.java
    hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/ThriftHRegionServer.java

Modified: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/HRegionInterface.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/HRegionInterface.java?rev=1589228&r1=1589227&r2=1589228&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/HRegionInterface.java
(original)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/HRegionInterface.java
Tue Apr 22 18:18:42 2014
@@ -51,7 +51,7 @@ import org.apache.hadoop.io.MapWritable;
  * number in HBaseRPCProtocolVersion
  */
 public interface HRegionInterface extends HBaseRPCProtocolVersion, Restartable,
-    Stoppable, ThriftClientInterface {
+    Stoppable, ThriftClientInterface, IRegionScanService {
 
   /**
    * Calls an endpoint on an region server.

Added: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/IRegionScanService.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/IRegionScanService.java?rev=1589228&view=auto
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/IRegionScanService.java
(added)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/IRegionScanService.java
Tue Apr 22 18:18:42 2014
@@ -0,0 +1,80 @@
+/**
+ * Copyright 2014 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.ipc;
+
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.ipc.thrift.exceptions.ThriftHBaseException;
+
+import com.facebook.swift.codec.ThriftField;
+import com.facebook.swift.service.ThriftException;
+import com.facebook.swift.service.ThriftMethod;
+import com.facebook.swift.service.ThriftService;
+
+/**
+ * Interface of scanner service in a region.
+ */
+@ThriftService
+public interface IRegionScanService {
+  /**
+   * Opens a scanner, optionally returns some data if numberOfRows > 0.
+   *
+   * @param regionName the name of the region to scan
+   * @param scan the Scan instance defining scan query.
+   * @param numberOfRows maximum number of rows to return after successfully
+   *          open the scanner.
+   * @return the result as a ScannerResult.
+   *         The length of the Result list of the return value could be empty
+   *         and EOR is set to true for sure in this case.
+   */
+  @ThriftMethod(value = "scanOpen", exception = {
+      @ThriftException(type = ThriftHBaseException.class, id = 1) })
+  ScannerResult scanOpen(
+      @ThriftField(name="regionName") byte[] regionName,
+      @ThriftField(name = "scan") Scan scan,
+      @ThriftField(name = "numberOfRows") int numberOfRows)
+      throws ThriftHBaseException;
+
+  /**
+   * Returns next scanning results.
+   *
+   * @param ID the ID of the scanner
+   * @param numberOfRows maximum number of rows to return,
+   * @return the result as a ScannerResult.
+   *         The length of the Result list of the return value could be empty
+   *         and EOR is set to true for sure in this case.
+   */
+  @ThriftMethod(value = "scanNext", exception = {
+      @ThriftException(type = ThriftHBaseException.class, id = 1) })
+  ScannerResult scanNext(
+      @ThriftField(name="id") long id,
+      @ThriftField(name = "numberOfRows") int numberOfRows)
+      throws ThriftHBaseException;
+
+  /**
+   * Closes the scanner on the server side.
+   *
+   * @param id  the ID of the scanner to close
+   * @return true  if a scanner is closed. false if the scanner doesn't exist.
+   */
+  @ThriftMethod(value = "scanClose", exception = {
+      @ThriftException(type = ThriftHBaseException.class, id = 1) })
+  boolean scanClose(@ThriftField(name = "id") long id)
+      throws ThriftHBaseException;
+}

Added: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/ScannerResult.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/ScannerResult.java?rev=1589228&view=auto
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/ScannerResult.java (added)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/ScannerResult.java Tue
Apr 22 18:18:42 2014
@@ -0,0 +1,154 @@
+/**
+ * Copyright 2014 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.ipc;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.hadoop.hbase.client.Result;
+
+import com.facebook.swift.codec.ThriftConstructor;
+import com.facebook.swift.codec.ThriftField;
+import com.facebook.swift.codec.ThriftStruct;
+
+/**
+ * The result structure of scanOpen and scanNext.
+ *
+ * ScannerResult is an immutable object, use ScannerResult.Builder to create
+ * one.
+ */
+@ThriftStruct(builder = ScannerResult.Builder.class)
+public class ScannerResult {
+  private final boolean eos;
+  private final boolean eor;
+  private final List<Result> results;
+  private final long id;
+
+  private ScannerResult(boolean eos, boolean eor, List<Result> results, long id) {
+    this.eos = eos;
+    this.eor = eor;
+    this.results = results;
+    this.id = id;
+  }
+
+  /**
+   * @return End-Of-Scan mark. If true, the whole scanning is over, no need to
+   *         call next region, the scanner has been closed.
+   */
+  @ThriftField(1)
+  public boolean getEOS() {
+    return eos;
+  }
+
+  /**
+   * @return End-Of-Region mark. If true, the scanning on this region has been
+   *         over, the scanner has been closed.
+   */
+  @ThriftField(2)
+  public boolean getEOR() {
+    return eor;
+  }
+
+  /**
+   * @return  the Result array. Never null.
+   */
+  @ThriftField(3)
+  public List<Result> getResults() {
+    return results;
+  }
+
+  /**
+   * @return  the ID of the scanner.
+   */
+  @ThriftField(4)
+  public long getID() {
+    return id;
+  }
+
+  /**
+   * Builder of ScannerResult.
+   */
+  public static class Builder {
+    private static final List<Result> EMPTY_RESULTS = Collections.emptyList();
+
+    private boolean eos = false;
+    private boolean eor = false;
+    private List<Result> results = EMPTY_RESULTS;
+    private long id = -1L;
+
+    @ThriftField(1)
+    public Builder setEOS(boolean vl) {
+      this.eos = vl;
+      return this;
+    }
+
+    @ThriftField(2)
+    public Builder setEOR(boolean vl) {
+      this.eor = vl;
+      return this;
+    }
+
+    public Builder setResult(Result[] vl) {
+      if (vl == null || vl.length == 0) {
+        this.results = EMPTY_RESULTS;
+      } else {
+        this.results = Arrays.asList(vl);
+      }
+      return this;
+    }
+
+    @ThriftField(3)
+    public Builder setResult(List<Result> vl) {
+      this.results = vl;
+      return this;
+    }
+
+    @ThriftField(4)
+    public Builder setID(long vl) {
+      this.id = vl;
+      return this;
+    }
+
+    public boolean getEOS() {
+      return eos;
+    }
+
+    public boolean getEOR() {
+      return eor;
+    }
+
+    public List<Result> getResults() {
+      return results;
+    }
+
+    public long getID() {
+      return id;
+    }
+
+    /**
+     * Creates a ScannerResult with the current status.
+     */
+    @ThriftConstructor
+    public ScannerResult build() {
+      return new ScannerResult(eos, eor, results, id);
+    }
+  }
+}

Modified: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/ThriftHRegionInterface.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/ThriftHRegionInterface.java?rev=1589228&r1=1589227&r2=1589228&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/ThriftHRegionInterface.java
(original)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/ThriftHRegionInterface.java
Tue Apr 22 18:18:42 2014
@@ -58,7 +58,7 @@ import com.google.common.util.concurrent
  */
 @ThriftService
 public interface ThriftHRegionInterface extends ThriftClientInterface,
-    IEndpointServer {
+    IEndpointServer, IRegionScanService {
 
   /**
    * Get metainfo about an HRegion

Modified: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/thrift/HBaseToThriftAdapter.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/thrift/HBaseToThriftAdapter.java?rev=1589228&r1=1589227&r2=1589228&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/thrift/HBaseToThriftAdapter.java
(original)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/ipc/thrift/HBaseToThriftAdapter.java
Tue Apr 22 18:18:42 2014
@@ -51,6 +51,7 @@ import org.apache.hadoop.hbase.io.hfile.
 import org.apache.hadoop.hbase.ipc.HBaseRPCOptions;
 import org.apache.hadoop.hbase.ipc.HBaseServer.Call;
 import org.apache.hadoop.hbase.ipc.HRegionInterface;
+import org.apache.hadoop.hbase.ipc.ScannerResult;
 import org.apache.hadoop.hbase.ipc.ThriftClientInterface;
 import org.apache.hadoop.hbase.ipc.ThriftHRegionInterface;
 import org.apache.hadoop.hbase.ipc.thrift.exceptions.ThriftHBaseException;
@@ -1246,4 +1247,36 @@ public class HBaseToThriftAdapter implem
     }
   }
 
+  @Override
+  public ScannerResult scanOpen(byte[] regionName, Scan scan, int numberOfRows)
+      throws ThriftHBaseException {
+    preProcess();
+    try {
+      return connection.scanOpen(regionName, scan, numberOfRows);
+    } finally {
+      postProcess();
+    }
+  }
+
+  @Override
+  public ScannerResult scanNext(long id, int numberOfRows)
+      throws ThriftHBaseException {
+    preProcess();
+    try {
+      return connection.scanNext(id, numberOfRows);
+    } finally {
+      postProcess();
+    }
+  }
+
+  @Override
+  public boolean scanClose(long id) throws ThriftHBaseException {
+    preProcess();
+    try {
+      return connection.scanClose(id);
+    } finally {
+      postProcess();
+    }
+  }
+
 }

Modified: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java?rev=1589228&r1=1589227&r2=1589228&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
(original)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
Tue Apr 22 18:18:42 2014
@@ -128,7 +128,9 @@ import org.apache.hadoop.hbase.ipc.HBase
 import org.apache.hadoop.hbase.ipc.HBaseServer.Call;
 import org.apache.hadoop.hbase.ipc.HMasterRegionInterface;
 import org.apache.hadoop.hbase.ipc.HRegionInterface;
+import org.apache.hadoop.hbase.ipc.ScannerResult;
 import org.apache.hadoop.hbase.ipc.thrift.HBaseThriftRPC;
+import org.apache.hadoop.hbase.ipc.thrift.exceptions.ThriftHBaseException;
 import org.apache.hadoop.hbase.master.AssignmentPlan;
 import org.apache.hadoop.hbase.master.RegionPlacement;
 import org.apache.hadoop.hbase.regionserver.metrics.RegionServerDynamicMetrics;
@@ -174,8 +176,8 @@ import com.google.common.base.Preconditi
  * HRegionServer makes a set of HRegions available to clients.  It checks in with
  * the HMaster. There are many HRegionServers in a single HBase deployment.
  */
-public class HRegionServer implements HRegionInterface, HRegionServerIf,
-    HBaseRPCErrorHandler, Runnable, Watcher, ConfigurationObserver {
+public class HRegionServer implements HRegionServerIf, HBaseRPCErrorHandler,
+    Runnable, Watcher, ConfigurationObserver {
   public static final Log LOG = LogFactory.getLog(HRegionServer.class);
   private static final HMsg REPORT_EXITING = new HMsg(Type.MSG_REPORT_EXITING);
   private static final HMsg REPORT_RESTARTING = new HMsg(
@@ -311,7 +313,6 @@ public class HRegionServer implements HR
    */
   public static ThreadPoolExecutor scanPrefetchThreadPool;
 
-
   // An array of HLog and HLog roller.  log is protected rather than private to avoid
   // eclipse warning when accessed by inner classes
   protected volatile HLog[] hlogs;
@@ -616,6 +617,26 @@ public class HRegionServer implements HR
     }
   }
 
+  @Override
+  public ScannerResult scanOpen(byte[] regionName, Scan scan, int numberOfRows)
+      throws ThriftHBaseException {
+    // TODO add implementation
+    return null;
+  }
+
+  @Override
+  public ScannerResult scanNext(long id, int numberOfRows)
+      throws ThriftHBaseException {
+    // TODO add implementation
+    return null;
+  }
+
+  @Override
+  public boolean scanClose(long id) throws ThriftHBaseException {
+    // TODO add implementation
+    return false;
+  }
+
   public int getHadoopRPCServerPort() {
     return this.serverInfo.getServerAddress().getPort();
   }

Modified: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServerIf.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServerIf.java?rev=1589228&r1=1589227&r2=1589228&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServerIf.java
(original)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServerIf.java
Tue Apr 22 18:18:42 2014
@@ -22,6 +22,7 @@ package org.apache.hadoop.hbase.regionse
 import java.util.SortedMap;
 import java.util.concurrent.atomic.AtomicLong;
 
+import org.apache.hadoop.hbase.ipc.HRegionInterface;
 import org.apache.hadoop.hbase.regionserver.metrics.RegionServerMetrics;
 
 /**
@@ -30,11 +31,11 @@ import org.apache.hadoop.hbase.regionser
  *
  * The only online server is using HRegionServer as the implementation.
  */
-public interface HRegionServerIf {
+public interface HRegionServerIf extends HRegionInterface {
   /**
    * @return what the regionserver thread name should be
    */
-  public String getRSThreadName();
+  String getRSThreadName();
 
   /**
    * Checks to see if the file system is still accessible.
@@ -42,12 +43,12 @@ public interface HRegionServerIf {
    *
    * @return false if file system is not available
    */
-  public void checkFileSystem();
+  void checkFileSystem();
 
   /**
    * Requests the region server to make a split on a specific region-store.
    */
-  public boolean requestSplit(HRegionIf r);
+  boolean requestSplit(HRegionIf r);
 
   /**
    * Requests the region server to make a compaction on a specific region-store.
@@ -55,21 +56,21 @@ public interface HRegionServerIf {
    * @param r the region-store.
    * @param why Why compaction requested -- used in debug messages
    */
-  public void requestCompaction(HRegionIf r, String why);
+  void requestCompaction(HRegionIf r, String why);
 
   /**
    * @return Region server metrics instance.
    */
-  public RegionServerMetrics getMetrics();
+  RegionServerMetrics getMetrics();
 
   /**
    * @return the size of global mem-store in bytes as an AtomicLong.
    */
-  public AtomicLong getGlobalMemstoreSize();
+  AtomicLong getGlobalMemstoreSize();
 
   /**
    * @return A new SortedMap of online regions sorted by region size with the
    *         first entry being the biggest.
    */
-  public SortedMap<Long, HRegion> getCopyOfOnlineRegionsSortedBySize();
+  SortedMap<Long, HRegion> getCopyOfOnlineRegionsSortedBySize();
 }

Added: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/IRegionScanServer.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/IRegionScanServer.java?rev=1589228&view=auto
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/IRegionScanServer.java
(added)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/IRegionScanServer.java
Tue Apr 22 18:18:42 2014
@@ -0,0 +1,33 @@
+/**
+ * Copyright 2014 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.regionserver;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.ipc.IRegionScanService;
+
+/**
+ * The interface of the server providing IRegionScanService.
+ */
+public interface IRegionScanServer extends IRegionScanService {
+  /**
+   * Initializes the server.
+   */
+  public void initialize(HRegionServerIf regionServer, Configuration conf);
+}

Modified: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/ThriftHRegionServer.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/ThriftHRegionServer.java?rev=1589228&r1=1589227&r2=1589228&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/ThriftHRegionServer.java
(original)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/ThriftHRegionServer.java
Tue Apr 22 18:18:42 2014
@@ -51,6 +51,7 @@ import org.apache.hadoop.hbase.client.TR
 import org.apache.hadoop.hbase.coprocessor.endpoints.EndpointServer;
 import org.apache.hadoop.hbase.coprocessor.endpoints.IEndpointServer;
 import org.apache.hadoop.hbase.io.hfile.histogram.HFileHistogram.Bucket;
+import org.apache.hadoop.hbase.ipc.ScannerResult;
 import org.apache.hadoop.hbase.ipc.ThriftHRegionInterface;
 import org.apache.hadoop.hbase.ipc.thrift.exceptions.ThriftHBaseException;
 import org.apache.hadoop.hbase.master.AssignmentPlan;
@@ -659,4 +660,21 @@ public class ThriftHRegionServer impleme
       throw new ThriftHBaseException(e);
     }
   }
+
+  @Override
+  public ScannerResult scanOpen(byte[] regionName, Scan scan, int numberOfRows)
+      throws ThriftHBaseException {
+    return server.scanOpen(regionName, scan, numberOfRows);
+  }
+
+  @Override
+  public ScannerResult scanNext(long id, int numberOfRows)
+      throws ThriftHBaseException {
+    return server.scanNext(id, numberOfRows);
+  }
+
+  @Override
+  public boolean scanClose(long id) throws ThriftHBaseException {
+    return server.scanClose(id);
+  }
 }



Mime
View raw message